Jeff Sharkey, recently hired by Google, presented an interesting session this afternoon called "Coding for Life - Battery Life, That Is". In it, he offered several practical tips for Android developers to prolong the life of their users' batteries.
All apps need to work together to be good citizens and conserve the limited battery power available on today's mobile devices, according to Jeff. Here are some typical battery capacities:
- HTC Dream: 1150mAh
- HTC Magic 1350mAh
- Samsung i7500: 1500mAh
- compare to Asus EEE PC: 5800mAh
Most users report under a day's worth of battery life on the HTC Dream (T-Mobile G1), so where does all the power go?
Waking up in the background when the phone would otherwise be sleeping costs a lot. For example, if an app wakes up every 10 minutes to update, and takes about 8 seconds to update, that's 350mA. Cost during a given hour: 5mAh resting, plus 6 updates an hour is another 4.6mAh updating. So basically that app cut your battery life in half. On top of that, just one app waking up can trigger a cascade of other apps that try to pile on and do their updates as well.
Bulk data transfer costs a lot. For example a 6MB song costs up to 45mAh on EDGE because it takes 9.1 minutes * 300mA. Moving between cells/networks is another cost because of radio ramp up and BroadcastIntents. Parsing textual data, and doing regex without JIT also contribute.
So what can developers do to improve the situation?
The first way is to be smarter about networking. Check network connection, wait for 3G or WiFi. Check connectivity.getBackgroundDataSetting() (new in Cupcake). Use an efficient data format and parser (XML > JSON > Protobuf; tree parser > steam parser). And use GZip for text data whenever possible. Android GZip libs use native code.
The next way is to look at foreground apps. Wakelocks are costly if forgotten. Pick the lowest level possible, and use specific timeouts to work around unforseen bugs. Use android:keepScreenOn to ensure correctness. Recycle Java objects, especially complex objects. - Use coarse network location - it's much cheaper. Avoid floating point math, and use a slower accelerometer rate.
Next, consider your background applications. Services should be short-lived; these are not daemons. Each process costs 2MB and risks being killed/restarted as foreground apps need memory. Otherwise keep memory usage low so you're not the first target. Trigger wake-up through AlarmManager or with <receiver> manifest elements, and call stopSelf() when finished.
Android 1.5 (Cupcake) introduced inexact repeating alarms (the setInexactRepeating() method) which lets the system batch up your update with others to minimize the number of wakeups the system has to do in a given time period.
in the Q&A session, Jeff shared some other insights. One that stuck out for me was that changing the screen brightness didn't affect battery life all that much. At the lowest brightness, the LCD backlight drew about 70mA, but it only drew about 110mA at its highest brightness. With factory defaults it takes about 90mA.