首先並非全部app的Service後臺運行都會被系統限制。java
知足如下兩個特色的APP,內的Service,可能會受到系統限制android
必須在android 8.0以上的設備上bash
APP的 targetSdkVersion 配置大於等於26app
APP的targetSdkVersion的配置在app/build.gradle文件中ide
android {
defaultConfig {
targetSdkVersion 26 //此配置
}
...
}
複製代碼
當APP處於空閒期時,將會有以下兩個限制:oop
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)
複製代碼
被回收的現象,就和咱們本身主動調用Context.stopService()同樣。 Service將會被執行:onDestory()生命週期方法。post
注意:gradle
這裏千萬要注意,理解:app處在空閒期,是什麼意思?ui
空閒期,在,官方文檔的英文描述爲:idle。google
app處在後臺,並不等於處在空閒期;
app處在後臺,並不等於處在空閒期;
app處在後臺,並不等於處在空閒期;
APP處於後臺,是進入空閒期的必要條件,但不是充分條件。
例如:
Model PixelXL手機, android8.0.0系統:在APP進入後臺狀態,並保持處於後臺狀態1分鐘後,才進入空閒期。
APP從開始處於後臺,到,正式進入空閒期的 這1分鐘期間,app能夠隨意startService是不會拋出異常的。App內的Service也不會被系統主動回收。
在這1分鐘期間,用戶若是打開APP,將APP置爲前臺,那麼下次進入後臺後須要從新計時,從新進入後臺保持1分鐘纔會進入空閒期。
APP存在常駐通知欄時,是否屬於前臺APP?
APP什麼狀況下會進入空閒期?
如何判斷App處在後臺?
APP進入空閒期時,如何防止Service不被Stop
APP處在空閒期時,如何啓動Service,不引起Crash
若是隻是普通的通知欄,並無什麼卵用的。
只有經過 Service.startForeground(int id, Notification notification) 啓動的通知欄,才能讓app成爲前臺APP。
以下圖,前臺Service的通知欄。
再次強調,經過 NotificationManager.notify(int id, notification) 顯示的普統統知,不會讓app成爲前臺APP,也不會讓進程成爲前臺進程。必須經過Service.startForeground(int id, Notification notification)方法現實的通知欄纔有用。
APP處於後臺以後,並不會當即進入空閒期,須要過幾分鐘,官方文檔並無明確時長。
Model PixelXL android8.0.0 在app進入後臺狀態1分鐘後才進入空閒期;
在模擬器上也是1分鐘後進入空閒期;
那麼如何判斷App處在後臺?這裏有點複雜,須要耐心捋一捋。
知足如下任一,一個條件的APP都屬於前臺,Service運行不受任何限制。
【詳見:下篇,突破android o Service限制】juejin.im/post/5dd16f…
好比說,輸入法APP永遠是一個前臺APP,他被系統的前臺進程綁定,因此他Service的能力永遠不會被限制。
再好比說,若是APP有可見Activity時,在APP中能夠隨意調用Context.startService(),也不會引起crash。
developer.android.google.cn/about/versi…
英語基礎好的盆友,強烈建議,把整片官方文檔讀一遍。
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.
複製代碼
讚美是一種美德,點個贊再走啊,老鐵