我们通过一个Demo将AIDL的实现,然后明白他的调用过程。方便后面的源码学习
这个Demo主要是模拟qq授权登录的过程:从Binder_A,点击QQ登录,跳转到Binder_B(假装为QQ)登录获取授权,授权成功后再调用Binder_A,将结果返回,完成登录。
首先我们先准备Binder_B,因为它需要先向Binder注册成为ServiceManager,并提供哪些方法?
1:首先准备Binder_B的界面:
如上图所示,
2:然后我们开始准备AIDL文件,告诉Binder我们能提供哪些方法
// ILoginInterface.aidl
//注意包名
package com.netease.binder;
// Declare any non-default types here with import statements
interface ILoginInterface {
// 登录
void login();
// 登录返回
void loginCallback(boolean loginStatus, String loginUser);
}
点击Build 我们可以看到生成了一个 java文件
public interface ILoginInterface extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements com.netease.binder.ILoginInterface {
private static final java.lang.String DESCRIPTOR = "com.netease.binder.ILoginInterface";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.netease.binder.ILoginInterface interface,
* generating a proxy if needed.
*/
public static com.netease.binder.ILoginInterface asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.netease.binder.ILoginInterface))) {
return ((com.netease.binder.ILoginInterface) iin);
}
return new com.netease.binder.ILoginInterface.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_login: {
data.enforceInterface(DESCRIPTOR);
this.login();
reply.writeNoException();
return true;
}
case TRANSACTION_loginCallback: {
data.enforceInterface(DESCRIPTOR);
boolean _arg0;
_arg0 = (0 != data.readInt());
java.lang.String _arg1;
_arg1 = data.readString();
this.loginCallback(_arg0, _arg1);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.netease.binder.ILoginInterface {
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 login() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_login, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
// 登录返回
@Override
public void loginCallback(boolean loginStatus, java.lang.String loginUser) 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.writeInt(((loginStatus) ? (1) : (0)));
_data.writeString(loginUser);
mRemote.transact(Stub.TRANSACTION_loginCallback, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_login = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_loginCallback = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
// 登录
public void login() throws android.os.RemoteException;
// 登录返回
public void loginCallback(boolean loginStatus, java.lang.String loginUser) throws android.os.RemoteException;
}
生成的Java文件分为几部分,首先ILoginInterface 是继承的IInterface
1:IInterface : IInterface 代表的就是 Server 进程对象具备什么样的能力(能提供哪些方法,其实对应的就是 AIDL 文件中定义的接口)
IInterface的实现类是IServiceManager:
内部类 ILoginInterface.Stub,是一个抽象类, 具体的 IInterface 的相关实现需要调用方自己实现。
2: IBinder 是一个接口,代表了一种跨进程通信的能力。只要实现了这个借口,这个对象就能跨进程传输。
3:Proxy::同样也实现了ILoginInterface接口,重写了里面的方法。后面我们会一点点走调用过程。
3:准备服务:
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
return new ILoginInterface.Stub() {
@Override
public void login() throws RemoteException {
//to do 登录成功,返回给调用方结果
}
@Override
public void loginCallback(boolean loginStatus, String loginUser) throws RemoteException {
}
};
}
}
这个MyService里面 我们能可以看到,extends Service ,这里的new ILoginInterface.stub就是上面抽象类的实现类,里面定义了接口方法。
@Nullable
public abstract IBinder onBind(Intent intent);
返回值我们可以看到 是new 了一个ILoginInterface.Stub,重写了他里面定义的接口方法
在AndroiMainfest.xml 中注册这个组件,表明过滤我action为"BinderB_Action"的动作/请求
<service
android:name=".service.MyService"
android:enabled="true"
android:exported="true"
android:process=":remote_service">
<intent-filter>
<!-- 激活 MyService 唯一name,不能重名-->
<action android:name="BinderB_Action" />
</intent-filter>
</service>
到此 我们的服务端准备暂时高一段落。
首先我们开始制作Binder的界面:
截图如下所示:
然后开始准备跨进程的AIDL文件