应用程序被杀死时Android后台服务正在重新启动
Posted
技术标签:
【中文标题】应用程序被杀死时Android后台服务正在重新启动【英文标题】:Android Background Service is restarting when application is killed 【发布时间】:2016-10-22 05:19:13 【问题描述】:我正在开发一个应用程序,其中创建了一个后台服务来收集传感器数据。我从我的活动开始服务:
startService(new Intent(this, MyService.class));
我创建了服务,因此如果应用程序被销毁,后台服务仍会继续收集数据。我试过这个,它在一定程度上奏效了。我的问题是,当我终止应用程序时,服务似乎重新启动,因为调用了 onCreate()
服务和 onStart()
方法。请问有什么方法可以不重启服务吗?
更新:
正如下面的答案所建议的,我在服务中添加了以下方法,但没有成功。
@Override
public int onStartCommand(Intent intent, int flags, int startId)
return START_NOT_STICKY;
【问题讨论】:
这也发生在我身上。而且我也不做任何绑定 你没有提到它,所以:你有没有尝试在 androidManifest 中为你的服务指定一个单独的全局进程? 你有什么解决办法吗?如果有请指导我 我最终使用了前台服务。这种类型的服务被认为是用户主动了解的进程,因此系统不会将其视为在内存不足时杀死的候选进程。为了确保用户知道正在运行的进程,它必须提供一个只有在服务停止时才能解除的通知。 【参考方案1】:这取决于 onStartCommand 中返回的值。
您必须返回 START_NOT_STICKY
根据documentation:
对于已启动的服务,它们可以决定运行另外两种主要的操作模式,具体取决于它们从 onStartCommand() 返回的值:START_STICKY 用于根据需要显式启动和停止的服务,而 START_NOT_STICKY 或START_REDELIVER_INTENT 用于只应在处理发送给它们的任何命令时保持运行的服务
简而言之: 如果您返回 START_STICKY,则只要资源可用,就会重新创建服务。如果您返回 START_NOT_STICKY,则必须重新激活发送新意图的服务。
由于所有这些都引发了我的好奇心,我制作了一个示例应用程序来测试它。您可以找到包含所有 sources here 的 zip 有一个 startService 按钮和一个 stopService 按钮可以执行您对它们的期望。 该服务在 onStartCommand 中返回 START_NOT_STICKY。 我在 onCreate、onStartCommand 和 onDestroy 中放置了 toast。
这里会发生什么:
如果我按下开始,就会调用 onCreate 和 onStart 如果我按下停止键,就会触发 onDestroy 如果我按 start 两次,onCreate 被调用一次,onStartCommand 被调用两次所以它的行为符合人们的预期。
如果我按照您的描述启动服务并终止应用程序,则不会调用 onDestroy,但不会调用 onCreate 或 onStart。
如果我回到应用程序并再次按启动,onCreate 会被调用,这意味着,正如我之前写的,START_NOT_STICKY 会阻止服务自动重启。
我猜你的应用中有其他东西会再次启动服务(可能是待处理的意图)。
【讨论】:
如何“杀死”应用程序?你怎么知道 onCreate() 和 onStart() 被一遍又一遍地调用了? 我通过在最近的应用程序托盘中刷掉应用程序来终止应用程序(我有一个在 Android 4.1.1 上运行的 Galaxy Nexus)。我知道onCreate()
和onStart()
被再次调用,因为我在这两种方法开始时显示了一个 toast 通知
您是否将活动绑定到服务?
当用户按下活动中的按钮时,我会停止服务。我的问题是:即使应用程序被杀死,我如何才能保持服务平稳运行,而无需重新启动?
感谢您的申请。当我终止您发送给我的应用程序时,尽管没有调用 onDestroy()
,但该服务不会继续运行并结束。我可以从我的任务管理器中检查这一点。当我将服务更改为START_STICKY
并终止应用程序时,服务会重新启动。我想我必须忍受它。【参考方案2】:
应用程序和服务存在于同一个进程中,这意味着当应用程序被终止时,您的服务也会被终止。更改 onStartCommand 的返回值不会影响此过程。它只是告诉服务在您告诉它时启动/停止,或者在它完成所需的操作时启动/停止。正如您对原始帖子的评论中所述,将其设置为前台进程是可行的,但这实际上只是强制服务具有高优先级,而不是解决问题。
要更改服务以使其被单独终止并假设它是已启动的服务而不是由于使用 onStartCommand 而绑定的服务,请在该服务的清单中指定进程名称。
来自Process and Threads Developer Guide:
每种组件元素的清单条目—
<activity>, <service>, <receiver>, and <provider>
— 支持一个 android:process 属性,可以指定一个 该组件应在其中运行的进程。你可以设置 这 属性,以便每个组件在自己的进程中运行左右 一些组件共享一个进程,而 其他人没有。您还可以设置 android:process 以便 不同应用程序的组件运行在同一个 进程——前提是应用程序共享相同的 Linux 用户 ID 并使用相同的证书进行签名。Android 可能会决定关闭某个进程 点,当内存不足且其他需要时 更直接地为用户服务的进程。 在进程中运行的应用程序组件 杀死因此被摧毁。一个进程被启动 当他们有工作要做时,再次为这些组件重新工作。
来自<service>
in Manifest File:
机器人:进程
要运行服务的进程的名称。 通常,应用程序的所有组件都在默认进程中运行 为应用程序创建。它与应用程序具有相同的名称 包裹。元素的 process 属性可以设置一个 所有组件的默认值不同。但是组件可以覆盖 默认具有自己的进程属性,允许您传播您的 跨多个进程的应用程序。
如果分配给此的名称 属性以冒号 (':') 开头,这是一个新进程,对 应用程序,在需要时创建,服务在其中运行 过程。如果进程名称以小写字符开头,则 服务将在该名称的全局进程中运行,前提是它 有权这样做。这允许不同的组件 应用程序共享进程,减少资源使用。
不知道为什么提到这一点的其他答案被否决。我过去使用过这种方法,而今天,我创建了一个简单的 Activity 应用程序,该应用程序在不同的进程上提供了一个服务,以确保我没有发疯。我使用 Android Device Monitor 来终止应用程序的进程。您可以在 ADM 中看到这两个单独的进程,并且可以看到当应用程序的进程被杀死时,服务的进程不会。
【讨论】:
【参考方案3】:Start not sticky 在 kitkat 上不起作用,而另一个 onTaskRemoved 在 Marshmellow 上不起作用。 onTaskRemoved 可以通过处理一些异常来使用。没有工作。但是试试那个。
【讨论】:
【参考方案4】:如果你使用 IntentService,它有一个
onHandleIntent()
你应该放置需要执行的代码的方法。它在一个单独的线程中执行(不是您的应用程序运行的 UI 线程),因此您的应用程序不应影响它。代码执行完毕后,线程终止,服务自动停止。
【讨论】:
我认为他指的不是 IntentService(具有 onHandleINtent 方法),而是一个普通的(Service)。 对不起,我是新手。是的,我指的是“普通服务”【参考方案5】:我遇到了同样的问题,并且能够通过使服务在全局进程中运行来解决它。您可以通过将以下内容添加到清单标记来做到这一点:
process="com.myapp.ProcessName"
(随便起个名字。)
当我这样做时,我发现当应用程序从列表中滑出时,我的服务没有被终止(并重新启动)。这大概是因为当你刷掉它时应用程序进程被杀死,但全局服务进程没有。
这样做的缺点是你的应用程序和服务之间的通信现在必须通过 IBinder 接口;您不能直接从另一个调用应用程序或服务中的函数,因为它们在不同的进程中运行。
【讨论】:
这似乎对我不起作用,至少在 Android 5.1.1 中不起作用【参考方案6】:我知道回答这个问题已经很晚了,但它可能对其他人有所帮助。这对我的音乐播放器应用程序很有帮助。
如果有音乐之类的服务可能会破坏或影响用户体验,那么在这种情况下你必须使用通知,当服务启动成功时,然后创建通知并使用该功能
startForeground(int Notification_id,Notification);
这将在后台运行您的服务,而无需重新启动和重新调用其方法
https://developer.android.com/reference/android/app/Service.html
【讨论】:
以上是关于应用程序被杀死时Android后台服务正在重新启动的主要内容,如果未能解决你的问题,请参考以下文章
android (Service & PhoneStateListener) - 当应用程序被任务管理器、杀手或内存不足杀死时,服务确实重新启动但不工作
怎么让 Android 程序一直后台运行,像 QQ 一样不被杀死
为啥我在 Android 中杀死我的应用程序时服务会重新启动?