START_STICKY 不适用于 Android KitKat [英] START_STICKY does not work on Android KitKat

查看:15
本文介绍了START_STICKY 不适用于 Android KitKat的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的一个应用程序有一个后台服务,它使用 onStartCommandSTART_STICKY 返回代码在系统杀死它时自动重新启动.似乎这不再适用于 Android KitKat.有什么解决办法吗?我应该在 Kitkat 上做一些不同的事情来保持服务运行吗?

One of my apps has a backgrouod service that uses the START_STICKY return code from onStartCommand to automatically restart when the system kills it. It seems that this is no longer working on Android KitKat. Is there any solution for this ? Should I be doing something different on Kitkat to keep the service running ?

注意:在 Android-Devlopers 组上有一个类似的讨论,关于从最近的应用程序列表中滑动应用程序的行为.这两个问题可能相关吗?https://groups.google.com/forum/#!topic/android-developers/H-DSQ4-tiac

Note: There is a similar discussion on the Android-Devlopers group about swiping the app from the recent apps list behaves. Could this two issues be related ? https://groups.google.com/forum/#!topic/android-developers/H-DSQ4-tiac

看到 Android 问题跟踪器上存在未解决的错误:

Saw that there are open bugs on Android issue tracker:

https://code.google.com/p/android/问题/详细信息?id=63793https://code.google.com/p/android/issues/detail?id=63618

Edit2:即使服务使用 startForeground 在单独的进程中运行并且在 AndroidManifest.xml 中使用标志 android:stopWithTask="false" 运行,也会发生同样的情况文件...

The same happens even if service is running using startForeground, in a separate process and with the flag android:stopWithTask="false" in the AndroidManifest.xml file...

Edit3:Android 问题跟踪器上的更多相关错误:

More related bugs on Android issue tracker:

https://code.google.com/p/android/问题/详细信息?id=62091https://code.google.com/p/android/issues/detail?id=53313https://code.google.com/p/android/issues/detail?id=104308

是否有某种解决方法来获得以前的行为?

Is there some sort of workaround to get the previous behavior ?

推荐答案

这不是一个 100% 有效的解决方案,但它是最好的,因为它几乎完全消除了问题.到目前为止,我将这个解决方案与覆盖 onTaskRemoved(见这个答案)和一个保持-活动通知(请参阅此答案).非常感谢其他答案!

This is not a 100% working solution but it's the best so far as it almost completely eliminates the problem. So far I integrated this solution along with overriding onTaskRemoved (See this answer) and a keep-alive notification (See this answer). Additional answers are very appreciated !

经过进一步调查,该错误似乎已存在于 Jelly Bean 中,并且似乎有解决方案(至少在我的情况下似乎可行.如果需要,将继续测试并更新答案).

After further investigation, it seems that the bug already exists in Jelly Bean and looks like there is a solution for that (At least in my case that seems to work. will keep on testing and update the answer if required).

据我观察,这只发生在接收由 AlarmManager 设置的广播的服务中.

From what I observed this only happens with services that receive broadcasts set by AlarmManager.

要重现错误,请执行以下步骤:

To reproduce the bug follow these steps:

  1. 启动应用
  2. 从应用程序内将服务作为前台服务启动(为此使用 startForeground)
  3. 从最近使用的应用"列表中滑动应用
  4. 发送由服务处理的广播
  5. 服务被终止!

使用 adb shell dumpsys >C:dumpsys.txt 您可以监控不同步骤之间的服务状态.(在 dumpsys 输出中查找 Process LRU list)在第 2 步和第 3 步中,您将看到如下内容:

Using adb shell dumpsys >C:dumpsys.txt you can monitor the state of the service between the different steps. (look for Process LRU list in the dumpsys output) on steps 2 and 3 you will see something like this:

Proc # 2: prcp  F/S/IF trm: 0 11073:<your process name>/u0a102 (fg-service)

具体来说,注意 F/S/IF(fg-service) 表示该服务作为前台服务运行(有关如何分析的更多详细信息此链接中的 dumpsys:https://stackoverflow.com/a/14293528/624109).

Specifically, notice the F/S/IF and the (fg-service) that indicate the service is running as a foreground service (more details on how to analyze the dumpsys at this link: https://stackoverflow.com/a/14293528/624109).

在第 4 步之后,您将不会在 Process LRU 列表中看到您的服务.相反,您可以查看设备 logcat,您将看到以下内容:

After step 4 you will not see your service in the Process LRU list. Instead, you can look at the device logcat and you will see the following:

I/ActivityManager(449): Killing 11073:<your process name>/u0a102 (adj 0): remove task

似乎导致这种行为的原因是接收到的广播将服务从其前台状态中取出,然后被终止.

What seems to be causing that behavior is the fact that the received broadcast takes the service out of its foreground state and then killed.

为避免这种情况,您可以在为 AlarmManager 创建 PendingIntent 时使用这个简单解决方案(来源:https://code.google.com/p/android/issues/detail?id=53313#c7)

To avoid that, you can use this simple solution when creating your PendingIntent for the AlarmManager (Source: https://code.google.com/p/android/issues/detail?id=53313#c7)

AlarmManager am = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent("YOUR_ACTION_NAME");
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1, intent, 0);

注意以下步骤:

  1. 针对意图调用 addFlags 并使用 FLAG_RECEIVER_FOREGROUND
  2. 在 PendingIntent.getBroadcast 中使用非零请求代码

如果您忽略其中任何一个步骤,它将无法工作.

If you leave any of those steps out it will not work.

注意FLAG_RECEIVER_FOREGROUND 是在 API 16 (Jelly Bean) 上添加的,所以这是错误第一次出现的时间......

Note that the FLAG_RECEIVER_FOREGROUND was added on API 16 (Jelly Bean) so it makes sense that this is when the bug first appeared...

很可能 KitKat 在杀死进程方面更具侵略性,这就是 KitKat 强调它的原因,但看起来这已经与 Jelly Bean 相关.

Most likely that KitKat is just more aggressive when it comes to killing processes and this is why it was emphasized with KitKat, but looks like this was already relevant on Jelly Bean.

注意 2:请注意问题中有关服务配置的详细信息 - 在单独的进程中作为前台服务运行,并且清单中的 endWithTask 设置为 false.

Note 2: Notice the details in the question about the service configuration - running in a separate process, as a foreground service, with endWithTask set to false in the manifest.

注意 3:当应用收到 android.appwidget.action.APPWIDGET_CONFIGURE 消息并显示新小部件的配置活动时,会发生同样的事情(用创建新小部件替换上面的第 4 步).我发现只有当小部件提供程序(处理 android.appwidget.action.APPWIDGET_UPDATE 的接收器)设置为在与活动进程不同的进程上运行时才会发生.更改后,配置活动和小部件提供程序都在同一进程中,这不再发生.

Note 3: The same thing happens when the app receives the android.appwidget.action.APPWIDGET_CONFIGURE message and shows a configuration activity for a new widget (Replace step 4 above with creating a new widget). I found that only happens when the widget provider (the receiver that handles android.appwidget.action.APPWIDGET_UPDATE) is set to run on a different process than the activity process. After changing that so both the configuration activity and the widget provider are on the same process, this no longer happens.

这篇关于START_STICKY 不适用于 Android KitKat的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆