Broadcast專講

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");
  1. 發送有序廣播需要指定一個權限。
  2. 優先級高的接收器,優先接收到消息,並可以像優先級低的廣播傳遞數據,還可以終止廣播繼續傳遞。
<!--定義優先級-->
<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

源碼地址

覺得有用?那打賞一個唄。去打賞

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