日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BroadcastReceiver应用详解(转)

發布時間:2023/12/10 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BroadcastReceiver应用详解(转) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自: http://blog.csdn.net/liuhe688/article/details/6955668

?

問渠那得清如許?為有源頭活水來。南宋.朱熹《觀書有感》

據說程序員是最愛學習的群體,IT男都知道,這個行業日新月異,必須不斷地學習新知識,不斷地為自己注入新鮮的血液,才能使自己跟上技術的步伐。

今天我們來講一下Android中BroadcastReceiver的相關知識。

BroadcastReceiver也就是“廣播接收者”的意思,顧名思義,它就是用來接收來自系統和應用中的廣播。

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

Android中的廣播機制設計的非常出色,很多事情原本需要開發者親自操作的,現在只需等待廣播告知自己就可以了,大大減少了開發的工作量和開發周期。而作為應用開發者,就需要數練掌握Android系統提供的一個開發利器,那就是BroadcastReceiver。下面我們就對BroadcastReceiver逐一地分析和演練,了解和掌握它的各種功能和用法。

首先,我們來演示一下創建一個BroadcastReceiver,并讓這個BroadcastReceiver能夠根據我們的需要來運行。

要創建自己的BroadcastReceiver對象,我們需要繼承android.content.BroadcastReceiver,并實現其onReceive方法。下面我們就創建一個名為MyReceiver廣播接收者:

?

[java]?view plaincopy
  • package?com.scott.receiver;??
  • ??
  • import?android.content.BroadcastReceiver;??
  • import?android.content.Context;??
  • import?android.content.Intent;??
  • import?android.util.Log;??
  • ??
  • public?class?MyReceiver?extends?BroadcastReceiver?{??
  • ??????
  • ????private?static?final?String?TAG?=?"MyReceiver";??
  • ??????
  • ????@Override??
  • ????public?void?onReceive(Context?context,?Intent?intent)?{??
  • ????????String?msg?=?intent.getStringExtra("msg");??
  • ????????Log.i(TAG,?msg);??
  • ????}??
  • ??
  • }??
  • 在onReceive方法內,我們可以獲取隨廣播而來的Intent中的數據,這非常重要,就像無線電一樣,包含很多有用的信息。

    在創建完我們的BroadcastReceiver之后,還不能夠使它進入工作狀態,我們需要為它注冊一個指定的廣播地址。沒有注冊廣播地址的BroadcastReceiver就像一個缺少選臺按鈕的收音機,雖然功能俱備,但也無法收到電臺的信號。下面我們就來介紹一下如何為BroadcastReceiver注冊廣播地址。

    靜態注冊

    靜態注冊是在AndroidManifest.xml文件中配置的,我們就來為MyReceiver注冊一個廣播地址:

    ?

    [html]?view plaincopy
  • <receiver?android:name=".MyReceiver">??
  • ????????????<intent-filter>??
  • ????????????????<action?android:name="android.intent.action.MY_BROADCAST"/>??
  • ????????????????<category?android:name="android.intent.category.DEFAULT"?/>??
  • ????????????</intent-filter>??
  • ????????</receiver>??
  • 配置了以上信息之后,只要是android.intent.action.MY_BROADCAST這個地址的廣播,MyReceiver都能夠接收的到。注意,這種方式的注冊是常駐型的,也就是說當應用關閉后,如果有廣播信息傳來,MyReceiver也會被系統調用而自動運行。

    動態注冊

    動態注冊需要在代碼中動態的指定廣播地址并注冊,通常我們是在Activity或Service注冊一個廣播,下面我們就來看一下注冊的代碼:

    ?

    [java]?view plaincopy
  • MyReceiver?receiver?=?new?MyReceiver();??
  • ??????????
  • IntentFilter?filter?=?new?IntentFilter();??
  • filter.addAction("android.intent.action.MY_BROADCAST");??
  • ??????????
  • registerReceiver(receiver,?filter);??
  • 注意,registerReceiver是android.content.ContextWrapper類中的方法,Activity和Service都繼承了ContextWrapper,所以可以直接調用。在實際應用中,我們在Activity或Service中注冊了一個BroadcastReceiver,當這個Activity或Service被銷毀時如果沒有解除注冊,系統會報一個異常,提示我們是否忘記解除注冊了。所以,記得在特定的地方執行解除注冊操作:

    ?

    ?

    [java]?view plaincopy
  • @Override??
  • protected?void?onDestroy()?{??
  • ????super.onDestroy();??
  • ????unregisterReceiver(receiver);??
  • }??
  • ?

    執行這樣行代碼就可以解決問題了。注意,這種注冊方式與靜態注冊相反,不是常駐型的,也就是說廣播會跟隨程序的生命周期。

    我們可以根據以上任意一種方法完成注冊,當注冊完成之后,這個接收者就可以正常工作了。我們可以用以下方式向其發送一條廣播:

    ?

    [java]?view plaincopy
  • public?void?send(View?view)?{??
  • ????Intent?intent?=?new?Intent("android.intent.action.MY_BROADCAST");??
  • ????intent.putExtra("msg",?"hello?receiver.");??
  • ????sendBroadcast(intent);??
  • }??
  • ?

    注意,sendBroadcast也是android.content.ContextWrapper類中的方法,它可以將一個指定地址和參數信息的Intent對象以廣播的形式發送出去。

    點擊發送按鈕,執行send方法,控制臺打印如下:

    看到這樣的打印信息,表明我們的廣播已經發出去了,并且被MyReceiver準確無誤的接收到了。

    上面的例子只是一個接收者來接收廣播,如果有多個接收者都注冊了相同的廣播地址,又會是什么情況呢,能同時接收到同一條廣播嗎,相互之間會不會有干擾呢?這就涉及到普通廣播和有序廣播的概念了。

    普通廣播(Normal Broadcast)

    普通廣播對于多個接收者來說是完全異步的,通常每個接收者都無需等待即可以接收到廣播,接收者相互之間不會有影響。對于這種廣播,接收者無法終止廣播,即無法阻止其他接收者的接收動作。

    為了驗證以上論斷,我們新建三個BroadcastReceiver,演示一下這個過程,FirstReceiver、SecondReceiver和ThirdReceiver的代碼如下:

    ?

    [java]?view plaincopy
  • package?com.scott.receiver;??
  • ??
  • import?android.content.BroadcastReceiver;??
  • import?android.content.Context;??
  • import?android.content.Intent;??
  • import?android.util.Log;??
  • ??
  • public?class?FirstReceiver?extends?BroadcastReceiver?{??
  • ??????
  • ????private?static?final?String?TAG?=?"NormalBroadcast";??
  • ??????
  • ????@Override??
  • ????public?void?onReceive(Context?context,?Intent?intent)?{??
  • ????????String?msg?=?intent.getStringExtra("msg");??
  • ????????Log.i(TAG,?"FirstReceiver:?"?+?msg);??
  • ????}??
  • ??
  • }??
  • [java]?view plaincopy
  • public?class?SecondReceiver?extends?BroadcastReceiver?{??
  • ??????
  • ????private?static?final?String?TAG?=?"NormalBroadcast";??
  • ??????
  • ????@Override??
  • ????public?void?onReceive(Context?context,?Intent?intent)?{??
  • ????????String?msg?=?intent.getStringExtra("msg");??
  • ????????Log.i(TAG,?"SecondReceiver:?"?+?msg);??
  • ????}??
  • ??
  • }??
  • [java]?view plaincopy
  • public?class?ThirdReceiver?extends?BroadcastReceiver?{??
  • ??????
  • ????private?static?final?String?TAG?=?"NormalBroadcast";??
  • ??????
  • ????@Override??
  • ????public?void?onReceive(Context?context,?Intent?intent)?{??
  • ????????String?msg?=?intent.getStringExtra("msg");??
  • ????????Log.i(TAG,?"ThirdReceiver:?"?+?msg);??
  • ????}??
  • ??
  • }??
  • 然后再次點擊發送按鈕,發送一條廣播,控制臺打印如下:

    ?

    看來這三個接收者都接收到這條廣播了,我們稍微修改一下三個接收者,在onReceive方法的最后一行添加以下代碼,試圖終止廣播:

    ?

    [java]?view plaincopy
  • abortBroadcast();??
  • 再次點擊發送按鈕,我們會發現,控制臺中三個接收者仍然都打印了自己的日志,表明接收者并不能終止廣播。

    ?

    有序廣播(Ordered Broadcast)

    有序廣播比較特殊,它每次只發送到優先級較高的接收者那里,然后由優先級高的接受者再傳播到優先級低的接收者那里,優先級高的接收者有能力終止這個廣播。

    為了演示有序廣播的流程,我們修改一下上面三個接收者的代碼,如下:

    ?

    [java]?view plaincopy
  • package?com.scott.receiver;??
  • ??
  • import?android.content.BroadcastReceiver;??
  • import?android.content.Context;??
  • import?android.content.Intent;??
  • import?android.os.Bundle;??
  • import?android.util.Log;??
  • ??
  • public?class?FirstReceiver?extends?BroadcastReceiver?{??
  • ??????
  • ????private?static?final?String?TAG?=?"OrderedBroadcast";??
  • ??????
  • ????@Override??
  • ????public?void?onReceive(Context?context,?Intent?intent)?{??
  • ????????String?msg?=?intent.getStringExtra("msg");??
  • ????????Log.i(TAG,?"FirstReceiver:?"?+?msg);??
  • ??????????
  • ????????Bundle?bundle?=?new?Bundle();??
  • ????????bundle.putString("msg",?msg?+?"@FirstReceiver");??
  • ????????setResultExtras(bundle);??
  • ????}??
  • ??
  • }??
  • [java]?view plaincopy
  • public?class?SecondReceiver?extends?BroadcastReceiver?{??
  • ??????
  • ????private?static?final?String?TAG?=?"OrderedBroadcast";??
  • ??????
  • ????@Override??
  • ????public?void?onReceive(Context?context,?Intent?intent)?{??
  • ????????String?msg?=?getResultExtras(true).getString("msg");??
  • ????????Log.i(TAG,?"SecondReceiver:?"?+?msg);??
  • ??????????
  • ????????Bundle?bundle?=?new?Bundle();??
  • ????????bundle.putString("msg",?msg?+?"@SecondReceiver");??
  • ????????setResultExtras(bundle);??
  • ????}??
  • ??
  • }??
  • [java]?view plaincopy
  • public?class?ThirdReceiver?extends?BroadcastReceiver?{??
  • ??????
  • ????private?static?final?String?TAG?=?"OrderedBroadcast";??
  • ??????
  • ????@Override??
  • ????public?void?onReceive(Context?context,?Intent?intent)?{??
  • ????????String?msg?=?getResultExtras(true).getString("msg");??
  • ????????Log.i(TAG,?"ThirdReceiver:?"?+?msg);??
  • ????}??
  • ??
  • }??
  • 我們注意到,在FirstReceiver和SecondReceiver中最后都使用了setResultExtras方法將一個Bundle對象設置為結果集對象,傳遞到下一個接收者那里,這樣以來,優先級低的接收者可以用getResultExtras獲取到最新的經過處理的信息集合。

    ?

    代碼改完之后,我們需要為三個接收者注冊廣播地址,我們修改一下AndroidMainfest.xml文件:

    ?

    [html]?view plaincopy
  • <receiver?android:name=".FirstReceiver">??
  • ????<intent-filter?android:priority="1000">??
  • ????????<action?android:name="android.intent.action.MY_BROADCAST"/>??
  • ????????<category?android:name="android.intent.category.DEFAULT"?/>??
  • ????</intent-filter>??
  • </receiver>??
  • <receiver?android:name=".SecondReceiver">??
  • ????<intent-filter?android:priority="999">??
  • ????????<action?android:name="android.intent.action.MY_BROADCAST"/>??
  • ????????<category?android:name="android.intent.category.DEFAULT"?/>??
  • ????</intent-filter>??
  • </receiver>??
  • <receiver?android:name=".ThirdReceiver">??
  • ????<intent-filter?android:priority="998">??
  • ????????<action?android:name="android.intent.action.MY_BROADCAST"/>??
  • ????????<category?android:name="android.intent.category.DEFAULT"?/>??
  • ????</intent-filter>??
  • </receiver>??
  • 我們看到,現在這三個接收者的<intent-filter>多了一個android:priority屬性,并且依次減小。這個屬性的范圍在-1000到1000,數值越大,優先級越高。

    ?

    現在,我們需要修改一下發送廣播的代碼,如下:

    ?

    [java]?view plaincopy
  • public?void?send(View?view)?{??
  • ????Intent?intent?=?new?Intent("android.intent.action.MY_BROADCAST");??
  • ????intent.putExtra("msg",?"hello?receiver.");??
  • ????sendOrderedBroadcast(intent,?"scott.permission.MY_BROADCAST_PERMISSION");??
  • }??
  • 注意,使用sendOrderedBroadcast方法發送有序廣播時,需要一個權限參數,如果為null則表示不要求接收者聲明指定的權限,如果不為null,則表示接收者若要接收此廣播,需聲明指定權限。這樣做是從安全角度考慮的,例如系統的短信就是有序廣播的形式,一個應用可能是具有攔截垃圾短信的功能,當短信到來時它可以先接受到短信廣播,必要時終止廣播傳遞,這樣的軟件就必須聲明接收短信的權限。

    ?

    所以我們在AndroidMainfest.xml中定義一個權限:

    ?

    [html]?view plaincopy
  • <permission?android:protectionLevel="normal"??
  • ????????????android:name="scott.permission.MY_BROADCAST_PERMISSION"?/>??
  • 然后聲明使用了此權限:

    ?

    ?

    [html]?view plaincopy
  • <uses-permission?android:name="scott.permission.MY_BROADCAST_PERMISSION"?/>??
  • 關于這部分如果有不明白的地方可以參考我之前寫過的一篇文章:Android聲明和使用權限

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

    我們看到接收是按照順序的,第一個和第二個都在結果集中加入了自己的標記,并且向優先級低的接收者傳遞下去。

    既然是順序傳遞,試著終止這種傳遞,看一看效果如何,我們修改FirstReceiver的代碼,在onReceive的最后一行添加以下代碼:

    ?

    [java]?view plaincopy
  • abortBroadcast();??
  • 然后再次運行程序,控制臺打印如下:

    ?

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

    上面就是BroadcastReceiver的介紹,下面我將會舉幾個常見的例子加深一下大家對廣播的理解和應用:

    1.開機啟動服務

    我們經常會有這樣的應用場合,比如消息推送服務,需要實現開機啟動的功能。要實現這個功能,我們就可以訂閱系統“啟動完成”這條廣播,接收到這條廣播后我們就可以啟動自己的服務了。我們來看一下BootCompleteReceiver和MsgPushService的具體實現:

    ?

    [java]?view plaincopy
  • package?com.scott.receiver;??
  • ??
  • import?android.content.BroadcastReceiver;??
  • import?android.content.Context;??
  • import?android.content.Intent;??
  • import?android.util.Log;??
  • ??
  • public?class?BootCompleteReceiver?extends?BroadcastReceiver?{??
  • ??????
  • ????private?static?final?String?TAG?=?"BootCompleteReceiver";??
  • ??????
  • ????@Override??
  • ????public?void?onReceive(Context?context,?Intent?intent)?{??
  • ????????Intent?service?=?new?Intent(context,?MsgPushService.class);??
  • ????????context.startService(service);??
  • ????????Log.i(TAG,?"Boot?Complete.?Starting?MsgPushService...");??
  • ????}??
  • ??
  • }??
  • [java]?view plaincopy
  • package?com.scott.receiver;??
  • ??
  • import?android.app.Service;??
  • import?android.content.Intent;??
  • import?android.os.IBinder;??
  • import?android.util.Log;??
  • ??
  • public?class?MsgPushService?extends?Service?{??
  • ??
  • ????private?static?final?String?TAG?=?"MsgPushService";??
  • ??????
  • ????@Override??
  • ????public?void?onCreate()?{??
  • ????????super.onCreate();??
  • ????????Log.i(TAG,?"onCreate?called.");??
  • ????}??
  • ??????
  • ????@Override??
  • ????public?int?onStartCommand(Intent?intent,?int?flags,?int?startId)?{??
  • ????????Log.i(TAG,?"onStartCommand?called.");??
  • ????????return?super.onStartCommand(intent,?flags,?startId);??
  • ????}??
  • ??
  • ????@Override??
  • ????public?IBinder?onBind(Intent?arg0)?{??
  • ????????return?null;??
  • ????}??
  • }??
  • 然后我們需要在AndroidManifest.xml中配置相關信息:

    ?

    ?

    [html]?view plaincopy
  • <!--?開機廣播接受者?-->??
  • <receiver?android:name=".BootCompleteReceiver">??
  • ????<intent-filter>??
  • ????????<!--?注冊開機廣播地址-->??
  • ????????<action?android:name="android.intent.action.BOOT_COMPLETED"/>??
  • ????????<category?android:name="android.intent.category.DEFAULT"?/>??
  • ????</intent-filter>??
  • </receiver>??
  • <!--?消息推送服務?-->??
  • <service?android:name=".MsgPushService"/>??
  • 我們看到BootCompleteReceiver注冊了“android.intent.action.BOOT_COMPLETED”這個開機廣播地址,從安全角度考慮,系統要求必須聲明接收開機啟動廣播的權限,于是我們再聲明使用下面的權限:

    ?

    ?

    [html]?view plaincopy
  • <uses-permission?android:name="android.permission.RECEIVE_BOOT_COMPLETED"?/>??
  • 經過上面的幾個步驟之后,我們就完成了開機啟動的功能,將應用運行在模擬器上,然后重啟模擬器,控制臺打印如下:

    ?

    如果我們查看已運行的服務就會發現,MsgPushService已經運行起來了。

    2.網絡狀態變化

    在某些場合,比如用戶瀏覽網絡信息時,網絡突然斷開,我們要及時地提醒用戶網絡已斷開。要實現這個功能,我們可以接收網絡狀態改變這樣一條廣播,當由連接狀態變為斷開狀態時,系統就會發送一條廣播,我們接收到之后,再通過網絡的狀態做出相應的操作。下面就來實現一下這個功能:

    ?

    [java]?view plaincopy
  • package?com.scott.receiver;??
  • ??
  • import?android.content.BroadcastReceiver;??
  • import?android.content.Context;??
  • import?android.content.Intent;??
  • import?android.net.ConnectivityManager;??
  • import?android.net.NetworkInfo;??
  • import?android.util.Log;??
  • import?android.widget.Toast;??
  • ??
  • public?class?NetworkStateReceiver?extends?BroadcastReceiver?{??
  • ??????
  • ????private?static?final?String?TAG?=?"NetworkStateReceiver";??
  • ??????
  • ????@Override??
  • ????public?void?onReceive(Context?context,?Intent?intent)?{??
  • ????????Log.i(TAG,?"network?state?changed.");??
  • ????????if?(!isNetworkAvailable(context))?{??
  • ????????????Toast.makeText(context,?"network?disconnected!",?0).show();??
  • ????????}??
  • ????}??
  • ??????
  • ????/**?
  • ?????*?網絡是否可用?
  • ?????*??
  • ?????*?@param?context?
  • ?????*?@return?
  • ?????*/??
  • ????public?static?boolean?isNetworkAvailable(Context?context)?{??
  • ????????ConnectivityManager?mgr?=?(ConnectivityManager)?context.getSystemService(Context.CONNECTIVITY_SERVICE);??
  • ????????NetworkInfo[]?info?=?mgr.getAllNetworkInfo();??
  • ????????if?(info?!=?null)?{??
  • ????????????for?(int?i?=?0;?i?<?info.length;?i++)?{??
  • ????????????????if?(info[i].getState()?==?NetworkInfo.State.CONNECTED)?{??
  • ????????????????????return?true;??
  • ????????????????}??
  • ????????????}??
  • ????????}??
  • ????????return?false;??
  • ????}??
  • ??
  • }??
  • 再注冊一下這個接收者的信息:

    ?

    ?

    [html]?view plaincopy
  • <receiver?android:name=".NetworkStateReceiver">??
  • ????<intent-filter>??
  • ????????<action?android:name="android.net.conn.CONNECTIVITY_CHANGE"/>??
  • ????????<category?android:name="android.intent.category.DEFAULT"?/>??
  • ????</intent-filter>??
  • </receiver>??
  • 因為在isNetworkAvailable方法中我們使用到了網絡狀態相關的API,所以需要聲明相關的權限才行,下面就是對應的權限聲明:

    ?

    ?

    [html]?view plaincopy
  • <uses-permission?android:name="android.permission.ACCESS_NETWORK_STATE"/>??
  • 我們可以測試一下,比如關閉WiFi,看看有什么效果。

    ?

    3.電量變化

    如果我們閱讀軟件,可能是全屏閱讀,這個時候用戶就看不到剩余的電量,我們就可以為他們提供電量的信息。要想做到這一點,我們需要接收一條電量變化的廣播,然后獲取百分比信息,這聽上去挺簡單的,我們就來實現以下:

    ?

    [java]?view plaincopy
  • package?com.scott.receiver;??
  • ??
  • import?android.content.BroadcastReceiver;??
  • import?android.content.Context;??
  • import?android.content.Intent;??
  • import?android.os.BatteryManager;??
  • import?android.util.Log;??
  • ??
  • public?class?BatteryChangedReceiver?extends?BroadcastReceiver?{??
  • ??
  • ????private?static?final?String?TAG?=?"BatteryChangedReceiver";??
  • ??????
  • ????@Override??
  • ????public?void?onReceive(Context?context,?Intent?intent)?{??
  • ????????int?currLevel?=?intent.getIntExtra(BatteryManager.EXTRA_LEVEL,?0);??//當前電量??
  • ????????int?total?=?intent.getIntExtra(BatteryManager.EXTRA_SCALE,?1);??????//總電量??
  • ????????int?percent?=?currLevel?*?100?/?total;??
  • ????????Log.i(TAG,?"battery:?"?+?percent?+?"%");??
  • ????}??
  • ??
  • }??
  • 然后再注冊一下廣播接地址信息就可以了:

    ?

    ?

    [html]?view plaincopy
  • <receiver?android:name=".BatteryChangedReceiver">??
  • ????<intent-filter>??
  • ????????<action?android:name="android.intent.action.BATTERY_CHANGED"/>??
  • ????????<category?android:name="android.intent.category.DEFAULT"?/>??
  • ????</intent-filter>??
  • </receiver>??
  • 當然,有些時候我們是要立即獲取電量的,而不是等電量變化的廣播,比如當閱讀軟件打開時立即顯示出電池電量。我們可以按以下方式獲取:

    ?

    [java]?view plaincopy
  • Intent?batteryIntent?=?getApplicationContext().registerReceiver(null,??
  • ????????new?IntentFilter(Intent.ACTION_BATTERY_CHANGED));??
  • int?currLevel?=?batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL,?0);??
  • int?total?=?batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE,?1);??
  • int?percent?=?currLevel?*?100?/?total;??
  • Log.i("battery",?"battery:?"?+?percent?+?"%");?
  • 總結

    以上是生活随笔為你收集整理的BroadcastReceiver应用详解(转)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。