1. 程式人生 > >startService啟動服務,應用置於後臺超過1min,服務被銷燬

startService啟動服務,應用置於後臺超過1min,服務被銷燬

分析基於Android8.0。

【操作步驟】

  1. 播放音樂
  2. 音樂切到後臺,播放其他音源超過1min
  3. 再將音樂切到前臺

【結果】

   音樂播放異常

【原因】

   應用在後臺空閒超過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