Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android中BroadCastReceiver詳解

Android中BroadCastReceiver詳解

編輯:關於Android編程

BroadcastReceiver的解釋

BroadcastReceiver也就是“廣播接收者”的意思,它是用來接收來自系統和應用中的廣播。

  在Android中,Broadcast是一種廣泛運用的在應用程序之間傳輸信息的機制。而BroadcastReceiver是對發送出來的 Broadcast進行過濾接受並響應的一類組件。

下面將詳細的闡述如何發送Broadcast和使用BroadcastReceiver過濾接收的過程:

  (1)首先在需要發送信息的地方,把要發送的信息和用於過濾的信息(如Action、Category)裝入一個Intent對象,然後通過調用 sendOrderBroadcast()或sendStickyBroadcast()方法,把 Intent對象以廣播方式發送出去。

  (2)當Intent發送以後,所有已經注冊的BroadcastReceiver會檢查注冊時的IntentFilter是否與發送的Intent相匹配,若匹配則就會調用BroadcastReceiver的onReceive()方法。所以當我們定義一個BroadcastReceiver的時候,都需要實現onReceive()方法。

注冊BroadcastReceiver有兩種方式

  靜態注冊:在AndroidManifest.xml中用標簽生命注冊,並在標簽內用標簽設置過濾器。

    //繼承BroadcastReceiver,重寫onReceiver方法
        
       //使用過濾器,接收指定action廣播
      
   

  動態注冊: 使用IntentFilter在代碼中動態的注冊一個廣播

 IntentFilter intentFilter = new IntentFilter();
  //為BroadcastReceiver指定action,使之用於接收同action的廣播
 intentFilter.addAction(String);   
 registerReceiver(BroadcastReceiver,intentFilter);

 另外值得注意的是,當我們使用動態注冊時候,當這個Activity或Service被銷毀時如果沒有解除注冊,系統會報一個異常,提示我們是否忘記解除注冊了,所以我們需要在onDestroy()方法中進行解除注冊,一般:在onStart中注冊,onStop中取消unregisterReceiver:

@Override  
protected void onDestroy() {  
    super.onDestroy();  
    unregisterReceiver(receiver);  
}

  指定廣播目標Action:Intent intent = new Intent(actionString);

  並且可通過Intent攜帶消息 :intent.putExtra(“msg”, “hi,我通過廣播發送消息了”);

  發送廣播消息:Context.sendBroadcast(intent )

其中在動態注冊中可將BroadcastReceiver的繼承類進行封裝,添加構造函數和BroadcastReceiver注冊

BroadcastReceiver的案例演示

首先我們創建一個類MyBroadcastReceiver用於繼承BroadcastReceiver:
這裡重寫了一個方法就是接受廣播的意圖並匹配:

//定義的為:public static final String //ACTION_REGISTER_SUCCESS_FINISH="register.success.finish";
Constants.ACTION_REGISTER_SUCCESS_FINISH.equals(intent.getAction())

這裡是常量:定義如下:

public class MyBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent != null && Constants.ACTION_REGISTER_SUCCESS_FINISH.equals(intent.getAction())) {
                finish();
            }
        }
    }

(1)接下裡我們就通過“動態注冊”的方式使用:

        private MyBroadcastReceiver receiver = new MyBroadcastReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(BmobConstants.ACTION_REGISTER_SUCCESS_FINISH); //添加action
        registerReceiver(receiver, filter); //注冊

(2)靜態注冊的話是現在清單文件中添加:

  
              
                  
                  
              
          

(2-1)我們就可以使用代碼了:

Intent intent = new Intent("register.success.finish");  
intent.putExtra("msg", "hello receiver.");  
sendBroadcast(intent);  //發送廣播

普通廣播(Normal Broadcast)

普通廣播對於多個接收者來說是完全異步的,通常每個接收者都無需等待即可以接收到廣播,接收者相互之間不會有影響。對於這種廣播,接收者無法終止廣播,即無法阻止其他接收者的接收動作。為了驗證以上論斷,我們新建三個BroadcastReceiver,演示一下這個過程,FirstReceiver、SecondReceiver和ThirdReceiver的代碼如下:

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);  
    }  
}  
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);  
    }  
}  
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方法的最後一行添加以下代碼,試圖終止廣播:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;"> abortBroadcast();

再次點擊發送按鈕,我們會發現,控制台中三個接收者仍然都打印了自己的日志,表明接收者並不能終止廣播。

有序廣播(Ordered Broadcast)

有序廣播比較特殊,它每次只發送到優先級較高的接收者那裡,然後由優先級高的接受者再傳播到優先級低的接收者那裡,優先級高的接收者有能力終止這個廣播。
為了演示有序廣播的流程,我們修改一下上面三個接收者的代碼,如下:

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);  
    }  
}  
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);  
    }  
}  
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文件:

  
      
          
          
      
  
  
      
          
          
      
  
  
      
          
          
      
  

我們看到,現在這三個接收者的多了一個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中定義一個權限:

  

然後聲明使用了此權限:

  

關於這部分如果有不明白的地方可以參考我之前寫過的一篇文章:Android聲明和使用權限
然後我們點擊發送按鈕發送一條廣播,控制台打印如下:

我們看到接收是按照順序的,第一個和第二個都在結果集中加入了自己的標記,並且向優先級低的接收者傳遞下去。
既然是順序傳遞,試著終止這種傳遞,看一看效果如何,我們修改FirstReceiver的代碼,在onReceive的最後一行添加以下代碼:

abortBroadcast();  

然後再次運行程序,控制台打印如下:
這裡寫圖片描述
此次,只有第一個接收者執行了,其它兩個都沒能執行,因為廣播被第一個接收者終止了。
上面就是BroadcastReceiver的介紹,下面我將會舉幾個常見的例子加深一下大家對廣播的理解和應用:

1.開機啟動服務

我們經常會有這樣的應用場合,比如消息推送服務,需要實現開機啟動的功能。要實現這個功能,我們就可以訂閱系統“啟動完成”這條廣播,接收到這條廣播後我們就可以啟動自己的服務了。我們來看一下BootCompleteReceiver和MsgPushService的具體實現:

import android.content.BroadcastReceiver;  
import android.content.Context;  
import android.content.Intent;  
import android.util.Log;  

public class BootCompleteReceiver extends BroadcastReceiver {  

    private static final String TAG = "BootCompleteReceiver";  

    @Override  
    public void onReceive(Context context, Intent intent) {  
        Intent service = new Intent(context, MsgPushService.class);  
        context.startService(service);  
        Log.i(TAG, "Boot Complete. Starting MsgPushService...");  
    }  

}  
import android.app.Service;  
import android.content.Intent;  
import android.os.IBinder;  
import android.util.Log;  

public class MsgPushService extends Service {  

    private static final String TAG = "MsgPushService";  

    @Override  
    public void onCreate() {  
        super.onCreate();  
        Log.i(TAG, "onCreate called.");  
    }  

    @Override  
    public int onStartCommand(Intent intent, int flags, int startId) {  
        Log.i(TAG, "onStartCommand called.");  
        return super.onStartCommand(intent, flags, startId);  
    }  

    @Override  
    public IBinder onBind(Intent arg0) {  
        return null;  
    }  
}  

然後我們需要在AndroidManifest.xml中配置相關信息:

  
  
      
          
          
          
      
  
  
  

我們看到BootCompleteReceiver注冊了“android.intent.action.BOOT_COMPLETED”這個開機廣播地址,從安全角度考慮,系統要求必須聲明接收開機啟動廣播的權限,於是我們再聲明使用下面的權限:
[html] view plaincopy

經過上面的幾個步驟之後,我們就完成了開機啟動的功能,將應用運行在模擬器上,然後重啟模擬器,控制台打印如下:
這裡寫圖片描述

如果我們查看已運行的服務就會發現,MsgPushService已經運行起來了。

2.網絡狀態變化

在某些場合,比如用戶浏覽網絡信息時,網絡突然斷開,我們要及時地提醒用戶網絡已斷開。要實現這個功能,我們可以接收網絡狀態改變這樣一條廣播,當由連接狀態變為斷開狀態時,系統就會發送一條廣播,我們接收到之後,再通過網絡的狀態做出相應的操作。下面就來實現一下這個功能:

import android.content.BroadcastReceiver;  
import android.content.Context;  
import android.content.Intent;  
import android.net.ConnectivityManager;  
import android.net.NetworkInfo;  
import android.util.Log;  
import android.widget.Toast;  

public class NetworkStateReceiver extends BroadcastReceiver {  

    private static final String TAG = "NetworkStateReceiver";  

    @Override  
    public void onReceive(Context context, Intent intent) {  
        Log.i(TAG, "network state changed.");  
        if (!isNetworkAvailable(context)) {  
            Toast.makeText(context, "network disconnected!", 0).show();  
        }  
    }  

    /** 
     * 網絡是否可用 
     */  
    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;  
    }  
}  

再注冊一下這個接收者的信息:

  
      
          
          
      
  

因為在isNetworkAvailable方法中我們使用到了網絡狀態相關的API,所以需要聲明相關的權限才行,下面就是對應的權限聲明:

  

我們可以測試一下,比如關閉WiFi,看看有什麼效果。

3.電量變化

如果我們閱讀軟件,可能是全屏閱讀,這個時候用戶就看不到剩余的電量,我們就可以為他們提供電量的信息。要想做到這一點,我們需要接收一條電量變化的廣播,然後獲取百分比信息,這聽上去挺簡單的,我們就來實現以下:

import android.content.BroadcastReceiver;  
import android.content.Context;  
import android.content.Intent;  
import android.os.BatteryManager;  
import android.util.Log;  

public class BatteryChangedReceiver extends BroadcastReceiver {  

    private static final String TAG = "BatteryChangedReceiver";  

    @Override  
    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 + "%");  
    }  

}  

然後再注冊一下廣播接地址信息就可以了:

  
     

當然,有些時候我們是要立即獲取電量的,而不是等電量變化的廣播,比如當閱讀軟件打開時立即顯示出電池電量。我們可以按以下方式獲取:

Intent batteryIntent = getApplicationContext().registerReceiver(null,  
        new IntentFilter(Intent.ACTION_BATTERY_CHANGED));  
int currLevel = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);  
int total = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 1);  
int percent = currLevel * 100 / total;  
Log.i("battery", "battery: " + percent + "%");  
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved