由于每个应用程序都运行在自己的进程空间,并且可以从应用程序UI运行另一个服务进程,而且经常会在不同的进程间传递对象。在Android平台,一个进程通常不能访问另一个进程的内存空间。但是android提供了AIDL可以用来进程间数据传递。

AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。
AIDL IPC机制是面向接口的,像COM或Corba一样,但是更加轻量级。它是使用代理类在客户端和实现端传递数据。

下面通过一个实例来演示AIDL,因为是进程之间数据传递,所以这里要使用建立android工程,一个是AIDL的服务端另一个是客户端.

服务端的实现步骤:

1.创建.aidl文件 IMyService.aidl

package cn.com.karl.aidl;import cn.com.karl.aidl.Person;interface IMyService {     void savePersonInfo(in Person person);     List<Person> getAllPerson();     String sayHello();}


因为这里用到了Peson对象,所以要创建一个person类。Person类,是一个序列化的类,这里使用Parcelable 接口来序列化,是Android提供的一个比Serializable 效率更高的序列化类。

public class Person implements Parcelable {    private String name;    private String telNumber;    private int age;    public Person() {}    public Person(Parcel pl){            name = pl.readString();            telNumber = pl.readString();            age = pl.readInt();    }    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 flags) {            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];            }    };}

然后创建Person.aidl文件,注意这里的parcelable小写。

package cn.com.karl.aidl;parcelable Person;
上面的IMyService.aidl保存以后会在gen的相应目录下启动生成如下代码:

Binder

package cn.com.karl.aidl;public interface IMyService extends android.os.IInterface{/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implements cn.com.karl.aidl.IMyService{private static final java.lang.String DESCRIPTOR = "cn.com.karl.aidl.IMyService";/** Construct the stub at attach it to the interface. */public Stub(){this.attachInterface(this, DESCRIPTOR);}/** * Cast an IBinder object into an cn.com.karl.aidl.IMyService interface, * generating a proxy if needed. */public static cn.com.karl.aidl.IMyService asInterface(android.os.IBinder obj){if ((obj==null)) {return null;}android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceof cn.com.karl.aidl.IMyService))) {return ((cn.com.karl.aidl.IMyService)iin);}return new cn.com.karl.aidl.IMyService.Stub.Proxy(obj);}public android.os.IBinder asBinder(){return this;}@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException{switch (code){case INTERFACE_TRANSACTION:{reply.writeString(DESCRIPTOR);return true;}case TRANSACTION_savePersonInfo:{data.enforceInterface(DESCRIPTOR);cn.com.karl.aidl.Person _arg0;if ((0!=data.readInt())) {_arg0 = cn.com.karl.aidl.Person.CREATOR.createFromParcel(data);}else {_arg0 = null;}this.savePersonInfo(_arg0);reply.writeNoException();return true;}case TRANSACTION_getAllPerson:{data.enforceInterface(DESCRIPTOR);java.util.List<cn.com.karl.aidl.Person> _result = this.getAllPerson();reply.writeNoException();reply.writeTypedList(_result);return true;}case TRANSACTION_sayHello:{data.enforceInterface(DESCRIPTOR);java.lang.String _result = this.sayHello();reply.writeNoException();reply.writeString(_result);return true;}}return super.onTransact(code, data, reply, flags);}private static class Proxy implements cn.com.karl.aidl.IMyService{private android.os.IBinder mRemote;Proxy(android.os.IBinder remote){mRemote = remote;}public android.os.IBinder asBinder(){return mRemote;}public java.lang.String getInterfaceDescriptor(){return DESCRIPTOR;}public void savePersonInfo(cn.com.karl.aidl.Person person) throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);if ((person!=null)) {_data.writeInt(1);person.writeToParcel(_data, 0);}else {_data.writeInt(0);}mRemote.transact(Stub.TRANSACTION_savePersonInfo, _data, _reply, 0);_reply.readException();}finally {_reply.recycle();_data.recycle();}}public java.util.List<cn.com.karl.aidl.Person> getAllPerson() throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();java.util.List<cn.com.karl.aidl.Person> _result;try {_data.writeInterfaceToken(DESCRIPTOR);mRemote.transact(Stub.TRANSACTION_getAllPerson, _data, _reply, 0);_reply.readException();_result = _reply.createTypedArrayList(cn.com.karl.aidl.Person.CREATOR);}finally {_reply.recycle();_data.recycle();}return _result;}public java.lang.String sayHello() throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();java.lang.String _result;try {_data.writeInterfaceToken(DESCRIPTOR);mRemote.transact(Stub.TRANSACTION_sayHello, _data, _reply, 0);_reply.readException();_result = _reply.readString();}finally {_reply.recycle();_data.recycle();}return _result;}}static final int TRANSACTION_savePersonInfo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);static final int TRANSACTION_getAllPerson = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);static final int TRANSACTION_sayHello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);}public void savePersonInfo(cn.com.karl.aidl.Person person) throws android.os.RemoteException;public java.util.List<cn.com.karl.aidl.Person> getAllPerson() throws android.os.RemoteException;public java.lang.String sayHello() throws android.os.RemoteException;}
因为sub类实现了Binder接口,所以以后会使用这个类。

2.实现service类

public class RemoteService extends Service {    private LinkedList<Person> personList = new LinkedList<Person>();        @Override    public IBinder onBind(Intent intent) {            return mBinder;    }    private final IMyService.Stub mBinder = new IMyService.Stub(){            @Override            public void savePersonInfo(Person person) throws RemoteException {                    if (person != null){                            personList.add(person);                    }            }            @Override            public List<Person> getAllPerson() throws RemoteException {                    return personList;            }@Overridepublic String sayHello() throws RemoteException {// TODO Auto-generated method stubreturn "欢迎你通过AIDL访问服务器端";}    };}

3.客户端实现步骤:

首先建立一个项目,把服务端的

包和类一起拷贝到客户端项目中。因为客户端要和服务端通信,必须要使用同一个aidl。

然后构造客户端的activity类:

public class RemoteClientActivity extends Activity {    /** Called when the activity is first created. */private TextView textHello,textPerson;private IMyService myService;private Button btnSave;private Button btnGet;private static Boolean mIsRemoteBound=false;private ServiceConnection conn=new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {// TODO Auto-generated method stubmyService=null;}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {// TODO Auto-generated method stubmyService=IMyService.Stub.asInterface(service);try {textHello.setText(myService.sayHello());} catch (RemoteException e) {// TODO Auto-generated catch blocke.printStackTrace();}}};    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);                textHello=(TextView) this.findViewById(R.id.textHello);        btnSave=(Button) this.findViewById(R.id.btnSave);        btnGet=(Button) this.findViewById(R.id.btnGet);        textPerson=(TextView) this.findViewById(R.id.textPerson);        if(mIsRemoteBound){        unbindService(conn);        }else{        Intent intent=new Intent("cn.com.karl.aidl.RemoteService");        bindService(intent, conn, BIND_AUTO_CREATE);        }        mIsRemoteBound = !mIsRemoteBound;        btnSave.setOnClickListener(new OnClickListener() {          private int index = 0;@Overridepublic void onClick(View v) {// TODO Auto-generated method stub   Person person = new Person();                   index = index + 1;                   person.setName("Person" + index);                   person.setAge(20);                   person.setTelNumber("123456");                    try {                   myService.savePersonInfo(person);                   } catch (RemoteException e) {                           e.printStackTrace();                   } }});        btnGet.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stub  List<Person> list = null;                   try {                          list = myService.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());                          }                          textPerson.setText(text);                  }else {                          Toast.makeText(RemoteClientActivity.this, "得到数据出错",                                          Toast.LENGTH_SHORT).show();                  } }});    }}

最后不要忘记注册service:

  <application        android:icon="@drawable/ic_launcher"        android:label="@string/app_name" >        <activity android:name=".MainActivity">            <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="cn.com.karl.aidl.RemoteService"></action>            </intent-filter>        </service>    </application>

启动service的时候使用了隐士意图。

运行服务端工程.

服务端已经启动,然后运行客户端工程:

OK,已经从服务端得到了数据,第一句话就是从服务端得到的,下面看看,传递对象和获取对象与服务端。

点击添加联系人,然后点击获取联系人按钮:




原文链接: http://blog.csdn.net/wangkuifeng0118/article/details/7277680

更多相关文章

  1. Android进程间通信机制——基础篇
  2. Android四大组件中每个组件的作用是什么?它们都可以开启多进程吗?
  3. Android中Service(服务)的使用
  4. Android(安卓)操作系统的内存回收机制(转载)
  5. Android(安卓)博客园客户端 (七)登录功能
  6. android binder 进程间通信机制4-Service Manager
  7. Android(安卓)开源项目第三篇——优秀项目篇
  8. webrtc服务器janus android客户端编译学习三
  9. Android中的UID和AppId

随机推荐

  1. Android(安卓)代码生成界面Sample
  2. 【译】Android(安卓)23最新接口变化(Andro
  3. Delphi XE5 android 获取电池电量
  4. Android(安卓)中保存图片的代码
  5. Android(安卓)密度转换多分辨率
  6. Android(安卓)DHT11驱动
  7. Android水波纹效果顺手拈来!
  8. Android(安卓)wifi信号强弱检测
  9. android对话框弹出方式动画
  10. Android(安卓)API level与version对应关