分析基于Android8.0。
【操作步骤】
播放音乐
音乐切到后台,播放其他音源超过1min
再将音乐切到前台
【结果】
音乐播放异常
【原因】
应用在后台空闲超过1min,系统销毁了服务。
log中包含如下信息:
ActivityManager: Stopping service due to app idle: u0a60 -1m14s699ms com.example.maureen.mytestbindservice/.TestRemoteService
【分析】
以上log来自ActiveServices.stopInBackgroundLocked函数:
而该函数因为应用处于后台空闲而被调用的堆栈信息:
(181101_10:29:01.984)01-01 00:09:19.735 448 533 D ActiveServices: stopInBackgroundLocked
(181101_10:29:01.994)01-01 00:09:19.736 448 533 D ActiveServices: java.lang.Throwable
(181101_10:29:01.995)01-01 00:09:19.736 448 533 D ActiveServices: at com.android.server.am.ActiveServices.stopInBackgroundLocked(ActiveServices.java:621)
(181101_10:29:01.995)01-01 00:09:19.736 448 533 D ActiveServices: at com.android.server.am.ActivityManagerService.doStopUidLocked(ActivityManagerService.java:23605)
(181101_10:29:01.995)01-01 00:09:19.736 448 533 D ActiveServices: at com.android.server.am.ActivityManagerService.idleUids(ActivityManagerService.java:23464)
(181101_10:29:01.995)01-01 00:09:19.736 448 533 D ActiveServices: at com.android.server.am.ActivityManagerService$MainHandler.handleMessage(ActivityManagerService.java:2443)
(181101_10:29:01.995)01-01 00:09:19.736 448 533 D ActiveServices: at android.os.Handler.dispatchMessage(Handler.java:106)
(181101_10:29:01.995)01-01 00:09:19.736 448 533 D ActiveServices: at android.os.Looper.loop(Looper.java:164)
(181101_10:29:01.995)01-01 00:09:19.736 448 533 D ActiveServices: at android.os.HandlerThread.run(HandlerThread.java:65)
(181101_10:29:01.995)01-01 00:09:19.736 448 533 D ActiveServices: at com.android.server.ServiceThread.run(ServiceThread.java:46)
(181101_10:29:01.995)01-01 00:09:19.737 448 533 W ActivityManager: Stopping service due to app idle: u0a59 -1m49s392ms com.example.maureen.mytestbindservice/.TestRemoteService
因为添加了部分log信息,所以与源码的代码行数不对应。其中ActivityManagerService.java的2443行对应的就是:
而IDLE_UIDS_MSG消息来源于AMS.idleUids或AMS.updateOomAdjLocked函数:
updateOomAdjLocked函数:
可以看到都是通过发送延时消息来停止服务的。而这个延时时间BACKGROUND_SETTLE_TIME的值:
ActivityManagerConstants.java
就是60s,即1min。
也就是说在后台超过1min,IDLE_UIDS_MSG就会执行,也就会将服务销毁。
【解决方案】
启动前台服务。
- 调用startForegroundService启动服务
- 在服务的onStartCommand中调用startForeground (5s内调用,否则会导致ANR),并设置Nofitication