Broadcast 知識梳理(1) - BroadcastReceiver 基本概念

一、基本概念

1.1 實(shí)現(xiàn)廣播接收者

首先,我們需要創(chuàng)建一個(gè)廣播接收者,繼承于BroadcastReceiver并重寫它的onReceive方法。

public class MyBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {}
}

在創(chuàng)建完接收者之后,還需要進(jìn)行注冊,告訴系統(tǒng)有這個(gè)監(jiān)聽者。廣播注冊的方式分為:靜態(tài)注冊和動態(tài)注冊。

靜態(tài)注冊

靜態(tài)注冊在AndroidManifest.xml中進(jìn)行指定。

<receiver android:enabled=["true" | "false"]
    android:exported=["true" | "false"]
    android:icon="drawable resource"
    android:label="string resource"
    android:name="string"
    android:permission="string"
    android:process="string" >
. . .
</receiver>
  • exportedexported決定了 廣播接收者所能收到廣播的范圍,假如為false,那么只有同一個(gè)App,或者userId相同的App發(fā)出的廣播它才能夠收到,并不是指同一個(gè)進(jìn)程。exported一般情況下默認(rèn)為false,唯一例外的是假如設(shè)置了intent-filter,那么默認(rèn)值為true。對于靜態(tài)注冊的廣播,在Android 3.1之后,應(yīng)用如果沒有啟動并且Intent中包含了FLAG_INCLUDE_STOPPED_PACKAGES屬性,那么會先調(diào)起應(yīng)用,否則在應(yīng)用沒有啟動的情況下將無法收到廣播。

  • permission:如果設(shè)置了permission,那么只有 具有相應(yīng)權(quán)限的廣播發(fā)送方 發(fā)送的廣播才能被此BroadcastReceiver接收。Android廣播的權(quán)限機(jī)制是雙向的,即我們既可以 要求發(fā)送者具有權(quán)限,也可以 要求接收者具有權(quán)限,才能完成端到端的通信過程,這里就是 要求發(fā)送者具有權(quán)限。

  • process:運(yùn)行所處的進(jìn)程,默認(rèn)為App的進(jìn)程。

動態(tài)注冊

動態(tài)注冊的廣播無需在AndroidManifest.xml進(jìn)行聲明,在代碼中進(jìn)行注冊和注銷即可。

//注冊廣播。
registerReceiver(BroadcastReceiver receiver, IntentFilter filter)
//注銷廣播。
unregisterReceiver(BroadcastReceiver receiver);

1.2 發(fā)送廣播

廣播的發(fā)送者通過Intent將其意圖發(fā)送出去,系統(tǒng)找到匹配的接收者,發(fā)送廣播的一般方式如下:

Intent intent = new Intent();
intent.setAction(INTENT_ACTION);
sendBroadcast(intent);

1.3 廣播類型

廣播可以分為以下幾類:無序廣播、有序廣播和粘性廣播。

1.3.1 無序廣播

無序廣播指的是所有廣播接收者收到廣播的順序是沒有規(guī)律的。

1.3.2 有序廣播

有序廣播指的是發(fā)送出的廣播被BroadcastReceiver按照priority從大到小的順序接收,當(dāng)priority相同時(shí),動態(tài)廣播優(yōu)先靜態(tài)廣播,發(fā)送有序廣播的方式為:

sendOrderedBroadcast(intent, receiverPermission, ...)

對于有序廣播有一個(gè)特點(diǎn),先接收的BroadcastReceiver具有攔截廣播的權(quán)利,攔截的方法為onReceive方法中調(diào)用abortBroadcast()方法。

1.3.3 粘性廣播

已經(jīng)廢棄,它是用來處理先收到廣播然后才注冊的情況。

1.4 應(yīng)用內(nèi)廣播

假如exported屬性為true,那么是允許兩個(gè)不同應(yīng)用通過廣播進(jìn)行通信的。就可能出現(xiàn) 安全隱患

  • 其他App可能會針對性地發(fā)出與當(dāng)前Appintent-filter相匹配的廣播,導(dǎo)致當(dāng)前App不斷接收到廣播并處理。
  • 其他App可以注冊與當(dāng)前App相匹配的intent-filter,從而獲取廣播具體信息。

為了避免出現(xiàn)以上的安全問題,有以下的解決方法:

  • 設(shè)置exported屬性為false。
  • 設(shè)置權(quán)限。
  • 發(fā)送廣播時(shí),指定具體的包名。

假如我們的廣播只需要在應(yīng)用內(nèi)部通信,那么可以采用封裝好的LocalBroadcastManager類,用于解決安全問題。

傳統(tǒng)的廣播是通過Binder來實(shí)現(xiàn)的,而LocalBroadcastManager則是采用Handler的方式。當(dāng)注冊廣播的時(shí)候,其實(shí)將Receiver添加到單例對象LocalBroadcastManager維護(hù)的列表當(dāng)中,發(fā)送消息的時(shí)候,通過Receiver所關(guān)聯(lián)的action找到它,最后回調(diào)它的onReceive方法。

因此,只有通過LocalBroadcastManager注冊的BroadcastReceiver才能收到通過LocalBroadcastManager發(fā)出的廣播。

具體的代碼實(shí)現(xiàn)可以參考這篇文章 LocalBroadcastManager 的實(shí)現(xiàn)原理,還是 Binder?。

二、一些需要注意的點(diǎn)

2.1 權(quán)限問題

通過權(quán)限可以也可以解決我們之前談到的安全問題,Broadcast的權(quán)限是雙向的。

2.1.1 要求接收者具有權(quán)限

這種方式 用于防止廣播信息泄露。

發(fā)送者AndroidManifest.xml中定義權(quán)限。

<permission android:name = "com.android.permission.RECV_XXX"/>

發(fā)送者在發(fā)送廣播的時(shí)候,采用帶有權(quán)限的接口進(jìn)行發(fā)送。

sendBroadcast("com.android.XXX_ACTION", "com.android.permission.RECV_XXX");


接收者 如果希望能收到廣播,那么需要在它的AndroidManifest.xml進(jìn)行聲明使用該權(quán)限。

 <uses-permission android:name="com.android.permission.RECV_XXX"></uses-permission>

2.1.2 要求發(fā)送者具有權(quán)限

這種方式 用于防止外部應(yīng)用惡意地發(fā)送廣播,導(dǎo)致接收者一直在處理

接收者AndroidManifest.xml中定義權(quán)限。

<permission android:name="com.android.SEND_XXX"/>

在接收者的AndroidManifest.xml聲明BroadcastReceiver的時(shí)候,通過permission字段指定權(quán)限。

<receiver android:name=".XXXReceiver" 
          android:permission="com.android.permission.SEND_XXX"> 
    <intent-filter>
         <action android:name="com.android.XXX_ACTION" /> 
    </intent-filter>
</receiver>


發(fā)送者 如果希望廣播能被該接收者收到,那么需要在AndroidManifest.xml中聲明使用該權(quán)限。

<uses-permission android:name="com.android.permission.SEND_XXX“></users-permission>

2.2 ANR

BroadcastReceiver方法中,不要進(jìn)行耗時(shí)的操作,超過10s會發(fā)生BroadcastQueue TimeoutANR異常。

2.3 onReceive 傳入的 Context

  • 靜態(tài)注冊的BroadcastReceiver,其Contextandroid.app.ReceiverRestrictedContext。

  • 動態(tài)注冊的普通BroadcastReceiver,與調(diào)用registerReceiver方法的Context有關(guān),如果是通過Application Context注冊的,那么ContextApplication Context,如果是Activity Context,那么其ContextActivity Context

  • LocalBroadcastManager動態(tài)注冊的BroadcastReceiver,其ContextApplication Context。

三、參考文章

Android Broadcast 和 BroadcastReceiver 的權(quán)限限制
Android 總結(jié)篇系列:Android 廣播機(jī)制
LocalBroadcastManager 的實(shí)現(xiàn)原理,還是 Binder?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 【Android 廣播】 BroadcastReceiver簡介 BroadcastReceiver(廣播接收器)...
    Rtia閱讀 3,551評論 1 17
  • 本文轉(zhuǎn)載自http://www.cnblogs.com/lwbqqyumidi/p/4168017.html 1....
    Ernest_Chang閱讀 773評論 0 3
  • 廣播接收器 是Android的四大組件之一,可見廣播在Android中的重要性; 1. 什么是廣播? 廣播(Bro...
    Lost_Robot閱讀 2,055評論 2 10
  • 前言 本來想寫一下廣播的,發(fā)現(xiàn)查閱后有整理的不錯的,只好轉(zhuǎn)載圖個(gè)簡便,日后好復(fù)習(xí)轉(zhuǎn)載:http://www.cnb...
    提升即效率閱讀 1,463評論 0 10
  • 01出發(fā)和歸途 他們在大雪紛飛的日子出發(fā),在另一個(gè)大雪紛飛的日子歸來。 途中有新生命的誕生,終點(diǎn)有年老者安息歸去。...
    Arya周閱讀 965評論 0 1

友情鏈接更多精彩內(nèi)容