By Erik
28th August 2010.
09:46
Thanks for the tutorial!
Looking forward to more tips and tricks.
Br
Erik
0
0
In this post I will cover a few important guidelines on how reduce power consumption of polling Android applications, i.e. applications that regularly connect to the internet, and get more out of the phone battery. I have crated a small sample app that puts all of the tricks into practice by setting up a background service that polls Twitter trends regularly and logs them to a file. By downloading the sample app and applying these guidelines, you will reduce the power consumption of your app by magnitudes, if you haven’t before. Click here to download the sample app.
We will cover four guidelines:
1. Synchronize you polls with other apps
2. Make polls short
3. Manage your connections
4. Stop your services
Synchronizing polls
Synchronizing you polls with other polling apps will reduce how often the radio is activated. It is achieved by using AlarmManager with setInexactRepeat and a interval constant provided in AlarmManager, e.g. INTERVAL_HALF_HOUR. These constants are special in that AlarmManager.setInexactRepeat will fire the intents at a regular intervals simultaneously, but not at exactly specified times. In the sample apps we have a BroadcastReceiver (Booter) which wakes up at boot which in turn kick off a Service (Poller) at regular synched intervals:
[java]
public void onReceive(Context context, Intent rIntent) {
if (rIntent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, Poller.class);
PendingIntent pIntent = PendingIntent.getService(context,0,intent, 0);
long interval = AlarmManager.INTERVAL_FIFTEEN_MINUTES;
long firstPoll = System.currentTimeMillis();
am.setInexactRepeating(AlarmManager.RTC, firstPoll, interval, pIntent);
}
}
[/java]
If apps don’t use this, this is what will happen when three different apps poll at random times within an interval:
As you can see, the radio has to stay in DCH and FACH state for a long time after each request and response transaction (user data) has been completed. If they sync the polls (HTTP requests) it looks like this:
As you can tell, this will save lots of power for each poll cycle.
Make sure to use AlarmManager.RTC, not AlarmManager.RTC_WAKEUP, i.e. don’t wake up the application unless some other app is also being woken up. Google services run regularly and will make sure your app wakes up now and then.
Execute polls in as short time as possible
A poll with several requests and responses spread out over time will force the radio to stay in a high power state for long time. If a poll consists of multiple requests, fire them all before waiting for responses if they are independent. If not, then try to reduce the poll to as few requests as possible, e.g. by changing the server interface. If you don’t have control over the server, then use features like multiquery or batched queries, if supported (e.g. Facebook). If you control the server, make sure it’s response times are short (within a couple of seconds). The sample project only has a single request, so this tip is not illustrated, but is straightforward to implement.
Minimizing the amount of data sent and received saves battery. Thus, also make sure to set the Accept-Encoding HTTP header to “gzip”. Twitter and Facebook APIs both support gzip. The sample project defines two Interceptors and an Entity to add support for compression, which makes it transparent when using the client.
[java]
httpclient.addRequestInterceptor(new GzipHttpRequestInterceptor());
httpclient.addResponseInterceptor(new GzipHttpResponseInterceptor());
HttpGet httpget = new HttpGet(“http://api.twitter.com/1/trends/current.jons”);
HttpResponse response = httpclient.execute(httpget);
[/java]
Manage HTTP connections
HttpURLConnection has a well known bug that leave connections hanging by not closing them as they should, when using HTTP GET. Specifically, it leaves connections hanging when using the Twitter API. After a minute or two after your requests is sent, the server forcibly closes the connection, causing a big power surge due to the radio link becoming active, even though your application is not sending or receiving any data. In the sample project I use the Apache client instead and make sure to close the connection forcibly using
[java]
httpclient.getConnectionManager().shutdown();
[/java]
Stop services
Services should be short lived and stopped as soon as they have finished their task, using stopSelf(). Have it wake up using intents when needed, e.g. using AlarmManager.
Sample app
In the sample app, the Poller class is only activated by the intent setup by the Booter class as you saw above. When an intent is fired, the Poller is activated by a call to onStart, which causes a poll to Twitter. After the poll, the Poller shuts down with a single line, causing it to not use any CPU until next intent fires it up.
By Erik
28th August 2010.
09:46
Thanks for the tutorial!
Looking forward to more tips and tricks.
Br
Erik
0
0
By Anders
1st September 2010.
08:45
Very nice tutorial!
Thanks for sharing.
Cheers,
Anders
0
0
By Håkan Jonsson
2nd September 2010.
16:41
Thanks for the feedback!
I hope to be able to write an article on how to detect & troubleshoot power consumption problems related to networking in the future.
/Håkan
0
0
By Bachi
22nd September 2010.
22:18
Thanks a lot for this tutorial and example app, it quite helped me!
One question though: Should one not implement a wake lock to prevent the device from falling asleep while the service is executing?
- Bachi
0
0
By Håkan Jonsson
27th September 2010.
17:49
Hi Bachi,
In the sample app, the CPU wakes up for a short time when the alarm triggers, which is enough for the poll to complete. If your service does something more time consuming you may need to use a partial wake lock to make sure the service completes its execution.
However, in this and possibly most cases I see no danger in the device falling asleep while the service is executing. Polling is usually a non critical activity, since you don’t know what you get or even if you get anything, and wake locks should only be acquired when really needed. If you use them, make sure you release them properly. Failure to do so will cause battery to drain fast. The battery bug in the Facebook app released this summer was caused by a failure to release the wake lock: http://geekfor.me/news/facebook-1-3-wakelock/
/Håkan
0
0
By Zach Young
20th October 2010.
16:12
In your example, why do you use a PendingIntent?
1
0
By Zach Young
20th October 2010.
16:39
Also on your poller service could you have used an IntentService instead?
0
0
By buy hoodia gordonii
9th November 2010.
17:41
Don’t you love the irony, eh?
0
0
By Chris Jenkins
14th January 2011.
03:44
Thanks for that, was searching for something like this for ages!
Will make a blog post about my findings I shall be sure to mention you!
Cheers,
Chris
0
0
By world of warcraft guide download
18th January 2011.
00:37
I’ve been surfing online more than two hours now, yet I never found any good post like yours. It’s pretty worth enough for me. These days I’m playing wow a lot Greetings Chrissy Kehm@cologne-uni.edu
0
0
Sort by