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