android里每个应用程序有一个独立的虚拟机,每个程序无法和另一个程序直接通信,保证了进程之内数据的安全,保证一个程序挂掉不至于影响另一个程序。Android里跨进程间通信必须通过系统底层间接的进行通信。
在android SDK中提供了4种用于跨进程通讯的方式。这4种方式正好对应于android系统中4种应用程序组件:Activity、Content Provider、Broadcast和Service。其中Activity可以跨进程调用其他应用程序的Activity;Content Provider可以跨进程访问其他应用程序中的数据(以Cursor对象形式返回),当然,也可以对其他应用程序的数据进行增、删、改操 作;Broadcast可以向android系统中所有应用程序发送广播,而需要跨进程通讯的应用程序可以监听这些广播;Service和Content Provider类似,也可以访问其他应用程序中的数据,但不同的是,Content Provider返回的是Cursor对象,而Service返回的是Java对象,这种可以跨进程通讯的服务叫AIDL服务。
Android Interface Defined Language(安卓接口定义语言),是android提供的一种进程间通信的解决方案;AIDL用起来比较耗内存、资源,所以没有必要所有地方都用AIDL。
如果只想IPC(跨进程)多个应用程序(无多线程)去访问只需要用binder,如果只想IPC(跨进程)不跨应用程序访问只需要用Messenger;只有你允许客户端从不同的应用程序为了进程间的通信而去访问你的service,以及想在你的service处理多线程,才去使用AIDL。
一. AIDL的基本使用:
1.创建.aidl文件:
as可以自动生成,但需要手动进行编译;eclipse则需要自己创建file,然后把后缀改为.aidl;如果不用IDE编译,也可以用sdk\build-tools\版本号\aidl.exe 工具进行编译,但注意要先添加环境变量。
编译成功后会在相应的目录下生成.java文件。
以下为官方的示例:
// 包名 package com.example.android; // Declare any non-default types here with import statements /** Example service interface */ interface IRemoteService { //实际就是一个接口,注意接口名要和aidl文件名一致 /** Request the process ID of this service, to do evil things with it. */ int getPid();//业务方法 /** 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); }2.继承接口,并向客户端暴露这个接口
public class RemoteService extends Service { @Override public void onCreate() { super.onCreate(); }现在当客户端调用bindService时,客户端的onServiceConected就会接收到这个binder实例了。private final IRemoteService.Stub mBinder = new IRemoteService.Stub() { public int getPid(){ return Process.myPid(); } public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) { // Does nothing } };@Override public IBinder onBind(Intent intent) { // 客户端进行绑定的时候,就获取到了该接口 return mBinder; } private final IRemoteService.Stub mBinder = new IRemoteService.Stub() { public int getPid(){//实现业务方法的逻辑 return Process.myPid(); } public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) { // Does nothing } };}
继承接口的时候有以下注意事项:
- Incoming calls are not guaranteed to be executed on the main thread, so you need to thinkabout multithreading from the start and properly build your service to be thread-safe.
- By default, RPC calls are synchronous. If you know that the service takes more than a fewmilliseconds to complete a request, you should not call it from the activity's main thread, becauseit might hang the application (Android might display an "Application is Not Responding"dialog)—you should usually call them from a separate thread in the client.
- No exceptions that you throw are sent back to the caller.
3.客户端调用
IRemoteService mIRemoteService; private ServiceConnection mConnection = new ServiceConnection() { // Called when the connection with the service is established public void onServiceConnected(ComponentName className, IBinder service) { // Following the example above for an AIDL interface, // this gets an instance of the IRemoteInterface, which we can use to call on the service mIRemoteService = IRemoteService.Stub.asInterface(service); } // Called when the connection with the service disconnects unexpectedly public void onServiceDisconnected(ComponentName className) { Log.e(TAG, "Service has unexpectedly disconnected"); mIRemoteService = null; } };
二.数据传递
支持的类型:
String
CharSequence
List(里面的元素都必须是支持的类型)
Map
(里面的元素都必须是支持的类型)
- 除short外的基本类型
- 使用List Map 需要加 in/out标识
- 继承
Parcelable
接口. - Implement
writeToParcel
, which takes thecurrent state of the object and writes it to aParcel
. - Add a static field called
CREATOR
to your class which is an object implementingtheParcelable.Creator
interface. - Finally, create an
.aidl
file that declares your parcelable class (as shown for theRect.aidl
file, below).
public class Person implements Parcelable{
private String name;
private int age;
/**
* @param source
*/
public Person(Parcel source) {
this.name = source.readString();
this.age = source.readInt();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public int describeContents() {
return 0;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
//塞进去 注意读写的顺序
dest.writeString(name);
dest.writeInt(age);
}
public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override//取出来 注意读写的顺序
public Person createFromParcel(Parcel source) {
return new Person(source);
}
@Override
public Person[] newArray(int size) {
return new Person[size];
}
};
public String toString() {
return "Person{name:"+name+ " age:"+age+ "}";
};
}
IRemoteService.aidl文件
package com.pigpp.aidl;
import com.pigpp.aidl.Person;
interface IRemoteService {
List<Person> add(in Person person);
}
Person.aidl(必须有,不然在aidl文件里导入Person类时找不到)
package com.pigpp.aidl;
parcelable Person;
服务端的service类,供客户端绑定后调用服务端的业务方法:
public class IRemoteService extends Service {
List<Person> persons;
private IBinder mBinder = new PersonCURD.Stub() {
@Override
public List<Person> add(Person person) throws RemoteException {
persons = new ArrayList<>();
persons.add(person);
return persons;
}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
客户端MainActivity
private Button btn;
PersonCURD mPersonCURD;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
mPersonCURD = null ;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mPersonCURD = PersonCURD.Stub.asInterface(service);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.btn);
Intent intent = new Intent("com.pigpp.aidl.IRemoteService");
bindService(intent, conn , Context.BIND_AUTO_CREATE);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
try {
List<Person> persons = mPersonCURD.add(new Person("张三",12));
Log.d("TAG", persons.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
-------------------------------End-----------------------------------------------
参考文章:http://android.blog.51cto.com/268543/537684/
参考视频:http://www.imooc.com/learn/606
代码地址:http://download.youkuaiyun.com/detail/u010431640/9449801