IPC 进程间通信
进程间通讯方式:共享内存--》共享文件----》Socket服务器与Client--》Java RPC(远程过程调用)
Android :Service远程绑定,调用方法、传数据
信使、AIDLAndroid Interface Definition Language
信使通讯:信使发送的消息是通过IBinder发送,实际的方法就是sendMessage
sendMessage注意:
1、Message 消息:Message消息在信使传递的时候,所有的数据必须是基础数据类型或者是Parcelable数据类型Message.obj不能直接使用String类型,那么推荐使用Bundle(可序列化的)使用Bundle来传递复杂信息
常见的Parcelable: Intent,Bundler,Bitmap
信使开发步骤:
创建服务,注册服务
为了对外提供服务的启动方式,隐式意图的定义 和exporter=“true”
在服务中创建信使,定义接收消息的Handler,返回Binder给外界
/**
* 绑定的时候,返回绑定的用来发送消息的控制器。
*
* @param intent
* @return
*/
@Override
public IBinder onBind(Intent intent) {
// 返回信使的 Binder 就可以收消息了
return receiveMessenger.getBinder();
}
返回的Binder
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 对于远程的服务 IBinder 采用信使方式的时候,类型就是信使之间的传输接口
// 可以理解为一个手机号,通过Messenger类就可以封装 IBinder,就可以发消息了
sendMessenger = new Messenger(service);
}
public void btnPause(View view) {
// 进行信息的发送
if (sendMessenger != null) {
Message message = new Message();
message.what = 998;
try {
sendMessenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
当发送relayTo
// 进行信息的发送
if (sendMessenger != null) {
Message message = new Message();
message.what = 199;
// 发送给服务的信息,服务收到的时候,可以进行
// 回报,通过 replyTo 可以给Activity发消息
message.replyTo = replyMessenger;
try {
sendMessenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
用于接收消息的信使必须采用Handler的构函,发送消息的信息必须采用IBinder进行构造
AIDL:定义了应用程序之间,接口方法调用规则Android的照相机
服务部定义AIDL,外界使用
AIDL编写规则
package包路径;interface 接口接口名称{定义接口}
注意这里的接口名称与文件名是一样的否则会告诉你在文件中声明。。。
当参数是数组或者List的时候,AIDL不知道这个参数是用来设置数据或者获取数据的,那么需要开发人员指定:添加方向的修饰符,in out inout
当AIDL文件中需要使用复杂的对象类型的时候,如Message作为参数,在客户端与服务端对应的源代码中必须要创建android.os.Message.aidl,这样aidl文件才可以编译通过
指定的类必须是parcelable的类型,
Message.aidl
package android.os;
parcelble Message;
使用import android.os.Message;
有非基础类型的参数使用in out inout来指定方向
远程调用底层的原理:
1、服务本身可以通过隐式意图启动,不论是否在一个进程中;真正的启动都是由Android系统。
2、当服务启动之后绑定服务时,最底层的交互方式都是透过IBinder对象来交互,IBinder是Android定义的应用程序之间交互的一个桥梁,实际上可以认为是IO流操作
3、IBinder的数据交互采用传递Parcelable对象形式常见的Parcelable: Intent,Bundler,Bitmap ,那么Parcelable最终可以形成字节数组,进行传递。同时也能够从字节数组解码出对象
iConnection=IConnection.Stub.asInterface(service);// 相当于建立了通道可以进行通讯,接下来可以操作aidl文件里的方法
客户端实现绑定后public void onServiceConnected(ComponentName name, IBinder service) {
iConnection=IConnection.Stub.asInterface(service);
try {
int i=iConnection.getInt();
Log.d("message","获得的889"+i);
} catch (RemoteException e) {
e.printStackTrace();
}
}
1、
Intent intent=new Intent("com.chen.action.PLAY_SERVICE");
// 绑定其他程序的服务时不知道类名的
// 因此需要是要隐式意图来绑定
bindService(intent,this,BIND_AUTO_CREATE);
2、服务
@Override
public void onCreate() {
super.onCreate();
// 在服务中用于接收其他程序发送过来的消息
// 需要采用Messenger(Handler)这种构函创建一个接收消息的信使
message=new Messenger(rhandler);
}
@Override
public IBinder onBind(Intent intent) {
// 将信使的绑定接口返回给其他应用程序
// 相当于把手机号给别人,其他人就可以用手机号给你发短信
return message.getBinder();
}
3、Activity
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 对于远程的服务,那么IBinder采用信使的方式的时候,类型是信
// 使之间的传输接口,可以认为是手机号Messenger类封装IBinder就可以发信息了
smessenger=new Messenger(service);
// 进行信息的发送
Message message=new Message();
message.what=100;
try {
smessenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
与Activity的生命周期绑定同步
@Override
protected void onPause() {
super.onPause();
unbindService(this);
}
@Override
public void onServiceDisconnected(ComponentName name) {
smessenger=null;// 信使制空
}
AIDL
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 使用AIDL的IBinder需要通过asInterface转化成相应的接口实现类
// 转换的servre就是AIDL 的接口,包含了所有可以调用服务的Service里面的方法
aidlService = AIDLService.Stub.asInterface(service);
try {
int result=aidlService.getVersion();
String s=aidlService.getString();
// aidlService.sayHello("client");
Log.d("result",""+result+s);
绑定的服务类
class Controller extends AIDLService.Stub{
@Override
public int getVersion() throws RemoteException {
return 998;
}
@Override
public String getString() throws RemoteException {
return "hello";
}
@Override
public void sayHello(String who) throws RemoteException {
Log.d("Service","nihao"+who);
}
@Override
public long sum(byte[] data) throws RemoteException {
return 0;
}
}