android开发AIDL实例
由于每个应用程序都运行在自己的进程空间,并且可以从应用程序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
更多相关文章
- Android进程间通信机制——基础篇
- Android四大组件中每个组件的作用是什么?它们都可以开启多进程吗?
- Android中Service(服务)的使用
- Android(安卓)操作系统的内存回收机制(转载)
- Android(安卓)博客园客户端 (七)登录功能
- android binder 进程间通信机制4-Service Manager
- Android(安卓)开源项目第三篇——优秀项目篇
- webrtc服务器janus android客户端编译学习三
- Android中的UID和AppId