I am interested to know how far it's possible to rely on a recursive AlarmManager alarm.
The documentation doesn't cover when the alarms get cleared, but from answers on this site here and there, my understanding is that they either only get cleared when the application gets updated/removed/force-stopped/device rebooted, or all the above plus user-removed via task list/inactivity/OOM.
Is there a conscise answer, or is it another one of those things which vary from device to device, ROM to ROM?
There is also Doze mode. In the Doze mode the Alarms are postponed until the doze mode off.
From doze mode page;
- Standard AlarmManager alarms (including setExact() and setWindow()) are deferred to the next maintenance window.
- If you need to set alarms that fire while in Doze, use
setAndAllowWhileIdle() or setExactAndAllowWhileIdle().
- Alarms set with setAlarmClock() continue to fire normally — the system exits Doze shortly before those alarms fire.
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 am currently working with an android application that uses android job scheduler to call an api at certain interval(lets say every 4 hours).
Suppose my device is not on charge and there is no activity being done on it, so it goes to sleep after some time(lets say after 1 hour of last api call).
Now my device wakes up after 5 hours due to some activity that I did deleberatly. Will the scheduler call the api immediately(as its more than 4 hrs since last call)? or will it wait for next 3 hours to run the job?
(*I have not acquired the wake lock in this case so the device will go to sleep.)
I think you by Deep Sleep you mean Doze. When your device in doze mode your JobServices will not trigger. Periodic job can't be exact. A job is either exact or periodic. So periodic will trigger while in maintenance window between execution interval. If you running your jobs on Lollipop + with high frequency, then it's possible, that some periods are skipped, because the device is saving battery.
Check out restrictions for doze mode:
Network access is suspended.
The system ignores wake locks.
Standard AlarmManager alarms (including setExact() and setWindow()) are deferred to the next maintenance window.
If you need to set alarms that fire while in Doze, use setAndAllowWhileIdle() or setExactAndAllowWhileIdle().
Alarms set with setAlarmClock() continue to fire normally — the system exits Doze shortly before those alarms fire.
The system does not perform Wi-Fi scans.
The system does not allow sync adapters to run.
The system does not allow JobScheduler to run.
But you can use some hacks to make your job executes at specific time/immediately after scheduling.
I'm creating an app to connect with BT device to collect heath data (i.e.: body temperature).
The sensor sleeps for periodic time and wakes up only for limited window of time to connect.
I've tried to create AlarmManager which fires Foreground Service with setExactAndAllowWhileIdle() and it is working as expected for periods higher than 9 minutes,
but below 9 minutes it goes to doze mode and do not fire AlarmManager BroadcastReceiver.
From documentation I do not understand if adding app to battery optimalization whitelist will allow AlarmManager to trigger more offen
https://developer.android.com/training/monitoring-device-state/doze-standby#support_for_other_use_cases
For example, the whitelisted app’s jobs and syncs are deferred (on API level 23 and below), and its regular AlarmManager alarms do not fire
What are the regular alarms? is setExactAndAllowWhileIdle() regular?
Any clarification will be appreciated
EDIT:
I understand that setExactAndAllowWhileIdle() will trigger event in doze mode for periods longer than 9 minutes, question is does adding app to whitelist will allow it to trigger more often
What are the regular alarms ? is setExactAndAllowWhileIdle() regular ?
No. setExactAndAllowWhileIdle() is not regular. Regular alarm could be AlarmManager alarms set though setExact() and setWindow().
but below 9 minutes it goes to doze mode and do not fire AlarmManager
BroadcastReceiver
It has restrictions on how frequently you can set alarm.
Based on the documentation:
To reduce abuse, there are restrictions on how frequently these alarms
will go off for a particular application. Under normal system
operation, it will not dispatch these alarms more than about every
minute (at which point every such pending alarm is dispatched); when
in low-power idle modes this duration may be significantly longer,
such as 15 minutes.
You can refer to Doze restrictions which says:
Standard AlarmManager alarms (including setExact() and setWindow())
are deferred to the next maintenance window.
If you need to set alarms that fire while in Doze, use setAndAllowWhileIdle() or setExactAndAllowWhileIdle().
Alarms set with setAlarmClock() continue to fire normally — the system exits Doze shortly before those alarms fire
For Whitelist:
Apps available in whitelist are partially exempt from Doze and App Standby optimizations. This doesn't mean they have full access to and could perform tasks during doze mode. An app that is whitelisted can use the network and hold partial wake locks during Doze and App Standby. However, other restrictions like jobs being differed, standard alarm trigger are still imposed
Note: You should check acceptable usecases for whitelisting an app.
Google Play policies prohibit apps from requesting direct exemption
from Power Management features in Android 6.0+ (Doze and App Standby)
unless the core function of the app is adversely affected.
I am using AlarmManager, trying to create an Alarm app for android.
I noticed that setRepeating was not working when the phone sleeps.
So, I tried setExactAndAllowWhileIdle.
But, I read this:
Unlike other alarms, the system is free to reschedule this type of alarm to happen out of order with any other alarms, even those from the same app. This will clearly happen when the device is idle (since this alarm can go off while idle, when any other alarms from the app will be held until later), but may also happen even when not idle. Note that the OS will allow itself more flexibility for scheduling these alarms than regular exact alarms, since the application has opted into this behavior. When the device is idle it may take even more liberties with scheduling in order to optimize for battery life.
I need accurate timings like an alarm clock. A user sets it for 6:00 am then ringing at 6:01 or 6:02 would be wierd!
Not ringing at all because the phone is idle is catastrophic!
What can I do now?
Do not use repeating alarms for this purpose. They are not accurate/reliable enough. Schedule one alarm using set() or setExact() (depending on your target API level). When that alarm goes off, set the next one.
NOTE: Make sure that you use an alarm type that will wake the phone:
RTC_WAKEUP or
ELAPSED_REALTIME_WAKEUP
Ok, so I'm setting an alarm:
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerTime, pendingIntent);
where
long triggerTime = SystemClock.elapsedRealtime() + mynterval;
I'm saving triggerTime for comparison in future.
And sometimes alarm is firing before triggerTime!
For example, I can see in logs:
scanTime: 702672466
SystemClock.elapsedRealtime: 702672132
What delta error is possible here - 1 second, 2-3 seconds or more?
And why is this happening?
This is happening due to Android Doze Mode.
If a user leaves a device unplugged and stationary for a period of time, with the screen off, the device enters Doze mode. In Doze mode, the system attempts to conserve battery by restricting apps' access to network and CPU-intensive services.
Now, alarm is the case of CPU-intensive services. As you can see in the image the intensive jobs are done together in so-called maintenance windows.
Standard AlarmManager alarms (including setExact() and setWindow()) are deferred to the next maintenance window.
If you need to set alarms that fire while in Doze, use setAndAllowWhileIdle() or setExactAndAllowWhileIdle().
Alarms set with setAlarmClock() continue to fire normally — the system exits Doze shortly before those alarms fire.