0

这需要一些上下文,请与我裸露...


我已将用于评估 NFC 数据的依赖项迁移到新应用程序。每当发现 NFC 标签时,我的应用程序都会生成一个 Activity 来处理该事件。在onCreatethis 的函数中NfcActivity,启动了一个后台服务(我们称之为它MyNfcHelperService)来检索扫描标签上的一些数据:

class NfcActivity : AppCompatActivity() {
    /*...*/
    
    override fun onCreate(savedInstanceState: Bundle?) {
        /*...*/

        val intent = Intent(this, MyNfcHelperService::class.java)
            .putExtra(/*...*/)
        
        startService(intent)
    }
}

此服务生成的作品稍后会被NfcActivity. 过去一切正常,但一旦发布到野外,我们注意到一些崩溃,这会报告Not allowed to start service Intent调用startService(intent)

我很快就看到了这篇相关的帖子,这表明这是由于对后台进程的 RAM 管理进行了一些改进(在 Android 8 中引入)。

根据接受的答案和提出的评论,我研究了JobIntentServices 上的文档并最终得到了类似的设置。我本来希望将MyNfcHelperService所有内容放在一起并将其逻辑移动到MyJobIntentService. 但是里面发生的事情MyNfcHelperService对我来说绝对是一个黑匣子。因此,我将上述服务包装在onHandleWork我的派生对象中JobIntentService,如下所示:

class MyJobIntentService: JobIntentService() {

    companion object {
        private const val JOB_ID = 1000

        fun start(context: Context) {
            val intentPkm = Intent(context, MyNfcHelperService::class.java)
                .putExtra(/*...*/)
            enqueueWork(context, intentPkm)
        }

        private fun enqueueWork(context: Context, intent: Intent) {
            enqueueWork(context, MyJobIntentService::class.java, JOB_ID, intent)
        }
    }

    override fun onHandleWork(intent: Intent) {
        applicationContext.startService(intent)
    }
}

然后我将这个类应用于NfcActivity

class NfcActivity : AppCompatActivity() {
    /*...*/
    
    override fun onCreate(savedInstanceState: Bundle?) {
        /*...*/

        MyJobIntentService.start(applicationContext)
    }
}

到目前为止,代码似乎工作。但是我很犹豫是否将它发布到野外,因为它感觉有点hacky,我不确定这个解决方案是否真的解决了上述问题。毕竟,我知道这个基础设施会根据计划的作业创建后台服务。


那么,我的代码对java.lang.IllegalStateException: Not allowed to start service Intent错误是否稳健,还是我完全走错了路?如果是后者,考虑到我无法访问MyNfcHelperService?

4

1 回答 1

0

在@MD 发表评论后,我改变了使用 WorkManager 的方法。这对于不同的 API 版本应该是最健壮的。我遵循官方文档并得出以下工作人员设置:

class MyNfcHelperServiceWorker(val context: Context, workerParams: WorkerParameters): Worker(context, workerParams) {
    override fun doWork(): Result {
        val intent = Intent(context, MyNfcHelperService::class.java)
                .putExtra(/*...*/)

        context.startService(intent)

        return Result.success()
    }
}

然后我NfcActivity像这样调整了里面的代码:

class NfcActivity : AppCompatActivity() {
    /*...*/
    
    override fun onCreate(savedInstanceState: Bundle?) {
        /*...*/

        OneTimeWorkRequestBuilder<MyNfcHelperServiceWorker>()
            .build()
            .also { helperServiceWorkRequest ->
                WorkManager.getInstance(this)
                    .enqueue(helperServiceWorkRequest)
            }
    }
}

初始测试运行良好。我对解决此问题的原因的理解是,android 现在将安排一个工作请求,该请求仅在允许我的应用程序创建后台进程时才java.lang.IllegalStateException: Not allowed to start service Intent满足启动MyNfcHelperService要求。

也就是说,我仍然有点头疼使用工人来启动服务。这样做真的是多余的,我不确定这可能会导致任何额外的影响。因此,我现在不会接受这个作为答案。

我非常感谢您对此事的任何其他评论和/或答案!

于 2020-07-06T09:59:00.450 回答