您的位置:首页 > 移动开发 > Android开发

android进程间通信——aidl(Android Interface Definition Language)

2012-10-21 17:06 267 查看
在android中,通常情况下一个进程是不允许其它进程访问自己的内存的。而aidl提供了client和service都“同意”的交互接口,用以实现进程间通信。

使用aidl通常有三个阶段:

由于创建的是两个应用程序,为了方便介绍,这里先给出服务提供者(Service)的工程目录结构图:



一、aidl的设计——设计aidl包括三个步骤:

1、定义aidl

在设计好aidl接口后,就可以编写aidl文件了。aidl文件编写的语法和java语言的语法一样——后缀名改为.aidl,然后同时将它保存到服务提供者(service)和服务使用者(client)的源代码(src/derectory)目录下。

在上面的目录中,包含了两个aidl文件。其中,IDescribePerson.aidl是重点;Person.aidl是系统的需求,必须定义。

2、实现定义的aidl接口

android SDK 工具会为任何包含有.aidl文件的应用程序生成一个IBinder接口。根据.aidl文件生成的IBinder接口会保存在目录(gen/directory)下,该接口包含一个继承自Binder 的内部类—Stub。你只需要继承Stub类并实现该类的方法即可。

在上面目录中,RemoteService.java继承自Service,其中一成员变量mBinder为IDescribePerson.Stub的实现。

3、将接口暴露给用户

实现一个Service并且复写onBind()方法,该方法返回Stub类的实现类的实例。

RemoteService的onBind()方法返回mBinder

(注意事项:aidl仅支持几种数据类型,包括:java所有的基本数据类型、String、CharSequence、List、Map、(Serializable、Parceable, 及其实现类))

二、进程间传递对象(Passing Objects Over IPC)

要实现进程间对象的传递,则该对象必须支持Parceable——类要实现Parceable接口。

上图中,类Person实现了Parceable接口。

三、调用进程通信方法(calling an IPC Method)——包括7个步骤:

下面将会用到client的相关内容,这里先将client目录结构图给出:



1、确保应用程序包含了aidl文件(如果嫌麻烦,可以直接将cxy.sh.aidl.server包下得内容直接拷贝过来)。

2、声明一个IBinder 的实例(该实例是基于AIDL文件生成的)。

3、实现ServiceConnection。

4、调用bindService(),传递参数ServiceConnection的实现。

5、在实现
onServiceConnected()
方法时,调用YourInterfaceName.Stub.asInterface((IBinder)service)返回接口。

6、调用接口中声明的方法。

7、调用方法
Context.unbindService()
断开与服务的连接。

下面给出各文件的源码(文件内容是eclipse自动生成的就不贴了):

aidlTest应用:

Person.java

package cxy.sh.aidl.server;
import android.os.Parcel;
import android.os.Parcelable;
public class Person implements Parcelable {
private String name ;
private String telNumber ;
private int age;
public Person(Parcel p){
name = p.readString();
telNumber = p.readString();
age = p.readInt();
}
public Person(){
}
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;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int arg1) {
dest.writeString(name);
dest.writeString(telNumber);
dest.writeInt(age);
}
public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>(){
@Override
public Person createFromParcel(Parcel source){
return new Person(source);
}
@Override
public Person[] newArray(int size){
return new Person[size];
}
};
}


RemoteService.java

package cxy.sh.aidl.server;
import java.util.LinkedList;
import java.util.List;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class RemoteService extends Service {
private LinkedList<Person> pList = new LinkedList<Person>();

@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private final IDescribePerson.Stub mBinder = new IDescribePerson.Stub(){

@Override
public void savePersonInfo(Person person) throws RemoteException{
if(person != null){
pList.add(person);
}
}
@Override
public List<Person> getAllPerson() throws RemoteException{
return pList;
}
};
}


IDescribePerson.aidl

package cxy.sh.aidl.server;
import cxy.sh.aidl.server.Person;
interface IDescribePerson{
void savePersonInfo(in Person person);
List<Person> getAllPerson();
}


Person.aidl

package cxy.sh.aidl.server;

parcelable Person;

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cxy.sh.aidl.server"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="14" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:label="@string/app_name"
android:name=".AidlTestActivity" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="RemoteService" >
<intent-filter>
<action android:name="cxy.sh.aidl.server.IDescribePerson"></action>
</intent-filter>
</service>
</application>
</manifest>


aidlClient应用:

AidlClientActivity.java

package cxy.sh.aidl.client;
import java.util.List;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import cxy.sh.aidl.server.IDescribePerson;
import cxy.sh.aidl.server.Person;
public class AidlClientActivity extends Activity {
private Button addPersonButton;
private Button listPersonButton;
private TextView inputPersonEdit;
private IDescribePerson mRemoteService ;
private ServiceConnection mRemoteCon = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mRemoteService = IDescribePerson.Stub.asInterface(service);
inputPersonEdit.setText("remote Servece connected !");
}
@Override
public void onServiceDisconnected(ComponentName name) {
mRemoteService = null ;
Log.e("tag", "remote Servece disconnected !");
}

};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new Thread(new Runnable(){
@Override
public void run() {
Intent service = new Intent("cxy.sh.aidl.server.IDescribePerson");
bindService(service, mRemoteCon,BIND_AUTO_CREATE);  ;
}
}).start();
addPersonButton = (Button) findViewById(R.id.btadd);
listPersonButton = (Button) findViewById(R.id.btlist);
inputPersonEdit = (TextView) findViewById(R.id.tv) ;
addPersonButton.setOnClickListener(
new View.OnClickListener(){
private int index = 0;
@Override
public void onClick(View view) {
Person person = new Person();
index = index + 1;
person.setName("person-->" + index);
person.setAge(20+index);
person.setTelNumber("123456-"+index);
try {
mRemoteService.savePersonInfo(person);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
listPersonButton.setOnClickListener(
new View.OnClickListener(){
@Override
public void onClick(View view) {
List<Person> list = null;
try {
list = mRemoteService.getAllPerson();
} catch (RemoteException e) {
e.printStackTrace();
}
if (list != null){
StringBuilder text = new StringBuilder();
for(Person person : list){
text.append("\n联系人姓名:");
text.append(person.getName());
text.append("\n             年龄 :");
text.append(person.getAge());
text.append("\n 电话号码:");
text.append(person.getTelNumber()+"\n");
}
inputPersonEdit.setText(text);
}else {
Toast.makeText(AidlClientActivity.this, "get data error",
Toast.LENGTH_SHORT).show();
}
}
});
}
@Override
protected void onPause() {
super.onPause();
unbindService(mRemoteCon);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: