Android JobIntentService 作为另一个服务的包装器
Posted
技术标签:
【中文标题】Android JobIntentService 作为另一个服务的包装器【英文标题】:Android JobIntentService as wrapper on another service 【发布时间】:2020-10-23 05:14:48 【问题描述】:这需要一些上下文,请与我裸露...
我已将用于评估 NFC 数据的依赖项迁移到新应用程序。每当发现 NFC 标签时,我的应用程序都会生成一个 Activity 来处理该事件。在这个NfcActivity
的onCreate
函数中,启动了一个后台服务(我们称之为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
内部发生的事情对我来说绝对是一个黑箱。 因此,我将上述服务包装在派生的JobIntentService
的onHandleWork
中,如下所示:
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)