zoukankan      html  css  js  c++  java
  • (转)android进程间通信:使用AIDL

    欢迎阅读本文,你能关注本文,你知道你需要进程间通信、需要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

    1. package  com.styleflying.AIDL;  
    2. interface  ITaskCallback {  
    3.     void  performAction();   

    package com.styleflying.AIDL; interface ITaskCallback { void performAction(); 

    文件:forService.aidl

    1. package  com.styleflying.AIDL;  
    2. import  com.styleflying.AIDL.forActivity;  
    3. interface  ITaskBinder {  
    4.     void  registerTestCall(ITaskCallback tc);  
    5.     void  invokCallBack();  
    6. }  

    package com.styleflying.AIDL; import com.styleflying.AIDL.forActivity; interface ITaskBinder { void registerTestCall(ITaskCallback tc); void invokCallBack(); }

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

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

    文件forActivity.java:

    1. /*  
    2.  * This file is auto-generated.  DO NOT MODIFY.  
    3.  * Original file: D:\\workspace\\AIDLTest\\src\\com\\styleflying\\AIDL\\forActivity.aidl  
    4.  */   
    5. package  com.styleflying.AIDL;  
    6. import  java.lang.String;  
    7. import  android.os.RemoteException;  
    8. import  android.os.IBinder;  
    9. import  android.os.IInterface;  
    10. import  android.os.Binder;  
    11. import  android.os.Parcel;  
    12. public   interface  forActivity  extends  android.os.IInterface  
    13. {  
    14. /** Local-side IPC implementation stub class. */   
    15. public   static   abstract   class  Stub  extends  android.os.Binder  implements com.styleflying.AIDL.forActivity  
    16. {  
    17. private   static   final  java.lang.String DESCRIPTOR =  "com.styleflying.AIDL.forActivity" ;  
    18. /** Construct the stub at attach it to the interface. */   
    19. public  Stub()  
    20. {  
    21. this .attachInterface( this , DESCRIPTOR);  
    22. }  
    23. /**  
    24.  * Cast an IBinder object into an forActivity interface,  
    25.  * generating a proxy if needed.  
    26.  */   
    27. public   static  com.styleflying.AIDL.forActivity asInterface(android.os.IBinder obj)  
    28. {  
    29. if  ((obj== null )) {  
    30. return   null ;  
    31. }  
    32. android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);  
    33. if  (((iin!= null )&&(iin  instanceof  com.styleflying.AIDL.forActivity))) {  
    34. return  ((com.styleflying.AIDL.forActivity)iin);  
    35. }  
    36. return   new  com.styleflying.AIDL.forActivity.Stub.Proxy(obj);  
    37. }  
    38. public  android.os.IBinder asBinder()  
    39. {  
    40. return   this ;  
    41. }  
    42. @Override   public   boolean  onTransact( int  code, android.os.Parcel data, android.os.Parcel reply,  int flags)  throws  android.os.RemoteException  
    43. {  
    44. switch  (code)  
    45. {  
    46. case  INTERFACE_TRANSACTION:  
    47. {  
    48. reply.writeString(DESCRIPTOR);  
    49. return   true ;  
    50. }  
    51. case  TRANSACTION_performAction:  
    52. {  
    53. data.enforceInterface(DESCRIPTOR);  
    54. this .performAction();  
    55. reply.writeNoException();  
    56. return   true ;  
    57. }  
    58. }  
    59. return   super .onTransact(code, data, reply, flags);  
    60. }  
    61. private   static   class  Proxy  implements  com.styleflying.AIDL.forActivity  
    62. {  
    63. private  android.os.IBinder mRemote;  
    64. Proxy(android.os.IBinder remote)  
    65. {  
    66. mRemote = remote;  
    67. }  
    68. public  android.os.IBinder asBinder()  
    69. {  
    70. return  mRemote;  
    71. }  
    72. public  java.lang.String getInterfaceDescriptor()  
    73. {  
    74. return  DESCRIPTOR;  
    75. }  
    76. public   void  performAction()  throws  android.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. static   final   int  TRANSACTION_performAction = (IBinder.FIRST_CALL_TRANSACTION +  0 );  
    92. }  
    93. public   void  performAction()  throws  android.os.RemoteException;  
    94. }  

    /* * This file is auto-generated. DO NOT MODIFY. * Original file: D:\\workspace\\AIDLTest\\src\\com\\styleflying\\AIDL\\forActivity.aidl */ package com.styleflying.AIDL; import java.lang.String; import android.os.RemoteException; import android.os.IBinder; import android.os.IInterface; import android.os.Binder; import android.os.Parcel; public interface forActivity extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.styleflying.AIDL.forActivity { private static final java.lang.String DESCRIPTOR = "com.styleflying.AIDL.forActivity"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an forActivity interface, * generating a proxy if needed. */ public static com.styleflying.AIDL.forActivity 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 com.styleflying.AIDL.forActivity))) { return ((com.styleflying.AIDL.forActivity)iin); } return new com.styleflying.AIDL.forActivity.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_performAction: { data.enforceInterface(DESCRIPTOR); this.performAction(); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.styleflying.AIDL.forActivity { 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 performAction() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_performAction, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } } static final int TRANSACTION_performAction = (IBinder.FIRST_CALL_TRANSACTION + 0); } public void performAction() throws android.os.RemoteException; }

    文件forService.java:

    ·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
    1. /*  
    2.  * This file is auto-generated.  DO NOT MODIFY.  
    3.  * Original file: D:\\workspace\\AIDLTest\\src\\com\\styleflying\\AIDL\\forService.aidl  
    4.  */   
    5. package  com.styleflying.AIDL;  
    6. import  java.lang.String;  
    7. import  android.os.RemoteException;  
    8. import  android.os.IBinder;  
    9. import  android.os.IInterface;  
    10. import  android.os.Binder;  
    11. import  android.os.Parcel;  
    12. public   interface  forService  extends  android.os.IInterface  
    13. {  
    14. /** Local-side IPC implementation stub class. */   
    15. public   static   abstract   class  Stub  extends  android.os.Binder  implements com.styleflying.AIDL.forService  
    16. {  
    17. private   static   final  java.lang.String DESCRIPTOR =  "com.styleflying.AIDL.forService" ;  
    18. /** Construct the stub at attach it to the interface. */   
    19. public  Stub()  
    20. {  
    21. this .attachInterface( this , DESCRIPTOR);  
    22. }  
    23. /**  
    24.  * Cast an IBinder object into an forService interface,  
    25.  * generating a proxy if needed.  
    26.  */   
    27. public   static  com.styleflying.AIDL.forService asInterface(android.os.IBinder obj)  
    28. {  
    29. if  ((obj== null )) {  
    30. return   null ;  
    31. }  
    32. android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);  
    33. if  (((iin!= null )&&(iin  instanceof  com.styleflying.AIDL.forService))) {  
    34. return  ((com.styleflying.AIDL.forService)iin);  
    35. }  
    36. return   new  com.styleflying.AIDL.forService.Stub.Proxy(obj);  
    37. }  
    38. public  android.os.IBinder asBinder()  
    39. {  
    40. return   this ;  
    41. }  
    42. @Override   public   boolean  onTransact( int  code, android.os.Parcel data, android.os.Parcel reply,  int flags)  throws  android.os.RemoteException  
    43. {  
    44. switch  (code)  
    45. {  
    46. case  INTERFACE_TRANSACTION:  
    47. {  
    48. reply.writeString(DESCRIPTOR);  
    49. return   true ;  
    50. }  
    51. case  TRANSACTION_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. return   true ;  
    59. }  
    60. case  TRANSACTION_invokCallBack:  
    61. {  
    62. data.enforceInterface(DESCRIPTOR);  
    63. this .invokCallBack();  
    64. reply.writeNoException();  
    65. return   true ;  
    66. }  
    67. }  
    68. return   super .onTransact(code, data, reply, flags);  
    69. }  
    70. private   static   class  Proxy  implements  com.styleflying.AIDL.forService  
    71. {  
    72. private  android.os.IBinder mRemote;  
    73. Proxy(android.os.IBinder remote)  
    74. {  
    75. mRemote = remote;  
    76. }  
    77. public  android.os.IBinder asBinder()  
    78. {  
    79. return  mRemote;  
    80. }  
    81. public  java.lang.String getInterfaceDescriptor()  
    82. {  
    83. return  DESCRIPTOR;  
    84. }  
    85. public   void  registerTestCall(com.styleflying.AIDL.forActivity cb)  throws  android.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. public   void  invokCallBack()  throws  android.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. static   final   int  TRANSACTION_registerTestCall = (IBinder.FIRST_CALL_TRANSACTION +  0 );  
    116. static   final   int  TRANSACTION_invokCallBack = (IBinder.FIRST_CALL_TRANSACTION +  1 );  
    117. }  
    118. public   void  registerTestCall(com.styleflying.AIDL.forActivity cb)  throws  android.os.RemoteException;  
    119. public   void  invokCallBack()  throws  android.os.RemoteException;  
    120. }  

    /* * This file is auto-generated. DO NOT MODIFY. * Original file: D:\\workspace\\AIDLTest\\src\\com\\styleflying\\AIDL\\forService.aidl */ package com.styleflying.AIDL; import java.lang.String; import android.os.RemoteException; import android.os.IBinder; import android.os.IInterface; import android.os.Binder; import android.os.Parcel; public interface forService extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.styleflying.AIDL.forService { private static final java.lang.String DESCRIPTOR = "com.styleflying.AIDL.forService"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an forService interface, * generating a proxy if needed. */ public static com.styleflying.AIDL.forService 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 com.styleflying.AIDL.forService))) { return ((com.styleflying.AIDL.forService)iin); } return new com.styleflying.AIDL.forService.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_registerTestCall: { data.enforceInterface(DESCRIPTOR); com.styleflying.AIDL.forActivity _arg0; _arg0 = com.styleflying.AIDL.forActivity.Stub.asInterface(data.readStrongBinder()); this.registerTestCall(_arg0); reply.writeNoException(); return true; } case TRANSACTION_invokCallBack: { data.enforceInterface(DESCRIPTOR); this.invokCallBack(); reply.writeNoException(); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.styleflying.AIDL.forService { 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 registerTestCall(com.styleflying.AIDL.forActivity cb) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeStrongBinder((((cb!=null))?(cb.asBinder()):(null))); mRemote.transact(Stub.TRANSACTION_registerTestCall, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } public void invokCallBack() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_invokCallBack, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } } static final int TRANSACTION_registerTestCall = (IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_invokCallBack = (IBinder.FIRST_CALL_TRANSACTION + 1); } public void registerTestCall(com.styleflying.AIDL.forActivity cb) throws android.os.RemoteException; public void invokCallBack() throws android.os.RemoteException; }

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

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

    再看mAIDLActivity.java:

    1. package  com.styleflying.AIDL;  
    2. import  android.app.Activity;  
    3. import  android.content.ComponentName;  
    4. import  android.content.Context;  
    5. import  android.content.Intent;  
    6. import  android.content.ServiceConnection;  
    7. import  android.os.Bundle;  
    8. import  android.os.IBinder;  
    9. import  android.os.RemoteException;  
    10. import  android.util.Log;  
    11. import  android.view.View;  
    12. import  android.view.View.OnClickListener;  
    13. import  android.widget.Button;  
    14. import  android.widget.Toast;  
    15. public   class  mAIDLActivity  extends  Activity {  
    16.     private   static   final  String TAG =  "AIDLActivity" ;  
    17.     private  Button btnOk;  
    18.     private  Button btnCancel;  
    19.     private  Button btnCallBack;  
    20.       
    21.     private   void  Log(String str) {  
    22.         Log.d(TAG, "------ "  + str +  "------" );  
    23.         }  
    24.       
    25.     private  forActivity mCallback =  new  forActivity.Stub() {  
    26.         public   void  performAction()  throws  RemoteException  
    27.         {  
    28.             Toast.makeText(mAIDLActivity.this ,  "this toast is called from service" ,  1 ).show();  
    29.         }  
    30.         };  
    31.           
    32.     forService mService;  
    33.     private  ServiceConnection mConnection =  new  ServiceConnection() {  
    34.         public   void  onServiceConnected(ComponentName className,  
    35.                 IBinder service) {  
    36.             mService = forService.Stub.asInterface(service);  
    37.             try  {  
    38.                 mService.registerTestCall(mCallback);}  
    39.             catch  (RemoteException e) {  
    40.                   
    41.             }  
    42.             }  
    43.         public   void  onServiceDisconnected(ComponentName className) {  
    44.             Log("disconnect service" );  
    45.             mService = null ;  
    46.             }  
    47.         };  
    48.     @Override   
    49.     public   void  onCreate(Bundle icicle) {  
    50.         super .onCreate(icicle);  
    51.         setContentView(R.layout.main);  
    52.         btnOk = (Button)findViewById(R.id.btn_ok);  
    53.         btnCancel = (Button)findViewById(R.id.btn_cancel);  
    54.         btnCallBack = (Button)findViewById(R.id.btn_callback);  
    55.         btnOk.setOnClickListener(new  OnClickListener() {  
    56.             public   void  onClick(View v) {  
    57.                 Bundle args = new  Bundle();  
    58.                 Intent intent = new  Intent(mAIDLActivity. this , mAIDLService. class );  
    59.                 intent.putExtras(args);  
    60.                 bindService(intent, mConnection, Context.BIND_AUTO_CREATE);  
    61.                 startService(intent);  
    62.                 }  
    63.             });  
    64.         btnCancel.setOnClickListener(new  OnClickListener() {  
    65.             public   void  onClick(View v) {  
    66.                 unbindService(mConnection);  
    67.                 //stopService(intent);   
    68.                 }  
    69.             });  
    70.         btnCallBack.setOnClickListener(new  OnClickListener() {  
    71.               
    72.             @Override   
    73.             public   void  onClick(View v)  
    74.             {  
    75.                 try   
    76.                 {  
    77.                     mService.invokCallBack();  
    78.                 } catch  (RemoteException e)  
    79.                 {  
    80.                     // TODO Auto-generated catch block   
    81.                     e.printStackTrace();  
    82.                 }  
    83.             }  
    84.         });  
    85.         }  
    86. }  

    package com.styleflying.AIDL; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class mAIDLActivity extends Activity { private static final String TAG = "AIDLActivity"; private Button btnOk; private Button btnCancel; private Button btnCallBack; private void Log(String str) { Log.d(TAG, "------ " + str + "------"); } private forActivity mCallback = new forActivity.Stub() { public void performAction() throws RemoteException { Toast.makeText(mAIDLActivity.this, "this toast is called from service", 1).show(); } }; forService mService; private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { mService = forService.Stub.asInterface(service); try { mService.registerTestCall(mCallback);} catch (RemoteException e) { } } public void onServiceDisconnected(ComponentName className) { Log("disconnect service"); mService = null; } }; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); btnOk = (Button)findViewById(R.id.btn_ok); btnCancel = (Button)findViewById(R.id.btn_cancel); btnCallBack = (Button)findViewById(R.id.btn_callback); btnOk.setOnClickListener(new OnClickListener() { public void onClick(View v) { Bundle args = new Bundle(); Intent intent = new Intent(mAIDLActivity.this, mAIDLService.class); intent.putExtras(args); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); startService(intent); } }); btnCancel.setOnClickListener(new OnClickListener() { public void onClick(View v) { unbindService(mConnection); //stopService(intent); } }); btnCallBack.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { try { mService.invokCallBack(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); } }

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

    1. package  com.styleflying.AIDL;  
    2. import  android.app.Service;  
    3. import  android.content.Intent;  
    4. import  android.os.IBinder;  
    5. import  android.os.RemoteCallbackList;  
    6. import  android.os.RemoteException;  
    7. import  android.util.Log;  
    8. public   class  mAIDLService  extends  Service {  
    9.     private   static   final  String TAG =  "AIDLService" ;    
    10.     private  forActivity callback;  
    11.     private   void  Log(String str) {  
    12.         Log.d(TAG, "------ "  + str +  "------" );  
    13.     }  
    14.     @Override   
    15.     public   void  onCreate() {  
    16.         Log("service create" );  
    17.     }  
    18.     @Override   
    19.     public   void  onStart(Intent intent,  int  startId) {  
    20.         Log("service start id="  + startId);  
    21.     }  
    22.       
    23.     @Override   
    24.     public  IBinder onBind(Intent t) {  
    25.         Log("service on bind" );  
    26.         return  mBinder;  
    27.     }  
    28.     @Override   
    29.     public   void  onDestroy() {  
    30.         Log("service on destroy" );  
    31.         super .onDestroy();  
    32.     }  
    33.     @Override   
    34.     public   boolean  onUnbind(Intent intent) {  
    35.         Log("service on unbind" );  
    36.         return   super .onUnbind(intent);  
    37.     }  
    38.     public   void  onRebind(Intent intent) {  
    39.         Log("service on rebind" );  
    40.         super .onRebind(intent);  
    41.     }  
    42.     private   final  forService.Stub mBinder =  new  forService.Stub() {  
    43.         @Override   
    44.         public   void  invokCallBack()  throws  RemoteException  
    45.         {  
    46.             callback.performAction();  
    47.               
    48.         }  
    49.         @Override   
    50.         public   void  registerTestCall(forActivity cb)  throws  RemoteException  
    51.         {  
    52.             callback = cb;  
    53.               
    54.         }  
    55.           
    56.     };  
    57. }  

    package com.styleflying.AIDL; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.util.Log; public class mAIDLService extends Service { private static final String TAG = "AIDLService"; private forActivity callback; private void Log(String str) { Log.d(TAG, "------ " + str + "------"); } @Override public void onCreate() { Log("service create"); } @Override public void onStart(Intent intent, int startId) { Log("service start id=" + startId); } @Override public IBinder onBind(Intent t) { Log("service on bind"); return mBinder; } @Override public void onDestroy() { Log("service on destroy"); super.onDestroy(); } @Override public boolean onUnbind(Intent intent) { Log("service on unbind"); return super.onUnbind(intent); } public void onRebind(Intent intent) { Log("service on rebind"); super.onRebind(intent); } 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; } }; }

    注意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)。

    欢迎阅读、收藏本文。例子随手写的,功能只在演示AIDL的使用。您可以转载本文,但请勿盲目乱贴。不是我小气,我不权威,我怕它被贴到泛滥,以讹传讹,害了人。

  • 相关阅读:
    Android UiAutomator 自动化测试环境搭建---新手1
    python -- 计算数学题--用程序解决问题1
    linux(ubuntu) 遇到的问题 --1
    android--email发送邮件,文本还有附件形式的邮件
    fiddler---使用方法1--抓取手机app包
    appium 学习各种小功能总结--功能有《滑动图片、保存截图、验证元素是否存在、》---新手总结(大牛勿喷,新手互相交流)
    java 显示视频时间--玩的
    appium获取app应用的package和 activity。---新手总结(大牛勿喷,新手互相交流)
    python --appium搭建环境过程 ---新手总结(大牛勿喷,新手互相交流)
    centos6下yslow部署
  • 原文地址:https://www.cnblogs.com/greywolf/p/3031187.html
Copyright © 2011-2022 走看看