Android 廣播機制

來源:互聯網
上載者:User

標籤:執行個體   回調   優先   equal   lin   info   border   boolean   onpause   

1、廣播接收者

        廣播接收者簡單地說就是接收廣播意圖的Java類,此Java類繼承BroadcastReceiver類,並重寫onReceive方法

public void onReceive(Context context,Intent intent),

其中intent可以獲得傳遞的資料

定義了三個廣播接收者如下: 

              優先順序   ReceiverSelf3  > ReceiverSelf2 > ReceiverSelf1   (註冊的代碼中可見)

public class ReceiverSelf1 extends BroadcastReceiver {
private final String TAG = "ReceiverSelf1";
@Override
public void onReceive(Context context, Intent intent) {
String name = intent.getExtras().getString("name");
if(isOrderedBroadcast()){
Log.d(TAG, "onReceive: getExtras in 有序廣播"+name);
}else{
Log.d(TAG, "onReceive: getExtras in 無序廣播"+name);
}
//當發送有序廣播時,可以讓廣播不再往下傳遞。 ReceiverSelf2 不能收到廣播(Manifest中ReceiverSelf1的優先順序更高 )
//如果發送的是 無序廣播 則會崩潰
}
}
public class ReceiverSelf2 extends BroadcastReceiver {
private final String TAG = "ReceiverSelf2";
@Override
public void onReceive(Context context, Intent intent) {
String name = intent.getExtras().getString("name");
if(isOrderedBroadcast()){
Log.d(TAG, "onReceive: getExtras in 有序廣播"+name);
}else{
Log.d(TAG, "onReceive: getExtras in 無序廣播"+name);
}
if(isOrderedBroadcast()){ //判斷接受的是否為 有序廣播
Bundle bundle = getResultExtras(false);
if(bundle != null){
String orderData = bundle.getString(BroadcastActivity.ORDER_DATA);
Log.d(TAG, BroadcastActivity.ORDER_DATA+" "+orderData);
}

String resultData = getResultData();
Log.d(TAG, BroadcastActivity.ORDER_DATA+" "+resultData);
setResultData("優先順序為 3 setResultData的資料"); //修改有序廣播的資料
Log.d(TAG, "onReceive: _______________________________________________");
abortBroadcast();  // 廣播不再往下傳播
}
}
public class ReceiverSelf3 extends BroadcastReceiver {
private final String TAG = "ReceiverSelf3";
@Override
public void onReceive(Context context, Intent intent) {
String name = intent.getExtras().getString("name");
if(isOrderedBroadcast()){
Log.d(TAG, "onReceive: getExtras in 有序廣播"+name);
}else{
Log.d(TAG, "onReceive: getExtras in 無序廣播"+name);
}

if(isOrderedBroadcast()){ //判斷接受的是否為 有序廣播
Bundle bundle = getResultExtras(false);
if(bundle != null){
String orderData = bundle.getString(BroadcastActivity.ORDER_DATA);
Log.d(TAG, BroadcastActivity.ORDER_DATA+" "+orderData);
}

String resultData = getResultData();
Log.d(TAG, BroadcastActivity.ORDER_DATA+" "+resultData);
setResultData("優先順序為 3 setResultData的資料"); //修改有序廣播的資料
Log.d(TAG, "onReceive: _______________________________________________");
}
}

BroadcastReceiver所對應的廣播分兩類:無序廣播和有序廣播。

2、註冊廣播

     廣播的註冊有兩種方式,一種為靜態註冊,即在AndroidManifest中註冊一個廣播接收者。另一種動態註冊的方式是通過代碼註冊。

<receiver android:name=".AndroidBroadcast.ReceiverSelf1">
<intent-filter android:priority="1">
<action android:name="com.xiazdong"/>
</intent-filter>
</receiver>

<receiver android:name=".AndroidBroadcast.ReceiverSelf2">
<intent-filter android:priority="2">
<action android:name="com.xiazdong"/>
</intent-filter>
</receiver>

<receiver android:name=".AndroidBroadcast.ReceiverSelf3">
<intent-filter android:priority="3">
<action android:name="com.xiazdong"/>
</intent-filter>
</receiver>

註: priority 表明接收者的優先順序 -1000~1000,優先順序越高的接收者先接收到廣播。

       intent-filter 定義自己接收廣播的意圖(可進行過濾)    


動態註冊如下:在代碼中通過調用Context的registerReceiver()方法進行動態註冊BroadcastReceiver,具體代碼如下:

@Override protected void onResume(){ super.onResume(); //執行個體化BroadcastReceiver子類 & IntentFilter mBroadcastReceiver mBroadcastReceiver = new mBroadcastReceiver(); IntentFilter intentFilter = new IntentFilter(); //設定接收廣播的類型 intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE); //調用Context的registerReceiver()方法進行動態註冊 registerReceiver(mBroadcastReceiver, intentFilter); }//註冊廣播後,要在相應位置記得銷毀廣播//即在onPause() 中unregisterReceiver(mBroadcastReceiver)//當此Activity執行個體化時,會動態將MyBroadcastReceiver註冊到系統中//當此Activity銷毀時,動態註冊的MyBroadcastReceiver將不再接收到相應的廣播。 @Override protected void onPause() { super.onPause(); //銷毀在onResume()方法中的廣播 unregisterReceiver(mBroadcastReceiver); }}

注:

  • 動態廣播最好在Activity的onResume()註冊、onPause()登出。
  • 對於動態廣播,有註冊就必然得有登出,否則會導致記憶體泄露,重複註冊、重複登出也不允許

關於廣播註冊的更多問題關注參考博文的最後一篇。

3、無序廣播

無序廣播即為我們平時經常使用的廣播,其主要是通過public abstract void sendBroadcast (Intent intent)方法進行發送,並通過intent傳遞資料。程式碼範例如下:

Intent intent = new Intent();
intent.setAction("com.xiazdong");
intent.putExtra("name", "xiazdong");
//發送無序廣播
this.sendBroadcast(intent);
Toast.makeText(getApplicationContext(), "發送廣播成功", Toast.LENGTH_SHORT).show();

       無序廣播會被AndroidMainfest註冊了的相應的感興趣(intent-filter匹配)接收,且順序是無序的(如果設定了 priority則優先順序高的BroadCastReceiver會先收到)。如果發送廣播時有相應的許可權要求,BroadCastReceiver如果想要接收此廣播,也需要有相應的許可權。

    無序廣播不可以被攔截,不可以被終止,不可以被修改,無序廣播任何接收者只要匹配條件都可以接收到。如果想通過無序廣播傳遞資料,則可以調用intent.putExtra方法傳遞, 接收者可通過intent.get...接收,不可通過getResultData接收。

4、有序廣播

有序廣播可以通過如下兩個方法發送:

public abstract void sendOrderedBroadcast (Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)

public void sendOrderedBroadcast(Intent intent,
String receiverPermission)

下面具體講解下一每個參數的含義:

intent: 所有廣播接收者的匹配規則

receiverPermission:指定廣播接收器的許可權,一般自訂,不常用,可傳null

resultReceiver:指定一個最終的廣播接收器,相當於finally功能,不論優先順序,最後都要接收一次廣播(),而這一次收到的廣播為無序廣播(可以在BroadcastReceiver中通過boolean orderedBroadcast = isOrderedBroadcast()方法驗證),但是卻可以通過getResultData等方法取得資料,這就是上面提到的特殊情況。即使前面的廣播調用了abortBroadcast(),該接收器仍然可以接收到一個無序廣播。


scheduler:看英文沒怎麼看懂什麼意思,一般傳null。
initialCode:指定一個code,一般傳Activity.RESULT_OK。
initialData:傳一個字串資料。對應的在BroadcastReceiver中通過String resultData = getResultData()取得資料;通過setResultData("優先順序為3的setResultData的資料")修改資料,將資料傳給下一個優先順序較低的BroadcastReceiver;如果在優先順序較高的BroadcastReceiver中沒有使用setResultData修改資料,那麼優先順序較低的接收到的資料還是最原始的資料,即initialData的值。
initialExtras:傳一個Bundle對象,也就是可以傳多種類型的資料。對應的在BroadcastReceiver中通過Bundle bundle = getResultExtras(false)取得Bundle對象,然後再通過bundle的各種get方法取得資料;通過setResultExtras()傳入一個修改過的bundle,將該bundle對象傳給下一個優先順序較低的BroadcastReceiver;如果在優先順序較高的BroadcastReceiver中沒有使用setResultExtras修改資料,那麼優先順序較低的接收到的資料還是最原始的bundle對象,即initialExtras的值。
發送一個無序廣播如下:
   
Intent intent = new Intent();
intent.setAction("com.xiazdong");
intent.putExtra("name", "xiazdong");
//發送有序廣播
//this.sendOrderedBroadcast(intent,null);
//通過 bundle傳遞資料
Bundle bundle = new Bundle();
bundle.putString(ORDER_DATA,"有序廣播通過 bundle 傳遞資料");
sendOrderedBroadcast(intent,null,null,mHandler, Activity.RESULT_OK,"發送一個有序廣播",bundle);
Toast.makeText(getApplicationContext(), "發送廣播成功", Toast.LENGTH_SHORT).show();

啟動並執行log如下:
       
5、通過廣播接收鎖屏和解屏事件
android 開發人員可以通過註冊接收器,監聽手機的鎖屏和解屏事件,自訂的接收器如下:
 private class ScreenBroadcastReceiver extends BroadcastReceiver {        private String action = null;        @Override        public void onReceive(Context context, Intent intent) {            action = intent.getAction();            if (Intent.ACTION_SCREEN_ON.equals(action)) { // 開屏                mListener.onScreenOn();                Log.d(TAG, "onReceive: "+"開屏");            } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // 鎖屏                mListener.onScreenOff();                Log.d(TAG, "onReceive: "+"鎖屏");            }        }    }
同時通過該動態註冊的方式註冊廣播,通過IntentFilter設定該接收器值接收鎖屏和解屏事件而不會關心其它事件:
IntentFilter filter = new IntentFilter();filter.addAction(Intent.ACTION_SCREEN_ON);filter.addAction(Intent.ACTION_SCREEN_OFF);mContext.registerReceiver(mScreenReceiver, filter);
這樣,當鎖屏和解屏事件發生時,onReceive回調就會被調用。

參考:
http://www.jianshu.com/p/0b3a7b35d76d
http://blog.csdn.net/xiazdong/article/details/7768807/
http://www.jianshu.com/p/ca3d87a4cdf3





Android 廣播機制

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.