19.深刻解析Android的AIDL界面
AIDL讲解

AIDL通信Server端实现
AIDL通信Server端实现
3、实体类的实现
Role类是一个序列化的类,这里使用Parcelable 接口来序列化,他是 Google 提供的一个比Serializable 效率更高的序列化类。(什么是序列 化? 简单说就是为了保存在内存中的各种对象的状态(也就是实例变 量,不是方法),并且可以把保存的对象状态再读出来。虽然你可以 用你自己的各种各样的方法来保存object states,但是Java给我们提 供了一种较好的保存对象状态的机制,那就是序列化。) 实现序列化,我们要实现三个方法: 1、describeContents() 没搞懂有什么用,反正直接返回0也可以 2、writeToParcel 方法。该方法将类的数据写入外部提供的Parcel中. 3、静态的Parcelable.Creator接口,本接口有两个方法: 一为createFromParcel(Parcel source) 实现从source中创建出类的实 例的功能。另一个为newArray(int size) 创建一个类型为T,长度为 size的数组,仅一句话(return new Role[size]即可,估计本方法是供 外部类反序列化本类数组使用。
在Linux的概念空间中,Android的每个Activity 都是一个独立的进程,每个Service也都是一 个独立的进程,Activity,Service之间要交换数 据属于IPC。IBinder就是为了Activity Service 通讯而设计的一个轻量级的IPC框架。IBinder 传递的数据被封装到android.os.parcel(注意 parcel并非通用的序列化机制,而是专为 IBinder设计的)客户端通过IBinder发送请求给 服务端,服务端提供实际服务。
aidl 底层原理

aidl 底层原理AIDL底层原理一、引言AIDL(Android Interface Definition Language)是Android中用于实现跨进程通信的一种机制。
它允许一个进程调用另一个进程中的方法,实现进程间的数据交换和通信。
本文将介绍AIDL的底层原理,探讨其实现机制和工作原理。
二、AIDL的定义和作用AIDL是Android提供的一种接口定义语言,用于定义客户端和服务端之间的通信接口。
通过AIDL,我们可以定义一组方法,供客户端调用服务端的功能。
AIDL可以被编译成Java接口,并生成相应的Binder类。
Binder类负责处理进程间通信的细节,包括数据的传输和方法的调用。
AIDL的主要作用是实现进程间通信(IPC,Inter-Process Communication)。
在Android中,每个应用程序运行在独立的进程中,如果需要在不同的进程中共享数据或调用方法,就需要使用IPC机制。
AIDL提供了一种简单、高效的方式来实现进程间通信,使得不同应用程序之间可以共享数据和功能。
三、AIDL的底层实现机制1. Binder机制AIDL底层的实现机制是Binder机制。
Binder是Android提供的一种跨进程通信的机制,它通过提供一个驱动程序来实现不同进程之间的通信。
在AIDL中,客户端和服务端通过Binder对象进行通信。
Binder机制的核心是Binder驱动程序和Binder对象。
Binder驱动程序负责处理进程间通信的细节,包括数据的传输和方法的调用。
每个进程都有一个Binder驱动程序,用于处理该进程内的Binder 对象。
2. AIDL接口AIDL接口是定义客户端和服务端之间通信接口的关键。
通过AIDL 接口,我们可以定义一组方法,用于实现客户端和服务端之间的数据交换和通信。
AIDL接口可以被编译成Java接口,并生成相应的Binder类。
客户端通过Binder类和服务端进行通信。
详解Android中AIDL的使用

详解Android中AIDL的使⽤AIDL,即Android Interface Definition Language,Android接⼝定义语⾔。
这门语⾔是为了实现进程间通信。
每⼀个进程都有⾃⼰的⼀块独⽴的内存,都在⾃⼰的内存上存储⾃⼰的数据,执⾏⾃⼰的操作,每个进程之间你不知我,我不知你,⽽AIDL,就是两个进程之间沟通的桥梁。
AIDL⽤来做什么AIDL是Android中IPC(Inter-Process Communication)⽅式中的⼀种,AIDL是Android Interface definition language的缩写,对于⼩⽩来说,AIDL的作⽤是让你可以在⾃⼰的APP⾥绑定⼀个其他APP的service,这样你的APP可以和其他APP交互。
aidl⽂件⽀持的数据类型包括:⼋种基本数据类型:byte、char、short、int、long、float、double、booleanString、CharSequence实现了Parcelable接⼝的数据类型List类型。
List承载的数据必须是AIDL⽀持的类型,或者是其他声明的AIDL对象Map类型。
Map承载的数据必须是AIDL⽀持的类型,或者是其他声明的AIDL对象在使⽤其他声明的AIDL对象的时候必须要导包,即使要使⽤的AIDL对象⽂件和当前正在编辑的aidl⽂件在同⼀个⽂件夹下。
aidl⽂件可以分为两类,⼀类⽤来声明实现了Parcelable接⼝的数据类型,以供其他AIDL⽂件使⽤那些⾮默认⽀持的数据类型。
还有⼀类是⽤来定义接⼝⽅法,声明要暴露哪些接⼝给客户端调⽤。
AIDL的具体使⽤步骤是:⼀、创建⼀个服务端⼯程1、如果aidl⽂件中涉及到实现了Parcelable接⼝的数据类型,则先将该aidl⽂件定义出来。
在src⽂件夹下右键,选择新建aidl ⽂件,这⾥新建了⼀个Book.aidl⽂件。
新建完以后,会在main⽂件下⽣成⼀个aidl的⽂件夹,aidl⽂件夹下的⽬录结构和java⽂件夹下的⽬录结构⼀样。
Android的AIDL通信机制

Android的AIDL通信机制Android 接口定义语言(AIDL)AIDL(Android 接口定义语言)与您可能使用过的其他IDL 类似。
您可以利用它定义客户端与服务使用进程间通信(IPC) 进行相互通信时都认可的编程接口。
在Android 上,一个进程通常无法访问另一个进程的内存。
尽管如此,进程需要将其对象分解成操作系统能够识别的原语,并将对象编组成跨越边界的对象。
编写执行这一编组操作的代码是一项繁琐的工作,因此Android 会使用AIDL 来处理。
注:只有允许不同应用的客户端用IPC 方式访问服务,并且想要在服务中处理多线程时,才有必要使用AIDL。
如果您不需要执行跨越不同应用的并发IPC,就应该通过实现一个Binder 创建接口;或者,如果您想执行IPC,但根本不需要处理多线程,则使用Messenger 类来实现接口。
无论如何,在实现AIDL 之前,请您务必理解绑定服务。
在您开始设计AIDL 接口之前,要注意AIDL 接口的调用是直接函数调用。
您不应该假设发生调用的线程。
视调用来自本地进程还是远程进程中的线程,实际情况会有所差异。
具体而言:来自本地进程的调用在发起调用的同一线程内执行。
如果该线程是您的主UI 线程,则该线程继续在AIDL 接口中执行。
如果该线程是其他线程,则其便是在服务中执行您的代码的线程。
因此,只有在本地线程访问服务时,您才能完全控制哪些线程在服务中执行(但如果真是这种情况,您根本不应该使用AIDL,而是应该通过实现Binder 类创建接口)。
来自远程进程的调用分派自平台在您的自有进程内部维护的线程池。
您必须为来自未知线程的多次并发传入调用做好准备。
换言之,AIDL 接口的实现必须是完全线程安全实现。
oneway 关键字用于修改远程调用的行为。
使用该关键字时,远程调用不会阻塞;它只是发送事务数据并立即返回。
接口的实现最终接收此调用时,是以正常远程调用形式将其作为来自Binder 线程池的常规调用进行接收。
Android进程间通信(一):AIDL使用详解

Android进程间通信(⼀):AIDL使⽤详解⼀、概述AIDL是Android Interface Definition Language的缩写,即Android接⼝定义语⾔。
它是Android的进程间通信⽐较常⽤的⼀种⽅式。
Android中,每⼀个进程都有⾃⼰的Dalvik VM实例,拥有⾃⼰的独⽴的内存空间,进程与进程之间不共享内存,这就产⽣了进程间通信的需求。
⼆、语法AIDL是Android接⼝定义语⾔,是⼀门语⾔,所以它拥有⾃⼰的语法和特性。
(⼀)数据类型AIDL⽀持的数据类型包括以下⼏种:1. Java的8种基本数据类型:int,short,long,char,double,byte,float,boolean;2. CharSequence类型,如String、SpannableString等;3. ArrayList,并且T必须是AIDL所⽀持的数据类型;4. HashMap<K,V>,并且K和V必须是AIDL所⽀持的数据类型;5. 所有Parceable接⼝的实现类,因为跨进程传输对象时,本质上是序列化与反序列化的过程;6. AIDL接⼝,所有的AIDL接⼝本⾝也可以作为可⽀持的数据类型;有两个需要注意的地⽅:1、在Java中,如果⼀个对象和引⽤它的类在同⼀个package下,是不需要导包的,即不需要import,⽽在AIDL中,⾃定义的Parceable对象和AIDL接⼝定义的对象必须在所引⽤的AIDL⽂件中显式import进来,不管这些对象和所引⽤它们的AIDL⽂件是否在同⼀个包下。
2、如果AIDL⽂件中使⽤到⾃定义的Parceable对象,则必须再创建⼀个与Parceable对象同名的AIDL⽂件,声明该对象为Parceable类型,并且根据上⼀条语法规定,在AIDL⽂件中进⾏显式import。
(⼆)⽂件类型1. 所有AIDL⽂件都是以.aidl作为后缀的;2. 根据⽤途区分,AIDL⽂件的有两种,⼀种是⽤于定义接⼝,另⼀种是⽤于声明parceable对象,以供其他AIDL⽂件使⽤;(三)定向tagAIDL中,除了基本数据类型,其他类型的⽅法参数都必须标上数据在跨进程通信中的流向:in、out或inout:1、in表⽰输⼊型参数:只能由客户端流向服务端,服务端收到该参数对象的完整数据,但服务端对该对象的后续修改不会影响到客户端传⼊的参数对象;2、out表⽰输出型参数:只能由服务端流向客户端,服务端收到该参数的空对象,服务端对该对象的后续修改将同步改动到客户端的相应参数对象;3、inout表⽰输⼊输出型参数:可在客户端与服务端双向流动,服务端接收到该参数对象的完整数据,且服务端对该对象的后续修改将同步改动到客户端的相应参数对象;定向tag需要⼀定的开销,根据实际需要去确定选择什么tag,不能滥⽤。
Android开发中的AIDL和跨进程通信技术

Android开发中的AIDL和跨进程通信技术随着移动设备的普及,Android操作系统成为了最受欢迎的移动操作系统之一。
开发人员在开发Android应用时,经常需要面对跨进程通信的需求。
为了实现不同进程间的数据交互,Android提供了AIDL(Android Interface Definition Language)和其他跨进程通信技术。
一、什么是AIDL?AIDL是一种借助于Android系统的IPC(Inter-Process Communication)机制,在不同进程间进行通信的技术。
它允许应用程序在不同的进程中调用和交互彼此提供的接口,实现进程间的数据交换。
二、为什么需要跨进程通信?在开发Android应用时,很多情况下都需要实现跨进程通信。
例如,当一个应用中有多个进程时,这些进程可能需要共享数据;或者当一个应用与另一个应用进行交互时,需要进行进程间通信。
此外,跨进程通信还可以实现一些特定功能,例如在后台进程中处理耗时操作,以提高应用的响应速度。
三、AIDL的使用方式使用AIDL时,需要定义一个AIDL接口,该接口包含应用程序之间通信所需的方法。
然后,将该AIDL接口实现为一个服务,并将其在应用程序中进行注册。
首先,创建一个AIDL文件,定义接口名称、包名,以及需要的方法。
接口中的每个方法都需要声明所抛出的异常。
然后,在服务中实现AIDL接口的方法。
服务可以是一个Service,也可以是一个继承自Service的子类。
在子类中,需要重写onBind()方法,并返回一个实现了AIDL接口的Binder对象。
在客户端中,需要绑定服务并获取AIDL接口的实例。
客户端可以调用AIDL接口中定义的方法,实现与服务的交互。
四、其他跨进程通信技术除了AIDL,Android还提供了其他一些跨进程通信技术。
1. MessengerMessenger是一种基于AIDL的轻量级跨进程通信技术。
它允许应用程序之间使用Message对象进行通信,实现进程间的数据交换。
AndroidAIDL实例解析

AndroidAIDL实例解析AIDL这项技术在我们的开发中⼀般来说并不是很常⽤,虽然⾃⼰也使⽤新浪微博的SSO登录,其原理就是使⽤AIDL,但是⾃⼰⼀直没有动⼿完整的写过AIDL的例⼦,所以就有了这篇简单的⽂章。
AIDL(AndRoid接⼝描述语⾔)是⼀种借⼝描述语⾔; 编译器可以通过aidl⽂件⽣成⼀段代码,通过预先定义的接⼝达到两个进程内部通信进程的⽬的. 如果需要在⼀个Activity中, 访问另⼀个Service中的某个对象, 需要先将对象转化成 AIDL可识别的参数(可能是多个参数), 然后使⽤AIDL来传递这些参数, 在消息的接收端, 使⽤这些参数组装成⾃⼰需要的对象.说⽩了,AIDL就是定义⼀个接⼝,客户端(调⽤端)通过bindService来与远程服务端简历⼀个连接,在该连接建⽴时会将返回⼀个IBinder对象,该对象是服务端Binder的BinderProxy,在建⽴连接时,客户端通过asInterface函数将该BinderProxy对象包装成本地的Proxy,并将远程服务端的BinderProxy对象赋值给Proxy类的mRemote字段,就是通过mRemote执⾏远程⽅法调⽤。
需要对Binder机制有更深的理解,请转到⽼罗的系列⽂字吧,进程间通信Binder机制在应⽤程序框架层的接⼝源代码分析。
下⾯我们看⼀个AIDL实例。
AIDL接⼝声明在src⽬录下创建⼀个com.example.advanceandroid.aidl包,然后在该包下创建⼀个ILogin.aidl⽂件,注意是创建⽂件⽽不是类或者接⼝类型。
在ILogin.aidl中声明接⼝,实例如下 :package com.example.advanceandroid.aidl;interface ILogin {String login();}注意看,接⼝和⽅法声明都不⽤public,⽅法加⼊public会提⽰错误。
详解Androidaidl的使用方法

详解Androidaidl的使⽤⽅法AIDL是Android中IPC(Inter-Process Communication)⽅式中的⼀种,AIDL是Android Interface definition language的缩写(对于⼩⽩来说,AIDL的作⽤是让你可以在⾃⼰的APP⾥绑定⼀个其他APP的service,这样你的APP可以和其他APP交互。
)AIDL只是Android中众多进程间通讯⽅式中的⼀种⽅式,AIDL和Messenger的区别:1. Messenger不适⽤⼤量并发的请求:Messenger以串⾏的⽅式来处理客户端发来的消息,如果⼤量的消息同时发送到服务端,服务端仍然只能⼀个个的去处理。
2. Messenger主要是为了传递消息:对于需要跨进程调⽤服务端的⽅法,这种情景不适⽤Messenger。
3. Messenger的底层实现是AIDL,系统为我们做了封装从⽽⽅便上层的调⽤。
4. AIDL适⽤于⼤量并发的请求,以及涉及到服务端端⽅法调⽤的情况AIDL通信的原理:⾸先看这个⽂件有⼀个叫做proxy的类,这是⼀个代理类,这个类运⾏在客户端中,其实AIDL实现的进程间的通信并不是直接的通信,客户端和服务端都是通过proxy来进⾏通信的:客户端调⽤的⽅法实际是调⽤是proxy中的⽅法,然后proxy通过和服务端通信将返回的结果返回给客户端。
1、AIDL的作⽤AIDL是⽤于Android的IPC通讯的,因此可以在⼀个APP内部通讯,也可以创建两个APP之间进⾏通讯。
AIDL的职能分配很明确,Service作为后台运⾏作为服务器管理各种交互,Client作为客户端请求数据或调⽤Service的⽅法。
2、AIDL的简单使⽤1)创建⼀个aidl⽂件,直接右键创建就可以了,package com.example.mytest;// IMyAidlInterface.aidlpackage com.example.mytest;// Declare any non-default types here with import statementsinterface IMyAidlInterface {/*** 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);String add(int x , int y);}2)选中刚刚建⽴的 .aidl⽂件⽣产对应的java⽂件。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
19.深刻解析Android的AIDL界面在Android应用框架里,应用层级的软件大多是Java类别,而系统层级的软件大多是C或 C++类别。
Android使用JNI接口来达成这个目标。
例如,在Android里有个MediaPlayer.cpp类别,当它搭配上JNI接口之后,在VM上执行的MediaPlayer.java 就可以透过JNI接口与MediaPlayer.cpp类别沟通了。
图1-1基于这样的架构,我门就可以尽量将MediaPlayer.java里的程序逻辑移入MediaPlayer.cpp类别里,以便加快程序的执行速度。
此外,以JNI接口包装MediaPlayer.cpp类别,并且衔接相互辉映的MediaPlayer.java类别,可以让众多的Java 应用程序透过MediaPlayer.java来使用MediaPlayer.cpp类别的服务。
这是一种非常有用的包装技巧,藉由包装来创造更多的应用机会。
为了进一步创造更多的应用机会,可以替MediaPlayer.java类别加上AIDL接口,让更多的Java应用程序能与MediaPlayer.java类别进行远距的IPC沟通。
如下图所示:图1-2上图表示出JNI在Android里扮演的角色,以及Android框架里Java与C/C++类别融合的基本架构。
上面的图1-2是一个较为抽象的图,凸显JNI与AIDL的相互呼应之角色。
于此,以高焕堂所写的第2本Android书:<<Android 软件架构设计>> 一书里的范例:HalfAdder组件为例,展示其幕后的细节架构。
首先看看其JNI界面之上的细节架构,如下UML图:图1-3 上图1-2幕后的细节架构之一上图凸显了AIDL界面的细节架构。
下图1-4将换个角度,从*.so开发者来看,当我们开发系统层级的C/C++类别时,也能善用JNI,创造C/C++类别的广大商机。
其细节架构如下UML图:图1-4 上图1-2幕后的细节架构之二1.3 说明C/C++组件开发从上图1-4可看到此范例的C/C++组件部份。
其详细的程序代码,请阅读高焕堂所写的第2本Android书:<<Android 软件架构设计>> 一书之第5~6章。
1.4 说明AIDL接口类别之开发基于刚才所撰写的相对应Java类别:Calculator.java,就能顺利配上AIDL界面了。
1.4.1 细说AIDL接口与IBinder接口其实,AIDL接口幕后是仰赖着IBinder界面的。
所以,我们的应用程序可以选择使用IBinder接口,也可以使用AIDL接口。
如果采取IBinder接口,就不必使用aidl.exe 工具去产出calInterface.java接口定义文件了,其接口类别较单纯一些,如下图所示:图1-5 仅使用较单纯的IBinder接口由于IBinder接口只提供单一函数(即transact()函数)来进行远距沟通,呼叫起来比较不方便。
例如,当Calculator类别有多个函数时,myActivity要如何呼叫它们呢?可以呼叫IBinder接口的transact()函数,再转而呼叫Calculator的各个函数。
由于它并不太方便,所以Android提供Proxy/Stub结构的AIDL接口来化解这个问题,其架构图如下:图1-6 更方便的AIDL接口(其接口类别结构较复杂一些)在本范例里,将采取AIDL接口,同时也介绍其幕后的IBinder接口,以及其两这之间的密切关系。
1.4.2 细说Stub类别的程序代码这个Stub类别就是由aidl.exe所产出的;也就是在calInterface.java里面。
兹再重复列出calInterface.java程序代码如下:/*---- calInterface.java ----*//** This file is auto-generated. DO NOT MODIFY.* Original file: calInterface.aidl*/package com.misoo.gx06;import ng.String;import android.os.RemoteException;import android.os.IBinder;import android.os.IInterface;import android.os.Binder;import android.os.Parcel;public interface calInterface extends android.os.IInterface{/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implementscom.misoo.gx06.calInterface{private static final ng.String DESCRIPTOR = "com.misoo.gx06.calInterface";/** Construct the stub at attach it to the interface. */public Stub(){this.attachInterface(this, DESCRIPTOR);}/*** Cast an IBinder object into an calInterface interface,* generating a proxy if needed.*/public static com.misoo.gx06.calInterface asInterface(android.os.IBinder obj){if ((obj==null)) {return null;}com.misoo.gx06.calInterface in =(com.misoo.gx06.calInterface)obj.queryLocalInterface(DESCRIPTOR);if ((in!=null)) {return in;}return new com.misoo.gx06.calInterface.Stub.Proxy(obj);}public android.os.IBinder asBinder(){return this;}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_EvDigitPress:{data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 = data.readInt();ng.String _result = this.EvDigitPress(_arg0);reply.writeNoException();reply.writeString(_result);return true;case TRANSACTION_EvCPress:{data.enforceInterface(DESCRIPTOR);ng.String _result = this.EvCPress();reply.writeNoException();reply.writeString(_result);return true;}case TRANSACTION_EvPlusPress:{data.enforceInterface(DESCRIPTOR);ng.String _result = this.EvPlusPress();reply.writeNoException();reply.writeString(_result);return true;}case TRANSACTION_EvAssignPress:{data.enforceInterface(DESCRIPTOR);ng.String _result = this.EvAssignPress();reply.writeNoException();reply.writeString(_result);return true;}}return super.onTransact(code, data, reply, flags);}private static class Proxy implements com.misoo.gx06.calInterface{private android.os.IBinder mRemote;Proxy(android.os.IBinder remote){mRemote = remote;}public android.os.IBinder asBinder(){return mRemote;}public ng.String getInterfaceDescriptor(){return DESCRIPTOR;}public ng.String EvDigitPress(int d) throws android.os.RemoteExceptionandroid.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();ng.String _result;try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(d);mRemote.transact(Stub.TRANSACTION_EvDigitPress, _data, _reply, 0);_reply.readException();_result = _reply.readString();}finally {_reply.recycle();_data.recycle();}return _result;}public ng.String EvCPress() throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();ng.String _result;try {_data.writeInterfaceToken(DESCRIPTOR);mRemote.transact(Stub.TRANSACTION_EvCPress, _data, _reply, 0);_reply.readException();_result = _reply.readString();}finally {_reply.recycle();_data.recycle();}return _result;}public ng.String EvPlusPress() throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();ng.String _result;try {_data.writeInterfaceToken(DESCRIPTOR);mRemote.transact(Stub.TRANSACTION_EvPlusPress, _data, _reply, 0);_reply.readException();_result = _reply.readString();finally {_reply.recycle();_data.recycle();}return _result;}public ng.String EvAssignPress() throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();ng.String _result;try {_data.writeInterfaceToken(DESCRIPTOR);mRemote.transact(Stub.TRANSACTION_EvAssignPress, _data, _reply, 0);_reply.readException();_result = _reply.readString();}finally {_reply.recycle();_data.recycle();}return _result;}}static final int TRANSACTION_EvDigitPress = (IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_EvCPress = (IBinder.FIRST_CALL_TRANSACTION + 1);static final int TRANSACTION_EvPlusPress = (IBinder.FIRST_CALL_TRANSACTION + 2); static final int TRANSACTION_EvAssignPress = (IBinder.FIRST_CALL_TRANSACTION + 3); }public ng.String EvDigitPress(int d) throws android.os.RemoteException; public ng.String EvCPress() throws android.os.RemoteException;public ng.String EvPlusPress() throws android.os.RemoteException;public ng.String EvAssignPress() throws android.os.RemoteException;}这个calInterface.java档案是由aidl.exe工具程序所产出的。