廣播是一種廣泛運用的在應(yīng)用程序之間傳輸信息的機制浙滤,主要用來監(jiān)聽系統(tǒng)或者應(yīng)用發(fā)出的廣播信息泼差,然后根據(jù)廣播信息作為相應(yīng)的邏輯處理,也可以用來傳輸少量组砚、頻率低的數(shù)據(jù)。
在實現(xiàn)開機啟動服務(wù)和網(wǎng)絡(luò)狀態(tài)改變掏颊、電量變化糟红、短信和來電時通過接收系統(tǒng)的廣播讓應(yīng)用程序作出相應(yīng)的處理艾帐。
BroadcastReceiver 自身并不實現(xiàn)圖形用戶界面,但是當它收到某個通知后盆偿, BroadcastReceiver 可以通過啟動 Service 柒爸、啟動 Activity 或是 NotificationMananger 提醒用戶。
使用廣播的注意事項
當系統(tǒng)或應(yīng)用發(fā)出廣播時陈肛,將會掃描系統(tǒng)中的所有廣播接收者揍鸟,通過 action 匹配將廣播發(fā)送給相應(yīng)的接收者,接收者收到廣播后將會產(chǎn)生一個廣播接收者的實例句旱,執(zhí)行其中的 onReceiver() 這個方法阳藻;特別需要注意的是這個實例的生命周期只有10秒,如果10秒內(nèi)沒執(zhí)行結(jié)束 onReceiver() 谈撒,系統(tǒng)將會報錯腥泥。在 onReceiver() 執(zhí)行完畢之后,該實例將會被銷毀啃匿,所以不要在 onReceiver() 中執(zhí)行耗時操作蛔外,也不要在里面創(chuàng)建子線程處理業(yè)務(wù)(因為可能子線程沒處理完,接收者就被回收了溯乒,那么子線程也會跟著被回收掉)夹厌;正確的處理方法就是通過 intent 調(diào)用 Activity 或者 Service 處理業(yè)務(wù)。
BroadcastReceiver的注冊
BroadcastReceiver 的注冊方式有且只有兩種裆悄,一種是靜態(tài)注冊(推薦使用)矛纹,另外一種是動態(tài)注冊,廣播接收者在注冊后就開始監(jiān)聽系統(tǒng)或者應(yīng)用之間發(fā)送的廣播消息光稼。
下面通過例子看一下兩種注冊方式,先定義一個接收短信的 BroadcastReceiver 類:
public class MyBroadcastReceiver extends BroadcastReceiver {
// action 名稱
String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED" ;
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals( SMS_RECEIVED )) {
// 一個receiver可以接收多個action的艾君,即可以有
// 多個intent-filter,需要在 onReceive
// 里面對 intent.getAction(action name) 進行判斷蹬癌。
...
}
}
}
-
靜態(tài)注冊
在 AndroidManifest.xml 的 application 里面定義 receiver 并設(shè)置要接收的action。
< receiver android:name = ".MyBroadcastReceiver" > < intent-filter android:priority = "777" > <action android:name = "android.provider.Telephony.SMS_RECEIVED" /> </ intent-filter > </ receiver >
這里的 priority 取值是 -1000 到 1000 虹茶,值越大優(yōu)先級越高冀瓦,同時注意加上系統(tǒng)接收短信的限權(quán)写烤。
靜態(tài)注冊的廣播接收者是一個常駐在系統(tǒng)中的全局監(jiān)聽器翼闽,當你在應(yīng)用中配置了一個靜態(tài)的 BroadcastReceiver 洲炊,安裝了應(yīng)用后而無論應(yīng)用是否處于運行狀態(tài)感局,廣播接收者都是已經(jīng)常駐在系統(tǒng)中了尼啡。同時應(yīng)用里的所有 receiver 都在清單文件里面,方便查看询微。要銷毀掉靜態(tài)注冊的廣播接收者,可以通過調(diào)用 PackageManager 將 Receiver 禁用撑毛。
-
動態(tài)注冊
在 Activity 中聲明 BroadcastReceiver 的擴展對象,在 onResume 中注冊雌续,onPause 中卸載.
public class MainActivity extends Activity { MyBroadcastReceiver receiver; @Override protected void onResume() { // 動態(tài)注冊廣播 (代碼執(zhí)行到這才會開始監(jiān)聽廣播消息胯杭,并對廣播消息作為相應(yīng)的處理) receiver = new MyBroadcastReceiver(); IntentFilter intentFilter = new IntentFilter( "android.provider.Telephony.SMS_RECEIVED" ); registerReceiver( receiver , intentFilter); super.onResume(); } @Override protected void onPause() { // 撤銷注冊 (撤銷注冊后廣播接收者將不會再監(jiān)聽系統(tǒng)的廣播消息) unregisterReceiver(receiver); super.onPause(); } }
-
靜態(tài)注冊和動態(tài)注冊的區(qū)別
靜態(tài)注冊的廣播接收者一經(jīng)安裝就常駐在系統(tǒng)之中,不需要重新啟動喚醒接收者做个;動態(tài)注冊的廣播接收者隨著應(yīng)用的生命周期,由 registerReceiver 開始監(jiān)聽顽频,由 unregisterReceiver 撤銷監(jiān)聽太闺,如果應(yīng)用退出后,沒有撤銷已經(jīng)注冊的接收者應(yīng)用應(yīng)用將會報錯跟束。
當廣播接收者通過 intent 啟動一個 activity 或者 service 時丑孩,如果 intent 中無法匹配到相應(yīng)的組件。動態(tài)注冊的廣播接收者將會導(dǎo)致應(yīng)用報錯,而靜態(tài)注冊的廣播接收者將不會有任何報錯温学,因為自從應(yīng)用安裝完成后,廣播接收者跟應(yīng)用已經(jīng)脫離了關(guān)系逃延。
發(fā)送廣播主要類型
-
普通廣播
普通廣播是完全異步的轧拄,可以在同一時刻(邏輯上)被所有接收者接收到,所有滿足條件的 BroadcastReceiver 都會隨機地執(zhí)行其 onReceive() 方法檩电。
同級別接收是先后是隨機的拄丰;級別低的收到廣播;消息傳遞的效率比較高料按,并且無法中斷廣播的傳播。
Intent intent = new Intent("android.provider.Telephony.SMS_RECEIVED"); //通過intent傳遞少量數(shù)據(jù) intent.putExtra("data", "finch"); // 發(fā)送普通廣播 sendBroadcast(Intent);
-
有序廣播
有序廣播通過 Context.sendOrderedBroadcast() 來發(fā)送垄潮,所有的廣播接收器優(yōu)先級依次執(zhí)行闷盔,廣播接收器的優(yōu)先級通過 receiver 的 intent-filter 中的 android:priority 屬性來設(shè)置,數(shù)值越大優(yōu)先級越高馁筐。
當廣播接收器接收到廣播后,可以使用 setResult() 函數(shù)來結(jié)果傳給下一個廣播接收器接收果正,然后通過 getResult() 函數(shù)來取得上個廣播接收器接收返回的結(jié)果盟迟。
當廣播接收器接收到廣播后,也可以用 abortBroadcast() 函數(shù)來讓系統(tǒng)攔截下來該廣播攒菠,并將該廣播丟棄,使該廣播不再傳送到別的廣播接收器接收卓起。
-
本地廣播
在 API21 的 Support v4 包中新增本地廣播凹炸,也就是 LocalBroadcastManager 。由于之前的廣播都是全局的奕筐,所有應(yīng)用程序都可以接收到,這樣就會帶來安全隱患墓阀,所以我們使用 LocalBroadcastManager 只發(fā)送給自己應(yīng)用內(nèi)的信息廣播渊胸,限制在進程內(nèi)使用蹬刷。
它的用法很簡單,只需要把調(diào)用 context 的 sendBroadcast泡态、registerReceiver迂卢、unregisterReceiver 的地方換為 LocalBroadcastManager.getInstance(Context context)中對應(yīng)的函數(shù)即可。
這里創(chuàng)建廣播的過程和普通廣播是一樣的過程而克,這里就不過多介紹了
-
系統(tǒng)廣播
當然系統(tǒng)中也會有很多自帶的廣播,當符合一定條件時腾降,系統(tǒng)會發(fā)送一些定義好的廣播碎绎,比如:重啟、充電筋帖、來電電話等等。我們可以通過action屬性來監(jiān)聽我們的系統(tǒng)廣播,創(chuàng)建廣播的過程和普通廣播是一樣的過程寄啼,這里就不過多介紹了代箭。
常用的廣播action屬性有:
屏幕被關(guān)閉之后的廣播:Intent.ACTION_SCREEN_OFF
屏幕被打開之后的廣播:Intent.ACTION_SCREEN_ON
充電狀態(tài),或者電池的電量發(fā)生變化:Intent.ACTION_BATTERY_CHANGED
關(guān)閉或打開飛行模式時的廣播:Intent.ACTION_AIRPLANE_MODE_CHANGED
表示電池電量低:Intent.ACTION_BATTERY_LOW
表示電池電量充足乙帮,即電池電量飽滿時會發(fā)出廣播:Intent.ACTION_BATTERY_OKAY
按下照相時的拍照按鍵(硬件按鍵)時發(fā)出的廣播:Intent.ACTION_CAMERA_BUTTON
值得注意的是蛤高,隨著系統(tǒng)版本的提升碑幅,很多系統(tǒng)廣播已經(jīng)不再被支持,如果你需要使用哪個系統(tǒng)廣播沟涨,最好看看最新版本的支持情況。