解析 Aidl 文件

之前介绍过Android进程间通信(IPC)的使用,写过一些Demo。但仅仅是拿来用,并没有深入分析aidl是怎样可以做到进程间通信的。

当创建 ITelephony.aidl文件时,aidl会为我们在gen目录中创建相应的文件。

package com.android.internal.telephony;

public interface ITelephony extends android.os.IInterface {
/** Local-side IPC implementation stub class. */
//继承binder 实现所定义的aidl文件内的接口
//静态抽象类 服务端用
//Stub重载实现了OnTransact()方法,这样他就可以根据Proxy发来的客服端的请求,
//进行解析并且调用对应请求的函数接口
public static abstract class Stub extends android.os.Binder implements
com.android.internal.telephony.ITelephony {
private static final java.lang.String DESCRIPTOR = "com.android.internal.telephony.ITelephony";

/** Construct the stub at attach it to the interface. */

//stub构造方法
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}

/**
* Cast an IBinder object into an com.example.aidl.IRemoteService
interface, generating a proxy if needed.
如果需要生成一个代理,为com.android.internal.telephony.itelephony接口铸造一个IBinder对象
*/

//当bindService之后(绑定服务),客户端会得到一个Binder引用,是Binder,不是接口的实例,
//然后就会用 aidl定义的接口.Stub.asInterface函数,去对这是不是跨进程的情况进行统一
//也就是不管你是在同一进程还是不同进程,在拿到Binder引用后,
//调用 aidl定义的接口.Stub.asInterface(IBinder obj)
//即可得到一个接口的实例

//判断Ibinder是否为空
//为空则返回空
//若不为空且是aidl接口的实例 则返回true
//调用 proxy()方法 并将IBinder传入

public static com.android.internal.telephony.ITelephony asInterface(
android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.android.internal.telephony.ITelephony))) {
return ((com.android.internal.telephony.ITelephony) iin);
}
return new com.android.internal.telephony.ITelephony.Stub.Proxy(obj);
}
//返回自身类里包含的Binder对象实例
public android.os.IBinder asBinder() {
return this;
}

//根据Proxy发来的客服端的请求,
//进行解析并且调用对应请求的函数接口
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_endCall: {
data.enforceInterface(DESCRIPTOR);
boolean _result = this.endCall();
reply.writeNoException();
reply.writeInt(((_result) ? (1) : (0)));
return true;
}
case TRANSACTION_answerRingingCall: {
data.enforceInterface(DESCRIPTOR);
this.answerRingingCall();
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}

//这是一个静态类 他是一个服务端在客户端的代理 供客户端使用
// 调用asbinder方法 将定义的aidl文件内的方法发送给服务端
private static class Proxy implements
com.android.internal.telephony.ITelephony {
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 boolean endCall() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
boolean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_endCall, _data, _reply, 0);
_reply.readException();
_result = (0 != _reply.readInt());
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}

// 挂断电话

@Override
public void answerRingingCall() 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_answerRingingCall, _data,
_reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}

static final int TRANSACTION_endCall = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_answerRingingCall = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}

public boolean endCall() throws android.os.RemoteException;

// 挂断电话

public void answerRingingCall() throws android.os.RemoteException;
}

其实,AIDL接口幕后是仰赖着IBinder界面的。所以,我们的应用程序可以选择使用IBinder接口,也可以使用AIDL接口。

如果采取IBinder接口,就不必使用aidl.exe工具去产calInterface.java接口定义文件了,其接口类别较单纯一些。但是由于

IBinder接口只提供单一函数(即transact()函数)来进行远距沟通,呼叫起来比较不方便。例如,当Calculator类别有多个函

数时,myActivity要如何呼叫它们呢? 可以呼叫IBinder接口的transact()函数,再转而呼叫Calculator的各个函数。由于

它并不太方便,所以Android提供Proxy/Stub结构的AIDL接口来化解这个问题。

---恢复内容结束---

时间: 2024-10-08 00:15:54

解析 Aidl 文件的相关文章

Nginx、Apache解析php文件的区别

一.Apache是如何解析php文件的 我们常说的lamp架构是linux.apache.mysql.php,我们知道任何架构或者网站离不开数据库的支持,那么php和apache又是如何协同工作的呢? php是apache的一个外挂程序,必须依靠web服务器才可以运行.当客户端浏览器触发事件--->php程序提交到apache服务器---->apache服务器根据php程序的特点判断是php程序,并从内存或者硬盘中提取访问所需要的应用程序,将其提交给php引擎程序--->php引擎程序解

接口测试-解析har文件

之前我已经研究到让业务测试通过不同方式来获取我们工具需要的har文件,现在我们拿到了业务测试提供的har文件,我们首先要解析这些文件里存放的信息,特别是entries字段里的信息,在万能的github上果然搜出来一个工具包 地址 har 因为maven库里还没有这个jar包提供下载,你需要将源码下载到本地,打包后上传到自己公司的私有库里,供其他开发者下载 源码 主要的类为HarUtils.java,还有命令行下执行需要的2个类(HarCli.java,ViewHar.java),这两个类的主要作

Java通过jxl解析Excel文件入库,及日期格式处理方式 (附源代码)

JAVA可以利用jxl简单快速的读取文件的内容,但是由于版本限制,只能读取97-03  xls格式的Excel. 本文是项目中用到的一个实例,先通过上传xls文件(包含日期),再通过jxl进行读取上传的xls文件(文件格式见下user.xls),解析不为空的行与列,写入数据库. 文件user.xls格式为: 下面来看代码实例演示: 一.前端jsp页面(本来内容很多,这里精简了) <%@ page language="java" contentType="text/htm

java解析properties文件

在自动化测试过程中,经常会有一些公用的属性要配置,以便后面给脚本使用,我们可以选择xml, excel或者json格式来存贮这些数据,但其实java本身就提供了properties类来处理properties文件,虽然名字叫properties,其实打开它发现就是一个记事本的文件,所以看起来也比较直观,下面是解析properties文件的实现代码. properties文件里存贮的样子是这样的,然后给他保存为xxx.properties即可. gsBAMUserName1=automation_

练习:读取解析CSV文件,将读取结果输出的控制台上,并封装到4个Teacher对象中.

/** *    读取解析CSV文件,将读取结果输出的控制台上,并封装到4个Teacher对象中. *    1, 土鳖, 13101015338, 北京海淀区 2, 咪咪, 13201015338, 北京朝阳区 3, 小仓, 13601015818, 北京宣武区 4, 饭岛爱, 13201025818, 北京朝阳区 /** * 读取解析CSV文件,将读取结果输出的控制台上,并封装到4个Teacher对象中. * 1, 土鳖, 13101015338, 北京海淀区 2, 咪咪, 13201015

使用XML序列化器生成XML文件和利用pull解析XML文件

首先,指定XML格式,我指定的XML格式如下: <?xml version='1.0' encoding='utf-8' standalone='yes' ?> <message> <sms> <body> 陈驰0 </body> <date> 1462162910995 </date> <address> 1380 </address> <type> 1 </type> &

python解析json文件

概念 序列化(Serialization):将对象的状态信息转换为可以存储或可以通过网络传输的过程,传输的格式可以是JSON.XML等.反序列化就是从存储区域(JSON,XML)读取反序列化对象的状态,重新创建该对象. JSON(JavaScript Object Notation):一种轻量级数据交换格式,相对于XML而言更简单,也易于阅读和编写,机器也方便解析和生成,Json是JavaScript中的一个子集. Python2.6开始加入了JSON模块,无需另外下载,Python的Json模

解析xml文件的几个步骤

1.生成xml文件的解析器 XmlPullParser parser = Xml.newPullParser(); 2.设置解析器读取流对象的编码格式 parser.setInput(is, "utf-8"); 3.设置解析xml文件之后要存储的位置 List<WeatherInfo> weatherInfo = null; WeatherInfo info = null; 4.定义解析器解析到的事件类型 int type = parser.getEventType();

JS解析XML文件和XML字符串

JS解析XML文件 <script type='text/javascript'>    loadXML = function(xmlFile){        var xmlDoc=null;        //判断浏览器的类型        //支持IE浏览器        if(!window.DOMParser && window.ActiveXObject){            var xmlDomVersions = ['MSXML.2.DOMDocument.