Android之AIDL(进程间通信)

20 阅读3分钟

public void basicTypes(int anInt, long aLong, boolean aBoolean,

float aFloat, double aDouble, String aString) {

// Does nothing

System.out.println("basicTypes");

}

};

/**

  • 实现定义的aidl接口。

*/

private final IRemoteService2.Stub mBinder2 = new IRemoteService2.Stub() {

@Override

public void sysout() {

System.out.println("This is IremoteService2.Stub.sysout()");

}

@Override

public String returnStr() throws RemoteException {

return "This is IRemoteServicfe2.Stub.returnStr()";

}

};

3、向客户端公开(暴露)接口-如果是编写服务,应该继承Service并且重载Service.onBind(Intent) 以返回实现了接口的对象实例

/**

  • 返回IBinder,在这里可以根据选择的接口进行返回哪一个 如果只有一个接口就不需要判断,直接返回就可以了。

*/

@Override

public IBinder onBind(Intent intent) {

if (IRemoteService2.class.getName().equals(intent.getAction())) {

return mBinder2;

}

if (IRemoteService.class.getName().equals(intent.getAction())) {

return mBinder;

}

return null;

}

4、 运行这个程序,那么服务就已经安装到系统了。接下来就是客户端访问服务,利用服务,进行进程间的通信。

下面再看看如何调用IPC 方法(Calling  an  IPC Method)

1、   声明.aidl 文件中定义的接口类型的变量和方法。

IRemoteService.aidl

package hb.android.aidl;

interface IRemoteService {

int getPid();

void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,

double aDouble, String aString);

}

IRemoteService2.aidl

package hb.android.aidl;

interface IRemoteService2 {

void sysout();

String returnStr();

}

2、   实现ServiceConnection

/**

  • ServiceConnection与Service想链接,IRemoteService.Stub.asInterface(service);

  • 会返回与当前的aidl文件相关的类的实例,这样就可以获取到远程的远程服务实现的IRemoteService接口了。

  • 注意如果一个ServiceConnection同一时刻只能与Service连接

  • 。如果需要同时连接一个服务里的多个aidl接口,那么必须定义两个ServiceConnection获取

  • ,因为一个ServiceConnection连接会返回一个aidl接口的实例。

*/

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

try {

if (service.getInterfaceDescriptor().equals(

IRemoteService.class.getName())) {

mIRemoteService = IRemoteService.Stub.asInterface(service);

mIRemoteService.basicTypes(0, 0, false, 0, 0, null);

}

} catch (RemoteException e) {

e.printStackTrace();

}

}

// Called when the connection with the service disconnects unexpectedly

public void onServiceDisconnected(ComponentName className) {

System.out.println("Service has unexpectedly disconnected");

mIRemoteService = null;

}

};

private ServiceConnection mConnection2 = new ServiceConnection() {

@Override

public void onServiceDisconnected(ComponentName name) {

System.out.println("Service2 has unexpectedly disconnected");

mIRemoteService2 = null;

}

@Override

public void onServiceConnected(ComponentName name, IBinder service) {

try {

if (service.getInterfaceDescriptor().equals(

IRemoteService2.class.getName())) {

mIRemoteService2 = IRemoteService2.Stub

.asInterface(service);

mIRemoteService2.sysout();

}

} catch (RemoteException e) {

e.printStackTrace();

}

}

};

3、   调用Context.bindService(),传递ServiceConnection的实现

intent = new Intent(IRemoteService.class.getName());

System.out.println(IRemoteService.class.getName());

bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

intent2 = new Intent(IRemoteService2.class.getName());

System.out.println(IRemoteService2.class.getName());

bindService(intent2, mConnection2, BIND_AUTO_CREATE);

4、   在ServiceConnection.onServiceConnected()方法中会接收到IBinder对象,调用YourInterfaceName.Stub.asInterface((IBinder)service)将返回值转换为YourInterface类型

mIRemoteService = IRemoteService.Stub.asInterface(service);

mIRemoteService.basicTypes(0, 0, false, 0, 0, null);

5、   调用接口中定义的方法。应该总是捕获连接被打断时抛出的DeadObjectException异常,这是远端方法唯一的异常。

6、   调用Context.unbindService()断开连接;

protected void onDestroy() {

super.onDestroy();

unbindService(mConnection);

unbindService(mConnection2);

};

如果想利用进程间的通信来传递对象,那么该对象必须实现Parcelable,下面详细步骤:

1、 使该类实现Parcelabel接口。 

package hb.android.entry;

import android.os.Parcel;

import android.os.Parcelable;

/**

  • 在进行间通信必须实现Parcelable接口

  • @author Administrator

*/

public class Person implements Parcelable {

public String name;

public String sex;

public String tel;

public Person() {

super();

}

public Person(Parcel in) {

readFromParcel(in);

}

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

/**

  • 实现从in中创建出类的实例的功能

*/

public Person createFromParcel(Parcel in) {

return new Person(in);

}

/**

  • 创建一个类型为T,长度为size的数组,仅一句话(return new T[size])即可。估计本方法是供外部类反序列化本类数组使用。

*/

public Person[] newArray(int size) {

return new Person[size];

}

};

/**

  • 从一个外部的Parcel对象读取对象。顺序必须与writeToParcel对应,不然会出错。

  • @param in

*/

public void readFromParcel(Parcel in) {

name = in.readString();

sex = in.readString();

tel = in.readString();

}

/**

  • 该方法将类的数据写入外部提供的Parcel中

*/

@Override

public void writeToParcel(Parcel dest, int flags) {

dest.writeString(name);

dest.writeString(sex);

dest.writeString(tel);

}

/**

  • 没搞懂有什么用,反正直接返回0也可以

*/

@Override

public int describeContents() {

return 0;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getSex() {

return sex;

}

public void setSex(String sex) {

this.sex = sex;

}

public String getTel() {

return tel;

}

public void setTel(String tel) {

this.tel = tel;