AIDL (Android Interface Definition Language)是一种IDL语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。
由于每个应用程序都运行在自己的进程空间,并且可以从应用程序UI运行另一个服务进程,而且经常会在不同的进程间传递对象。在Android平台,一个进程通常不能访问另一个进程的内存空间,所以要想对话,需要将对象分解成操作系统可以理解的基本单元,并且有序的通过进程边界。
通过代码来实现这个数据传输过程是冗长乏味的,Android提供了AIDL工具来处理这项工作。
选择AIDL的使用场合
官方文档特别提醒我们何时使用AIDL是必要的:只有你允许客户端从不同的应用程序为了进程间的通信而去访问你的service,以及想在你的service处理多线程。
如果不需要进行不同应用程序间的并发通信(IPC),you should create your interface by implementing a Binder;或者你想进行IPC,但不需要处理多线程的,则implement your interface using a Messenger。无论如何,在使用AIDL前,必须要理解如何绑定service——bindService。
1定义服务端
用鼠标点击目录main 创建aidl文件
1、首先你需要在工程module目录下的src下main中新建一个aidl文件夹,操作方式如下:
2、创建后android studio会自动在mian下新建aidl文件夹,并且在aidl文件下自动新增一个与项目同名的包,新建的aidl文件就在这个包下。
如果是别处复制来的aidl文件,就要自己创建相应的文件夹和相应的包,包名需和AndroidManifest.xml中的Package名字一致。总之最后的效果要和下图一样。
3、重新编译若顺利通过了,就会在app/build/generated/source/aidl/debug/下生成了MusicConnect.java,但是我在编译的时候报了下面的错误:
提示MusicConnect.aidl中导入的类MusicData找不到。到MusicConnect.aidl文件中看看,确实导入了MusicData这个类
4、为何提示找不到这个类呢?
参考《Android/OPhone开发完全讲义》第8章里的一段叙述:
“AIDL服务只支持有限的数据类型,因此,如果用AIDL服务传递一些复杂的数据就需要做更一步处理。AIDL服务支持的数据类型如下:
Java的简单类型(int、char、boolean等)。不需要导入(import)。
String和CharSequence。不需要导入(import)。
List和Map。但要注意,List和Map对象的元素类型必须是AIDL服务支持的数据类型。不需要导入(import)。
AIDL自动生成的接口。需要导入(import)。
实现android.os.Parcelable接口的类。需要导入(import)。
其中后两种数据类型需要使用import进行导入,将在本章的后面详细介绍。
传递不需要import的数据类型的值的方式相同。传递一个需要import的数据类型的值(例如,实现android.os.Parcelable接口的类)的步骤略显复杂。除了要建立一个实现android.os.Parcelable接口的类外,还需要为这个类单独建立一个aidl文件,并使用parcelable关键字进行定义。”
看完这段话后,在看看MusicData这个类,他的确是一个实现了android.os.Parcelable接口的类
5、因此我们还要单独建立一个MusicData.aidl文件,并使用parcelable关键字进行定义。并且要将MusicData.aidl文件放在与MusicData.java文件相对应的entity包中,看下图你就明白了。
6、这时就可以重新编译项目,编译之后就会在app/build/generated/source/aidl/debug/下生成了MusicConnect.java
这样就可以在其他的类中调用MusicConnect.java中的方法了。
=================================================================================================
1 创建需要传递的对象 Parcelable
public class Person implements Parcelable {
private String name;
public Person() {
}
protected Person(Parcel in) {
name = in.readString();
telNumber = in.readString();
}
public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
@Override
public Person createFromParcel(Parcel in) {
return new Person(in);
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTelNumber() {
return telNumber;
}
public void setTelNumber(String telNumber) {
this.telNumber = telNumber;
}
private String telNumber;
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(telNumber);
}
}
2 编写aidl (Person 对象的路径和在aidl中的Person.aidl路径必须相同)
// Person.aidl
package com.example.servers;
parcelable Person;
IMyAidlInterface.aidl
package com.example.servers;
import com.example.servers.Person;//手动编写
//IMyAidlInterface
interface IMyAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
Person getinfo();
}
3 build工程
4 创建 myservers 继承server 在配置文件中配置
<service android:name=".Myservers" > <intent-filter> <action android:name="com" /> </intent-filter> </service>
public class Myservers extends Service { IMyAidlInterface.Stub std= new IMyAidlInterface.Stub(){ Myservers my=Myservers.this; @Override public Person getinfo() throws RemoteException { return my.getinfo(); } }; @Override public void onCreate() { super.onCreate(); // Logger.addLogAdapter(new AndroidLogAdapter()); Toast.makeText(this, "出阿尕金", Toast.LENGTH_SHORT).show(); } @Override public IBinder onBind(Intent intent) { return std; } public Person getinfo(){ Person person = new Person(); person.setName("zhangsang"); person.setTelNumber("18923023293"); return person; } }
5 在服务端启动服务
Intent intents=new Intent(); intents.setAction("com"); intents.setPackage(this.getPackageName()); con=new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); try { getinfo = iMyAidlInterface.getinfo(); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { } }; bindService(intents, con, BIND_AUTO_CREATE);
客户端
复制 服务端的aidl整个目录到客户端 把服务端的Person.java 复制整个路径到 客户端
客户端调用
Intent intents=new Intent(); intents.setAction("com"); intents.setPackage("com.example.servers");//服务端的包名 con=new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Toast.makeText(MainActivity.this, "绑定成功", Toast.LENGTH_SHORT).show(); iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); try { getinfo = iMyAidlInterface.getinfo(); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { } }; bindService(intents, con, BIND_AUTO_CREATE);