1.前言
Android8.0的新特性值得注意一下,不然會出現(xiàn)很多莫名的問題。。。
2.后臺執(zhí)行限制
Android 8.0 為提高電池續(xù)航時(shí)間而引入的變更之一是,當(dāng)您的應(yīng)用進(jìn)入已緩存狀態(tài)時(shí),如果沒有活動的組件,系統(tǒng)將解除應(yīng)用具有的所有喚醒鎖。
此外,為提高設(shè)備性能,系統(tǒng)會限制未在前臺運(yùn)行的應(yīng)用的某些行為。具體而言:
- 現(xiàn)在,在后臺運(yùn)行的應(yīng)用對后臺服務(wù)的訪問受到限制。
-
應(yīng)用無法使用其清單注冊大部分隱式廣播(即,并非專門針對此應(yīng)用的廣播)。
默認(rèn)情況下,這些限制僅適用于針對 O 的應(yīng)用。不過,用戶可以從 Settings 屏幕為任意應(yīng)用啟用這些限制,即使應(yīng)用并不是以 O 為目標(biāo)平臺。
Android 8.0 還對特定函數(shù)做出了以下變更:
如果針對 Android 8.0 的應(yīng)用嘗試在不允許其創(chuàng)建后臺服務(wù)的情況下使用 startService() 函數(shù),則該函數(shù)將引發(fā)一個(gè) IllegalStateException。
新的 Context.startForegroundService() 函數(shù)將啟動一個(gè)前臺服務(wù)。現(xiàn)在,即使應(yīng)用在后臺運(yùn)行,系統(tǒng)也允許其調(diào)用 Context.startForegroundService()。不過,應(yīng)用必須在創(chuàng)建服務(wù)后的五秒內(nèi)調(diào)用該服務(wù)的 startForeground() 函數(shù)。
以下這個(gè)就是Android8.0的后臺限制新特性導(dǎo)致的.
自己編寫了一個(gè)demo跟蹤廣播的發(fā)送流程。
demo:注冊一個(gè)靜態(tài)receiver,然后發(fā)送廣播。
Activity中發(fā)送廣播的代碼:
public class MainActivity extends Activity {
public static final String TAG = "TEST";
public final String TEST_ACTION = "com.test.TEST_ACTION";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG,"onResume");
Log.d(TAG,">>sendBroadcast");
Intent intent = new Intent(TEST_ACTION);
sendBroadcast(intent);
Log.d(TAG,"<<sendBroadcast");
}
private BroadcastReceiver mTestReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
Log.d(TAG,"Dynamic receiver:action="+action);
}
};
}
AndroidManifest.xml中注冊靜態(tài)receiver:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.atc6111.testswitchicon">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".MyTestReceiver">
<intent-filter>
<action android:name="com.test.TEST_ACTION"/>
</intent-filter>
</receiver>
</application>
</manifest>
Receiver對應(yīng)的java文件:
public class MyTestReceiver extends BroadcastReceiver {
private final String TAG = "TEST-MyTestReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG,"Static receiver:action=" + intent.getAction());
}
}
運(yùn)行這個(gè)demo。發(fā)現(xiàn)這個(gè)receiver一直都沒有收到廣播。。。。
查看log,發(fā)現(xiàn)了waring信息:
W BroadcastQueue: Background execution not allowed: receiving Intent { act=com.test.TEST_ACTION flg=0x10 } to com.example.atc6111.testswitchicon/.MyTestReceiver
"Background execution not allowed" 打印出該warning的代碼:
即是以下兩種情況靜態(tài)receiver不會接收到廣播:
1.發(fā)送的intent設(shè)置了FLAG --FLAG_RECEIVER_EXCLUDE_BACKGROUND;
2.以下情況的均滿足時(shí):
①intent沒有指定接收組件,也就是沒有setComponent
②intent沒有執(zhí)行接收的package,也就是沒有setPackage
③發(fā)送的intent沒有設(shè)置FLAG-FLAG_RECEIVER_INCLUDE_BACKGROUND
④給定的權(quán)限并不都是簽名權(quán)限。
根據(jù)這兩種情況,即是說靜態(tài)receiver接收不了隱式廣播。本來打算采用最簡單的方法添加Flag來解決的。
但是奇怪的是,Android Studio里沒有FLAG_RECEIVER_INCLUDE_BACKGROUND!!!!
然后,只好在發(fā)送intent的時(shí)候setPackage。
@Override
protected void onResume() {
super.onResume();
Log.d(TAG,"onResume");
Log.d(TAG,">>sendBroadcast");
Intent intent = new Intent(TEST_ACTION);
intent.setPackage(getPackageName());
sendBroadcast(intent);
Log.d(TAG,"<<sendBroadcast");
}
修改之后,靜態(tài)Receiver就能收到廣播了。