Device capability for billions | Android Developers
Reaching new users means supporting an increasing variety of Android platform versions and device specifications. To improve the user experience, optimize for common RAM configurations, and screen sizes and resolutions.
Support multiple screen sizes
Your app can provide a better user experience for billions of users if it supports screens of various sizes and resolutions. This section describes a few ways you can do this.
Use density-independent pixels (dp)
Defining layout dimensions with pixels doesn't work well because different screens have different pixel densities, so the same number of pixels may correspond to different physical sizes on different devices.
To overcome this Android supports the density-independent pixel (dp), which corresponds to the physical size of a pixel at 160 dots per inch (mdpi density).
Defining layouts with dp ensures that the physical size of your user interface is consistent regardless of device. Visit the Android guide on Supporting Multiple Screens for best practices on using density-independent pixels.
Test text and graphics on ldpi and mdpi screen densities
Test to ensure that your text and graphics work well on low- and medium-density (ldpi and mdpi) screens because these are common densities, especially in lower-cost devices. Look out for text that may be unclear on lower-density screens, where fine details aren't visible.
Devices with lower-density screens tend to have lower hardware specifications. To ensure that your app performs well on these devices, consider reducing or eliminating heavy graphics processing loads, such as animations and transitions.
Validate that your layouts scale down by testing on smaller screens. As screen sizes shrink, be very selective about visible UI elements, because there is limited space for them.
The Material Design guidelines describe metrics and keylines to ensure that your layouts can scale across screen densities.
Not all of your users may be using devices powered by the latest, greatest version of the Android platform. Here are some ways you can improve backward compatibility, helping make your app available to as many people as possible.
Set your targetSdkVersion and minSdkVersion appropriately
Apps should build and target the most recent version of Android to ensure they offer the most current behavior across a broad range of devices; this still provides backward compatibility to older versions. Here are the best practices for targeting API levels appropriately:
targetSdkVersion should be the latest version of Android. Targeting the most recent version ensures that your app inherits newer runtime behaviors when running newer versions of Android. Be sure to test your app on newer Android versions when updating the targetSdkVersion as it can affect app behavior.
minSdkVersion Sets the minimum supported Android version. Setting minSdkVersion also results in the Android build tools reporting incorrect use of new APIs that might not be available in older versions of the platform. By doing so, you are protected from inadvertently breaking backward compatibility.
Consult the Android dashboards, the Google Play Developer Console for your app, and industry research in your target markets to gauge which versions of Android to target, based on your target users.
Use the Android Support libraries
Ensure your app provides a consistent experience across OS versions by using the Android Support Library. This library provides backward-compatible versions of Android framework APIs as well as features that are only available through the library APIs such as AppCompatActivity and the Material Design Support Library.
Multidex support library: provides support for large apps that have more than 65K methods. This can happen if your app is using many libraries.
For more information about the available support libraries, see the Support Libraries Features section of the Android Developer site.
Use Google Play services
Google Play services brings the best of Google APIs independent of Android platform version. Consider using features from Google Play services to offer the most streamlined Google experience on Android devices.
Google Play services also include useful APIs such as GcmNetworkManager, which provides much of Android 5.0's JobScheduler API for older versions of Android.
Updates to Google Play services are distributed automatically by the Google Play Store, and new versions of the client library are delivered through the Android SDK Manager.
Use memory efficiently
Memory is an unsung hero of the user experience. Good memory management can make your app more stable and more performant; in some cases, its effective use may be the only thing making your app usable at all. Here are some ways you can help your app use memory wisely.
Reduce memory footprint on low-cost devices
Adjust your memory footprint dynamically to ensure compatibility across devices with different RAM configurations.
Methods such as isLowRamDevice() and getMemoryClass() help determine memory constraints at runtime. Based on this information, you can scale down your memory use. As an example, you can use lower resolution images on low memory devices.
For more information about managing your app's memory, see the Android training on Managing Your App's Memory.
Avoid long-running processes
Long-running processes stay resident in memory and can slow down the device. In most situations, your app should wake up for a given event, process data, and shut down. You should use Firebase Cloud Messaging (FCM) and GcmNetworkManager to avoid long running background services and reduce memory pressure on the user's device.
Benchmark memory use
Android Studio provides memory benchmarking and profiling tools, enabling you to measure memory use at run time. Benchmarking your app's memory footprint enables you to monitor memory use over multiple versions of the app. This can help catch unintentional memory footprint growth. Use the Memory Profiler tool to do the following:
Find out whether undesirable garbage collection (GC) event patterns might be causing performance problems.
Identify object types that get or stay allocated unexpectedly or unnecessarily.
Android (Go edition) is an optimized experience for entry-level devices with ≤1GB RAM, starting with Android Oreo (Go edition). To ensure your app runs great on Android (Go edition) devices, you should should take into account the following guidelines:
targetSdkVersion should be the latest version of Android. Android (Go edition) devices only run Android Oreo (API 27 or higher).
The app should run smoothly on devices with ≤1GB RAM. Keep in mind the memory optimizations listed in Use memory efficiently above and use Android vitals to identify and fix bad behaviors like slow rendering and frozen frames.
The on-device app size should be smaller than 40MB.
The Proportional Set Size (PSS) of the app's RAM usage should not exceed 90MB. For games, the PSS of the game's RAM usage should not exceed 150MB. For more information about PSS, see the Investigating Your RAM Usage guide.
The startup time of the app should be minimal and under 5 seconds.
SYSTEM_ALERT_WINDOW (which allows apps to draw a window on top of other apps) might be disabled on Android Go devices that have low RAM. Before drawing over other apps, check whether your app has this authorization by calling Settings.canDrawOverlays(). If your app cannot get the permission, gracefully degrade your app so that the user can continue using your app, possibly by disabling the feature that requires the SYSTEM_ALERT_WINDOW permission.
We recommend that most developers optimize their existing app, which will be available on all Android (Go edition) devices, because making your app run faster and lighter will benefit your whole audience. You can use the Multiple APK feature on the Play Console to distribute a specific APK for Android (Go edition) devices but you should only do so without compromising the experience (e.g. you should avoid removing features). The APK targeting Android (Go edition) devices needs to declare <uses-feature android:name="android.hardware.ram.low" android:required="true">, target at least API Level 26, and have a higher version code than the non-Go edition APK.
Related
Additional resources
To learn more about supporting a variety of devices, view the following resource:
A useful way to evaluate app excellence is to walk through the workflows in your app and evaluate the smoothness and safety of the app experience.
This checklist defines a set of core quality criteria and associated tests to help you assess the quality of your app. Some of these criteria might be easy to miss, and the tests help you remember to include them in your test plans.
The checklist highlights the minimum quality that all apps should meet. Your testing will likely go well beyond what's described here.
Each item in the quality checklist has a unique ID which you might find helpful to use when you communicate with your team. You can also view the previous version of these guidelines.
Visual experience
Your app should provide standard Android visual design and interaction patterns where appropriate, for a consistent and intuitive user experience.
The app correctly preserves and restores user or app state.
The app preserves user or app state when leaving the foreground and prevents accidental data loss due to back-navigation and other state changes.
When returning to the foreground, the app should restore the preserved state and any significant stateful transaction that was pending. Examples include: changes to editable fields, game progress, menus, videos, and other sections of the app or game.
When the app is resumed from the Recents app switcher, the app returns the user to the exact state in which it was last used.
When the app is resumed after the device wakes from the sleep (locked) state, the app returns the user to the exact state in which it was last used.
When the app is relaunched from Home or All Apps, it should do one of the following, depending on how much time has passed since it was last used:
If the app was last used a short time ago (minutes), restore the app state as close as possible to its previous state.
If more time has passed since the app was last used, try to restore the app as close as possible to its previous state; or start it from its home screen or some other default state.
Notifications are persistent only if related to ongoing events, such as music playback or a phone call. For more information, see the Functionality section.
The app avoids running unnecessarily long services in the background. To ensure the smooth running of the user’s device, the system applies various restrictions on background services. These are not considered good uses of background services:
Maintaining a network connection for notifications
The app loads quickly or provides onscreen feedback to the user (a progress indicator or similar cue) if the app takes longer than two seconds to load.
Apps should render frames every 16ms to achieve 60 frames per second. Developers can use the Profile HWUI rendering option in testing. If there are issues, tools are available to help diagnose slow rendering.
With StrictMode enabled (see StrictMode Testing, below), no red flashes (performance warnings from StrictMode) are visible when testing the app. Any red flashes indicate bad behaviors regarding storage, network access, or memory leaks.
For Google SDKs, consider using SDKs powered by Google Play services, when available. These SDKs are backward compatible, receive automatic updates, reduce your app package size, and make efficient use of on-device resources.
The developer is accountable for the entire app’s codebase, inclusive of any third-party SDKs used.
The app properly supports the power management features that were introduced in Android 6.0 (Doze and App Standby). In the case where core functionality is disrupted by power management, only qualified apps may request an exemption. See Support for other use cases in Doze and App Standby.
During development, developers can test app standby and doze behavior using these ADB commands.
The app requests only the absolute minimum number of permissions that it needs to support its use case at hand. For some permissions such as location, use coarse location in place of fine location if possible.
SC-P2
The app requests permission to access sensitive data (such as SMS, Call Log, or Location) or services that cost money (such as Dialer or SMS) only when directly related to the core use cases of the apps. Implications related to these permissions should be prominently disclosed to the user.
Depending on how you are using the permissions, there might be an alternative way to fulfill your app's use case without relying on access to sensitive information. For example, instead of requesting permissions related to a user’s contacts, it may be more appropriate to request access by using an implicit intent.
If you need to pass an Intent to another app, so that the receiving app can invoke and expect a callback in the calling app, do not include a nested intent in the extras. Use a PendingIntent.
When setting up your PendingIntents, explicitly set the immutable flag, where applicable.
The app strictly adheres to the terms of the Google Play Developer Content Policy and does not offer inappropriate content, does not use the intellectual property or brand of others, and so on.
The app’s feature graphic follows the guidelines outlined in this support article. Make sure that:
The app listing includes a high-quality feature graphic.
The feature graphic does not contain device images, screenshots, or small text that will be illegible when scaled down and displayed on the smallest screen size that your app is targeting.
The feature graphic does not resemble an advertisement.
Common user-reported bugs in the Reviews tab of the Google Play page are addressed if they are reproducible and occur on many different devices. If a bug occurs on only a few devices, you should still address it if those devices are particularly popular or new.
Setting up a test environment
For the purpose of setting up a test environment for this checklist, we recommend the following:
Focused on emulator testing - Android Emulator is a great way to test your app under different Android versions and screen resolutions. You should set up emulated devices (AVDs) to represent the most common form factors and hardware/software combinations for your target user base. In addition to testing for phones, we also recommend you test other form factors using the following emulators at a minimum:
Foldables - 7.6” Fold-in with outer display (this is listed under phones in the AVD Manager).
Tablet - Pixel C 9.94” (2,560px x 1,800px).
For mobile app notification testing, pair a mobile device / emulator with Wear OS emulator - Wear OS Round 1.84”.
Hardware devices - Your test environment should include a small number of actual hardware devices that represent the key form factors and hardware/software combinations that are currently available to consumers. It's not necessary to test on every device that's on the market — rather, you should focus on a small number of representative devices, even using one or two devices per form factor.
Device test labs - You can also use third party services, such as Firebase Test Lab, to test your app on a wider variety of devices.
Test with the latest Android version - In addition to testing representative Android versions for your target user base, you should always test against the latest version of Android (currently Android 11). This ensures that the latest behavior changes do not negatively impact your user’s experience.
For more comprehensive guidance on testing including unit testing, integration testing and UI testing, check out the Android testing fundamentals.
Test procedures
These test procedures help you discover various types of quality issues in your app. You can combine the tests or integrate groups of tests together in your own test plans. See the sections above for references that associate criteria with these test procedures.
Type
Test
Description
Core Suite
CR-0
Navigate to all parts of the app — all screens, dialogs, settings, and all user flows.
If the application allows for editing or content creation, game play, or media playback, make sure to test those flows.
While testing the app, introduce interruptions from other apps, such as receiving a notification or a phone call; and apply transient changes to device attributes, such as network connectivity, battery function, GPS availability, and system load.
Enter and test all in-app purchase flows
CR-1
From each app screen, press the device's Home key or swipe up in gesture navigation, then re-launch the app from the All Apps screen.
CR-2
From each app screen, switch to another running app, and then return to the app under test using the Recents app switcher.
CR-3
From each app screen (and dialogs), press the Back button or use the back swipe gesture.
CR-5
From each app screen, rotate the device between landscape and portrait orientation and folding / unfolding at least three times.
CR-6
Switch to another app to send the test app into the background. Go to Settings and check whether the test app has any services running while in the background. In Android 4.0 and higher, go to the Apps screen and find the app in the "Running" tab.
CR-7
Press the power button to put the device to sleep, then press the power button again to wake the screen.
CR-8
Set up a screen lock on the device. Press the power button to put the device to sleep (which locks the device). Then, press the power button again to wake the screen and unlock the device.
CR-9
Trigger and observe in the notifications drawer all types of notifications that the app can display. Expand notifications where applicable (Android 4.1 and higher), and tap on all available actions.
CR-10
Review Support for other use cases in Doze and App Standby.
Install on SD Card
SD-1
Repeat Core Suite with the app installed to a device’s SD card (if the app supports this installation method).
To move the app to SD card, you can use Settings > App Info > Move to SD Card.
Performance and Stability
SP-1
Review the Android manifest file and build configuration to ensure that the application is built against the latest available SDK (targetSdk and compileSdk).
SP-2
Review the build.gradle file for any outdated dependencies.
Pay close attention to garbage collection and its impact on the user experience.
Battery
BA-1
Repeat Core Suite across Doze and App Standby cycles.
Pay close attention to alarms, timers, notifications, syncs, and so on. See Testing with Doze and App Standby for requirements and guidelines.
Security
SC-1
Review all data stored in external storage.
SC-2
Review how the data that’s loaded from external storage is handled and processed.
SC-3
Review all content providers defined in the Android manifest file. Make sure each provider has an appropriate protectionLevel.
SC-4
Review all permissions that your app requires, in the manifest file, at runtime, and in the app settings screen (Settings > App Info) on the device.
SC-5
Review all application components defined in the Android manifest file for the appropriate export state. The exported property must be set explicitly for all components.
Run the application and exercise all core functionality, while observing the device log. No private user information should be logged.
Google Play
GP-1
Sign into the Google Play Developer Console to review your developer profile, app description, screenshots, feature graphic, content rating and user feedback.
GP-2
Download your feature graphic and screenshots, and scale them down to match the display sizes on the devices and form factors that you are targeting.
GP-3
Review all graphical assets, media, text, code libraries, and other content that’s packaged in the app or expansion file download.
Testing with StrictMode
For performance testing, we recommend enabling StrictMode in your app and using it to catch operations that could affect performance, network accesses, file reads/writes, and so on. Look for potentially problematic operations both on the main thread and on other threads.
Reduced data cost for billions | Android Developers
Data plans in some countries can cost upwards of 10% of a typical user's monthly income. This means that minimizing your app's download size and letting the user control how your app uses data can have a large, tangible benefit to many users. Minimizing download size also helps conserve space in internal storage, which is a scarce resource in some devices.
Here you can find some strategies to help optimize the amount of data your app uses, both over the network and in internal storage.
Reduce app size
Reducing app size is one of the fundamental ways you can help your user consume less data, in terms of both network data and internal storage. This section describes several approaches to reducing app size.
Reduce APK graphical asset size
Graphical assets are often the largest contributor to the size of the APK. Optimizing these can result in smaller downloads and thus faster installation times for users.
For graphical assets such as icons, use the Scalable Vector Graphics (SVG) format. SVG images are tiny in size compared to bitmap graphics and can be rendered at runtime to any resolution. The Android Support Library provides a backward-compatible implementation for vector resources to Android 2.1 (API level 7). Get started with vectors with this Medium post.
For non-vector images, such as photos, use WebP to reduce image load times and save network bandwidth. WebP is proven to result in smaller file sizes than its PNG and JPG counterparts, with at least the same image quality. Even at lossy settings, WebP can produce a nearly identical image to the original. Android has included lossy WebP support since Android 4.0 (API level 14: Ice Cream Sandwich) and support for lossless, transparent WebP since Android 4.2 (API level 17: Jelly Bean).
If you have many large images across multiple densities, consider using Multiple APK support to split your APK by density. This results in builds targeted for specific densities, meaning users with low-density devices won’t have to incur the penalty of downloading unused high-density assets.
Every library in your Android project is adding potentially unused code to the APK. Be particularly careful about using external libraries because not all libraries are designed for use in mobile apps. Ensure that the libraries your app is using are optimized for mobile use.
Consider optimizing your compiled code using a tool such as ProGuard. ProGuard identifies code that isn’t being used and removes it from your APK. Also enable resource shrinking at build time by setting minifyEnabled=true, shrinkResources=true in build.gradle—this automatically removes unused resources from your APK.
When using Google Play services, you should selectively include only the necessary APIs into your APK.
Low-cost devices often come with little on-device storage. Users can extend this with SD cards; however, apps need to explicitly declare that they support being installed to external storage before users can move them.
Allow your app to be installed to external storage using the android:installLocation flag in your AndroidManifest.xml. For more information on enabling your app to be moved to external storage, see the Android guide on App Install Location.
Reduce post-install app disk use
Keeping your app’s disk use low means that users are less likely to uninstall your app when the device is low on free space. It’s important to apply bounds around your caches—this prevents your app’s disk use from growing indefinitely. Be sure you put your cached data in getCacheDir()—the system can delete files placed here as needed, so they won’t show up as storage committed to the app.
Offer configurable network use
The Android platform includes a number of ways you can give the user control over your app's network use, optimizing it for their own needs. For example, on first use, your app can walk the user through a variety of network-related settings. You can also provide a network preferences screen from outside the app.
Provide onboarding experiences for users' network choices
Apps that allow users to reduce data use are well received, even if they have heavy data requirements. If your app uses a considerable amount of bandwidth (for example, video streaming apps), you can provide an onboarding experience for users to configure network use. For example, you could allow the user to force lower-bitrate video streams on cellular networks.
Additional settings for users to control data syncing, prefetching, and network use behavior (for example, prefetch all starred news categories on Wi-Fi only), also help users tailor your app’s behavior to their needs.
For more information on managing network use, see the Android training on Managing Network Usage.
Provide a network preferences screen
You can navigate to the app’s network settings from outside the app by means of a network preferences screen. You can invoke this screen from either the system settings screen or the system data usage screen.
To provide a network preferences screen that users can access from within your app as well as from the system settings, in your app include an activity that supports the ACTION_MANAGE_NETWORK_USAGE action.
Users have different expectations when watching TV, compared to using a phone or tablet. A typical TV user sits about 10 feet away from the screen, so small details are less noticeable and small text is hard to read. Since users sit away from a TV, they must use a remote control device to navigate and make selections rather than touching elements on the screen. These differences significantly affect the requirements for what makes a good TV user experience.
The first step toward creating a great experience for TV users is to review and follow the Android TV design guidelines, which provides instructions on how to build the best user experience for TV apps. You should also review the Building TV Apps training, to understand the fundamental implementation requirements for a TV app.
Important: To ensure a great user experience, apps for TV devices must meet specific requirements for usability. Only apps that meet the following quality criteria will qualify as an Android TV app on Google Play.
These criteria ensure that your app follows critical design and interaction patterns to ensure a consistent, intuitive, and enjoyable user experience on TV devices.
Type
Test
Description
Launcher
TV-LM
The app displays a launcher icon in the Android TV Launcher after installation. (Learn how)
TV-LB
The app displays a 320 x 180px full-size banner as its launcher icon in the Android TV Launcher. (Learn how)
TV-BN
The app launch banner contains the name of the app. (Learn how)
TV-LG
If the app is a game, it appears in the Games row in the Android TV Launcher.
The app runs successfully when the user selects the application banner from the home screen. (Learn how)
Layout
TV-LO
All app interfaces are presented in landscape orientation. (Learn how)
TV-TC
The app displays core text at 16sp or higher in size. (Learn how)
TV-TA
The app displays all text at 12sp or higher in size. (Learn how)
TV-OV
The app does not display any text or functionality that is partially cut off by the edges of the screen. (Learn how)
TV-TR
The app does not partially obscure other apps. The app fills the entire screen and has a non-transparent background.
Navigation
TV-DP
The app functionality is navigable using 5-way D-pad controls, unless the app requires a gamepad controller as specified in TV-GP. (Learn how)
TV-DK
If the app requires a game controller, as specified in TV-GP, all functionality is navigable using standard Android game controller keys. (Learn how)
TV-DM
The app does not depend on a remote controller having a Menu button to access user interface controls. (Learn how)
TV-DB
Back button presses lead back to the Android TV home screen. (Learn how)
TV-DL
For apps with a live TV feed integrated on the Live tab, the app meets frictionless playback and direct-back requirements. (Learn how)
Search
TV-SD
In-app search results are navigable using D-pad controls, unless the app requires a gamepad controller, as specified in TV-GP. (Learn how)
TV-SB
An in-app search query should show up in the search box, similar to the user interface provided by SearchFragment, and results should be relevant to that query. (Learn how)
Functionality
These criteria ensure that your app is configured correctly and provides the expected functional behavior.
The app manifest sets the hardware feature android.hardware.touchscreen to not required. (Learn how)
Game Controllers
TV-GP
If the app uses a game controller as its primary input method, it declares the appropriate requirement with the <uses-feature> manifest tag. (Learn how)
TV-GC
If the app provides visual instructions for using game controllers, the instructions should be free of branding and show a compatible button layout. (Learn how)
Advertising
TV-AP
The app allows interaction with advertising using D-pad controls. (Learn how)
TV-AD
For advertising that uses fullscreen, non-video ads, the app allows the user to immediately dismiss the ad with D-pad controls.
TV-AU
For advertising that uses clickable, non-fullscreen, non-video ads, the app does not allow ads to link to a web URL.
TV-AA
For advertising that uses clickable, non-fullscreen, non-video ads, the app does not allow ads to link to another app that is not available on TV devices.
Web Content
TV-WB
For web content, the app uses WebView components and does not attempt to launch a web browser app.
Media Playback
TV-NP
If the app continues to play sound or video after the user has returned to the home screen or switched to another app, the app provides a Now Playing card on the home screen recommendation row so users can return to the app to control playback. (Learn how)
TV-PA
If the app provides a Now Playing card, selecting this card takes the user to a screen that allows playback to be paused. (Learn how)
TV-PP
If the app plays video or music content, the app toggles between play and pause of media playback when a play or pause key event is sent during playback. (Learn how)
TV-PC
While a video or audio is playing, pressing the D-pad center button should immediately pause the media that is playing. When paused, D-pad center button should resume playing. D-pad left and right buttons should fast forward or rewind the current track. (Learn how)
TV-PN
When adding items to the Watch Next channel, developers should follow the Watch Next guidelines. (Learn how)
Ambient Mode
TV-BU
When there is user-initiated active video playback, the app must prevent the device from going into Ambient Mode. (Learn How)
TV-BY
When there is no user-initiated active video playback or animation, the app must not prevent the device from going into Ambient mode.
TV-BA
For audio-only playback, the app must not prevent the device from going to Ambient Mode. Exception: The app implements an experience of non-static imagery (e.g. music videos, images) while music is playing.
After I submit my app, how will find out if my app does not meet all the requirements for TV devices?
If your app does not meet the usability requirements described on this page, the Play Store team will contact you through the email address specified in the Google Play Console account associated with the app.
Caution: Make sure your app includes the required manifest entries for TV devices, otherwise your app will not be considered a TV app and will not be reviewed for TV usability requirements.
My app targets more than just TV devices. If my app does not meet the TV device requirements, will my new or updated app still appear on Google Play for other devices?
Yes. The requirements described above only excludes distribution to Google Play on TV devices. Distribution to other device types, such as phones and tablets, is not affected.
If my app meets the publishing requirements, when will it be available in the Google Play Store on TV devices?
Apps that meet the requirements for TV will appear on the Play Store on TV devices immediately.
Battery consumption for billions | Android Developers
Access to reliable power supplies varies, and outages can disrupt planned charges. Defend your users' batteries against unnecessary drain by benchmarking your battery use, avoiding wakelocks, scheduling tasks, and monitoring sensor requests.
Reduce battery consumption
There are several steps you can take to help make sure that your app is only consuming battery power when it needs to, and that it's not consuming more power than necessary.
Your app should minimize its activity when in the background and when the device is running on battery power.
Sensors, such as GPS sensors, can drain battery significantly. Avoid issues by using the FusedLocationProvider API to manage the underlying location technology. It provides a simple API so that you can specify requirements—such as high accuracy or low power—at a high level. It also optimizes the device's use of battery power by caching locations and batching requests across apps. For more information about the ideal ways to request location, see the Getting the Last Known Location training guide.
Wake locks are mechanisms to keep devices on so that they can perform background activities. Avoid using wake locks because they prevent the device from going into low-power states.
WorkManager schedules tasks and lets the system batch operations. This greatly simplifies the implementation of common patterns, such as waiting for network connectivity, device charging state, retries, and backoff. Use WorkManager to perform non-essential background activity when the device is charging and is connected to an unmetered network.
For more information on how network activity can drain the battery, and how to tackle this issue, see Reducing Network Battery Drain.
Benchmark battery use
Benchmarking your app’s battery use in a controlled environment helps you understand the battery-heavy tasks in your app. It's a good practice to benchmark your app’s battery use to gauge efficiency and track changes over time. Batterystats collects battery data about your apps, and Battery Historian converts that data into an HTML visualization.
For more information on reducing battery use, see the Android training on Optimizing Battery Life.
Over half of all users worldwide will experience your app over a 2G connection. To improve their experience, optimize for low-speed connections and offline working by storing data, queuing requests, and handling images for optimal performance.
Here you can find some tips on how to accomplish these things.
Optimize images
There are a number of ways to make images easier to download. These include serving WebP images, dynamically sizing images, and using image-loading libraries.
Serve WebP images
Serve WebP files over the network to reduce image load times and save network bandwidth. A WebP file is often smaller in size than its PNG and JPG counterparts, with at least the same image quality. Even using lossy settings, WebP can produce a nearly identical image to the original. Android has included lossy WebP support since Android 4.0 (API level 14: Ice Cream Sandwich) and support for lossless, transparent WebP since Android 4.2 (API level 17: Jelly Bean).
Dynamically size images
Have your apps request images at the target rendering size, based on the device specification, and your server provide appropriately sized images. Doing this minimizes the data sent over the network and reduces the amount of memory needed to hold each image, resulting in improved performance and user satisfaction.
User experience degrades when users have to wait for images to download. Using appropriate image sizes helps to address these issues. Consider making image size requests based on network type or network quality; this size could be smaller than the target rendering size.
Dynamic placeholders such as pre-computed palette values or low-resolution thumbnails can improve the user experience while the image is being fetched.
Use image loading libraries
Your app should not fetch any image more than once. Image loading libraries such as Glide and Picasso fetch the image, cache it, and provide hooks into your Views to show placeholder images until the actual images are ready. Because images are cached, these libraries return the local copy the next time an image is requested.
Image-loading libraries manage their cache, holding onto the most recent images so that your app storage doesn’t grow indefinitely.
Optimize networking
You can enhance the user experience by providing an optimal network experience.
For example, you can make your app usable offline, use WorkManager and Room, and deduplicate network requests.
Make your app usable offline
In rural location and less affluent areas, it’s common for devices to lose network connectivity. Creating a useful offline state means users can interact with your app at all times. Do this by storing data locally, caching data, and queuing outbound requests to action when connectivity is restored.
Where possible, apps shouldn’t notify users that connectivity has been lost. It’s only when the user performs an operation where connectivity is essential that the user needs to be notified.
When a device lacks connectivity, your app should batch up network requests—on behalf of the user—that can be executed when connectivity is restored. An example of this is an email client that allows users to compose, send, read, move, and delete existing mails even when the device is offline. These operations can be cached and executed when connectivity is restored. In doing so, the app is able to provide a similar user experience whether the device is online or offline.
Use Room to fetch and cache data
Ensure that your app stores all data on disk using a database or similar structure so that it performs optimally regardless of network conditions. Use the Room persistence library to cache data in a local database, and use WorkManager to update that cache when the device has a network connection.
Apps should cache content that is fetched from the network. Before making subsequent requests, apps should display locally cached data. This ensures that the app is functional regardless of whether the device is offline or on a slow or unreliable network.
Deduplicate network requests
An offline-first architecture initially tries to fetch data from local storage and, failing that, requests the data from the network. After being retrieved from the network, the data is cached locally for future retrieval. This helps to ensure that network requests for the same piece of data only occur once—with subsequent requests satisfied locally. To achieve this, use a local database for long-lived data (usually android.database.sqlite or SharedPreferences).
This architecture also simplifies an app’s flow between offline and online states as one side fetches from the network to the cache, while the other retrieves data from the cache to present to the user.
For transitory data, use a bounded disk cache such as a DiskLruCache. Data that doesn’t typically change should only be requested once over the network and cached for future use. Examples of such data are images and non-temporal documents like news articles or social posts.
Fine-tune data transfer
There are several ways in which your app can adapt to network conditions to provide a better user experience. For example, it can prioritize network requests to minimize the user's waiting time for information. It can also detect and adapt to slower network speeds and changes that may take place in the network connection.
Prioritize bandwidth
You shouldn't assume that any network that the device is connected to is long-lasting or reliable. For this reason, apps should prioritize network requests to display the most useful information to the user as soon as possible.
Presenting users with visible and relevant information immediately is a better user experience than making them wait for information that might not be necessary. This reduces the time that the user has to wait and increases the usefulness of the app on slow networks.
To achieve this, sequence your network requests such that text is fetched before rich media. Text requests tend to be smaller, compress better, and hence transfer faster, meaning that your app can display useful content quickly. For more information on managing network requests, visit the Android training on Managing Network Usage.
Use less bandwidth on slower connections
The ability for your app to transfer data in a timely fashion is dependent on the network connection. Detecting the quality of the network and adjusting the way your app uses it can help provide an excellent user experience.
You can use the following methods to detect the underlying network quality. Using the data from these methods, your app should tailor its use of the network to continue to provide a timely response to user actions:
On slower connections, consider downloading only lower-resolution media or perhaps none at all. This ensures that your users can use the app on slow connections. Where you don’t have an image or the image is still loading, you should always show a placeholder. You can create a dynamic placeholder by using the Palette library to generate placeholder colors that match the target image.
On devices powered by Android 7.0 (API level 24) and higher, users can turn on the Data Saver setting, which helps minimize data use. Android 7.0 extends ConnectivityManager to detect Data Saver settings. For more information about this feature, see Data Saver.
Detect network changes, then change app behavior
Network quality is not static; it changes based on location, network traffic, and local population density. Apps should detect changes in network and adjust bandwidth accordingly. By doing so, your app can tailor the user experience to the network quality. Detect network state using these methods:
As the network quality degrades, scale down the number and size of requests. As the connection quality improves, you can scale up your requests to optimal levels.
On higher quality, unmetered networks, consider prefetching data to make it available ahead of time. From a user experience standpoint, this might mean that news reader apps fetch three articles at a time on 2G but fetch twenty articles at a time on Wi-Fi. For more information on adjusting app behavior based on network changes, visit the Android training on Monitoring the Connectivity Status.
The broadcast CONNECTIVITY_CHANGE is sent when a change in network connectivity occurs. When your app is in the foreground, you can call registerReceiver to receive this broadcast. After receiving the broadcast, you should reevaluate the current network state and adjust your UI and network use appropriately. You shouldn't declare this receiver in your manifest, as it's unavailable in Android 7.0 (API level 24) and higher. For more information about this and other changes in Android 7.0, see Android 7.0 Changes.
Related
Additional resources
To learn more about supporting a variety of connection speeds, view the following resource: