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.
Related
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.
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 want to create repeating service by alarm manager. if app is running in live time then it is correct running every one min. it in sleep mode to running every five min. why it is not running every one min in sleep mode?
public static final long NOTIFY_INTERVAL = 60000;
AlarmManager alarms = getAlarmMAnager();
alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), NOTIFY_INTERVAL, recurringAlarm);
That is very much expected and can happen due to various reasons
Android Oreo has limitations on running services in background, so you may face this on O devices
Doze mode on Android Marshmallow onwards can cause this, it will stop all network operations itself & take away CPU wake locks
AlarmManager is not meant to for doing repeated operations in background
I will suggest you to use JobsSchedulers or Firebase Dispatchers for tasks which you want to execute in background, as it will take care of Doze mode, background service limitations, no network scenarios etc.
I just went through this tutorial:
update-widget-in-onreceive-method
(btw: would you propose any improvements to that code?)
At the end someone mentions:
I'm just wondering if there is a way to extend this further so that when the device is asleep (screen off), the updates stop. Then when the device wakes up, the updates resume.
So my question: is there a way of doing this? how?
or is the alarmmanager automatically stopped? - I don't think so.
You can specify whether the device will wake up when scheduling the AlarmManager.
Quote from the documentation:
ELAPSED_REALTIME
Alarm time in SystemClock.elapsedRealtime() (time
since boot, including sleep). This alarm does not wake the device up; if it goes off while the device is asleep, it will not be delivered until the next time the device wakes up.
ELAPSED_REALTIME_WAKEUP
Alarm time in
SystemClock.elapsedRealtime() (time since boot, including sleep),
which will wake up the device when it goes off.
Same goes for AlarmManager.RTC and AlarmManager.RTC_WAKEUP
So you probably want one of the two AlarmManager.RTC or AlarmManager.ELAPSED_REALTIME. These continue while the device is awake and stop when the device is in standby. If this alarm is triggered while the device is asleep it will be delivered when the user turns the device back on though, exactly what you want. And no, the AlarmManagers scheduled alarms are not cancelled automatically in general.
The part mentioned here can be found in this part of the tutorial, specific this line:
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 20*1000, pendingIntent);