Android 廣播機(jī)制

目錄

一.概述

二.注冊(cè)廣播

三.發(fā)送廣播

四.處理廣播

五.廣播的優(yōu)先級(jí)

一苟翻、概述

廣播(Broadcast)機(jī)制用于進(jìn)程/線程間通信韵卤,因此在我們應(yīng)用程序內(nèi)發(fā)出的廣播,其他的應(yīng)用程序應(yīng)該也是可以收到的崇猫。廣播分為廣播發(fā)送和廣播接收兩個(gè)過程沈条,其中廣播接收者BroadcastReceiver便是Android四大組件之一。

BroadcastReceiver分為兩類:
  • 靜態(tài)廣播接收者:通過AndroidManifest.xml的標(biāo)簽來申明的BroadcastReceiver诅炉。
  • 動(dòng)態(tài)廣播接收者:通過AMS.registerReceiver()方式注冊(cè)的BroadcastReceiver蜡歹,動(dòng)態(tài)注冊(cè)更為靈活,可在不需要時(shí)通過unregisterReceiver()取消注冊(cè)汞扎。

從廣播發(fā)送方式可分為三類:

  • 普通廣播:通過Context.sendBroadcast()發(fā)送季稳,可并行處理
  • 有序廣播:通過Context.sendOrderedBroadcast()發(fā)送,串行處理
  • Sticky廣播:通過Context.sendStickyBroadcast()發(fā)送

二.注冊(cè)廣播

1.靜態(tài)注冊(cè)廣播

常駐型廣播澈魄,這個(gè)廣播接收者會(huì)在程序運(yùn)行的整個(gè)過程中一直存在景鼠,不會(huì)被注銷掉,當(dāng)程序被殺掉后不會(huì)再接收到廣播了痹扇。它的注冊(cè)方式就是在你應(yīng)用程序的AndroidManifast.xml 中進(jìn)行注冊(cè)铛漓,這種注冊(cè)方式通常又被稱作靜態(tài)注冊(cè)。這種方式可以理解為通過清單文件注冊(cè)的廣播是交給操作系統(tǒng)去處理的鲫构。在Manifest.xml中注冊(cè)廣播浓恶,是一種比較推薦的方法,因?yàn)樗恍枰謩?dòng)注銷廣播(如果廣播未注銷结笨,程序退出時(shí)可能會(huì)出錯(cuò))包晰。

<receiver android:name=".receiver.WakeReceiver">
        <intent-filter>
            <!--   利用系統(tǒng)廣播拉活-->
            <action android:name="android.intent.action.BOOT_COMPLETED" /> <!-- Android開機(jī)廣播-->
            <!-- 系統(tǒng)廣播,接收打電話的廣播 炕吸,這個(gè)需要配置權(quán)限 --> 
            <action android:name="android.intent.action.NEW_OUTGOING_CALL" /> 
            <action android:name="android.intent.action.USER_PRESENT" /><!--鎖屏解鎖-->
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /><!--網(wǎng)絡(luò)變化-->
            <action android:name="com.wake.gray" /><!-- 自定義廣播 -->
        </intent-filter>
    </receiver>

2.動(dòng)態(tài)注冊(cè)廣播

動(dòng)態(tài)注冊(cè)廣播不是常駐型廣播伐憾,也就是說廣播跟隨程序的生命周期

步驟如下:

實(shí)例化自定義的廣播接收者

實(shí)例化意圖過濾器,并設(shè)置要過濾的廣播類型(如赫模,我們接收收到短信系統(tǒng)發(fā)出的廣播)

使用Context的registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)方法注冊(cè)廣播

public static final String BROADCAST_ACTION = "com.example.corn";
private BroadcastReceiver mBroadcastReceiver;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

 mBroadcastReceiver = new MyBroadcastReceiver();
 IntentFilter intentFilter = new IntentFilter();
 intentFilter.addAction(BROADCAST_ACTION);
 registerReceiver(mBroadcastReceiver, intentFilter);
}

@Override
protected void onDestroy() {
 super.onDestroy();
 unregisterReceiver(mBroadcastReceiver);
}

3.兩種注冊(cè)廣播的區(qū)別

第一種是常駐型树肃,也就是說當(dāng)應(yīng)用程序關(guān)閉后,如果有信息廣播來瀑罗,程序也會(huì)被系統(tǒng)調(diào)用自動(dòng)運(yùn)行胸嘴,比如靜態(tài)注冊(cè)實(shí)現(xiàn)開機(jī)啟動(dòng)

第二種不是常駐型廣播雏掠,也就是說廣播跟隨程序的生命周期。

動(dòng)態(tài)注冊(cè)的廣播的優(yōu)先級(jí)高于靜態(tài)注冊(cè)的廣播

三.發(fā)送廣播

根據(jù)廣播的發(fā)送方式劣像,可以將其分為以下幾種類型:

  • Normal Broadcast:普通廣播

  • Ordered broadcast:有序廣播

  • Sticky Broadcast:粘性廣播(在 android 5.0/api 21中deprecated,不再推薦使用乡话,相應(yīng)的還有粘性有序廣播,同樣已經(jīng)deprecated)

1.普通廣播

普通廣播(Normal broadcasts)是一種完全異步執(zhí)行的廣播驾讲,在廣播發(fā)出之后蚊伞,所有的廣播接收器幾乎都會(huì)在同一時(shí)刻接收到這條廣播消息,因此它們之間沒有任何先后順序可言吮铭。這種廣播的效率會(huì)比較高时迫,但同時(shí)也意味著它是無法被截?cái)嗟?/p>

Context類提供兩個(gè)方法可以用于發(fā)送普通廣播:

sendBroadcast(Intent intent);

sendBroadcast(Intent intent, String receiverPermission);
差別是第二個(gè)設(shè)置權(quán)限。

發(fā)給特定的用戶:

sendBroadcastAsUser(Intent intent, UserHandle user);

sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission);

2.有序廣播

有序廣播(Ordered broadcasts)則是一種同步執(zhí)行的廣播谓晌,在廣播發(fā)出之后掠拳,同一時(shí)刻只會(huì)有一個(gè)廣播接收器能夠收到這條廣播消息,當(dāng)這個(gè)廣播接收器中的邏輯執(zhí)行完畢后纸肉,廣播才會(huì)繼續(xù)傳遞溺欧。所以此時(shí)的廣播接收器是有先后順序的,優(yōu)先級(jí)高的廣播接收器就可以先收到廣播消息柏肪,并且前面的廣播接收器還可以截?cái)嗾趥鬟f的廣播姐刁,這樣后面的廣播接收器就無法收到廣播消息了,只是其的主要發(fā)送方式變?yōu)椋簊endOrderedBroadcast(intent, receiverPermission, ...)烦味。

  • 1>多個(gè)具當(dāng)前已經(jīng)注冊(cè)且有效的BroadcastReceiver接收有序廣播時(shí)聂使,是按照先后順序接收的,先后順序判定標(biāo)準(zhǔn)遵循為:將當(dāng)前系統(tǒng)中所有有效的動(dòng)態(tài)注冊(cè)和靜態(tài)注冊(cè)的BroadcastReceiver按照priority屬性值從大到小排序谬俄,對(duì)于具有相同的priority的動(dòng)態(tài)廣播和靜態(tài)廣播柏靶,動(dòng)態(tài)廣播會(huì)排在前面。

  • 2>先接收的BroadcastReceiver可以對(duì)此有序廣播進(jìn)行截?cái)嗬B郏购竺娴腂roadcastReceiver不再接收到此廣播屎蜓,也可以對(duì)廣播進(jìn)行修改,使后面的BroadcastReceiver接收到廣播后解析得到錯(cuò)誤的參數(shù)值钥勋。當(dāng)然炬转,一般情況下,不建議對(duì)有序廣播進(jìn)行此類操作算灸,尤其是針對(duì)系統(tǒng)中的有序廣播返吻。

五.App應(yīng)用內(nèi)廣播(Local Broadcast)

我們發(fā)送和接收的廣播全部都是屬于系統(tǒng)全局廣播,即發(fā)出的廣播可以被其他任何的任何應(yīng)用程序接收到乎婿,并且我們也可以接收來自于其他任何應(yīng)用程序的廣播。這樣就很容易會(huì)引起安全性的問題街佑,比如說我們發(fā)送的一些攜帶關(guān)鍵性數(shù)據(jù)的廣播有可能被其他的應(yīng)用程序截獲谢翎,或者其他的程序不停地向我們的廣播接收器里發(fā)送各種垃圾廣播捍靠。為了能夠簡單地解決廣播的安全性問題,Android 引入了一套本地廣播機(jī)制森逮,使用這個(gè)機(jī)制發(fā)出的廣播只能夠在應(yīng)用程序的內(nèi)部進(jìn)行傳遞榨婆,并且廣播接收器也只能接收來自本應(yīng)用程序發(fā)出的廣播,這樣所有的安全性問題就都不存在了褒侧。

1.使用它發(fā)送的廣播將只在自身App內(nèi)傳播良风,因此你不必?fù)?dān)心泄漏隱私數(shù)據(jù)

2.其它App無法對(duì)你的App發(fā)送該廣播,因?yàn)槟愕腁pp根本就不可能接收到非自身應(yīng)用發(fā)送的該廣播闷供,因此你不必?fù)?dān)心有安全漏洞可以利用

3.比系統(tǒng)的全局廣播更加高效
/registerReceiver(mBroadcastReceiver, intentFilter);
//注冊(cè)應(yīng)用內(nèi)廣播接收器
localBroadcastManager = LocalBroadcastManager.getInstance(this);
localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);

localBroadcastManager.unregisterReceiver(mBroadcastReceiver);
Intent intent = new Intent();
intent.setAction(BROADCAST_ACTION);
intent.putExtra("name", "qqyumidi");
//sendBroadcast(intent);
//發(fā)送應(yīng)用內(nèi)廣播
localBroadcastManager.sendBroadcast(intent);

注:對(duì)于LocalBroadcastManager方式發(fā)送的應(yīng)用內(nèi)廣播烟央,只能通過LocalBroadcastManager動(dòng)態(tài)注冊(cè)的ContextReceiver才有可能接收到(靜態(tài)注冊(cè)或其他方式動(dòng)態(tài)注冊(cè)的ContextReceiver是接收不到的)。

六.廣播的優(yōu)先級(jí)

有序廣播的接收者按照一定的優(yōu)先級(jí)進(jìn)行消息的接收歪脏。如:A,B,C的優(yōu)先級(jí)依次降低疑俭,那么消息先傳遞給A,在傳遞給B婿失,最后傳遞給C钞艇。優(yōu)先級(jí)別聲明在中,取值為[-1000,1000]數(shù)值越大優(yōu)先級(jí)別越高豪硅。優(yōu)先級(jí)也可通過filter.setPriority(10)方式設(shè)置哩照。

另外Ordered broadcasts的接收者可以通過abortBroadcast()的方式取消廣播的傳播,也可以通過setResultData和setResultExtras方法將處理的結(jié)果存入到Broadcast中懒浮,傳遞給下一個(gè)接收者飘弧。然后,下一個(gè)接收者通過getResultData()和getResultExtras(true)接收高優(yōu)先級(jí)的接收者存入的數(shù)據(jù)嵌溢。例如:

<receiver
android:name=".FirstReceiver">
<intent-filter
    android:priority="999">
    <action android:name="com.mark.broadcast.receiver" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
 <receiver android:name=".MyReceiver" >
<intent-filter
    android:priority="1000">
    <action android:name="com.mark.broadcast.receiver" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>

如上兩個(gè)receiver我們分別設(shè)置為priority為999,和1000眯牧,及時(shí)MyReceiver是后注冊(cè)的,但是其優(yōu)先級(jí)比FirstReceiver高赖草,則MyReceiver會(huì)先處理廣播学少。

參考

Android Broadcast廣播機(jī)制分析

LocalBroadcastManager—?jiǎng)?chuàng)建更高效、更安全的廣播

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末秧骑,一起剝皮案震驚了整個(gè)濱河市版确,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌乎折,老刑警劉巖绒疗,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異骂澄,居然都是意外死亡吓蘑,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來磨镶,“玉大人溃蔫,你說我怎么就攤上這事×彰ǎ” “怎么了伟叛?”我有些...
    開封第一講書人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長脐嫂。 經(jīng)常有香客問我统刮,道長,這世上最難降的妖魔是什么账千? 我笑而不...
    開封第一講書人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任侥蒙,我火速辦了婚禮,結(jié)果婚禮上蕊爵,老公的妹妹穿的比我還像新娘辉哥。我一直安慰自己,他們只是感情好攒射,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開白布醋旦。 她就那樣靜靜地躺著,像睡著了一般会放。 火紅的嫁衣襯著肌膚如雪饲齐。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,245評(píng)論 1 299
  • 那天咧最,我揣著相機(jī)與錄音捂人,去河邊找鬼。 笑死矢沿,一個(gè)胖子當(dāng)著我的面吹牛滥搭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播捣鲸,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼瑟匆,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了栽惶?” 一聲冷哼從身側(cè)響起愁溜,我...
    開封第一講書人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎外厂,沒想到半個(gè)月后馋袜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體茧泪,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年刚照,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了稻爬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出意荤,到底是詐尸還是另有隱情,我是刑警寧澤只锻,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站紫谷,受9級(jí)特大地震影響齐饮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜笤昨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一祖驱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瞒窒,春花似錦捺僻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至拔稳,卻和暖如春葛峻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背巴比。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來泰國打工术奖, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人轻绞。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓采记,卻偏偏與公主長得像,于是被迫代替她去往敵國和親政勃。 傳聞我的和親對(duì)象是個(gè)殘疾皇子唧龄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354

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