0. 前言
最近遇到一個問題,在做培訓時,屢試不爽的廣播消息竟然存在接收不到廣播的情況。經瞭解後發現,Android O 已對隱式廣播添加限制。so,下面總結下 Android 中廣播相關。
1. 廣播註冊
廣播註冊分爲靜態註冊和動態註冊,靜態註冊的廣播,可以在程序沒被啓動時,接收到全局廣播消息。而動態註冊廣播,只有在程序啓動後接收廣播消息。
1.1 靜態註冊
定義好廣播消息後,在 AndroidManife.xml 中註冊即可,示例中,添加多個 Action。
<receiver
android:name="com.flueky.demo.DemoReceiver"
android:permission="com.flueky.demo.permission.Demo_Receiver">
<intent-filter android:priority="999">
<action android:name="com.flueky.app.Demo_Receiver" />
</intent-filter>
<intent-filter>
<action android:name="com.flueky.demo.TEST_RECEIVER1" />
</intent-filter>
<intent-filter>
<action android:name="com.flueky.demo.TEST_RECEIVER2" />
</intent-filter>
</receiver>
1.2 動態註冊
動態註冊指在 Activity 或 Service 中註冊,並在 Activity 或 Service 銷燬時,需要註銷。
// 註冊廣播
registerReceiver(testReceiver, new IntentFilter("com.flueky.demo.TEST_RECEIVER1"));
// 註銷廣播
unregisterReceiver(testReceiver);
由於動態註冊的廣播可以通過定義內部類的方式實現,因此,動態 註冊的廣播可以同宿主 Activity 或 Service 進行交互。
2. 廣播分類
2.1 無序廣播
應用發出廣播後,所有註冊了廣播 Action 接收到廣播的先後順序是未知的,則叫發送了無序廣播。
Intent intent = new Intent("com.flueky.app.Demo_Receiver");
sendBroadcast(intent, "com.flueky.demo.permission.Demo_Receiver");
2.2 有序廣播
應用發出廣播後,所有註冊了廣播 Action 接收到廣播的先後順序是固定的,則叫發送了無序廣播。
Intent intent = new Intent("com.flueky.app.Demo_Receiver");
sendOrderedBroadcast(intent, "com.flueky.demo.permission.Demo_Receiver");
- 發送有序廣播需要指定一個權限。
- 優先級高的接收器,優先接收到消息,並可以像優先級低的廣播傳遞數據,還可以終止廣播繼續傳遞。
<!--定義優先級-->
<intent-filter android:priority="999">
<action android:name="com.flueky.app.Demo_Receiver" />
</intent-filter>
有序廣播接收器中傳遞消息和終止廣播如下:
//非有序廣播,不不做下面的操作
if (!isOrderedBroadcast())
return;
// 獲取前一個廣播傳遞的消息
Bundle bundle = getResultExtras(true);
String received = bundle.getString("received");
Log.d(TAG, "onReceive: 廣播發送 "+(received==null?"null":received));
// 將消息傳遞給下一個待接收的廣播。
bundle.putString("received","已被 send 接收");
setResultExtras(bundle);
// 終止廣播
abortBroadcast();
2.3 本地廣播
發送有序廣播和無序廣播後,設備中的其他應用只需要註冊了接收廣播的 Action ,都可以接收到廣播消息。爲了只在自己應用中接收到廣播消息,Google 先後給出了兩種方案。其中一種是本地廣播,通過 v4 包提供了 LocalBroadcastManager 類,註冊、註銷和發送廣播。
// 註冊本地廣播
LocalBroadcastManager.getInstance(this).registerReceiver(testReceiver, new IntentFilter("com.flueky.demo.TEST_RECEIVER2"));
// 發送本地廣播
LocalBroadcastManager.getInstance(this).sendBr
oadcast(new Intent("com.flueky.demo.TEST_RECEIVER2"));
// 註銷本地廣播
LocalBroadcastManager.getInstance(this).unregisterReceiver(testReceiver);
本地廣播只能通過動態註冊的方式,而且由 LocalBroadcastManager 註冊的廣播只能接收 LocalBroadcastManager 發送的廣播。
3. 自定義權限
在 Android 8.0 以上,使用全局廣播必須給廣播接收器添加上權限。發送廣播時需要使用廣播接收器申明的權限,而且,發送廣播的應用需要在 AndroidManifest.xml 中申明權限。
具體做法是:發送廣播的應用清單文件類容如下:
<!--定義一個權限-->
<permission
android:name="com.flueky.demo.permission.Demo_Receiver"
android:protectionLevel="signature" />
<!--申明使用這個權限-->
<uses-permission android:name="com.flueky.demo.permission.Demo_Receiver" />
代碼如下:
// 發送帶權限的廣播,有序廣播和無序廣播都行。
Intent intent = new Intent("com.flueky.app.Demo_Receiver");
sendBroadcast(intent, "com.flueky.demo.permission.Demo_Receiver");
接收廣播應用的清單文件如下:
<!--使用自定義的權限,包括下面註冊廣播時,使用的 permission 屬性。-->
<uses-permission android:name="com.flueky.demo.permission.Demo_Receiver" />
<receiver
android:name="com.flueky.demo.DemoReceiver"
android:permission="com.flueky.demo.permission.Demo_Receiver">
<intent-filter android:priority="1000">
<action android:name="com.flueky.app.Demo_Receiver" />
</intent-filter>
</receiver>
最後,發送廣播和接收廣播的應用必須使用同一個簽名文件。因爲自定義權限的安全級別是 signature。
源碼地址。
覺得有用?那打賞一個唄。去打賞