服务的生命周期
服务的生命周期跟采用启动服务的方法有关: 当采用Context.startService()方法启动服务,与之有关的生命周期方法onCreate() onStart() onDestroy()onCreate()该方法在服务被创建时调用,该方法只会被调用一次,无论调用多少次startService()或bindService()方法,服务也只被创建一次。onStart() 只有采用Context.startService()方法启动服务时才会回调该方法。该方法在服务开始运行时被调用。多次调用startService()方法尽管不会多次创建服务,但onStart() 方法会被多次调用。onDestroy()该方法在服务被终止时调用。 当采用Context.bindService()方法启动服务,与之有关的生命周期方法onCreate() onBind() onUnbind() onDestroy()onBind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,多次调用Context.bindService()方法并不会导致该方法被多次调用。onUnbind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务解除绑定时被调用。如果先采用startService()方法启动服务,然后调用bindService()方法绑定到服务,再调用unbindService()方法解除绑定,最后调用bindService()方法再次绑定到服务,触发的生命周期方法如下:onCreate()onStart()onBind()onUnbind()[重载后的方法需返回true]onRebind()
1、服务监听通话
核心文件
public class PhoneService extends Service {
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCreate() {
super.onCreate();
TelephonyManager manager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
manager.listen(new PhoneListener(), PhoneStateListener.LISTEN_CALL_STATE);
}
private final class PhoneListener extends PhoneStateListener{
private String incomeingNumber;
private MediaRecorder mediaRecorder;
private File file;
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
try {
switch(state){
case TelephonyManager.CALL_STATE_RINGING: //来电
this.incomeingNumber = incomingNumber;
break ;
case TelephonyManager.CALL_STATE_OFFHOOK: //通话中
file = new File(Environment.getExternalStorageDirectory(),incomeingNumber+System.currentTimeMillis()+".3gp");
mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//话筒,只能录说话人
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);//手机常用格式
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);//编码方式
mediaRecorder.setOutputFile(file.getAbsolutePath());
mediaRecorder.prepare();
mediaRecorder.start(); //开始录音
break ;
case TelephonyManager.CALL_STATE_IDLE: //挂断后返回空闲
if(mediaRecorder != null ){
mediaRecorder.stop();
mediaRecorder.release();
mediaRecorder = null;
uploadFile();
}
break ;
}
} catch ( Exception e) {
e.printStackTrace();
}
}
private void uploadFile() {
// TODO Auto-generated method stub
}
}
}
context.stopService(service);
public class BootBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context,PhoneService.class);//显式或隐式
context.startService(service);//intent激活服务
}
}
<service android:name=".PhoneService"></service>
<receiver android:name=".BootBroadcastReceiver">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<!-- 访问网络 -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<!-- 读取通话状态 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!-- 创建或者删除文件 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 写文件 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 录音 -->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
</manifest>
2、建立于访问者相互通信的本地服务
本地服务:服务与访问者在同一个进程中,反之则远程。
public class StuqueryActivity extends Activity {
private EditText stuno_text;
private StuServiceConnection conn = new StuServiceConnection();
private Istu istu;
private TextView nameText;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
stuno_text = (EditText) this.findViewById(R.id.stuno);
nameText = (TextView) this.findViewById(R.id.name);
Intent service = new Intent(this, StuService.class);
bindService(service, conn, BIND_AUTO_CREATE);//启动服务
}
private class StuServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName paramComponentName,
IBinder paramIBinder) {
istu = (Istu) paramIBinder;
}
@Override
public void onServiceDisconnected(ComponentName paramComponentName) {
istu = null;
}
}
@Override
protected void onDestroy() {
unbindService(conn);
super.onDestroy();
}
public void queryStu(View v) {
String no = stuno_text.getText().toString();
int no_int = Integer.parseInt(no);
String name = istu.queryStu(no_int);
nameText.setText(name);
}
}
public class StuService extends Service {
private StuBinder binder = new StuBinder();
private String[] names = { "张飞", "赵云", "刘备" };
public String query(int no) {
if (no > 0 && no < 4) {
return names[no - 1];
}
return null;
}
@Override
public IBinder onBind(Intent intent) {
//通过binder来调取服务中飞方法
return binder;
}
private class StuBinder extends Binder implements Istu{
@Override
public String queryStu(int no) {
return query(no);
}
}
}
public interface Istu {
public String queryStu(int no);
}
... <application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:label="@string/app_name"
android:name=".StuqueryActivity" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".StuService"></service>...
3、建立于访问者相互通信的远程服务 AIDL
AIDL是一种接口定义语言,实现两个进程通信。
远程部分
package com.yza.aidl;
//AIDL接口描述规则 不能有修饰符
interface StuQuery {
String queryStu(int no);
}
public class StuQueryService extends Service {
private IBinder binder = new StuQueryBinder();
private String[] names = { "张飞", "赵云", "刘备" };
public String query(int no) {
if (no > 0 && no < 4) {
return names[no - 1];
}
return null;
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return binder;
}
private final class StuQueryBinder extends StuQuery.Stub {
@Override
public String queryStu(int no) throws RemoteException {
// TODO Auto-generated method stub
return query(no);
}
}
}
<!-- 最好用隐式意图 -->
<service android:name=".StuQueryService">
<intent-filter >
<action android:name="com.yza.stu.query" />
</intent-filter>
</service>
本地则
public class StuqueryActivity extends Activity {
private EditText stuno_text;
private StuServiceConnection conn = new StuServiceConnection();
private TextView nameText;
private StuQuery stuQuery;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
stuno_text = (EditText) this.findViewById(R.id.stuno);
nameText = (TextView) this.findViewById(R.id.name);
Intent service = new Intent("com.yza.stu.query");
bindService(service, conn, BIND_AUTO_CREATE);//启动服务
}
private class StuServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName paramComponentName,
IBinder paramIBinder) {
stuQuery = StuQuery.Stub.asInterface(paramIBinder);
}
@Override
public void onServiceDisconnected(ComponentName paramComponentName) {
stuQuery = null;
}
}
@Override
protected void onDestroy() {
unbindService(conn);
super.onDestroy();
}
public void queryStu(View v) {
String no = stuno_text.getText().toString();
int no_int = Integer.parseInt(no);
String name;
try {
name = stuQuery.queryStu(no_int);
nameText.setText(name);
} catch (RemoteException e) { //远程意外
// TODO Auto-generated catch block
e.printStackTrace();
nameText.setText("意外");
}
}
}