




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、BroadcastReceiver應用詳解據(jù)說程序員是最愛學習的群體,IT男都知道,這個行業(yè)日新月異,必須不斷地學習新知識,不斷地為自己注入新鮮的血液,才能使自己跟上技術的步伐。今天我們來講一下Android中BroadcastReceiver的相關知識。BroadcastReceiver也就是“廣播接收者”的意思,顧名思義,它就是用來接收來自系統(tǒng)和應用中的廣播。在Android系統(tǒng)中,廣播體現(xiàn)在方方面面,例如當開機完成后系統(tǒng)會產(chǎn)生一條廣播,接收到這條廣播就能實現(xiàn)開機啟動服務的功能;當網(wǎng)絡狀態(tài)改變時系統(tǒng)會產(chǎn)生一條廣播,接收到這條廣播就能及時地做出提示和保存數(shù)據(jù)等操作;當電池電量改變時,系統(tǒng)會產(chǎn)
2、生一條廣播,接收到這條廣播就能在電量低時告知用戶及時保存進度,等等。Android中的廣播機制設計的非常出色,很多事情原本需要開發(fā)者親自操作的,現(xiàn)在只需等待廣播告知自己就可以了,大大減少了開發(fā)的工作量和開發(fā)周期。而作為應用開發(fā)者,就需要數(shù)練掌握Android系統(tǒng)提供的一個開發(fā)利器,那就是BroadcastReceiver。下面我們就對BroadcastReceiver逐一地分析和演練,了解和掌握它的各種功能和用法。首先,我們來演示一下創(chuàng)建一個BroadcastReceiver,并讓這個BroadcastReceiver能夠根據(jù)我們的需要來運行。要創(chuàng)建自己的BroadcastReceiver對象
3、,我們需要繼承android.content.BroadcastReceiver,并實現(xiàn)其onReceive方法。下面我們就創(chuàng)建一個名為MyReceiver廣播接收者:1. package com.scott.receiver; 2. 3. import android.content.BroadcastReceiver; 4. import android.content.Context; 5. import android.content.Intent;
4、0; 6. import android.util.Log; 7. 8. public class MyReceiver extends BroadcastReceiver 9. 10. private static final String TAG = "MyRece
5、iver" 11. 12. Override 13. public void onReceive(Context context, Intent intent) 14. String ms
6、g = intent.getStringExtra("msg"); 15. Log.i(TAG, msg); 16. 17. 18. 在onReceive方法內,我們可以獲取隨廣播而來的Intent中的數(shù)據(jù),這非常重要,就像無線電一樣,包含很多有用的信息。在創(chuàng)建完我們的BroadcastR
7、eceiver之后,還不能夠使它進入工作狀態(tài),我們需要為它注冊一個指定的廣播地址。沒有注冊廣播地址的BroadcastReceiver就像一個缺少選臺按鈕的收音機,雖然功能俱備,但也無法收到電臺的信號。下面我們就來介紹一下如何為BroadcastReceiver注冊廣播地址。靜態(tài)注冊靜態(tài)注冊是在AndroidManifest.xml文件中配置的,我們就來為MyReceiver注冊一個廣播地址:1. <receiver android:name=".MyReceiver"> 2.
8、160; <intent-filter> 3. <action android:name="ent.action.MY_BROADCAST"/> 4.
9、60; <category android:name="ent.category.DEFAULT" /> 5. </intent-filter> 6.
10、0; </receiver> 配置了以上信息之后,只要是ent.action.MY_BROADCAST這個地址的廣播,MyReceiver都能夠接收的到。注意,這種方式的注冊是常駐型的,也就是說當應用關閉后,如果有廣播信息傳來,MyReceiver也會被系統(tǒng)調用而自動運行。動態(tài)注冊動態(tài)注冊需要在代碼中動態(tài)的指定廣播地址并注冊,通常我們是在Activity或Service注冊一個廣播,下面我們就來看一下注冊的代碼:1. MyReceiver receiver = n
11、ew MyReceiver(); 2. 3. IntentFilter filter = new IntentFilter(); 4. filter.addAction("ent.action.MY_BROADCAST"); 5.
12、60; 6. registerReceiver(receiver, filter); 注意,registerReceiver是android.content.ContextWrapper類中的方法,Activity和Service都繼承了ContextWrapper,所以可以直接調用。在實際應用中,我們在Activity或Service中注冊了一個BroadcastReceiver,當這個Activity或Service被銷毀時如果沒有解除注冊,系統(tǒng)會報一個異常,提示我們是否忘記解除注冊了。所以,記得在特定的地方執(zhí)行解除注冊操作:1. Ov
13、erride 2. protected void onDestroy() 3. super.onDestroy(); 4. unregisterReceiver(receiver); 5. 執(zhí)行這樣行代碼就可以解決問題了。注意,這種注冊方式與靜態(tài)注冊相反,不是常駐型的,也就是說廣播會跟隨程序的生命周期。我們可以根據(jù)以上任意一種方法完成注冊,當注冊完成之后,這
14、個接收者就可以正常工作了。我們可以用以下方式向其發(fā)送一條廣播:1. public void send(View view) 2. Intent intent = new Intent("ent.action.MY_BROADCAST"); 3. intent.putExtra("msg", "h
15、ello receiver."); 4. sendBroadcast(intent); 5. 注意,sendBroadcast也是android.content.ContextWrapper類中的方法,它可以將一個指定地址和參數(shù)信息的Intent對象以廣播的形式發(fā)送出去。點擊發(fā)送按鈕,執(zhí)行send方法,控制臺打印如下:看到這樣的打印信息,表明我們的廣播已經(jīng)發(fā)出去了,并且被MyReceiver準確無誤的接收到了。上面的例子只是一個接收者來接收廣播,如果有多個接收
16、者都注冊了相同的廣播地址,又會是什么情況呢,能同時接收到同一條廣播嗎,相互之間會不會有干擾呢?這就涉及到普通廣播和有序廣播的概念了。普通廣播(Normal Broadcast)普通廣播對于多個接收者來說是完全異步的,通常每個接收者都無需等待即可以接收到廣播,接收者相互之間不會有影響。對于這種廣播,接收者無法終止廣播,即無法阻止其他接收者的接收動作。為了驗證以上論斷,我們新建三個BroadcastReceiver,演示一下這個過程,F(xiàn)irstReceiver、SecondReceiver和ThirdReceiver的代碼如下:1. package com.scott.receiver;
17、 2. 3. import android.content.BroadcastReceiver; 4. import android.content.Context; 5. import android.content.Intent; 6. import android.util.Log; 7. 8. public class FirstReceiver extends
18、 BroadcastReceiver 9. 10. private static final String TAG = "NormalBroadcast" 11. 12. Override 1
19、3. public void onReceive(Context context, Intent intent) 14. String msg = intent.getStringExtra("msg"); 15.
20、 Log.i(TAG, "FirstReceiver: " + msg); 16. 17. 18. 1. public class SecondReceiver extends BroadcastReceiver 2. 3.
21、160; private static final String TAG = "NormalBroadcast" 4. 5. Override 6. public void onReceive(Context context, Intent
22、60;intent) 7. String msg = intent.getStringExtra("msg"); 8. Log.i(TAG, "SecondReceiver: " + msg); 9.
23、60; 10. 11. 1. public class ThirdReceiver extends BroadcastReceiver 2. 3. private static final String TAG = "NormalBroadc
24、ast" 4. 5. Override 6. public void onReceive(Context context, Intent intent) 7. String msg
25、0;= intent.getStringExtra("msg"); 8. Log.i(TAG, "ThirdReceiver: " + msg); 9. 10. 11. 然后再次點擊發(fā)送按鈕,發(fā)送一條廣播,控制臺打印如下:看來這三個接收者都接收到這條
26、廣播了,我們稍微修改一下三個接收者,在onReceive方法的最后一行添加以下代碼,試圖終止廣播:1. abortBroadcast(); 再次點擊發(fā)送按鈕,我們會發(fā)現(xiàn),控制臺中三個接收者仍然都打印了自己的日志,表明接收者并不能終止廣播。有序廣播(Ordered Broadcast)有序廣播比較特殊,它每次只發(fā)送到優(yōu)先級較高的接收者那里,然后由優(yōu)先級高的接受者再傳播到優(yōu)先級低的接收者那里,優(yōu)先級高的接收者有能力終止這個廣播。為了演示有序廣播的流程,我們修改一下上面三個接收者的代碼,如下:1. package com.scott.receiver;
27、160;2. 3. import android.content.BroadcastReceiver; 4. import android.content.Context; 5. import android.content.Intent; 6. import android.os.Bundle; 7. import android.util.Log; 8. 9. public
28、class FirstReceiver extends BroadcastReceiver 10. 11. private static final String TAG = "OrderedBroadcast" 12. 13.
29、 Override 14. public void onReceive(Context context, Intent intent) 15. String msg = intent.getStringExtra("msg"); 16.
30、60; Log.i(TAG, "FirstReceiver: " + msg); 17. 18. Bundle bundle = new Bundle();
31、19. bundle.putString("msg", msg + "FirstReceiver"); 20. setResultExtras(bundle); 21. 22. 23.
32、 1. public class SecondReceiver extends BroadcastReceiver 2. 3. private static final String TAG = "OrderedBroadcast" 4.
33、60; 5. Override 6. public void onReceive(Context context, Intent intent) 7. String msg = getResultExtras(true).getString("msg&
34、quot;); 8. Log.i(TAG, "SecondReceiver: " + msg); 9. 10. Bundle bundle = new
35、160;Bundle(); 11. bundle.putString("msg", msg + "SecondReceiver"); 12. setResultExtras(bundle); 13.
36、14. 15. 1. public class ThirdReceiver extends BroadcastReceiver 2. 3. private static final String TAG = "OrderedBroadcast" 4.
37、160; 5. Override 6. public void onReceive(Context context, Intent intent) 7. String msg = getResultExtras(t
38、rue).getString("msg"); 8. Log.i(TAG, "ThirdReceiver: " + msg); 9. 10. 11. 我們注意到,在FirstReceiver和SecondReceiver中最后都使用了setResultExtra
39、s方法將一個Bundle對象設置為結果集對象,傳遞到下一個接收者那里,這樣以來,優(yōu)先級低的接收者可以用getResultExtras獲取到最新的經(jīng)過處理的信息集合。代碼改完之后,我們需要為三個接收者注冊廣播地址,我們修改一下AndroidMainfest.xml文件:1. <receiver android:name=".FirstReceiver"> 2. <intent-filter android:priority="1000">
40、60; 3. <action android:name="ent.action.MY_BROADCAST"/> 4. <category android:name="ent.category.DEFAULT" />
41、5. </intent-filter> 6. </receiver> 7. <receiver android:name=".SecondReceiver"> 8. <intent-filter android:priority="999"> 9.
42、; <action android:name="ent.action.MY_BROADCAST"/> 10. <category android:name="ent.category.DEFAULT" /> 11. </intent-
43、filter> 12. </receiver> 13. <receiver android:name=".ThirdReceiver"> 14. <intent-filter android:priority="998"> 15. <action a
44、ndroid:name="ent.action.MY_BROADCAST"/> 16. <category android:name="ent.category.DEFAULT" /> 17. </intent-filter> 18. </recei
45、ver> 我們看到,現(xiàn)在這三個接收者的<intent-filter>多了一個android:priority屬性,并且依次減小。這個屬性的范圍在-1000到1000,數(shù)值越大,優(yōu)先級越高?,F(xiàn)在,我們需要修改一下發(fā)送廣播的代碼,如下:1. public void send(View view) 2. Intent intent = new Intent("ent.action
46、.MY_BROADCAST"); 3. intent.putExtra("msg", "hello receiver."); 4. sendOrderedBroadcast(intent, "scott.permission.MY_BROADCAST_PERMISSION"); 5. 注意,使用sendOrder
47、edBroadcast方法發(fā)送有序廣播時,需要一個權限參數(shù),如果為null則表示不要求接收者聲明指定的權限,如果不為null,則表示接收者若要接收此廣播,需聲明指定權限。這樣做是從安全角度考慮的,例如系統(tǒng)的短信就是有序廣播的形式,一個應用可能是具有攔截垃圾短信的功能,當短信到來時它可以先接受到短信廣播,必要時終止廣播傳遞,這樣的軟件就必須聲明接收短信的權限。所以我們在AndroidMainfest.xml中定義一個權限:1. <permission android:protectionLevel="normal" 2.
48、160; android:name="scott.permission.MY_BROADCAST_PERMISSION" /> 然后聲明使用了此權限:1. <uses-permission android:name="scott.permission.MY_BROADCAST_PERMISSION" /> 關于這部分如果有不明白的地方可以參考我之前
49、寫過的一篇文章:Android聲明和使用權限然后我們點擊發(fā)送按鈕發(fā)送一條廣播,控制臺打印如下:我們看到接收是按照順序的,第一個和第二個都在結果集中加入了自己的標記,并且向優(yōu)先級低的接收者傳遞下去。既然是順序傳遞,試著終止這種傳遞,看一看效果如何,我們修改FirstReceiver的代碼,在onReceive的最后一行添加以下代碼:1. abortBroadcast(); 然后再次運行程序,控制臺打印如下:此次,只有第一個接收者執(zhí)行了,其它兩個都沒能執(zhí)行,因為廣播被第一個接收者終止了。上面就是BroadcastReceiver的介紹,下面我將會舉幾個常見的例子加深一下大家對
50、廣播的理解和應用:1.開機啟動服務我們經(jīng)常會有這樣的應用場合,比如消息推送服務,需要實現(xiàn)開機啟動的功能。要實現(xiàn)這個功能,我們就可以訂閱系統(tǒng)“啟動完成”這條廣播,接收到這條廣播后我們就可以啟動自己的服務了。我們來看一下BootCompleteReceiver和MsgPushService的具體實現(xiàn):1. package com.scott.receiver; 2. 3. import android.content.BroadcastReceiver; 4. import android.conte
51、nt.Context; 5. import android.content.Intent; 6. import android.util.Log; 7. 8. public class BootCompleteReceiver extends BroadcastReceiver 9. 10. p
52、rivate static final String TAG = "BootCompleteReceiver" 11. 12. Override 13. public void onReceive(Context context, Intent intent
53、) 14. Intent service = new Intent(context, MsgPushService.class); 15. context.startService(service); 16.
54、; Log.i(TAG, "Boot Complete. Starting MsgPushService."); 17. 18. 19. 1. package com.scott.receiver; 2. 3. import android.app.Service; 4. import&
55、#160;android.content.Intent; 5. import android.os.IBinder; 6. import android.util.Log; 7. 8. public class MsgPushService extends Service 9. 10. private static fin
56、al String TAG = "MsgPushService" 11. 12. Override 13. public void onCreate() 14. super.on
57、Create(); 15. Log.i(TAG, "onCreate called."); 16. 17. 18. Override 19. public
58、160;int onStartCommand(Intent intent, int flags, int startId) 20. Log.i(TAG, "onStartCommand called."); 21. return super.
59、onStartCommand(intent, flags, startId); 22. 23. 24. Override 25. public IBinder onBind(Intent arg0) 26.
60、 return null; 27. 28. 然后我們需要在AndroidManifest.xml中配置相關信息:1. <!- 開機廣播接受者 -> 2. <receiver android:name=".BootCompleteReceiver"> 3. <intent-fil
61、ter> 4. <!- 注冊開機廣播地址-> 5. <action android:name="ent.action.BOOT_COMPLETED"/> 6.
62、60;<category android:name="ent.category.DEFAULT" /> 7. </intent-filter> 8. </receiver> 9. <!- 消息推送服務 -> 10. <service android:name=".MsgPushService"/&
63、gt; 我們看到BootCompleteReceiver注冊了“ent.action.BOOT_COMPLETED”這個開機廣播地址,從安全角度考慮,系統(tǒng)要求必須聲明接收開機啟動廣播的權限,于是我們再聲明使用下面的權限:1. <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> 經(jīng)過上面的幾個步驟之后,我們就完成了開機啟動的功能,將應用運行在模擬器上,然后重啟模擬器,控制臺打印如
64、下:如果我們查看已運行的服務就會發(fā)現(xiàn),MsgPushService已經(jīng)運行起來了。2.網(wǎng)絡狀態(tài)變化在某些場合,比如用戶瀏覽網(wǎng)絡信息時,網(wǎng)絡突然斷開,我們要及時地提醒用戶網(wǎng)絡已斷開。要實現(xiàn)這個功能,我們可以接收網(wǎng)絡狀態(tài)改變這樣一條廣播,當由連接狀態(tài)變?yōu)閿嚅_狀態(tài)時,系統(tǒng)就會發(fā)送一條廣播,我們接收到之后,再通過網(wǎng)絡的狀態(tài)做出相應的操作。下面就來實現(xiàn)一下這個功能:1. package com.scott.receiver; 2. 3. import android.content.BroadcastReceiver;
65、0;4. import android.content.Context; 5. import android.content.Intent; 6. import .ConnectivityManager; 7. import .NetworkInfo; 8. import android.util.Log; 9. import android.widget.Toast; 10. 1
66、1. public class NetworkStateReceiver extends BroadcastReceiver 12. 13. private static final String TAG = "NetworkStateReceiver" 14.
67、160; 15. Override 16. public void onReceive(Context context, Intent intent) 17. Log.i(TAG, "network state changed."
68、); 18. if (!isNetworkAvailable(context) 19. Toast.makeText(context, "network disconnected!", 0).show(); 20.
69、60; 21. 22. 23. /* 24. * 網(wǎng)絡是否可用 25. * 26.
70、; * param context 27. * return 28. */ 29. public static boolean isNetworkAvailable(Context context) 30.
71、0; ConnectivityManager mgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 31. NetworkInfo info = mgr.getAllNetworkInfo(); 32. &
72、#160; if (info != null) 33. for (int i = 0; i < info.length; i+) 34.
73、160; if (infoi.getState() = NetworkInfo.State.CONNECTED) 35. return true; 36. &
74、#160; 37. 38. 39. r
75、eturn false; 40. 41. 42. 再注冊一下這個接收者的信息:1. <receiver android:name=".NetworkStateReceiver"> 2. <intent-filter> 3.
76、60; <action android:name=".conn.CONNECTIVITY_CHANGE"/> 4. <category android:name="ent.category.DEFAULT" /> 5. </intent-filter>
77、;6. </receiver> 因為在isNetworkAvailable方法中我們使用到了網(wǎng)絡狀態(tài)相關的API,所以需要聲明相關的權限才行,下面就是對應的權限聲明:1. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> 我們可以測試一下,比如關閉WiFi,看看有什么效果。3.電量變化如果我們閱讀軟件,可能是全屏閱讀,這個時候用戶就看不到剩余的電量,我們就可以為他們提供電量的信息。要想做到這一點,我們需要接收一條電量變化的廣播,然后獲取百分比信息,這聽上去挺簡單的,我們就來實現(xiàn)以下:1. package com.scott.receiver; 2. 3. import android.content.BroadcastReceiver; 4. import android.content.Context; 5. im
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 幼兒園園本培訓
- 智慧園區(qū)大連礦山智慧化工園區(qū)建設
- 餐飲店食品經(jīng)營操作流程4篇
- 培訓說課教學
- 股骨骨折中醫(yī)護理查房
- 院感消毒隔離知識培訓
- 合唱的音樂課件
- 幼兒園教師的成語培訓
- 美國通識教育體系解析
- 汽車議價技巧培訓
- 中國保險行業(yè)協(xié)會官方-2023年度商業(yè)健康保險經(jīng)營數(shù)據(jù)分析報告-2024年3月
- DG∕TJ 08-87-2016 道路、排水管道成品與半成品施工及驗收規(guī)程
- 福建省福州市倉山區(qū)2022-2023學年八年級下學期期末英語試卷(含解析)
- 校園文化墻面設計施工流程
- 美學原理2爾雅滿分答案
- MOOC 工程倫理-西南石油大學 中國大學慕課答案
- 九年級上語文課本同步規(guī)范漢字字帖
- 24春國家開放大學《教育法學》終結性考試(大作業(yè))參考答案
- JTJ300-2000 港口及航道護岸工程設計與施工規(guī)范
- 血管外科科普知識宣傳
- 小米汽車發(fā)布會
評論
0/150
提交評論