Tame your Android apps power consumption — optimize for battery life

Tame your Android apps power consumption — optimize for battery life

When it comes to battery performance, most of the literature will tell you to concentrate of 3 major areas:

  • Networking, and
  • WakeLocks / Timers
  • Sensors

This is 100% true, networking is by far the most battery intensive operations for most apps. WakeLocks followed by sensor use are the other two major areas and GPS happens to be one of the most commonly used sensor. There are however other areas where you can tweak your app which can result in lower battery usage; some of the techniques discussed below are especially important if your app support Android Wear devices.

Why optimize for battery

Android developers often neglect what impact their app has on battery life. Most of us do not have a background in embedded systems and so we are not conditioned to think about how our design decisions and code can affect battery life.

An app that is greedy for power can leave a bad impression with users and result in bad reviews, and uninstalls. Take a look at the reviews for the Facebook app some time. Even though it is the most popular app in the world, it consistently has bad reviews that mention battery drain as a source of user dissatisfaction. The same is true for the Chrome browser. At present, on my phone, these are the only non-system apps that show up in the battery performance screen.

Most apps do not have the staying power of the Facebook app or Chrome browser, and so a bad impression can cost us users. Users are far more likely to share a bad experience with others than they are to share a good experience. This mean that if your app has a reputation for being a battery hog, this could cost you a lot of potential users as well.

Strategies for battery optimization

In general, there are few strategies to keep in mind when trying to optimize for power use.

Differ work till the phone is put on charge

The win from this strategy is obvious. If we perform tasks while the phone is charging, this will not count towards battery drain. Unless something has to be done right away or shortly, we should differ it till the phone is plugged in. A good example of this is data synchronization with web services for something like the Contacts app or for the Photo gallery app.

Batch work together

There is a power cost of using sensors, radio and even threads. If we can request data once (for example, GPS coordinates) and use it multiple times for different operations, this will be far more efficient than requesting GPS coordinates every time. As a matter of fact, if the phone is going to wake for any particular job, this is a good time to do any background processing your app wants as well as the cost of waking the phone will be borne by multiple apps. Multiple apps will do work in a batch rather than in an ad hoc manner. This is discussed below in depth when I discuss networking and sensors.

Cache and don’t use features and pixels needlessly

Cache can help us avoid networking operations and background processing all of which helps save power. A good example of this would be to download and re-sample bitmaps. These are discussed is greater detail below.

Use Google Play Services

Google Play Services are an amazing set of API that can make development so much easier that it’s hard to avoid them. That being said, if you use Google Play Services to get GPS coordinates or for any other purpose, the power cost of this is spread out across various apps.

Reducing Battery Drain by improving Networking strategy

In general, networking on your device has various states, if there is data being sent and received, your device is fully awake. If data has not been sent and received for a while, your device will start to step down into a standby state. Your device will go from fully awake, to a low power mode to standby.

android.developers.com

To get a better understanding of this, you can read Optimizing Downloads for Efficient Network Access on Android Developers site.

There are a few things to keep in mind when it comes to optimizing for networking.

Batch operations to avoid repeatedly waking your radio

Its very easy to get into a pattern where you request a bit of data, wait a while, then request more data. The problem with this approach is that you will constantly go from a standby mode to a wake mode and there is a power cost associated with doing this. You ideally want to go into full power mode, stay there for as little of a period of time and do as much as possible and then go back into standby.

Each XmlHttpRequest (XHR) results in the radio waking and then staying awake for a while listing for a response. In the worst case scenario, you could wake the radio, as soon as it goes back to sleep.

The best way to avoid this pattern is to distinguish between what has to happen now, and what you can do later. You want to batch together as many network operations as possible. This will allow your radio to enter full power once and stay in full or low power mode for only as long as needed.

Since it’s not possible to predict what the user may want to do, it is a good idea to prefetch as much data as possible in order to avoid unnecessary requests. A good example of this is something like an image gallery where we may want to download and generate thumbnails of a few screens worth of images because it is highly likely the users will scroll through the images.

Perform one large operations over various small ones

It is better to perform one large download compared to various small operations. This is a little counter intuitive when compared to AJAX on the web. The reason for this is that a large download allows your radio to enter into a low power mode while various small downloads will keep you in full power mode.

Download as little as possible

This may seem like it contradicts point #3. However, it is extremely common to use JSON or XML for data transfer, even though the data will be compressed using GZIP, it will still be far larger than a binary serialized format. Using a binary serialized format, such as a FlatBuffer, you can transfer the same amount of data in a fraction of the size. If your networking has to be awake for a shorter period of time, this will save you power. Also, parsing text formats such as JSON are more processor intensive than parsing binary formats (saving you battery).

Caching aggressively can also help reduce the number of networking operations and hence save a lot of power.

Differ requests where possible

Differing request till when the device is plugged in for recharging or is on Wi-Fi can dramatically increase battery performance. In order to make it easier for us to differ tasks till the device is plugged in and/or on WIFI, Google has recently provided the GcmNetworkManager API. You can use the API to schedule network-oriented tasks, and let Google Play services batch network operations across the system. There is also a JobScheduler API that was released as part of Android L.

Use WakeLocks and Timers sparingly

I’ve touch upon WakeLocks in this article already without going into depth about them. Honestly, you can do an entire artcile on them alone. To keep it brief, if there is some work that has to be done when your phone is asleep, you can use WakeLocks to take the phone out of sleep mode. As you can imagine that a lot of apps on a device doing the same could mean that your app is repeatedly being woken up and never really sleeping. You could also forget to release a WakeLock and hence drain your phones battery.

For this reason, if you are using a WakeLock, you should use the version of WakeLock.acquire() that takes a time-out and always remember to release your WakeLocks. This does not however solve the problem of different apps constantly waking up the device which is where the JobScheduler API and theGcmNetworkManager API is extremely useful. These API’s can batch jobs together for you with other apps hence avoiding the scenario where different apps are waking up the phone every few minutes.

WakeLocks are often used with Timers. If you app uses Timers, use inexact timers if applicable. Android can delay these a few minutes in order to batch operations together.

Battery drain by sensors

There are too many sensors to cover individually, instead I’m going to cover GPS which is the main culprit for most apps and give you general guidelines for others.

GPS

The worst culprit for battery drain in sensors tends to be the GPS. It is one of the most commonly used sensors and often developers will request exact coordinates when just a rough location will be enough. Getting a rough user location through the network or last known user location has negligible effect on the battery drain, however requesting coarse or fine location though the GPS is far more draining.

The best advice here is to use the last known location or request passive location updates if applicable and avoid using the GPS altogether. If you must use the GPS, determine whether coarse location is enough and unregister your location listener after coordinates have been received.

If a fine location is needed, then set a time-out for listening for the users location, such as 30 seconds. If you need constant location updates then set as large of an update interval as is feasible.

Location Strategies on the Android Developers site is a good read for this and so is the deep dive into location post on the Android developers blog (its old, but still worth a read).

Also, using FusedLocationProvideApi is a good idea as it is more efficient than using the GPS API directly.

Other Sensors

The rule for most sensors is fairly straight forward, turn them off as soon as you have the data that you need. Most sensors require you to subscribe or register for updates, once you are done, you should unregister or unsubscribe in order to prevent wasting battery. If you use a sensor and you can work off the cached data in the future, do so.

Other minor wins

These will not make a huge difference on your phone, but may make a big difference in Android Wear devices.

The Display

The display is the number of cause of battery drain for your phone. Avoid using WakeLock unless you need it. In OLED screens, individual pixels emit light. This means using dark background can save you power. Its a minor win (nearly negligible) on phones, however on Android Wear devices, this can make a major difference. Keep in mind that LCD screen work differently and using a dark pixels will not result in any savings.

Hardware Acceleration

Generally, turning on hardware acceleration is considered a good thing. However, to simplify a complex problem, hardware acceleration means more silicon on your device being used and hence more battery drain. Do not activate hardware acceleration unless you need it. While on phones and tablets this may not make a big difference, the battery drain can be significant for Android Wear watch faces (for example). Having hardware acceleration activated can drain the battery significantly for Android Wear.

Bluetooth or Wi-Fi

Developers often default to use Wi-Fi or networking on a device if it is available. Now even some Android Wear devices have Wi-Fi built in. However, Bluetooth is far more battery efficient than Wi-Fi. If you find yourself trying to decide between Wi-Fi or Bluetooth in your Android app, from a battery performance point of view, Bluetooth is the clear winning. On Phones however, Wi-Fi is always activated and its simply easier to use it. However, when it comes to communication with your Android Wear device, always use Bluetooth over Wi-Fi. Ideally, despite having Wi-Fi, for any such networking operations, your Android Wear device should always differ to the phone which should communicate via Bluetooth to the Android Wear device.

Threads

If your app has to perform a lot of minor tasks in the background, using a thread-pool or one long living thread to perform these tasks is preferred over using AsyncTasks or Threads. There is power cost and time cost to creating a thread and destroying it, if you do this a lot, it can have an affect not just on your battery, but also on your apps performance.

Analyzing battery usage for your app

The Battery Stats and Battery Historian tool is part of the Android SDK. They can give you a visual overview of how WakeLocks are being used on your device, who is requesting them and how long are they holding on to them. It can also give you an idea of how often and for how long your mobile radio is being activated.

Also, starting in Android L, under Settings > Battery you can select an app and see for how long they have been holding on to WakeLock and even uninstall apps that are abusing WakeLock from there.


Yay! you made it to the end! We should hang out! feel free to follow me on Medium, LinkedInGoogle+ or Twitter.

發佈了6 篇原創文章 · 獲贊 6 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章