Android基礎-07 廣播與服務
01_爲什麼需要廣播接受者
電臺:中央人民廣播電臺,93.4mhz; 收音機:93.4mhz,收聽廣播;
Android系統內置的電臺,發送一些事件:接收短信、外撥電話、電量不足、電量充滿、SD插拔、軟件安裝與下載等。
Android應用程序中的收音機:廣播接收者,指定需要接收的事件類型; 可以做一些對用戶有用的業務邏輯操作。
廣播接收者的特點:
1、即使廣播接收者沒有運行,當廣播事件到達的時候,系統會自動啓動廣播接收者,並且調用onReceive方法處理消息;
2、從android4.0之後,添加了一個新特點,如果強制停止就相當於凍結了這個程序,只能等到下次手工啓動後才能生效;
02廣播接受者案例ip撥號器(重點)
17951 139999999
步驟:
1、準備一個收音機:
創建一個廣播接收者的類,繼承BroadcastReceiver:
public class OutCallBroadcastReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
}
}
2、插上一塊電池:
<receiver android:name="com.itheima.ipdail.OutCallBroadcastReceiver"></receiver>
3、調整到一定的頻道:
<receiver android:name="com.itheima.ipdail.OutCallBroadcastReceiver">
<intent-filter >
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
4、添加權限到清單文件:
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
03廣播接受者案例短信監聽器(重點)
配置文件:
<receiver android:name="com.iheima.smslistener.SMSBroadcastReceiver">
<intent-filter >
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
代碼:
package com.iheima.smslistener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.SmsMessage;
public class SMSBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//接收短信的內容
Object[] objs = (Object[]) intent.getExtras().get("pdus");
for(Object obj : objs){
SmsMessage sms = SmsMessage.createFromPdu((byte[]) obj);
String content = sms.getMessageBody();
String phone = sms.getOriginatingAddress();
System.out.println("content=="+ content);
System.out.println("phone=="+ phone);
}
}
}
04廣播接受者案例sd卡狀態監聽(重點)
android2.3的模擬器上測試,4.0之後的版本上去掉了SD插拔的功能;
代碼:
配置文件:
<receiver android:name="com.itheima.sdlistener.SDBroadcastReceiver">
<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>
代碼:
package com.itheima.sdlistener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class SDBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//得到廣播的事件類型
String action= intent.getAction();
if("android.intent.action.MEDIA_MOUNTED".equals(action)){
System.out.println("SD卡已經插上了............");
}
if("android.intent.action.MEDIA_UNMOUNTED".equals(action)){
System.out.println("SD卡已拔掉了............");
}
if("android.intent.action.MEDIA_REMOVED".equals(action)){
System.out.println("SD卡已經移除上了............");
}
}
}
05廣播接受者案例開機啓動(重點)
配置文件:
<receiver android:name="com.itheima.bootcomplete.BootCompleteBroadcastReceiver" >
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
代碼:
package com.itheima.bootcomplete;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.sax.StartElementListener;
public class BootCompleteBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context,MainActivity.class);
//告訴activity使用自己的任務棧來維護界面,如果任務棧中沒有當前任務就戶創建一個任務
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
06廣播接受者案例卸載安裝(重點)
配置文件:
<receiver android:name="com.itheima.azxzlistener.AZXZBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_INSTALL" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<!-- 這個屬性必須添加 -->
<data android:scheme="package"/>
</intent-filter>
</receiver>
代碼:
package com.itheima.azxzlistener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class AZXZBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if("android.intent.action.PACKAGE_INSTALL".equals(action)){
System.out.println("有一個新軟件安裝了...........");
}
if("android.intent.action.PACKAGE_REMOVED".equals(action)){
System.out.println("有一個軟件卸載了...........");
}
if("android.intent.action.PACKAGE_REPLACED".equals(action)){
System.out.println("有一個軟件升級了...........");
}
}
}
07_發送自定義廣播
示例代碼:
代碼:
Intent intent = new Intent();
intent.putExtra("news", "我是廣播");
//給廣播頂一個事件類型
intent.setAction("com.itheima.selfbroadcast.SBC");
//發送廣播消息
sendBroadcast(intent);
08_有序廣播和無序廣播(重點)
有序廣播:
廣播發送的消息會按照廣播接收者的優先級從高到低一級一級的發放消息。
消息可以被攔截,被修改;
無序廣播:
廣播發送的消息發送出去後,只要廣播接收者指定了它的事件類型,都可以接收到這個消息。
消息不能被攔截;
代碼:
Intent intent = new Intent();
intent.setAction("com.itheima.FFNTBT");
//發送一個有序的廣播
//intent 傳遞數據的意圖對象
//receiverPermission 指定了只有這個權限的廣播接收者才能接收到這個消息
//resultReceiver 指定了哪個廣播接收者最後接收到消息
//scheduler 消息處理器
//initialCode 初始的消息碼
//initialData 初始數據
//initialExtras 發送的額外數據
sendOrderedBroadcast(intent, null, null, null, 1, "我是國務院,發放2014年農田補貼,每畝地補貼900元", null);
09_服務和進程優先級
服務:是一個沒有界面,可以長期運行在後臺的應用程序(沒有界面的activity);
服務的特點:
(1)android4.0之後的版本上,需要帶有服務的應用程序必須要有一個界面,並且在至少運行過一次,否則不生效;
(2)是一個沒有界面,可以長期運行在後臺的應用程序;
進程:運行應用程序的載體。當應用程序一啓動的時候,android操作系統就提供一個linux的進程,進程是負責維護dalvik虛擬機的,而我們開發的應用程序試運行在dalvik虛擬機上的。
應用程序:四大組件放在一起就是應用程序。
進程的特點:
(1)應用程序啓動時創建了進程;
(2)應用程序退出的時候,進程並沒有退出;
(3)手工結束進程;當可用內存空間不足,系統會自動清理沒有用到的進程;
進程的等級:
1. Foreground process(前臺進程)
應用程序,用戶正在操作,activity的onresume方法被執行了,可以相應點擊事件。
2. Visible process (可視進程)
應用程序的ui界面,用戶還可以看到,但是不能操作了。
3. Service process (服務進程)
應用程序沒有界面,但是有一個後臺的服務還處於運行狀態
4. Background process(後臺進程)
應用程序沒有服務處於運行狀態,應用程序被最小化了,activity執行了onstop方法
5. Empty process (空進程)
沒有任何組件運行,所有的activity都關閉了,任務棧清空了
10_服務的特點
特點:
1、第一次開啓服務時,會創建一個服務對象:oncreate,開啓服務會調用onstartCommand;
2、停止服務時調用ondestroy方法;
3、服務只能被創建一次,可以多次開啓,每次開啓時都會調用onstartCommand方法;
4、服務只能停止一次,如果多次停止不會執行任何操作;
11_電話竊聽器的模板代碼(重點)
12_利用服務實現電話竊聽器
代碼:
package com.itheima.phonelistener;
import android.app.Service;
import android.content.Intent;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
public class PhoneListenerService extends Service {
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
//得到系統提供的電話服務對象
TelephonyManager tm = (TelephonyManager) this.getSystemService(TELEPHONY_SERVICE);
//監聽電話狀態
//listener 電話狀態的監聽器
//LISTEN_CALL_STATE 監聽的事件類型
tm.listen(new MyListener(), PhoneStateListener.LISTEN_CALL_STATE);
}
private class MyListener extends PhoneStateListener {
private MediaRecorder r;
/**
* 當電話狀態發生變化時調用這個方法 state 電話狀態:鈴聲響起、接通電話、閒置狀態
*/
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:// 空閒狀態
if(r != null){
//停止錄音
r.stop();
//釋放多媒體對象
r.release();
//讓垃圾回收器回收多媒體對象佔用的資源
r = null;
}
break;
case TelephonyManager.CALL_STATE_RINGING:// 鈴聲響起狀態
try {
//創建一個錄音機的對象
r = new MediaRecorder();
//設置音頻的來源
r.setAudioSource(MediaRecorder.AudioSource.MIC);
//設置輸出文件的格式
r.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
//設置文件保存的路徑
r.setOutputFile(Environment.getExternalStorageDirectory()+"/123.3gp");
//設置音頻文件的編碼
r.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
//準備多媒體對象
r.prepare();
} catch (Exception e) {
e.printStackTrace();
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK:// 接通狀態
if(r != null){
//開始錄音
r.start();
}
break;
default:
break;
}
}
}
}
配置文件:
權限:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<service android:name="com.itheima.phonelistener.PhoneListenerService"></service>
資料下載