什么是aidl:
aidl是 Android Interface definition language的缩写,一看就明白,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口
icp:interprocess communication :内部进程通信。

在Android中, 每个应用程序都有自己的进程,当需要在不同的进程之间传递对象时,该如何实现呢? 显然, Java中是不支持跨进程内存共享的。因此要传递对象, 需要把对象解析成操作系统能够理解的数据格式, 以达到跨界对象访问的目的。在JavaEE中,采用RMI通过序列化传递对象。在Android中, 则采用AIDL(Android Interface Definition Language:接口定义语言)方式实现。

(1)在Eclipse Android工程的Java包目录中建立一个扩展名为aidl的文件。该文件的语法类似于Java代码,但会稍有不同。
(2)如果aidl文件的内容是正确的,ADT会自动生成一个Java接口文件(*.java)。
(3)建立一个服务类(Service的子类)。
(4)实现由aidl文件生成的Java接口。
(5)在AndroidManifest.xml文件中配置AIDL服务,尤其要注意的是,<action>标签中android:name的属性值就是客户端要引用该服务的ID,也就是Intent类的参数值。

AIDL是一种接口定义语言,用于约束两个进程间的通讯规则,供编译器生成代码,实现Android设备上的两个进程间通信(IPC)。AIDL的IPC机制和EJB所采用的CORBA很类似,进程之间的通信信息,首先会被转换成AIDL协议消息,然后发送给对方,对方收到AIDL协议消息后再转换成相应的对象。由于进程之间的通信信息需要双向转换,所以android采用代理类在背后实现了信息的双向转换,代理类由android编译器生成,对开发人员来说是透明的。

实现进程通信,一般需要下面四个步骤:

假设A应用需要与B应用进行通信,调用B应用中的download(String path)方法,B应用以Service方式向A应用提供服务。需要下面四个步骤:

1>在B应用中创建*.aidl文件,aidl文件的定义和接口的定义很相类,如:在cn.itcast.aidl包下创建IDownloadService.aidl文件,内容如下:

package cn.itcast.aidl;

interface IDownloadService {

void download(String path);

}

当完成aidl文件创建后,eclipse会自动在项目的gen目录中同步生成IDownloadService.java接口文件。接口文件中生成一个Stub的抽象类,里面包括aidl定义的方法,还包括一些其它辅助方法。值得关注的是asInterface(IBinder iBinder),它返回接口类型的实例,对于远程服务调用,远程服务返回给客户端的对象为代理对象,客户端在onServiceConnected(ComponentName name, IBinder service)方法引用该对象时不能直接强转成接口类型的实例,而应该使用asInterface(IBinder iBinder)进行类型转换。

编写Aidl文件时,需要注意下面几点:

1.接口名和aidl文件名相同。

2.接口和方法前不用加访问权限修饰符public,private,protected等,也不能用final,static。

3.Aidl默认支持的类型包话java基本类型(int、long、boolean等)和(String、List、Map、CharSequence),使用这些类型时不需要import声明。对于List和Map中的元素类型必须是Aidl支持的类型。如果使用自定义类型作为参数或返回值,自定义类型必须实现Parcelable接口。

4.自定义类型和AIDL生成的其它接口类型在aidl描述文件中,应该显式import,即便在该类和定义的包在同一个包中。

5.在aidl文件中所有非Java基本类型参数必须加上in、out、inout标记,以指明参数是输入参数、输出参数还是输入输出参数。

6.Java原始类型默认的标记为in,不能为其它标记。

2>在B应用中实现aidl文件生成的接口(本例是IDownloadService),但并非直接实现接口,而是通过继承接口的Stub来实现(Stub抽象类内部实现了aidl接口),并且实现接口方法的代码。内容如下:

public class ServiceBinder extends IDownloadService.Stub {

@Override

public void download(String path) throws RemoteException {

Log.i("DownloadService", path);

}

}

3>在B应用中创建一个Service(服务),在服务的onBind(Intent intent)方法中返回实现了aidl接口的对象(本例是ServiceBinder)。内容如下:

public class DownloadService extends Service {

private ServiceBinder serviceBinder = new ServiceBinder();

@Override

public IBinder onBind(Intent intent) {

return serviceBinder;

}

public class ServiceBinder extends IDownloadService.Stub {

@Override

public void download(String path) throws RemoteException {

Log.i("DownloadService", path);

}

}

}

其他应用可以通过隐式意图访问服务,意图的动作可以自定义,AndroidManifest.xml配置代码如下:

<service android:name=".DownloadService" >

<intent-filter>

<action android:name="cn.itcast.process.aidl.DownloadService" />

</intent-filter>

</service>

4>把B应用中aidl文件所在package连同aidl文件一起拷贝到客户端A应用,eclipse会自动在A应用的gen目录中为aidl文件同步生成IDownloadService.java接口文件,接下来就可以在A应用中实现与B应用通信,代码如下:

public class ClientActivity extends Activity {

private IDownloadService downloadService;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

this.bindService(new Intent("cn.itcast.process.aidl.DownloadService"), this.serviceConnection, BIND_AUTO_CREATE);//绑定到服务

}

@Override

protected void onDestroy() {

super.onDestroy();

this.unbindService(serviceConnection);//解除服务

}

private ServiceConnection serviceConnection = new ServiceConnection() {

@Override

public void onServiceConnected(ComponentName name, IBinder service) {

downloadService = IDownloadService.Stub.asInterface(service);

try {

downloadService.download("http://www.itcast.cn");

} catch (RemoteException e) {

Log.e("ClientActivity", e.toString());

}

}

@Override

public void onServiceDisconnected(ComponentName name) {

downloadService = null;

}

};

}

Aidl默认支持的类型包话java基本类型(int、long、boolean等)和(String、List、Map、CharSequence),如果要传递自定义的类型该如何实现呢?

进程间传递自定义类型的实现过程请参见页面下方备注栏:

1> 创建自定义类型,并实现Parcelable接口,使其支持parcelable协议。如:在cn.itcast.domain包下创建Person.java:

package cn.itcast.domain;

import android.os.Parcel;

import android.os.Parcelable;

public class Person implements Parcelable

private Integer id;

private String name;

public Person(){}

public Person(Integer id, String name) {

this.id = id;

this.name = name;

}

public Integer getId() {

return id;

}

public void setId(Integer id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

@Override

public int describeContents() {

return 0;

}

@Override

public void writeToParcel(Parcel dest, int flags) {//把javanbean中的数据写到Parcel

dest.writeInt(this.id);

dest.writeString(this.name);

}

//添加一个静态成员,名为CREATOR,该对象实现了Parcelable.Creator接口

public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>(){

@Override

public Person createFromParcel(Parcel source) {//从Parcel中读取数据,返回person对象

return new Person(source.readInt(), source.readString());

}

@Override

public Person[] newArray(int size) {

return new Person[size];

}

};

}

2> 在自定义类型所在包下创建一个aidl文件对自定义类型进行声明,文件的名称与自定义类型同名。

package cn.itcast.domain;

parcelable Person;

3> 在接口aidl文件中使用自定义类型,需要使用import显式导入,本例在cn.itcast.aidl包下创建IPersonService.aidl文件,内容如下:

package cn.itcast.aidl;

import cn.itcast.domain.Person;

interface IPersonService {

void save(in Person person);

}

4> 在实现aidl文件生成的接口(本例是IPersonService),但并非直接实现接口,而是通过继承接口的Stub来实现(Stub抽象类内部实现了aidl接口),并且实现接口方法的代码。内容如下:

public class ServiceBinder extends IPersonService.Stub {

@Override

public void save(Person person) throws RemoteException {

Log.i("PersonService", person.getId()+"="+ person.getName());

}

}

5> 创建一个Service(服务),在服务的onBind(Intent intent)方法中返回实现了aidl接口的对象(本例是ServiceBinder)。内容如下:

public class PersonService extends Service {

private ServiceBinder serviceBinder = new ServiceBinder();

@Override

public IBinder onBind(Intent intent) {

return serviceBinder;

}

public class ServiceBinder extends IPersonService.Stub {

@Override

public void save(Person person) throws RemoteException {

Log.i("PersonService", person.getId()+"="+ person.getName());

}

}

}

其他应用可以通过隐式意图访问服务,意图的动作可以自定义,AndroidManifest.xml配置代码如下:

<service android:name=".PersonService" >

<intent-filter>

<action android:name="cn.itcast.process.aidl.PersonService " />

</intent-filter>

</service>

6> 把应用中的aidl文件和所在package一起拷贝到客户端应用的src目录下,eclipse会自动在客户端应用的gen目录中为aidl文件同步生成IPersonService.java接口文件,接下来再把自定义类型文件和类型声明aidl文件及所在package一起拷贝到客户端应用的src目录下。

最后就可以在客户端应用中实现与远程服务的通信,代码如下:

public class ClientActivity extends Activity {

private IPersonService personService;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

this.bindService(new Intent("cn.itcast.process.aidl.PersonService"), this.serviceConnection, BIND_AUTO_CREATE);//绑定到服务

}

@Override

protected void onDestroy() {

super.onDestroy();

this.unbindService(serviceConnection);//解除服务

}

private ServiceConnection serviceConnection = new ServiceConnection() {

@Override

public void onServiceConnected(ComponentName name, IBinder service) {

personService = IPersonService.Stub.asInterface(service);

try {

personService.save(new Person(56,"liming"));

} catch (RemoteException e) {

Log.e("ClientActivity", e.toString());

}

}

@Override

public void onServiceDisconnected(ComponentName name) {

personService = null;

}

};

}

最后我们在总结一下android中 本地服务和 AIDL服务的区别:
本地服务不支持onBind(),它从onBind()返回null,这种类型的服务只能由承载服务的应用程序组件访问。可以调用 startService()来调用本地服务。AIDL服务可以同时供 同一进程内的组件和其他应用程序的组件使用。这种类型的服务在AIDL 文件中为自身与其客户端定义一个契约。服务实现 AIDL契约,而客户端绑定到 AIDL定义。服务通过从 onBind()方法 返回AIDL接口的实现,来实现契约。客户端通过调用 bindService()来绑定到AIDL服务,并调用 unBindService()来从服务断开。

更多相关文章

  1. Android:apk文件结构及打包技巧
  2. Android(安卓)java.io.IOException异常情况整理
  3. android初次学习(android studio安装及注意事项 1.5版本)
  4. Android的WebView简单使用实例(附Demo)
  5. android camera API1调用camera HAL3流程学习总结
  6. Android(安卓)数据存储和文件使用案例分析
  7. Android学习笔记--Binder
  8. 3. Android(安卓)MultiMedia框架完全解析 - setDataSource继续分
  9. android 使用AsyncTask实现异步下载文件

随机推荐

  1. Android之 UI主线程
  2. Android(安卓)高级进阶之路 《总结篇》
  3. Android使用JDBC连接mysql数据库
  4. Android(安卓)recovery 流程分析
  5. Eclipse 安装 Google Android(安卓)插件
  6. android 多媒体数据库详解
  7. 《深入浅出Google Android》即将隆重上市
  8. Android实现朋友圈评论回复列表
  9. Android中gravity与layout_gravity的区别
  10. Android(安卓)corners 圆角属性各个版本