Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android基礎之四大組件---BroadcastReceiver

Android基礎之四大組件---BroadcastReceiver

編輯:關於Android編程

學習Android一段時間,來總結下BroadcastReceiver的使用方法。

一、什麼是廣播,廣播接受者

廣播:廣泛運用在應用程序之間傳輸信息的機制。 廣播接受者(BroadcastReceiver):接收來自系統和應用中的廣播。

Android系統中,廣播體現在很多方面,例如開機啟動後會發出一條廣播,當接收到這條廣播就能實現開機啟動服務的功能。當網絡狀態發生變化時產生一條廣播,接收到後能及時做出提示和保存數據等操作。當電池電量改變時,系統會產生一條廣播,接收到這條廣播就能在電量低時告知用戶及時保存進度,等等。

二、廣播注冊的兩種方式

1.靜態注冊
靜態注冊方式是在AndroidManifest.xml中配置。如下所示

            
                
                
            

如果當注冊一些如短信的廣播時,需要配置權限


    < intent-filter android:priority= "1000">     
        < action android:name= " android.provider.Telephony.SMS_RECEIVED"/>
    


//加上權限
< uses-permission android:name= "android.permission.RECEIVE_SMS"/>
< uses-permission android:name= "android.permission.SEND_SMS"/>
2.動態注冊
動態注冊需要在代碼中動態的指定廣播地址並注冊,通常我們是在Activity或Service注冊一個廣播,下面我們就來看一下注冊的代碼:
MyBroadcastReceiver receiver = new MyBroadcastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("com.hlh.base");
registerReceiver(receiver, filter);

但是代碼中注冊也分兩種情況
注冊方法一:registerReceiver(BroadcastReceiver receiver, IntentFilter fileter);第一個參數是我們要處理廣播的BroadcastReceiver;第二個參數是意圖過濾器。

注冊方式二:registerReceiver(receiver, filter, broadcastPermission, scheduler)第一個參數是 BroadcastReceiver (廣播接收者,可以是系統的,也可以是自定義的);第二個參數是意圖過濾器;第三個參數是廣播權限;第四個參數是 Hander ;

note:權限重復問題,如果AndroidManifest.xml注冊了該權限,用該方法再注冊,則receiver無法接收到廣播;如果AndroidManifest.xml沒有注冊該權限,該方法注冊也無法收到廣播;當該方法沒有注冊權限,AndroidManifest.xml注冊的時候,receiver可以接收到廣播。

三、Android中使用廣播的一般步驟

1.定義廣播接受者
public class MyBroadcastReceiver extends BroadcastReceiver{
    public static final String TAG= "broadcastreceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "接收到廣播" + intent.getStringExtra("msg"));
    }
}
2.注冊廣播
MyBroadcastReceiver receiver = new MyBroadcastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("com.hlh.base");
registerReceiver(receiver, filter);
3.發送廣播
Intent intent = new Intent("com.hlh.base");
intent.putExtra("msg", "love Android");
sendBroadcast(intent);
4.接收廣播、處理操作
這裡寫圖片描述

四、廣播類型

1、普通廣播(Normal Broadcast) :接受者不能終止廣播。普通廣播對於多個接收者來說是完全異步的,通常每個接收者都無需等待即可以接收到廣播,接收者相互之間不會有影響。對於這種廣播,接收者無法終止廣播,即無法阻止其他接收者的接收動作。
為了驗證以上論斷,我們新建三個BroadcastReceiver,演示一下這個過程,FirstReceiver、SecondReceiver和ThirdReceiver的代碼如下:
public class FirstReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(MyConfig.LOG, "FirstReceiver  " + intent.getStringExtra("msg"));
    }
}
public class SecondReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(MyConfig.LOG, "SecondReceiver " + intent.getStringExtra("msg"));
    }
}
public class ThirdReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(MyConfig.LOG, "ThirdReceiver " + intent.getStringExtra("msg"));
    }
}

注冊完廣播後,發送廣播,控制台打印如下:

這裡寫圖片描述

然後在三個廣播接受者的onReceive()中加入abortBroadcast()方法終止廣播。再次點擊發送按鈕,我們會發現,控制台中三個接收者仍然都打印了自己的日志,因此接收者並不能終止廣播。

2、有序廣播(Ordered Broadcast)
有序廣播按照接受者的優先級順序接收廣播,優先級別在intent-filter中的priority中聲明。-1000到1000之間,值越大,優先級越高。它每次只發送到優先級較高的接收者那裡,然後由優先級高的接受者再傳播到優先級低的接收者那裡,優先級高的接收者有能力終止這個廣播。
演示有序廣播流程,修改上面三個接收者的代碼,如下所示。
FirstReceiver.java
public class FirstReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(MyConfig.LOG, "FirstReceiver  " + intent.getStringExtra("msg"));

        Bundle bundle = new Bundle();
        bundle.putString("msg", intent.getStringExtra("msg") + " @FirstReceiver");
        setResultExtras(bundle);
    }
}

SecondReceiver.java

public class SecondReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(MyConfig.LOG, "SecondReceiver " + getResultExtras(true).getString("msg"));

        Bundle bundle = new Bundle();
        bundle.putString("msg", getResultExtras(true).getString("msg") + " @SecondReceiver");
        setResultExtras(bundle);
    }
}

ThirdReceiver.java

public class ThirdReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(MyConfig.LOG, "ThirdReceiver " + getResultExtras(true).getString("msg"));
    }
}

在FirstReceiver和SecondReceiver中最後都使用了setResultExtras方法將一個Bundle對象設置為結果集對象,傳遞到下一個接收者那裡,這樣以來,優先級低的接收者可以用getResultExtras獲取到最新的經過處理的信息集合。
代碼改完之後,我們需要為三個接收者注冊廣播地址,我們修改一下AndroidMainfest.xml文件:


            
                
                
            
        
        
            
                
                
            
        
        
            
                
                
            
        

最後,修改發送廣播的代碼:

Intent intent = new Intent("com.hlh.base");
intent.putExtra("msg", "love Android");
sendOrderedBroadcast(intent, "com.hlh.base.MY_BROADCASTRECEIVER_PERMISSION");

注意,使用sendOrderedBroadcast方法發送有序廣播時,需要一個權限參數,如果為null則表示不要求接收者聲明指定的權限,如果不為null,則表示接收者若要接收此廣播,需聲明指定權限。這樣做是從安全角度考慮的,例如系統的短信就是有序廣播的形式,一個應用可能是具有攔截垃圾短信的功能,當短信到來時它可以先接受到短信廣播,必要時終止廣播傳遞,這樣的軟件就必須聲明接收短信的權限。
所以我們在AndroidMainfest.xml中定義一個權限:

然後聲明使用了此權限:

然後我們點擊發送按鈕發送一條廣播,控制台打印如下:

這裡寫圖片描述

我們看到接收是按照順序的,第一個和第二個都在結果集中加入了自己的標記,並且向優先級低的接收者傳遞下去。
既然是順序傳遞,試著終止這種傳遞,看一看效果如何,我們修改FirstReceiver的代碼,在onReceive的最後一行添加以下代碼:abortBroadcast();
再次運行控制台只打印了
這裡寫圖片描述

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

五、實例

1.開機啟動服務

我們經常有這樣的應用場合,比如消息推送服務,需要開機啟動就能實現。實現該功能,必須訂閱開機啟動完成這條廣播,接收到這條廣播後,即可啟動我們的消息推送服務。接收開機完成的廣播接收者BootCompleteReceiver.java和消息推送服務MsgPushService.java如下所示

public class BootCompleteReceiver extends BroadcastReceiver{
    private static final String MSG = "BootCompleteReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        //啟動消息推送服務
        Intent service = new Intent(context, MsgPushService.class);
        context.startService(service);
        Log.d(MSG, "Boot Complete , Starting MsgPushService...");
    }
}
public class MsgPushService extends Service{
    private static final String TAG = "MsgPushService";

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

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

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

接下來在AnroidManifest.xml配置相關信息

    
            
                
                
                
            
    
    
    

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

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

這裡寫圖片描述

2.網絡變化服務
在某些場合,比如用戶浏覽網絡信息時,網絡突然斷開,我們要及時地提醒用戶網絡已斷開。要實現這個功能,我們可以接收網絡狀態改變這樣一條廣播,當由連接狀態變為斷開狀態時,系統就會發送一條廣播,我們接收到之後,再通過網絡的狀態做出相應的操作。下面就來實現一下這個功能:
public class NetworkStateReceiver extends BroadcastReceiver{
    private static final String TAG = "NetworkStateReceiver";
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "network state changed");
        if (!isNetworkAvailable(context)) {
            Toast.makeText(context, "network disconnected error", Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 網絡是否可用
     */
    public static boolean isNetworkAvailable(Context context) {
        ConnectivityManager ctm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo[] info = ctm.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,所以需要聲明相關的權限才行,下面就是對應的權限聲明:

六、注意的問題

BroadcastReceiver的哦你Receive()生命周期只有十秒左右,如果在 onReceive() 內做超過十秒內的事情,就會報錯。每次廣播到來時 , 會重新創建 BroadcastReceiver 對象 , 並且調用 onReceive() 方法 , 執行完以後 , 該對象即被銷毀 . 當 onReceive() 方法在 10 秒內沒有執行完畢, Android 會認為該程序無響應 . 所以在BroadcastReceiver 裡不能做一些比較耗時的操作 , 否側會彈出 ANR(Application No Response) 的對話框。如果需要完成一項比較耗時的工作 , 應該通過發送 Intent 給 Service, 由 Service 來完成 .
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved