在网上看到一篇介绍AIDL的文章,自己把代码在2.2的sdk上跑了一下,稍微更改了一下原文中的代码(下文中的代码都是自己编译通过后使用的代码)并且添加了xml文件,大家可以按照这个代码自己实现一遍。

以下部门来自网上其他朋友的文章(由于出处太多,无法找到原始的地址)

================================================================

Android,每个应用程序都可以有自己的进程.在写UI应用的时候,经常要用到Service.在不同的进程中,怎样传递对象呢?显然, Java中不允许跨进程内存共享.因此传递对象,只能把对象拆分成操作系统能理解的简单形式,以达到跨界对象访问的目的.J2EE,采用RMI的方式,可以通过序列化传递对象.Android,则采用AIDL的方式.理论上AIDL可以传递Bundle,实际上做起来却比较麻烦.

AIDL(AndRoid接口描述语言)是一种借口描述语言;编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程的目的.如果需要在一个Activity,访问另一个Service中的某个对象,需要先将对象转化成AIDL可识别的参数(可能是多个参数),然后使用AIDL来传递这些参数,在消息的接收端,使用这些参数组装成自己需要的对象.

AIDLIPC的机制和COMCORBA类似,是基于接口的,但它是轻量级的。它使用代理类在客户端和实现层间传递值.如果要使用AIDL,需要完成2件事情: 1.引入AIDL的相关类.; 2.调用aidl产生的class.

具体实现步骤如下:

1、创建AIDL文件,在这个文件里面定义接口,该接口定义了可供客户端访问的方法和属性。

: ITaskBinder.adil

        
  1. packagecom.android.aidltest;
  2. importcom.android.aidltest.ITaskCallback;
  3. interfaceITaskBinder{
  4. booleanisTaskRunning();
  5. voidstopRunningTask();
  6. voidregisterCallback(ITaskCallbackcb);
  7. voidunregisterCallback(ITaskCallbackcb);
  8. }


其中: ITaskCallback在文件ITaskCallback.aidl中定义:

        
  1. packagecom.android.aidltest;
  2. interfaceITaskCallback{
  3. voidactionPerformed(intactionId);
  4. }

注意:理论上,参数可以传递基本数据类型和String,还有就是Bundle的派生类,不过在Eclipse,目前的ADT不支持Bundle做为参数,据说用Ant编译可以,我没做尝试.

2、编译AIDL文件,Ant的话,可能需要手动,使用Eclipse plugin的话,可以根据adil文件自动生产java文件并编译,不需要人为介入.

3、在Java文件中,实现AIDL中定义的接口.编译器会根据AIDL接口,产生一个JAVA接口。这个接口有一个名为Stub的内部抽象类,它继承扩展了接口并实现了远程调用需要的几个方法。接下来就需要自己去实现自定义的几个接口了.

ITaskBinder.aidl中接口的实现,MyService.java中接口以内嵌类的方式实现:

        
  1. privatefinalITaskBinder.StubmBinder=newITaskBinder.Stub(){
  2. @Override
  3. publicvoidunregisterCallback(ITaskCallbackcb)throwsRemoteException{
  4. printf("serviceonunregisterCallback");
  5. //TODOAuto-generatedmethodstub
  6. if(cb!=null)
  7. mCallbacks.unregister(cb);
  8. }
  9. @Override
  10. publicvoidstopRunningTask()throwsRemoteException{
  11. printf("serviceonstopRunningTask");
  12. //TODOAuto-generatedmethodstub
  13. }
  14. @Override
  15. publicvoidregisterCallback(ITaskCallbackcb)throwsRemoteException{
  16. printf("serviceonregisterCallback");
  17. //TODOAuto-generatedmethodstub
  18. if(cb!=null)
  19. mCallbacks.register(cb);
  20. }
  21. @Override
  22. publicbooleanisTaskRunning()throwsRemoteException{
  23. printf("serviceonisTaskRunning");
  24. //TODOAuto-generatedmethodstub
  25. returnfalse;
  26. }
  27. };

aidltest.javaITaskCallback.aidl接口实现:

        
  1. privateITaskCallbackmCallback=newITaskCallback.Stub(){
  2. @Override
  3. publicvoidactionPerformed(intactionId)throwsRemoteException{
  4. //TODOAuto-generatedmethodstub
  5. printf("callbackid="+actionId);
  6. }
  7. };

4、向客户端提供接口ITaskBinder,如果写的是service,扩展该Service并重载onBind ()方法来返回一个实现上述接口的类的实例。这个地方返回的mBinder,就是上面通过内嵌了定义的那个. (MyService.java)

        
  1. publicIBinderonBind(Intentt){

  2. printf("serviceonbind");

  3. returnmBinder;

Activity,可以通过Binder定义的接口,来进行远程调用.

5、在服务器端回调客户端的函数.前提是当客户端获取的IBinder接口的时候,要去注册回调函数,只有这样,服务器端才知道该调用那些函数在:MyService.java:

        
  1. voidcallback(intval){
  2. finalintN=mCallbacks.beginBroadcast();
  3. for(inti=0;i<N;i++){
  4. try{
  5. mCallbacks.getBroadcastItem(i).actionPerformed(val);
  6. }catch(RemoteExceptione){
  7. }
  8. }
  9. mCallbacks.finishBroadcast();
  10. }

AIDL的创建方法:

AIDL语法很简单,可以用来声明一个带一个或多个方法的接口,也可以传递参数和返回值。 由于远程调用的需要,这些参数和返回值并不是任何类型.下面是些AIDL支持的数据类型:

1.不需要import声明的简单Java编程语言类型(int,boolean)

2. String, CharSequence不需要特殊声明

3. List, MapParcelables类型, 这些类型内所包含的数据成员也只能是简单数据类型, String等其他比支持的类型.

(另外: 我没尝试Parcelables, Eclipse+ADT下编译不过, 或许以后会有所支持).


实现接口时有几个原则:

.抛出的异常不要返回给调用者. 跨进程抛异常处理是不可取的.

.IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity的主线程中调用。 也就是IPC调用会挂起应用程序导致界面失去响应. 这种情况应该考虑单起一个线程来处理.

.不能在AIDL接口中声明静态属性。

IPC
的调用步骤:

1. 声明一个接口类型的变量,该接口类型在.aidl文件中定义。

2. 实现ServiceConnection

3. 调用ApplicationContext.bindService(),并在ServiceConnection实现中进行传递.

4. ServiceConnection.onServiceConnected()实现中,你会接收一个IBinder实例(被调用的Service). 调用

YourInterfaceName.Stub.asInterface((IBinder)service)将参数转换为YourInterface类型。

5. 调用接口中定义的方法。 你总要检测到DeadObjectException异常,该异常在连接断开时被抛出。它只会被远程方法抛出。

6. 断开连接,调用接口实例中的ApplicationContext.unbindService()

下面是整个程序:

1.ITaskCallback.aidl

        
  1. packagecom.android.aidltest;
  2. interfaceITaskCallback{
  3. voidactionPerformed(intactionId);
  4. }

2. ITaskBinder.aidl

        
  1. packagecom.android.aidltest;
  2. importcom.android.aidltest.ITaskCallback;
  3. interfaceITaskBinder{
  4. booleanisTaskRunning();
  5. voidstopRunningTask();
  6. voidregisterCallback(ITaskCallbackcb);
  7. voidunregisterCallback(ITaskCallbackcb);
  8. }

3.MyService.java

        
  1. packagecom.android.aidltest;
  2. importandroid.app.Service;
  3. importandroid.content.Intent;
  4. importandroid.os.IBinder;
  5. importandroid.os.RemoteCallbackList;
  6. importandroid.os.RemoteException;
  7. importandroid.util.Log;
  8. publicclassMyServiceextendsService{
  9. publicvoidonCreate(){
  10. printf("servicecreate");
  11. }
  12. publicvoidonStart(Intentintent,intstartId){
  13. printf("servicestartid="+startId);
  14. callback(startId);
  15. }
  16. @Override
  17. publicIBinderonBind(Intentintent){
  18. //TODOAuto-generatedmethodstub
  19. printf("serviceonbind");
  20. returnmBinder;
  21. }
  22. publicvoidonDestroy(){
  23. printf("serviceondestroy");
  24. super.onDestroy();
  25. }
  26. publicbooleanonUnbind(Intentintent){
  27. printf("serviceonunbind");
  28. returnsuper.onUnbind(intent);
  29. }
  30. publicvoidonRebind(Intentintent){
  31. printf("serviceonrebind");
  32. super.onRebind(intent);
  33. }
  34. privatevoidprintf(Stringstr){
  35. Log.e("TAG","#######################---"+str+"-------");
  36. }
  37. voidcallback(intval){
  38. finalintN=mCallbacks.beginBroadcast();
  39. for(inti=0;i<N;i++){
  40. try{
  41. mCallbacks.getBroadcastItem(i).actionPerformed(val);
  42. }catch(RemoteExceptione){
  43. }
  44. }
  45. mCallbacks.finishBroadcast();
  46. }
  47. privatefinalITaskBinder.StubmBinder=newITaskBinder.Stub(){
  48. @Override
  49. publicvoidunregisterCallback(ITaskCallbackcb)throwsRemoteException{
  50. printf("serviceonunregisterCallback");
  51. //TODOAuto-generatedmethodstub
  52. if(cb!=null)
  53. mCallbacks.unregister(cb);
  54. }
  55. @Override
  56. publicvoidstopRunningTask()throwsRemoteException{
  57. printf("serviceonstopRunningTask");
  58. //TODOAuto-generatedmethodstub
  59. }
  60. @Override
  61. publicvoidregisterCallback(ITaskCallbackcb)throwsRemoteException{
  62. printf("serviceonregisterCallback");
  63. //TODOAuto-generatedmethodstub
  64. if(cb!=null)
  65. mCallbacks.register(cb);
  66. }
  67. @Override
  68. publicbooleanisTaskRunning()throwsRemoteException{
  69. printf("serviceonisTaskRunning");
  70. //TODOAuto-generatedmethodstub
  71. returnfalse;
  72. }
  73. };
  74. finalRemoteCallbackList<ITaskCallback>mCallbacks
  75. =newRemoteCallbackList<ITaskCallback>();
  76. }

4. aidltest.java

        
  1. packagecom.android.aidltest;
  2. importandroid.app.Activity;
  3. importandroid.content.ComponentName;
  4. importandroid.content.Context;
  5. importandroid.content.Intent;
  6. importandroid.content.ServiceConnection;
  7. importandroid.os.Bundle;
  8. importandroid.os.IBinder;
  9. importandroid.os.RemoteException;
  10. importandroid.util.Log;
  11. importandroid.view.View;
  12. importandroid.view.View.OnClickListener;
  13. importandroid.widget.Button;
  14. publicclassAidlTestextendsActivity{
  15. privateButtonbtnOk;
  16. privateButtonbtnCancel;
  17. /**Calledwhentheactivityisfirstcreated.*/
  18. @Override
  19. publicvoidonCreate(BundlesavedInstanceState){
  20. super.onCreate(savedInstanceState);
  21. setContentView(R.layout.main);
  22. btnOk=(Button)findViewById(R.id.btn_ok);
  23. btnCancel=(Button)findViewById(R.id.btn_cancel);
  24. btnOk.setText("StartService");
  25. btnCancel.setText("StopService");
  26. btnOk.setOnClickListener(newOnClickListener(){
  27. publicvoidonClick(Viewv){
  28. onOkClick();
  29. }
  30. });
  31. btnCancel.setOnClickListener(newOnClickListener(){
  32. publicvoidonClick(Viewv){
  33. onCancelClick();
  34. }
  35. });
  36. }
  37. voidonOkClick(){
  38. printf("clickedok");
  39. Bundleargs=newBundle();
  40. Intentintent=newIntent(this,MyService.class);
  41. intent.putExtras(args);
  42. bindService(intent,mConnection,Context.BIND_AUTO_CREATE);
  43. startService(intent);
  44. }
  45. voidonCancelClick(){
  46. printf("clickedcancel");
  47. Intentintent=newIntent(this,MyService.class);
  48. unbindService(mConnection);
  49. }
  50. privatevoidprintf(Stringstr){
  51. Log.e("TAG","##################-------"+str+"-----");
  52. }
  53. ITaskBindermService;
  54. privateServiceConnectionmConnection=newServiceConnection(){
  55. publicvoidonServiceConnected(ComponentNameclassName,
  56. IBinderservice){
  57. mService=ITaskBinder.Stub.asInterface(service);
  58. try{
  59. mService.registerCallback(mCallback);
  60. }catch(RemoteExceptione){
  61. }
  62. }
  63. publicvoidonServiceDisconnected(ComponentNameclassName){
  64. mService=null;
  65. }
  66. };
  67. privateITaskCallbackmCallback=newITaskCallback.Stub(){
  68. @Override
  69. publicvoidactionPerformed(intactionId)throwsRemoteException{
  70. //TODOAuto-generatedmethodstub
  71. printf("callbackid="+actionId);
  72. }
  73. };
  74. }

5. xml文件

AndroidMenifest.xml

        
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <manifestxmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.android.aidltest"
  4. android:versionCode="1"
  5. android:versionName="1.0">
  6. <applicationandroid:icon="@drawable/icon"android:label="@string/app_name">
  7. <activityandroid:name=".AidlTest"
  8. android:label="@string/app_name">
  9. <intent-filter>
  10. <actionandroid:name="android.intent.action.MAIN"/>
  11. <categoryandroid:name="android.intent.category.LAUNCHER"/>
  12. </intent-filter>
  13. </activity>
  14. <serviceandroid:name=".MyService">
  15. <intent-filter>
  16. <actionandroid:name="com.android.aidltest.START_MYSERVICE"/>
  17. <categoryandroid:name="android.intent.category.DEFAULT"/>
  18. </intent-filter>
  19. </service>
  20. </application>
  21. <uses-sdkandroid:minSdkVersion="8"/>
  22. </manifest>

main.xml

        
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent"
  6. >
  7. <TextView
  8. android:layout_width="fill_parent"
  9. android:layout_height="wrap_content"
  10. android:text="@string/hello"
  11. />
  12. <Button
  13. android:id="@+id/btn_ok"
  14. android:layout_width="wrap_content"
  15. android:layout_height="wrap_content"
  16. android:text="@string/btn_ok"
  17. />
  18. <Button
  19. android:id="@+id/btn_cancel"
  20. android:layout_width="wrap_content"
  21. android:layout_height="wrap_content"
  22. android:text="@string/btn_cancel"
  23. />
  24. </LinearLayout>

string.xml

        
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <resources>
  3. <stringname="hello">HelloWorld,AidlTest!</string>
  4. <stringname="app_name">AIDLTest</string>
  5. <stringname="btn_ok">OK</string>
  6. <stringname="btn_cancel">Cancel</string>
  7. </resources>

更多相关文章

  1. android目录结构介绍(寒假学习1)
  2. 百度地图开发-申请ak及相关配置
  3. 《Android(安卓)安全(一)》AndroidManifest.xml之allowBackup属性
  4. unity与android交互(1)
  5. [转]Android(安卓)xmlns 的作用及其自定义
  6. Android的ADT不能自动生成R.java
  7. Android资源文件Res详解——ShapeDrawable
  8. Android日记之2012\01\15
  9. 手动编译android项目

随机推荐

  1. 解决 “android New package not yet reg
  2. versionCode与versionName的区别、应用、
  3. 简单实现Android AudioReccord录音方式
  4. Android NullPointerException解决方法(空
  5. Android(安卓)BigNews 曾量更新
  6. [Unity3D]Android实现不锁屏
  7. [Android]调用字符串资源的几种方法
  8. 一个打通jni,java framework,application三
  9. Android Activity切换动画效果详解(附源代
  10. [Gradle for Android 笔记系列]二 、Pack