編輯:關於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() {
@Override
public void onReceive(Context context, Intent intent) {
System.out.println("receiver1 started!");
}
};
BroadcastReceiver receiver2=new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
System.out.println("receiver2 started!");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//注冊廣播
IntentFilter filter=new IntentFilter();
filter.addAction("com.xin.action.broadcast");
registerReceiver(receiver1, filter);
registerReceiver(receiver2, filter);
}
@Override
protected void onPause() {
super.onPause();
//取消注冊廣播
unregisterReceiver(receiver1);
unregisterReceiver(receiver2);
}代碼注冊屬於非常駐型廣播,我們需在Activity相應的生命周期中取消注冊廣播:unregisterReceiver
2)通過xml文件注冊常駐型廣播,此時的MyBroadcast1、MyBroadcast2為兩個廣播類:
public class MyBroadcast1 extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
System.out.println("MyBroadcast1 started!");
}
}
public class MyBroadcast2 extends BroadcastReceiver{
@Override
public 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{
@Override
public 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{
@Override
public 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中攜帶過來的數據,所以出現上面的結果!<喎?/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="/uploadfile/Collfiles/20140823/2014082309213077.jpg" alt="\">
我們在注冊廣播的Activity中注冊廣播:RegisterActivity,在其生命周期的onPause方法中取消注冊廣播unregisterBr
//定義廣播
BroadcastReceiver receiver=new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action=intent.getAction();
int count=intent.getIntExtra("count", 0);
System.out.println("action="+action+",count="+count);
}
};
//注冊廣播
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.register);
IntentFilter filter=new IntentFilter();
//添加廣播Action
filter.addAction("com.xin.action.broadcast");
filter.addAction("com.xin.action.sticky.broadcast");
registerReceiver(receiver, filter);
}
//取消注冊廣播
@Override
protected void onPause() {
super.onPause();
System.out.println("RegisterBroadActivity onPause!");
unregisterReceiver(receiver);
}在MainActivity中發送廣播:
//定義一個變量,來統計點擊發送粘性廣播的次數,然後測試粘性廣播的接收是不是最後一條廣播
private int count;
@Override
public void onClick(View v) {
Intent intent=null;
switch(v.getId()){
case R.id.btn_send1://發出廣播sendBroadcast
intent=new Intent("com.xin.action.broadcast");
sendBroadcast(intent);
break;
case R.id.btn_send2://發出粘性廣播sendStickyBroadcast
count++;
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;
}
}
@Override
protected 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() {
@Override
public void onReceive(Context context, Intent intent) {
Intent intent=new Intent(context,TestService.class);
startService(intent);
}
};
Android開源項目SlidingMenu的學習筆記(二)
在前面已經介紹了SlidingMenu的用法:Android開源項目SlidingMenu的學習筆記(一),接下來再深入學習下,根據滑出項的Menu切換到對應的頁面 目錄
Android4.4新增函數訪問外部存儲
在Android 4.4系統中,外置存儲卡(SD卡)被稱為二級外部存儲設備(secondary storage),應用程序已無法往外置存儲卡(SD卡)寫入數據,並且WRI
微信支付怎麼用
微信支付是騰訊公司最新推出的一種支付方式,是集成在微信客戶端的支付功能,用戶可以通過手機完成快速的支付流程。還有一些朋友不知道微信支付怎麼用的,下面小編通過
Android四大組件之Service精通
(一)概述本節,我們繼續來研究Service(服務)組件,本節將會學習下Android中的AIDL跨進程通信的一些 概念,並不深入到源碼層次,暫時知道是什麼,會用即可!(