简体   繁体   中英

Kotlin Coroutine Delay In Android Service Not Firing Accurately

I have an Android Service running in a separate process, and it launches a Kotlin Coroutine with a delay in it to perform work after the delay. What I'm noticing is if my target device is running on battery and the screen is turned off, the delay does not expire at the specified time. For example, if I set the delay for 5 minutes (300000 millis), and the device screen is off, and let the device sit for ~4 minutes, when I turn the device screen on to see the delay expire it does not expire at 5 minutes. What I see is that the delay will expire roughly 4 minutes from when I turn the screen back on. The delay does expire correctly if the device screen is kept on, if the phone is connected to power, or if the device is connected to my development machine via remote ADB.

It seems like this has something to do with Doze Mode and the device going into power save mode, which in turn is affecting how delay is functioning, however I can't find any documentation on the topic.

Things I've tried but had no success:

  • Using a Handler instead (just to see what would happen)
  • Moving the Service to the main process
  • Ensuring I maintain a Wifi lock (needed for other functionality)
  • Ensuring the service is a foreground service (needed for other long-running work in the service) and is started

Again this can be observed on devices running Android 7.0+.

Code using a Coroutine:

delayedJob =
   CoroutineScope(serviceScope).launch {
      delay(WAIT_TIME_MILLIS)
      doDelayedWork()
   }

I figured out my issue: there was a bug in my WakeLock logic which resulted in a failure to acquire the lock; the result is the system was Dozing my service, which in turn caused all Threads/Handlers/Coroutines to be dozed as well. Hope this helps someone else seeing this kind of weird behavior (seen on Android 7.0+ devices).

@two1stnamz Thanks for sharing, interesting. I'm trying to keep our private, commercial safety app from dozing on a Samsung watch on Wear OS 3.0/Android 11 and running to all the issues. Need to send data to our server every 30-60 seconds reliably. Thought of coroutines. I've secured a wakelock for the screen to come an stay on for inbound phone calls, but curious if you could share your wakelock code and how to defeated doze? :-) Thanks.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM