前台协程工作器导致android.app.RemoteServiceException:Context.startForegroundService()没有随后调用Service.startForeground()

7
在协程工作线程上出现以下崩溃,此崩溃只会在某些三星、Vivo和Oppo设备上发生,具体而言是在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)

在worker上实现了doWork函数,其中init()函数执行我的任务。
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)
    }
}

我没有使用任何位置或麦克风或任何默认的前台服务类型,这是一个简单的工作程序,它执行一些任务。


嗨,@Akash Amin,你找到答案了吗?我也遇到了同样的问题。 - stallianz
Android问题跟踪器中有一些报告,但它们都被关闭为“不会修复”,例如https://issuetracker.google.com/issues/190412030。它们总是说因为某些东西阻塞了主线程太多。在我的情况下,我也在Crashlytics中看到了报告,几乎全部是在三星设备上。如果我的应用程序代码有问题,那么为什么只会在三星设备上发生?此外,我只看到每个用户的崩溃一次,这也很奇怪。可能只有在应用程序更新时才会发生? - Branislav Kuliha
1个回答

1
在最新的Workmanager API中,您可以在Worker中使用“setExpedited”和“getForegroundInfo”代替“setForeground”。它会将您的工作标记为立即启动(满足约束条件)。
步骤:
1. 重写getForegroundInfo方法并返回ForegroundInfo。 2. 在构建workrequest时,使用setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)(有关更多配额策略,请查看下面的链接)。 3. 完成。
注意:setExpedited仅适用于OneTimeRequest,而不适用于PeriodicWorkRequest。
更多信息请参见:setExpedited

如果您尝试使用setExpedited而不是覆盖getForegroundInfo方法,则会收到错误消息:Java.lang.IllegalStateException: Not implemented at androidx.work.CoroutineWorker.getForegroundInfo。感谢您提供的步骤。 - Hmerman6006
我不认为 setExpedited 会解决在使用安卓11及以下版本的设备上出现的问题,因为文档中指出:“为了保持对加急作业的向后兼容性,WorkManager 可能在早于 Android 12 的平台版本上运行前台服务。前台服务可以向用户显示通知。” - SVP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接