Android BroadcastReceiver使用詳解

想要全面瞭解廣播,須知以下幾點

1、創建廣播接收者類
    繼承BroadcastReceiver,重寫onReceive方法, 以MyReceiver extends BroadcastReceiver爲例子
    public void onReceive(Context context, Intent intent){}
---------------------------------------------------------------------------------------------

2、靜態註冊廣播or動態註冊廣播
---------------------------------------------------------------------------------------------
    2.1 靜態註冊廣播
          

靜態註冊

靜態註冊是在AndroidManifest.xml文件中配置的,我們就來爲MyReceiver註冊一個廣播地址:

[html] view plain copy
  1. <receiver android:name=".MyReceiver">  
  2.             <intent-filter>  
  3.                 <action android:name="android.intent.action.MY_BROADCAST"/>  
  4.                 <category android:name="android.intent.category.DEFAULT" />  
  5.             </intent-filter>  
  6.         </receiver>  
配置了以上信息之後,只要是android.intent.action.MY_BROADCAST這個地址的廣播,MyReceiver都能夠接收的到。注意,這種方式的註冊是常駐型的,也就是說當應用關閉後,如果有廣播信息傳來,MyReceiver也會被系統調用而自動運行。

     2.2 動態註冊廣播

動態註冊

動態註冊需要在代碼中動態的指定廣播地址並註冊,通常我們是在Activity或Service註冊一個廣播,下面我們就來看一下注冊的代碼:

[java] view plain copy
  1. MyReceiver receiver = new MyReceiver();  
  2.           
  3. IntentFilter filter = new IntentFilter();  
  4. filter.addAction("android.intent.action.MY_BROADCAST");  
  5.           
  6. registerReceiver(receiver, filter);  
注意,registerReceiver是android.content.ContextWrapper類中的方法,Activity和Service都繼承了ContextWrapper,所以可以直接調用。在實際應用中,我們在Activity或Service中註冊了一個BroadcastReceiver,當這個Activity或Service被銷燬時如果沒有解除註冊,系統會報一個異常,提示我們是否忘記解除註冊了。所以,記得在特定的地方執行解除註冊操作:

[java] view plain copy
  1. @Override  
  2. protected void onDestroy() {  
  3.     super.onDestroy();  
  4.     unregisterReceiver(receiver);  
  5. }  

執行這樣行代碼就可以解決問題了。注意,這種註冊方式與靜態註冊相反,不是常駐型的,也就是說廣播會跟隨程序的生命週期。
------------------------------------------------------------------------------


3、我們可以根據以上任意一種方法完成註冊,當註冊完成之後,這個接收者就可以正常工作了。我們可以用以下方式向其發送一條廣播:

[java] view plain copy
  1. public void send(View view) {  
  2.     Intent intent = new Intent("android.intent.action.MY_BROADCAST");  
  3.     intent.putExtra("msg""hello receiver.");  
  4.     sendBroadcast(intent);  
  5. }  

注意,sendBroadcast也是android.content.ContextWrapper類中的方法,它可以將一個指定地址和參數信息的Intent對象以廣播的形式發送出去。

----------------------------------------------------------------------------

4、普通廣播和有序廣播
4.1 Normal Broadcast(普通廣播):Normal Broadcast是完全異步的,可以在同一時刻(邏輯上)被所有接收者接收到,消息傳遞的效率比較高。但缺點是接受者不能將處理結果傳遞給下一個接收者,並且無法終止Broadcast Intent的廣播。

 4.2 Ordered Broadcast(有序廣播):Ordered Broadcast的接收者將按預先聲明的優先級依次接受Broadcast。如:A的級別高於B、B的級別高於C,那麼Broadcast先傳給A,再傳給B,最後傳給C。優先級別聲明在<intent-filter.../>元素的android:priority屬性中,數越大優先級別越高,取值範圍爲-1000-1000,優先級別也可以調用IntentFilter對象的setPriority()進行設置。OrderedBroadcast接收者可以終止Broadcast Intent的傳播,BroadcastIntent的傳播一旦終止,後面的接收者就無法接收到Broadcast。另外,OrderedBroadcast的接收者可以將數據傳遞給下一個接收者。如:A得到Broadcast後,可以往它的結果對象中存入數據,當Broadcast傳給B時,B可以從A的結果對象中得到A存入的數據。
4.3 context提供的如下兩個方法用於發送廣播:
      sendBroadcast():發送Normal Broadcast
      sendOrderedBroadcast():發送OrderedBroadcast。

4.4 對於OrderedBroadcast而言,系統會根據接收者生命的優先級別順序逐個執行接收者,優先接收到Broadcast的接收者可以終止Broadcast,調用BroadcastReceiver的abortBroadcast()方法即可終止Broadcast。如果Broadcast被前面的接收者終止,後面的接收者就再也無法獲取到Broadcast。

4.5 不僅如此,對於OrderBroadcast而言,優先接收到Broadcast的接收者可以通過setResultExtras(Bundle)方法將處理結果存入Broadcast中,然後傳給下一個接收者,下一個接收者通過代碼: Bundle bundle=getResultExtras(true)可以獲取上一個接收者存入的數據。


有序廣播示例

如下:

[java] view plain copy
  1. package com.scott.receiver;  
  2.   
  3. import android.content.BroadcastReceiver;  
  4. import android.content.Context;  
  5. import android.content.Intent;  
  6. import android.os.Bundle;  
  7. import android.util.Log;  
  8.   
  9. public class FirstReceiver extends BroadcastReceiver {  
  10.       
  11.     private static final String TAG = "OrderedBroadcast";  
  12.       
  13.     @Override  
  14.     public void onReceive(Context context, Intent intent) {  
  15.         String msg = intent.getStringExtra("msg");  
  16.         Log.i(TAG, "FirstReceiver: " + msg);  
  17.           
  18.         Bundle bundle = new Bundle();  
  19.         bundle.putString("msg", msg + "@FirstReceiver");  
  20.         setResultExtras(bundle);  
  21.     }  
  22.   
  23. }  
[java] view plain copy
  1. public class SecondReceiver extends BroadcastReceiver {  
  2.       
  3.     private static final String TAG = "OrderedBroadcast";  
  4.       
  5.     @Override  
  6.     public void onReceive(Context context, Intent intent) {  
  7.         String msg = getResultExtras(true).getString("msg");  
  8.         Log.i(TAG, "SecondReceiver: " + msg);  
  9.           
  10.         Bundle bundle = new Bundle();  
  11.         bundle.putString("msg", msg + "@SecondReceiver");  
  12.         setResultExtras(bundle);  
  13.     }  
  14.   
  15. }  
[java] view plain copy
  1. public class ThirdReceiver extends BroadcastReceiver {  
  2.       
  3.     private static final String TAG = "OrderedBroadcast";  
  4.       
  5.     @Override  
  6.     public void onReceive(Context context, Intent intent) {  
  7.         String msg = getResultExtras(true).getString("msg");  
  8.         Log.i(TAG, "ThirdReceiver: " + msg);  
  9.     }  
  10.   
  11. }  
我們注意到,在FirstReceiver和SecondReceiver中最後都使用了setResultExtras方法將一個Bundle對象設置爲結果集對象,傳遞到下一個接收者那裏,這樣以來,優先級低的接收者可以用getResultExtras獲取到最新的經過處理的信息集合。

代碼改完之後,我們需要爲三個接收者註冊廣播地址,我們修改一下AndroidMainfest.xml文件:

[html] view plain copy
  1. <receiver android:name=".FirstReceiver">  
  2.     <intent-filter android:priority="1000">  
  3.         <action android:name="android.intent.action.MY_BROADCAST"/>  
  4.         <category android:name="android.intent.category.DEFAULT" />  
  5.     </intent-filter>  
  6. </receiver>  
  7. <receiver android:name=".SecondReceiver">  
  8.     <intent-filter android:priority="999">  
  9.         <action android:name="android.intent.action.MY_BROADCAST"/>  
  10.         <category android:name="android.intent.category.DEFAULT" />  
  11.     </intent-filter>  
  12. </receiver>  
  13. <receiver android:name=".ThirdReceiver">  
  14.     <intent-filter android:priority="998">  
  15.         <action android:name="android.intent.action.MY_BROADCAST"/>  
  16.         <category android:name="android.intent.category.DEFAULT" />  
  17.     </intent-filter>  
  18. </receiver>  
我們看到,現在這三個接收者的<intent-filter>多了一個android:priority屬性,並且依次減小。這個屬性的範圍在-1000到1000,數值越大,優先級越高。

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

[java] view plain copy
  1. public void send(View view) {  
  2.     Intent intent = new Intent("android.intent.action.MY_BROADCAST");  
  3.     intent.putExtra("msg""hello receiver.");  
  4.     sendOrderedBroadcast(intent, "scott.permission.MY_BROADCAST_PERMISSION");  
  5. }  
注意,使用sendOrderedBroadcast方法發送有序廣播時,需要一個權限參數,如果爲null則表示不要求接收者聲明指定的權限,如果不爲null,則表示接收者若要接收此廣播,需聲明指定權限。這樣做是從安全角度考慮的,例如系統的短信就是有序廣播的形式,一個應用可能是具有攔截垃圾短信的功能,當短信到來時它可以先接受到短信廣播,必要時終止廣播傳遞,這樣的軟件就必須聲明接收短信的權限。

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

[html] view plain copy
  1. <permission android:protectionLevel="normal"  
  2.             android:name="scott.permission.MY_BROADCAST_PERMISSION" />  
然後聲明使用了此權限:

[html] view plain copy
  1. <uses-permission android:name="scott.permission.MY_BROADCAST_PERMISSION" />  
關於這部分如果有不明白的地方可以參考Scott Liu之前寫過的一篇文章:Android聲明和使用權限


參考博文:http://blog.csdn.net/liuhe688/article/details/6955668
發佈了52 篇原創文章 · 獲贊 15 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章