android开发AIDL实例

来源:互联网 发布:网络机顶盒看电视软件 编辑:程序博客网 时间:2024/05/17 23:04

From: http://blog.csdn.net/wangkuifeng0118/article/details/7277680 

  由于每个应用程序都运行在自己的进程空间,并且可以从应用程序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

        

[html] view plaincopy
  1. package cn.com.karl.aidl;  
  2. import cn.com.karl.aidl.Person;  
  3.   
  4. interface IMyService {  
  5.      void savePersonInfo(in Person person);  
  6.      List<Person> getAllPerson();  
  7.      String sayHello();  
  8. }  

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

       
[html] view plaincopy
  1. public class Person implements Parcelable {  
  2.   
  3.     private String name;  
  4.     private String telNumber;  
  5.     private int age;  
  6.   
  7.     public Person() {}  
  8.   
  9.     public Person(Parcel pl){  
  10.             name = pl.readString();  
  11.             telNumber = pl.readString();  
  12.             age = pl.readInt();  
  13.     }  
  14.   
  15.     public String getName() {  
  16.             return name;  
  17.     }  
  18.   
  19.     public void setName(String name) {  
  20.             this.name = name;  
  21.     }  
  22.   
  23.     public String getTelNumber() {  
  24.             return telNumber;  
  25.     }  
  26.   
  27.     public void setTelNumber(String telNumber) {  
  28.             this.telNumber = telNumber;  
  29.     }  
  30.   
  31.     public int getAge() {  
  32.             return age;  
  33.     }  
  34.   
  35.     public void setAge(int age) {  
  36.             this.age = age;  
  37.     }  
  38.   
  39.     @Override  
  40.     public int describeContents() {  
  41.             return 0;  
  42.     }  
  43.   
  44.     @Override  
  45.     public void writeToParcel(Parcel dest, int flags) {  
  46.             dest.writeString(name);  
  47.             dest.writeString(telNumber);  
  48.             dest.writeInt(age);  
  49.     }  
  50.   
  51.     public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {  
  52.   
  53.             @Override  
  54.             public Person createFromParcel(Parcel source) {  
  55.                     return new Person(source);  
  56.             }  
  57.   
  58.             @Override  
  59.             public Person[] newArray(int size) {  
  60.                     return new Person[size];  
  61.             }  
  62.   
  63.     };  
  64. }  

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

         

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

Binder

[html] view plaincopy
  1. package cn.com.karl.aidl;  
  2. public interface IMyService extends android.os.IInterface  
  3. {  
  4. /** Local-side IPC implementation stub class. */  
  5. public static abstract class Stub extends android.os.Binder implements cn.com.karl.aidl.IMyService  
  6. {  
  7. private static final java.lang.String DESCRIPTOR = "cn.com.karl.aidl.IMyService";  
  8. /** Construct the stub at attach it to the interface. */  
  9. public Stub()  
  10. {  
  11. this.attachInterface(this, DESCRIPTOR);  
  12. }  
  13. /**  
  14.  * Cast an IBinder object into an cn.com.karl.aidl.IMyService interface,  
  15.  * generating a proxy if needed.  
  16.  */  
  17. public static cn.com.karl.aidl.IMyService asInterface(android.os.IBinder obj)  
  18. {  
  19. if ((obj==null)) {  
  20. return null;  
  21. }  
  22. android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);  
  23. if (((iin!=null)&&(iin instanceof cn.com.karl.aidl.IMyService))) {  
  24. return ((cn.com.karl.aidl.IMyService)iin);  
  25. }  
  26. return new cn.com.karl.aidl.IMyService.Stub.Proxy(obj);  
  27. }  
  28. public android.os.IBinder asBinder()  
  29. {  
  30. return this;  
  31. }  
  32. @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException  
  33. {  
  34. switch (code)  
  35. {  
  36. case INTERFACE_TRANSACTION:  
  37. {  
  38. reply.writeString(DESCRIPTOR);  
  39. return true;  
  40. }  
  41. case TRANSACTION_savePersonInfo:  
  42. {  
  43. data.enforceInterface(DESCRIPTOR);  
  44. cn.com.karl.aidl.Person _arg0;  
  45. if ((0!=data.readInt())) {  
  46. _arg0 = cn.com.karl.aidl.Person.CREATOR.createFromParcel(data);  
  47. }  
  48. else {  
  49. _arg0 = null;  
  50. }  
  51. this.savePersonInfo(_arg0);  
  52. reply.writeNoException();  
  53. return true;  
  54. }  
  55. case TRANSACTION_getAllPerson:  
  56. {  
  57. data.enforceInterface(DESCRIPTOR);  
  58. java.util.List<cn.com.karl.aidl.Person> _result = this.getAllPerson();  
  59. reply.writeNoException();  
  60. reply.writeTypedList(_result);  
  61. return true;  
  62. }  
  63. case TRANSACTION_sayHello:  
  64. {  
  65. data.enforceInterface(DESCRIPTOR);  
  66. java.lang.String _result = this.sayHello();  
  67. reply.writeNoException();  
  68. reply.writeString(_result);  
  69. return true;  
  70. }  
  71. }  
  72. return super.onTransact(code, data, reply, flags);  
  73. }  
  74. private static class Proxy implements cn.com.karl.aidl.IMyService  
  75. {  
  76. private android.os.IBinder mRemote;  
  77. Proxy(android.os.IBinder remote)  
  78. {  
  79. mRemote = remote;  
  80. }  
  81. public android.os.IBinder asBinder()  
  82. {  
  83. return mRemote;  
  84. }  
  85. public java.lang.String getInterfaceDescriptor()  
  86. {  
  87. return DESCRIPTOR;  
  88. }  
  89. public void savePersonInfo(cn.com.karl.aidl.Person person) throws android.os.RemoteException  
  90. {  
  91. android.os.Parcel _data = android.os.Parcel.obtain();  
  92. android.os.Parcel _reply = android.os.Parcel.obtain();  
  93. try {  
  94. _data.writeInterfaceToken(DESCRIPTOR);  
  95. if ((person!=null)) {  
  96. _data.writeInt(1);  
  97. person.writeToParcel(_data, 0);  
  98. }  
  99. else {  
  100. _data.writeInt(0);  
  101. }  
  102. mRemote.transact(Stub.TRANSACTION_savePersonInfo, _data, _reply, 0);  
  103. _reply.readException();  
  104. }  
  105. finally {  
  106. _reply.recycle();  
  107. _data.recycle();  
  108. }  
  109. }  
  110. public java.util.List<cn.com.karl.aidl.Person> getAllPerson() throws android.os.RemoteException  
  111. {  
  112. android.os.Parcel _data = android.os.Parcel.obtain();  
  113. android.os.Parcel _reply = android.os.Parcel.obtain();  
  114. java.util.List<cn.com.karl.aidl.Person> _result;  
  115. try {  
  116. _data.writeInterfaceToken(DESCRIPTOR);  
  117. mRemote.transact(Stub.TRANSACTION_getAllPerson, _data, _reply, 0);  
  118. _reply.readException();  
  119. _result = _reply.createTypedArrayList(cn.com.karl.aidl.Person.CREATOR);  
  120. }  
  121. finally {  
  122. _reply.recycle();  
  123. _data.recycle();  
  124. }  
  125. return _result;  
  126. }  
  127. public java.lang.String sayHello() throws android.os.RemoteException  
  128. {  
  129. android.os.Parcel _data = android.os.Parcel.obtain();  
  130. android.os.Parcel _reply = android.os.Parcel.obtain();  
  131. java.lang.String _result;  
  132. try {  
  133. _data.writeInterfaceToken(DESCRIPTOR);  
  134. mRemote.transact(Stub.TRANSACTION_sayHello, _data, _reply, 0);  
  135. _reply.readException();  
  136. _result = _reply.readString();  
  137. }  
  138. finally {  
  139. _reply.recycle();  
  140. _data.recycle();  
  141. }  
  142. return _result;  
  143. }  
  144. }  
  145. static final int TRANSACTION_savePersonInfo = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);  
  146. static final int TRANSACTION_getAllPerson = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);  
  147. static final int TRANSACTION_sayHello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);  
  148. }  
  149. public void savePersonInfo(cn.com.karl.aidl.Person person) throws android.os.RemoteException;  
  150. public java.util.List<cn.com.karl.aidl.Person> getAllPerson() throws android.os.RemoteException;  
  151. public java.lang.String sayHello() throws android.os.RemoteException;  
  152. }  
      因为sub类实现了Binder接口,所以以后会使用这个类。

         2.实现service类
         

[html] view plaincopy
  1. public class RemoteService extends Service {  
  2.   
  3.     private LinkedList<Person> personList = new LinkedList<Person>();  
  4.       
  5.     @Override  
  6.     public IBinder onBind(Intent intent) {  
  7.             return mBinder;  
  8.     }  
  9.   
  10.     private final IMyService.Stub mBinder = new IMyService.Stub(){  
  11.   
  12.             @Override  
  13.             public void savePersonInfo(Person person) throws RemoteException {  
  14.                     if (person != null){  
  15.                             personList.add(person);  
  16.                     }  
  17.             }  
  18.   
  19.             @Override  
  20.             public List<Person> getAllPerson() throws RemoteException {  
  21.                     return personList;  
  22.             }  
  23.   
  24.             @Override  
  25.             public String sayHello() throws RemoteException {  
  26.                 // TODO Auto-generated method stub  
  27.                 return "欢迎你通过AIDL访问服务器端";  
  28.             }  
  29.     };  
  30. }  

         3.客户端实现步骤:

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

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

         然后构造客户端的activity类:

       

[html] view plaincopy
  1. public class RemoteClientActivity extends Activity {  
  2.     /** Called when the activity is first created. */  
  3.     private TextView textHello,textPerson;  
  4.     private IMyService myService;  
  5.     private Button btnSave;  
  6.     private Button btnGet;  
  7.     private static Boolean mIsRemoteBound=false;  
  8.     private ServiceConnection conn=new ServiceConnection() {  
  9.           
  10.         @Override  
  11.         public void onServiceDisconnected(ComponentName name) {  
  12.             // TODO Auto-generated method stub  
  13.             myService=null;  
  14.         }  
  15.           
  16.         @Override  
  17.         public void onServiceConnected(ComponentName name, IBinder service) {  
  18.             // TODO Auto-generated method stub  
  19.                 myService=IMyService.Stub.asInterface(service);       
  20.             try {  
  21.                 textHello.setText(myService.sayHello());  
  22.             } catch (RemoteException e) {  
  23.                 // TODO Auto-generated catch block  
  24.                 e.printStackTrace();  
  25.             }  
  26.         }  
  27.     };  
  28.     @Override  
  29.     public void onCreate(Bundle savedInstanceState) {  
  30.         super.onCreate(savedInstanceState);  
  31.         setContentView(R.layout.main);  
  32.           
  33.         textHello=(TextView) this.findViewById(R.id.textHello);  
  34.         btnSave=(Button) this.findViewById(R.id.btnSave);  
  35.         btnGet=(Button) this.findViewById(R.id.btnGet);  
  36.         textPerson=(TextView) this.findViewById(R.id.textPerson);  
  37.         if(mIsRemoteBound){  
  38.             unbindService(conn);  
  39.         }else{  
  40.         Intent intent=new Intent("cn.com.karl.aidl.RemoteService");  
  41.         bindService(intent, conn, BIND_AUTO_CREATE);  
  42.         }  
  43.         mIsRemoteBound = !mIsRemoteBound;  
  44.         btnSave.setOnClickListener(new OnClickListener() {  
  45.               private int index = 0;  
  46.   
  47.             @Override  
  48.             public void onClick(View v) {  
  49.                 // TODO Auto-generated method stub  
  50.                    Person person = new Person();  
  51.                    index = index + 1;  
  52.                    person.setName("Person" + index);  
  53.                    person.setAge(20);  
  54.                    person.setTelNumber("123456");   
  55.                    try {  
  56.                        myService.savePersonInfo(person);  
  57.                    } catch (RemoteException e) {  
  58.                            e.printStackTrace();  
  59.                    }   
  60.             }  
  61.         });  
  62.         btnGet.setOnClickListener(new OnClickListener() {  
  63.               
  64.             @Override  
  65.             public void onClick(View v) {  
  66.                 // TODO Auto-generated method stub  
  67.                   List<Person> list = null;   
  68.   
  69.                   try {  
  70.                           list = myService.getAllPerson();  
  71.                   } catch (RemoteException e) {  
  72.                           e.printStackTrace();  
  73.                   }   
  74.   
  75.                   if (list != null){  
  76.                           StringBuilder text = new StringBuilder();  
  77.   
  78.                           for(Person person : list){  
  79.                                   text.append("\n联系人:");  
  80.                                   text.append(person.getName());  
  81.                                   text.append("\n             年龄:");  
  82.                                   text.append(person.getAge());  
  83.                                   text.append("\n 电话:");  
  84.                                   text.append(person.getTelNumber());  
  85.                           }  
  86.   
  87.                           textPerson.setText(text);  
  88.                   }else {  
  89.                           Toast.makeText(RemoteClientActivity.this, "得到数据出错",  
  90.                                           Toast.LENGTH_SHORT).show();  
  91.                   }   
  92.             }  
  93.         });  
  94.     }  
  95. }  

              最后不要忘记注册service:

           

[html] view plaincopy
  1. <application  
  2.       android:icon="@drawable/ic_launcher"  
  3.       android:label="@string/app_name" >  
  4.       <activity android:name=".MainActivity">  
  5.           <intent-filter>  
  6.               <action android:name="android.intent.action.MAIN" />  
  7.   
  8.               <category android:name="android.intent.category.LAUNCHER" />  
  9.           </intent-filter>  
  10.       </activity>  
  11.       <service android:name=".RemoteService">  
  12.           <intent-filter >  
  13.               <action android:name="cn.com.karl.aidl.RemoteService"></action>  
  14.           </intent-filter>  
  15.       </service>  
  16.   </application>  

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

          运行服务端工程.

         

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

         

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

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

           


0 0