自定義權(quán)限
在清單文件中通過(guò)進(jìn)行聲明恩沛,然后通過(guò)引用自己聲明的權(quán)限(可不引用)鬼佣。示例:
android:name="com.baigle.imitatehandler.TEST"
android:protectionLevel="signature" />
protectionLevel
在自定義權(quán)限時(shí)允跑,通常會(huì)指定protectionLevel屬性钞脂,常用的如下:
normal:默認(rèn)的敛苇,應(yīng)用安裝前竭鞍,用戶可以看到相應(yīng)的權(quán)限,但無(wú)需用戶主動(dòng)授權(quán)裆熙。
dangerous:normal安全級(jí)別控制以外的任何危險(xiǎn)操作端礼。需要dangerous級(jí)別權(quán)限時(shí),Android會(huì)明確要求用戶進(jìn)行授權(quán)入录。常見(jiàn)的如:網(wǎng)絡(luò)使用權(quán)限蛤奥,相機(jī)使用權(quán)限及聯(lián)系人信息使用權(quán)限等。
signature:它要求權(quán)限聲明應(yīng)用和權(quán)限使用應(yīng)用使用相同的keystore進(jìn)行簽名僚稿。如果使用同一keystore凡桥,則該權(quán)限由系統(tǒng)授予,否則系統(tǒng)會(huì)拒絕蚀同。并且權(quán)限授予時(shí)唬血,不會(huì)通知用戶。它常用于應(yīng)用內(nèi)部唤崭。例如:
android:name="com.baigle.imitatehandler.TEST"
android:protectionLevel="signature" />
android:name="com.baigle.imitatehandler.OtherActivity"
android:label="@string/app_name"
android:permission="com.baigle.imitatehandler.TEST" >
上面把protectionLevel聲明為signature。如果別的應(yīng)用使用的不是同一個(gè)簽名文件脖律,就沒(méi)辦法使用該權(quán)限谢肾,從而保護(hù)了自己的接收者。
BroadcastReceiver
對(duì)于廣播接收者來(lái)說(shuō)小泉,別的應(yīng)用也可以監(jiān)聽(tīng)并觸發(fā)我們的廣播接收者芦疏。如果廣播接收者注冊(cè)在清單文件中,只需要在中配置android:exported="false"屬性微姊。這樣酸茴,系統(tǒng)中的其它應(yīng)用就無(wú)法觸及到該receiver了。
但如果receiver是動(dòng)態(tài)注冊(cè)的兢交,就需要?jiǎng)?chuàng)建自己的使用權(quán)限薪捍,并且將protectionLevel設(shè)置為signature。這樣配喳,當(dāng)別的應(yīng)用和receiver所在的應(yīng)用使用的簽名不一樣時(shí)酪穿,便不會(huì)啟動(dòng)該receiver。例如:
注冊(cè)廣播接收者
BroadcastReceiver receiver = new OtherActivity();
IntentFilter filter = new IntentFilter("action1");
filter.addCategory(Intent.CATEGORY_DEFAULT);
//注冊(cè)receiver時(shí)晴裹,直接指定發(fā)送者應(yīng)該具有的權(quán)限被济。不然外部應(yīng)用依舊可以觸及到receiver
registerReceiver(receiver, filter, permission, null);
在注冊(cè)的時(shí)候,最關(guān)鍵的一點(diǎn)是用registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)進(jìn)行注冊(cè)涧团,而不是平常用的是registerReceiver(BroadcastReceiver, IntentFilter)只磷。相較于后者经磅,前者在注冊(cè)的時(shí)候要求了發(fā)送者必須具有的權(quán)限。如果發(fā)送者沒(méi)有該權(quán)限,那么發(fā)送者發(fā)送的廣播即使經(jīng)過(guò)IntentFilter的過(guò)濾,也不會(huì)被receiver接收淮韭。此時(shí)如果再自定義一個(gè)權(quán)限鹦肿,并且將權(quán)限的protectionLevel設(shè)置為signature,那么外部應(yīng)用便無(wú)法使用該權(quán)限纠炮,也就無(wú)法觸及到該receiver。上面的permission便是這樣的一個(gè)權(quán)限,聲明如下:
android:name="com.baigle.imitatehandler.TEST"
android:protectionLevel="signature" />
發(fā)送廣播的代碼如下:
Intent intent = new Intent("action1");
intent.putExtra("text", "receiver");
intent.addCategory(Intent.CATEGORY_DEFAULT);
// 也可以使用sendBroadcast(intent);進(jìn)行發(fā)送
sendBroadcast(intent, permission);
有序廣播
通過(guò)sendBroadcast發(fā)送的廣播都是無(wú)序廣播犹芹,所有receiver的接收順序和執(zhí)行順序都是無(wú)法確定,它們什么時(shí)候能運(yùn)行完畢也是無(wú)法確定鞠绰,
同時(shí)也無(wú)法在receiver之間進(jìn)行通信腰埂。從而也無(wú)法使用getResultCode(),setResult()及abortBroadcast()
一系列的方法蜈膨。
通過(guò)sendOrderedBroadcast()發(fā)送的廣播便是有序廣播屿笼。
特點(diǎn)
有序廣播有如下特點(diǎn):
1,所有的receiver依次執(zhí)行翁巍。按優(yōu)先級(jí)高低進(jìn)行排序驴一,優(yōu)先級(jí)高的receiver先執(zhí)行,直到最后灶壶。但優(yōu)先級(jí)相同的receiver執(zhí)行順序不確定肝断。
2,高優(yōu)先級(jí)的receiver可以使用setResult()等方法向其后的receiver傳遞數(shù)據(jù)驰凛。
3胸懈,低優(yōu)先級(jí)的receiver可以通過(guò)getResult()等方法來(lái)獲取高優(yōu)先級(jí)receiver通過(guò)setResult()等方法傳遞的數(shù)據(jù)。
4恰响,所有的receiver都可以調(diào)用abortBroadcast()等方法中止廣播趣钱,使廣播不再往比它優(yōu)先級(jí)低的receiver上傳遞。
5胚宦,優(yōu)先級(jí)的注冊(cè)方法有兩種首有,在清單文件中可以通過(guò)為intent-filter中添加android:priority屬性。在代碼中间唉,可以通過(guò)IntentFilter.setPriority()進(jìn)行設(shè)置绞灼。優(yōu)先級(jí)最低是-999。
功能
利用有序廣播的上述特點(diǎn)呈野,可以實(shí)現(xiàn)一些功能低矮。比如當(dāng)界面顯示時(shí)不執(zhí)行某個(gè)操作,而當(dāng)界面不顯示時(shí)執(zhí)行某個(gè)操作被冒。
具體思路:將執(zhí)行操作放在一個(gè)低優(yōu)先級(jí)的receiver中军掂,同時(shí)在界面中注冊(cè)一個(gè)高優(yōu)先級(jí)的receiver轮蜕,并且兩個(gè)receiver的intent
一樣。當(dāng)界面接收到廣播時(shí)蝗锥,直接取消廣播或者通知低優(yōu)先的廣播不執(zhí)行操作跃洛。這里最主要的就是界面中的廣播接收者要放在哪個(gè)方法中進(jìn)行注冊(cè),一般是放在
onStart()和onStop()中的终议。因?yàn)檫@兩個(gè)方法確定了界面可見(jiàn)的邊界
注冊(cè)和取消注冊(cè)的代碼略汇竭,只是在注冊(cè)時(shí)要通過(guò)IntentFilter.setPriority()方法設(shè)置界面receiver的優(yōu)先級(jí),一般設(shè)置成1000穴张。具體的接收者如下:
private class InterceptReceiver extends BroadcastReceiver {
//界面顯示時(shí)细燎,如果有廣播,會(huì)執(zhí)行到該方法皂甘。
public void onReceive(Context context, Intent intent) {
//setResultCode(Activity.RESULT_CANCELED);//改變r(jià)esultCode的值
abortBroadcast();//或者直接取消廣播
}
}
執(zhí)行操作的receiver一般要根據(jù)resultCode的值判斷是否應(yīng)該進(jìn)行某種操作玻驻。如下:
public void onReceive(Context context, Intent intent) {
int code = getResultCode();
if (code == Activity.RESULT_OK) {//do something
System.out.println("non canceled");
} else {//do nothing
System.out.println("canceled");
}
}
發(fā)送廣播也沒(méi)什么問(wèn)題,只是在發(fā)送的時(shí)候?qū)esultCode的值初始值設(shè)置為Activity.RESULT_OK偿枕,這主要是為了和執(zhí)行操作的receiver相對(duì)應(yīng)璧瞬。如:
// 設(shè)置resultCode的初始值為RESULT_OK
sendOrderedBroadcast(intent, null, null, null,
Activity.RESULT_OK, null, null);