目錄
一.概述
二.注冊(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ì)先處理廣播学少。