Foreground Coroutine Worker causing android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground()
Asked Answered
L

1

7

Getting the following crash on coroutine worker, the crash is happening on only some Samsung, Vivo and Oppo devices specifically and only on Android 10

Fatal Exception: android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{2dcabaa u0 `app_id_hidden`/androidx.work.impl.foreground.SystemForegroundService}
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2159)
       at android.os.Handler.dispatchMessage(Handler.java:107)
       at android.os.Looper.loop(Looper.java:230)
       at android.app.ActivityThread.main(ActivityThread.java:7752)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:526)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1034)

The doWork function on the worker is implemented as, where the init() function does my job.

override suspend fun doWork(): Result {
    setForeground(createForegroundInfo())
    return init()
}

private fun init() {
    //implementation hidden
}

private fun createForegroundInfo(): ForegroundInfo {
    val notificationId = 1
    return ForegroundInfo(notificationId, createNotification())
}

private fun createNotification(): Notification {
    val context = applicationContext

    val builder = NotificationCompat.Builder(context, ChannelType.NOTIFICATION_CHANNEL_GENERAL)
                .setContentTitle("Message")
                .setSmallIcon(R.drawable.ic_notif_small)
                .setOngoing(true)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        createNotificationChannel(
                    ChannelType.NOTIFICATION_CHANNEL_GENERAL,
                    ChannelType.NOTIFICATION_CHANNEL_GENERAL
        ).also {
            builder.setChannelId(it.id)
        }
    }
    return builder.build()
}

@TargetApi(Build.VERSION_CODES.O)
private fun createNotificationChannel(
         channelId: String,
         name: String
    ): NotificationChannel {
        return NotificationChannel(
                channelId, name, NotificationManager.IMPORTANCE_LOW
        ).also { channel ->
            notificationManager.createNotificationChannel(channel)
    }
}

I am not using any location or microphone or any default foreground service types. It's a plain worker which does some job.

Legend answered 8/1, 2021 at 7:6 Comment(2)
hi, @Akash Amin did you find an answer to this? I'm facing the same issue.Callicrates
There are a few reports in the Android issue tracker, but they are all closed as Won't Fix, e.g. issuetracker.google.com/issues/190412030. They always say it is because something is blocking the main thread too much. In my case I also have reports in crashlytics almost entirely on Samsung devices. If there is a problem in my app code then why does it happen only on Samsung devices? Furthermore I see the crash only once per user, which is also weird. Could be that it happens only when the app is being updated?Suffix
K
2

In the latest Workmanager API, you can use "setExpedited" along with "getForegroundInfo" instead of "setForeground" in your Worker. It will mark your work as starting immediately (meeting the constraints).

Steps :

  • Override the getForegroundInfo method and return the ForegroundInfo.
  • While building the workrequest, use setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) (for more quota policy, checkout the link below)
  • And done.

Note: setExpedited would only work with OneTimeRequest and not with PeriodicWorkRequest

For more info : setExpedited

Kape answered 23/1, 2022 at 6:35 Comment(2)
Important answer this if you are trying to use setExpedited and not overriding the getForegroundInfo method you will receive an error: Java.lang.IllegalStateException: Not implemented at androidx.work.CoroutineWorker.getForegroundInfo. Thank you for the steps.Xenolith
I don't think setExpedited will fix the issue on devices using Android 11 and below unfortunately since as the doc states: "To maintain backwards compatibility for expedited jobs, WorkManager might run a foreground service on platform versions older than Android 12. Foreground services can display a notification to the user."Petrapetracca

© 2022 - 2024 — McMap. All rights reserved.