天天看點

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資訊

Android 廣播機制詳解

就這樣這個普通廣播就接收到了,我們就可以再onReceive中做我們想做的操作。我們可以這個來進行全局的操作。

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

前面說過 Android 的廣播有各式各樣,那麼Android 系統是如何幫我們處理我們需要哪種廣播并為我們提供相應的廣播服務呢?這裡有一點需要大家注意,每實作一個廣播接收類必須在我們應用程式中的 manifest 中顯式的注明哪一個類需要廣播,并為其設定過濾器,如下圖:

Android 廣播機制詳解

我們正是在

<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

Android 廣播機制詳解

确實廣播二比廣播一先接收到

那麼我們要怎麼截斷資料呢那便是在優先級高的廣播onReceived中添加代碼

**abortBroadcast();**就OK了我們來看Log

Android 廣播機制詳解

确實攔截了。

小結:

在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廣播機制源碼下載下傳,裡面有更詳細的内容