我有一个后台服务,当内存不足时,它有时会被操作系统杀死。
开发指南简单地说“如果您的服务已启动,那么您必须将其设计为优雅地处理系统重新启动。如果系统终止您的服务,它会在资源再次可用时立即重新启动”。
在一个(相关)问题上,当服务被操作系统杀死时,在服务中启动的主动运行AsyncTask会发生什么,即没有service.onDestroy被调用?它是否继续运行或与服务一起静静地撕开?
在较新版本下,服务将触发以下事件:
onCreate()
其次是...
int onStartCommand(Intent intent, int flags, int startid)
我知道在上面的评论中你提到使用它,但值得重复:不要使用旧的“onStart()”事件。 onStartCommand是一种新的做事方式。
onCreate()可用于创建任何对象等,但在onStartCommand()中执行服务的实际代码。
完成onStartCommand()后,您应该返回一个结果。使用“START_STICKY”告诉操作系统,如果需要将其终止,它可以重新启动。使用“START_NOT_STICKY”告诉操作系统在内存再次可用后不要再尝试重新启动它。这意味着您的应用程序需要再次手动启动该服务。还有其他选项 - 请查看API文档。
检查这些标志将允许您查看服务启动的原因 - 如果您自己的应用程序已启动它,或者操作系统启动它以重新启动它。您需要定期存储任何重要变量的状态,以便在操作系统重新启动时可以检索它们 - 您可以使用SharedPreferences私有存储来存储这些变量。绝对存储在onDestroy事件中的任何事件,但不要指望被调用。
此外,建议您将startID字段存储在变量中,并在服务运行完成后将其与stopSelfResult(startId)一起使用。
请记住,如果您的服务被操作系统杀死,您可能无法存储任何变量。您需要能够查看操作系统重新启动时您所处的状态是否正常,如果不是重置所有内容或优雅地死亡。
至于调试,您是否考虑过编写另一个应用程序,它只会在Activity中吸取内存以强制内存不足?顶级活动应该优先考虑内存并强制服务死亡。
在服务中启动的其他线程仍然是同一应用程序进程的一部分,因此它们将与服务(以及应用程序的其余部分)一起被终止。您可以通过在线程内添加常规日志语句然后终止服务来验证这一点。 。
其他可能对您有用的方法是检查您的服务是否已在应用程序内部运行。这是一个功能:
// Determine if one of my services is currently running
public static boolean isMyServiceRunning(Context context, String servicename) {
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (servicename.equals(service.service.getClassName())) {
return true;
}
}
return false;
}
如果它是本地服务(默认),而不是远程服务,则它与您的应用程序在同一进程中运行。这意味着您可以通过杀死应用程序的进程来模拟杀死它。您可以使用ddms,例如在eclipse或命令行中,甚至从手机(设置 - >应用程序)中执行此操作。
kotlin版本的Tony Maro的答案:
@Suppress("DEPRECATION")
fun <T> Context.isServiceRunning(service: Class<T>): Boolean {
return (getSystemService(ACTIVITY_SERVICE) as ActivityManager)
.getRunningServices(Integer.MAX_VALUE)
.any { it.service.className == service.name }
}