Android之旅十七 android中的廣播使用

來源:互聯網
上載者:User

Android之旅十七 android中的廣播使用

廣播是一種廣泛運用在應用程式之間傳輸資訊的機制,android中的廣播用於監聽系統事件或應用程式事件!android中的廣播包括普通廣播、有序廣播以及非同步廣播(粘性廣播)!

廣播又有常駐型廣播和非常駐型廣播,常駐型廣播是在xml中進行註冊的,當應用程式關閉後,如果有對應的廣播發送過來,廣播接收器還是能夠被啟用;非常駐型廣播是在代碼中進行註冊的,當應用程式關閉,廣播也就取消了,我們可以在Activity中的onCreate或者onResume方法中註冊廣播,然後在onDestory或者onPause方法中取消註冊廣播;

注意:如果是非常駐型廣播,應用程式關閉後,必須取消註冊廣播,否則會拋出異常!!

普通廣播的發送

普通廣播的發送使用方式:

sendBroadcast(Intent intent):intent表,所有匹配該廣播的意圖都能收到該廣播資訊

sendBroadcast(intent, String receiverPermission);intent與上面一樣,receiverPermission表示許可權,與之匹配許可權的廣播才能接收到相應的廣播,如果為null,表示不經許可的要求!

一、使用sendBroadcast(Intent intent)發送廣播

1)通過代碼註冊非常駐型廣播:

//定義兩個廣播接收者BroadcastReceiver receiver1=new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {System.out.println("receiver1 started!");}};BroadcastReceiver receiver2=new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {System.out.println("receiver2 started!");}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//註冊廣播IntentFilter filter=new IntentFilter();filter.addAction("com.xin.action.broadcast");registerReceiver(receiver1, filter);registerReceiver(receiver2, filter);}@Overrideprotected void onPause() {super.onPause();//取消註冊廣播unregisterReceiver(receiver1);unregisterReceiver(receiver2);}
代碼註冊屬於非常駐型廣播,我們需在Activity相應的生命週期中取消註冊廣播:unregisterReceiver

2)通過xml檔案註冊常駐型廣播,此時的MyBroadcast1、MyBroadcast2為兩個廣播類:

public class MyBroadcast1 extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {System.out.println("MyBroadcast1 started!");}}
public class MyBroadcast2 extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {System.out.println("MyBroadcast2 started!");}}

在AndroidManifest.xml中的application中添加:

                                                                                                                
代碼中的IntentFilter和xml檔案中的intent-filter是一樣的,都是Intent意圖,表示Intent(String actionName)發送出去的廣播能被哪些廣播接收者所接收!

3)廣播的發送:與之匹配的intent意圖的廣播將被啟用

Intent intent=new Intent("com.xin.action.broadcast");sendBroadcast(intent);
輸出結果為:MyBroadcast1 started,MyBroadcast2 started!!

二、使用sendBroadcast(intent, String receiverPermission)發送廣播

第二個參數的介紹如上面所示,指的是一個許可權,我們需在AndroidManifest.xml中聲明一個許可權:

裡面還有很多的屬性可供我們選擇,大家可以去自己去瞭解一下;

然後我們的發送廣播方和接收廣播方都需要該許可權定義:

發送廣播方使用該許可權:

通過方法發送廣播:sendBroadcast(intent,"com.xin.permission");其中第二個參數表示我們定義的許可權name

接收方聲明廣播許可權:

                                                        
這樣,使用帶許可權的廣播就定義好了,我們在發送方和接收方都需要給許可權進行定義,否則訊息發送不過去!

注意,通過sendBroadcast(intent,"com.xin.permission");發送的廣播,並不一定需要在receiver中添加android:permission才能接收到,測試發現,沒有添加這個也能接收到:

                                                        

有序廣播的發送

顧名思義,有序廣播就是廣播的發送是按照順序進行的,它根據優先順序別的定義android:priority的高低來進行有序發送,一個接受完發給下一個接收,優先順序越高,表示它接收到的廣播層級高,android:priority的範圍一般是在-1000到1000之間;
有序廣播和普通廣播之間的區別:

有序廣播和無序廣播的區別:我們發送完無序廣播之後,我們不知道誰先接收誰後接收,更不要說當這個接收了之後不要再發給另外的了。而有序廣播就可以做到這一點,它通過設定優先權可以決定廣播接受者的順序。

有序廣播的發送方式:

sendOrderedBroadcast(intent, receiverPermission);

sendOrderedBroadcast(intent, receiverPermission, resultReceiver,

scheduler, initialCode, initialData, initialExtras)

意圖,廣播,所有匹配的這一意圖將接收機接收廣播。

receiverPermission 這是許可權,一個接收器必須持以接收您的廣播。如果為 null ,不經許可的要求。
resultReceiver 您自己 BroadcastReceiver 來當作最後的廣播接收器。
調度自訂處理常式,用以安排 resultReceiver 回調 ; 如果為 null 將語境中的主線程舉行。
initialCode 一種結果代碼的初始值。通常為 Activity.RESULT_OK 。這個值是 -1 ;為其他 int 型 也可以,如 0,1,2;
initialData 一種結果資料的初始值。通常情況下為空白 , 是 String 類型 ;
initialExtras 一種結果額外的初始值。通常情況下為空白 , 是 Bundle;

有序廣播需注意方面:

1, 該廣播的層級有層級之分,層級數值是在 -1000 到 1000 之間 , 值越大 , 優先順序越高;
2, 同層級接收是先後是隨機的,再到層級低的收到廣播;
3, 同層級接收是先後是隨機的,如果先接收到的把廣播截斷了,同層級的例外的接收者是無法收到該廣播的,截斷廣播的方式:abortBroadcast() ;
4 ,能截斷廣播的繼續傳播,進階別的廣播收到該廣播後,可以決定把該鐘廣播是否截斷掉。
5 ,實驗現象,在這個方法發來的廣播中,代碼註冊方式中,收到廣播先後次序為:註明優先順序的、代碼
代碼示範:

下面給大家示範一下發送有序廣播,並且通過Intent在廣播之間傳遞資料,因為關於許可權那塊上面已經說了,所以在有序廣播這裡就不再描述了,通過sendOrderedBroadcast(intent, receiverPermission);方法發送有序廣播,第二個參數就設定為null了:這裡我們通過xml註冊廣播

1)定義廣播

public class MyBroadcast2 extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {System.out.println("MyBroadcast2 started!");//接收sendOrderedBroadcast傳遞過來的Intent中的參數System.out.println(intent.getStringExtra("test"));//添加另一個參數Bundle bundle=new Bundle();bundle.putString("test2", "我是從MyBroadcast2中儲存的資料");//將其封裝為Bundle對象,讓下一個廣播接收setResultExtras(bundle);}}
public class MyBroadcast1 extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {System.out.println("MyBroadcast started!");//接收sendOrderedBroadcast傳遞過來的Intent中的參數System.out.println(intent.getStringExtra("test"));//得到從上一個廣播中攜帶過來的另一個資料Bundle bundle=getResultExtras(true);System.out.println(bundle.getString("test2"));}}
2)在AndroidManifest.xml中聲明廣播:

                                                                                                        
上面聲明的廣播中,MyBroadcast2比Mybroadcast1的優先順序高!

3)發送有序廣播

Intent intent=new Intent("com.xin.action.broadcast");intent.putExtra("test", "我是sendOrderedBroadcast發送過來的資料!");sendOrderedBroadcast(intent,null);
測試結果:



因為Mybroadcast2的優先順序(1000)比Mybroadcast1(900)的高,所以廣播通過sendOrderedBroadcast發送出去後,首先被Mybroadcast2接收,然後再Mybroadcast2中通過setResultExtras設定了另一些參數一起傳到Mybroadcast1,然後Mybroadcast1接收到廣播,也通過getResultExtras(true)接收從Mybroadcast2中攜帶過來的資料,所以出現上面的結果!<喎?http://www.bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+vq2y4srUt6LP1qOs1NrKudPDc2VuZEJyb2FkY2FzdMqxuvKjrMjnufvU2kJyb2FkY2FzdFJlY2VpdmVy1tDKudPDc2V0UmVzdWx0RXh0cmFzu/LV32dldFJlc3VsdEV4dHJhc6Oss8zQ8rvhsai07aOs0vLOqsv8t6LLzbXEsrvKx9PQ0PK547KlITwvcD4KPHA+16LS4qO6PGJyPgoxoaLI57n7ysfU2rT6wuvW0NeisuG1xKOsztLDx7/J0tTNqLn9ZmlsdGVyLnNldFByaW9yaXR5KDEwMDApO8C0yejWw8bk08XPyLy2o6zV4sDvvs2yu77ZwP3LtcP3wcshPC9wPgo8cD4yoaLI57n7ztLDx8/ryMPT0NDyueOypdTa0ru49kJyb2FkY2FzdFJlY2VpdmVy1tC908rVuvOjrLK71NnN+c/C0ru49rnjsqXWtNDQo6y/ydLUtffTw8bkYWJvcnRCcm9hZGNhc3QoKTvW0LbPueOypbXEt6LLzaOsuvPD5rXEueOypb2rvdPK1bK7tb0hPC9wPgo8cD48YnI+CjwvcD4KPHA+1bPQ1LnjsqUo0uyyvbnjsqUptcS3osvNPC9wPgo8cD7U2s34yc/XqNK1w/uzxrj3srvSu9H5o6zT0MjLvbLL/MrH1bPQ1LnjsqWjrNKy09DIy8u1y/zKx9Lssr2547Klo6zPyLK7zNbC28v8tcTXqNK1w/u0yrXEzsrM4sHLo6zPyMC0yMPO0sPHwcu94sv809DKssO008Msy/zT68bVzai547KltcTH+LHwvs3Kx7WxueOypcihz/vXorLhuvOjrMi7uvO3osvN0ru49tWz0NS547Klo6y547Kl1tjQwteisuG688jUyLvE3L3TytW1vdWz0NS547Klt6LLzbn9wLS1xM/7z6IhPC9wPgo8cD7G1c2oueOypdPr1bPQ1LnjsqXX7rTztcTH+LHwo7o8L3A+CjxwPs7Sw8fWqrXAo6zO0sPHz8jXorLhueOypaOsyLu687eiy82547Klo6zEx8O0zt7C28rHyrLDtLnjsqW2vMTcsbu908rVtb2jrMTHw7TI57n7ztLDx8/It6LLzbnjsqWjrLrz16Ky4bnjsqXE2KO6PC9wPgo8cD7G1c2oueOypaO6zrTXorLhueOypS0tPreiy82547KlLS0+16Ky4bnjsqUtLT6908rVsru1vbnjsqU8L3A+CjxwPtWz0NS547Klo7rOtNeisuG547KlLS0+t6LLzbnjsqUtLT7XorLhueOypS0tPsTcvdPK1bW9ueOypaOssqLH0sTcvdPK1bW9tuC0zreiy82547KltcTX7rrz0rvM9bnjsqXQxc+iPC9wPgo8cD7V4r7NysfBvdXf1q685LXEx/ix8KOsz8LD5s7Sw8fNqLn9tPrC67XEt73Kvbj4tPO80r7Z0ru49sD919OjrM7Sw8e1xLnjsqXKx9TatPrC69bQ16Ky4bXEt8ezo9ek0M2547KlOjwvcD4KPHA+0rPD5ta7sPy6rMj9uPay4srUsLTFpaO6PC9wPgo8cD48aW1nIHNyYz0="http://www.2cto.com/uploadfile/Collfiles/20140823/2014082309213077.jpg" alt="\">

我們在註冊廣播的Activity中註冊廣播:RegisterActivity,在其生命週期的onPause方法中取消註冊廣播unregisterBr

 //定義廣播BroadcastReceiver receiver=new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action=intent.getAction();int count=intent.getIntExtra("count", 0);System.out.println("action="+action+",count="+count);}};//註冊廣播@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.register);IntentFilter filter=new IntentFilter();//添加廣播Actionfilter.addAction("com.xin.action.broadcast");filter.addAction("com.xin.action.sticky.broadcast");registerReceiver(receiver, filter);}//取消註冊廣播@Overrideprotected void onPause() {super.onPause();System.out.println("RegisterBroadActivity onPause!");unregisterReceiver(receiver);}
在MainActivity中發送廣播:

    //定義一個變數,來統計點擊發送粘性廣播的次數,然後測試粘性廣播的接收是不是最後一條廣播    private int count;@Overridepublic void onClick(View v) {Intent intent=null;switch(v.getId()){case R.id.btn_send1://發出廣播sendBroadcastintent=new Intent("com.xin.action.broadcast");sendBroadcast(intent);break;case R.id.btn_send2://發出粘性廣播sendStickyBroadcastcount++;intent=new Intent("com.xin.action.sticky.broadcast");intent.putExtra("count", count);sendStickyBroadcast(intent);break;case R.id.register://啟動註冊廣播頁面intent=new Intent(MainActivity.this,RegisterBroadActivity.class);startActivity(intent);break;}}@Overrideprotected void onResume() {super.onResume();count=0;System.out.println("MainActivity onResume!");}
注意,發送粘性廣播,我們需要在AndroidManifest.xml中添加能夠發送粘性廣播的許可權,否則會報錯:

測試及結論:

當我們點擊發送sendBroadcast按鈕3次--點擊註冊按鈕,控制台無輸出結果

當我們點擊發送sendStickyBroadcast按鈕4次--點擊註冊按鈕,控制台輸出結果:action=com.xin.action.sticky.broadcast,count=4

這就是普通廣播和粘性廣播的區別
sendBroadcast發送出去的廣播,如果沒有廣播進行註冊,那麼該廣告也就接收不到了,當重新註冊廣播後,也接收不到
sendStickyBroadcast發送出去的廣播,如果沒有廣播進行註冊,那麼該廣告此時也就接收不到了,當重新註冊廣播後,會接收到,並且會接受sendStickyBroadcast發出去的最後一條廣播,所以上面的輸出結果中點擊發送stickybroadcast 4次,count變為4,那麼當重新註冊廣播後,控制台會輸出結果count=4;
sendStickyBroadcast發出的最後一個Intent會被保留,下次當Recevier處於活躍的 時候,又會接受到它。

當我們需要移除掉粘性廣播的時候,調用方法:removeStickyBroadcast(intent);即可清除掉粘性廣播

還有一個發送廣播的方式:sendStickyOrderedBroadcast (),測試在這個方法發來的廣播,代碼註冊方式中,收到廣播先後次序為:註明優先順序的、代碼註冊的、沒有優先順序的;如果都沒有優先順序,代碼註冊收到為最先。

上面給大家介紹了廣播操作中的幾種方式:

發送廣播:sendBroadcast(Intent intent)、sendBroadcast(Intent intent,String receiverPermission);

發送有序廣播:sendOrderedBroadcast(Intent intent,String receiverPermission);

發送粘性廣播:sendStickyBroadcast(Intent intent);

還有一種方式:sendStickyOrderedBroadcast();(未研究,不知道用的多不多)


在Android的廣播操作中,我們還應該知道:

1、無論對於有序廣播還是無序廣播,廣播接收器預設都是運行在主線程中的(main線程,即UI線程)。可以通過在程式中使用registerReceiver(receiver, filter, broadcastPermission, scheduler)方法中的最後一個參數指定要啟動並執行廣播接收器的線程。也可以在Manifest.xml檔案中設定(Intent-filter標籤中設定android:process)。

2、我們在代碼中註冊廣播registerBroadcast十次,那麼廣播發送過來的時候會接收十次,登出廣播只需一次!

3、每次廣播到來時 , 會重新建立 BroadcastReceiver 對象 , 並且調用 onReceive() 方法 , 執行完以後 , 該對象即被銷毀 . 當 onReceive() 方法在 10 秒內沒有執行完畢, Android 會認為該程式無響應 . 所以在BroadcastReceiver 裡不能做一些比較耗時的操作 , 否側會彈出 ANR(Application NoResponse) 的對話方塊,如果需要完成一項比較耗時的工作 , 應該通過發送 Intent 給 Service, 由 Service 來完成 . 這裡不能使用子線程來解決 , 因為 BroadcastReceiver 的生命週期很短 , 子線程可能還沒有結束BroadcastReceiver 就先結束了 .BroadcastReceiver 一旦結束 , 此時 BroadcastReceiver 的所在進程很容易在系統需要記憶體時被優先殺死 , 因為它屬於空進程 ( 沒有任何活動組件的進程 ). 如果它的宿主進程被殺死 , 那麼正在工作的子線程也會被殺死 . 所以採用子線程來解決是不可靠的 .

4、耗時的操作應該通過廣播啟動service來執行操作

BroadcastReceiver receiver=new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {Intent intent=new Intent(context,TestService.class);startService(intent);}};

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.