Android四大組件之BroadcastReceiver

一、簡介


image.png-25.5kB
image.png-25.5kB

用于接收和處理Context.sendBroadcast(Intent)發(fā)送的廣播意圖的代碼的基類。您可以使用Context.registerReceiver()動態(tài)注冊該類的實例,也可以使用AndroidManifest.xml中的 <receiver> 標記 靜態(tài)聲明實現(xiàn)。因此,BroadcastReceiver是四大組件中唯一一個可以不是必須在清單文件注冊的組件。

和Service類似,為了防止廣播的濫用導致系統(tǒng)性能變慢,應該也有安全的考慮,自Android 8.0(API 26)開始,Android禁用了大部分的隱式廣播(靜態(tài)注冊),這里是例外的隱式廣播。

Android系統(tǒng)預定了很多系統(tǒng)廣播,我們也可以自定義廣播,Android應用可以從Android系統(tǒng)和其他Android應用發(fā)送或接收廣播消息,因為默認是全局廣播;如果為了安全,只想在自己的程序內接收發(fā)送廣播,我們還可以通過LocalBroadcastManager管理我們的廣播,注冊和發(fā)送本地廣播,當然,只能用于動態(tài)注冊。廣播機制類似于發(fā)布 - 訂閱設計模式。

發(fā)布廣播可以通過Context.sendBroadcast(Intent)發(fā)送異步執(zhí)行的標準廣播,所有注冊接收該廣播的客戶端將幾乎同時收到該廣播,效率高,無法截斷;也可以通過Context.sendOrderedBroadcast(intent,permission)發(fā)送同步執(zhí)行的有序廣播,所有注冊接收該廣播的客戶端會根據(jù)優(yōu)先級順序接收到廣播,效率低,可截斷,截斷之后其他優(yōu)先級低未接收到廣播的客戶端將不能接收到該廣播。

二、使用


1. 創(chuàng)建receiver

public class MyReceiver extends BroadcastReceiver {
    private static final String TAG = "MyReceiver";

    /**
     * 必須重寫,接收到廣播時回調;收到廣播后的操作寫在這里
     */
    @Override
    public void onReceive(Context context, Intent intent) {
        StringBuilder sb = new StringBuilder();
        sb.append("Packge: " + context.getPackageName() + "\n");
        sb.append("Action: " + intent.getAction() + "\n");
        
        String log = sb.toString();
        
        Log.d(TAG, log);
        
        Toast.makeText(context, log, Toast.LENGTH_LONG).show();
    }
}

2. 注冊receiver

動態(tài)注冊:

  • 可以接收其他APP的廣播(全局廣播)
// filter
IntentFilter filter = new IntentFilter();
// 設置優(yōu)先級 范圍:SYSTEM_LOW_PRIORITY(-1000)~SYSTEM_HIGH_PRIORITY(1000),默認:0
filter.setPriority(100);
// 自定義
filter.addAction("com.example.myreceiver"); 
// 系統(tǒng)開機
filter.addAction(Intent.ACTION_BOOT_COMPLETED);
// receiver
mMyReceiver = new MyReceiver();
// 動態(tài)注冊系統(tǒng)范圍內廣播
registerReceiver(mMyReceiver,filter);
  • 只接收程序內廣播(本地廣播)
// 獲取本地廣播管理者實例
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);
// filter
IntentFilter filter = new IntentFilter();
// 設置優(yōu)先級
filter.setPriority(100);
// 自定義
filter.addAction("com.example.myreceiver");
// 系統(tǒng)開機
filter.addAction(Intent.ACTION_BOOT_COMPLETED);
// receiver
mMyReceiver = new MyReceiver();
// 注冊本地廣播
localBroadcastManager.registerReceiver(mMyReceiver,filter);

要記得取消注冊!

@Override
protected void onDestroy() {
    super.onDestroy();
    // 動態(tài)注冊要記得取消注冊,防止造成內存泄漏
    unregisterReceiver(mMyReceiver);
}

靜態(tài)注冊:

<!-- 靜態(tài)注冊  enabled:是否啟用receiver; exported:是否接收其他App的廣播 -->
<receiver
    android:name=".receiver.MyReceiver"
    android:enabled="true"
    android:exported="true">
    <!-- 設置優(yōu)先級 -->
    <intent-filter  android:priority="100">
        <!-- 自定義 -->
        <action android:name="com.example.myreceiver" />
        <!-- 系統(tǒng): 接收開機廣播 -->
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

兩種注冊方式,根據(jù)需求二選一,提倡動態(tài)注冊,而且8.0對靜態(tài)注冊做了限制,另外,對于一些Action,由于涉及用戶隱私,需要在清單文件申請權限:

<manifest>
 。。。
// 獲取接收開機廣播的權限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
 。。。
</manifest>

3. 發(fā)送廣播

標準廣播:

// intent
Intent intent = new Intent();
intent.setAction("com.example.myreceiver");
// intent.setPackage("com.example.myandroiddemo"); // 對于靜態(tài)注冊,需設置接收端的包名才行
// 發(fā)送標準廣播
sendBroadcast(intent);

有序廣播:

// intent
Intent intent = new Intent();
intent.setAction("com.example.myreceiver");
// 發(fā)送有序廣播
sendOrderedBroadcast(intent,null);

本地廣播:

// intent
Intent intent = new Intent();
intent.setAction("com.example.myreceiver");
// 發(fā)送本地廣播
mLocalBroadcastManager.sendBroadcast(intent);

優(yōu)點:

  • 您知道您正在發(fā)送的廣播數(shù)據(jù)不會離開您的應用,因此無需擔心泄露私人數(shù)據(jù)。
  • 其他應用程序無法將這些廣播發(fā)送到您的應用程序,因此您無需擔心他們可以利用的安全漏洞。
  • 它比通過系統(tǒng)發(fā)送全局廣播更高效。

個人總結,水平有限,如果有錯誤,希望大家能給留言指正!如果對您有所幫助,可以幫忙點個贊!如果轉載,希望可以留言告知并在顯著位置保留草帽團長的署名和標明文章出處!最后,非常感謝您的閱讀!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容