Android四大元件:BroadcastReceiver
4.3 廣播發送者向AMS傳送廣播
4.3.1 廣播的傳送
- 廣播是用”意圖(Intent)“標識
- 定義廣播的本質:定義廣播所具備的“意圖(Intent)”
- 廣播發送:廣播發送者將此廣播的”意圖“通過sendBroadcast()方法傳送出去
4.3.2 廣播的型別
廣播的型別主要分為5類:
- 普通廣播(Normal Broadcast)
- 系統廣播(System Broadcast)
- 有序廣播(Ordered Broadcast)
- 粘性廣播(Sticky Broadcast)
- App應用內廣播(Local Broadcast)
具體說明如下:
1. 普通廣播(Normal Broadcast)
即開發者自身定義intent的廣播(最常用)。傳送廣播使用如下:
Intent intent = new Intent();
//對應BroadcastReceiver中intentFilter的action
intent.setAction(BROADCAST_ACTION);
//傳送廣播
sendBroadcast(intent);
- 若被註冊了的廣播接收者中註冊時intentFilter的action與上述匹配,則會接收此廣播(即進行回撥onReceive())。如下mBroadcastReceiver則會接收上述廣播
<receiver
//此廣播接收者類是mBroadcastReceiver
android:name=".mBroadcastReceiver" >
//用於接收網路狀態改變時發出的廣播
<intent-filter>
<action android:name="BROADCAST_ACTION" />
</intent-filter>
</receiver>
- 若傳送廣播有相應許可權,那麼廣播接收者也需要相應許可權
2. 系統廣播(System Broadcast)
- Android中內建了多個系統廣播:只要涉及到手機的基本操作(如開機、網路狀態變化、拍照等等),都會發出相應的廣播
- 每個廣播都有特定的Intent - Filter(包括具體的action),Android系統廣播action如下:
系統操作 | action |
---|---|
監聽網路變化 | android.net.conn.CONNECTIVITY_CHANGE |
關閉或開啟飛航模式 | Intent.ACTION_AIRPLANE_MODE_CHANGED |
充電時或電量發生變化 | Intent.ACTION_BATTERY_CHANGED |
電池電量低 | Intent.ACTION_BATTERY_LOW |
電池電量充足(即從電量低變化到飽滿時會發出廣播 | Intent.ACTION_BATTERY_OKAY |
系統啟動完成後(僅廣播一次) | Intent.ACTION_BOOT_COMPLETED |
按下照相時的拍照按鍵(硬體按鍵)時 | Intent.ACTION_CAMERA_BUTTON |
螢幕鎖屏 | Intent.ACTION_CLOSE_SYSTEM_DIALOGS |
裝置當前設定被改變時(介面語言、裝置方向等) | Intent.ACTION_CONFIGURATION_CHANGED |
插入耳機時 | Intent.ACTION_HEADSET_PLUG |
未正確移除SD卡但已取出來時(正確移除方法:設定--SD卡和裝置記憶體--解除安裝SD卡) | Intent.ACTION_MEDIA_BAD_REMOVAL |
插入外部儲存裝置(如SD卡) | Intent.ACTION_MEDIA_CHECKING |
成功安裝APK | Intent.ACTION_PACKAGE_ADDED |
成功刪除APK | Intent.ACTION_PACKAGE_REMOVED |
重啟裝置 | Intent.ACTION_REBOOT |
螢幕被關閉 | Intent.ACTION_SCREEN_OFF |
螢幕被開啟 | Intent.ACTION_SCREEN_ON |
關閉系統時 | Intent.ACTION_SHUTDOWN |
重啟裝置 | Intent.ACTION_REBOOT |
注:當使用系統廣播時,只需要在註冊廣播接收者時定義相關的action即可,並不需要手動傳送廣播,當系統有相關操作時會自動進行系統廣播
3. 有序廣播(Ordered Broadcast)
-
定義
傳送出去的廣播被廣播接收者按照先後順序接收有序是針對廣播接收者而言的
-
廣播接受者接收廣播的順序規則(同時面向靜態和動態註冊的廣播接受者)
- 按照Priority屬性值從大-小排序;
- Priority屬性相同者,動態註冊的廣播優先;
-
特點
- 接收廣播按順序接收
- 先接收的廣播接收者可以對廣播進行截斷,即後接收的廣播接收者不再接收到此廣播;
- 先接收的廣播接收者可以對廣播進行修改,那麼後接收的廣播接收者將接收到被修改後的廣播
-
具體使用
有序廣播的使用過程與普通廣播非常類似,差異僅在於廣播的傳送方式:sendOrderedBroadcast(intent);
4. App應用內廣播(Local Broadcast)
-
背景
Android中的廣播可以跨App直接通訊(exported對於有intent-filter情況下預設值為true) -
衝突
可能出現的問題:- 其他App針對性發出與當前App intent-filter相匹配的廣播,由此導致當前App不斷接收廣播並處理;
- 其他App註冊與當前App一致的intent-filter用於接收廣播,獲取廣播具體資訊;
即會出現安全性 & 效率性的問題。
-
解決方案
使用App應用內廣播(Local Broadcast)- App應用內廣播可理解為一種區域性廣播,廣播的傳送者和接收者都同屬於一個App。
- 相比於全域性廣播(普通廣播),App應用內廣播優勢體現在:安全性高 & 效率高
-
具體使用1 - 將全域性廣播設定成區域性廣播
- 註冊廣播時將exported屬性設定為false,使得非本App內部發出的此廣播不被接收;
- 在廣播發送和接收時,增設相應許可權permission,用於許可權驗證;
- 傳送廣播時指定該廣播接收器所在的包名,此廣播將只會傳送到此包中的App內與之相匹配的有效廣播接收器中。
通過intent.setPackage(packageName)指定報名
-
具體使用2 - 使用封裝好的LocalBroadcastManager類
使用方式上與全域性廣播幾乎相同,只是註冊/取消註冊廣播接收器和傳送廣播時將引數的context變成了LocalBroadcastManager的單一例項注:對於LocalBroadcastManager方式傳送的應用內廣播,只能通過LocalBroadcastManager動態註冊,不能靜態註冊
//註冊應用內廣播接收器
//步驟1:例項化BroadcastReceiver子類 & IntentFilter mBroadcastReceiver
mBroadcastReceiver = new mBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
//步驟2:例項化LocalBroadcastManager的例項
localBroadcastManager = LocalBroadcastManager.getInstance(this);
//步驟3:設定接收廣播的型別
intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);
//步驟4:呼叫LocalBroadcastManager單一例項的registerReceiver()方法進行動態註冊
localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);
//取消註冊應用內廣播接收器
localBroadcastManager.unregisterReceiver(mBroadcastReceiver);
//傳送應用內廣播
Intent intent = new Intent();
intent.setAction(BROADCAST_ACTION);
localBroadcastManager.sendBroadcast(intent);
5. 粘性廣播(Sticky Broadcast)
由於在Android5.0 & API 21中已經失效,所以不建議使用,在這裡也不作過多的總結。
5. 特別注意
對於不同註冊方式的廣播接收器回撥OnReceive(Context context,Intent intent)中的context返回值是不一樣的:
- 對於靜態註冊(全域性+應用內廣播),回撥onReceive(context, intent)中的context返回值是:ReceiverRestrictedContext;
- 對於全域性廣播的動態註冊,回撥onReceive(context, intent)中的context返回值是:Activity Context;
- 對於應用內廣播的動態註冊(LocalBroadcastManager方式),回撥onReceive(context, intent)中的context返回值是:Application Context。
- 對於應用內廣播的動態註冊(非LocalBroadcastManager方式),回撥onReceive(context, intent)中的context返回值是:Activity Context;