Android8.0無法接收隱式廣播訊息
App裡有一個自己在Manifest檔案裡面註冊的廣播接收器(Receiver),到Android8.0的機器上除錯的時候卻接收不到訊息,一番搜尋和研究之後,才發現Android8.0已經對隱式廣播做了限制。
版本區別
對於targetSdkVersion 在26或者以上的App,在Manifest裡面註冊的Receiver已經受到限制,而用Java程式碼動態註冊的Receiver則不受影響。
targetSdkVersion 在 25或以下的App,其Receiver不受影響,即使在Android8.0以上的機器上執行。
如果targetSdkVersion 在26或者以上,在Manifest註冊的Receiver可能無法接收到廣播訊息,並且會在Logcat裡面打印出如下訊息:
BroadcastQueue: Background execution not allowed: receiving Intent { act=com.xiaoqiang.try.something.receiver flg=0x2010 (has extras) } to xiaoqiang.com.trysomething/.broadcast.TheReceiver
有哪些影響
首先要了解一個概念。官方文件裡提到implicit broadcast,可譯為隱式廣播,指那些沒有指定接收App(即包名)的廣播。
- 系統傳送的廣播毫無疑問都是隱式廣播,因此基本上都會受到影響,除了部分受豁免廣播之外
- App傳送的自定義隱式廣播,都會受到影響
為何限制隱式廣播
總所周知,在Manifest裡面註冊的系統廣播接收器會被快取在系統中,即使當App關閉之後,如果有相應的廣播發出,應用程式仍然會被喚醒。比如如果有20個App在Manifest裡面註冊了ACTION_BOOT_COMPLETED的廣播接收器監聽裝置啟動,那麼當裝置啟動時,就會有20個應用程式被喚醒並作出相應的動作。而動態註冊的廣播則跟隨元件的生命週期而消存。因此在Manifest裡面註冊廣播接收器的App越多,裝置的效能就越容易受到影響,限制隱式廣播主要是為了優化系統性能。
如何應對這一限制
分析了受限制的原因之後,就知道該如何應對這一影響了。
- 優先使用動態註冊Receiver的方式,能動態註冊絕不使用Manifest註冊
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.xiaoqiang.try.something.receiver");
TheReceiver receiver = new TheReceiver();
registerReceiver(receiver, intentFilter);
1
2
3
4
如果一定要Manifest註冊,那麼當傳送廣播的時候,指定廣播接收者的包名,即傳送顯式廣播
Intent intent = new Intent("com.xiaoqiang.try.something.receiver");
intent.putExtra("receive","test broadcast");
intent.setPackage(getPackageName());
//intent.setComponent(...)
sendBroadcast(intent);
1
2
3
4
5
如果要接收系統廣播,而對應的廣播在Android8.0中無法被接收,那麼只能暫時把App的targetSdkVersion改為25或以下。