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; } @Override public String sayHello() throws RemoteException { // TODO Auto-generated method stub return "欢迎你通过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() { @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub myService=null; } @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub myService=IMyService.Stub.asInterface(service); try { textHello.setText(myService.sayHello()); } catch (RemoteException e) { // TODO Auto-generated catch block e.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; @Override public 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() { @Override public 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,已经从服务端得到了数据,第一句话就是从服务端得到的,下面看看,传递对象和获取对象与服务端。

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值