androidkotlinbroadcastreceivercoroutine

Run Coroutine functions on broadcast receiver


Im making an Alarm app, and using AlarmManager to set alarms. Im saving every alarm using Room after running the setAlarm on the AlarmManager, so I can later restore them if the phone gets turned off and o .

Im running a BroadcastReceiver after the device gets booted using the guide from Android Developer site: https://developer.android.com/training/scheduling/alarms#boot

And my idea is to get the alarms from Room on the onReceive method But Room uses a suspend fun to get the alarms, but I cant run it on the onReceive since BroadcastReceiver doesnt have a lifecycle

How could I achieve a similar result?


Solution

  • This section in the BroadcastReceiver documentation gives an example of how to do this.

    You could clean it up a bit with an extension function:

    fun BroadcastReceiver.goAsync(
        context: CoroutineContext = EmptyCoroutineContext,
        block: suspend CoroutineScope.() -> Unit
    ) {
        val pendingResult = goAsync()
        @OptIn(DelicateCoroutinesApi::class) // Must run globally; there's no teardown callback.
        GlobalScope.launch(context) {
            try {
                block()
            } finally {
                pendingResult.finish()
            }
        }
    }
    

    Then in your receiver, you can use it like below. The code in the goAsync block is a coroutine. Remember that you should not use Dispatchers.Main in this coroutine and it must complete within 10 seconds.

    override fun onReceive(context: Context, intent: Intent) = goAsync {
        val repo = MyRepository.getInstance(context)
        val alarms = repo.getAlarms() // a suspend function
        // do stuff
    }