我正在开发一个应用程序,在该应用程序中创建后台服务来收集传感器数据。我从我的活动开始提供服务:
startService(new Intent(this, MyService.class));
我创建了服务,因此如果应用程序被销毁,后台服务仍会继续收集数据。我试过这个,它在一定程度上起作用了。我的问题是,当我终止应用程序时,服务似乎重新启动,因为调用了onCreate()
服务和onStart()
方法。是否有任何方法可以重新启动服务?
更新
正如下面的答案所示,我在服务中添加了以下方法,但没有运气。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
答案 0 :(得分:20)
这取决于onStartCommand中返回的值。
您必须返回START_NOT_STICKY
对于已启动的服务,他们可以决定运行另外两种主要操作模式,具体取决于它们从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上放置了祝酒词。
发生了什么:
所以它表现得像人们期望的那样。
如果我按照你的描述启动服务并杀死应用程序,则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可能决定关闭某个进程 当内存很低而其他人需要时 更直接地为用户提供服务的流程。 应用程序组件在进程中运行 因此被杀害了。一个过程开始了 再次为那些组件再次为他们做的工作。
机器人:过程
运行服务的进程的名称。 通常,应用程序的所有组件都在默认进程中运行 为应用程序创建。它与应用程序的名称相同 包。元素的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接口;你不能直接从另一个中调用应用程序或服务中的函数,因为它们在不同的进程中运行。