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

內(nèi)容目錄

  1. 廣播的定義
  2. 廣播的用途(信息傳輸與共享通知
  3. 廣播的使用場(chǎng)景
  4. 廣播主要的種類(普通廣播诡右、有序廣播本地廣播
  5. 注冊(cè)廣播接收 (靜態(tài)接收動(dòng)態(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ù)了弄痹,以便做出一些處理。比如說(shuō)攔截系統(tǒng)短信嵌器,攔截騷擾電話等肛真。
  2. 作為通知的作用,比如在 Service 中要通知主程序爽航、更新主程序的 UI 等蚓让,因?yàn)?Service 是沒(méi)有界面的,所以不能直接獲得主程序中的控件讥珍,這樣我們就只能在主程序中實(shí)現(xiàn)一個(gè)廣播接收者專門用來(lái)接收service發(fā)過(guò)來(lái)的數(shù)據(jù)和通知了历极。

3.廣播的使用場(chǎng)景

  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í)刻收到這條廣播消息。效率高觅赊,沒(méi)有先后順序右蕊,無(wú)法截?cái)唷儆谌謴V播吮螺。調(diào)用 sendBroadcast()發(fā)送饶囚,最常用的廣播帕翻。

  • 有序廣播Ordered Broadcast同步執(zhí)行的廣播,發(fā)出去的廣播會(huì)被廣播接收者按照順序接收萝风,廣播接收者按照Priority屬性值從大-小排序嘀掸,Priority屬性相同者,動(dòng)態(tài)注冊(cè)的廣播優(yōu)先规惰,廣播接收者還可以選擇對(duì)廣播進(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)勢(shì)體現(xiàn)在:安全性高 & 效率高贪磺。對(duì)于LocalBroadcastManager方式發(fā)送的應(yīng)用內(nèi)廣播硫兰,只能通過(guò)LocalBroadcastManager動(dòng)態(tài)注冊(cè),不能靜態(tài)注冊(cè)寒锚。調(diào)用sendBroadcast發(fā)送劫映。


4、注冊(cè)廣播接收 (靜態(tài)和動(dòng)態(tài))

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

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

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

  • 靜態(tài)注冊(cè):將廣播寫在 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 不能做過(guò)多的耗時(shí)操作衔掸,10秒沒(méi)響應(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 動(dòng)態(tài)注冊(cè)

  • 動(dòng)態(tài)注冊(cè) : 自定義類繼承 BroadcastReceiver,然后重寫具體實(shí)現(xiàn)onReceive()振愿。在代碼中調(diào)用registerReceiver()注冊(cè)來(lái)進(jìn)行廣播的注冊(cè)捷犹。必須在 onDestroy 中調(diào)用unregisterReceiver()方法弛饭,否則會(huì)引起內(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()中要取消注冊(cè),否則會(huì)引起內(nèi)存泄漏仅炊。
    protected void onDestroy() {
        unregisterReceiver(networkChangeReceiver);
    }
    //ChangeReceiver就是接收后會(huì)怎么樣怎么樣
    class myBroadcastReceiver extends BroadcastReceiver {
        public void onReceive(Context context, Intent intent){
        //to do
        }
     }

5斗幼、廣播的發(fā)送

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

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

2.有序廣播(同步)

  • 定義:發(fā)送出去的廣播被廣播接收者按照先后順序接收
  • 接收廣播的順序規(guī)則(同時(shí)面向靜態(tài)和動(dòng)態(tài)注冊(cè)的廣播接受者)
    • 按照Priority屬性值從大-小排序;
    • Priority屬性相同者抚垄,動(dòng)態(tài)注冊(cè)的廣播優(yōu)先蜕窿;
  • 特點(diǎn):
    • 接收廣播按順序接收;
    • 先接收的廣播接收者可以對(duì)廣播進(jìn)行截?cái)?/code>呆馁,即后接收的廣播接收者不再接收到此廣播桐经;
    • 先接收的廣播接收者可以對(duì)廣播進(jìn)行修改,那么后接收的廣播接收者將接收到被修改后的廣播
//通過(guò)sendOrderBroadcast發(fā)送
Intent intent = new Intent("com.example.songsong.MY_BROADCAST");
sendOrderBroadcast(intent,null);
    /*給廣播接收器設(shè)置優(yōu)先級(jí) */
    <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)行動(dòng)態(tài)注冊(cè)本地廣播
localBroadcastManager.registerReceiver(localReceiver, intentFilter);
//接收4:在onDestroy中取消注冊(cè)
localBroadcastManager.unregisterReceiver(localReceiver);
//接收5:在localReceiver中繼承BroadcastReceiver并重寫onReceiver浙滤。
...

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

  1. 自定義廣播接收者 BroadcastReceiver阴挣,并復(fù)寫 onRecvice();
  2. 通過(guò) Binder 機(jī)制向 AMS(Activity Manager Service) 注冊(cè)廣播;
  3. 通過(guò) 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é)啟動(dòng)四大組件啟動(dòng)切換調(diào)度拜隧。


8.本地廣播 LocalBroadcastManager

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

  • 沖突

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

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

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

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

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

  • App被反編譯獲得Action后旷坦,會(huì)被植入廣告、數(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)沒(méi)有執(zhí)行完畢娩井,Android 會(huì)認(rèn)為該程序無(wú)響應(yīng)ANR,所以在 onReceive 通常是不能開啟線程的似袁,一般是通過(guò) service 或者 IntentService 來(lái)處理洞辣。


12.BroadCastReceiver 的生命周期

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

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

  • Broadcast廣播通過(guò)Intent來(lái)傳輸數(shù)據(jù)卷胯,而Intent的數(shù)據(jù)大小限制為小于1MB,如果大于等于1MB都會(huì)出現(xiàn)異常威酒。

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

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


本文參考資料:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市吓著,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌送挑,老刑警劉巖绑莺,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異惕耕,居然都是意外死亡纺裁,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門司澎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)欺缘,“玉大人,你說(shuō)我怎么就攤上這事挤安⊙枋猓” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵蛤铜,是天一觀的道長(zhǎng)嫩絮。 經(jīng)常有香客問(wèn)我,道長(zhǎng)围肥,這世上最難降的妖魔是什么剿干? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮穆刻,結(jié)果婚禮上置尔,老公的妹妹穿的比我還像新娘。我一直安慰自己氢伟,他們只是感情好榜轿,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布幽歼。 她就那樣靜靜地躺著,像睡著了一般差导。 火紅的嫁衣襯著肌膚如雪试躏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天设褐,我揣著相機(jī)與錄音颠蕴,去河邊找鬼。 笑死助析,一個(gè)胖子當(dāng)著我的面吹牛犀被,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播外冀,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼寡键,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了雪隧?” 一聲冷哼從身側(cè)響起西轩,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎脑沿,沒(méi)想到半個(gè)月后藕畔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡庄拇,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年注服,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片措近。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡溶弟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瞭郑,到底是詐尸還是另有隱情辜御,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布屈张,位于F島的核電站我抠,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏袜茧。R本人自食惡果不足惜菜拓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望笛厦。 院中可真熱鬧纳鼎,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至逗宁,卻和暖如春映九,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背瞎颗。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工件甥, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人哼拔。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓引有,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親倦逐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子譬正,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容