page.title=Building for Billions
page.metaDescription=Best practices on how to optimize Android apps for low- and no-bandwidth and low-cost devices.
page.image=/distribute/images/billions-guidelines.png

@jd:body

<!-- table of contents -->
<div id="qv-wrapper"><div id="qv">
<h2><a href="#connectivity">Connectivity</a></h2>
 <ol>
  <li><a href="#images">Optimize images</a></li>
  <li><a href="#network">Optimize networking</a></li>
  <li><a href="#transfer">Fine-tune data transfer</a></li>
 </ol>
<h2><a href="#capability">Device Capability</a></h2>
 <ol>
  <li><a href="#screens">Support varying screen sizes</a></li>
  <li><a href="#compatibility">Backward compatibility</a></li>
  <li><a href="#memory">Efficient memory usage</a></li>
 </ol>

<h2><a href="#cost">Data Cost</a></h2>
 <ol>
  <li><a href="#appsize">Reduce app size</a></li>
  <li><a href="#configurablenetwork">Offer configurable network usage</a></li>
 </ol>

<h2><a href="#consumption">Battery Consumption</a></h2>
 <ol>
  <li><a href="#consumption-reduce">Reduce battery consumption</a></li>
  <li><a href="#consumption-benchmark">Benchmark battery usage</a></li>
 </ol>

<h2><a href="#contentsection">Content</a></h2>
 <ol>
  <li><a href="#content-responsive">Fast and responsive UI</a></li>
  <li><a href="#ui">UI Best practices</a></li>
  <li><a href="#localization">Localization</a></li>
 </ol>
</div>
</div>

<!-- intro -->
<p>Internet use—and smartphone penetration—is growing fastest in markets with
 low, intermittent, or expensive connectivity. Successful apps in these
 markets need to perform across a variety of speeds and devices, as well as
 conserve and share information about battery and data consumption.</p>

<p>To help you address these important considerations, we’ve compiled the
 following checklist. These do not follow a particular order, and as
 always it's a good idea to research particularities of any market or country
 you're targeting.
</p>

<!-- connectivity -->
<div class="headerLine">
  <h2 id="connectivity">Connectivity</h2>
</div>

<p>Over half of the users in the world still experience your app over 2G
 connections. To improve their experience, optimize for no- and low-connection
 speeds. For offline and slow connections: store data, queue requests, and handle
 images for optimal performance.
</p>

<h3 id="images">Optimize images</h3>
<h4 id="images-format">Serve WebP images</h4>
 <ul>
  <li>Serve <a
   href="https://developers.google.com/speed/webp/">WebP</a> files over the
   network. WebP reduces image load times, saves network bandwidth, and often
   results 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. Android has had lossy <a
   href="{@docRoot}guide/appendix/media-formats.html">WebP support</a> 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).</li>
 </ul>
<h4 id="images-sizing">Dynamic image sizing</h4>
 <ul>
  <li>Have your apps request images at the targeted rendering size, and have
   your server provide those images to fit; the target rendering size will
   vary based on device specifications. Doing this minimizes the network
   overhead and reduces the amount of memory needed to hold each image,
   resulting in improved performance and user satisfaction.</li>
  <li>Your user experience degrades when users are waiting 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.</li>
  <li>Dynamic placeholders like <a
   href="{@docRoot}reference/android/support/v7/graphics/Palette.html">
   pre-computed palette values</a> or low-resolution thumbnails can improve
   the user experience while the image is being fetched.</li>
 </ul>
<h4 id="images-libraries">Use image loading libraries</h4>
 <ul>
  <li>Your app should not have to fetch any image more than once. Image
   loading libraries such as <a class="external-link"
   href="https://github.com/bumptech/glide">Glide</a> and  <a
   class="external-link" href="http://square.github.io/picasso/">Picasso</a>
   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 they are
   requested.</li>
  <li>Image-loading libraries manage their cache, holding onto the most recent
   images so that your app storage doesn’t grow indefinitely.</li>
 </ul>

<h3 id="network">Optimize networking</h3>
<h4 id="network-offline">Make your app usable offline</h4>
 <ul>
  <li>In places like subways, planes, elevators, and parking garages, it is
   common for devices to lose network connectivity. Creating a useful offline
   state results in users being able to interact with the app at all times, by
   presenting cached information. Ensure that your app is usable offline or
   when network connectivity is poor by storing data locally, caching data,
   and queuing outbound requests for when connectivity is restored.</li>
  <li>Where possible, apps should not notify users that connectivity has
   been lost. It is only when the user performs an operation where connectivity
   is essential that the user needs to be notified.</li>
  <li>When a device lacks connectivity, your app should batch up network
   requests&mdash;on behalf of the user&mdash;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.</li>
 </ul>
<h4 id="network-arch">Use GcmNetworkManager and/or Content Providers</h4>
 <ul>
  <li>Ensure that your app stores all data on disk via a database or similar
   structure so that it performs optimally regardless of network conditions
   (for example, via SQLite + ContentProvider). The <a
   href="https://developers.google.com/cloud-messaging/network-manager">
   GCM Network Manager</a>
   (<a href="https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager">
   <code>GcmNetworkManager</code></a>) can result in a robust mechanism to
   sync data with servers while <a
   href="{@docRoot}guide/topics/providers/content-providers.html">content
   providers</a> ({@link android.content.ContentProvider}) cache that data,
   combining to provide an architecture that enables a useful offline state.</li>
  <li>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/unreliable network.</li>
 </ul>
<h4 id="network-duplicate">Deduplicate network requests</h4>
 <ul>
  <li>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—the rest of the requests are satisfied locally. To
   achieve this, use a local database for long-lived data (usually
   {@link android.database.sqlite} or
   {@link android.content.SharedPreferences}).</li>
  <li>An offline-first architecture always looks for data locally first, then
   makes the request over the network. The response is cached and then returned
   locally. Such an architecture 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.</li>
  <li>For transitory data, use a bounded disk cache such as a <a class="external-link"
   href="https://github.com/JakeWharton/DiskLruCache"><code>DiskLruCache</code>
   </a>. 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.</li>
 </ul>

<h3 id="transfer">Fine-tune data transfer</h3>
<h4 id="transfer-prioritize">Prioritize bandwidth</h4>
 <ul>
  <li>Writers of apps should not 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.</li>
  <li>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.</li>
  <li>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 <a
   href="{@docRoot}training/basics/network-ops/managing.html">Managing Network
   Usage</a>.</li>
 </ul>
<h4 id="network-bandwidth">Use less bandwidth on slower connections</h4>
 <ul>
  <li>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.</li>
  <li>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:
    <ul>
     <li>{@link android.net.ConnectivityManager}>
     {@link android.net.ConnectivityManager#isActiveNetworkMetered}</li>
     <li>{@link android.net.ConnectivityManager}>
     {@link android.net.ConnectivityManager#getActiveNetworkInfo}</li>
     <li>{@link android.net.ConnectivityManager}>
     {@link android.net.ConnectivityManager#getNetworkCapabilities}</li>
     <li>{@link android.telephony.TelephonyManager}>
     {@link android.telephony.TelephonyManager#getNetworkType}</li>
    </ul>
  </li>
  <li>On slower connections, consider downloading only lower-resolution media
   or perhaps none at all. This ensures that your users are still able to 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 <a
   href="{@docRoot}tools/support-library/features.html#v7-palette">
   Palette library</a> to generate placeholder colors that match the target
   image.</li>
  <li>Prioritize 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 adjusting bandwidth based on network connection, see the
   Android training on <a
   href="{@docRoot}training/basics/network-ops/managing.html">Managing Network
   Usage</a>.</li>
  <li>On devices powered by Android 7.0 (API level 24) and higher,
  users can turn on the
  <strong>Data Saver</strong> setting, which helps minimize data usage. Android 7.0
  extends {@link android.net.ConnectivityManager} to detect <strong>Data Saver</strong>
  settings. For more information about this feature, see
  <a href="/training/basics/network-ops/data-saver.html">Data Saver.</a>
  </li>
 </ul>
<h4 id="network-behavior">Detect network changes, then change app behavior</h4>
 <ul>
  <li>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:
    <ul>
     <li>{@link android.net.ConnectivityManager}>
     {@link android.net.ConnectivityManager#getActiveNetworkInfo}</li>
     <li>{@link android.net.ConnectivityManager}>
     {@link android.net.ConnectivityManager#getNetworkCapabilities}</li>
     <li>{@link android.telephony.TelephonyManager}>
     {@link android.telephony.TelephonyManager#getDataState}</li>
    </ul>
  </li>
  <li>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.</li>
  <li>On higher quality, unmetered networks, consider <a
   href="{@docRoot}training/efficient-downloads/efficient-network-access.html#PrefetchData">
   prefetching data</a> to make it available ahead of time. From a user
   experience standpoint, this might mean that news reader apps only 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 <a
   href="{@docRoot}training/monitoring-device-state/connectivity-monitoring.html">
   Monitoring the Connectivity Status</a>.</li>
  <li>The broadcast <a
   href="{@docRoot}reference/android/net/ConnectivityManager.html#CONNECTIVITY_ACTION">
   <code>CONNECTIVITY_CHANGE</code></a> is sent when a change in network
   connectivity occurs. When your app is in the foreground, you can call <a
   href="{@docRoot}reference/android/content/Context.html#registerReceiver(android.content.BroadcastReceiver,%20android.content.IntentFilter)">
   <code>registerReceiver</code></a> to receive this broadcast. After receiving
   the broadcast, you should reevaluate the current network state and adjust
   your UI and network usage appropriately. You should not declare this receiver
   in your manifest, as that feature is unavailable in Android 7.0 (API level 24)
   and higher.
   For more information about this and other changes in Android 7.0,
   see <a href="/about/versions/nougat/android-7.0-changes.html">
   Android 7.0 Changes</a>.</li>
 </ul>

<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13"
  data-query="collection:distribute/essentials/billionsquality/connectivity"
  data-sortOrder="-timestamp"
  data-cardSizes="6x3"
  data-maxResults="6"></div>

<!-- capability -->
<div class="headerLine">
  <h2 id="capability">Device Capability</h2>
</div>
<p>Reaching new users means supporting an increasing variety of Android
 platform versions and device specifications. Optimize for common RAM and
 screen sizes and resolutions to improve the user experience. </p>

<h3 id="screens">Support varying screen sizes</h3>
<h4 id="screens-dp">Use density-independent pixels (dp)</h4>
 <ul>
  <li>Defining layout dimensions with pixels is a problem because different
   screens have different pixel densities, so the same number of pixels may
   correspond to different physical sizes on different devices. The
   density-independent pixel (dp) corresponds to the physical size of a pixel
   at 160 dots per inch (mdpi density).</li>
  <li>Defining layouts with dp ensures that the physical size of your user
   interface is consistent regardless of device. Visit the Android
   guide on <a
   href="https://developer.android.com/guide/practices/screens_support.html">
   Supporting Multiple Screens</a> for best practices using
   density-independent pixels.</li>
 </ul>
<h4 id="screens-density">Test graphics on ldpi/mdpi screen densities</h4>
 <ul>
  <li>Ensure that your app layouts work well on low- and medium-density
   (ldpi/mdpi) screens because these are <a
   href="https://developer.android.com/about/dashboards/index.html#Screens">
   common densities</a>, especially in lower-cost devices. Testing on
   lower-density screens helps to validate that your layouts are legible on
   lower-density screens.</li>
  <li>Lower-density screens can result in unclear text where the finer details
   aren't visible. The Material Design guidelines describe <a
   class="external-link" href="https://www.google.com/design/spec/layout/metrics-keylines.html">
   metrics and keylines</a> to ensure that your layouts can scale across
   screen densities.</li>
  <li>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 loads, such as animations and
   transitions. For more information on supporting different densities, see
   the Android training on <a
   href="https://developer.android.com/training/multiscreen/screendensities.html">
   Supporting Different Densities</a>.</li>
 </ul>
<h4 id="screens-sizes">Test layouts on small/medium screen sizes</h4>
 <ul>
  <li>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.</li>
  <li>Devices with smaller screens tend to have lower hardware specifications.
   To ensure that your app performs well on these devices, try reducing or
   eliminating heavy loads, such as animations or transitions. For more
   information on supporting different screen sizes, see the Android
   training on <a
   href="https://developer.android.com/training/multiscreen/screendensities.html">
   Supporting Different Screen Sizes</a>.</li>
 </ul>

<h3 id="compatibility">Backward compatibility</h3>
<h4 id="compatibility-sdkversion">Set your targetSdkVersion and minSdkVersion
 appropriately</h4>
 <ul>
  <li>Apps should build and target a recent version of Android to ensure 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:
    <ul>
     <li><a
      href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">
      {@code targetSdkVersion}</a> 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.</li>
     <li><a
      href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">
      {@code minSdkVersion}</a> sets the minimum supported Android version.
      Use Android 4.0 (API level 14: Ice Cream Sandwich) or Android 4.1 (API
      level 16: Jelly Bean)—these versions give maximum coverage for modern
      devices. Setting {@code 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, developers are protected
      from inadvertently breaking backward compatibility.</li>
    </ul>
  </li>
  <li>Consult the <a
   href="https://developer.android.com/about/dashboards/index.html#Platform">
   Android dashboards</a>, the <a class="external-link"
   href="https://play.google.com/apps/publish/">Google Play Developer
   Console</a> for your app, and industry research in your target markets to
   gauge which versions of Android to target, based on your target users.</li>
 </ul>
<h4 id="compatibility-libraries">Use the Android Support libraries</h4>
 <ul>
  <li>Ensure your app provides a consistent experience across OS versions by
   using the Google-provided support libraries such as AppCompat and the Design
    Support Library. The Android Support Library package is a set of code
    libraries that provides backward-compatible versions of Android framework
    APIs as well as features that are only available through the library APIs.
    </li>
  <li>Some of the the highlights include:
  <ul>
   <li>v4 & v7 support library: Many framework APIs for older versions of
    Android such as {@link android.support.v4.view.ViewPager},
    {@link android.app.ActionBar},
    {@link android.support.v7.widget.RecyclerView}, and
    {@link android.support.v7.graphics.Palette}.</li>
   <li><a href="{@docRoot}tools/support-library/features.html#design">Design
    Support</a> library: APIs to support adding Material Design components
    and patterns to your apps.</li>
   <li><a href="{@docRoot}tools/support-library/features.html#multidex">
    Multidex Support</a> library: provides support for large apps that have
    more than 65K methods. This can happen if your app is using many
    libraries.</li>
  </ul>
  </li>
  <li>For more information on the available support libraries, see the <a
   href="https://developer.android.com/tools/support-library/features.html">
   Support Libraries Features</a> section of the Android Developer site.</li>
 </ul>
<h4 id="compatibility-playservices">Use Google Play services</h4>
 <ul>
  <li>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.</li>
  <li>Google Play services also include useful APIs such as <a
   href="https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager">
   <code>GcmNetworkManager</code></a>, which provides much of Android 5.0’s
   {@link android.app.job.JobScheduler} API for older versions of Android. </li>
  <li>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. </li>
 </ul>
<h3 id="memory">Efficient memory usage</h3>
<h4 id="memory-footprint">Reduce memory footprint on low-cost devices</h4>
 <ul>
  <li>Adjusting your memory footprint dynamically helps to ensure compatibility
   across devices with different RAM configurations.</li>
  <li>Methods such as {@link android.app.ActivityManager#isLowRamDevice} and
   {@link android.app.ActivityManager#getMemoryClass()} help determine memory
   constraints at runtime. Based on this information, you can scale down your
   memory usage. As an example, you can use lower resolution images on low memory
   devices.</li>
  <li>For more information on managing your app’s memory, see the Android
   training on <a href="{@docRoot}training/articles/memory.html">Managing
   Your App's Memory</a>.</li>
 </ul>
<h4 id="memory-longprocesses">Avoid long-running processes</h4>
 <ul>
  <li>Long-running processes stay resident in memory and can result in slowing
   down the device. In most situations, your app should wake up for a given
   event, process data, and shut down. You should use <a
   href="https://developers.google.com/cloud-messaging">Google Cloud Messaging
   (GCM)</a> and/or <a
   href="https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager">
   <code>GcmNetworkManager</code></a> to avoid long running background
   services and reduce memory pressure on the user’s device.</li>
 </ul>
<h4 id="memory-benchmark">Benchmark memory usage</h4>
 <ul>
  <li>Android Studio provides memory benchmarking and profiling tools, enabling
   you to measure memory usage at run time. Benchmarking your app’s memory
    footprint enables you to monitor memory usage over multiple versions of
    the app. This can help catch unintentional memory footprint growth. These
    tools can be used in the following ways:
  <ul>
   <li>Use the <a
    href="{@docRoot}tools/performance/memory-monitor/index.html">Memory
    Monitor</a> tool to find out whether undesirable garbage collection (GC)
    event patterns might be causing performance problems.</li>
   <li>Run <a
    href="{@docRoot}tools/performance/heap-viewer/index.html">Heap Viewer</a>
    to identify object types that get or stay allocated unexpectedly or
    unnecessarily.</li>
   <li>Use <a
   href="{@docRoot}tools/performance/allocation-tracker/index.html">
   Allocation Tracker</a> to identify where in your code the problem might
   be.</li>
  </ul>
  </li>
  <li>For more information on benchmarking memory usage, see the <a
   href="{@docRoot}tools/performance/comparison.html">
   Memory Profilers</a> tools on the Android Developers site.</li>
 </ul>

<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13"
  data-query="collection:distribute/essentials/billionsquality/capability"
  data-sortOrder="-timestamp"
  data-cardSizes="6x3"
  data-maxResults="6"></div>

<!-- cost -->
<div class="headerLine">
  <h2 id="cost">Data Cost</h2>
</div>
<p>Data plans in some countries can cost upwards of 10% of monthly income.
 Conserve data and give control to optimize user experience. Reduce data
 consumption and give users control over your app’s use of data.</p>

<h3 id="appsize">Reduce app size</h3>
<h4 id="appsize-graphics">Reduce APK graphical asset size</h4>
 <ul>
  <li>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.</li>
  <li>For graphical assets like icons, use Scalable Vector Graphics (SVG)
   format. SVG images are relatively tiny in size and can be rendered at
   runtime to any resolution. The <a
   href="{@docRoot}tools/support-library/index.html">Android Support</a>
   library provides a backward-compatible implementation for vector resources as
   far back as Android 2.1 (API level 7). Get started with vectors with <a
   class="external-link"
   href="https://medium.com/@chrisbanes/appcompat-v23-2-age-of-the-vectors-91cbafa87c88">
   this Medium post</a>. </li>
  <li>For non-vector images, like photos, use <a
   href="https://developers.google.com/speed/webp/">WebP</a>. WebP reduces
   image load times, saves network bandwidth, and 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. Android has had 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).</li>
  <li>If you have many large images across multiple densities, consider
   using <a href="{@docRoot}google/play/publishing/multiple-apks.html">Multiple
   APK support</a> 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 unused high-density assets.</li>
  <li>For more information about reducing APK size, see
  <a href="/topic/performance/reduce-apk-size.html">Reduce APK Size</a> and
  <a href="/studio/build/shrink-code.html">Shrink Your Code and Resources</a>. In addition, you can
  find a detailed guide on reducing APK size in this <a class="external-link"
  href="https://medium.com/@wkalicinski/smallerapk-part-4-multi-apk-through-abi-and-density-splits-477083989006">
   series of Medium posts</a>.</li>
 </ul>
<h4 id="appsize-code">Reduce code size</h4>
 <ul>
  <li>Be careful about using external libraries because not all libraries are
   meant to be used in mobile apps. Ensure that the libraries your app is
   using are optimized for mobile use.</li>
  <li>Every library in your Android project is adding potentially unused code
   to your APK. There are also some libraries that aren’t designed with mobile
   development in mind. These libraries can end up contributing to significant
   APK bloat.</li>
  <li>Consider optimizing your compiled code using a tool such as <a
   href="{@docRoot}tools/help/proguard.html">ProGuard</a>. ProGuard identifies
   code that isn’t being used and removes it from your APK. Also <a
   class="external-link"
   href="http://tools.android.com/tech-docs/new-build-system/resource-shrinking">
   enable resource shrinking</a> at build time by setting
   <code>minifyEnabled=true</code>, <code>shrinkResources=true</code> in
   <code>build.gradle</code>—this automatically removes unused resources from
   your APK.</li>
  <li>When using Google Play services, you should <a
   href="{@docRoot}google/play-services/setup.html#add_google_play_services_to_your_project">
   selectively include</a> only the necessary APIs into your APK.</li>
  <li>For more information on reducing code size in your APK, see the Android
   training on how to <a
   href="{@docRoot}training/articles/memory.html#DependencyInjection">Avoid
   dependency injection frameworks</a>.</li>
 </ul>
<h4 id="appsize-external">Allow app to be moved to external (SD) storage</h4>
 <ul>
  <li>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.
  </li>
  <li>Allow your app to be installed to external storage using the <a
   href="{@docRoot}guide/topics/manifest/manifest-element.html#install"><code>
   android:installLocation</code></a> flag in your AndroidManifest. For more
   information on enabling your app to be moved to external storage, see the
   Android guide on <a
   href="{@docRoot}guide/topics/data/install-location.html">App Install
   Location</a>.</li>
 </ul>

<h4 id="appsize-postinstall">Reduce post-install app disk usage</h4>
 <ul>
  <li>Keeping your app’s disk usage low means that users are less likely to
   uninstall your app when the device is low on free space. When using caches,
   it’s important to apply bounds around your caches—this prevents your app’s
   disk usage from growing indefinitely. Be sure you put your cached data in
   {@link android.content.Context#getCacheDir()}—the system can delete files
   placed here as needed, so they won’t show up as storage committed to the
   app.</li>
 </ul>

<h3 id="configurablenetwork">Offer configurable network usage</h3>
<h4 id="configurablenetwork-onboarding">Provide onboarding experiences for
subjective user choices</h4>
 <ul>
  <li>Apps that allow users to reduce data usage are well received, even if
   they demand 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 usage. For example,
   you could allow the user to force lower-bitrate video streams on cellular
   networks. </li>
  <li>Additional settings for users to control data syncing, prefetching, and
   network usage behavior (for example, prefetch all starred news categories on
   Wi-Fi only), also help users tailor your app’s behavior to their needs.</li>
  <li>For more information on managing network usage, see the Android training
   on <a href="{@docRoot}training/basics/network-ops/managing.html">Managing
   Network Usage</a>.</li>
 </ul>
<h4 id="configurablenetwork-preferences">Provide a network preferences
screen</h4>
 <ul>
  <li>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.</li>
  <li>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
   {@link android.content.Intent#ACTION_MANAGE_NETWORK_USAGE} action.</li>
  <li>For further information on adding a network preferences screen, see the
   Android training on <a
   href="{@docRoot}training/basics/network-ops/managing.html#prefs">
   Implementing a Preferences Activity</a>.</li>
 </ul>



<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13"
  data-query="collection:distribute/essentials/billionsquality/cost"
  data-sortOrder="-timestamp"
  data-cardSizes="6x3"
  data-maxResults="6"></div>


<!-- consumption -->
<div class="headerLine">
  <h2 id="consumption">Battery Consumption</h2>
</div>
<p>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.</p>
<h3 id="consumption-reduce">Reduce battery consumption</h3>
 <ul>
  <li>Your app should do minimal activity when in the background and when the
   device is running on battery power.</li>
   <li>Sensors, like GPS, can also significantly drain your battery. For this
   reason, we recommend that you use the <a
   href="https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderApi">
   <code>FusedLocationProvider</code></a> API. The
   <code>FusedLocationProvider</code> API manages the
   underlying location technology and provides a simple API so that you can
   specify requirements&mdash;like high accuracy or low power&mdash;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 <a
   href="{@docRoot}training/location/retrieve-current.html">Getting the Last
   Known Location</a> training guide.
  </li>
  <li><a href="{@docRoot}reference/android/os/PowerManager.WakeLock.html">Wake
   locks</a> 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.</li>
  <li>To reduce the number of device wake-ups, batch network activity. For more
   information on batching, see the Android training on <a
   href="{@docRoot}training/efficient-downloads/efficient-network-access.html">
   Optimizing Downloads for Efficient Network Access</a>.</li>
  <li><a
   href="https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager">
   <code>GcmNetworkManager</code></a> schedules tasks and lets Google Play
   services batch operations across the system. This greatly
   simplifies the implementation of common patterns, such as waiting for
   network connectivity, device charging state, retries, and backoff. Use
   <code>GcmNetworkManager</code> to perform non-essential background activity
   when the device is charging and is connected to an unmetered network.</li>
  <li>For more information on how network activity can drain the battery, and
  how to tackle this issue, see <a
  href="/topic/performance/power/network/index.html">Reducing Network Battery Drain</a>.
 </ul>
<h3 id="consumption-benchmark">Benchmark battery usage</h3>
 <ul>
  <li>Benchmarking your app’s usage in a controlled environment helps you
   understand the battery-heavy tasks in your app. It is a good practice to
   benchmark your app’s battery usage to gauge efficiency and track changes
   over time.
</li>
  <li><a
   href="{@docRoot}tools/performance/batterystats-battery-historian/index.html">
   Batterystats</a> collects battery data about your apps, and <a
   href="{@docRoot}tools/performance/batterystats-battery-historian/index.html">
   Battery Historian</a> converts that data into an HTML visualization. For
   more information on reducing battery usage, see the Android training on <a
   href="{@docRoot}training/monitoring-device-state/index.html">Optimizing
   Battery Life</a>.</li>
 </ul>

<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13"
  data-query="collection:distribute/essentials/billionsquality/consumption"
  data-sortOrder="-timestamp"
  data-cardSizes="6x3"
  data-maxResults="6"></div>

<!-- content -->
<div class="headerLine">
  <h2 id="contentsection">Content</h2>
</div>
<p>Make sure that your app works well on a variety of screens: offering good,
 crisp graphics and appropriate layouts on low resolution and physically small
 screens. Ensure that your app is designed to be easily localized by
 accommodating the variations between languages: allow for spacing, density,
 order, emphasis, and wording variations. Also make sure that date, time, and
 the like are internationalized and displayed according to the phone’s
 settings.</p>

<h3 id="content-responsive">Fast and responsive UI</h3>
<h4 id="content-feedback">Touch feedback on all touchable items</h4>
 <ul>
  <li>Touch feedback adds a tactile feeling to the user interface. You should
   ensure your app provides touch feedback on all touchable elements to reduce
   the perceived app latency as much as possible.
</li>
  <li><a
   href="https://www.google.com/design/spec/animation/responsive-interaction.html">
   Responsive interaction</a> encourages deeper exploration of an app by
   creating timely, logical, and delightful screen reactions to user input.
   Responsive interaction elevates an app from an information-delivery service
   to an experience that communicates using multiple visual and tactile
   responses.</li>
  <li>For more information, see the Android training on <a
   href="{@docRoot}training/material/animations.html#Touch">Customizing Touch
   Feedback</a>.</li>
 </ul>
<h4 id="content-interactive">UI should always be interactive</h4>
 <ul>
  <li>Apps that are unresponsive when performing background activity feel slow
   and reduce user satisfaction. Ensure your app always has a responsive UI
   regardless of any background activity. Achieve this by performing network
   operations or any heavy-duty operations in a background thread—keep the UI
   thread as idle as you can.</li>
  <li>Material Design apps use minimal visual changes when your app is loading
   content by representing each operation with a single activity indicator.
   Avoid blocking dialogs with <a
   href="https://www.google.com/design/spec/components/progress-activity.html">
   loading indicators</a>.</li>
  <li><a
   href="http://www.google.com/design/spec/patterns/empty-states.html">Empty
   states</a> occur when the regular content of a view can’t be shown. It might
   be a list that has no items or a search that returns no results. Avoid
   completely empty states. The most basic empty state displays a
   non-interactive image and a text tagline. Where you don’t have an image, or
   the image is still loading, you should always show either a static
   placeholder, or create a dynamic placeholder by using the <a
   href="{@docRoot}tools/support-library/features.html#v7-palette">Palette
   library</a> to generate placeholder colors that match the target image.</li>
  <li>For more information, see the Android training on <a
   href="{@docRoot}training/articles/perf-anr.html">Keeping Your App
   Responsive</a>.</li>
 </ul>
<h4 id="content-60fps">Target 60 frames per second on low-cost devices</h4>
 <ul>
  <li>Ensure that your app always runs fast and smoothly, even on low-cost
   devices.</li>
  <li>Overdraw can significantly slow down your app—it occurs when the pixels
   are being drawn more than once per pass. An example of this is when you have
   an image with a button placed on top of it. While some overdraw is
   unavoidable, it should be minimized to ensure a smooth frame rate. Perform
   <a href="{@docRoot}tools/performance/debug-gpu-overdraw/index.html">Debug
   GPU overdraw</a> on your app to ensure it is minimized.</li>
  <li>Android devices refresh the screen at 60 frames per second (fps), meaning
   your app has to update the screen within roughly 16 milliseconds. <a
   href="{@docRoot}tools/performance/profile-gpu-rendering/index.html">Profile
   your app</a> using on-device tools to see if and when your app is not
   meeting this 16-ms average.</li>
  <li>Reduce or remove animations on low-cost devices to lessen the burden on
   the device’s CPU and GPU.  For more information, see the Android training on
   <a href="{@docRoot}training/improving-layouts/index.html">Improving Layout
   Performance</a>. </li>
  <li>An efficient view hierarchy can speed up your app without increasing the
      app's memory footprint. For more information, see
  <a href="/topic/performance/optimizing-view-hierarchies.html">Performance
  and View Hierarchies.</a>
 </ul>
<h4 id="content-firstload">If anticipated start speed is low, use launch screen on first load</h4>
 <ul>
  <li>The launch screen is a user’s first experience of your application.
   Launching your app while displaying a blank canvas increases its perceived
   loading time, so consider using a placeholder UI or a branded launch screen
   to reduce the perceived loading time.</li>
  <li>A<a href="https://www.google.com/design/spec/patterns/launch-screens.html#launch-screens-types-of-launch-screens">
   placeholder UI</a> is the most seamless launch transition, appropriate for
   both app launches and in-app activity transitions.</li>
  <li><a
   href="https://www.google.com/design/spec/patterns/launch-screens.html#launch-screens-placeholder-ui">
   Branded launch screens</a> provide momentary brand exposure, freeing the UI
   to focus on content.</li>
  <li>For more information on implementing splash screens, see the <a
   href="https://www.google.com/design/spec/patterns/launch-screens.html">
   Launch screens</a> section of the Material Design spec.</li>
  <li>The best way to deal with slow start speeds is not to have them. <a
  href="/topic/performance/launch-time.html">Launch-Time Performance</a> provides
  information that may help you speed up your app's launch time.</li>
 </ul>
<h3 id="ui">UI best practices</h3>
 <ul>
  <li><a
   href="https://www.google.com/design/spec/material-design/introduction.html">
   Material Design</a> is a visual language that synthesizes the classic
   principles of good design with the innovation and possibility of technology
   and science. Material Design aims to develop a single underlying system that
   allows for a unified experience across platforms and device sizes. Consider
   using key Material Design components so that users intuitively know how to
   use your app.</li>
  <li>Ready-to-use Material Design components are available via the <a
   href="{@docRoot}tools/support-library/features.html#design">Design Support
   library</a>. These components are supported in Android 2.1 (API level 7) and
   above.</li>
 </ul>
<h3 id="localization">Localization</h3>
 <ul>
  <li>Your users could be from any part of the world and their first language
   may not be yours. If you don’t present your app in a language that your
   users can read, it is a missed opportunity. You should therefore
   localize your app for key regional languages.</li>
  <li>To learn more, visit the Android training on <a
 href="{@docRoot}training/basics/supporting-devices/languages.html">
 Supporting Different Languages</a>.</li>
  <li>Starting from Android 7.0 (API level 24), the Android framework
  makes available a subset of the <a class="external-link"
  href="http://userguide.icu-project.org/">ICU4J APIs</a>, which can
  help you localize your app into multiple languages. For more
  information, see <a href="/guide/topics/resources/icu4j-framework.html"> 
  ICU4J Android Framework APIs.</a>
 </ul>

<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13"
  data-query="collection:distribute/essentials/billionsquality/content"
  data-sortOrder="-timestamp"
  data-cardSizes="6x3"
  data-maxResults="6"></div>