一篇就夠了系列之BroadcastReceiver全解析

前言:

上一篇一篇就夠了系列之Service全解析,介紹了Android四大組件的Service,本篇繼續來介紹Android四大組件之BroadcastReceiver(廣播接收者)。

Broadacast(廣播):

Google官方文檔廣播

首先,我們應該清楚在Android系統中,Broadcast(廣播)是什麼?

廣播是一種可以在不同App之間,類似訂閱者模式(publish-subscribe design pattern)的信息交流的方式。比如當系統的 開機,電量的變化 都會發送廣播,對這些廣播進行了訂閱的廣播接收者此時會接收到相關的通知然後就可以在其中做出相應的處理操作。這些系統的廣播很有用,但是你也要十分小心不要濫用廣播這種方式,會有導致系統運行緩慢的可能。

分類

  • 普通廣播(Normal Broadacast)
  • 有序廣播(Order Broadcast)
  • 本地廣播(LocalBroadcast)
  • 粘性廣播(StickyBroadcast):已經廢棄了該API,不做討論。

英文原文:

  • The sendBroadcast(Intent) method sends broadcasts to all receivers in an undefined order. This is called a Normal Broadcast. This is more efficient, but means that receivers cannot read results from other receivers, propagate data received from the broadcast, or abort the broadcast.

  • The sendOrderedBroadcast(Intent, String) method sends broadcasts to one receiver at a time. As each receiver executes in turn, it can propagate a result to the next receiver, or it can completely abort the broadcast so that it won’t be passed to other receivers. The order receivers run in can be controlled with the android:priority attribute of the matching intent-filter; receivers with the same priority will be run in an arbitrary order.

  • The LocalBroadcastManager.sendBroadcast method sends broadcasts to receivers that are in the same app as the sender. If you don’t need to send broadcasts across apps, use local broadcasts. The implementation is much more efficient (no interprocess communication needed) and you don’t need to worry about any security issues related to other apps being able to receive or send your broadcasts.

普通廣播
一般的廣播,即發送一個廣播後,所有監聽該廣播的接收者都可以接收到,同時接收並且不能阻止別人接收
代碼爲:

sendBroadcast(new Intent("com.wenyi.interview.mynormalb"));

有序廣播
有序廣播比較特殊,它每次只發送到優先級較高的接收者那裏,然後由優先級高的接受者再傳播到優先級低的接收者那裏,優先級高的接收者有能力終止這個廣播。優先級在manifest中進行設置,代碼爲:

sendOrderedBroadcast(new Intent("com.wenyi.interview.mynormalb"), "interview.permission.MY_BROADCAST_PERMISSION);  

或者

sendOrderedBroadcast(intent, receiverPermission, resultReceiver,
       scheduler, initialCode, initialData, initialExtras)

注意,在兩個參數的方法中,使用sendOrderedBroadcast方法發送有序廣播時,需要一個權限參數,如果爲null則表示不要求接收者聲明指定的權限,如果不爲null,則表示接收者若要接收此廣播,需聲明指定權限。這樣做是從安全角度考慮的,例如系統的短信就是有序廣播的形式,一個應用可能是具有攔截垃圾短信的功能,當短信到來時它可以先接受到短信廣播,必要時終止廣播傳遞,這樣的軟件就必須聲明接收短信的權限。
所以我們在AndroidMainfest.xml中定義和聲明一個權限:

    //定義
    <permission 
        android:protectionLevel="normal"
        android:name="interview.permission.MY_BROADCAST_PERMISSION"/>
    //聲明
    <uses-permission android:name="interview.permission.MY_BROADCAST_PERMISSION"/>

在七個參數的方法中:
resultReceiver :BroadcastReceiver類型,即指定最後的廣播接收器。
scheduler:Handler類型,調度自定義處理程序,用以安排 resultReceiver 回調 ; 如果爲 null 將在語境中的主線程舉行。
initialCode :int類型,一種結果代碼的初始值。通常爲 Activity.RESULT_OK 。這個值是 -1 ;爲其他 int 型 也可以,如 0,1,2;
initialData :String類型,一種結果數據的初始值。通常情況下爲空 ;
initialExtras :Bundle類型,一種結果額外的初始值。通常情況下爲空;

本地廣播:即發送的廣播只有該App可以接收到,信息更加安全,效率更高,推薦使用。

  LocalBroadcastManager.getInstance(BroadcastActivity.this).sendBroadcast(new Intent("com.wenyi.interview.mynormalb"));

總結:通過以上可知,廣播的發送很簡單,在Activity或者Service中直接調用即可,下面來看看接收者。

BroadcastReceiver(廣播接收者)

廣播接收者作爲四大組件之一,使用的時候需要進行註冊,不同於其他的組件,BroadcastReceiver除了在Manifest中進行註冊外,還可以用Java代碼直接註冊。

Manifest註冊:

manifest:

            <permission 
        android:protectionLevel="normal"
        android:name="interview.permission.MY_BROADCAST_PERMISSION"/>

    <uses-permission android:name="interview.permission.MY_BROADCAST_PERMISSION"/>

        <receiver android:name=".FourComponet.broadcast.MyReceiver1"
            >
            <intent-filter android:priority="-1000">
                <action android:name="com.wenyi.interview.mynormalb"/>
            </intent-filter>
        </receiver>

        <receiver android:name=".FourComponet.broadcast.MyReceiver2">
            <intent-filter android:priority="1000">
                <action android:name="com.wenyi.interview.mynormalb"/>
            </intent-filter>
        </receiver>

Activity:

public class BroadcastActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_broadcast);


        findViewById(R.id.normal_broadcast).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendBroadcast(new Intent("com.wenyi.interview.mynormalb"));
            }
        });

        findViewById(R.id.ordered_broadcast).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendOrderedBroadcast(new Intent("com.wenyi.interview.mynormalb"),"interview.permission.MY_BROADCAST_PERMISSION");
            }
        });
        findViewById(R.id.ordered_broadcast_2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendOrderedBroadcast(new Intent("com.wenyi.interview.mynormalb"),"interview.permission.MY_BROADCAST_PERMISSION"
                ,new MyReceiver1(),null,0,"",null);
            }
        });

    }
}

Receiver1:

public class MyReceiver1 extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {

        Log.i("wy", "MyReceiver1    time:"+System.currentTimeMillis());
    }
}

Receiver2:

public class MyReceiver2 extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {

        Log.i("wy", "MyReceiver2    time:"+System.currentTimeMillis());

        abortBroadcast();

    }
}

代碼十分的簡單,主要可簡單總結爲:

  1. 繼承Broadcast,重寫onReceiver方法
  2. 在manifest進行註冊,需要定義action,這是廣播的依據,有序廣播需要定義和申明權限
  3. 普通廣播都能接收,有序廣播按照優先級接收,可以銷燬,調用 abortBroadcast()方法
  4. 打印log,嘗試加深理解

Java代碼註冊:

    @Override
    protected void onResume() {
        super.onResume();

        //動態註冊receiver的Intent過濾器和action
        IntentFilter filter = new IntentFilter();
        filter.addAction("dynamic_register");
        mMyReceiver3=new MyReceiver3();
        registerReceiver(mMyReceiver3, filter);

        Intent intent = new Intent();
        //這條廣播的標誌
        intent.setAction("dynamic_register");
        //發送廣播
        sendBroadcast(intent);

        //動態註冊receiver的Intent過濾器和action
        IntentFilter filter1 = new IntentFilter();
        filter1.addAction("dynamic_register_2");
        mMyReceiver4=new MyReceiver4();
        manager=LocalBroadcastManager.getInstance(BroadcastActivity.this);
        manager.registerReceiver(mMyReceiver4, filter1);

        Intent intent1 = new Intent();
        //這條廣播的標誌
        intent1.setAction("dynamic_register_2");
        //發送廣播
        manager.sendBroadcast(intent1);
    }

    @Override
    protected void onPause() {
        super.onPause();

        unregisterReceiver(mMyReceiver3);
        manager.unregisterReceiver(mMyReceiver4);
    }

說明:

  1. 代碼進行註冊,一般是在onResume中進行註冊,onPause中進行解註冊,一定要解註冊。
  2. 註冊代碼邏輯也就是設置filter的action,然後調用註冊方法。
  3. 本地廣播只能這樣進行動態註冊,註冊的調用對象是LocalBroadcastManager,解註冊也是如此。

最後:

  • onReceiver中不能做耗時操作,超過十秒鐘會異常
  • 生命週期十分簡單,創建,運行,結束

常見的系統廣播:

1.開機啓動服務

action:android.intent.action.BOOT_COMPLETED
category :android.intent.category.DEFAULT
同時申明權限:

2.網絡狀態變化

action:android.net.conn.CONNECTIVITY_CHANGE
category :android.intent.category.DEFAULT
同時申明權限:

3.電量變化

action:android.intent.action.BATTERY_CHANGED
category :android.intent.category.DEFAULT

4.監聽SD卡狀態

清單文件中定義廣播接收者接收的類型,監聽SD卡常見的三種狀態,所以廣播接收者需要接收三種廣播

 <receiver android:name="com.itheima.sdcradlistener.SDCardReceiver">
    <intent-filter >
        <action android:name="android.intent.action.MEDIA_MOUNTED"/>
        <action android:name="android.intent.action.MEDIA_UNMOUNTED"/>
        <action android:name="android.intent.action.MEDIA_REMOVED"/>
        <data android:scheme="file"/>
    </intent-filter>
</receiver>

5監聽應用的安裝、卸載、更新

原理:應用在安裝卸載更新時,系統會發送廣播,廣播裏會攜帶應用的包名
清單文件定義廣播接收者接收的類型,因爲要監聽應用的三個動作,所以需要接收三種廣播

<receiver android:name="com.itheima.app.AppReceiver">
    <intent-filter >
        <action android:name="android.intent.action.PACKAGE_ADDED"/>
        <action android:name="android.intent.action.PACKAGE_REPLACED"/>
        <action android:name="android.intent.action.PACKAGE_REMOVED"/>
        <data android:scheme="package"/>
    </intent-filter>
</receiver>

歡迎閱讀其他系列文章:

一篇就夠了系列之Activity全解析

一篇就夠了系列之Service全解析

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章