詳解:android O 對Service的限制【Background Execution Limits】

目錄

  1. 哪些APP內的Service後臺運行會被系統限制?
  2. android O【即android8.0】對Service增加了哪些限制?
  3. 疑惑:
    1. 存在通知欄的App,是否屬於前臺APP?
    2. 如何判斷App處在後臺?
    3. 如何判斷APP處在空閒期?
    4. 如何做到:APP進入空閒期時,不讓系統立即回收Service, 啓動Service不Crash。
  4. 官方文檔
  5. 官方文檔摘抄重要部分



1. 哪些app的Service後臺運行會被系統限制?

首先並不是所有app的Service後臺運行都會被系統限制。

滿足以下兩個特點的APP,內的Service,可能會受到系統限制

  • 必須在android 8.0以上的設備上

  • APP的 targetSdkVersion 配置大於等於26

    APP的targetSdkVersion的配置在app/build.gradle文件中

        android {
            defaultConfig {
                targetSdkVersion 26 //此配置
            }
            ...
        }
    



2. android O 對Service增加了哪些限制?

當APP處於空閒期時,將會有如下兩個限制:

  • 主動調用 Context.startService() 將引發crash。崩潰日誌,如下:
java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.compat.test/com.test.Service4 }: app is in background uid UidRecord{a0d4e51 u0a84 CEM  bg:+1m2s21ms idle procs:1 seq(0,0,0)}
        at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1505)
        at android.app.ContextImpl.startService(ContextImpl.java:1461)
        at android.content.ContextWrapper.startService(ContextWrapper.java:644)
        at com.test.MainActivityV2$8.run(MainActivityV2.java:153)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6541)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)



  • 對於普通的Service,App進入空閒期後,系統將會立即停止並回收該服務

被回收的現象,就和我們自己主動調用Context.stopService()一樣。
Service將會被執行:onDestory()生命週期方法。


注意:

這裏千萬要注意,理解:app處在空閒期,是什麼意思?

空閒期,在,官方文檔的英文描述爲:idle。

app處在後臺,並不等於處在空閒期;

app處在後臺,並不等於處在空閒期;

app處在後臺,並不等於處在空閒期;

APP處於後臺,是進入空閒期的必要條件,但不是充分條件。

例如:

​ Model PixelXL手機, android8.0.0系統:在APP進入後臺狀態,並保持處於後臺狀態1分鐘後,才進入空閒期。

​ APP從開始處於後臺,到,正式進入空閒期的 這1分鐘期間,app可以隨意startService是不會拋出異常的。App內的Service也不會被系統主動回收。

​ 在這1分鐘期間,用戶如果打開APP,將APP置爲前臺,那麼下次進入後臺後需要重新計時,重新進入後臺保持1分鐘纔會進入空閒期。



3. 我們心中可能會產生5個疑問

  1. APP存在常駐通知欄時,是否屬於前臺APP?

  2. APP什麼情況下會進入空閒期?

  3. 如何判斷App處在後臺?

  4. APP進入空閒期時,如何防止Service不被Stop

  5. APP處在空閒期時,如何啓動Service,不引發Crash


  • APP存在常駐通知欄時,是否屬於前臺APP?

如果只是普通的通知欄,並沒有什麼卵用的。

只有通過 Service.startForeground(int id, Notification notification) 啓動的通知欄,才能讓app成爲前臺APP。

如下圖,前臺Service的通知欄。

前臺通知欄

再次強調,通過 NotificationManager.notify(int id, notification) 顯示的普通通知,不會讓app成爲前臺APP,也不會讓進程成爲前臺進程。必須通過Service.startForeground(int id, Notification notification)方法現實的通知欄纔有用。


  • APP什麼情況下會進入空閒期?

    APP處於後臺之後,並不會立即進入空閒期,需要過幾分鐘,官方文檔並沒有明確時長。

    Model PixelXL android8.0.0 在app進入後臺狀態1分鐘後才進入空閒期;

    在模擬器上也是1分鐘後進入空閒期;


  • 那麼如何判斷App處在後臺?這裏有點複雜,需要耐心捋一捋。

    滿足以下任一,一個條件的APP都屬於前臺,Service運行不受任何限制。

    • app存在一個可見的Activity,Activity處於started或者paused或者resume階段
    • app中有一個前臺Service【即主動吊用過startForeground(int id, Notification notification)的Service】
    • app被另一個前臺app通過Service、Content Provider 綁定或者連接,比如說:
      • IME 輸入法APP,被系統的前臺進程綁定【或者我們APP中的一個Service,被其他第三方APP綁定,當第三方APP處在前臺時,那麼我們的APP也是處在前臺的。】
      • Wallpaper service
      • Notification listener
      • Voice or text service



  • **如何突破Android O Service **

    【詳見:下篇,突破android o Service限制】。

請注意,當APP處於前臺時,他的所有Service是不受限制的。

比如說,輸入法APP永遠是一個前臺APP,他被系統的前臺進程綁定,所以他Service的能力永遠不會被限制。

再比如說,如果APP有可見Activity時,在APP中可以隨意調用Context.startService(),也不會引發crash。



4. 官方鏈接:

https://developer.android.google.cn/about/versions/oreo/background?hl=en

英語基礎好的盆友,強烈建議,把整片官方文檔讀一遍。


5. 摘抄官方文檔,解釋:前後臺APP,以及空閒期

The system distinguishes between foreground and background apps. (The definition of background for purposes of service limitations is distinct from the definition used by memory management; an app might be in the background as pertains to memory management, but in the foreground as pertains to its ability to launch services.)An app is considered to be in the foreground if any of the following is true:

1) It has a visible activity, whether the activity is started or paused.
2) It has a foreground service.
3) Another foreground app is connected to the app, either by binding to one of its services or by making use of one of its content providers. For example, the app is in the foreground if another app binds to its:
    a. IME
    b. Wallpaper service
    c. Notification listener
    d. Voice or text service
If none of those conditions is true, the app is considered to be in the background.

原文鏈接:https://juejin.im/post/5dd16aab51882549e55badf4



點這裏,查看大叔的博客大綱







​ 讚美是一種美德,點個贊 再走啊,老鐵

weixin_2dcode

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章