Binder是android中进程通信的信使,是客户端和服务端通信的媒介,当bindService的时候,服务端会返回一个binder对象,然后客户端就可以根据binder操作服务端的数据。普通服务和aidl都是这么完成的。今天就来详细探讨下aidl的使用。
使用aidl首先是要定义一个aid接口,然后系统会为我们生成用的代码,里面就包含我们的媒介binder,还有几个特殊的方法:
- asInterface(android.os.IBinder obj)这个方法是将服务端传过来的binder对象转换成aidl类型的接口,便于我们去操作服务端数据。
- asbinder,由名字就知道返回当前的binder对象。
- 自己定义的方法。
先来定义一个aidl文件
interface IMaidl {
String getName();
}
一个最简单的aidl代码,看看系统自动生成了什么样的代码
public interface IMaidl extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements com.example.apple.db.IMaidl {
private static final java.lang.String DESCRIPTOR = "com.example.apple.db.IMaidl";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.example.apple.db.IMaidl interface,
* generating a proxy if needed.
*/
public static com.example.apple.db.IMaidl asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.example.apple.db.IMaidl))) {
return ((com.example.apple.db.IMaidl) iin);
}
return new com.example.apple.db.IMaidl.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_getName: {
data.enforceInterface(DESCRIPTOR);
java.lang.String _result = this.getName();
reply.writeNoException();
reply.writeString(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.example.apple.db.IMaidl {
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 java.lang.String getName() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getName, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_getName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public java.lang.String getName() throws android.os.RemoteException;
我们上面提到的方法都有吧。下面看看服务端的代码
public class AIDLService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return binder;
}
IMaidl.Stub binder = new IMaidl.Stub() {
@Override
public String getName() throws RemoteException {
return getServiceName();
}
};
String getServiceName() {
return "这是服务端给的信息";
}
}
绑定服务,别忘了还需要到xml注册服务。
bindService(new Intent(this, AIDLService.class), new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IMaidl iMaidl = IMaidl.Stub.asInterface(service);
String name1 = iMaidl.getName();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}, BIND_AUTO_CREATE);
通过aidl定义的接口,跨进程调用服务端的数据 String name1 = iMaidl.getName();。
aidl简单的三部曲就完成了。
了解更多,可以关注公众号