目录
1. 简介
Android AIDL 作为跨进程通信的一种可选方式;
最近再整理以前写过的代码中,觉得这玩意还是值得整理一下的,有时间了拿出来写写,简单记录一下;
2. 定义
在Android Studio 中新建AIDL 文件,如下图所示
注意AIDL 的编写方式,
- 文件格式为,aidl;
- package 包声明要和实际目录(rootProject/.../aidl/...)对应起来;
- 尽量使用基础类型和API 中已有对象或多态;
3. 编译
这个没啥好说的,使用Android Studio -> Build -> Make Module 'XXX' 即可,此处的‘XXX’ 为项目Modules research-common;
此时,你的项目Modules generateJava 目录下,如图所示:
这个是Android 视图,如果你所用的Android Sutdio 中没有看到,切换到Project 视图,目录在./rootProject/.../build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/.../aidl/...
如下图所示:
4. 说明
如下图所示:
AIDL 编译后自动生成的结构差不多都和上图长的结构一致;
简明说一下:
1. 自己定义的AIDL 接口为IMessageManagere,编译后为IMessageManager extend android.os.IInterface;这个IInterface 接口为系统提供的接口类,如下:
package android.os;
/**
* Base class for Binder interfaces. When defining a new interface,
* you must derive it from IInterface.
*/
public interface IInterface
{
/**
* Retrieve the Binder object associated with this interface.
* You must use this instead of a plain cast, so that proxy objects
* can return the correct result.
*/
public IBinder asBinder();
}
简单理解为,AIDL 通过IPC 方式中的IBinder(Binder设备文件)进行跨进程交互;如果我想和你交流,我得先跟你是同类,然后我说的和你说的是同类语言才行;
2. 注意到由于是IPC 方式得交互,所有自己定义得接口方法都带有android.os.RemoteException 声明,如下图所示:
3. 然后核心部分来了,IMessageManager.Stub 作为远程Binder 得委托对象,有关Binder和IBinder 的底层细节暂不讨论,需要C/C++ 层知识,我看的有时候都蒙圈了,水平有限,怕误人子弟嘞;
需要注意的大致节凑如下几点方法:
- IBinder#queryLocalInterface();
- IMessageManager.Stub.Proxy();
- Binder#attachInterface();
- IMessageManager.Stub#onTransact();
- IBinder#transact();
我们只需要简单看下如下关键点,
/**
* Cast an IBinder object into an com.xxx.aidl.IMessageManager interface,
* generating a proxy if needed.
*/
public static com.xxx.aidl.IMessageManager asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.xxx.aidl.IMessageManager))) {
return ((com.xxx.aidl.IMessageManager) iin);
}
return new com.xxx.aidl.IMessageManager.Stub.Proxy(obj);
}
4. 使用ServiceConnection 对象进行连接进行,所有远程服务都可通过此处的IBinder 句柄进行,如下所示:
protected ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IMessageManager messageManager = IMessageManager.Stub.asInterface(service);
try {
String value = "" + System.currentTimeMillis();
int count = (int) (Math.random() * 100);
for (int i = 0; i < count; i++) {
messageManager.updateMsg(value + i);
}
String msg = messageManager.getMsg();
Log.d(TAG, "the current(sum:" + count + ") obtain msg(" + value + ") is " + msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "the current(ComponentName:" + name.getShortClassName() + ")");
}
};
5. 通过Context#bindService()和Context#unbindService() 建立连接和解绑连接;
Intent intent = new Intent(this, MessageManagerService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
unbindService(serviceConnection);
6. 在Manifest.xml 中记得声明即可;
<service
android:name=".service.MessageManagerService"
android:process=":remote" />
简单记录就先这些吧,还是需要平时写代码的过程中,进行多思考,多总结;