您的位置:首页 > 移动开发 > Android开发

Android - 绑定服务调用服务里面的方法,start/bind开启服务的比较,混合方式开启服务,本地服务,远程服务,系统服务,录音API

2017-06-06 11:53 926 查看

1.服务

startService()

缺陷: 我们不可以调用服务的方法, 不可以与服务进行通信.

bindService() 绑定服务

可以间接的调用到服务里面的方法, 可以与服务进行通信.

2.为什么不能通过new Service()来调用服务里面的方法

服务是系统new出来的,系统new出来之后会把上下文为什么准备好,我们自己去new的Service和系统new的Service不是同一个对象,拿不到上下文

3.通过什么方式来调用服务里的方法

Android中提供了调用服务里的方法的解决方案,就是要获取到服务的代理

4.服务返回其代理

服务通过onBind()方法返回代理,其返回值是一个IBinder的实现类

@Override
public IBinder onBind(Intent intent) {
System.out.println("服务被绑定了, 返回IBinder的中间人");
return new MyBinder();
}


创建一个IBinder的实现类,IBinder是一个接口,实现该接口我们需要实现里面所有的方法,非常不方便,系统为我们提供了一个方便的实现类Binder,让该类继承Binder,我们就可以提供代理方法了

public class MyBinder extends Binder{

public void callMethodInService(String name){
methodInService(name);
}

}


5.绑定服务获得其代理,调用服务里的方法

public class MainActivity extends Activity {

//代理人
private MyBinder myBinder;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

//绑定服务获取中间人
public void bind(View view){
//2. 要绑定哪个Service
Intent intent = new Intent(this,TestService.class);

//1. 绑定Service
//intent 要绑定哪个Service
//conn 通讯频道,通过该conn来获取服务的代理
//BIND_AUTO_CR
4000
EATE如果服务不存在,会把服务创建出来.
bindService(intent, new MyConn(), BIND_AUTO_CREATE);
}

//3. 创建通讯频道
private class MyConn implements ServiceConnection{

//当服务被成功连接的时候调用的方法
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//4. 成功连接后,得到了服务的代理对象
myBinder = (MyBinder) service;
}

//当服务失去连接的时候调用的方法.
@Override
public void onServiceDisconnected(ComponentName name) {

}
}

//通过中间人调用服务里面的方法
public void call(View view){
//5. 通过得到的代理对象,调用服务里的方法
myBinder.callMethodInService("小华华", 250);
}
}


6.绑定服务调用服务方法的步骤

编写服务代码

public IBinder onBind(Intent intent) {}


在服务内部定义一个代理人对象 MyBinder

代理人对象有一个方法可以间接的调用服务内部的方法


在onbind方法里面返回代理人对象

在Activity代码采用绑定的方式连接到服务

bindService(intent, new MyConn(),  BIND_AUTO_CREATE);


在serviceConnection的实现类里面有一个方法,获取到服务返回的代理人对象

public void onServiceConnected(ComponentName name, IBinder service)


强制类型转换IBinder转化成 MyBinder类型

myBinder = (MyBinder) service;


调用代理人对象的方法–间接调用了服务里面的方法.

7.绑定方式开启服务的生命周期

绑定的方式开启服务,如果服务不存在, oncreate—>onbind

服务的onstart和onstartcommand方法不会被执行.

解除绑定服务 onunbind()—>ondetroy()

多次绑定服务,服务只会被创建一次,oncreate方法只会被执行一次

多次绑定服务,onbind方法不会被重复调用.

在实际开发的时候,如果需要调用服务的方法,就绑定服务,只能绑定一次

服务只可以被解绑一次,如果用同一个conn对象多次解绑,服务会抛出一次.

8.通过接口隐藏代码内部实现的细节

学习一种代码的设计方式,如果一个内部类有多个方法,我只想暴露出其中的一部分方法时,可以通过接口将想要暴露的方法暴露出去。

如果将内部类设置为public,则所有方法都暴露出去了,如果将内部类设置为private,则所有方法其他人都不能调用了

具体实现方式:设置内部类为private的,将想要暴露出去的方法抽取到一个public的接口中

9.两种开启服务方式的比较

start的方式开启服务

服务一旦开启,长期后台运行,服务和开启者(Activity)没有任何的关系,开启者退出了,服务还是继续在后台长期运行, 开启者(Activity)不可以调用服务里面的方法. 在系统设置界面里面可以观察到

bind的方式开启服务

不求同时生,但求同时死. 如果开启者(Activity)退出了, 服务也会跟着挂掉.

开启者(Activity)可以间接的利用中间人调用服务里面的方法.在系统设置界面看不到的.

服务如果被开启同时被绑定,服务就停不掉了.必须解除绑定服务才可以停止服务.

10.混合的方式开启服务.

为了保证服务又能长期后台运行,又能调用到服务里面的方法.

采用混合的方式开启服务.

请严格按照步骤编写代码:

start的方式开启服务 (保证服务长期后台运行)

bind的方式绑定服务 (调用服务的方法)

unbind的方式解除绑定服务

stop的方式停止服务

11.本地服务和远程服务

本地服务 local service

服务的代码在当前应用程序的内部

远程服务 remote service

服务的代码在另外一个应用程序里面

12.重要概念

进程

操作系统分配的独立的内存空间.

IPC

inter process communication 进程间通讯

aidl

android interface definition language 安卓接口定义语言

13.绑定远程服务调用服务方法的流程

服务提供者

跟本地服务的代码编写是一样

远程服务的接口定义文件,将.java的后缀名修改为 —> .aidl

把接口定义文件的访问修饰符全部删除,如public、private。系统会在gen文件夹下自动为我们生成.java文件

原来代理人MyBinder,由extend Binder implemet IService修改为 –> extends IService.Stub

使用服务者

先把远程服务的.aidl文件拷贝到本地应用程序的工程目录里面,包名必须一致,系统会在gen文件夹下自动为我们生成.java文件

获取到代理的iBinder对象后,通过iService = IService.Stub.asInterface(service)得到远程服务的代理对象

通过代理对象调用远程服务的方法

14.系统服务了解

系统开启后,就会开启大量的常用服务,以后其他应用想使用系统服务的时候,可以通过context.getSystemService(String 服务名)方法获取到对应的系统服务

15.监听通话状态

获取系统服务,设置通话状态监听器

tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
listener = new MyPhoneListener();
tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);


创建通话状态监听器

private class MyPhoneListener extends PhoneStateListener {

@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE: // 空闲状态,代表当前没有电话
System.out.println("停止录音");
break;
case TelephonyManager.CALL_STATE_RINGING:// 响铃状态

break;
case TelephonyManager.CALL_STATE_OFFHOOK:// 通话状态
System.out.println("通话状态,开启录音机,录音.");
break;
}
}

}


不使用的时候注销掉监听器,释放资源

tm.listen(listener, PhoneStateListener.LISTEN_NONE);


16.录音API

开始录音

mRecorder = new MediaRecorder();

//从麦克风录音,VOICE_CALL可录双向的,但是法律不允许
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
//输出格式
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
//文件存放位置
mRecorder.setOutputFile("/mnt/sdcard/"+SystemClock.uptimeMillis()+".3gp");
//音频编码方式
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

try {
mRecorder.prepare();
} catch (Exception e) {
System.out.println("prepare() failed");
}

mRecorder.start();


停止录音

mRecorder.stop();
mRecorder.release();
mRecorder = null;


17.serviceMethod



18.总结

服务(Service)

通过什么方式调用服务中的方法

创建服务的代理,将服务中的方法暴露出去

绑定服务,调用服务中的方法

通过接口隐藏代码内部实现细节

绑定服务的生命周期

startService和bindService两种开启服务方式的区别

如何保证服务又能长期后台运行,又能调用到服务里面的方法

本地服务和远程服务的区别

进程、IPC、AIDL

绑定远程服务,调用服务中的方法

系统服务了解,如何使用系统提供的服务

使用系统服务的案例——监听通话状态,进行录音
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐