Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> [Android] BroadcastReceiver總結

[Android] BroadcastReceiver總結

編輯:關於Android編程

BroadcastReceiver的定義

廣播是一種廣泛運用的在應用程序之間傳輸信息的機制,主要用來監聽系統或者應用發出的廣播信息,然後根據廣播信息作為相應的邏輯處理,也可以用來傳輸少量、頻率低的數據。

在實現開機啟動服務和網絡狀態改變、電量變化、短信和來電時通過接收系統的廣播讓應用程序作出相應的處理。

BroadcastReceiver 自身並不實現圖形用戶界面,但是當它收到某個通知後, BroadcastReceiver 可以通過啟動 Service 、啟動 Activity 或是 NotificationMananger 提醒用戶。

BroadcastReceiver使用注意

當系統或應用發出廣播時,將會掃描系統中的所有廣播接收者,通過action匹配將廣播發送給相應的接收者,接收者收到廣播後將會產生一個廣播接收者的實例,執行其中的onReceiver()這個方法;特別需要注意的是這個實例的生命周期只有10秒,如果10秒內沒執行結束onReceiver(),系統將會報錯。 
  
在onReceiver()執行完畢之後,該實例將會被銷毀,所以不要在onReceiver()中執行耗時操作,也不要在裡面創建子線程處理業務(因為可能子線程沒處理完,接收者就被回收了,那麼子線程也會跟著被回收掉);正確的處理方法就是通過in調用activity或者service處理業務。

BroadcastReceiver的注冊

BroadcastReceiver的注冊方式有且只有兩種,一種是靜態注冊(推薦使用),另外一種是動態注冊,廣播接收者在注冊後就開始監聽系統或者應用之間發送的廣播消息。

接收短信廣播示例

定義自己的BroadcastReceiver 類

public class MyBroadcastReceiver extends BroadcastReceiver {

// action 名稱
String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED" ;

    public void onReceive(Context context, Intent intent) {

       if (intent.getAction().equals( SMS_RECEIVED )) {
           // 一個receiver可以接收多個action的,即可以有多個intent-filter,需要在onReceive裡面對intent.getAction(action name)進行判斷。
       }
    }
}

靜態方式

  在AndroidManifest.xml的application裡面定義receiver並設置要接收的action。

< receiver android:name = ".MyBroadcastReceiver" > 

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

 

這裡的priority取值是 -1000到1000,值越大優先級越高,同時注意加上系統接收短信的限權。

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

靜態注冊的廣播接收者是一個常駐在系統中的全局監聽器,當你在應用中配置了一個靜態的BroadcastReceiver,安裝了應用後而無論應用是否處於運行狀態,廣播接收者都是已經常駐在系統中了。同時應用裡的所有receiver都在清單文件裡面,方便查看。 
  
要銷毀掉靜態注冊的廣播接收者,可以通過調用PackageManager將Receiver禁用。

動態方式

在Activity中聲明BroadcastReceiver的擴展對象,在onResume中注冊,onPause中卸載.
   

public class MainActivity extends Activity {
    MyBroadcastReceiver receiver;
    @Override
     protected void onResume() {
        // 動態注冊廣播 (代碼執行到這才會開始監聽廣播消息,並對廣播消息作為相應的處理)
        receiver = new MyBroadcastReceiver();
        IntentFilter intentFilter = new IntentFilter( "android.provider.Telephony.SMS_RECEIVED" );
        registerReceiver( receiver , intentFilter);

        super.onResume();
    }
    @Override
    protected void onPause() {  
        // 撤銷注冊 (撤銷注冊後廣播接收者將不會再監聽系統的廣播消息)
        unregisterReceiver(receiver);
        super.onPause();
    }
}

靜態注冊和動態注冊的區別

1、靜態注冊的廣播接收者一經安裝就常駐在系統之中,不需要重新啟動喚醒接收者;
動態注冊的廣播接收者隨著應用的生命周期,由registerReceiver開始監聽,由unregisterReceiver撤銷監聽,如果應用退出後,沒有撤銷已經注冊的接收者應用應用將會報錯。

2、當廣播接收者通過intent啟動一個activity或者service時,如果intent中無法匹配到相應的組件。 
動態注冊的廣播接收者將會導致應用報錯,而靜態注冊的廣播接收者將不會有任何報錯,因為自從應用安裝完成後,廣播接收者跟應用已經脫離了關系。 

發送BroadcastReceiver

發送廣播主要有兩種類型:

普通廣播

應用在需要通知各個廣播接收者的情況下使用,如 開機啟動

使用方法:sendBroadcast()

Intent intent = new Intent("android.provider.Telephony.SMS_RECEIVED"); 
//通過intent傳遞少量數據
intent.putExtra("data", "finch"); 
// 發送普通廣播
sendBroadcast(Intent); 

  普通廣播是完全異步的,可以在同一時刻(邏輯上)被所有接收者接收到,所有滿足條件的 BroadcastReceiver 都會隨機地執行其 onReceive() 方法。
  同級別接收是先後是隨機的;級別低的收到廣播;
  消息傳遞的效率比較高,並且無法中斷廣播的傳播。

有序廣播

應用在需要有特定攔截的場景下使用,如黑名單短信、電話攔截。 

使用方法:

 sendOrderedBroadcast(intent, receiverPermission);

 receiverPermission :一個接收器必須持以接收您的廣播。如果為 null ,不經許可的要求(一般都為null)。

//發送有序廣播
 sendOrderedBroadcast(intent, null);

  在有序廣播中,我們可以在前一個廣播接收者將處理好的數據傳送給後面的廣播接收者,也可以調用abortBroadcast()來終結廣播的傳播。

public void onReceive(Context arg0, Intent intent) {
  //獲取上一個廣播的bundle數據
  Bundle bundle = getResultExtras(true);//true:前一個廣播沒有結果時創建新的Bundle;false:不創建Bundle
  bundle.putString("key", "777");
  //將bundle數據放入廣播中傳給下一個廣播接收者
  setResultExtras(bundle); 
  
  //終止廣播傳給下一個廣播接收者
  abortBroadcast();
}

  高級別的廣播收到該廣播後,可以決定把該廣播是否截斷掉。
  同級別接收是先後是隨機的,如果先接收到的把廣播截斷了,同級別的例外的接收者是無法收到該廣播。
  

異步廣播

使用方法:sendStickyBroadcast() :

發出的Intent當接收Activity(動態注冊)重新處於onResume狀態之後就能重新接受到其Intent.(the Intent will be held to be re-broadcast to future receivers)。就是說sendStickyBroadcast發出的最後一個Intent會被保留,下次當Activity處於活躍的時候又會接受到它。

發這個廣播需要權限:

卸載該廣播:

removeStickyBroadcast(intent);

在卸載之前該intent會保留,接收者在可接收狀態都能獲得。

異步有序廣播

使用方法:sendStickyOrderedBroadcast(intent, resultReceiver, scheduler,
initialCode, initialData, initialExtras):

這個方法具有有序廣播的特性也有異步廣播的特性;同時需要限權:

  

總結

靜態廣播接收的處理器是由PackageManagerService負責,當手機啟動或者新安裝了應用的時候,PackageManagerService會掃描手機中所有已安裝的APP應用,將AndroidManifest.xml中有關注冊廣播的信息解析出來,存儲至一個全局靜態變量當中。

動態廣播接收的處理器是由ActivityManagerService負責,當APP的服務或者進程起來之後,執行了注冊廣播接收的代碼邏輯,即進行加載,最後會存儲在一個另外的全局靜態變量中。需要注意的是:

 1、 這個並非是一成不變的,當程序被殺死之後,已注冊的動態廣播接收器也會被移出全局變量,直到下次程序啟動,再進行動態廣播的注冊,當然這裡面的順序也已經變更了一次。

2、這裡也並沒完整的進行廣播的排序,只記錄的注冊的先後順序,並未有結合優先級的處理。

廣播發出的時候,廣播接收者接收的順序如下:

1.當廣播為普通廣播時,有如下的接收順序:

無視優先級
動態優先於靜態
同優先級的動態廣播接收器,先注冊的大於後注冊的
同優先級的靜態廣播接收器,先掃描的大於後掃描的 

2.如果廣播為有序廣播,那麼會將動態廣播處理器和靜態廣播處理器合並在一起處理廣播的消息,最終確定廣播接收的順序: 
  
優先級高的先接收 
同優先級的動靜態廣播接收器,動態優先於靜態
同優先級的動態廣播接收器,先注冊的大於後注冊的
同優先級的靜態廣播接收器,先掃描的大於後掃描的 

一些常用的系統廣播的action 和permission

開機啟動

 
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED">  </uses-permission>
網絡狀態
<action android:name="android.net.conn.CONNECTIVITY_CHANGE">  </action>
 

網絡是否可用的方法:

  public static boolean isNetworkAvailable(Context context) {  
        ConnectivityManager mgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);  
        NetworkInfo[] info = mgr.getAllNetworkInfo();  
        if (info != null) {  
            for (int i = 0; i < info.length; i++) {  
      if (info[i].getState() == NetworkInfo.State.CONNECTED) {  
                    return true;  
                }  
            }  
        }  
        return false;  
    } 
電量變化

BroadcastReceiver 的onReceive方法:

public void onReceive(Context context, Intent intent) {  
        int currLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);  //當前電量   

        int total = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 1);    //總電量  
        int percent = currLevel * 100 / total;  
        Log.i(TAG, "battery: " + percent + "%");  
    }  
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved