With Android 9 battery optimization has been pushed further and apps are classified into standby buckets depending on how much the user has recently interacted with the app (see Android documentation). The system limits the device resources available to each app based on which bucket the app is in.
How can I keep my app in the "working set" bucket, even if the user does not interact with it? (I do not find any permission or similar that allows to override this power management feature.)
More specifically, I have a PeriodicWorkRequest
that must run once every 30 minutes with a flexibility of 10 minutes. However, if I understand the table of imposed power restrictions such a work request could be deferred up to 24 hours, if my app is put into the "rare" bucket. (Under the hood, the Work library uses the job scheduler.)
Further Details on the Scenario
The app is safety critical and not intended for public use but only meaningful to a restricted set of users. However, if anyone else uses this app nothing bad happens, but the app does not serve any purpose for him/her.
More precisely, the app is connected to the central fire alarm station of a specific building. All employees are asked to install the app on their smartphone. If the central fire alarm station of that building detects an event, it sends a push notification (via FCM) to all registered smartphones and the app plays an alarm sound. This implies nothing happens for (hopefully) a long time and the user has no intention to interact with the app in any way. The app itself does not provide any interaction, it only illustrates the current state (which is either a green "OK" sign or a red "ALERT" sign) and waits in the background for the rest of the time.
As the app is safety critical, the fault condition that the app looses the connection to the server must be detected. To this end, the server actually sends messages in the background periodically, i.e. a sequence idle
, idle
, idle
, idle
, alarm
, alarm
, alarm
, alarm
, idle
, idle
, idle
, ... Normally, messages are broadcasted with low FCM-priority every 5 minutes. If the state changes, an additional message is immediately sent with high FCM-priority (cp. bold letters).
The app implements a watchdog using PeriodicWorkRequest
as mentioned in the question above. This watchdog does twofold: Wake up the device and make the device receive all (low priority) FCM-messages that have been postponed and then check if the most recent message is not older than 1.5*5min. If this fails, the app tries to re-register itself with the server and waits if state messages start to come in again. If this fails too, the app presents a warning to the user.
Everything works fine so far. The only problem is the new kind of battery optimization which slows down the watchdog at some point of time. Of course, I could hand out a standing regulation that forces all employees to open the app once in a while and simply look at it, but that is a little bit silly.
I could re-phrase the question above: I totally understand why Android is pushing battery optimization to an edge. There are a lot of (insane) apps that have misused periodic tasks for purposes that should have been solved differently. And the web is still full of "idiotic" programming advises, like checking a specific webpage for modifications every 5secs. However, how am I expected to write safety critical apps that require a watchdog for legitimated purposes if battery optimization becomes more and more an obstacle. Google's thumb of rule "if the user does not use your app, it is obviously unimportant to him/her" does not apply here.