編輯:關於Android編程
學習Android一段時間,來總結下BroadcastReceiver的使用方法。
一、什麼是廣播,廣播接受者
廣播:廣泛運用在應用程序之間傳輸信息的機制。 廣播接受者(BroadcastReceiver):接收來自系統和應用中的廣播。Android系統中,廣播體現在很多方面,例如開機啟動後會發出一條廣播,當接收到這條廣播就能實現開機啟動服務的功能。當網絡狀態發生變化時產生一條廣播,接收到後能及時做出提示和保存數據等操作。當電池電量改變時,系統會產生一條廣播,接收到這條廣播就能在電量低時告知用戶及時保存進度,等等。
二、廣播注冊的兩種方式
1.靜態注冊
如果當注冊一些如短信的廣播時,需要配置權限
< 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.動態注冊
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) :接受者不能終止廣播。普通廣播對於多個接收者來說是完全異步的,通常每個接收者都無需等待即可以接收到廣播,接收者相互之間不會有影響。對於這種廣播,接收者無法終止廣播,即無法阻止其他接收者的接收動作。
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)
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”這個開機廣播地址,從安全角度考慮,系統要求必須聲明接收開機啟動廣播的權限,於是我們再聲明使用下面的權限:
經過上面的幾個步驟之後,我們就完成了開機啟動的功能,將應用運行在模擬器上,然後重啟模擬器,控制台打印如下:
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.概述 PigeonCall,中文名“飛鴿電話”,是一款Android平台的VoIP網絡電話應用,但只工作於局域網,支持給任意局域網內
今天主要修改了幾個bug,然後改了下背景圖片和圖標,添加了變動人數的功能,即:指定參與AA的人數,參與AA計算。還有就是利用getResources().getIdent
相信很多Windows電腦用戶都遇到過類似問題:當用數據線將手機和PC相連後卻無法被Windows系統識別,無論重啟PC還是手機都無效。此時,我們該如何解決
本文在《7種形式的Android Dialog使用實例》在這篇文章的基礎進行學習,具體內容如下1.概述 android原生控件向來以丑著稱(新推出的Material D