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

Android 廣播機制詳解

一、廣播的簡介

首先,當我們一聽到廣播這個詞時。就可以想到小學是教室的廣播。不錯Android中的廣播機制與我們生活中的廣播是有異曲同工之妙的。Android中的傳送廣播也就像廣播室播廣播,可以讓很多註冊過廣播的地方收到這條廣播。接下來我們對其進行分析。

二、廣播的傳送

廣播的傳送主要是分為2種,分別是普通廣播(Normal broadcasts)和有序廣播(Ordered broadcasts)。他們之間的不同點如下所示 :

普通廣播(Normal broadcasts)
普通廣播採用的是Context.sendBroadcast()傳送的。
普通廣播是完全非同步的,他可以在同一時刻(邏輯上)被所有註冊了的接收者接收到,訊息傳遞的效率比較高,就像教室的廣播一樣,當傳送廣播時所有開了廣播的教室等會同時收到。但這種方式的缺點是:接收者不能將處理結果傳遞給下一個接收者,並且無法終止廣播Intent的傳播;

有序廣播(Ordered broadcasts)
有序廣播是採用Context.sendOrderedBroadcast()傳送的
然而有序廣播是按照接收者宣告的優先級別(宣告在intent-filter元素的android:priority屬性中,數越大優先級別越高,取值範圍:-1000到1000。也可以呼叫IntentFilter物件的setPriority()進行設定),被接收者依次接收廣播。就相當於公司領導發通知肯定是不會直接到員工手上的,需要先到部門老大那然後部門老大再告訴你,部門老大可以選擇不告訴你或者增加一些資訊然後通知你。如:A的級別高於B,B的級別高於C,那麼,廣播先傳給A,再傳給B,最後傳給C。A得到廣播後,可以往廣播裡存入資料,當廣播傳給B時,B可以從廣播中得到A存入的資料。中間優先順序高的也可以將廣播攔截,這樣優先順序低的就無法收到了。

Demo分析
首先我們先來看一下普通廣播的傳送

public class MainActivity extends AppCompatActivity {
    Button button;
    public static final String ACTION_INTENT_TEST = "com.terry.broadcast.test";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button=findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(ACTION_INTENT_TEST);
                sendBroadcast(intent);
            }
        });
    }
}

上面是一個按鈕點選事件然後傳送,接下來我們製作一個接收廣播的類

public class MyReceiver extends BroadcastReceiver {
    private static final String TAG = "MyReceiver";
    public MyReceiver(){
        Log.d(TAG, "MyReceiver: ");
    }
    @Override
    public void  onReceive(Context context, Intent intent) {
        Log.d(TAG, "onReceive: ");
    }
}
 <receiver
            android:name=".MyReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.terry.broadcast.test"></action>
            </intent-filter>
        </receiver>

我們這裡是先製作了一個類來接收,然後再AndroidManifest中註冊這個廣播設定 也就是我們傳送是intent攜帶的。他會去匹配有這個intent-filter的廣播。我們看Log資訊
在這裡插入圖片描述
就這樣這個普通廣播就接收到了,我們就可以再onReceive中做我們想做的操作。我們可以這個來進行全域性的操作。

那麼問題來了,Android 如何判斷並篩選廣播?

前面說過 Android 的廣播有各式各樣,那麼Android 系統是如何幫我們處理我們需要哪種廣播併為我們提供相應的廣播服務呢?這裡有一點需要大家注意,每實現一個廣播接收類必須在我們應用程式中的 manifest 中顯式的註明哪一個類需要廣播,併為其設定過濾器,如下圖:
在這裡插入圖片描述
我們正是在<intent-filter> <action android:name="com.terry.broadcast.test"></action> </intent-filter>中設定篩選的。然後傳送時攜帶它

Demo分析二有序廣播
我們上面不變,然後同樣的建立再建立一個廣播。唯一的差別就是AndroidManifest的設定不同。然後我們採用Context.sendOrderedBroadcast()的傳送方式

<receiver
            android:name=".MyReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter android:priority="100">
                <action android:name="com.terry.broadcast.test" />
            </intent-filter>
        </receiver>
        <receiver
            android:name=".MyReceiver2"
            android:enabled="true"
            android:exported="true">
            <intent-filter android:priority="200">
                <action android:name="com.terry.broadcast.test" />
            </intent-filter>
        </receiver>

很明顯可以看到廣播二的priority="200"是200而第一個是100,所以這個的優先順序比100的高它會先接收。我們看Log

確實廣播二比廣播一先接收到
那麼我們要怎麼截斷資料呢那便是在優先順序高的廣播onReceived中新增程式碼
**abortBroadcast();**就OK了我們來看Log
在這裡插入圖片描述
確實攔截了。

小結:
在Android 中如果要傳送一個廣播必須使用sendBroadCast 向系統傳送對其感興趣的廣播接收器中。
使用廣播必須要有一個intent 物件必設定其action動作物件
使用廣播必須在配置檔案中顯式的指明該廣播物件
每次接收廣播都會重新生成一個接收廣播的物件
在BroadCast 中儘量不要處理太多邏輯問題,建議複雜的邏輯交給Activity 或者 Service 去處理
如果在AndroidManifest.xml中註冊,當應用程式關閉的時候,也會接收到廣播。在應用程式中註冊就不產生這種情況了。

下面自己來看一下如何在應用程式中註冊BroadcastReceiver

利用程式碼註冊 BroadcastReceiver 時有以下步驟:

1)生成一個 BroadcastReceiver 物件;

2)生成一個 IntentFilter 物件;

3)為 IntentFilter 物件新增一個 Action ;

4)利用 IntentFilter 和 BroadcastReceiver 繫結註冊一個 BroadcastReceiver 到系統中,當系統廣播發出Action事件的時候,就會匹配到該BroadcastReceiver。然後執行 onReceive方法,我們可以在裡面寫我們需要做的事,如網路變動、開機啟動之類的。

Android廣播機制原始碼下載,裡面有更詳細的內容