startService啟動服務,應用置於後臺超過1min,服務被銷燬
阿新 • • 發佈:2018-12-18
分析基於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