1. 程式人生 > >Android四大元件之BroadcastReceiver(廣播)

Android四大元件之BroadcastReceiver(廣播)

什麼是廣播

  • 廣播是一個全域性的監聽器,屬於Android四大元件之一,它分為兩個角色:廣播發送者、廣播接收者
  • 廣播用於不同元件之間(應用內/不同應用之間),還有多執行緒之間的通訊
  • -

廣播的分類及區別——無序廣播和有序廣播

  • 廣播分為無序廣播和有序廣播,這兩種區別在於,無序廣播發送的時候,幾乎所有的廣播接收器都能同時接收到這條廣播,它們之間沒有先後順序,這種廣播的效率比較高,但是一旦發出就無法截斷。而有序廣播則不同,在廣播發出後,同一時間只會有一個廣播接收器能夠接收到這條廣播,當這個接收器中的邏輯執行完畢後才會廣播才會繼續傳遞,所以這個時候的廣播是有先後順序的,優先順序高的廣播接收器會優先接收到廣播並且可以截斷廣播或者更改廣播內容

廣播的註冊方式及區別——靜態註冊和動態註冊

  • 註冊廣播的方式一般有兩種,在AndroidManifest.xml中註冊的稱為靜態註冊,在程式碼中註冊的稱為動態註冊
  • 靜態註冊只需要在AndroidManifest.xml中新增<receiver>標籤,例如:
        <receiver
            //廣播接收器名字
            android:name=".MyBoradCast"
            //是否啟動廣播
            android:enabled="true"
            //是否能夠接收其他app發出的廣播
            android:exported
="true">
<intent-filter> <action android:name="com.example.mytest.MY_BROADCAST" /> </intent-filter> </receiver>
  • 動態註冊廣播我們就需要在程式碼中新增邏輯了,需要注意,對於動態廣播,有註冊就要有登出,否則會導致記憶體洩露
  • 廣播接收器
MyBoradCast myBoradCast;
  • onResume方法中註冊廣播
myBoradCast = new
MyBoradCast(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("com.example.mytest.MY_BROADCAST"); registerReceiver(myBoradCast,intentFilter);
  • onPause方法中登出廣播
unregisterReceiver(myBoradCast);

註冊廣播

  • 建立2個廣播接收器MyBoradCastMyBoradCast2
public class MyBoradCast extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.e( "onReceive: ", "MyBoradCast**********");
    }
}
public class MyBoradCast2 extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.e( "onReceive2: ", "MyBoradCast2**********");
    }
}

靜態註冊無序廣播

  • AndroidManifest.xml中註冊MyBoradCast
        <receiver
            //廣播接收器名字
            android:name=".MyBoradCast"
            //是否啟動廣播
            android:enabled="true"
            //是否能夠接收其他app發出的廣播
            android:exported="true">
            <intent-filter>
                <action android:name="com.example.mytest.MY_BROADCAST" />
            </intent-filter>
        </receiver>
  • 傳送廣播
Intent intent = new Intent("com.example.mytest.MY_BROADCAST");
sendBroadcast(intent);

靜態註冊有序廣播

  • AndroidManifest.xml中註冊MyBoradCastMyBoradCast2,不同的是在<intent-filter>標籤中新增android:process優先順序屬性,優先順序大的先接收廣播,傳送有序廣播使用sendOrderedBroadcast方法
        <receiver
            android:name=".MyBoradCast"
            android:enabled="true"
            android:exported="true">
            <intent-filter android:process="9">
                <action android:name="com.example.mytest.MY_BROADCAST" />
            </intent-filter>
        </receiver>
        <receiver
            android:name=".MyBoradCast2"
            android:enabled="true"
            android:exported="true">
            <intent-filter android:priority="10">
                <action android:name="com.example.mytest.MY_BROADCAST" />
            </intent-filter>
        </receiver>
  • 傳送廣播
Intent intent = new Intent("com.example.mytest.MY_BROADCAST");
sendOrderedBroadcast(intent,null);

這裡寫圖片描述

  • 可以看到,由於MyBoradCast2的優先順序比較大,所以先由MyBoradCast2接收了廣播

動態註冊無序廣播

  • onResume方法中註冊廣播,在onPause方法中登出廣播,上面已經說到了
myBoradCast = new MyBoradCast();
IntentFilter intentFilter =  new IntentFilter();
intentFilter.addAction("com.example.mytest.MY_BROADCAST");
registerReceiver(myBoradCast,intentFilter);
unregisterReceiver(myBoradCast);

動態註冊有序廣播

  • 註冊有序廣播相比無序只是需要多添加個屬性
myBoradCast = new MyBoradCast();
IntentFilter intentFilter =  new IntentFilter();
//優先順序
intentFilter.setPriority(1);
intentFilter.addAction("com.example.mytest.MY_BROADCAST");
registerReceiver(myBoradCast,intentFilter);

案例

  • 我們可以在Activity中建立一個內部類廣播 ,方便呼叫Activity的各種屬性
    class MyBroadcast extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.e("shopping: ","**********************" );
        }
    }
  • 然後在Activity的onResume方法中註冊
        myBroadcast = new MyBroadcast();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("com.example.yang.paopao.shopping");
        registerReceiver(myBroadcast,intentFilter);
  • onPause方法中登出廣播
        unregisterReceiver(myBroadcast);

介面卡中傳送廣播示例

  • 在Adpater中傳送廣播,建立一個方法,在裡面新增邏輯,Adpater中傳送廣播需要通過傳入的物件呼叫sendBroadcast方法,當Activity接收到廣播後執行相應的邏輯
    private void broad(){
        Intent intent = new Intent("com.example.yang.paopao.shopping");
        context.sendBroadcast(intent);
    }

Service中傳送廣播示例

  • 在Service中傳送廣播與Activity中一樣直接通過sendBroadcast傳送
Intent intent1 = new Intent("com.example.yang.paopao.shopping");
sendBroadcast(intent1);

系統廣播

  • Android中內建了多個系統廣播,只要涉及到手機的基本操作,如開機、網路狀態變化等,都會發出相應的廣播
  • 常見的操作有
    監聽網路變化 android.net.conn.CONNECTIVITY_CHANGE
    關閉或開啟飛航模式 Intent.ACTION_AIRPLANE_MODE_CHANGED
    系統啟動完成後(僅廣播一次) Intent.ACTION_BOOT_COMPLETED
    重啟裝置 Intent.ACTION_REBOOT
    螢幕被關閉 Intent.ACTION_SCREEN_OFF
    螢幕被開啟 Intent.ACTION_SCREEN_ON
  • 這幾種都是我們常見的系統操作,系統廣播是系統傳送的,我們只是接收者
  • 我們來看看監聽網路變化廣播的用法,首先在AndroidManifest.xml中新增許可權
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  • 然後建立一個內部類
    class NetworkChangeReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            //ConnectivityManager主要用於管理與網路連線相關的操作用於查詢網路連線狀態
            ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
            //查詢網路連線狀態
            NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo( );
            if (networkInfo != null || networkInfo.isAvailable()){
                Toast.makeText(context, "已連線網路", Toast.LENGTH_SHORT).show();
            }else {
                Toast.makeText(context, "沒有網路", Toast.LENGTH_SHORT).show();
            }
        }
    }
  • 註冊廣播
        networkChangeReceiver = new NetworkChangeReceiver();
        IntentFilter intentFilter =  new IntentFilter();
        intentFilter.addAction("android.net.com.CONNECTIVITY_CHANGE");
        registerReceiver(networkChangeReceiver,intentFilter);
  • 登出廣播
        unregisterReceiver(networkChangeReceiver);
  • 然後再看看螢幕喚醒與關閉的廣播
    class ScreenStatusReceiver extends BroadcastReceiver {
        String SCREEN_ON = "android.intent.action.SCREEN_ON";
        String SCREEN_OFF = "android.intent.action.SCREEN_OFF";

        @Override
        public void onReceive(Context context, Intent intent) {
            if (SCREEN_ON.equals(intent.getAction())) {
                Log.e("onReceive: ", "螢幕喚醒");
            }
            else if (SCREEN_OFF.equals(intent.getAction())) {
                Log.e("onReceive: ", "螢幕關閉");
            }
        }
    }
  • 註冊廣播
        screenStatusReceiver = new ScreenStatusReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_SCREEN_ON);
        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
        registerReceiver(screenStatusReceiver, intentFilter);
  • onDestroy中登出廣播
        unregisterReceiver(screenStatusReceiver);
  • 執行程式
  • 這裡寫圖片描述
  • 這裡需要注意,登出廣播不能像前面那樣寫在onPause中,否則關閉螢幕的時候Activity不可見就會執行onPause然後登出廣播