Android background service calls onDestroy() before coroutine finishes work

Viewed 47

I have background service in Android to handle Google Firebase Push Notifications:

class MyFirebaseMessagingService : FirebaseMessagingService() {

    @Inject
    lateinit var repository: Repository

    @Inject
    lateinit var coroutineDispatchers: CoroutineDispatchers

    private val serviceJob = Job()
    private lateinit var serviceScope: CoroutineScope

    override fun onCreate() {
        super.onCreate()
        AndroidInjection.inject(this)
        serviceScope = CoroutineScope(coroutineDispatchers.default + serviceJob)
    }

    override fun onNewToken(token: String) {
        // Not important
    }

    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        super.onMessageReceived(remoteMessage)
   
        serviceScope.launch {
            try{
                Timber.e(repository.someSuspendMethod())
            } catch (e: Exception){
                Timber.e(e)
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        serviceJob.cancel()
    }
}

My problem is that job is getting cancelled before finishing, because onDestroy() is called. Any idea why Service is killing itself before job is done?

1 Answers

I changed your class to this

class MyFirebaseMessagingService : FirebaseMessagingService(), LifecycleOwner {

private val mDispatcher = ServiceLifecycleDispatcher(this)

@Inject
lateinit var repository: Repository


override fun onCreate() {
    mDispatcher.onServicePreSuperOnCreate()
    super.onCreate()
}


override fun getLifecycle() = mDispatcher.lifecycle

override fun onNewToken(token: String) {
    // Not important
}

override fun onMessageReceived(remoteMessage: RemoteMessage) {
    super.onMessageReceived(remoteMessage)

    lifecycleScope.launch {
        try{
            Timber.e(repository.someSuspendMethod())
        } catch (e: Exception){
            Timber.e(e)
        }
    }
}

override fun onDestroy() {
    mDispatcher.onServicePreSuperOnDestroy()
    super.onDestroy()
}

}

I use this way to save notification messages in the database

Related