I have an AlarmManager which calls a BroadcastReceiver every minute. It is working fine without any problem. The BroadcastReceiver looks up the values existing on a SharedPreferences file. It checks around 4 values every minute.
I was just wondering if this is taking a toll on the system. And will it eventually make the device slower ?
PS - I cannot reduce the values anymore. That would conflict with my current design.
Thank You in advance.
PPS - A brief theory regarding the time and speed of SharedPreference would be greatly appreciated.
Well, I don't know if AlarmManager drains your battery fast, but what I suggest u to do is remove the AlarmManager part in your code, and use a Handler instead.
From the AlarmManager:
Note: The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running. For normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.
precision timing required either:
setRepeating for < API19
setExact API 19 <
Note: only alarms for which there is a strong demand for exact-time delivery (such as an alarm clock ringing at the requested time) should be scheduled as exact. Applications are strongly discouraged from using exact alarms unnecessarily as they reduce the OS's ability to minimize battery use.
these are both pretty battery consuming.
So u would have to go with:
setInexactRepeating for < API 19
Note: 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 traditionally supplied by setRepeating(int, long, long, PendingIntent), since the system can adjust alarms' delivery times to cause them to fire simultaneously, avoiding waking the device from sleep more than necessary.
but this is not very precise for an alarm that has to execute every minute.
So, you're probably best of with a Handler:
final Handler handler = new Handler()
handler.postDelayed( new Runnable() {
#Override
public void run() {
//Do your things
handler.postDelayed( this, 60 * 1000 );
}
}, 60 * 1000 );
Hope this answers your question. If anything isn't correct or should be improved, feel free to edit/add this, or leave a comment below.
Related
I have to update Data in my App every 24 hours at 2 am.
Currently, I have an Alarm via the AlarmManager which sends an alarm every 24 hours with the setRepeating method.
In the past I have experienced some unreliabilities with the timing of the alarm, so I was experimenting with an intent-filter and Intent.ACTION_TIME_TICK.
My Question:
What is the difference between setting a repeated alarm every 24 hours and using an intent-filter which gets its information from the system?
You should absolutely not do anything with ACTION_TIME_TICK. Nor would it be reliable if you tried- it would only work while your app is running, and if you're backgrounded you will be killed for resources. The correct answer here is actually JobScheduler or WorkManager, depending on the nature of what you're doing. Most likely WorkManager. However if you were worried about the reliability of timing of an alarm, you probably are thinking about your problem wrong. Unless you have a VERY niche use case, a bit of inaccuracy in downloading a nightly update is generally ok. In fact it may even be welcome, to spread the load out on the server. Your inaccuracy of dl time is likely due to Doze, which is a mechanic your use case should likely account for (Doze is a power saving mode where it reduces the frequency of timed events running when the screen is off).
What are the parameters of the following:
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_FIFTEEN_MINUTES, alarmIntent);
And of the following:
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, alarmIntent);
What is the difference and also how are the two different in terms of functionality?
Both examples schedule a repeating alarm that will send the given alarmIntent. On both cases, the first time it is sent will be immediate (calendar.getTimeInMillis() returns the current time). On both cases, the device will be woken up when the alarm needs to be sent (as evident by AlarmManager.RTC_WAKEUP).
There are two differences between these calls. The simpler one is that the intent will be sent every fifteen minutes on the first call, and every day on the second call (as you can see in the third parameter). The more complicated difference is the function call itself: setRepeating will schedule the first alarm for exactly every fifteen minutes; setInexactRepeating will schedule the second alarm for approximately every 24 hours, meaning it might deviate from that interval - with the advantage of consuming less power.
Do notice that this has changed in API 19, where these two calls are synonymous. See this guide, and this API documentation.
Decide how precise your alarm needs to be
Choosing the alarm type is often the first step in creating an alarm. A further distinction is how precise you need your alarm to be.
For most apps, setInexactRepeating() is the right choice. When you use this method, Android synchronizes multiple inexact repeating alarms and fires them at the same time. This reduces the drain on the battery.
For the rare app that has rigid time requirements as example, the alarm needs to fire precisely at 4:00 p.m. everyday then use setRepeating().
Reference: Decide how precise your alarm needs to be
To augment previous answers, there are a number of other best practices to consider when using repeating alarms, particularly inexact alarms requested using setInexactRepeating().
Alarm Type
Non-WAKEUP alarms are better than WAKEUP alarms from a power management perspective. Using the former your alarm may fire late, but it will still fire either when the device is woken by the user, or when another wakeup alarm fires. Using WAKEUP alarms will wake the device out of sleep, consuming additional battery and potentially causing other inexact alarms to fire that have been delayed that could otherwise have been delayed longer (reducing the batching power-saving benefits that inexact alarms provide).
Prefer alarms using the ELAPSED timebase rather than the RTC timebase. The former are more likely to have a more random distribution across devices than RTC alarms, which reduces the risk of network congestion and on the server if the alarm is triggering some sort of poll. Phones running Gingerbread (or older) suffer from a bug whereby RTC inexact alarms have a tendency to align closely to the real-time clock, e.g. approximately 30s past each quarter of an hour. ELAPSED alarms don't suffer from this bug on these earlier platform versions. Even if your alarm doesn't trigger any network activity, remember that if it is a wakeup alarm it may trigger other alarm non-wakeup intents that may hit the network.
Timebase
Be careful to specify the requested start time in the correct time domain for the alarm type. Failure to do this can result in alarms being set in the past (they fire right away) if setting an RTC alarm with an ELAPSED timebase or far in the future if setting an ELAPSED alarm using the RTC timebase. You can check what alarms an app has scheduled using dumpsys alarm via the adb shell.
Interval
Specifying an inexact alarm interval of anything other than the interval constants defined in the AlarmManager API is redundant on SDK <19: they will be scheduled as exact not inexact alarms, losing all the power-saving benefits that inexact alarms provide.
Edit: here's further explanation of the bug relating to gingerbread and honeycomb 3.0 devices: https://code.google.com/p/android/issues/detail?id=31550
setRepeating is more accurate and setInexactRepeating is for saving battery but no accurate , setInexactRepeating is good for maintenance in background for example and setRepeating is necessary for example for alarm clock .
Use setInexactRepeating() is used when app is not seriously used to required for example wake up early in the morning . if Alarm wake up approximately that time there is no any life dangeous.
like medicine pills app where highly critical patient use that app to reminde nurse or doctor staff the is compulsory to use setRepeating().
When you use setInexactRepeating()
then Android synchronizes repeating alarms from multiple apps and fires them at the same time(once). This reduces the total number of times the system must wake the device.
thus reducing drain on the battery.
repeating alarms are inexact. Note that while setInexactRepeating() is an improvement over setRepeating() also
it can still overwhelm a server if every instance of an app hits the server around the same time. Therefore, for network requests, add some randomness to your alarms.
My code logic is like
Set a repeated wakeup alarm.
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), 60000, pIntent);
during onReceive() of the receiver. do something very quick, may just need 100ms at most.
The operation will repeat every minute and it will be battery burden somehow ( since we want to the background service run as long as possible).
Now, according to our power monitoring tool, even if we do just some logging in onReceive(). It still takes around 1.5 seconds.
I have done some research and I conjecture it may related to the waiting in
alarm_suspend of android enhanced linux kernel.
However, I am not sure about it. Looks like there is no reason android need to keep the alarm running time that long, so I am asking if someone has some good experience on setting up the alarm and make the overhead as small as possible?
Thanks.
How to use alarm manager at accurate time interval?
I used alarm manager but it response inaccurate.
Can anyone help me?
I used this code
PendingIntent sender;
AlarmManager am;
long firstTime;
Intent itnt = new Intent();
itnt.setAction("abts.medismo.medismo.ALARMRECEIVER");
sender = PendingIntent.getBroadcast(context, 0,itnt, 0);
am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.cancel(sender);
firstTime = SystemClock.elapsedRealtime();
am.setInExactRepeating(AlarmManager.ELAPSED_REALTIME,firstTime, Integer.parseInt(sep[3]), sender);
You should use ELAPSED_REALTIME_WAKEUP, because if the phone is asleep it wont fire until it wakes up again.
There are two issues here.
The first, as others have pointed out, is that your alarms are not "wakeup" alarms. This means that if the device is asleep when the trigger time is reached, the alarm will not cause the device to wake up and process the alarm immediately. Instead, it will be processed as soon as something else causes the device to become active, such as the user picking it up and pushing the power button to start using it.
The second issue is that you are using setInexactRepeating(). As the name implies, these alarms are never going to be delivered at precisely predictable times. As the documentation says, "In addition, while the overall period of the repeating alarm will be as requested, the time between any two successive firings of the alarm may vary."
This is often enough for most apps, and it is more efficient in terms of battery use. However, if you truly need the alarm to be delivered at a specific time, you need to set the alarm time yourself instead of relying on periodic alarms. In addition, as of API version 19, you should use the new setExact() APIs if you truly need precise delivery.
I believe your observed inaccuracy may be caused by the subtle variation of flags for the alarms.
AlarmManager.ELAPSED_REALTIME and AlarmManager.ELAPSED_REALTIME_WAKEUP utilize elapsedRealtime(), which is the number of milliseconds since the device last booted up, good for measuring elapsed time for timers and the like.
AlarmManager.RTC and AlarmManager.RTC_WAKEUP utilize currentTimeMillis(), which is the system clock:
time in milliseconds since January 1, 1970 00:00:00 UTC. This method shouldn't be used for measuring timeouts or other elapsed time measurements, as changing the system time can affect the results.
All four of the AlarmManager clock flags I've listed will include time spent in sleep, but only the *_WAKEUP flags will wake the device to sound the alarm; the default flags will wait until the device is otherwise awakened and then sound the alarm immediately.
Make sure you select the flag that matches your use-case, and ensure that the value of your delay {Integer at sep[3]?} is the amount of time to wait between alarms in milliseconds; as you have it, your Integer is being unboxed and cast to a long; it works, but unless there's a reason for it, I recommend switching to a primitive long; so a 15 minute delay would be:
int delay = 900000L // 15 minutes * 60 seconds * 1000 milliseconds
http://developer.android.com/reference/android/app/AlarmManager.html
http://developer.android.com/reference/android/os/SystemClock.html
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.