FirebaseMessagingService Cancels CoroutineScope Before the Job is Finished


In the following code snippet, I'm trying to execute a suspend function MessageHandler.handleMessage() in onMessageReceived(), however the function doesn't finish becuase the ioScope is canceled due to onDestroy() being called.

class FcmService : FirebaseMessagingService() {
    companion object {
        private const val FCM_KEY_MESSAGE = "message"
    }

    private val conversationsRepo: ConversationsRepoImpl by inject()
    private val chatMessagesRepo: ChatMessagesRepoImpl by inject()
    private val ioScope = CoroutineScope(Dispatchers.IO)

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

        val message = message.data[FCM_KEY_MESSAGE] ?: return

        ioScope.launch {
            try {
                MessageHandler.handleMessage(
                    conversationsRepo,
                    chatMessagesRepo,
                    message
                )
            } catch (e: Exception) {
                Log.e("xxx", "Error: ${e.message.toString()}")
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()

        Log.d("xxx", "onDestroy()")
        ioScope.cancel()
    }
}

Here is the log:

onDestroy()
Error: Job was cancelled

How can I make the suspend function finish?

0
Mar 11 at 10:00 PM
User AvatarSam Chen
#android#firebase#firebase-cloud-messaging#android-service#kotlin-coroutines

Accepted Answer

once the message is processed (onMessageReceived finishes) the service is stopped. Since you are starting a new CoroutineScope in there, onMessageReceived is basically returning immediately. Your scope hasn't started yet and when it does onDestroy was called already so the scope was cancelled.

I would suggest deferring the work that needs to be done in the scope to a new WorkManager worker to do what you are trying to do

User Avatartyczj
Mar 12 at 12:15 PM
1