【转】Android BroadcastReceiver介绍
本文主要介紹BroadcastReceiver的概念、使用、生命周期、安全性、分類、特殊的BroadcastReceiver(本地、粘性、有序、粘性有序廣播)。
示例代碼見(jiàn)BroadcastReceiverDemo,示例APK見(jiàn):TrineaAndroidDemo.apk。
?
1、概念介紹及兩種注冊(cè)方式的區(qū)別
BroadcastReceiver作為Android四大組件之一,不像Activity,沒(méi)有可顯示的界面。BroadcastReceiver包括兩個(gè)概念,廣播發(fā)送者和廣播接收者(Receiver),這里的廣播實(shí)際就是指Intent,程序可以自己發(fā)送廣播自己接收,也可以接受系統(tǒng)或其他應(yīng)用的廣播或是發(fā)送廣播給其他應(yīng)用程序。
發(fā)送者可以通過(guò)類似Context.sendBroadcast接口發(fā)送廣播,接收者通過(guò)Context.registerReceiver()動(dòng)態(tài)注冊(cè)或在AndroidManifest.xml文件中通過(guò)<receiver>標(biāo)簽靜態(tài)注冊(cè),注冊(cè)完成后,當(dāng)發(fā)送者發(fā)送某個(gè)廣播時(shí)系統(tǒng)會(huì)將發(fā)送的廣播(Intent)與系統(tǒng)中所有注冊(cè)的符合條件的接收者(Receiver)?的IntentFilter進(jìn)行匹配,若匹配成功則執(zhí)行相應(yīng)接收者的onReceive函數(shù),匹配規(guī)則見(jiàn)Intent和IntentFilter的匹配規(guī)則。
關(guān)于registerReceiver動(dòng)態(tài)注冊(cè)和通過(guò)<receiver>標(biāo)簽靜態(tài)注冊(cè)廣播的區(qū)別如下:
a.對(duì)bindService的調(diào)用,<receiver>注冊(cè)的廣播,在onReceive結(jié)束后廣播即不存在,所以不能在其中給自己異步傳遞結(jié)果,如bindService而只能使用startService,如果想跟service交互可使用peekService。
b. 手動(dòng)控制。registerReceiver為動(dòng)態(tài)注冊(cè),自己可以手動(dòng)注冊(cè)或是取消注冊(cè);<receiver>標(biāo)簽為靜態(tài)注冊(cè),由系統(tǒng)開(kāi)機(jī)時(shí)自動(dòng)掃描注冊(cè),所以無(wú)法手動(dòng)控制,開(kāi)機(jī)一直運(yùn)行中。
c. 資源消耗不同。registerReceiver可以手動(dòng)控制,所以適當(dāng)?shù)淖?cè)和取消注冊(cè)能節(jié)省系統(tǒng)資源,<receiver>標(biāo)簽系統(tǒng)開(kāi)機(jī)后一直有效。
d. 有效期不同。通過(guò)registerReceiver注冊(cè)的BroadcastReceiver在對(duì)其進(jìn)行注冊(cè)的Context對(duì)象"銷(xiāo)毀"了或者調(diào)用了unregisterReceiver方法時(shí)也就失效了,而通過(guò)<receiver>標(biāo)簽注冊(cè)的BroadcastReceiver只要應(yīng)用程序沒(méi)有被刪除就一直有效。
e. 對(duì)registerReceiver函數(shù)的調(diào)用許可不同。通過(guò)registerReceiver注冊(cè)的BroadcastReceiver在其onReceive函數(shù)中可以再次調(diào)用某個(gè)Context的registerReceiver函數(shù),而通過(guò)<receiver>標(biāo)簽注冊(cè)的BroadcastReceiver不允許再調(diào)用某個(gè)Context的registerReceiver函數(shù)?。
f. 使用情況不同。對(duì)于自己發(fā)送和接受的廣播可以通過(guò)registerReceiver注冊(cè),對(duì)于系統(tǒng)常用廣播的接收通常用<receiver>標(biāo)簽注冊(cè)。
?
2、使用舉例
BroadcastReceiverDemoR.layout.broadcast_receiver_demo的內(nèi)容為一個(gè)簡(jiǎn)單的id為sendBroadcast的Button?
從上面代碼可以看到我們
a. 新建BroadcastReceiver只需要繼承BroadcastReceiver并重寫(xiě)OnReceiver函數(shù),加上自己的處理邏輯。
b. 通過(guò)registerReceiver注冊(cè)廣播,通過(guò)unregisterReceiver取消注冊(cè)廣播,通過(guò)sendBroadcast發(fā)送廣播。
其中注冊(cè)和取消注冊(cè)廣播放在了OnResume和OnPause函數(shù)中可以有效的節(jié)省系統(tǒng)消耗。如果希望廣播一直運(yùn)行中可以在Activity的OnCreate函數(shù)中注冊(cè),在OnDestrory函數(shù)中取消注冊(cè)。
這里的MyBroadcastReceiver也可以在AndroidManifest.xml文件中靜態(tài)注冊(cè),這樣程序安裝后便一直運(yùn)行中。比如希望接收到短信到來(lái)時(shí)的廣播,如下:
<receiver android:name="MyBroadcastReceiver"><intent-filter><action android:name="android.provider.Telephony.SMS_RECEIVED" /></intent-filter> </receiver>?
3、生命周期
BroadcastReceiver在onReceive函數(shù)執(zhí)行結(jié)束后即表示生命周期結(jié)束,所以不適合在onReceive中做綁定服務(wù)操作,結(jié)束后若某個(gè)進(jìn)程只含有該BroadcastReceiver,則優(yōu)先級(jí)將降低可能被系統(tǒng)回收,所以BroadcastReceiver中不適合做一些異步操作,如新建線程下載數(shù)據(jù),BroadcastReceiver結(jié)束后可能在異步操作完成前進(jìn)程已經(jīng)被系統(tǒng)kill。
同時(shí)由于ANR限制BroadcastReceiver的onReceive函數(shù)必須在10秒內(nèi)完成,而且onReceive默認(rèn)會(huì)在主線程中執(zhí)行,所以BroadcastReceiver中不適合做一些耗時(shí)操作,對(duì)于耗時(shí)操作需要交給service處理,比如網(wǎng)絡(luò)或數(shù)據(jù)庫(kù)耗時(shí)操作、對(duì)話框的顯示(因?yàn)楝F(xiàn)實(shí)時(shí)間可能超時(shí),用Notification代替)。
?
4、安全性
BroadcastReceiver的設(shè)計(jì)初衷就是從全局考慮的,可以方便應(yīng)用程序和系統(tǒng)、應(yīng)用程序之間、應(yīng)用程序內(nèi)的通信,所以對(duì)單個(gè)應(yīng)用程序而言BroadcastReceiver是存在安全性問(wèn)題的,相應(yīng)問(wèn)題及解決如下:
a、當(dāng)應(yīng)用程序發(fā)送某個(gè)廣播時(shí)系統(tǒng)會(huì)將發(fā)送的Intent與系統(tǒng)中所有注冊(cè)的BroadcastReceiver的IntentFilter進(jìn)行匹配,若匹配成功則執(zhí)行相應(yīng)的onReceive函數(shù)。可以通過(guò)類似sendBroadcast(Intent, String)的接口在發(fā)送廣播時(shí)指定接收者必須具備的permission。或通過(guò)Intent.setPackage設(shè)置廣播僅對(duì)某個(gè)程序有效。
?
b. 當(dāng)應(yīng)用程序注冊(cè)了某個(gè)廣播時(shí),即便設(shè)置了IntentFilter還是會(huì)接收到來(lái)自其他應(yīng)用程序的廣播進(jìn)行匹配判斷。對(duì)于動(dòng)態(tài)注冊(cè)的廣播可以通過(guò)類似registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler)的接口指定發(fā)送者必須具備的permission,對(duì)于靜態(tài)注冊(cè)的廣播可以通過(guò)android:exported="false"屬性表示接收者對(duì)外部應(yīng)用程序不可用,即不接受來(lái)自外部的廣播。
?
c.上面兩個(gè)問(wèn)題其實(shí)都可以通過(guò)LocalBroadcastManager來(lái)解決,LocalBroadcastManager只會(huì)將廣播限定在當(dāng)前應(yīng)用程序中,具體見(jiàn)下面6特殊的BroadcastReceiver中的介紹
?
d.使用android:protectionLevel
?
5、分類
BroadcastReceiver可以分為普通和有序兩種,下面6特殊BroadcastReceiver中介紹了其他一些種類。
通過(guò)Context.sendBroadcast發(fā)送的廣播即為普通廣播,對(duì)于普通廣播接收者接收到它的順序是不定的,所以接收者接收到后無(wú)法使用其他接收者對(duì)它的處理結(jié)果也無(wú)法停止它。
?
通過(guò)Context.sendOrderedBroadcast發(fā)送的廣播即為有序廣播,與普通廣播的不同在于,接收者是有序接收到廣播的并且可以對(duì)廣播進(jìn)行修改或是取消廣播向下傳遞。系統(tǒng)根據(jù)接收者定義的優(yōu)先級(jí)順序決定哪個(gè)接收者先接收到它,接收者處理完后可以將結(jié)果傳遞給優(yōu)先級(jí)低的接收者也可以停止廣播使得其他優(yōu)先級(jí)低的接收者無(wú)法接收到該廣播。優(yōu)先級(jí)通過(guò)android:priority屬性定義,數(shù)值越大優(yōu)先級(jí)別越高,取值范圍:-1000到1000,雖然API文檔介紹對(duì)sendBroadcast發(fā)送的廣播無(wú)效,不過(guò)本人測(cè)試同樣有效,相同優(yōu)先級(jí)的接收者接收到廣播的順序隨機(jī)。Android系統(tǒng)收到短信、接到電話后發(fā)送的廣播都是有序廣播,所以可以進(jìn)行短信或電話的攔截,即取消廣播。
PS:有序廣播可以在onReceive函數(shù)中通過(guò)BroadcastReceiver的abortBroadcast接口(這個(gè)接口對(duì)sendBroadcast發(fā)送廣播無(wú)效)取消廣播,通過(guò)接口sendOrderedBroadcast(Intent, String, BroadcastReceiver, android.os.Handler, int, String, Bundle)發(fā)送的廣播即便優(yōu)先級(jí)高的廣播取消了廣播,接口參數(shù)中指定的BroadcastReceiver依然可以在其他接收者處理完后接收到廣播。通過(guò)BroadcastReceiver的getResultExtras接口獲得結(jié)果的Bundle再通過(guò)Bundle的putString和getString方法修改或獲取數(shù)據(jù),可以見(jiàn)本文最后的實(shí)例代碼舉例。
?
6、特殊的BroadcastReceiver
a. LocalBroadcastManager本地廣播
android引入了LocalBroadcastManager解決在第4部分安全性介紹的一些問(wèn)題,LocalBroadcastManager除了能解決BroadcastReceiver進(jìn)程間安全性問(wèn)題外,相對(duì)Context操作的BroadcastReceiver而言還具有更高的運(yùn)行效率。
使用LocalBroadcastManager需要引入Android Support Library,如何引入見(jiàn)Add Support Package。
本地廣播通過(guò)LocalBroadcastManager.getInstance(context).sendBroadcast(intent)發(fā)送廣播,LocalBroadcastManager.getInstance(context).registerReceiver注冊(cè)服務(wù),通過(guò)LocalBroadcastManager.getInstance(context).unregisterReceiver取消注冊(cè)服務(wù),其他同普通廣播.
?
b. Sticky?Broadcast粘性廣播
如果發(fā)送者發(fā)送了某個(gè)廣播,而接收者在這個(gè)廣播發(fā)送后才注冊(cè)自己的Receiver,這時(shí)接收者便無(wú)法接收到剛才的廣播,為此Android引入了StickyBroadcast,在廣播發(fā)送結(jié)束后會(huì)保存剛剛發(fā)送的廣播(Intent),這樣當(dāng)接收者注冊(cè)完Receiver后就可以繼續(xù)使用剛才的廣播。如果在接收者注冊(cè)完成前發(fā)送了多條相同Action的粘性廣播,注冊(cè)完成后只會(huì)收到一條該Action的廣播,并且消息內(nèi)容是最后一次廣播內(nèi)容。系統(tǒng)網(wǎng)絡(luò)狀態(tài)的改變發(fā)送的廣播就是粘性廣播。
粘性廣播通過(guò)Context的sendStickyBroadcast(Intent)接口發(fā)送,需要添加權(quán)限<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
也可以通過(guò)Context的removeStickyBroadcast(Intent?intent)接口移除緩存的粘性廣播。
?
c. OrderedBroadcastReceiver有序廣播
這個(gè)在5分類中已經(jīng)介紹,接收者有序接收廣播并可以修改廣播結(jié)果或是取消廣播,通過(guò)Context的sendOrderedBroadcast接口發(fā)送
?
d. StickyOrderedBroadcast粘性有序廣播
這個(gè)就是粘性廣播和有序廣播的結(jié)合了,通過(guò)Context的sendStickyOrderedBroadcast接口發(fā)送。
?
各種廣播操作Demo示例代碼見(jiàn)BroadcastReceiverDemo,由于本地廣播的support library暫時(shí)下載不了,不包括本地廣播,本地廣播操作間上面介紹。
注意AndroidManifest文件中需要添加粘性廣播操作權(quán)限<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
?
參考:
http://developer.android.com/reference/android/content/BroadcastReceiver.html
from :http://www.cnblogs.com/trinea/archive/2012/11/09/2763182.html
總結(jié)
以上是生活随笔為你收集整理的【转】Android BroadcastReceiver介绍的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: groovy --不注意的小错误(ja
- 下一篇: PingUtil in Android