廣播(掌握)
- 廣播的概念
- 現(xiàn)實(shí):電臺(tái)通過(guò)發(fā)送廣播發(fā)布消息吼旧,買(mǎi)個(gè)收音機(jī),就能收聽(tīng)
- Android:系統(tǒng)在產(chǎn)生某個(gè)事件時(shí)發(fā)送廣播未舟,應(yīng)用程序使用廣播接收者接收這個(gè)廣播圈暗,就知道系統(tǒng)產(chǎn)生了什么事件掂为。
Android系統(tǒng)在運(yùn)行的過(guò)程中,會(huì)產(chǎn)生很多事件员串,比如開(kāi)機(jī)勇哗、電量改變、收發(fā)短信寸齐、撥打電話欲诺、屏幕解鎖
廣播接收者(掌握)
- 當(dāng)一條廣播被發(fā)送出來(lái)時(shí),系統(tǒng)是在所有清單文件中遍歷渺鹦,通過(guò)匹配意圖過(guò)濾器找到能接收這條廣播的廣播接收者
IP撥號(hào)器(掌握)
原理:接收撥打電話的廣播扰法,修改廣播內(nèi)攜帶的電話號(hào)碼
-
定義廣播接收者接收打電話廣播
public class CallReceiver extends BroadcastReceiver {
//當(dāng)廣播接收者接收到廣播時(shí),此方法會(huì)調(diào)用 @Override public void onReceive(Context context, Intent intent) { //拿到用戶撥打的號(hào)碼 String number = getResultData(); //修改廣播內(nèi)的號(hào)碼 setResultData("17951" + number); }
}
-
在清單文件中定義該廣播接收者接收的廣播類型
<receiver android:name="com.itheima.ipdialer.CallReceiver"> <intent-filter > <action android:name="android.intent.action.NEW_OUTGOING_CALL"/> </intent-filter> </receiver>
-
接收打電話廣播需要權(quán)限
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
即使廣播接收者的進(jìn)程沒(méi)有啟動(dòng)毅厚,當(dāng)系統(tǒng)發(fā)送的廣播可以被該接收者接收時(shí)塞颁,系統(tǒng)會(huì)自動(dòng)啟動(dòng)該接收者所在的進(jìn)程
短信攔截器(熟悉)
系統(tǒng)收到短信時(shí)會(huì)產(chǎn)生一條廣播,廣播中包含了短信的號(hào)碼和內(nèi)容
-
定義廣播接收者接收短信廣播
public void onReceive(Context context, Intent intent) { //拿到廣播里攜帶的短信內(nèi)容 Bundle bundle = intent.getExtras(); Object[] objects = (Object[]) bundle.get("pdus"); for(Object ob : objects ){ //通過(guò)object對(duì)象創(chuàng)建一個(gè)短信對(duì)象 SmsMessage sms = SmsMessage.createFromPdu((byte[])ob); System.out.println(sms.getMessageBody()); System.out.println(sms.getOriginatingAddress()); }
}
系統(tǒng)創(chuàng)建廣播時(shí)吸耿,把短信存放到一個(gè)數(shù)組祠锣,然后把數(shù)據(jù)以pdus為key存入bundle,再把bundle存入intent
-
清單文件中配置廣播接收者接收的廣播類型咽安,注意要設(shè)置優(yōu)先級(jí)屬性锤岸,要保證優(yōu)先級(jí)高于短信應(yīng)用,才可以實(shí)現(xiàn)攔截
<receiver android:name="com.itheima.smslistener.SmsReceiver"> <intent-filter android:priority="1000"> <action android:name="android.provider.Telephony.SMS_RECEIVED"/> </intent-filter> </receiver>
-
添加權(quán)限
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
4.0之后板乙,廣播接收者所在的應(yīng)用必須啟動(dòng)過(guò)一次是偷,才能生效
4.0之后,如果廣播接收者所在應(yīng)用被用戶手動(dòng)關(guān)閉了募逞,那么再也不會(huì)啟動(dòng)了蛋铆,直到用戶再次手動(dòng)啟動(dòng)該應(yīng)用
監(jiān)聽(tīng)SD卡狀態(tài)(掌握)
-
清單文件中定義廣播接收者接收的類型,監(jiān)聽(tīng)SD卡常見(jiàn)的三種狀態(tài)放接,所以廣播接收者需要接收三種廣播
<receiver android:name="com.itheima.sdcradlistener.SDCardReceiver"> <intent-filter > <action android:name="android.intent.action.MEDIA_MOUNTED"/> <action android:name="android.intent.action.MEDIA_UNMOUNTED"/> <action android:name="android.intent.action.MEDIA_REMOVED"/> <data android:scheme="file"/> </intent-filter> </receiver>
-
廣播接收者的定義
public class SDCardReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // 區(qū)分接收到的是哪個(gè)廣播 String action = intent.getAction(); if(action.equals("android.intent.action.MEDIA_MOUNTED")){ System.out.println("sd卡就緒"); } else if(action.equals("android.intent.action.MEDIA_UNMOUNTED")){ System.out.println("sd卡被移除"); } else if(action.equals("android.intent.action.MEDIA_REMOVED")){ System.out.println("sd卡被拔出"); } } }
勒索軟件(掌握)
接收開(kāi)機(jī)廣播刺啦,在廣播接收者中啟動(dòng)勒索的Activity
-
清單文件中配置接收開(kāi)機(jī)廣播
<receiver android:name="com.itheima.lesuo.BootReceiver"> <intent-filter > <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver>
-
權(quán)限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
-
定義廣播接收者
@Override public void onReceive(Context context, Intent intent) { //開(kāi)機(jī)的時(shí)候就啟動(dòng)勒索軟件 Intent it = new Intent(context, MainActivity.class); context.startActivity(it); }
以上代碼還不能啟動(dòng)MainActivity,因?yàn)閺V播接收者的啟動(dòng)纠脾,并不會(huì)創(chuàng)建任務(wù)棧玛瘸,那么沒(méi)有任務(wù)棧,就無(wú)法啟動(dòng)activity
-
手動(dòng)設(shè)置創(chuàng)建新任務(wù)棧的flag
it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
監(jiān)聽(tīng)?wèi)?yīng)用的安裝苟蹈、卸載糊渊、更新(熟悉)
原理:應(yīng)用在安裝卸載更新時(shí),系統(tǒng)會(huì)發(fā)送廣播慧脱,廣播里會(huì)攜帶應(yīng)用的包名
-
清單文件定義廣播接收者接收的類型渺绒,因?yàn)橐O(jiān)聽(tīng)?wèi)?yīng)用的三個(gè)動(dòng)作,所以需要接收三種廣播
<receiver android:name="com.itheima.app.AppReceiver"> <intent-filter > <action android:name="android.intent.action.PACKAGE_ADDED"/> <action android:name="android.intent.action.PACKAGE_REPLACED"/> <action android:name="android.intent.action.PACKAGE_REMOVED"/> <data android:scheme="package"/> </intent-filter> </receiver>
-
廣播接收者的定義
public void onReceive(Context context, Intent intent) { //區(qū)分接收到的是哪種廣播 String action = intent.getAction(); //獲取廣播中包含的應(yīng)用包名 Uri uri = intent.getData(); if(action.equals("android.intent.action.PACKAGE_ADDED")){ System.out.println(uri + "被安裝了"); } else if(action.equals("android.intent.action.PACKAGE_REPLACED")){ System.out.println(uri + "被更新了"); } else if(action.equals("android.intent.action.PACKAGE_REMOVED")){ System.out.println(uri + "被卸載了"); } }
廣播的兩種類型(掌握)
- 無(wú)序廣播:所有跟廣播的intent匹配的廣播接收者都可以收到該廣播,并且是沒(méi)有先后順序(同時(shí)收到)
- 有序廣播:所有跟廣播的intent匹配的廣播接收者都可以收到該廣播宗兼,但是會(huì)按照廣播接收者的優(yōu)先級(jí)來(lái)決定接收的先后順序
- 優(yōu)先級(jí)的定義:-1000~1000
- 結(jié)果接收者:所有廣播接收者都接收到廣播之后躏鱼,它才接收,并且一定會(huì)接收
- abortBroadCast:阻止其他接收者接收這條廣播殷绍,類似攔截染苛,只有有序廣播可以被攔截
Service(掌握)
- 就是默默運(yùn)行在后臺(tái)的組件,可以理解為是沒(méi)有前臺(tái)的activity主到,適合用來(lái)運(yùn)行不需要前臺(tái)界面的代碼
- 服務(wù)可以被手動(dòng)關(guān)閉茶行,不會(huì)重啟,但是如果被自動(dòng)關(guān)閉镰烧,內(nèi)存充足就會(huì)重啟
- startService啟動(dòng)服務(wù)的生命周期
- onCreate-onStartCommand-onDestroy
- 重復(fù)的調(diào)用startService會(huì)導(dǎo)致onStartCommand被重復(fù)調(diào)用
進(jìn)程優(yōu)先級(jí)(掌握)
- 前臺(tái)進(jìn)程:擁有一個(gè)正在與用戶交互的activity(onResume方法被調(diào)用)的進(jìn)程
- 可見(jiàn)進(jìn)程:擁有一個(gè)非前臺(tái),但是對(duì)用戶可見(jiàn)的activity(onPause方法被調(diào)用)的進(jìn)程
- 服務(wù)進(jìn)程:擁有一個(gè)通過(guò)startService方法啟動(dòng)的服務(wù)的進(jìn)程
- 后臺(tái)進(jìn)程:擁有一個(gè)后臺(tái)activity(onStop方法被調(diào)用)的進(jìn)程
- 空進(jìn)程:沒(méi)有擁有任何活動(dòng)的應(yīng)用組件的進(jìn)程楞陷,也就是沒(méi)有任何服務(wù)和activity在運(yùn)行
電話竊聽(tīng)器(熟悉)
電話狀態(tài):空閑怔鳖、響鈴、接聽(tīng)
-
獲取電話管理器固蛾,設(shè)置偵聽(tīng)
TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); tm.listen(new MyPhoneStateListener(), PhoneStateListener.LISTEN_CALL_STATE);
-
偵聽(tīng)對(duì)象的實(shí)現(xiàn)
class MyPhoneStateListener extends PhoneStateListener{ //當(dāng)電話狀態(tài)改變時(shí)结执,此方法調(diào)用 @Override public void onCallStateChanged(int state, String incomingNumber) { // TODO Auto-generated method stub super.onCallStateChanged(state, incomingNumber); switch (state) { case TelephonyManager.CALL_STATE_IDLE://空閑 if(recorder != null){ recorder.stop(); recorder.release(); } break; case TelephonyManager.CALL_STATE_OFFHOOK://摘機(jī) if(recorder != null){ recorder.start(); } break; case TelephonyManager.CALL_STATE_RINGING://響鈴 recorder = new MediaRecorder(); //設(shè)置聲音來(lái)源 recorder.setAudioSource(MediaRecorder.AudioSource.MIC); //設(shè)置音頻文件格式 recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); recorder.setOutputFile("sdcard/haha.3gp"); //設(shè)置音頻文件編碼 recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); try { recorder.prepare(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } break; } } }