廣播的分類
定義分類
- 系統(tǒng)廣播
由Android系統(tǒng)內(nèi)部自動發(fā)出,用戶只負責接收 - 自定義廣播
由開發(fā)者自己定義的廣播
注冊方式分類
- 動態(tài)注冊
在代碼中注冊的 - 靜態(tài)注冊
動態(tài)注冊要求程序必須在運行時才能進行强法,如果需要在程序還沒啟動的時候就可以接收到注冊的廣播稳诚,就需要靜態(tài)注冊了凝化。主要是在AndroidManifest中進行注冊
發(fā)送方式分類(只能是自定義廣播)
- 標準廣播
沒有先后順序可言,不能修改內(nèi)容罪既,無法被截斷 - 有序廣播
根據(jù)優(yōu)先級依次向后傳播酪耳,優(yōu)先級相同時動態(tài)注冊高于
靜態(tài)注冊,abortBroadcast()可截斷廣播
廣播的安全性
Android中的廣播可以跨進程甚至跨App直接通信煮嫌,可能會收到其他app發(fā)送的相同的自定義廣播笛谦,也可能被其他app收到并獲取其中信息。一些增加安全性的方案包括:
1. 靜態(tài)注冊自定義廣播時 android:exported="false" 屬性設(shè)置false昌阿,不接收其他App內(nèi)部發(fā)出的此廣播
2. 發(fā)送自定義廣播時饥脑,intent.setPackage(packageName)指定包名,這樣此廣播將只會發(fā)送到此包中的App內(nèi)與之相匹配的有效廣播接收器中
3. 采用LocalBroadcastManager的方式直接發(fā)送本地廣播
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("xxx");
localBroadcastManager = LocalBroadcastManager.getInstance(this); //獲取實例
localBroadcastManager.registerReceiver(myBroadcastReceiver, intentFilter); //注冊本地廣播監(jiān)聽
localBroadcastManager.sendBroadcast(new Intent("xxx")); // 發(fā)送本地廣播
localBroadcastManager.unregisterReceiver(myBroadcastReceiver);//退出時解除注冊
注意:AndroidX廢除了localBroadcastManager 直接使用Context的registerReceiver()懦冰、sendBroadcast()灶轰、unregisterReceiver() 進行注冊、發(fā)送刷钢、解除
4. 在廣播發(fā)送和接收時笋颤,都增加上permission,用于權(quán)限驗證
4.1. 自己定義權(quán)限闯捎,并且使用自定義權(quán)限
<permission
android:name="my.permission.name"
android:label="BroadcastReceiverPermission"
android:protectionLevel="signature">
</permission>
<uses-permission android:name="my.permission.name" />
android:protectionLevel屬性如下:
- normal:默認的椰弊,應(yīng)用安裝前许溅,用戶可以看到相應(yīng)的權(quán)限瓤鼻,但無需用戶主動授權(quán)。
- dangerous:normal安全級別控制以外的任何危險操作贤重。需要dangerous級別權(quán)限時茬祷,Android會明確要求用戶進行授權(quán)。常見的如:網(wǎng)絡(luò)使用權(quán)限并蝗,相機使用權(quán)限及聯(lián)系人信息使用權(quán)限等祭犯。
- signature:它要求權(quán)限聲明應(yīng)用和權(quán)限使用應(yīng)用使用相同的keystore進行簽名。如果使用同一keystore滚停,則該權(quán)限由系統(tǒng)授予沃粗,否則系統(tǒng)會拒絕。并且權(quán)限授予時键畴,不會通知用戶最盅。它常用于應(yīng)用內(nèi)部。把protectionLevel聲明為signature起惕。如果別的應(yīng)用使用的不是同一個簽名文件涡贱,就沒辦法使用該權(quán)限,從而保護了自己的接收者惹想。
4.2. 如果采用靜態(tài)注冊的方式:
<receiver
android:name=".common.MyBroadcastReceiver"
android:exported="false"
android:permission="my.permission.name">
<intent-filter>
<action android:name="action.name"/>
</intent-filter>
</receiver>
4.3. 如果采用動態(tài)注冊的方式:
//注冊receiver時问词,指定發(fā)送者的權(quán)限,不然外部應(yīng)用可以收到receiver
registerReceiver(receiver, intentFilter, "my.permission.name", null);