您的位置:首页 > 大数据 > 人工智能

AIDL 一

2016-02-28 01:13 435 查看
AIDL一般的项目当中很少接触到,但是老被问到,因此基于实在不想知道它是什么东西的态度下来看看它,结果和预想差不多。这个东西其实和protobuf的使用方法比较类似,都是通过代码生成类,然后调用这个不能编辑的类里面的对象或方法。但我记得protobuf生成文件是通过一个exe执行后直接导出的,而aidl相对代码可读性要高一点并且IDE会帮你生成,里面方法或者参数的定义都是和protobuf一样预先在客户端和服务端约定好,这也是IDL的体现。

我们都知道AIDL是用于进程间通信的,线程间的通信是handler的职责范围而进程间的通信同样可以,那么就引入了Messenger。官方文档解释:它引用了一个Handler对象,以便others能够向它发送消息(使用mMessenger.send(Message msg)方法)。该类允许跨进程间基于Message的通信(即两个进程间可以通过Message进行通信),在服务端使用Handler创建一个Messenger,客户端持有这个Messenger就可以与服务端通信了。Messenger不复杂,查阅源码还是比较好理解的。

那么重点在于,Messenger是一个Parcelable类,Messenger又持有Handler对象,Handler持有IMessenger对象,IMessenger持有一个继承自Binder实现了IBinder的Stub,而这个Stub就是两个进程间通信所共用的对象,有了一个共同对象当然就可以以此为依据进行通信了。

代码上来看,服务端继承Service需要实现OnBind:

@Override
public IBinder onBind(Intent intent) {
return new Messenger(mHandler).getBinder();
}


而客户端在连上服务端后要获取IBinder:

@Override
public void onServiceConnected(ComponentName name, IBinder service) {
messenger = new Messenger(service);
}


何为服务端,何为客户端,需要先了解本地service默认情况下运行在当前进程的主线程中,远程service运行再另一个进程中。而这两者区别在于service的定义:“android:process”。

那么了解上面的Messenger,就可以很好的理解AIDL的实现方式了,因为Messenger就是以AIDL的方式实现并封装好的,那么我们可以这样理解,通常说的aidl实现其实就是在一定规则或框架下自定义进程间通信,Messenger仅仅是一个android实现好了的可使用的API。那么aidl的实现规则里,为何会有service的参与,为何会有aidl文件,那么只要细心回想查看LocationManager之类的系统manager类,里面都会看到ILocationManager等等上面讲过的影子,是的,gps肯定是运行在不同的进程中与你的app交互的,而其实现方式肯定也是以aidl方式实现的,在Android系统中有很多的Manager,wifi的管理类叫WifiManager,蓝牙的管理类叫BluetoothManager,只要有xxxManager.java,就会有Ixxx.aidl,并且有xxxService.java。这个Ixxx.aidl就是实现Manager和Service通信的桥梁。总归一句话,aidl的实现规则实际上也是android系统服务实现的产物,如果还要究其原因,可以看老罗的源码分析,里面讲得很透彻。

aidl实现方式的规则:

1 自己写一个aidl文件,放在专门存放aidl文件的地方。android studio可以右击app module新建出来,但需注意gradle构建时的productFlavors不同会发生包名不一致而报错。该文件里面基本代码为:

interface IAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);

}


看上去像java,但需谨慎的是,包名要一致,另一个是该文件里面定义的数据类型有的要引入有的不用:

所有基础类型(int, char, 等)

String,List,Map,CharSequence等类

其他AIDL接口类型

所有Parcelable的类

这个一试就知道了。

2 build项目,不报错就会生成一个java文件,目录在项目输出目录下。

3 一个继承自service的类,该类项目主目录下就可以(即和activity之类的文件同一个包名下就可以不用放在aidl文件的存放目录下),该类里基本代码为:

public class IAidlService extends Service {

@Override public void onCreate() {
super.onCreate();
}

@Override public void onDestroy() {
super.onDestroy();
}

@Nullable @Override public IBinder onBind(Intent intent) {
return new IAidlInterface.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble,
String aString) throws RemoteException {

}
};
}
}


4 一个实现了ServiceConnection的类,与通信基本代码为:

public class IAidlServiceConnection implements ServiceConnection {

public IAidlServiceConnection() {

}

@Override public void onServiceConnected(ComponentName name, IBinder service) {
iAidlInterface = IAidlInterface.Stub.asInterface(service);
}

@Override public void onServiceDisconnected(ComponentName name) {
iAidlInterface = null;
}
}


连上服务后就可以通过iAidlInterface执行定义好的放在服务端的代码了。

5 初始化等等基本代码:

IAidlServiceConnection connection;
IAidlInterface iAidlInterface;

private void initService() {
connection = new IAidlServiceConnection();
Intent i = new Intent(this, IAidlService.class);
boolean ret = getApplicationContext().bindService(i, connection, Context.BIND_AUTO_CREATE);
}

@Override protected void onDestroy() {
super.onDestroy();
releaseService();
}

private void releaseService() {
getApplicationContext().unbindService(connection);
connection = null;
}


以上就是aidl的实现基本规则,按照这些套路做就行了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: