1. 程式人生 > >Android BroadcastReceive廣播詳解

Android BroadcastReceive廣播詳解

定義

是一個全域性的監聽器

工作原理

在這裡插入圖片描述

使用流程

在這裡插入圖片描述

自定義廣播接收者BroadcastReceiver

繼承BroadcastReceivre基類
必須複寫抽象方法onReceive()方法
1.廣播接收器接收到相應廣播後,會自動回撥 onReceive() 方法
2.一般情況下,onReceive方法會涉及 與 其他元件之間的互動,如傳送Notification、啟動Service等
3.預設情況下,廣播接收器執行在 UI 執行緒,因此,onReceive()方法不能執行耗時操作,否則將導致ANR
程式碼範例

package com.yuexia.
myservice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; public class MyBroadcastReceiver extends BroadcastReceiver { private static final String TAG = "MyBroadcastReceiver"; @Override public void onReceive
(Context context, Intent intent) { // TODO: This method is called when the BroadcastReceiver is receiving // an Intent broadcast. Log.d(TAG, "onReceive: 接收成功"); //使用廣播攔截技術,程式碼如下 //-------------------abortBroadcast(); } }

廣播接收器註冊方式

靜態註冊
在AndroidManifest.xml中宣告

<receiver 
    android:enabled=["true" | "false"]
//此broadcastReceiver能否接收其他App的發出的廣播
//預設值是由receiver中有無intent-filter決定的:如果有intent-filter,預設值為true,否則為false
    android:exported=["true" | "false"]
    android:icon="drawable resource"
    android:label="string resource"
//繼承BroadcastReceiver子類的類名
    android:name=".mBroadcastReceiver"
//具有相應許可權的廣播發送者傳送的廣播才能被此BroadcastReceiver所接收;
    android:permission="string"
//BroadcastReceiver執行所處的程序
//預設為app的程序,可以指定獨立的程序
//注:Android四大基本元件都可以通過此屬性指定自己的獨立程序
    android:process="string" >

//用於指定此廣播接收器將接收的廣播型別
//本示例中給出的是用於接收網路狀態改變時發出的廣播
 <intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
    </intent-filter>
</receiver>

動態註冊

// 選擇在Activity生命週期方法中的onResume()中註冊
@Override
  protected void onResume(){
      super.onResume();
    // 1. 例項化BroadcastReceiver子類 &  IntentFilter
     mBroadcastReceiver mBroadcastReceiver = new mBroadcastReceiver();
     IntentFilter intentFilter = new IntentFilter();

    // 2. 設定接收廣播的型別
    intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);

    // 3. 動態註冊:呼叫Context的registerReceiver()方法
     registerReceiver(mBroadcastReceiver, intentFilter);
 }
// 註冊廣播後,要在相應位置記得銷燬廣播
// 即在onPause() 中unregisterReceiver(mBroadcastReceiver)
// 當此Activity例項化時,會動態將MyBroadcastReceiver註冊到系統中
// 當此Activity銷燬時,動態註冊的MyBroadcastReceiver將不再接收到相應的廣播。
 @Override
 protected void onPause() {
     super.onPause();
      //銷燬在onResume()方法中的廣播
     unregisterReceiver(mBroadcastReceiver);
     }
}
1.動態廣播,有註冊就必然得有登出,否則會導致記憶體洩露
2.重複註冊、重複登出也不允許
3.在onResume()註冊、onPause()登出是因為onPause()在App死亡前一定會被執行,從而保證廣播在App死亡前一定會被登出,從而防止記憶體洩露。

不在onCreate() & onDestory() 或 onStart() & onStop()註冊、登出是因為:
3.1
當系統因為記憶體不足(優先順序更高的應用需要記憶體,請看上圖紅框)要回收Activity佔用的資源時,Activity在執行完onPause()方法後就會被銷燬,有些生命週期方法onStop(),onDestory()就不會執行。當再回到此Activity時,是從onCreate方法開始執行。
3.2
假設我們將廣播的登出放在onStop(),onDestory()方法裡的話,有可能在Activity被銷燬後還未執行onStop(),onDestory()方法,即廣播仍還未登出,從而導致記憶體洩露。
3.3
但是,onPause()一定會被執行,從而保證了廣播在App死亡前一定會被登出,從而防止記憶體洩露。

兩種註冊方式的區別

兩種註冊方式的區別

普通廣播

即 開發者自身定義 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>

若傳送廣播有相應許可權,那麼廣播接收者也需要相應許可權

有序廣播

1.定義
傳送出去的廣播被廣播接收者按照先後順序接收

2.廣播接受者接收廣播的順序規則(同時面向靜態和動態註冊的廣播接受者)

3.按照Priority屬性值從大-小排序;
Priority屬性相同者,動態註冊的廣播優先;

4.特點
接收廣播按順序接收
先接收的廣播接收者可以對廣播進行截斷,即後接收的廣播接收者不再接收到此廣播;
先接收的廣播接收者可以對廣播進行修改,那麼後接收的廣播接收者將接收到被修改後的廣播

5.具體使用
有序廣播的使用過程與普通廣播非常類似,差異僅在於廣播的傳送方式:

sendOrderedBroadcast(intent);

App應用內廣播

其他還有
系統廣播(System Broadcast)
粘性廣播(Sticky Broadcast)
我就不一一介紹了
付Demo:

MyBroadcastReceiver.calss
package com.yuexia.myservice;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class MyBroadcastReceiver extends BroadcastReceiver {
    private static final String TAG = "MyBroadcastReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO: This method is called when the BroadcastReceiver is receiving
        // an Intent broadcast.
        Log.d(TAG, "onReceive: 接收成功");
        //使用廣播攔截技術,程式碼如下
        //-------------------abortBroadcast();
    }
}
MainActivity.calss
package com.yuexia.myservice;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity implements View.OnClickListener{
    private boolean isBound = false;
    private Intent intent;
    private MyBroadcastReceiver mBroadcastReceiver;
    private LocalBroadcastManager localBroadcastManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        intent = new Intent(this,TextService.class);
        initView();
    }
    
    private void initView() {
    	//傳送廣播的按鈕
        Button btn_send=(Button) this.findViewById(R.id.btn_send);
        btn_send.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_send :
                Intent intent = new Intent();
                //對應BroadcastReceiver中intentFilter的action
                intent.setAction("android.net.conn.CONNECTIVITY_CHANGE");
                //傳送廣播
                localBroadcastManager.sendBroadcast(intent);
                break;
        }
    }
    // 選擇在Activity生命週期方法中的onResume()中註冊
    @Override
    protected void onResume(){
        // 1. 例項化BroadcastReceiver子類 &  IntentFilter
        mBroadcastReceiver = new MyBroadcastReceiver();
        IntentFilter intentFilter = new IntentFilter();

        // 2. 設定接收廣播的型別
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");

        //步驟2:例項化LocalBroadcastManager的例項
        localBroadcastManager = LocalBroadcastManager.getInstance(this);
        //步驟4:呼叫LocalBroadcastManager單一例項的registerReceiver()方法進行動態註冊
        localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);

        // 3. 動態註冊:呼叫Context的registerReceiver()方法
//        registerReceiver(mBroadcastReceiver, intentFilter);
        super.onResume();
    }
    // 註冊廣播後,要在相應位置記得銷燬廣播
    // 即在onPause() 中unregisterReceiver(mBroadcastReceiver)
    // 當此Activity例項化時,會動態將MyBroadcastReceiver註冊到系統中
    // 當此Activity銷燬時,動態註冊的MyBroadcastReceiver將不再接收到相應的廣播。
    @Override
    protected void onPause() {
        //銷燬在onResume()方法中的廣播
        localBroadcastManager.unregisterReceiver(mBroadcastReceiver);
        super.onPause();
    }
}

到這裡就結束了

本文借鑑了很多內容和圖片,更詳細的可以看
https://www.jianshu.com/p/ca3d87a4cdf3