您好,登錄后才能下訂單哦!
1.廣播和廣播接收者
? ? Android中的廣播和廣播接收者相當于現實生活中的電臺和聽收音機的人,
???Android系統內部相當于已經定義好了電臺, 就是內部定義好了一些事件(外撥電話,短信到來?
?電池電量低 sd卡狀態 卸載安裝 ?開機啟動等等),我們開發者只需要注冊這個事件就ok了(注冊事
?件就是創建廣播接收者之后在清單里配置意圖過濾器的action屬性,相當于聽收音機的人調頻一樣)
? ?更確切的說,廣播接收者就是Android系統的全局監聽者,可以監聽系統的很多事件,只要廣播
?接收者注冊了這些事件,就會被這些事件觸發。
? ?★廣播接收者被觸發,底層原理應該是廣播事件會利用隱式意圖啟動符合條件的廣播接收者.?
?
2.注冊廣播接收者
? ?注冊廣播接收者有2種方式,而且一個廣播接收者配置多個過濾動作Action。
? ?★第1種:在清單里注冊
????在配置文件中注冊的接收者的特點是即使應用程序已被關閉,該接收者依然可接受它感興趣的廣播。
? ? ? ? ? ? ? ? 上面紅色特性,已經驗證過,確實如此!
????一般大多數的廣播接收者都是在清單文件中注冊,只有少量的廣播接收者是在代碼里注冊
????當然可以在清單里注冊的廣播接收者,也一定能夠在代碼里注冊。??
????
???★第2種:在Activity里注冊
?????在Activity中綁定接收者必須依附該應用程序存在,或者一個BroadcastReceiver用于更新UI,就沒有必要在
????????????? ??程序關閉時接收者還運行,故無需在AndroidManifest.xml中注冊而可以放在Activity中注冊。?
???? ?操作特別頻繁的廣播事件 ?比如 鎖屏和解鎖這種廣播接收者在清單文件里面注冊是無效的
????必需在代碼里注冊,否則會報下面這個異常。
???? ?MainActivity has leaked IntentReceiver
????? ScreenReceiver@b65bb500 that was originally registered here. Are you missing a
? ? ? ?call to unregisterReceiver()??
???? ?代碼里注冊廣播接收者
???? ?首先,定義一個類繼承BroadcastReceiver:
????? ? public class ScreenReceiver extends BroadcastReceiver
???? ?下一步,在一個Activity中注冊上面定義的廣播接收者??
????????ScreenReceiver?screenReceiver?=?new?ScreenReceiver(); //創建意圖對象過濾器 IntentFilter?intentFilter?=?new?IntentFilter(); intentFilter.addAction("android.intent.action.SCREEN_OFF"); intentFilter.addAction("android.intent.action.SCREEN_ON"); //注冊鎖屏和解鎖廣播 registerReceiver(screenReceiver,?intentFilter);
?
3.廣播接收者開發步驟
? ?第1步:定義一個類繼承廣播接收者,并在清單或代碼里注冊,包括receiver的name屬性、
????? ?過濾器的Action屬性。
? ? 第2步:復寫定義的廣播接收者類的onReceive方法,定義廣播接收者被觸發后想實現的邏輯。
???? ? 一般如果廣播接收者注冊了多個事件,還得先判斷一下事件的類型。
????????????public?void?onReceive(Context?context,?Intent?intent)?{?? ????????????????//得到事件的類型 String?action?=?intent.getAction(); ????????????}
案例:注意不同的案例獲取數據的方式
4.案例1_IP撥號器(外撥電話)
? ?■清單配置
????<receiver?android:name="com.itheima.ipdialerListener.OutGoingReceiver"?> ??????<intent-filter> ?????????<!--?配置action?new?outgoing?call?--> ?????????<action?android:name="android.intent.action.NEW_OUTGOING_CALL"/> ??????</intent-filter> ????</receiver>
???■權限?
?????<uses-permission?android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
???■廣播接收者的接收后的邏輯??
????public?class?OutGoingReceiver?extends?BroadcastReceiver?{ @Override public?void?onReceive(Context?context,?Intent?intent)?{ //獲取廣播事件的數據-電話號碼 String?phoneNumber?=?getResultData();???//直接調用BroadcastReceiver的方法 System.out.println("phoneNumber:"?+?phoneNumber); //假如電話號碼開頭是0,就是長途。 if(phoneNumber.startsWith("0")) { phoneNumber?=?"95128"?+?phoneNumber; } //改變廣播當前的數據-用修改過后電話號碼替換。 setResultData(phoneNumber);???//注意這個方法只能與有序廣播聯用? } ????}
??將應用程序安裝好,撥打一個手機號以0開始的電話號碼0123,點擊撥打按鈕,效果如下所示:
??
5.案例2_sd卡狀態監聽
??????
? ?■清單配置
???? 注意過濾器里多了一個<data android:scheme="file"/>
?????<receiver?android:name="com.itheima.sdcard.SDCardReceiver"?> ????????????<intent-filter> ????????????????<action?android:name="android.intent.action.MEDIA_MOUNTED"/> ????????????????<action?android:name="android.intent.action.MEDIA_UNMOUNTED"/> ????????????????<data?android:scheme="file"/> ????????????</intent-filter> ????????</receiver>
???■權限?
?????無
???■廣播接收者的接收后的邏輯??
????public?class?SDCardReceiver?extends?BroadcastReceiver?{ ???????? @Override ???????? public?void?onReceive(Context?context,?Intent?intent)?{ ???????? ????????//因為清單里有2個action,所以要獲取action的類型。 ???????? String?action?=?intent.getAction(); ???????? if(Intent.ACTION_MEDIA_MOUNTED.equals(action)) ???????? { ???????? System.out.println("sd卡掛載了"); ???????? }else?if(Intent.ACTION_MEDIA_UNMOUNTED.equals(action)){ ???????? System.out.println("sd卡卸載了"); ???????? }else?{ ???????? System.out.println("sd監聽出錯了"); ???????? } ???????? } ????????}
???進入2.3這些低版本的模擬器,settings-storage里面可以模擬sd的掛載與卸載。
? ??
6.案例3_短信監聽器
? ? 短信監聽的底層原理,應該是短信數據庫內容提供者者安插了內容觀察者,一旦手機接收到短
? 信,勢必短信數據庫會發生變化,內容觀察者分析到了就會發送一條短信接收的廣播,并且把短
? 信相關的信息封裝在了意圖對象里。 ?
? ?■清單配置
? ????高版本的ADT提示里沒有action對應的選項,應從低版本ADT拷貝action值到清單中。
????<receiver?android:name="com.itheima.msglistener.MsgListener"?> ????????????<intent-filter> ????????????????<action?android:name="android.provider.Telephony.SMS_RECEIVED"/> ????????????</intent-filter> ????????</receiver>
???■權限?
?????<uses-permission?android:name="android.permission.RECEIVE_SMS"/>
???■廣播接收者的接收后的邏輯??
?????注意SmsMessage對象所在的包? ?
????//獲取短信數據,可能有多條短信數據吧。 //由此可見,短信的數據在intent里的封裝的格式是Bundle,也就是map集合。 Object[]?object?=?(Object[])?intent.getExtras().get("pdus"); //創建SmsMessage對象來分離短信的各項內容?,注意SmsMessage所在的包。 for?(Object?obj?:?object)?{ ????//創建SmsMessage實例,解析短信信息:發送者、短信內容 SmsMessage?smsMessage?=?SmsMessage.createFromPdu((byte[])?obj); String?messageBody?=?smsMessage.getMessageBody(); String?originatingAddress?=?smsMessage.getOriginatingAddress(); System.out.println("短信發送者:"?+?originatingAddress); System.out.println("短信內容:"?+?messageBody); }
???
?? ?關于短信監聽,android2.3版本時沒有考慮到安全問題,4.0之后,考慮到安全問題,廣播接
? 收者需要有一個啟動界面才能生效(但不一定要求界面就要啟動,也就是說只要有個activity就行了
??)。
? ? 對于用戶來說,在2.3這些低版本設備上,對于沒有界面的短信監聽應用,如果一旦有短信發送過
? 來,應用就會被激活,在setting中的forcestop按鈕也才會變得可選,可以在setting中點擊這個按
? 鈕就能關閉應用
? ??
? ? 對于流氓程序員來說,不但可以做個沒有啟動界面和圖標的應用,更可以結合卸載監聽事件,不讓
? 安裝的流氓應用卸載,還可以加個密碼確認之后才能輸入,要多流氓就有多流氓。
?
7.案例4_應用安裝與卸載的監聽
? ?
? ?■清單配置
? ? ? 注意過濾器多了一個<data android:scheme="package" />
?????<receiver?android:name="com.itheima.packageaddandremove.PackageReceiver"?> ????????????<intent-filter> ????????????????<action?android:name="android.intent.action.PACKAGE_ADDED"?/> ????????????????<action?android:name="android.intent.action.PACKAGE_REMOVED"?/> ????????????????<data?android:scheme="package"?/> ????????????</intent-filter> ????????</receiver>
???■權限?
?????無
???■廣播接收者的接收后的邏輯??
????//得到包名 Uri?packageName??=?intent.getData(); //獲取事件類型 String?action?=?intent.getAction(); if("android.intent.action.PACKAGE_ADDED".equals(action)) { System.out.println(packageName?+?"安裝了。。。。。"); } else?if("android.intent.action.PACKAGE_REMOVED".equals(action)) { System.out.println(packageName?+?"卸載了。。。。。"); }
? ?
8.案例5_開機啟動監聽
? 如果想在廣播接收者里啟動activity,必須要為意圖指定一個任務棧標記。
? ?■清單配置
? ? ??
???■權限?
????
???■廣播接收者的接收后的邏輯??
????
??開機啟動廣播監聽,可以與很多地方相結合。如啟動activity或service,可以在service里又與
?其它的監聽事件如短信、電話監聽相結合,做出電話竊聽器這樣子之類的應用。
? ?另外,開機啟動監聽比較的費時,有時候其實是實現了,但是 Log就是不出信息,可以采用開
?啟Activity的方式(記得intent要setFlags),這樣效果就明顯了。
9.電源鍵長按廣播
? ?定義廣播類:
package?com.done.assistcarrecord.receiver; import?android.content.BroadcastReceiver; import?android.content.Context; import?android.content.Intent; import?android.util.Log; import?com.done.assistcarrecord.MyApplication; import?com.done.assistcarrecord.common.Constants; import?com.done.assistcarrecord.util.ShellUtil; import?com.done.assistcarrecord.util.log.ExceptionLogCatcher; /** ?*?Created?by?Administrator?on?2018/4/15?0015. ?*?監聽電源長按,防止模擬點擊事件時誤操作點擊了飛行模式。 ?*/ public?class?PowerBroadcastReceiver?extends?BroadcastReceiver?{ ????private?static?final?String?TAG?=?"PowerBroadcastReceiver"; ????public?static?boolean?isPowerDialogShowed?=?false;????????????????//是否出現電源長按界面 ????@Override ????public?void?onReceive(Context?context,?Intent?intent)?{ ????????//你自己先把?reasons?==?homekey?和?長按homekey?排除,剩下的做下面的處理 ????????String?reason?=?intent.getStringExtra("reason"); ????????if?(intent.getAction().equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)){ ????????????System.out.println("Intent.ACTION_CLOSE_SYSTEM_DIALOGS?:?"?+?intent.getStringExtra("reason")); ????????????if?(intent.getExtras()!=null?&&?intent.getExtras().getBoolean("myReason")){ ????????????}else?if?(reason?!=?null){ ????????????????if?(reason.equalsIgnoreCase("globalactions")){ ????????????????????//監聽電源長按鍵的方法: ????????????????????Intent?myIntent?=?new?Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); ????????????????????myIntent.putExtra("myReason",?true); ????????????????????context.sendOrderedBroadcast(myIntent,?null); ????????????????????Log.e(TAG,?"onReceive:?電源??鍵被長按"); ????????????????????ExceptionLogCatcher.getInstance().put("電源??鍵被長按"); ????????????????????isPowerDialogShowed?=?true; ????????????????????MyApplication.gHANDLER.postDelayed(new?Runnable()?{ ????????????????????????@Override ????????????????????????public?void?run()?{ ????????????????????????????ShellUtil.execCommand(Constants.CLICK_CANCEL_POWER_LONG_PRESS_DIALOG,?true); ????????????????????????} ????????????????????},500); ????????????????????isPowerDialogShowed?=?false; ????????????????????ExceptionLogCatcher.getInstance().put("模擬關閉電源對話框成功"); ????????????????}else?if?(reason.equalsIgnoreCase("homekey")){ ????????????????????//<span?>監聽</span><span?>Home鍵的方法</span> ????????????????????//在這里做一些你自己想要的操作,比如重新打開自己的鎖屏程序界面,這樣子就不會消失了 ????????????????????Log.e(TAG,?"onReceive:?Home?鍵被觸發"); ????????????????}else?if?(reason.equalsIgnoreCase("recentapps")){ ????????????????????//監聽Home鍵長按的方法 ????????????????????Log.e(TAG,?"onReceive:?Home?鍵被長按"); ????????????????} ????????????} ????????} ????} }
????在代碼里注冊(好像在清單里注冊,是接收不到廣播的)
@Override public?void?onCreate()?{ ????//監聽長按事件 ????final?IntentFilter?homeFilter?=?new?IntentFilter( ????????????Intent.ACTION_CLOSE_SYSTEM_DIALOGS); ????powerBroadcastReceiver?=?new?PowerBroadcastReceiver(); ????registerReceiver(powerBroadcastReceiver,?homeFilter);
????一般在onDestroy方法里注銷廣播
if(powerBroadcastReceiver?!=?null){ ????unregisterReceiver(powerBroadcastReceiver); ????powerBroadcastReceiver?=?null; }
????
10.TIME_TICK 廣播
? ? ?https://blog.csdn.net/mrleeapple/article/details/50525236? (系統源碼明確指出不能靜態注冊)
####################################################################################
上面講到幾個案例,都有一個共同的特點:廣播都是由系統發送的。那么可以自己定義并發送廣播嗎?
查看API會發現Context類有發送廣播的方法,Activity和Service都繼承了Context,所以這兩個對象
都可以發送廣播,或者只要有Context對象的對象都可以發送廣播。廣播就是在發送Intent,Intent用
來封裝數據并且過濾廣播接收者,發送廣播有2種方式:(系統發送廣播也是用的這2個方法)
1.發送無序廣播
? ?■發送廣播代碼:sendBroadcast
?public?void?sendUnOrder(String?content) ????{ ???? Intent?intent?=?new?Intent(); ???? //注意設置意圖對象的action,以便過濾發送給哪個廣播接收者。 ???? intent.setAction("com.itheima.UNORDER_SEND"); ???? intent.putExtra("content",?content); ???? //無序廣播的發送方法 ???? sendBroadcast(intent); ???? ????}
? ?■廣播接收者清單配置: ???
? ?只要定義一個廣播接收者,在清單里配置它的action屬性和發送代碼里的action參數一樣,發送廣
?播的方法就會將意圖Intent發送給符合條件的廣播接收者的onReceive參數里,這也印證了為什么廣播
?接收者的接收方法里會有一個Intent參數的原因:onReceive參數里的Intent就是發送這個廣播的對象
?傳遞的Intent。
? ?
2.發送有序廣播
? ■發送廣播代碼:sendOrderedBroadcast? ??
?public?void?sendOrder(String?content) ????{ ???? Intent?intent?=?new?Intent(); ???? intent.setAction("com.itheima.ORDER_SEND"); ???? //注意有序廣播的發送方法 ???? sendOrderedBroadcast(intent,?null,?new?FinalReceiver(),?null,?1,?content,?null); ????}
??■廣播接收者清單配置:??
????和接收無序廣播的廣播接收者不同,接收有序廣播的廣播接收者的過濾器除了要配置action
? ?標簽之外,過濾器本身還要設置priority屬性,表示過濾器的優先級,優先級高的過濾器的廣播
? ?接收者會優先接收到廣播。
????終極接收者無須在清單配置任何信息,連receiver也不用配置。
? ? ?
? ?■廣播接收者接收廣播代碼:?
???????
????
3.有序廣播與無序廣播的區別(**********重點***********)
??■有序廣播?
????廣播的數據可以被修改,廣播可以被攔截,但是終極接收者仍然可以接受到。
??■無序廣播??
??? ?廣播的數據不可以被修改,廣播不可以被攔截。
?
--------------------------------廣播的一些異常------------------------------------
1)IllegalStateException: Can not perform this action after onSaveInstanceState
? ??http://www.tuicool.com/articles/yU3Yji
?http://stackoverflow.com/questions/7575921/illegalstateexception-can-not-perform-this-action-after-onsaveinstancestate-wit
??
? 一是要解注冊廣播,二是在fragmentManager提交的時候采用
transaction.commitAllowingStateLoss();
2)https://blog.csdn.net/yuanyuan_186/article/details/17389699
3)收不到開機廣播:????
?????https://blog.csdn.net/baidu_27196493/article/details/78269674
4)android:報Activity has leaked IntentReceiver或者receiver is not registered錯誤 - yuanyuan_186的專欄 - CSDN博客
?
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。