I have an application that uses a ForegroundService
to send location updates to a server. Basically a tracker.
This ForegroundService
has a Handler
that periodically (using postDelayed) executes a block of code to send the location.
This works perfectly fine, when the app is in the foreground and even in the background, but I started to notice a delay when the phone is locked, with the screen off for about 15minutes. I mean, 15 minutes of no user activity and no charger plugged.
This is happening on a Android Q (v10) device. I'm assuming this would also happen on any device running Oreo onwards.
Let's make it clear... My app send the location every 30sec, but when entering what I suppose is the DozeMode or AppStandByMode, it continues sending the location, but every 2 minutes (more or less). If I turn the screen on, or plug-in the charger it inmediately come back to the 30sec pace. That's what makes me thing about the DozeMode or AppStandByMode. Moreover, if I leave the phone untouched, but with the charger plugged in, then this never happens.
As said, I'm pretty sure the DozeMode or AppStandByMode is kicking in, and I know I can whitelist my app to prevent that. But before going further I would like to reproduce this without the need to wait those 15minutes every time I want to test the behavior of my app.
So I "googled" how I can force this and here's what I've found:
For DozeMode
(see source)
adb shell dumpsys battery unplug
adb shell dumpsys deviceidle step deep
And continue to execute the last command until reaching IDLE state.
For AppStandByeMode
(see source)
adb shell dumpsys battery unplug
adb shell am set-inactive packageName true
And query the state with this other command:
adb shell am get-inactive packageName
which I confirm it returns Idle=true
I also even do as this other blog suggest, issuing:
adb shell dumpsys deviceidle force-idle
I though I was not getting in this mode, but now it seems I am and I can not get out of it... See the update
UPDATE
At first I thought I was not entering the DozeMode... Now I can confirm I'm in, but it always triggers inmediately. (no more waiting those 15min)
Whenever I lock the phone and screen goes off, it automatically enters the doze mode and begin spacing the location updates. I plug the charger and then again sends them at 30sec.
I've try:
adb shell dumpsys deviceidle unforce
adb shell dumpsys deviceidle disable
adb shell dumpsys battery reset
and still the same.
Also:
- power-down and power back up the phone
- uninstall the app
- change battery optimization to NOT OPTIMZE inside the app settings
Did I miss a step?
Except for Doze mode, Android 9 extended the concept of AppStandby with App Standby Buckets.
Along with network restrictions, an app that is in a low priority bucket will be affected in the frequency of running Jobs, triggering Alarms, and receiving FCM messages.
You can get your app's current bucket using this command: adb shell am get-standby-bucket your.package.name
You can set the bucket and see how your app behaves using this command: adb shell am set-standby-bucket your.package.name <never/rare>
I wrote an article that summarizes all changes regarding background process limitations over the years: https://rotemmatityahu.medium.com/workmanager-does-it-always-manage-to-work-fd8518655052