I'm writing an application which needs to detect when the screen turns on or off from the background (with the precision of about 1 minute). Ideally, I'd just statically register for Intent.ACTION_SCREEN_ON and Intent.ACTION_SCREEN_OFF, but unforuntately, that's not allowed.
This leaves me with two not-so-great---actually-pretty-horrible options (unless there's something I'm unaware of, which is likely):
Run a omnipresent Service + BroadcastReceiver which registers for the ACTION_SCREEN_ON and OFF intents OR
Use the AlarmManager to schedule some code to run every minute, and check if the display is on/off with isInteractive()
#1 isn't great because it can be killed, it wastes memory, it needs to be run onboot which doesn't work when installed on the SD card, etc.. the list goes on.
#2 isn't great because it's less precise and... let's face it- polling is almost never the right answer
But worst of all, they will both have a negative impact on battery life. This is actually the most important factor IMHO.
TL;DR
Which is the lesser of the two evils with respect to battery life impact?
I'm not an android developer (but it would be fun) but when reading the AlarmManager class overview, it says that it will periodically launch an application if it is not running already. This isn't polling as the code isn't running and not affecting performance or keep the processor awake (consuming energy). I'm sure the AlarmManager class itself isn't polling either.
You might also look at suspending your applications process instead and periodically waking it up. Launching a process is typically an expensive operation. Though suspending the application doesn't consume processor resources (and so affect power consumption) it does have a memory footprint.
Related
I wrote an app recently and, well I'm quite disappointed about how much battery the service consumes. I go to make a call yesterday to find my battery is at 9%; I check the android system statics for the battery and find that my app is responsible for 60% of the battery drainage
My question is, what can one do to reduce the battery usage on an app that runs and then sleeps for 60 seconds? The service is reading from a SQLite database; I could cache the data, but would that really account for that much battery usage? What are some standard ways to reduce battery drainage in a service?
You should look into using AlarmManager to schedule your app or service to be called when necessary. This has a big advantage over your current wake lock method, because even a partial wake lock will keep the CPU running. An AlarmManager alarm can wake the phone even from CPU sleep.
Basically, get rid of your existing wake lock and schedule an AlarmManager alarm—which can repeat once a minute, if that's what you need—to wake up the device, if necessary, and send you a message.
The AlarmManager itself will take out a wake lock while calling an onReceive() method to notify you of the alarm, and relinquish it when onReceive() finishes, letting the phone go back into deep sleep if it wants to.
Note that this means that if you want to do extended work—e.g. firing something off on a background thread—you'll probably want to take your own wake lock out in onReceive() and relinquish it when your work is done, otherwise the phone may go to sleep while you're in the middle of the work.
This is all pretty well-explained in the AlarmManager docs, but the best explanation I've seen is in Mark Murphy's The Busy Coder's Guide to Android Development; he also provides a library for exactly this pattern on Github. Definitely worth a look.
I'm writing an app that constantly polls the device's sensors and every so often should write down some statistics to a file. This could be as fast as once a second or as slow once a minute. Should I use Handler's postDelayed()method or just schedule it with the AlarmManager?
This should help you discriminate between Handler and AlarmManager.
[source]
Though it is agreed these mostly work for API 23. It's a new release.
If the app should work in standby then AlarmManager. If not then Handler.
AlarmManager will wake CPU therefore it will drain battery more, while Handler will not work on standby.
Decide your design based on the below key points:
AlarmManager:
The advantage with the AlarmManager is that it works even if the device is in deep sleep mode (CPU is off). When the alarm fires, it hits the BroadcastReceiver and in onReceive, it acquires the wake lock (if you have used WAKEUP types of alarms like RTC_WAKEUP or ELAPSED_TIME_WAKEUP). After finishing the onReceive() it releases the wake lock.
But most of the times it DID NOT WORK for me. So I have acquired my own wake locks in onReceive() and released them at the end to make sure I really get CPU.
The reason why it DID NOT WORK is that when multiple applications simultaneously use a resource (such as wake locks that prevent the system from suspending), the framework spreads CPU consumption across those applications, although not necessarily equally. So, if it is critical, it is always better to acquire wake locks and do the stuff.
Timers and Handlers:
Handler and Timers do not work in deep sleep mode meaning the task/runnable will not run as per the schedule when the device is asleep. They do not count the time in sleep which means that the delay given to execute task will be calculated only during active mode. So, actual delay will be delay-given + time-spent-in-deep-sleep.
I'd say that it depends on the polling interval. I guess it's quite low in your case (around a few secs), so you should go the Handler way, or by using the Timer class.
AlarmManger is a much higher level service and it involves a larger overhead to handle this use case. When an alarm triggers, you need to handle it with BroadcastReceivers. This means that every time you handle one of these alarm, you needs to register listeners for the sensors you're interested in, which is immensely inefficient imho.
Admittedly I am just kind of hacking here so I would like some knowledge.
I have a service I run in the background connected to another thread that counts down a timer. I was having problems with the count down dying after a while and presumed it was due to garbage collection of the service. I seem to have fixed the issue (and see no real battery use) using startForeground. Now I read about wakelocks, are there any best practices on when to use one or the other?
Thanks!
I have a service I run in the background connected to another thread that counts down a timer.
Please use AlarmManager, so your service only needs to be in memory when it is actually doing work, not just watching the clock tick. One of the biggest user complaints about Android is all these background things that developers create that clog up their phones.
I seem to have fixed the issue (and see no real battery use) using startForeground.
The point behind startForeground() is to indicate that your service is continuously delivering value to the user, such that the user will notice if the service is reclaimed due to hanging around too long or low memory conditions. Sitting and watching the clock tick is not "continuously delivering value to the user". Please use AlarmManager, and you will not need startForeground().
Now I read about wakelocks, are there any best practices on when to use one or the other?
WakeLock keeps the CPU powered on (and possibly other things, like the screen). It has little to do with startForeground(). If you use AlarmManager, depending on the work that you are doing, you may need a WakeLock to ensure the device stays awake while you do your perodic wo
I have an application that wakes up at frequent intervals (once per minute) to do some stuff in the background. I will be using the AlarmManager to schedule the wake ups.
I am looking at two different ways of structuring a Service to do the background work:
keep the service continuously running in the foreground with setForeground(). This is attractive since the application state will remain in memory between wake-ups.
use stopSelf() to destroy the Service after it has finished running the background task. This will require persisting some non-trivial objects between each wake up.
What are the pros and cons of each approach? How costly is persistence? What is the recommended approach for storage for case 2?
I will be using the AlarmManager to schedule the wake ups.
Hopefully not if you are going with option #1. If your service will be running all of the time anyway, just use Timer.
What are the pros and cons of each approach?
setForeground() doesn't work and hasn't for quite some time. startForeground() works, but it requires an active Notification.
A one-minute polling cycle is on the cusp of when I'd consider switching to AlarmManager and an IntentService. That being said, a one-minute polling cycle is awfully frequent. I strongly encourage you to make this user-configurable, including an option for "please don't poll, I'll request updates through the UI".
This will require persisting some non-trivial objects between each wake up.
You need to be persisting those objects in both cases. For example, when the user attacks your option #1 service with a task killer, it'd be nice if you did not lose their data.
How costly is persistence?
It does not really matter, since you need to be be persisting those objects in both cases.
What is the recommended approach for storage for case 2?
That is impossible to answer in the abstract.
You definently want to go with option 2 and stop your service once it's done. If you keep it running your going to keep using system resources, namely the battery. Do what you need to do, then stop the service. Also, what kind of wake up are you doing every minute? If you are doing a full-out device wake up (RTC_WAKEUP), you're once again going to kill the devices battery.
I hope this doesn't sound snooty, but I once heard a devloper say "Don't fight android, android will win". When you keep tyring to set your service to the foreground, you're fighting against androids attempts to clean up resources that aren't in use. You should instead embrace android. Do things as asynchronously as possible. That's the android way :)
I believe it's because of some power saving option or whatever but I cant debug it since it only fails when it's on battery
I have a service that checks on a webpage every 60 seconds
I use an asyncTask in the service to do this
and I make it Thread.thisThread.sleep(60000); before checking
am I doing something wrong? could the sleep function cause the server to be stopped by android?
I have a service that checks on a webpage every 60 seconds I use an asyncTask in the service to do this and I make it Thread.thisThread.sleep(60000); before checking
Please don't do that.
First, make the period configurable, including a "don't do this, ever" option. Users really do not like it when developers write apps whose primary purpose appears to be to use up a ton of battery life. Keeping the device awake and polling a Web server every minute is going to use up a ton of battery life. It is behavior like this that is causing users to run to every task killer they can find.
Second, particularly for periods greater than a minute or so, please use AlarmManager and a [WakefulIntentService][1]. Schedule the AlarmManager to invoke your application at the user-chosen period (ideally via setInexactRepeating()). Have the WakefulIntentService poll your Web page. If you follow the documented WakefulIntentService recipe, the device will stay awake long enough for you to get your data, then will fall back asleep. Your service will not remain in memory all of the time. You get your functionality, and the user gets better device performance.