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

Android復習之BroadCastReceiver

編輯:關於Android編程

是什麼

BroadCastReceiver是四大組件之一,相當於一個全局的監聽器,用於監聽系統全局的廣播。

怎麼樣

由於BroadCastReceiver是全局監聽器,因此它可以方便的實現系統中不同組件之間的通信。

怎麼用

實現步驟分三步

創建BroadCastReceiver 創建需要啟動BroadCastReceiver的Intent 調用Context的sendBroadCast或sendOrderBroadCast方法啟動指定的receiver

receiver需要繼承BroadCastReceiver並實現onReceive方法,當程序發出一個BroadCast的Intent之後所有匹配了改Intent的BroadCastreceover都有可能會被啟動

與Activity和Service不同的是BroadCastReceiver生命周期比較短,本質是一個系統級全局的監聽器,專門負責監聽個程序所發出的BroadCast

實現了BroadCastReceive就要有與只匹配的Intent

兩種匹配intent方式

在代碼中動態設置,通過intentFilter設置Action 在AndroidMainifest中的receiver標簽中設置Action

值得注意的是:

執行完onReceiver後實例會被銷毀,生命周期短 發送廣播後如果沒有與之匹配的receiver,程序不會報錯,這與Activity和Service不同 不能在onReceiver方法中做耗時操作,10秒內onReceive方法沒有執行完成會被認為程序無響應,因此耗時操作應該在Service中開啟線程來執行

兩種發送廣播的方式

sendBroadCast()普通廣播 sendOrderBroadCast()有序廣播
有序廣播會根據優先級別按順序執行接收者,優先接到的可通過abortBroadCast來終止廣播,也可以通過setResultExtra()來修改接收到的值並傳遞,下一個廣播在通過getResultExtra()來獲取。

兩種注冊方式

動態注冊,廣播會跟隨程序的生命周期,在Activity或service中注冊,但是必須到onDestroy中銷毀,不然會報錯 靜態注冊,常駐型,即使應用關閉,也能夠接收廣播

代碼演示

xml裡面兩個按鈕,一個動態注冊,一個靜態注冊

這裡寫圖片描述

按照前面說的第一步,先創建一個類TestReceiver繼承BroadcastReceiver,該類是一個抽象類,需要實現裡面的抽象方法onReceive(Context context, Intent intent)

public class TestReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String sky = intent.getStringExtra("sky");
        Log.d("TestReceiver", "接收到的值" + sky);


    }
}

這裡面的Intent就是接收傳過來的值

第二步,創建匹配該broadCastReceiver的Intent,首先要給broadCastReceiver設置一個Action,然後再通過給Intent設置Action,如果Intent的Action與broadCastReceiver的Action匹配,也就是一樣,則broadCastReceiver將會被系統啟動,接收到Intent傳過來的消息。首先注冊廣播,由上面可知注冊有動態注冊和靜態注冊,

動態注冊代碼
receiver = new TestReceiver();
        registerReceiver(receiver, new IntentFilter(ACTION));

由於動態注冊廣播會跟隨程序的生命周期,所以注冊時實例化應該聲明為全局變量,以便在onDestroy中注銷,否則會報錯!

通過registerReceiver方法來動態注冊廣播,參數1是被注冊的廣播,參數2是IntentFilter,設置broadCastReceiver的Action,
2. 動態注冊代碼


            
                
            
        

在AndroidMainifest中注冊,這是常駐性注冊,即使應用被關閉,接收到匹配的Action,廣播也能被啟動,也是通過Iintent-filter標簽來設置Action。

這兩種注冊方式,根據需求進行選擇,選擇動態注冊,務必記得手動注銷

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

第三步,發送廣播,注冊好了廣播,就可以使用了,在按鈕的點擊事件中添加如下代碼

   /**
                 * 匹配Intent,與這個Action相同的接收者都會接收到。
                 */
                Intent intent = new Intent();
                intent.setAction(ACTION);
                intent.putExtra("sky", "I appreciate the man who are goood at Android");
                sendBroadcast(intent);

這裡的ACTION與注冊廣播時的ACTION要一樣,否則匹配失敗,無法接收

 public static final String ACTION = "com.cd.broadcastreceiver";

這個ACTION字符串可以是任意的,但是為了看起來規范,選擇包名的形式。

點擊按鈕看到如下輸出

這裡寫圖片描述

說明廣播是接收到了。

這裡是一個接收者一個發送者,而且匹配的ACTION一致,如果有多個接收者匹配了同一個發送者的ACTION會不會都收到,或者多個接收者之間有沒有相互的影響呢?

在上面的基礎上添加另外兩個接收者TestReceiver2和TestReceiver3,然後我選擇靜態注冊

  
        
            
                
            
        
        
            
                
            
        
        
            
                
            
        

這裡三個接收者都是設置的相同的ACTION.

發送代碼不變,點擊按鈕輸出如下

這裡寫圖片描述

三個都接收到了,而且輸出順序是按照AndroidMainifest注冊順序輸出的,不確定這兩者之間有沒有關系,知道的麻煩告訴我一聲。

接著我在第一個廣播的onReceiver 方法中添加了abortBroadcast();終止廣播。

這裡寫圖片描述

再次運行,輸出如下
這裡寫圖片描述

還是接收到了,表明接收者不能終止廣播,注意到在abortBroadcast的地方報了個錯,這個先不管,

那麼如何終止廣播或者在廣播傳播的過程中修改廣播內容呢?可以使用有序廣播

有序廣播每次只發送到優先級高的那裡,然後由優先級高的依次往優先級低的發送,優先級高的可以決定終止或繼續傳播這個廣播。
修改之前三個接收者的代碼如下

第一個廣播TestReceiver

public class TestReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String sky = intent.getStringExtra("sky");
        Log.d("TestReceiver", "接收到的值" + sky);
        Bundle bundle=new Bundle();
        bundle.putString("message",sky+"from TestReceiver");
        setResultExtras(bundle);
    }
}

第二個廣播TestReceiver2

public class TestReceiver2 extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String sky = getResultExtras(true).getString("sky");
        Log.d("TestReceiver2", "接收到的值" + sky);
        Bundle bundle=new Bundle();
        bundle.putString("message",sky+"message from TestReceiver2");
        setResultExtras(bundle);
    }
}

第三個廣播TestReceiver3

public class TestReceiver3 extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String sky = getResultExtras(true).getString("sky");
        Log.d("TestReceiver3", "接收到的值" + sky);

    }
}

通過setResultExtras寫入數據,getResultExtras獲取數據

AndroidMainifest修改如下


        
            
                
            
        
        
            
                
            
        
        
            
                
            
        

注意到,在intent-filter標簽下,添加了android:priority屬性,這是是設置廣播的優先級,取值范圍是-1000~1000,值越大,優先級越高,如果沒有設置優先級會報這個錯

BroadcastReceiver trying to return result during a non-ordered broadcast

而且只有第一個聲明的能接收到,後面的無法接收。
修改發送廣播的代碼

 Intent intent1 = new Intent();
                intent1.setAction(ACTION);
                intent1.putExtra("sky","register in AndroidMainifest");
                sendOrderedBroadcast(intent1,null);

將sendBroadcast改為sendOrderedBroadcast,這裡多了一個權限參數,null表示不用權限,想了解權限可看這篇文章Android聲明和使用權限

修改完,點擊按鈕輸出為

這裡寫圖片描述

由圖可以看到,接收順序是按照優先級來執行的,以及傳遞的值也是依次接收到了,【這裡有個疑問,在輸出的最後一行,第一個廣播又輸出了一次,這個很不可思議,不是廣播在onReceive方法執行完後,實例就被摧毀了麼,為什麼會執行兩次呢?如果有人看到這篇文章,並且知道造成的原因,麻煩告訴我一下,謝謝】

現在再次在TestReceiver的onReceiver中調用abortBroadcast();
輸出如下
這裡寫圖片描述
可以看到,優先級高的接收到了廣播,後面優先級低的就被終止了,而且沒有報之前那個錯了。所以abortBroadcast要在有序廣播中使用。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved