应用程序被终止时,Android后台服务正在重启

时间:2013-03-16 18:21:59

标签: android service background-service

我正在开发一个应用程序,在该应用程序中创建后台服务来收集传感器数据。我从我的活动开始提供服务:

startService(new Intent(this, MyService.class));

我创建了服务,因此如果应用程序被销毁,后台服务仍会继续收集数据。我试过这个,它在一定程度上起作用了。我的问题是,当我终止应用程序时,服务似乎重新启动,因为调用了onCreate()服务和onStart()方法。是否有任何方法可以重新启动服务?

更新

正如下面的答案所示,我在服务中添加了以下方法,但没有运气。

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    return START_NOT_STICKY;
}

7 个答案:

答案 0 :(得分:20)

这取决于onStartCommand中返回的值。

您必须返回START_NOT_STICKY

根据documentation

  

对于已启动的服务,他们可以决定运行另外两种主要操作模式,具体取决于它们从onStartCommand()返回的值:START_STICKY用于根据需要显式启动和停止的服务,而START_NOT_STICKY或START_REDELIVER_INTENT用于在处理发送给它们的任何命令时只应保持运行的服务

简而言之: 如果返回START_STICKY,则只要资源可用,就会重新创建服务。如果您返回START_NOT_STICKY,则必须重新激活发送新意图的服务。

由于所有这些都引发了我的好奇心,我制作了一个示例应用来测试它。你可以找到所有sources here的邮政编码 有一个startService按钮和一个stopService按钮,它可以满足您的需求。 该服务在onStartCommand中返回START_NOT_STICKY。 我在onCreate,onStartCommand和onDestroy上放置了祝酒词。

发生了什么:

  • 如果按开始,则调用onCreate和onStart
  • 如果我按停止,则触发onDestroy
  • 如果我按两次开始,则onCreate被调用一次,onStartCommand被调用两次

所以它表现得像人们期望的那样。

如果我按照你的描述启动服务并杀死应用程序,则onDestroy不会被调用,但onCreate或onStart都不会被调用。

如果我回到应用程序并再按一下, onCreate将被调用,这意味着,正如我之前所写,START_NOT_STICKY会阻止服务自动重启。

我猜您的应用中还有其他内容可以再次启动服务(可能是待处理的意图)。

答案 1 :(得分:4)

应用程序和服务存在于同一进程中,这意味着当应用程序被杀时,您的服务也将被杀死。更改onStartCommand的返回值不会影响此过程。它只是告诉服务,当你告诉它或者它完成了它需要的时候,它要么开始/停止。正如您对原始帖子的评论所述,将其设置为前台进程是有效的,但这实际上只是强迫服务具有高优先级,而不是解决问题。

要更改服务以使其单独销毁并假设它是由于使用onStartCommand而启动的服务而不是绑定服务,请在该服务的清单中指定进程名称。

来自Process and Threads Developer Guide

  

每种组件元素的清单条目 - <activity>, <service>, <receiver>, and <provider> -   支持可以指定的android:process属性   应该运行该组件的过程。你可以设置   这个   属性,以便每个组件在其自己的进程中运行   一些组件共享一个进程   别人不这样做。你也可以设置android:process   不同应用程序的组件在同一个组件中运行   进程 - 提供应用程序共享相同的内容   Linux用户ID,并使用相同的证书进行签名。

     

Android可能决定关闭某个进程   当内存很低而其他人需要时   更直接地为用户提供服务的流程。   应用程序组件在进程中运行   因此被杀害了。一个过程开始了   再次为那些组件再次为他们做的工作。

来自<service> in Manifest File

  

机器人:过程

     

运行服务的进程的名称。   通常,应用程序的所有组件都在默认进程中运行   为应用程序创建。它与应用程序的名称相同   包。元素的process属性可以设置a   所有组件的默认值不同。但组件可以覆盖   默认具有自己的流程属性,允许您传播您的   跨多个流程的应用程序

     

如果分配给此名称   属性以冒号(':')开头,这是一个私有的新进程   应用程序,在需要时创建,服务在其中运行   处理。如果进程名称以小写字符开头,则   服务将在该名称的全局进程中运行,前提是它   有权这样做。这允许组件不同   应用程序共享进程,减少资源使用。

不确定为什么提到这个问题的其他答案被否决了。我过去曾经使用过这种方法,今天,我在一个不同的过程中创建了一个简单的一个Activity应用程序,以确保我没有疯狂。我使用Android设备监视器来杀死应用程序的进程。您可以在ADM中看到两个独立的进程,并且可以看到当应用程序的进程被终止时,服务不会被执行。

答案 2 :(得分:1)

开始不粘不会在kitkat之上工作,而另一个onTaskRemoved在Marshmellow之上不起作用。 可以通过处理一些异常来使用onTaskRemoved。没有那么努力。但试试那个。

答案 3 :(得分:0)

如果您使用的是IntentService,则它有一个

onHandleIntent() 

您应该放置需要执行的代码的方法。它在一个单独的线程(不是运行应用程序的UI线程)中执行,因此您的应用程序不应该影响它。代码完成执行后,线程终止,服务自动停止。

答案 4 :(得分:0)

我知道回答这个问题的时间要晚得多,但可能对其他人有帮助。这真的帮助了我的音乐播放器应用程序。

如果存在可能破坏性或可能影响音乐等用户体验的服务,那么在这种情况下您必须使用通知,并且当服务成功启动时,然后创建通知并使用该功能

startForeground(int Notification_id,Notification);

这将在后台运行您的服务,而无需重新启动并重新调用其方法

https://developer.android.com/reference/android/app/Service.html

答案 5 :(得分:-2)

当内存不足时,在后台运行的服务会自动被杀死。而不是使用startService()来启动服务,而是尝试使用StartForeground()。该服务在前台运行,即使内存不足也不会被杀死。

答案 6 :(得分:-2)

我遇到了同样的问题,并且能够通过在全局流程中运行服务来解决它。您可以通过将以下内容添加到清单标记来执行此操作:

  

过程= “com.myapp.ProcessName”

(弥补名称。)

当我这样做时,我发现当应用程序从列表中删除时,我的服务没有被杀死(并重新启动)。大概这是因为当您将其刷掉时,应用程序进程会被终止,但全局服务进程则不会。

这样做的缺点是您的应用和服务之间的通信现在必须通过IBinder接口;你不能直接从另一个中调用应用程序或服务中的函数,因为它们在不同的进程中运行。