Android:如何防止服务在崩溃后重新启动?

10

有没有一种方法可以防止ActivityManager在我的服务“崩溃”后自动重新启动它?在某些情况下,我会在程序退出时强制终止我的服务,但不希望Android继续重新启动它。


1
展示你的服务框架实现。 - coder_For_Life22
它是一个常规服务还是IntentService? - Joachim Isaksson
3个回答

32

这种行为是由您的Service实现中onStartCommand()的返回值所定义的。常量START_NOT_STICKY告诉Android如果进程被“杀死”,不要重新启动服务。换句话说:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    // We don't want this service to continue running if it is explicitly
    // stopped, so return not sticky.
    return START_NOT_STICKY;
}

HTH


1
如果有未完成的意图,它将无法工作。我遇到了这个问题,上述方法不起作用。下面的方法可能是一个更好的选择,但我还没有实现它。尝试了在堆栈溢出中建议的其他方法,但它们尚未成功。 - Brian Reinhold
@BrianReinhold,你的问题似乎在这个问题上有一个特定的转折点,你是否已经发布了自己的问题,解释了你的用例和观察到的问题?我很想深入研究一下。 - devunwired
此时,我已经尝试了我能想到的所有方法来解决我在Stack Overflow和其他地方找到的问题(我猜是Intents,但我不确定)。我尝试过共享首选项、静态全局、START_NON_STICKY以及在create()中使用stopSelf()和onStartCommand()的所有组合,但没有任何东西可以阻止系统重新启动服务。可能独特的是,我在ACTION_SHUTDOWN广播事件中停止服务。在服务的onDestroy()返回之后,服务的onCreate被调用并且主活动重新启动。然后平板电脑关闭。 - Brian Reinhold
另外,如果我在ACTION_SHUTDOWN事件中不调用stopService,则一切正常,但我无法获得所需的行为(当系统关闭电源时,服务的onDestroy从未被调用。这可能是由于在BroadcastReceiver的事件处理程序中调用stopService()导致系统完全损坏。 - Brian Reinhold

6

以下是我想到的解决方案,希望能对其他人有所帮助。即使使用了START_NOT_STICKY,我的应用程序仍然会重新启动。因此,我检查意图是否为null,这意味着服务是由系统重新启动的。

@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
    // Ideally, this method would simply return START_NOT_STICKY and the service wouldn't be
    // restarted automatically. Unfortunately, this seems to not be the case as the log is filled
    // with messages from BluetoothCommunicator and MainService after a crash when this method
    // returns START_NOT_STICKY. The following does seem to work.
    Log.v(LOG_TAG, "onStartCommand()");
    if (intent == null) {
        Log.w(LOG_TAG, "Service was stopped and automatically restarted by the system. Stopping self now.");
        stopSelf();
    }
    return START_STICKY;
}

谢谢!我需要从服务中获取频繁的位置更新并将其发送到服务器。我通过基于通知的前台服务实现了这一点,但是每当应用程序关闭时,它就停止接收位置更新。经过两天的努力,我找到了你的答案并调整了你的代码。在stopSelf()之前,我使用AlarmManager配置了同一服务的重启,延迟10秒后再次启动。这非常有效,现在可以持续从服务中获取位置更新。非常感谢! - ms_27
这个解决方案唯一的问题是onCreate在onStartCommand之前调用,并且除非启动新线程并等待来自onStartCommand方法的信号,否则无法在onCreate中访问意图。但这可能过度杀伤力了,因为更简单的方法是将代码从onCreate移动到onStartCommand中。 - TheRealChx101

1

您的服务可以在SharedPreferences中存储一个值。例如,每次服务启动时,您可以像这样存储一些内容: store("serviceStarted", 1);

当您的服务定期终止(您发送一条消息来执行此操作)时,您将覆盖此值: store("serviceStarted", 0);

下次您的服务重新启动时,它会检测到serviceStarted值为“1” - 这意味着您的服务未正常停止并重新启动。当您检测到此情况时,您的服务可以调用:stopSelf();来取消自身。

了解更多信息: http://developer.android.com/reference/android/app/Service.html#ServiceLifecycle


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接