START_STICKY在Android KitKat上不起作用 [英] START_STICKY does not work on Android KitKat

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

问题描述

我的一个应用程序提供了一个背景图服务,该服务使用系统从onStartCommand退回START_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 = 63793 https://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 = 62091 https://code.google.com/p/android/issues/detail ?id = 53313 https://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. 服务被终止!
  1. Start the app
  2. start the service as a foreground service (use startForeground for that) from within the app
  3. Swipe the app from "Recent Apps" list
  4. Send a broadcast that is handled by the service
  5. The service is killed !

使用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 list中看到您的服务. 相反,您可以查看设备的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时使用此简单解决方案(来源:

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),因此这是该bug首次出现的时间...

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天全站免登陆