1. 程式人生 > >Android初試--Android中的BroadcastReceiver(2)

Android初試--Android中的BroadcastReceiver(2)

如果有多個接收者都註冊了相同的廣播地址,又會是什麼情況呢,能同時接收到同一條廣播嗎,相互之間會不會有干擾呢?這就涉及到普通廣播和有序廣播的概念了。

普通廣播(Normal Broadcast

普通廣播對於多個接收者來說是完全非同步的,通常每個接收者都無需等待即可以接收到廣播,接收者相互之間不會有影響。對於這種廣播,接收者無法終止廣播,即無法阻止其他接收者的接收動作。

為了驗證以上論斷,我們新建三個BroadcastReceiver,演示一下這個過程,FirstReceiverSecondReceiverThirdReceiver的程式碼如下:

FirstReceiver

package com.scott.receiver;

import android.content.BroadcastReceiver;

import android.content.Context;

import android.content.Intent;

import android.util.Log;

public class FirstReceiver extends BroadcastReceiver {

private static final String TAG = "NormalBroadcast";

@Override

public void onReceive(Context context, Intent intent) {

String msg = intent.getStringExtra("msg");

Log.i(TAG, "FirstReceiver: " + msg);

}

}


SecondReceiver

public class SecondReceiver extends BroadcastReceiver {

private static final String TAG = "NormalBroadcast";

@Override

public void onReceive(Context context, Intent intent) {

String msg = intent.getStringExtra("msg");

Log.i(TAG, "SecondReceiver: " + msg);

}

}


ThirdReceiver

public class ThirdReceiver extends BroadcastReceiver {

private static final String TAG = "NormalBroadcast";

@Override

public void onReceive(Context context, Intent intent) {

String msg = intent.getStringExtra("msg");

Log.i(TAG, "ThirdReceiver: " + msg);

}}

從上面程式的執行結果來看這三個接收者都接收到這條廣播了,我們稍微修改一下三個接收者,在 onReceive 方法的最後一行新增以下程式碼,試圖終止廣播:abortBroadcast();再次執行,我們會發現,控制檯中三個接收者仍然都列印了自己的日誌,表明接收者並不能終止廣播。

有序廣播(Ordered Broadcast

有序廣播比較特殊,它每次只發送到優先順序較高的接收者那裡,然後由優先順序高的接受者再傳播到優先順序低的接收者那裡,優先順序高的接收者有能力終止這個廣播。

為了演示有序廣播的流程,我們修改一下上面三個接收者的程式碼,如下:

FirstReceiver 

import android.content.BroadcastReceiver;

import android.content.Context;

import android.content.Intent;

import android.os.Bundle;

import android.util.Log;

public class FirstReceiver extends BroadcastReceiver {

private static final String TAG = "OrderedBroadcast";

@Override

public void onReceive(Context context, Intent intent) {

String msg = intent.getStringExtra("msg");

Log.i(TAG, "FirstReceiver: " + msg);

Bundle bundle = new Bundle();

bundle.putString("msg", msg + "@FirstReceiver");

setResultExtras(bundle);

}

}


 SecondReceiver 

public class SecondReceiver extends BroadcastReceiver {

private static final String TAG = "OrderedBroadcast";

@Override

public void onReceive(Context context, Intent intent) {

String msg = getResultExtras(true).getString("msg");

Log.i(TAG, "SecondReceiver: " + msg);

Bundle bundle = new Bundle();

bundle.putString("msg", msg + "@SecondReceiver");

setResultExtras(bundle);

}}

 

ThirdReceiver 

public class ThirdReceiver extends BroadcastReceiver {

private static final String TAG = "OrderedBroadcast";

@Override

public void onReceive(Context context, Intent intent) {

String msg = getResultExtras(true).getString("msg");

Log.i(TAG, "ThirdReceiver: " + msg);

}

}

我們注意到,在FirstReceiver和SecondReceiver中最後都使用了setResultExtras方法將一個Bundle物件設定為結果集物件,傳遞到下一個接收者那裡,這樣以來,優先順序低的接收者可以用getResultExtras獲取到最新的經過處理的資訊集合。

程式碼改完之後,我們需要為三個接收者註冊廣播地址,我們修改一下AndroidMainfest.xml檔案:

        <receiver android:name=".FirstReceiver">

         <intent-filter android:priority="1000">

         <action android:name="android.intent.action.MY_BROADCAST"/>

         <category android:name="android.intent.category.DEFAULT" />

         </intent-filter>

        </receiver>

        <receiver android:name=".SecondReceiver">

         <intent-filter android:priority="999">

         <action android:name="android.intent.action.MY_BROADCAST"/>

         <category android:name="android.intent.category.DEFAULT" />

         </intent-filter>

        </receiver>

        <receiver android:name=".ThirdReceiver">

         <intent-filter android:priority="998">

         <action android:name="android.intent.action.MY_BROADCAST"/>

         <category android:name="android.intent.category.DEFAULT" />

         </intent-filter>

        </receiver>

我們看到,現在這三個接收者的<intent-filter>多了一個android:priority屬性,並且依次減小。這個屬性的範圍在-1000到1000,數值越大,優先順序越高。

現在,我們需要修改一下發送廣播的程式碼,如下:

    public void send(View view) {

     Intent intent = new Intent("android.intent.action.MY_BROADCAST");

     intent.putExtra("msg", "hello receiver.");

     sendOrderedBroadcast(intent, "scott.permission.MY_BROADCAST_PERMISSION");

}

注意,使用sendOrderedBroadcast方法傳送有序廣播時,需要一個許可權引數,如果為null則表示不要求接收者宣告指定的許可權,如果不為null,則表示接收者若要接收此廣播,需宣告指定許可權。這樣做是從安全形度考慮的,例如系統的簡訊就是有序廣播的形式,一個應用可能是具有攔截垃圾簡訊的功能,當簡訊到來時它可以先接受到簡訊廣播,必要時終止廣播傳遞,這樣的軟體就必須宣告接收簡訊的許可權。

所以我們在AndroidMainfest.xml中定義一個許可權:

    <permission android:protectionLevel="normal"

     android:name="scott.permission.MY_BROADCAST_PERMISSION" />

然後宣告使用了此許可權:

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

然後我們執行程式,我們看到接收是按照順序的,第一個和第二個都在結果集中加入了自己的標記,並且向優先順序低的接收者傳遞下去。

既然是順序傳遞,試著終止這種傳遞,看一看效果如何,我們修改FirstReceiver的程式碼,在onReceive的最後一行新增以下程式碼:

abortBroadcast();

此次,只有第一個接收者執行了,其它兩個都沒能執行,因為廣播被第一個接收者終止了。