Android學(xué)習(xí)筆記之Broadcast Receiver

內(nèi)容目錄

  1. 廣播的定義
  2. 廣播的用途(信息傳輸與共享通知
  3. 廣播的使用場景
  4. 廣播主要的種類(普通廣播有序廣播本地廣播
  5. 注冊廣播接收 (靜態(tài)接收動態(tài)接收)
  6. 廣播的發(fā)送(sendBroadcastsendOrderBroadcast
  7. 廣播內(nèi)部實(shí)現(xiàn)機(jī)制
  8. AMS 是什么?
  9. 本地廣播 LocalBroadcastManager
  10. 全局廣播的缺點(diǎn)
  11. BroadcastReceiver 和 LocalBroadcastReceiver 區(qū)別
  12. BroadCastReceiver 的生命周期
  13. 廣播傳輸?shù)臄?shù)據(jù)是否有限制,是多少,為什么要限制?

1.廣播的定義

  • 在 Android 中,Broadcast 是一種在應(yīng)用程序之間傳輸信息的機(jī)制,要發(fā)送的廣播內(nèi)容是一個(gè) Intent,這個(gè) Intent 中可以攜帶我們要傳送的數(shù)據(jù)。(數(shù)據(jù)小于1MB)

2.廣播的用途

  1. 廣播實(shí)現(xiàn)了不同程序之間的信息傳輸與共享,只要和發(fā)送廣播的 action 相同的接收者,都能接收到這個(gè)廣播。典型的應(yīng)用就是 android 自帶的短信,電話等等廣播,只要我們實(shí)現(xiàn)了他們的 action 的廣播,那么我們就能接收他們的數(shù)據(jù)了,以便做出一些處理。比如說攔截系統(tǒng)短信,攔截騷擾電話等。
  2. 作為通知的作用,比如在 Service 中要通知主程序、更新主程序的 UI 等,因?yàn)?Service 是沒有界面的,所以不能直接獲得主程序中的控件,這樣我們就只能在主程序中實(shí)現(xiàn)一個(gè)廣播接收者專門用來接收service發(fā)過來的數(shù)據(jù)和通知了。

3.廣播的使用場景

  1. 同一app內(nèi)部的同一組件內(nèi)的消息通信(單個(gè)或多個(gè)線程之間)(可用handler解決);
  2. 同一app內(nèi)部的不同組件之間的消息通信(單個(gè)進(jìn)程)(可用EventBus);
  3. 同一app具有多個(gè)進(jìn)程的不同組件之間的消息通信;
  4. 不同app之間的組件之間的消息通信;
  5. Android系統(tǒng)在特定情況下與App之間的消息通信。

4.廣播主要的種類

  • 普通廣播Normal Broadcast異步執(zhí)行的廣播,所有接收者在同一時(shí)刻收到這條廣播消息。效率高,沒有先后順序,無法截?cái)?。屬于全局廣播。調(diào)用 sendBroadcast()發(fā)送,最常用的廣播。

  • 有序廣播Ordered Broadcast同步執(zhí)行的廣播,發(fā)出去的廣播會被廣播接收者按照順序接收,廣播接收者按照Priority屬性值從大-小排序,Priority屬性相同者,動態(tài)注冊的廣播優(yōu)先,廣播接收者還可以選擇對廣播進(jìn)行截?cái)嗪托薷摹U{(diào)用sendOrderedBroadcast()發(fā)送。

  • 本地廣播Local Broadcast:App應(yīng)用內(nèi)廣播可理解為一種局部廣播,廣播的發(fā)送者和接收者都同屬于一個(gè)App。相比于全局廣播(普通廣播),App應(yīng)用內(nèi)廣播優(yōu)勢體現(xiàn)在:安全性高 & 效率高。對于LocalBroadcastManager方式發(fā)送的應(yīng)用內(nèi)廣播,只能通過LocalBroadcastManager動態(tài)注冊,不能靜態(tài)注冊。調(diào)用sendBroadcast發(fā)送。


4、注冊廣播接收 (靜態(tài)和動態(tài))

4.1兩種注冊方法的區(qū)別

  • 動態(tài)注冊的接收器必須要在程序啟動之后才能接收到廣播;
  • 靜態(tài)注冊的接收器即便程序未啟動也能接收到廣播,比如想接收到手機(jī)開機(jī)完成后系統(tǒng)發(fā)出的廣播就只能用靜態(tài)注冊了。

4.2靜態(tài)注冊具體步驟

  • 靜態(tài)注冊:將廣播寫在 AndroidMainifest.xml 文件當(dāng)中,特點(diǎn)是:常駐系統(tǒng),不受組件生命周期影響,即便應(yīng)用退出,廣播還是可以被接收,耗電、占內(nèi)存。
  • 第一步:創(chuàng)建繼承 BroadcastReceiver,然后重寫具體實(shí)現(xiàn)onReceive(),由于生命周期短,耗時(shí)工作應(yīng)該發(fā)給Service,onReceive()不要開啟子線程。
public class MyReceiver extends BroadcastReceiver {
        //onReceive 不能做過多的耗時(shí)操作,10秒沒響應(yīng)就ANR
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "boot complete", Toast.LENGTH_SHORT).show();
    }
}
  • 第二步:在 AndroidMainifest.xml 中添加<receiver>,子標(biāo)簽intent-filter中添加需要監(jiān)聽的action。Exported 屬性表示是否允許這個(gè)廣播接收本程序以外的廣播,Enabled 屬性表示是否啟用用這個(gè)廣播接收器。
<receiver
    android:name=".MyReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

4.3 動態(tài)注冊

  • 動態(tài)注冊 : 自定義類繼承 BroadcastReceiver,然后重寫具體實(shí)現(xiàn)onReceive()。在代碼中調(diào)用registerReceiver()注冊來進(jìn)行廣播的注冊。必須在 onDestroy 中調(diào)用unregisterReceiver()方法,否則會引起內(nèi)存泄露。特點(diǎn)是:不常駐,跟隨組件的生命變化,組件結(jié)束,廣播結(jié)束。在組件結(jié)束前,需要先移除廣播,否則容易造成內(nèi)存泄漏。
    protected void onCreate() {
       myBroadcastReceiver ChangeReceiver = new myBroadcastReceiver();
       IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
        registerReceiver(ChangeReceiver, intentFilter);
    }
    //在onDestroy()中要取消注冊,否則會引起內(nèi)存泄漏。
    protected void onDestroy() {
        unregisterReceiver(networkChangeReceiver);
    }
    //ChangeReceiver就是接收后會怎么樣怎么樣
    class myBroadcastReceiver extends BroadcastReceiver {
        public void onReceive(Context context, Intent intent){
        //to do
        }
     }

5、廣播的發(fā)送

1.標(biāo)準(zhǔn)廣播(異步)

//通過sendBroadcast發(fā)送標(biāo)準(zhǔn)合家歡廣播
Intent intent = new Intent("com.example.songsong.MY_BROADCAST");
sendBroadcast(intent);

2.有序廣播(同步)

  • 定義:發(fā)送出去的廣播被廣播接收者按照先后順序接收
  • 接收廣播的順序規(guī)則(同時(shí)面向靜態(tài)和動態(tài)注冊的廣播接受者)
    • 按照Priority屬性值從大-小排序;
    • Priority屬性相同者,動態(tài)注冊的廣播優(yōu)先;
  • 特點(diǎn):
    • 接收廣播按順序接收;
    • 先接收的廣播接收者可以對廣播進(jìn)行截?cái)?/code>,即后接收的廣播接收者不再接收到此廣播;
    • 先接收的廣播接收者可以對廣播進(jìn)行修改,那么后接收的廣播接收者將接收到被修改后的廣播
//通過sendOrderBroadcast發(fā)送
Intent intent = new Intent("com.example.songsong.MY_BROADCAST");
sendOrderBroadcast(intent,null);
    /*給廣播接收器設(shè)置優(yōu)先級 */
    <intent-filter android:priority="100">
        <action android:name="com.example.broadcasttest.LOCAL_BROADCAST" />
    </intent-filter>
//廣播接收器截?cái)啵?public void onReceive(Context context, Intent intent) {
    abortBroadcast();
}

3.本地廣播

//發(fā)送1:實(shí)例化localBroadcastManager
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);
//發(fā)送2:發(fā)送廣播
Intent intent = new Intent("android.net.conn.CONNECTIVITY_CHANGE");
localBroadcastManager.sendBroadcast(intent);
//接收1:實(shí)例化IntentFilter和接收器LocalReceiver
IntentFilter intentFilter = new IntentFilter(); 
LocalReceiver localReceiver  = new LocalReceiver();
//接收2:設(shè)置廣播接收類型
intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);
//接收3:進(jìn)行動態(tài)注冊本地廣播
localBroadcastManager.registerReceiver(localReceiver, intentFilter);
//接收4:在onDestroy中取消注冊
localBroadcastManager.unregisterReceiver(localReceiver);
//接收5:在localReceiver中繼承BroadcastReceiver并重寫onReceiver。
...

6.廣播內(nèi)部實(shí)現(xiàn)機(jī)制

  1. 自定義廣播接收者 BroadcastReceiver,并復(fù)寫 onRecvice();
  2. 通過 Binder 機(jī)制向 AMS(Activity Manager Service) 注冊廣播;
  3. 通過 Binder 機(jī)制向 AMS(Activity Manager Service) 發(fā)送廣播。
  4. AMS 查找符合相應(yīng)條件(IntentFilter/Permission等)的BroadcastReceiver,將廣播發(fā)送到BroadcastReceiver 所在的消息循環(huán)隊(duì)列中。
  5. BroadcastReceiver 所在消息隊(duì)列拿到此廣播后,回調(diào)它的 onReceive() 方法。

7.AMS 是什么?

AMS(Activity Manager Service):是貫穿Android系統(tǒng)組件的核心服務(wù),負(fù)責(zé)啟動四大組件啟動切換調(diào)度。


8.本地廣播 LocalBroadcastManager

  • 背景:Android中的廣播可以跨App直接通信(exported對于有intent-filter情況下默認(rèn)值為true)

  • 沖突

    • 其他App針對性發(fā)出與當(dāng)前App intent-filter相匹配的廣播,由此導(dǎo)致當(dāng)前App不斷接收廣播并處理;
    • 其他App注冊與當(dāng)前App一致的intent-filter用于接收廣播,獲取廣播具體信息(即會出現(xiàn)安全性 & 效率性的問題)。
  • 解決方案:使用App應(yīng)用內(nèi)廣播(Local Broadcast)

    • App應(yīng)用內(nèi)廣播可理解為一種局部廣播,廣播的發(fā)送者和接收者都同屬于一個(gè)App。
    • 相比于全局廣播(普通廣播),App應(yīng)用內(nèi)廣播優(yōu)勢體現(xiàn)在:安全性高 & 效率高;
  • 特點(diǎn)

    • 發(fā)送的廣播只能夠在自己 App 的內(nèi)部傳遞,不會泄露給其他 App,確保隱私數(shù)據(jù)不會泄露;
    • 廣播接收器只能接收來自本 App 發(fā)出的廣播;
    • 其他App也無法向你的App發(fā)送該廣播,不用擔(dān)心其他App會來搞破壞;
    • 比系統(tǒng)的全局廣播更加高效。
  • 內(nèi)部實(shí)現(xiàn)原理

    1. LocalBroadcastManager 高效的原因主要因?yàn)樗鼉?nèi)部是通過Handler實(shí)現(xiàn)的,它的sendBroadcast()方法是通過handler()發(fā)送一個(gè)Message實(shí)現(xiàn)的。
    2. 相比系統(tǒng)廣播是通過Binder實(shí)現(xiàn)的,本地廣播會更加高效。別人應(yīng)用無法向自己的App發(fā)送廣播,而自己App發(fā)送的廣播也不會離開自己的App。
    3. LocalBroadcastManager 內(nèi)部協(xié)作主要是靠兩個(gè)Map集合:mReceiversmActions,當(dāng)然還有一個(gè)List集合mPendingBroadcasts,主要是存儲待接收的廣播對象。

9.全局廣播的缺點(diǎn)

  • App被反編譯獲得Action后,會被植入廣告、數(shù)據(jù)泄露。

10.BroadcastReceiver 和 LocalBroadcastReceiver 區(qū)別

  • BroadcastReceiver跨應(yīng)用廣播,利用Binder機(jī)制實(shí)現(xiàn)。
  • LocalBroadcastReceiver應(yīng)用內(nèi)廣播,利用Handler實(shí)現(xiàn),利用了IntentFilter的match功能,提供消息的發(fā)布與接收功能,實(shí)現(xiàn)應(yīng)用內(nèi)通信,效率比較高。


11.Broadcast Receiver能在onReceive中執(zhí)行耗時(shí)任務(wù)嗎?

BroadcastReceiver 在 10 秒內(nèi)沒有執(zhí)行完畢,Android 會認(rèn)為該程序無響應(yīng)ANR,所以在 onReceive 通常是不能開啟線程的,一般是通過 service 或者 IntentService 來處理。


12.BroadCastReceiver 的生命周期

  • a. 廣播接收者的生命周期非常短暫的,在接收到廣播的時(shí)候創(chuàng)建,onReceive()方法結(jié)束之后銷毀;
  • b. 廣播接收者中不要做一些耗時(shí)的工作,否則會彈出 Application No Response應(yīng)用無響應(yīng)對話框;
  • c. 最好也不要在廣播接收者中創(chuàng)建子線程做耗時(shí)的工作,因?yàn)閺V播接收者被銷毀后進(jìn)程就成為了空進(jìn)程,很容易被系統(tǒng)殺掉;
  • d. 耗時(shí)的較長的工作最好放在服務(wù)中完成;

13.廣播傳輸?shù)臄?shù)據(jù)是否有限制,是多少,為什么要限制?

  • Broadcast廣播通過Intent來傳輸數(shù)據(jù),而Intent的數(shù)據(jù)大小限制為小于1MB,如果大于等于1MB都會出現(xiàn)異常。

  • Intent攜帶信息的大小其實(shí)是受Binder限制,Binder傳遞緩存有一個(gè)限定大小,通常是1Mb。但同一個(gè)進(jìn)程中所有的傳輸共享緩存空間。多個(gè)地方在進(jìn)行傳輸時(shí),即時(shí)它們各自傳輸?shù)臄?shù)據(jù)不超出大小限制,TransactionTooLargeException異常也可能會被拋出。

  • 參考文章:https://blog.csdn.net/u011033906/article/details/89316543


本文參考資料:

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

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容