Android四大組件之BroadcastReceiver

BroadcastReceiver:

  1. Android四大組件之一,經過intent發送接收消息。系統自己也會發送廣播,好比網絡發生變化,屏幕的熄滅和亮起,接收短信,開機等這些行爲都會發送廣播。咱們能夠經過特定的、系統約定好的Action進行接收廣播,來處理一些咱們本身的邏輯。不過監聽系統廣播,大可能是須要進行權限申請的。
  2. 分爲有序廣播無序廣播本地廣播

BroadcastReceiver的使用:

基本用法

繼承 BroadcastReceiver 類,重寫 onReceive 方法。java

public class MyBroadcastReceiver1 extends BroadcastReceiver {
    private static final String TAG = "廣播接收者===";
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i(TAG, "onReceive: 我是動態註冊的廣播111111111111 "+hashCode());
    }
}
複製代碼

註冊廣播

  1. 靜態註冊android

    在 AndroidManifest.xml 裏面進行註冊網絡

    <!--在設置action裏面的name的時候,雖然能夠隨便設置,可是儘可能用包名作 前綴,符合程序規則,這裏爲了測試就隨便寫了-->
    <receiver android:name=".broadcastreceiver.MyBroadcastReceiver3">
        <intent-filter android:priority="1010">
            <action android:name="test" />
        </intent-filter>
    </receiver>
    複製代碼
  2. 動態註冊ide

    首先建立實例測試

    MyBroadcastReceiver1  myBroadcastReceiver1 = new MyBroadcastReceiver1();
    複製代碼

    註冊廣播this

    IntentFilter filter1 = new IntentFilter("test");
    //設置優先級
    filter1.setPriority(100);
    registerReceiver(myBroadcastReceiver1, filter1);
    複製代碼

    反註冊廣播spa

    unregisterReceiver(myBroadcastReceiver1);
    複製代碼

    注意: 1. 通常咱們在進行動態註冊後,必定要進行反註冊操做,避免資源浪費。反註冊操做通常在 Activity 的 onDestroy 中進行 2.必定要在進行註冊後才進行反註冊操做,不然程序會直接崩潰。線程

發送廣播

  • 有序廣播code

    Intent test = new Intent("test");
    sendOrderedBroadcast(test,null);
    //or 下面方法爲指定一個 最終廣播接收者 此綁定着不受 中斷廣播影響,最終都會接收到廣播。
    /*有意思的是,若是最終廣播接受者的接收消息的優先級在執行中斷廣播操做的廣播接受者之上的時候, 會先接收到消息,而後中斷廣播後最終又會接收到一次消息,總共接收到兩次消息。 固然,若是不執行中斷廣播的操做,仍是會先按照廣播接收順序接收一次消息後,最終再接收一次,總共兩次*/
    sendOrderedBroadcast(test, null, myBroadcastReceiver1, null, 0, null, null);
    複製代碼
    • 能夠經過abortBroadcast()進行中斷廣播,後面的廣播接受者都不能進行接收廣播。xml

    • 能夠經過在 onReceive 改變傳遞數據。

      @Override
      public void onReceive(Context context, Intent intent) {
          Bundle bundle = new Bundle();
           //傳遞數據
          bundle.putString("aaa","我是接受者1");
          setResultExtras(bundle);
      }
      ///////////////////////////////
      @Override
      public void onReceive(Context context, Intent intent) {
          Bundle resultExtras = getResultExtras(true);
          //要對resultExtras 進行判空處理,若是前面沒有傳遞數據,這裏的resultExtras會爲null
          //改變前面廣播發送的數據
          if(resultExtras!=null){
               resultExtras.putString("aaa","我是接受者2");
          }
      }
      //最終後面接收到的 "aaa" 的值爲 "我是接受者2"
      ///////////////////
      @Override
      public void onReceive(Context context, Intent intent) {
          //中斷廣播
          abortBroadcast();
      }
      複製代碼
    • sendOrderedBroadcast(test,null) 第二個參數是廣播接受者指定所需的權限。 (這個有待研究, 在設置指定權限後,好像其餘沒有指定權限的廣播接收者也能收到廣播,懵逼。。。看到網上的提示:Android對同一PID的權限驗證是直接經過的。所以若是Sender和Receiver在同一進程,是不能作權限限制的。 具體代碼能夠看一下ActivityManagerService的checkComponentPermission)

  • 無序廣播

    Intent intent2 = new Intent("test");
    sendBroadcast(intent2);
    複製代碼
    • 沒法中斷廣播。
    • 無序廣播雖然說官方文檔上說是,接收消息的順序是無序的,可是經過測試,仍是有順序的。
  • 本地廣播

    使用 LocalBroadcastManager 進行發送本地廣播和註冊本地廣播,只能發送無序廣播。本地廣播只能進行動態註冊,其發送的廣播只能在本進程中接收,註冊的廣播只能被本進程發送的廣播接收。

    //獲取本地廣播管理器單例
    LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context);
    //註冊本地廣播
    IntentFilter filter1 = new IntentFilter("test");
    filter1.setPriority(100);
    localBroadcastManager.registerReceiver(myBroadcastReceiver1, filter1);
    //發送本地廣播
    Intent test = new Intent("test");
    localBroadcastManager.sendBroadcast(test);
    複製代碼

    使用本地廣播能夠防止外部應用惡意接收咱們的廣播數據,並進行篡改。也能夠防止外部應用惡意的發送垃圾廣播給咱們。

廣播接收順序

- 有序廣播:
    1. 優先級(priority)高的優先於低的。
    2. 同優先級不一樣註冊方式狀況下,動態高於靜態。
    3. 同優先級同註冊方式狀況下,動態註冊:先註冊的高於後註冊的,靜態註冊:先掃描的優先於後掃描的。
- 無序廣播:
    1. 動態註冊高於靜態註冊,無視優先級。
    2. 不一樣優先級同註冊方式,根據優先級高低進行排序。
    3. 同優先級同註冊方式狀況下,動態註冊:先註冊的高於後註冊的,靜態註冊:先掃描的優先於後掃描的。
複製代碼

廣播特色

  1. 廣播接受者每次接收廣播時,都會從新建立一個實例(能夠經過打印其hashcode值進行驗證)
  2. 優先級字段 priority 取值範圍爲 -1000-1000。(測試發現其實能夠最大取到Integer.MAX_VAUE,就是2的31次方,2147483648)
  3. onReceive裏不能進行耗時操做,由於廣播接受者依賴於主線程,執行太久(網上看到說是10s)會報ANR(Application Not Response),也不建議在onReceive裏面建立一個子線程進行耗時操做,由於在onReceive裏面的業務邏輯執行完後,就有可能被系統回收,子線程依賴的活動組件被回收後,子線程任務有可能還沒結束,此時會被標記爲空進程,在內存吃緊的時候會被優先殺死回收。咱們能夠在Activity或者Service裏面進行一些耗時操做。

Android8.0靜態註冊廣播接收不到隱式發送的廣播

在Android8.0以上,靜態註冊的廣播,是接收不到隱式發送的廣播的,只能接收經過顯示方式發送的廣播,也就是 intent.setComponent() 指定一個廣播。 動態註冊的廣播不受影響。

Intent intent2 = new Intent("test");
intent2.setComponent(new ComponentName(this, MyBroadcastReceiver4.class));
sendBroadcast(intent2);
複製代碼

參考文獻:

《愛上Android》書籍

Android 四大組件

相關文章
相關標籤/搜索