aidl跨进程通信的步骤: 1、创建aidl文件。 2、build后生成aidl对应的java文件。 3、创建服务端Service。 4、创建客户端Activity,bindService(),获取IBinder的proxy 。
一、创建aidl文件
代码语言:javascript复制// IImoocAIDL.aidl
package com.mecury.aidltest;
// Declare any non-default types here with import statements
interface IImoocAIDL {
//计算num1 num2
int add(int num1,int num2);
}
二、build后生成对应的interface类:
aidl生成的对应的interface类 IImoocAIDL 中,有两个继承自IImoocAIDL的类: 抽象类 stub 和 实际类 Proxy。
Proxy运行在客户端,当客户端远程调用此方法时,其内部实现是这样的:
1、客户端调用 proxy. add(int num1, int num2) 时,add方法内会调用transact方法; 2、transact方法会发起RPC请求,同时当前线程挂起; 3、然后服务端中的stub类中的onTransact方法会被调用; 4、直到RPC过程结束,被挂起的线程继续执行,并从_reply中取出RPC返回的结果。
代码语言:javascript复制/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: F:\AS for android\AIDLTest\aidlclient\src\main\aidl\com\mecury\aidltest\IImoocAIDL.aidl
*/
package com.mecury.aidltest;
// Declare any non-default types here with import statements
public interface IImoocAIDL extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements com.mecury.aidltest.IImoocAIDL {
private static final java.lang.String DESCRIPTOR = "com.mecury.aidltest.IImoocAIDL"; //Binder的唯一标识
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.mecury.aidltest.IImoocAIDL interface,
* generating a proxy if needed.
*/
//将服务端的Binder对象转换成客户需要的AIDL对象,转换区分进程,客户端服务端位于同一进程,返回服务端的
//Stub对象本身;否则返回的是系统的封装后的Stub.proxy对象。
public static com.mecury.aidltest.IImoocAIDL asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.mecury.aidltest.IImoocAIDL))) {
return ((com.mecury.aidltest.IImoocAIDL) iin);
}
return new com.mecury.aidltest.IImoocAIDL.Stub.Proxy(obj);
}
//返回当前Binder对象
@Override
public android.os.IBinder asBinder() {
return this;
}
//运行在服务端的Binder线程池中
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_add: {
data.enforceInterface(DESCRIPTOR);
//读取客户端传递过来再data中存储的方法的参数
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
//调用方法
int _result = this.add(_arg0, _arg1);
//将计算结果写入reply中
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags); //向Transact传递数据
}
//代理类,运行在客户端
private static class Proxy implements com.mecury.aidltest.IImoocAIDL {
private android.os.IBinder mRemote; //声明一个IBinder对象
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
//返回当前Binder对象
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
//客户端调用此方法,传递进来num1和num2两个参数,
@Override
public int add(int num1, int num2) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
//向_data中写入参数
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(num1);
_data.writeInt(num2);
//通过transact方法向服务端传递参数,并调用了方法,返回的结果写入_reply中
mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
//标识位
static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION 0);
}
//计算num1 num2
public int add(int num1, int num2) throws android.os.RemoteException;
}
三、创建服务端Service
在服务端Service中创建继承于IImoocAIDL.Stub的IBinder类:
代码语言:javascript复制public class IRemoteService extends Service {
//客户端绑定service时会执行
@Override
public IBinder onBind(Intent intent) {
return iBinder;
}
private IBinder iBinder = new IImoocAIDL.Stub(){
@Override
public int add(int num1, int num2) throws RemoteException {
Log.e("TAG","收到了来自客户端的请求" num1 " " num2 );
return num1 num2;
}
};
}
同时,在AndroidManifest.xml中注册该Service,并定义其所在的进程remote:
代码语言:javascript复制<service android:name=".IRemoteService"
android:process=":remote"
android:exported="true">
<intent-filter>
<action android:name="com.mecury.aidltest.IRomoteService"/>
</intent-filter>
</service>
四、创建客户端Activity,bindService(),获取IBinder的proxy
MainActivity: 这里onServiceConnected中返回的iBinder, 经过IImoocAIDL.Stub.asInterface(service)后返回的是Stub的proxy。
代码语言:javascript复制public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button button;
private IImoocAIDL iImoocAIDL;
private ServiceConnection conn = new ServiceConnection() {
//绑定服务,回调onBind()方法
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iImoocAIDL = IImoocAIDL.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
iImoocAIDL = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindService();
initView();
}
private void initView() {
button = (Button) findViewById(R.id.button);
button.setOnClickListener(this);
}
@Override
public void onClick(View v) {
try {
int res = iImoocAIDL.add(1, 2);
} catch (RemoteException e) {
e.printStackTrace();
}
}
private void bindService() {
Intent intent = new Intent();
//绑定服务端的service
intent.setAction("com.mecury.aidltest.IRomoteService");
//新版本(5.0后)必须显式intent启动 绑定服务
intent.setComponent(new ComponentName("com.mecury.aidltest","com.mecury.aidltest.IRemoteService"));
//绑定的时候服务端自动创建
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
}
}
总结:
进程间通信的关键:不是Service, 而是APDL中 IBinder 的实现类stub 和 Proxy,真正实现进程间通信 是通过 transact方法 和 onTransact方法。