Android JobIntentService 作为另一个服务的包装器

Posted

技术标签:

【中文标题】Android JobIntentService 作为另一个服务的包装器【英文标题】:Android JobIntentService as wrapper on another service 【发布时间】:2020-10-23 05:14:48 【问题描述】:

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


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

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

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

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

我很快遇到了this related post,这表明这是由于对后台进程的 RAM 管理进行了一些改进(在 android 8 中引入)。

根据接受的答案和提出的 cmets,我研究了 docs on JobIntentServices 并最终得到了类似的设置。我希望将MyNfcHelperService 全部删除,并将其逻辑移至MyJobIntentService但是MyNfcHelperService 内部发生的事情对我来说绝对是一个黑箱。 因此,我将上述服务包装在派生的JobIntentServiceonHandleWork 中,如下所示:

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 的内容,任何人都可以提出替代方法吗?

【问题讨论】:

为什么选择 Jobintentservice?使用工作管理器 @MD 很有趣,Work Manager 似乎也在后台使用 JobScheduler for API 23+。所以我想我的问题仍然存在,我可以使用这种方法,同时保持MyNfcHelperService 吗? 我猜 WorkManager 现在更稳定了。您的方法是正确的,但它不适用于某些制造商设备,例如我在 Honor(Huwai)设备中看到这种类型的崩溃 好的,谢谢。随着新见解的出现,我会对其进行调查并更新我的帖子。 【参考方案1】:

@MD 发表评论后,我改变了使用 WorkManager 的方法。这对于不同的 API 版本应该是最健壮的。我跟着official docs 到达了以下工人设置:

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)
            
    

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

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

我真的很感激任何关于此事的其他 cmets 和/或答案!

【讨论】:

以上是关于Android JobIntentService 作为另一个服务的包装器的主要内容,如果未能解决你的问题,请参考以下文章

我们如何在 Scala 中使用 android JobIntentService?

Android JobIntentService 作为另一个服务的包装器

Activity 和 JobIntentService 生命周期

JobIntentService 不适用于 Oreo 以下的 API (API <= 26)

Proguard:JobIntentService IllegalArgumentException启用模糊处理

【原创】JobIntentService使用