AIDL(AndroidinterfaceDefinitionLanguage)

AIDL:Android Interface Definition Language,即Android接口定义语言。

Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。 为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现。与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition Language,IDL)来公开服务的接口。我们知道4个Android应用程序组件中的3个(Activity、BroadcastReceiver和ContentProvider)都可以进行跨进程访问,另外一个Android应用程序组件Service同样可以。因此,可以将这种可以跨进程访问的服务称为AIDL(Android Interface Definition Language)服务。

建立AIDL服务的步骤

建立AIDL服务要比建立普通的服务复杂一些,具体步骤如下: (1)在Eclipse Android工程的Java包目录中建立一个扩展名为aidl的文件。该文件的语法类似于Java代码,但会稍有不同。 (2)如果aidl文件的内容是正确的,ADT会自动生成一个Java接口文件(*.java)。 (3)建立一个服务类(Service的子类)。 (4)实现由aidl文件生成的Java接口。 (5)在AndroidManifest.xml文件中配置AIDL服务,尤其要注意的是,<action>标签中android:name的属性值就是客户端要引用该服务的ID,也就是Intent类的参数值。

1.什么是aidl:aidl是 Android Interface definition language的缩写,一看就明白,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口
icp:interprocess communication :内部进程通信

2.既然aidl可以定义并实现进程通信,那么我们怎么使用它呢?文档/android-sdk/docs/guide/developing/tools/aidl.html中对步骤作了详细描述:

--1.Create your .aidl file - This file defines an interface (YourInterface.aidl) that defines the methods and fields available to a client.
创建你的aidl文件,我在后面给出了一个例子,它的aidl文件定义如下:写法跟java代码类似,但是这里有一点值得注意的就是它可以引用其它aidl文件中定义的接口,但是不能够引用你的java类文件中定义的接口

[java] view plaincopy
  1. packagecom.cao.android.demos.binder.aidl;
  2. importcom.cao.android.demos.binder.aidl.AIDLActivity;
  3. interfaceAIDLService{
  4. voidregisterTestCall(AIDLActivitycb);
  5. voidinvokCallBack();
  6. }

--2.Add the .aidl file to your makefile - (the ADT Plugin for Eclipse manages this for you). Android includes the compiler, called AIDL, in the tools/ directory.
编译你的aidl文件,这个只要是在eclipse中开发,你的adt插件会像资源文件一样把aidl文件编译成java代码生成在gen文件夹下,不用手动去编译:编译生成AIDLService.java如我例子中代码


--3.Implement your interface methods - The AIDL compiler creates an interface in the Java programming language from your AIDL interface. This interface has an inner abstract class named Stub that inherits the interface (and implements a few additional methods necessary for the IPC call). You must create a class that extends YourInterface.Stub and implements the methods you declared in your .aidl file.
实现你定义aidl接口中的内部抽象类Stub,public static abstract class Stub extends android.os.Binder implements com.cao.android.demos.binder.aidl.AIDLService
Stub类继承了Binder,并继承我们在aidl文件中定义的接口,我们需要实现接口方法,下面是我在例子中实现的Stub类:

[java] view plaincopy
  1. privatefinalAIDLService.StubmBinder=newAIDLService.Stub(){
  2. @Override
  3. publicvoidinvokCallBack()throwsRemoteException{
  4. Log("AIDLService.invokCallBack");
  5. Rect1rect=newRect1();
  6. rect.bottom=-1;
  7. rect.left=-1;
  8. rect.right=1;
  9. rect.top=1;
  10. callback.performAction(rect);
  11. }
  12. @Override
  13. publicvoidregisterTestCall(AIDLActivitycb)throwsRemoteException{
  14. Log("AIDLService.registerTestCall");
  15. callback=cb;
  16. }
  17. };

Stub翻译成中文是存根的意思,注意Stub对象是在被调用端进程,也就是服务端进程,至此,服务端aidl服务端得编码完成了。

--4.Expose your interface to clients - If you're writing a service, you should extend Service and override Service.onBind(Intent) to return an instance of your class that implements your interface.
第四步告诉你怎么在客户端如何调用服务端得aidl描述的接口对象,doc只告诉我们需要实现Service.onBind(Intent)方法,该方法会返回一个IBinder对象到客户端,绑定服务时不是需要一个ServiceConnection对象么,在没有了解aidl用法前一直不知道它是什么作用,其实他就是用来在客户端绑定service时接收service返回的IBinder对象的:

[java] view plaincopy
  1. AIDLServicemService;
  2. privateServiceConnectionmConnection=newServiceConnection(){
  3. publicvoidonServiceConnected(ComponentNameclassName,IBinderservice){
  4. Log("connectservice");
  5. mService=AIDLService.Stub.asInterface(service);
  6. try{
  7. mService.registerTestCall(mCallback);
  8. }catch(RemoteExceptione){
  9. }
  10. }
  11. publicvoidonServiceDisconnected(ComponentNameclassName){
  12. Log("disconnectservice");
  13. mService=null;
  14. }
  15. };

mService就是AIDLService对象,具体可以看我后面提供的示例代码,需要注意在客户端需要存一个服务端实现了的aidl接口描述文件,但是客户端只是使用该aidl接口,不需要实现它的Stub类,获取服务端得aidl对象后mService = AIDLService.Stub.asInterface(service);,就可以在客户端使用它了,对mService对象方法的调用不是在客户端执行,而是在服务端执行。

4.aidl中使用java类,需要实现Parcelable接口,并且在定义类相同包下面对类进行声明

上面我定义了Rect1类
之后你就可以在aidl接口中对该类进行使用了

package com.cao.android.demos.binder.aidl; import com.cao.android.demos.binder.aidl.Rect1;interface AIDLActivity {      void performAction(in Rect1 rect);  }


注意 in/out的说明,我这里使用了in表示输入参数,out没有试过,为什么使用in/out暂时没有做深入研究。

5.aidl使用完整示例,为了清除说明aidl使用,我这里写了一个例子,例子参考了博客:

http://blog.csdn.net/saintswordsman/archive/2010/01/04/5130947.aspx

作出说明

例子实现了一个AIDLTestActivity,AIDLTestActivity通过bindservice绑定一个服务AIDLTestService,通过并获取AIDLTestActivity的一个aidl对象AIDLService,该对象提供两个方法,一个是registerTestCall注册一个aidl对象,通过该方法,AIDLTestActivity把本身实现的一个aidl对象AIDLActivity传到AIDLTestService,在AIDLTestService通过操作AIDLActivity这个aidl远端对象代理,使AIDLTestActivity弹出一个toast,完整例子见我上传的资源:

http://download.csdn.net/source/3284820

文章仓促而成,有什么疑问欢迎大家一起讨论。

原帖子链接:

http://blog.csdn.net/stonecao/article/details/6425019



欢迎阅读本文,你能关注本文,你知道你需要进程间通信、需要AIDL(以及Binder),那么可以默认你对这些概念已经有了一些了解,你(大致)知道它们是什么,它们有什么用,所以为了节约大家的眼力和时间,在此我不复制粘贴网上泛滥的博客或者翻译冗长的android文档。

关于AIDL的介绍在文档:docs/guide/developing/tools/aidl.html

关于IBinder的介绍在文档:docs/reference/android/os/IBinder.html

以及Binder:docs/reference/android/os/Binder.html

在后文中,我将以我自己的理解向你介绍相关的概念。以我目前粗浅的经验,应用程序使用AIDL的地方,几乎都和Service有关,所以你也需要知道一些关于Service的知识。日后得闲我也会继续写一些关于Service的贴。

本文将以一个例子来和你分享使用AIDL的基础技能,这个例子里有:

1、一个类mAIDLActivity,继承Activity。里面有三个按钮,text分别为StartService,StopService,CallbackTest。

2、一个类mAIDLService,继承Service。为了充分展示ADIL的功能,它做以下工作:当用户点击CallbackTest按钮时,从mAIDLActivity调用mAIDLService中的Stub对象的一个方法invokCallBack(),而这个方法又会调用mAIDLActivity中Stub对象的一个方法performAction(),这个方法在屏幕上显示一个toast。没什么意义,只是展示一下AIDL如何使用。

3、两个AIDL文件:forService.aidl和forActivity.aidl。对应名字,在Service和Activity中分别有对象需要用到它们定义的接口。

4、相关XML文件,略过。关于manifest中Service的语法,见docs/guide/topics/manifest/service-element.html。你也可以简单地在<application></application>中加入

<service android:name=".mAIDLService" android:process=":remote"> </service>

开发环境为Eclipse。

拣重要的先说,来看看aidl文件的内容:

文件:forActivity.aidl

[java] view plain copy
  1. packagecom.styleflying.AIDL;
  2. interfaceforActivity{
  3. voidperformAction();
  4. }

文件:forService.aidl

[java] view plain copy
  1. packagecom.styleflying.AIDL;
  2. importcom.styleflying.AIDL.forActivity;
  3. interfaceforService{
  4. voidregisterTestCall(forActivitycb);
  5. voidinvokCallBack();
  6. }

这两个文件和Java文件放置的地方一样,看包名。

在Eclipse中它们将被自动编译为forActivity.java和forService.java,它们存放在gen目录下。为了方便手头无法演练的读者,代码贴上,不用细看。

文件forActivity.java:

[java] view plain copy
  1. /*
  2. *Thisfileisauto-generated.DONOTMODIFY.
  3. *Originalfile:D://workspace//AIDLTest//src//com//styleflying//AIDL//forActivity.aidl
  4. */
  5. packagecom.styleflying.AIDL;
  6. importjava.lang.String;
  7. importandroid.os.RemoteException;
  8. importandroid.os.IBinder;
  9. importandroid.os.IInterface;
  10. importandroid.os.Binder;
  11. importandroid.os.Parcel;
  12. publicinterfaceforActivityextendsandroid.os.IInterface
  13. {
  14. /**Local-sideIPCimplementationstubclass.*/
  15. publicstaticabstractclassStubextendsandroid.os.Binderimplementscom.styleflying.AIDL.forActivity
  16. {
  17. privatestaticfinaljava.lang.StringDESCRIPTOR="com.styleflying.AIDL.forActivity";
  18. /**Constructthestubatattachittotheinterface.*/
  19. publicStub()
  20. {
  21. this.attachInterface(this,DESCRIPTOR);
  22. }
  23. /**
  24. *CastanIBinderobjectintoanforActivityinterface,
  25. *generatingaproxyifneeded.
  26. */
  27. publicstaticcom.styleflying.AIDL.forActivityasInterface(android.os.IBinderobj)
  28. {
  29. if((obj==null)){
  30. returnnull;
  31. }
  32. android.os.IInterfaceiin=(android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
  33. if(((iin!=null)&&(iininstanceofcom.styleflying.AIDL.forActivity))){
  34. return((com.styleflying.AIDL.forActivity)iin);
  35. }
  36. returnnewcom.styleflying.AIDL.forActivity.Stub.Proxy(obj);
  37. }
  38. publicandroid.os.IBinderasBinder()
  39. {
  40. returnthis;
  41. }
  42. @OverridepublicbooleanonTransact(intcode,android.os.Parceldata,android.os.Parcelreply,intflags)throwsandroid.os.RemoteException
  43. {
  44. switch(code)
  45. {
  46. caseINTERFACE_TRANSACTION:
  47. {
  48. reply.writeString(DESCRIPTOR);
  49. returntrue;
  50. }
  51. caseTRANSACTION_performAction:
  52. {
  53. data.enforceInterface(DESCRIPTOR);
  54. this.performAction();
  55. reply.writeNoException();
  56. returntrue;
  57. }
  58. }
  59. returnsuper.onTransact(code,data,reply,flags);
  60. }
  61. privatestaticclassProxyimplementscom.styleflying.AIDL.forActivity
  62. {
  63. privateandroid.os.IBindermRemote;
  64. Proxy(android.os.IBinderremote)
  65. {
  66. mRemote=remote;
  67. }
  68. publicandroid.os.IBinderasBinder()
  69. {
  70. returnmRemote;
  71. }
  72. publicjava.lang.StringgetInterfaceDescriptor()
  73. {
  74. returnDESCRIPTOR;
  75. }
  76. publicvoidperformAction()throwsandroid.os.RemoteException
  77. {
  78. android.os.Parcel_data=android.os.Parcel.obtain();
  79. android.os.Parcel_reply=android.os.Parcel.obtain();
  80. try{
  81. _data.writeInterfaceToken(DESCRIPTOR);
  82. mRemote.transact(Stub.TRANSACTION_performAction,_data,_reply,0);
  83. _reply.readException();
  84. }
  85. finally{
  86. _reply.recycle();
  87. _data.recycle();
  88. }
  89. }
  90. }
  91. staticfinalintTRANSACTION_performAction=(IBinder.FIRST_CALL_TRANSACTION+0);
  92. }
  93. publicvoidperformAction()throwsandroid.os.RemoteException;
  94. }

文件forService.java:

[java] view plain copy
  1. /*
  2. *Thisfileisauto-generated.DONOTMODIFY.
  3. *Originalfile:D://workspace//AIDLTest//src//com//styleflying//AIDL//forService.aidl
  4. */
  5. packagecom.styleflying.AIDL;
  6. importjava.lang.String;
  7. importandroid.os.RemoteException;
  8. importandroid.os.IBinder;
  9. importandroid.os.IInterface;
  10. importandroid.os.Binder;
  11. importandroid.os.Parcel;
  12. publicinterfaceforServiceextendsandroid.os.IInterface
  13. {
  14. /**Local-sideIPCimplementationstubclass.*/
  15. publicstaticabstractclassStubextendsandroid.os.Binderimplementscom.styleflying.AIDL.forService
  16. {
  17. privatestaticfinaljava.lang.StringDESCRIPTOR="com.styleflying.AIDL.forService";
  18. /**Constructthestubatattachittotheinterface.*/
  19. publicStub()
  20. {
  21. this.attachInterface(this,DESCRIPTOR);
  22. }
  23. /**
  24. *CastanIBinderobjectintoanforServiceinterface,
  25. *generatingaproxyifneeded.
  26. */
  27. publicstaticcom.styleflying.AIDL.forServiceasInterface(android.os.IBinderobj)
  28. {
  29. if((obj==null)){
  30. returnnull;
  31. }
  32. android.os.IInterfaceiin=(android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
  33. if(((iin!=null)&&(iininstanceofcom.styleflying.AIDL.forService))){
  34. return((com.styleflying.AIDL.forService)iin);
  35. }
  36. returnnewcom.styleflying.AIDL.forService.Stub.Proxy(obj);
  37. }
  38. publicandroid.os.IBinderasBinder()
  39. {
  40. returnthis;
  41. }
  42. @OverridepublicbooleanonTransact(intcode,android.os.Parceldata,android.os.Parcelreply,intflags)throwsandroid.os.RemoteException
  43. {
  44. switch(code)
  45. {
  46. caseINTERFACE_TRANSACTION:
  47. {
  48. reply.writeString(DESCRIPTOR);
  49. returntrue;
  50. }
  51. caseTRANSACTION_registerTestCall:
  52. {
  53. data.enforceInterface(DESCRIPTOR);
  54. com.styleflying.AIDL.forActivity_arg0;
  55. _arg0=com.styleflying.AIDL.forActivity.Stub.asInterface(data.readStrongBinder());
  56. this.registerTestCall(_arg0);
  57. reply.writeNoException();
  58. returntrue;
  59. }
  60. caseTRANSACTION_invokCallBack:
  61. {
  62. data.enforceInterface(DESCRIPTOR);
  63. this.invokCallBack();
  64. reply.writeNoException();
  65. returntrue;
  66. }
  67. }
  68. returnsuper.onTransact(code,data,reply,flags);
  69. }
  70. privatestaticclassProxyimplementscom.styleflying.AIDL.forService
  71. {
  72. privateandroid.os.IBindermRemote;
  73. Proxy(android.os.IBinderremote)
  74. {
  75. mRemote=remote;
  76. }
  77. publicandroid.os.IBinderasBinder()
  78. {
  79. returnmRemote;
  80. }
  81. publicjava.lang.StringgetInterfaceDescriptor()
  82. {
  83. returnDESCRIPTOR;
  84. }
  85. publicvoidregisterTestCall(com.styleflying.AIDL.forActivitycb)throwsandroid.os.RemoteException
  86. {
  87. android.os.Parcel_data=android.os.Parcel.obtain();
  88. android.os.Parcel_reply=android.os.Parcel.obtain();
  89. try{
  90. _data.writeInterfaceToken(DESCRIPTOR);
  91. _data.writeStrongBinder((((cb!=null))?(cb.asBinder()):(null)));
  92. mRemote.transact(Stub.TRANSACTION_registerTestCall,_data,_reply,0);
  93. _reply.readException();
  94. }
  95. finally{
  96. _reply.recycle();
  97. _data.recycle();
  98. }
  99. }
  100. publicvoidinvokCallBack()throwsandroid.os.RemoteException
  101. {
  102. android.os.Parcel_data=android.os.Parcel.obtain();
  103. android.os.Parcel_reply=android.os.Parcel.obtain();
  104. try{
  105. _data.writeInterfaceToken(DESCRIPTOR);
  106. mRemote.transact(Stub.TRANSACTION_invokCallBack,_data,_reply,0);
  107. _reply.readException();
  108. }
  109. finally{
  110. _reply.recycle();
  111. _data.recycle();
  112. }
  113. }
  114. }
  115. staticfinalintTRANSACTION_registerTestCall=(IBinder.FIRST_CALL_TRANSACTION+0);
  116. staticfinalintTRANSACTION_invokCallBack=(IBinder.FIRST_CALL_TRANSACTION+1);
  117. }
  118. publicvoidregisterTestCall(com.styleflying.AIDL.forActivitycb)throwsandroid.os.RemoteException;
  119. publicvoidinvokCallBack()throwsandroid.os.RemoteException;
  120. }

两段代码差不多,前面基本一样,从后面看,最后跟着我们在AIDL中自定义的方法,没有实现。两个文件各定义一个了接口,这两个接口分别会在Activity和Service中使用,在那里我们将实现自定义的方法。两个接口中都定义了一个抽象类Stub,实现所在的接口。Stub中又有一个类Proxy。Stub中有一个static的asInterface()方法,里面有很多return语句,在mAIDLActivity中调用它时,它返回一个新创建的内部类Proxy对象。

这个Stub对我们来说很有用,它继承了Binder。Binder有什么用呢?一个类,继承了Binder,那么它的对象就可以被远程的进程使用了(前提是远程进程获取了这个类的对象【对象的引用】,至于如如何获得看下文),在本例中就是说,如果一个Service中有一个继承了Stub的类的对象,那么这个对象中的方法就可以在Activity中使用,对Activity也是这样。至于Binder的细节,网上有很多贴介绍,看不明白也不影响我们完成这个例子。

再看mAIDLActivity.java:

[java] view plain copy
  1. packagecom.styleflying.AIDL;
  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. importandroid.widget.Toast;
  15. publicclassmAIDLActivityextendsActivity{
  16. privatestaticfinalStringTAG="AIDLActivity";
  17. privateButtonbtnOk;
  18. privateButtonbtnCancel;
  19. privateButtonbtnCallBack;
  20. privatevoidLog(Stringstr){
  21. Log.d(TAG,"------"+str+"------");
  22. }
  23. privateforActivitymCallback=newforActivity.Stub(){
  24. publicvoidperformAction()throwsRemoteException
  25. {
  26. Toast.makeText(mAIDLActivity.this,"thistoastiscalledfromservice",1).show();
  27. }
  28. };
  29. forServicemService;
  30. privateServiceConnectionmConnection=newServiceConnection(){
  31. publicvoidonServiceConnected(ComponentNameclassName,
  32. IBinderservice){
  33. mService=forService.Stub.asInterface(service);
  34. try{
  35. mService.registerTestCall(mCallback);}
  36. catch(RemoteExceptione){
  37. }
  38. }
  39. publicvoidonServiceDisconnected(ComponentNameclassName){
  40. Log("disconnectservice");
  41. mService=null;
  42. }
  43. };
  44. @Override
  45. publicvoidonCreate(Bundleicicle){
  46. super.onCreate(icicle);
  47. setContentView(R.layout.main);
  48. btnOk=(Button)findViewById(R.id.btn_ok);
  49. btnCancel=(Button)findViewById(R.id.btn_cancel);
  50. btnCallBack=(Button)findViewById(R.id.btn_callback);
  51. btnOk.setOnClickListener(newOnClickListener(){
  52. publicvoidonClick(Viewv){
  53. Bundleargs=newBundle();
  54. Intentintent=newIntent(mAIDLActivity.this,mAIDLService.class);
  55. intent.putExtras(args);
  56. bindService(intent,mConnection,Context.BIND_AUTO_CREATE);
  57. startService(intent);
  58. }
  59. });
  60. btnCancel.setOnClickListener(newOnClickListener(){
  61. publicvoidonClick(Viewv){
  62. unbindService(mConnection);
  63. //stopService(intent);
  64. }
  65. });
  66. btnCallBack.setOnClickListener(newOnClickListener(){
  67. @Override
  68. publicvoidonClick(Viewv)
  69. {
  70. try
  71. {
  72. mService.invokCallBack();
  73. }catch(RemoteExceptione)
  74. {
  75. //TODOAuto-generatedcatchblock
  76. e.printStackTrace();
  77. }
  78. }
  79. });
  80. }
  81. }

很短,相信大家很容易看明白。注意mConnection,它的onServiceConnected()中有一句mService = forService.Stub.asInterface(service);给mService赋值了,这个mService是一个forService,而service是onServiceConnected()传进来的参数,onServiceConnected()会在连接Service的时候被系统调用,这个service参数的值来自哪里呢?看mAIDLService.java:

[java] view plain copy
  1. packagecom.styleflying.AIDL;
  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. publicclassmAIDLServiceextendsService{
  9. privatestaticfinalStringTAG="AIDLService";
  10. privateforActivitycallback;
  11. privatevoidLog(Stringstr){
  12. Log.d(TAG,"------"+str+"------");
  13. }
  14. @Override
  15. publicvoidonCreate(){
  16. Log("servicecreate");
  17. }
  18. @Override
  19. publicvoidonStart(Intentintent,intstartId){
  20. Log("servicestartid="+startId);
  21. }
  22. @Override
  23. publicIBinderonBind(Intentt){
  24. Log("serviceonbind");
  25. returnmBinder;
  26. }
  27. @Override
  28. publicvoidonDestroy(){
  29. Log("serviceondestroy");
  30. super.onDestroy();
  31. }
  32. @Override
  33. publicbooleanonUnbind(Intentintent){
  34. Log("serviceonunbind");
  35. returnsuper.onUnbind(intent);
  36. }
  37. publicvoidonRebind(Intentintent){
  38. Log("serviceonrebind");
  39. super.onRebind(intent);
  40. }
  41. privatefinalforService.StubmBinder=newforService.Stub(){
  42. @Override
  43. publicvoidinvokCallBack()throwsRemoteException
  44. {
  45. callback.performAction();
  46. }
  47. @Override
  48. publicvoidregisterTestCall(forActivitycb)throwsRemoteException
  49. {
  50. callback=cb;
  51. }
  52. };
  53. }

注意onBind(),它的返回类型为IBinder,返回了一个mBinder,看看mBinder的定义:

private final forService.Stub mBinder = new forService.Stub() {

@Override
public void invokCallBack() throws RemoteException
{
callback.performAction();
}

@Override
public void registerTestCall(forActivity cb) throws RemoteException
{
callback = cb;

}

};

它是实现了我们在AIDL中定义的方法,这个mBinder最终返回给了mAIDLActivity中的mService,于是在mAIDLActivity中可以使用mBinder中的方法了。在mAIDLActivity中也有一个类似mBinder的对象,看看定义:

private forActivity mCallback = new forActivity.Stub()

{
public void performAction() throws RemoteException
{
Toast.makeText(mAIDLActivity.this, "this toast is called from service", 1).show();
}
};

我们要在界面上显示一个toast,就是在这里实现的。这个对象,在mConnection的onServiceConnected()被调用时,通过调用mService(也就是远程的mAIDLService中的mBinder)的registerTestCall(),传递给了mAIDLService,于是在mAIDLService中可以调用performAction()了。

很啰嗦,只为了能把这个细节说清楚。请大家认真看,我尽量避免错别字、混乱的大小写和逻辑不清的语法,相信你会看明白。是不是很简单?再啰嗦一下,做一个大致总结,我们使用AIDL是要做什么呢:

让Acticity(或者说一个进程/一个类?)和Service(或者说远端进程/远端类/对象?)获取对方的一个Stub对象,这个对象在定义时实现了我们在AIDL中定义的方法,于是这些远程对象中的方法可以在本地使用了。如果这种使用(通信)是单向的,比如只是Activity需要通知Service做什么,那么只要Service中有一个Stub对象,并且传给Acticity就够了。

至于如何获得远程的Stub,参看上面的代码,看mConnection、registerTestCall、onRebind,它们展示了一种方法。

另外,有时候我们可能在一个类中有多个Stub对象,它们都要给远程交互的类的实例,这个时候可以考虑使用RemoteCallbackList<>(docs/reference/android/os/RemoteCallbackList.html)。


更多相关文章

  1. Android(安卓)O指纹识别解析
  2. Android(安卓)Studio主要目录及文件简介
  3. android中处理json最佳方法
  4. Android(安卓)如何判断CPU是32位还是64位
  5. Android(安卓)Gradle插件入门
  6. 使用android MediaPlayer播放音频文件时,有时会出现prepareasync
  7. Android(安卓)AIDL使用详解
  8. 类和 Json对象
  9. NPM 和webpack 的基础使用

随机推荐

  1. android实现ios形式的字体,实现各种自定义
  2. Android的消息机制,用Android线程间通信的
  3. Android(安卓)2020年最新保活方案 保活90
  4. 论“Android”在未来十年的发展
  5. Android学习建议
  6. [Android(安卓)Studio] Android(安卓)Stu
  7. 《Android/OPhone 开发完全讲义》样章和
  8. Android(安卓)React Native的使用细节问
  9. Android(安卓)驱动之旅 第四章:在Android(
  10. 做自己的Android(安卓)ROM,屏蔽对framewor