服务service
服务时后台运行,没有界面
一、进程的概念
当一个应用启动后,后台会生成这个应用的进程,这个进程(process)中包含应用的主线程(Thread);
进程的优先级
1、Foreground process 前台进程,用户正在使用的应用,相当于activity处于onResume优先级最高
2、Visible process 可视进程,一直影响用户可见状态,相当于activity的onPause方法
3、Service process 服务进程,服务被启动,服务调用startService()方法
4、Background process 后台进程,应用不可见,相当于activity处于onStop()状态,界面不可见未执行onDestory()方法
5、Empty process 空进程,应用不维护任何可激活的组件属于空进程,但系统不会直接杀死这个种进程,为了缓存的作用,方便下次使用的开启效率。系统会杀死这种进程来维持系统性能的稳定。
二、服务
【1】配置清单文件
android:name="com.example.birdtest.TestService">
【2】定义服务,继承Service类
public class MyService extends Service {
@Override
public void onCreate() {
服务创建
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
服务开启
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
服务销毁
super.onDestroy();
}
【3】服务使用
1)在Activity中开启服务
Intent intent = new Intent(this,MyService.class)
2)startService(intent);
在Activity中关闭服务
Intent intent = new Intent(this.MyService.class);
stopService(intent);
【4】特点
1)第一次开启服务,服务执行onCreate()方法和onStartCommond()方法
2)再次开启服务时,服务仅执行onStartCommond()方法;
3)服务一旦被开启,服务就会在后台长期运行,直到用户手动停止
三、电话监听器
TelephonyManager:电话的服务管理者,可以获取电话的状态和电话的其他信息
实例化:
TelephonyManager tm = Context.getSystemService(Context.TELEPHONY_SERVICE);
录音机:MediaRecorder
实现代码:
/**
* 电话监听器
*/
public class PhoneyService extends Service {
//录音机实例
MediaRecorder mr = null;
@Override
public void onCreate() {
//【1】获取电话监听服务
TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
//【2】注册电话监听状态
//参数1 具体时那个类去接听,写监听的逻辑;参数2 常量 监听电话的状态
tm.listen(new MyPhoneStatListen(),PhoneStateListener.LISTEN_CALL_STATE);
super.onCreate();
}
//定义一个类监听电话的状态
public class MyPhoneStatListen extends PhoneStateListener{
//电话状态发生改变时调用
@Override
public void onCallStateChanged(int state, String phoneNumber) {
//【3】判断电话的状态
switch (state){
case TelephonyManager.CALL_STATE_IDLE: //电话空闲状态
if(mr!=null){
mr.stop();
mr.reset();
mr.release();
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK : //电话的摘机的状态(接听)
//开始录音
mr.start();
break;
case TelephonyManager.CALL_STATE_RINGING: //电话响铃状态
//准备录音机MediaRecorder
//[1]创建
mr = new MediaRecorder();
//[2]设置音频的来源mic 麦克 Voice_call 双方的通话麦克和听筒
mr.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
//[3]设置音频输入格式 3gp格式
mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
//[4]设置音频的编码方式
mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
//[5]设置文件存储的位置
mr.setOutputFile("");
//[6]准备录音
try {
mr.prepare();
} catch (IOException e) {
e.printStackTrace();
}
//下面的步骤放入
//[7]开始录音
//mr.start();
//[8]停止录音
//mr.stop();
//[9]重置
//mr.reset();
//[10]释放资源
//mr.release();
break;
//[11]配置权限
//
}
super.onCallStateChanged(state, phoneNumber);
}
}
四、启动服务的两种方式
1、startService(); 直接开启;
2、bind方式开启服务;
【1】定义服务
public class TestService extends Service {
//中介,让Activity可以调用doServiceDoSomething方法
public class MyIBinder extends Binder {
public void callService(){
doServiceDoSomething();
}
}
//当服务绑定时调用,服务只能绑定一次
@Override
public IBinder onBind(Intent intent) {
return new MyIBinder();
}
public void doServiceDoSomething(){
System.out.println("服务做的事情");
}
}
【2】调用绑定的服务
Intent service = new Intent(MainActivity.this,TestService.class);
myServiceConnection = new MyServiceConnection();
//意图,定义的服务,服务自动创建
bindService(service,myServiceConnection,BIND_AUTO_CREATE);
myIBinder.callService();
//这个类用于监听服务的状态
public class MyServiceConnection implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myIBinder = (TestService.MyIBinder) service;
//可以调用服务的方法了
myIBinder.callService();
System.out.println("服务调用成功");
}
@Override
public void onServiceDisconnected(ComponentName name) {
System.out.println("失去服务的链接");
}
}
【3】注意:
当Activity被销毁时注意解绑服务
unbindService(MyServiceConnection);
1)第一次执行时,服务会执行OnCreate()和OnBind();
2)当OnBind()方法返回为null时,OnServiceConnected()方法不执行
3)多次绑定服务没有相应
4)服务不可以多次解绑
5)绑定的服务在设置页面中没有显示,相当于隐形的服务
7)绑定的服务可以在activity中调用服务里的方法
6)Activity挂掉的时候,服务也会挂掉。
3、混合开启服务-固定步骤
【1】先调用startService方法开启服务,确保服务能在后台长期运行
【2】调用bindService方法,获取中间人对象
【3】调用unbindService方法,解绑服务
【4】调用stopService()方法
五、调用服务的方法
【1】通过bindservice方式调用服务方法的过程
1)在服务中定义一个方法,让Activity调用
public void myMedhod(int pro){
doSomething();
}
2)在服务的内部定义一个中间人对象
public class MyBind extends Binder{
public void callMethod(int pro){
myMethod(pro);
}
}
3)服务中返回中间人对象
public IBinder onBind(Intent intent){
return new MyBind();
}
4)在Activity中绑定服务
Intent intent = new Intent(this,MyService.class);
Myconn conn = new Myconn();
bindService(intent,conn,BIND_AUTO_CREATE);
5)重写onDestroy(),解绑服务 unbindService(conn);
6) Activity中拿到中间人对象myBinder,就可以调用服务的方法了。
private class Myconn implements ServiceConnection{
//重新服务调用成功的方法
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myIBinder = (TestService.MyIBinder) service;
System.out.println("服务调用成功");
}
//重写服务失去链接的方法
}
【2】通过接口的方式调用服务李的方法
java的多态
1)定义一个接口,把服务中的方法暴露出来
2)定义的中间人对象实现定义的接口
3)在activity中获取中间人对象时的类型时我们定义的接口
六、aidl
全称 Android Interface Definition Language ,Android接口定义语言
本地服务:运行在自己应用里的服务
远程服务:运行在其他应用里的服务
实现进程中的通信, IPC,Inter-Process Communication的缩写,含义为进程间通信或者跨进程通信,是指两个进程之间进行数据交换的过程。
实现步骤
【1】被调用者创建aidl文件,这个文件类似于java的接口文件
【2】系统会自动生成这个aidl文件的类 Iservice.aidl
public static abstract class Stub extends IBinder implements Iservice
【2】被调用者使用onBinder()获取的IBinder对象 需要的IBinder 继承Stub
【3】被调用者配置清单文件
//调用者需要通过这个来调用
【3】保证调用和被调用的两个aidl文件是同一个,保证aidl文件的包名和类名相同
【4】调用者获取IBinder对象通过Stub中的静态asInterface()方法
public void onServiceConnected(ComponentName name,IBinder service){
iservice = Stub.asInterface(service);
}
【5】调用者使用
Intent intent = new Intent();
intent.setAction("com.ncs.myservice");//被调用者服务应以的包名
//绑定服务
bindService(intent,ServiceConnection,BIND_AUTO_CREATE);
【6】注意调用远程服务捕获异常