Android系統(tǒng)的四大組件還有一種BroadcastReceiver,這種組件本質(zhì)上就是一個全局監(jiān)聽器,用于監(jiān)聽全局的廣播消息。由于BroadcastReceiver是一個全局監(jiān)聽器,因此它可以非常方便地實(shí)現(xiàn)系統(tǒng)中不同組件之間的通訊。例如,我們希望客戶端程序與startService()方法啟動的Service之間通訊,就可以借助于BroadcastReceiver來實(shí)現(xiàn)。
10.7.1 BroadcastReceiver用于接收程序(包括用戶開發(fā)的程序和系統(tǒng)內(nèi)建的程序)所發(fā)出的Broadcast Intent,與應(yīng)用程序啟動Activity、Service相同的是,程序啟動BroadcastReceiver也只需要兩步。
1、創(chuàng)建需要啟動的BroadcastReceiver的Intent。
2、調(diào)用Content的sendBroadcast()或sendOrderdBroadcast()方法啟動指定的BroadcastReceiver。
與Activity、Service具有完整的生命周期不同,BroadcastReceiver本質(zhì)上只是一個系統(tǒng)級的監(jiān)聽器--------它專門負(fù)責(zé)監(jiān)聽個程序所發(fā)出的Broadcast。
提示:
前面介紹的各種OnXxxListener只是程序級別的監(jiān)聽器,這些監(jiān)聽器運(yùn)行在指定程序所在進(jìn)程中,當(dāng)程序退出時,onXxxListener監(jiān)聽器也就隨之關(guān)閉了。但BroadcastReceiver屬于系統(tǒng)級的監(jiān)聽器,他擁有自己的進(jìn)程,只要存在與之匹配的Intent被廣播出來,BroadcastReceiver就會被激發(fā)。
由于BroadcastReceiver本質(zhì)上屬于一個監(jiān)聽器,因此實(shí)現(xiàn)BroadcastReceiver的方法也十分簡單,只要重寫B(tài)roadcastReceiver的onReceive(Content content,Intent intent)方法即可。
一旦實(shí)現(xiàn)了BroadcastReceiver,接下來就應(yīng)該指定該BroadcastReceiver能匹配的Intent,此時有兩種方式。
1、使用代碼進(jìn)行指定,調(diào)用BroadcastReceiver的Content的registerReceiver(BroadcastReceiver receiver,IntentFilter filter)方法指定。例如如下代碼

2、在AndroidManifest.xml文件中配置。例如如下代碼:

每次系統(tǒng)Broadcast事件發(fā)生后,系統(tǒng)就會創(chuàng)建對應(yīng)的BroadcastReceiver實(shí)例,并自動觸發(fā)它的onReceive()方法,onReceive()方法執(zhí)行完后,BroadcastReceiver實(shí)例就會被銷毀。
提示:
與Activity組件不同的是,當(dāng)系統(tǒng)通過Intent啟動指定了Activity組件時,如果系統(tǒng)沒有找到合適的Activity組件,則會導(dǎo)致程序異常終止;單系統(tǒng)通過Intent激發(fā)BroadcastReceiver時,如果找不到合適的BroadcastReceiver組件,應(yīng)用不會有任何問題 。
如果BroadcastReceiver的onReceive()方法不能在10秒內(nèi)執(zhí)行完成,Android會認(rèn)為該程序無響應(yīng),所以不要在BroadcastReceiver的onReceive()方法里面執(zhí)行一些耗時操作;否則會彈出ANR(Application No Response)對話框。
如果確實(shí)需要根據(jù)Broadcast來完成意向比較耗時的操作,則可以考慮通過Intent啟動一個Service來完成該操作。不應(yīng)該考慮使用新線程去完成耗時操作,因?yàn)锽roadcastReceiver本省的生命周期很短,可能出現(xiàn)的情況是子線程還沒有結(jié)束,BroadcastReceiver就已經(jīng)退出了。
如果BroadcastReceiver所在的進(jìn)程結(jié)束了,雖然該進(jìn)程內(nèi)還有用戶啟動的新線程,但由于該進(jìn)程內(nèi)不包含任何活動組件,因此系統(tǒng)可能在內(nèi)存緊張時優(yōu)先結(jié)束該進(jìn)程。這樣就可能導(dǎo)致BroadcastReceiver啟動的子線程不能執(zhí)行完成。
10.7.2 ?發(fā)送廣播
在程序中發(fā)送廣播十分簡單,只要調(diào)用Content的sendBroadast(Intent intent)方法即可,這條廣播將會啟動intent參數(shù)所對應(yīng)的BroadcastReceiver。
下面簡單的程序示范了如何發(fā)送Broadcast、使用BroadcastReceiver接收廣播。該程序的Activity界面中包含一個按鈕,當(dāng)用戶單擊按鈕時程序會向外發(fā)送一條廣播,該程序的代碼如下。

上面的程序中創(chuàng)建了一個Intent對象,并使用該Intent對象對外發(fā)送一條廣播。個hi按行層序所使用的BroadcastReceiver代碼如下。

真能夠如上面的程序中看到的,當(dāng)符合該action的廣播出現(xiàn)時,該廣播的onReceive()方法將會被處罰,從而在該方法中顯示廣播攜帶的消息。
上面發(fā)送廣播的程序中指定發(fā)送廣播時所用的Intent的Action為org.cxrazyit.action.CRAZY_BROADCAST,這就需要配置上面的BroadcastReceiver應(yīng)監(jiān)聽Action為該字符串的Intent,在AndroidManifest.xml文件中增加如下配置即可:

可以運(yùn)行一下試試看
10.7.3 有序廣播
Broadcast被分為如下兩種。
1、Normal Broadcast(普通廣播):Normal Broadcast是完全異步的,可以在同一時刻(邏輯上)被所有的接收者接收到,消息傳遞的效率比較高。但缺點(diǎn)是接收者不能將處理結(jié)果傳遞給下一個接收者,并卻無法終止Broadcast Intent的傳播。
2、Ordered Broadcast(有序廣播):Ordered Broadcast的接收者將預(yù)先聲明的優(yōu)先級依次接收Broadcast。比如A的級別高于B、B的級別高于C,那么Broadcast先傳給A,再傳給B。最后傳給C。優(yōu)先級別聲明在<intent-filter.....>元素的android:priority屬性中,數(shù)越大級別越高,取值范圍-1000-1000,也可以調(diào)用IntentFilter對象的setPriority()設(shè)置優(yōu)先級別。Ordered Broadcast接收者可以終止Broadcast Intent的傳播。Broadcast Intent的出阿伯一旦終止,后面的接收者就無法接收到Broadcast。另外,Ordered Broadcast的接收者可以將數(shù)據(jù)傳遞給下一個結(jié)合搜著,比如A得到Broadcast后,可以往它的結(jié)果對象中存入數(shù)據(jù),當(dāng)Broadcast傳給B,B可以從A的結(jié)果對象得到A存入的數(shù)據(jù)。
Content提供兩個方法用于發(fā)送廣播。
sendBroadcast() :發(fā)送Normal Broadcast。
sendOrderedBroadcast():發(fā)送Ordered Broadcast
對于Ordered?Broadcast而言,系統(tǒng)會根據(jù)接收者聲明的優(yōu)先級別按順序諸葛執(zhí)行接收者,優(yōu)先接受到Broadcast的接收者可以終止Broadcast,調(diào)用BroadcastReceiver的abortBroadcast()
方法即刻終止Broadcast。如果Broadcast背前面的接收者終止,后面的廣播接收者就在也無法獲取到Broadcast了。
不僅如此,對于Ordered Broadcast而言,優(yōu)先接收到Broadcast的接收者可以通過serResultExtras(Bundle)方法將處理結(jié)果存入Broadcast中,然后傳給下一個接收者,下一個接收者通過代碼Bundle bundle = getResultExtras(true)可以獲取上一個接收者存入的數(shù)據(jù)。
提示:
系統(tǒng)接收到短信,發(fā)出Broadcast屬于Ordered ?Broadcast。如果想阻止用戶收到短信,可以通過設(shè)置優(yōu)先級,讓自定義的BroadcastReceiver現(xiàn)貨區(qū)到Broadcast,然后總之Broadcast。
接下來介紹一下發(fā)送廣播的示例,該程序的Activity界面上只有一個普通的按鈕,用于發(fā)送一條有序廣播。該程序代碼如下。

上面程序中的粗體字代碼指定了Intent的Action屬性,再調(diào)用endOrderedBroadcast()方法來發(fā)送有序廣播。對于有序廣播而言,他會按優(yōu)先級依次觸發(fā)每個BroadcastReceiver的onReceive()方法。
下面的程序定義了第一個BroadcastReceiver。

上面的BroadcastReceiver不僅處理了他所接受的消息,而且向處理結(jié)果中存入了Key為first的消息,這個消息將可以被第二個BroadcastReceiver解析出來。
上面的程序中的1號字體代碼用于取消廣播,如果保持這條代碼生效,那么優(yōu)先級比MyReceiver低的BroadcastReceiver都將不會被處罰。
在AndroidManifest.xml文件中部署該BroadcastReceiver,并制定其優(yōu)先級為20.配置片段如下:

接下來微程序提供第二個BroadcastReceiver,這個BroadcastReceiver將會解析前一個BroadcastReceiver所存入的Key為first的消息。該BroadcastReceiver的代碼如下。

上面程序的代碼用于解析前一個BroadcastReceiver存儲結(jié)果的Key為first的消息,在AndroidManifest.xml文件中配置該BroadcastReceiver,并指定其優(yōu)先級為0.配置片段消息如下:
