首先定义
// IMyService.aidl
package com.devtom.myservice;
interface IMyService {
void printLog(String message);
}
定义完成了之后,编译工具会自动帮我们生成接口相关的文件。
生成的代码文件如下
package com.devtom.myservice;
public interface IMyService extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements com.devtom.myservice.IMyService {
private static final java.lang.String DESCRIPTOR = "com.devtom.myservice.IMyService";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.devtom.myservice.IMyService interface,
* generating a proxy if needed.
*/
public static com.devtom.myservice.IMyService asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.devtom.myservice.IMyService))) {
return ((com.devtom.myservice.IMyService) iin);
}
return new com.devtom.myservice.IMyService.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@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_printLog: {
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
this.printLog(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.devtom.myservice.IMyService {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public void printLog(java.lang.String message) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(message);
mRemote.transact(Stub.TRANSACTION_printLog, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_printLog = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public void printLog(java.lang.String message) throws android.os.RemoteException;
}
再来看看service相关的实现
public class MyRemoteService extends Service {
private static final String TAG = "MyRemoteService";
public static class MyServiceBinder extends IMyService.Stub {
@Override
public void printLog(String message) throws RemoteException {
Log.e(TAG, "this is message from remote " + message);
}
}
private MyServiceBinder binder;
@Override
public void onCreate() {
super.onCreate();
binder = new MyServiceBinder();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return binder;
}
}
客户端调用的代码如下
public class MainActivity extends Activity {
private IMyService binder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, MyRemoteService.class);
bindService(intent, serviceConnection, Service.BIND_AUTO_CREATE);
this.findViewById(R.id.test).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
binder.printLog("this is message from client");
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
binder = MyRemoteService.MyServiceBinder.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
binder = null;
}
};
}
目前按照个人理解
MainActivity当中通过ServiceConnect 拿到的对象实际上是IMyService 当中的Proxy 对象的引用,之所以会有这个代理对象的存在,目前的理解是,系统为了方便我们调用,通过这个代理对象完成了调用远程服务数据的封装,所以我们在Proxy当中可以看到代理对printLog的实现:
@Override public void printLog(java.lang.String message) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeString(message); mRemote.transact(Stub.TRANSACTION_printLog, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } }
在Proxy的实现中,主要是完成了对数据的封装,并没有实现其他的逻辑,完成数据的封装之后,然后调用了 mRemote的transact方法。
Proxy 中成员变量 mRemote 所指向的对象是 IMyService.Stub ,因为Stub 是一个抽象类,所以最终mRemote指向的实例也就是IMyService.Stub 的实现类了
@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_printLog: { data.enforceInterface(DESCRIPTOR); java.lang.String _arg0; _arg0 = data.readString(); this.printLog(_arg0); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); }
在onTransact 方法当中实现了对数据的解析,将获取到的数据传给自己定义的方法当中去,最终调用了自己实现的方法。
3.通过这个例子,最重要的还是里面的Binder, 数据的传递,解析都是Binder这个对象来完成的。
知道AIDL 的套路之后,可以自己手写一个实现。
public class MyServiceBinderImpl extends Binder implements MyServiceInterface, IInterface{
public static final String TAG = "MyServiceBinderImpl";
public static final String DESCRIPTOR = "com.devtom.myservice.MyServiceBinderImpl";
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
switch (code) {
case INTERFACE_TRANSACTION:
reply.writeString(DESCRIPTOR);
break;
case Binder.FIRST_CALL_TRANSACTION + 0:
data.enforceInterface(DESCRIPTOR);
String strData = data.readString();
printLog(strData);
reply.writeNoException();
break;
}
return super.onTransact(code, data, reply, flags);
}
@Override
public void printLog(String message) {
Log.e(TAG, "this message is " + message);
}
@Override
public IBinder asBinder() {
return this;
}
}
这个实际上就是自己动手去解析数据。
调用了也很简单 ,
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(MyServiceBinderImpl.DESCRIPTOR);
_data.writeString("this my own aidl implement");
binder.transact(IMyService.Stub.TRANSACTION_printLog, _data, _reply, 0);
_reply.readException();
} catch (RemoteException e) {
} finally {
_reply.recycle();
_data.recycle();
}
此处的binder对象就是从ServiceConnection的onServiceConnected 方法参数中获取的,因为我们去掉了代理帮帮我们封装数据,所以这里就只能自己手动的去封装数据了。
其实从上面自己手动实现AIDL 的功能可以看出,我们新建的service只是为了方便我们自己调用,我们完全可以去掉了这些方法(printLog)在onTrasaction里面来实现各种功能,当然这个只是扯淡。