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.
Related
I have two questions.
I want fire a Broadcast receiver using AlarmManager and show a notification in onReceive method. Should I use from WakeLoke for this?
What is different between setAlarmClock() and setExactAndAllowWhileIdle() ?
I use (as you wrote) the onReceive method to start a newWakeLock and it works fine for me.
The difference lies in the behavior in doze mode (Doze Mode: https://developer.android.com/training/monitoring-device-state/doze-standby).
I do not know your exact problem, but I worked very hard to develop an app which contains few timers and every timer should make a notification at the exact time even the screen is locked and the device is in the doze mode. My solution is to fire an Broadcast over an AlarmManager with the setExact(...) method.
Answer your question in reverse order
.2. setExactWhileIdle guarantees that if the system is not sleeping and not in doze, the alarm will go off within 1 minute of the given time. if the system is in doze mode, the alarm will go off within 15 minutes of the given time. In practice, if the system is not in doze mode or low on battery, the alarm will go off on time. On the other hand, setAlarmClock is the closest one can get to a guarentee that the system will deliver the alarm at a specific time; this does come at a relatively large drain on battery. So, if your goal is to implement highly time sensitive notifications such as an alarm clock, then use setAlarmClock. Otherwise try to avoid it.
.1. according to the documentation, upon an alarm being dispatched from setExactAndAllowWhildIdle or setAlarmClock:
the app will also be added to the system's temporary power exemption list for approximately 10 seconds to allow that application to acquire further wake locks in which to complete its work.
My suggestion is that if all you are doing is posting a notification, then a wake lock is not necessary. Otherwise, if you are doing longer running work, use a wake lock
Obligatory Disclaimer: battery drain is a real thing. please don't make an app that drains the battery. do everything in your power to design your app not to disturb the systems power optimization. All exact alarms and especially setAlarmClock disrupt the systems attempts to optimize battery. If its necessary, then its necessary. Otherwise, do not do it.
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.
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 have an activity with some Handlers that are being executed at intervals no more than 5 minutes. The activity is launched from a BroadcastReceiver and may be launched with the screen off waiting for the user to grab the phone and get the user input, when this happens, the activity onPause() is called so for sure CPU is in sleep mode. I have not set the activity to turn screen on because I want to save as much battery as possible.
I've tested it with my phone and works really well, while screen is off all Handlers execute all the code they have to run. If I turn the screen on and off while the activity is open everything works fine.
Now, I've read everywhere that some devices does not work as expected when screen goes off and CPU sleeps, most of the times with accelerometers. Now my question is, do I need to acquire a WakeLock so the CPU does not sleep while my activity is open? I really want to know this because, as I said before, I don't want to 'waste' battery by acquiring an expensive WakeLock.
I would prefer a detailed answer of a person that really knows how this works.
Your goal cannot be stably achieved by your approach. If you use an Handler's postDelayed() method and the CPU goes to deepsleep, the ms counter will stop and will only continue if the CPU wakes up again.
See this for more detail.
So if you want to have some kind of a cron job you will need to use wakelock.
Fortunately there is a Service implementation that does exactly that: Wakeful IntentService
From the doc:
The recommended pattern for Android's equivalent to cron jobs and Windows scheduled tasks is to use AlarmManager. This works well when coupled with an IntentService, as the service will do its work on a background thread and shut down when there is no more work to do. There's one small problem: IntentService does nothing to keep the device awake. If the alarm was a WAKEUP variant, the phone will only stay awake on its own while the BroadcastReceiver handling the alarm is in its onReceive() method. Otherwise, the phone may fall back asleep. WakefulIntentService attempts to combat this by combining the ease of IntentService with a partial WakeLock.
I'm have a widget that is being updated from a service. When the user then turn off the screen, the service stops and won't start to update the widget again when the user wake up the device. So on to my question, is there some way to "restart" the service when the user wake up the device? I know I can keep the service keep going when the screen is locked, but I think it would drain to much battery then... I have google'd alot but haven't found anything...
Thanks in advance!
EDIT: Okey, this is strange! Now somehow it does that automatically, so it's working now! Thanks anyway!
EDIT 2: Or, now I don't really think it's the screen lock that stops the service, cause it just sometimes stops randomly without crashdialog when I use the phone... Anyone know how I should do to fix that?
For a widget it usually doesn't make sense to keep a service running all the time, you usually update the widget periodically.
The easiest way to do this and to be battery efficient is to schedule an intent using AlarmManager and setAlarmInexactRepeating:
Schedule a repeating alarm that has inexact trigger time requirements; for example, an alarm that repeats every hour, but not necessarily at the top of every hour. These alarms are more power-efficient than the strict recurrences supplied by setRepeating(int, long, long, PendingIntent), since the system can adjust alarms' phase to cause them to fire simultaneously, avoiding waking the device from sleep more than necessary.
The intent should trigger a BroadcastReceiver which in turn should trigger your service to update the widget. Using IntentService is usually a good choice for that.
If you need more control over the intent scheduling, you can also set the alarms yourself in when the service is finished with updating the widget, and supply RTC or ELAPSED_REALTIME as the type of alarms. Both types won't wake up the device if it's sleeping. If the device is not sleeping (but locked) you'll effectively piggy back on other events that woke the device.
If you really need to update as soon as the device is unlocked, the ACTION_USER_PRESENT broadcast might be what you need, but I'd still recommend to implement that as an addition to scheduling a periodic update.
Yes this is Possible!
When the user turn off the screen You Have to handle BroadCast Receiver (http://developer.android.com/reference/android/content/BroadcastReceiver.html)
That handle to Stop service & the service stops and stop to update the widget,
when the user wake up the device you have to Receive Broadcast start to update the widget.
I think it would be The best idea to save more battery.
For More information Please Refer this Link