問題:什么是Broadcast Receiver
先說答案:
廣播接收者(Broadcast Receiver)
是Android 應(yīng)用開發(fā)中的一個核心組件,用于監(jiān)聽和響應(yīng)系統(tǒng)級別或應(yīng)用級別的廣播消息猬膨。
廣播消息是在應(yīng)用程序或Android系統(tǒng)之間傳遞的信息,可以是諸如設(shè)備屏幕關(guān)閉嗤疯、電池電量低蔚润、一段時間后觸發(fā)的提醒、應(yīng)用安裝或卸載等事件的通知。
主要特性:
事件驅(qū)動:廣播接收器被設(shè)計用來響應(yīng)廣播消息词疼,這些消息通常對應(yīng)于系統(tǒng)事件或應(yīng)用內(nèi)事件。
系統(tǒng)廣播:Android系統(tǒng)會發(fā)出多種系統(tǒng)級別的廣播帘腹,例如開機贰盗、網(wǎng)絡(luò)變化、短信到達(dá)等阳欲。
應(yīng)用廣播:應(yīng)用可以發(fā)送自定義廣播舵盈,其他應(yīng)用的廣播接收器可以選擇監(jiān)聽這些廣播陋率。
怎么發(fā)送廣播:
發(fā)送普通廣播:
普通廣播是完全異步的,所有接收器幾乎同時接收到廣播翘贮,它們的執(zhí)行順序不能被指定爆惧。
Intent intent = new Intent();
intent.setAction("com.example.broadcast.MY_NOTIFICATION");
intent.putExtra("data", "Something interesting");
sendBroadcast(intent);
發(fā)送有序廣播:
有序廣播按照接收器聲明的優(yōu)先級(在 AndroidManifest.xml 中用 android:priority 屬性指定)順序發(fā)送芍耘。
當(dāng)多個接收器監(jiān)聽相同的動作時,系統(tǒng)會根據(jù)優(yōu)先級從高到低依次發(fā)送廣播坝初。
Intent intent = new Intent();
intent.setAction("com.example.broadcast.MY_NOTIFICATION");
intent.putExtra("data", "Something interesting");
sendOrderedBroadcast(intent, null);
怎么接收廣播:
靜態(tài)注冊
靜態(tài)注冊意味著在應(yīng)用的AndroidManifest.xml文件中聲明廣播接收器。
這樣注冊的接收器可以接收到即使應(yīng)用未運行時發(fā)出的廣播事件拗小。
要靜態(tài)注冊一個廣播接收器哀九,你需要在AndroidManifest.xml文件中添加<receiver>標(biāo)簽,
并且在<intent-filter>標(biāo)簽內(nèi)指定需要監(jiān)聽的廣播動作。
<receiver android:name=".MyBroadcastReceiver" android:exported="true">
? ? <intent-filter>
? ? ? ? <action android:name="com.example.broadcast.MY_NOTIFICATION"/>
? ? ? ? <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
? ? </intent-filter>
</receiver>
動態(tài)注冊動態(tài)注冊是在代碼中進(jìn)行的簿寂,通常是在一個組件(如Activity或Service)的生命周期內(nèi)常遂。
這樣注冊的接收器只有在組件運行時才能接收廣播平绩。
要動態(tài)注冊廣播接收器跃赚,你需要創(chuàng)建IntentFilter纬傲,并調(diào)用registerReceiver()方法。
public class MyActivity extends Activity {
? ? private MyBroadcastReceiver myReceiver;
? ? private IntentFilter intentFilter;
? ? @Override
? ? protected void onCreate(Bundle savedInstanceState) {
? ? ? ? super.onCreate(savedInstanceState);
? ? ? ? // 實例化廣播接收器和意圖過濾器
? ? ? ? myReceiver = new MyBroadcastReceiver();
? ? ? ? intentFilter = new IntentFilter("com.example.broadcast.MY_NOTIFICATION");
? ? ? ? // 注冊廣播接收器
? ? ? ? registerReceiver(myReceiver, intentFilter);
? ? }
? ? @Override
? ? protected void onDestroy() {
? ? ? ? super.onDestroy();
? ? ? ? // 注銷廣播接收器
? ? ? ? unregisterReceiver(myReceiver);
? ? }
}
動態(tài)注冊的廣播接收器不會在應(yīng)用未運行時接收廣播,因此它不會像靜態(tài)注冊的那樣增加應(yīng)用的內(nèi)存使用侠讯。
中止廣播/邏輯處理(靜態(tài)注冊動態(tài)注冊的就是下面這個東西):
僅有序廣播可以被中止,普通廣播不能被中止袁翁。在有序廣播中,當(dāng)前接收到廣播的接收器可以調(diào)用abortBroadcast()方法來中止廣播焙压,這樣優(yōu)先級較低的其他接收器就不會再接收到這個廣播了。
public class MyReceiver extends BroadcastReceiver {
? ? @Override
? ? public void onReceive(Context context, Intent intent) {
? ? ? ? // 判斷是否是需要中止的廣播
? ? ? ? if ("com.example.broadcast.MY_NOTIFICATION".equals(intent.getAction())) {
? ? ? ? ? ? // 邏輯處理
? ? ? ? ? ? // ...
? ? ? ? ? ? // 中止廣播
? ? ? ? ? ? abortBroadcast();
? ? ? ? }
? ? }
}
權(quán)限控制:
在發(fā)送和接收廣播時,可以通過指定權(quán)限來限制哪些應(yīng)用可以接收廣播绰沥。發(fā)送廣播時零截,可以在?sendBroadcast?或?sendOrderedBroadcast?方法中傳遞一個權(quán)限字符串,系統(tǒng)會確保只有擁有這個權(quán)限的接收器才能接收到該廣播。
生命周期和限制:
廣播接收器沒有自己的用戶界面傻铣。
它們的生命周期非常短暫蜕径,只在?onReceive()?方法調(diào)用期間存活梦染。
執(zhí)行長時間運行的操作不應(yīng)該在?onReceive()?方法中直接進(jìn)行,而是應(yīng)該通過啟動一個服務(wù)(如?IntentService)來進(jìn)行朴皆。
注意事項:
性能:廣播接收器的執(zhí)行對性能有影響帕识,因此應(yīng)該避免在onReceive()方法中進(jìn)行重型操作。
權(quán)限:接收某些系統(tǒng)廣播可能需要相應(yīng)的權(quán)限遂铡。
隱式廣播限制:為了提高系統(tǒng)性能肮疗,Android 8.0(API 級別 26)引入了對靜態(tài)注冊的隱式廣播的限制。
線程:onReceive()方法默認(rèn)運行在主線程(UI線程)扒接,因此在此方法中進(jìn)行的任何耗時操作都會阻塞UI線程伪货。
最佳實踐:
考慮隱私和安全性:避免發(fā)送敏感信息,或者確保通過權(quán)限限制其訪問钾怔。
注意性能:不要在?onReceive()?方法中執(zhí)行長時間運行的任務(wù)碱呼。
考慮使用本地廣播:如果廣播僅在自己的應(yīng)用內(nèi)部通信,可以考慮使用?LocalBroadcastManager宗侦。它不是跨應(yīng)用的巍举,因此更安全,也更高效凝垛。不過從AndroidX庫開始懊悯,LocalBroadcastManager?被標(biāo)記為廢棄,推薦使用其他方式梦皮,例如?LiveData?或者?EventBus炭分。