【问题标题】:How to force a service restart?如何强制重启服务?
【发布时间】:2011-11-07 14:43:56
【问题描述】:

我有一个后台服务,它有时会在内存不足时被操作系统杀死。

  1. 如何模拟这种行为以便调试它?

开发指南简单地说“如果您的服务已启动,那么您必须将其设计为优雅地处理系统重新启动。如果系统终止您的服务,它会在资源再次可用时重新启动它”。

  1. 从被杀死到完成重新启动的调用顺序是什么?

在一个侧面(相关)问题上,当服务被操作系统杀死时,服务中启动的主动运行的 AsyncTask 会发生什么,即没有调用 service.onDestroy?它是继续运行还是与服务一起默默地被撕掉?

【问题讨论】:

    标签: android service restart kill-process low-memory


    【解决方案1】:

    Tony Maro 的回答的 Kotlin 版本:

    @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 }
    }
    

    【讨论】:

      【解决方案2】:

      在较新的版本下,服务将触发以下事件:

      onCreate()
      

      接着……

      int onStartCommand(Intent intent, int flags, int startid)
      

      我知道您在上面提到的 cmets 中提到了使用它,但值得重复:不要使用旧的“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 中的终止(如 yjw 所述)会给我重新启动行为。并感谢您的详尽解释。
      • 关于 DDMS 的好提示,解释上没有问题。碰巧我在编写条形码扫描应用程序时遇到了几乎相同的问题,该应用程序将所有工作作为服务完成,因此不需要打开屏幕。
      【解决方案3】:

      如果它是本地服务(默认),而不是远程服务,那么它与您的应用在同一进程中运行。这意味着您可以通过杀死应用程序的进程来模拟杀死它。您可以使用 ddms 来执行此操作,例如在 eclipse 中或从命令行,甚至从您的手机(设置 -> 应用程序)。

      【讨论】:

      • 我可以杀戮,但没有与之相关的重新启动。
      • 检查您从服务的 onStartCommand 返回的值。我想这就是你想要的:developer.android.com/reference/android/app/…
      • 是的,这就是我正在使用的。我的主要问题是我不知道如何模拟 Android 杀死-重启-服务行为。
      • 有点晚了,但您仍然面临问题吗?我编写了一个简单的服务,我只登录 onCreate、onStartCommand、onDestroy,并使用标志 START_STICKY,我注意到如果我使用 DDMS 终止进程,我的服务实际上是重新创建的(在 onStartCommand 中使用 Intent = null,如文档所示)。如果我使用设置 -> 应用程序,它不起作用
      猜你喜欢
      • 1970-01-01
      • 2013-06-06
      • 1970-01-01
      • 2014-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-01
      • 1970-01-01
      相关资源
      最近更新 更多