Android-深入理解AIDL

本文深入剖析 Android 进程间通信机制 AIDL 的工作原理与实现方式,通过客户端和服务端的具体示例代码,详细解读 AIDL 的配置、绑定及数据交互流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近从新温习AIDL,发现技术这玩意就跟女人一样,你过久没去了解就会对它陌生却又充满新鲜感,然后查看网上的多半是胡扯,粘贴,我这里整合下,里面如果有错误望大家及时指出。废话不多说,进入主题

首先来了解几点常识:

1,一个Android应用程序对应一个进程;

2,Android应用程序进程间需要借助IPC轻量级通讯协议;

3,切勿把线程和进程的概念搞混乱。一个进程可以包含多个线程,但是一个线程只会附属于一个进程,可以理解成1对多的关系;

4,我们常见的Handler它是运行在UI主线程的,它负责的是异步处理数据,执行也是父线程和子线程;所以别把它和进程的概念混在一起。

进入主题,Android进程间的通讯:AIDL

这里我以为大家比较熟悉的C/S模式来讲解整个通讯过程;但是我并没有去新建立两个项目了,就一个项目中,模拟进程通讯。不多说,先上项目图


第一步,首先建立两个aidl文件,forActivity.adil,forService.aidl 先来看看它们内部实现

[java]  view plain  copy
  1. package com.aidl;  
  2. interface forActivity{  
  3.   void perAction();  
  4.   void showString(int count);  
  5. }  
[java]  view plain  copy
  1. package com.aidl;  
  2. import com.aidl.forActivity;  
  3. interface forService{  
  4.      void registerTestCall(forActivity fa);  
  5.      void callBack();  
  6. }  



一看,哎哟,这里面的编码规则和java文件一样,但是这个时候,我其他地方要调用怎么办?别着急编译器会默认在gen文件中生成对应.java文件

打开其中一个文件查看下其中源码,先不详细分析,慢慢来,就好比追女生一样,要慢慢来,急不得

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

第二步,新建mAIDLActivity.java文件,它模拟Client , 新建mAIDLService.java文件,它模拟Server;

           先看看mAIDLActivity.java文件;

[java]  view plain  copy
  1. public class mAIDLActivity extends Activity {  
  2.     private static final String TAG = "AIDLActivity";  
  3.     private Button btnOk;  
  4.     private Button btnCancel;  
  5.     private Button btnCallBack;  
  6.   
  7.     private void Log(String str) {  
  8.         android.util.Log.d(TAG, "------ " + str + "------");  
  9.     }  
  10.       
  11.     @Override  
  12.     protected void onCreate(Bundle savedInstanceState) {  
  13.         // TODO Auto-generated method stub  
  14.         super.onCreate(savedInstanceState);  
  15.         setContentView(R.layout.main);  
  16.         btnOk = (Button) findViewById(R.id.btn_ok);  
  17.         btnCancel = (Button) findViewById(R.id.btn_cancel);  
  18.         btnCallBack = (Button) findViewById(R.id.btn_callback);  
  19.         btnOk.setOnClickListener(new OnClickListener() {  
  20.             public void onClick(View v) {  
[java]  view plain  copy
  1.                         //绑定服务  
  2.       Intent intent = new Intent(mAIDLActivity.this,mAIDLService.class);  
  3.       bindService(intent, mcConnection, Context.BIND_AUTO_CREATE);  
  4.       //startService(intent);  
  5.     }  
  6. });  
  7. btnCancel.setOnClickListener(new OnClickListener() {  
  8.     public void onClick(View v) {  
[java]  view plain  copy
  1.                                 //取消绑定  
  2.                 unbindService(mcConnection);  
  3.                 /*unbindService(mConnection); 
  4.                 // stopService(intent); 
  5. */          }  
  6.         });  
  7.         btnCallBack.setOnClickListener(new OnClickListener() {  
  8.   
  9.             @Override  
  10.             public void onClick(View v) {  
  11.                 try {  
[java]  view plain  copy
  1.                                    //进程数据交互通讯  
  2.                 mService.callBack();  
  3.             } catch (RemoteException e) {  
  4.                 // TODO Auto-generated catch block  
  5.                 e.printStackTrace();  
  6.             }  
  7.         }  
  8.     });  
  9. }  
  10.    forService mService;  
  11.    forActivity mActivity = new forActivity.Stub() {  
  12.       
  13.     @Override  
  14.     public void perAction() throws RemoteException {  
  15.         Log("执行了啦");  
  16.     }  
  17.   
  18.     @Override  
  19.     public void showString(int count) throws RemoteException {  
  20.         Log(count+"");  
  21.     }  
  22.       
  23. };  
  24.      
  25.    ServiceConnection mcConnection = new ServiceConnection() {  
  26.       
  27.     @Override  
  28.     public void onServiceDisconnected(ComponentName name) {  
  29.           
  30.     }  
  31.       
  32.     @Override  
  33.     public void onServiceConnected(ComponentName name, IBinder service) {  
  34.         mService = forService.Stub.asInterface(service);  
  35.         try {  
  36.             mService.registerTestCall(mActivity);  
  37.         } catch (RemoteException e) {  
  38.   
  39.         }  
  40.     }  
  41. };  
这三个按钮的作用我就不用说了吧,那么明白的解释在那里还不懂的话,那你就别继续看了,好好看看片,撸一管撤退吧。

先分析下上述文件

[java]  view plain  copy
  1. ServiceConnection mcConnection = new ServiceConnection() {  
  2.           
  3.         @Override  
  4.         public void onServiceDisconnected(ComponentName name) {  
  5.               
  6.         }  
  7.           
  8.         @Override  
  9.         public void onServiceConnected(ComponentName name, IBinder service) {  
  10.             mService = forService.Stub.asInterface(service);  
  11.             try {  
  12.                 mService.registerTestCall(mActivity);  
  13.             } catch (RemoteException e) {  
  14.   
  15.             }  
  16.         }  
  17.     };  
ServiceConnection的使用和介绍我上一篇博文已经说了,大家可以去看看,说实在的就是如果不是研究AIDL,这家伙我估计都不会看到.

看这句代码

[java]  view plain  copy
  1. mService = forService.Stub.asInterface(service);  
如果直接看的话不看源码,我第一想到的就是实例化?强转,?一大堆不靠谱的逻辑,作为一个装逼程序猿,如果遇到不知道的情况,别瞎猜,看源码才是王道.来打开forService.文件
[java]  view plain  copy
  1. public interface forService extends android.os.IInterface  
  2. {  
  3. /** Local-side IPC implementation stub class. */  
  4. public static abstract class Stub extends android.os.Binder implements com.aidl.forService  
  5. {  
  6. private static final java.lang.String DESCRIPTOR = "com.aidl.forService";  
  7. /** Construct the stub at attach it to the interface. */  
  8. public Stub()  
  9. {  
  10. this.attachInterface(this, DESCRIPTOR);  
  11. }  
  12. /** 
  13.  * Cast an IBinder object into an com.aidl.forService interface, 
  14.  * generating a proxy if needed. 
  15.  */  
  16. public static com.aidl.forService asInterface(android.os.IBinder obj)  
  17. {  
  18. if ((obj==null)) {  
  19. return null;  
  20. }  
  21. android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);  
  22. if (((iin!=null)&&(iin instanceof com.aidl.forService))) {  
  23. return ((com.aidl.forService)iin);  
  24. }  
  25. return new com.aidl.forService.Stub.Proxy(obj);  
  26. }  

这里我们发现,Stub是forService的内部静态抽象类,并且是继承Binder和实例化了接口forService. 查看方法adInterface中的实现,它分三步来判断

 1,如果是空,直接给你空,让你一边玩去

  2,如果传入的Ibinder对象就是com.aidl.forService,因为forService的继承的IInterface,看IInterface的介绍Base class for Binder interfaces. When defining a new interface, you must derive it from IInterface.那得列直接强转成forService对象返回去,万事大吉;
  3.如果为空,那就new一个新的,对象嘛.程序猿从来不缺.

下面继续分析mAIDLService文件.不多说,先看源码

[java]  view plain  copy
  1. public class mAIDLService extends Service {  
  2.        
  3.     @Override  
  4.     public IBinder onBind(Intent intent) {  
  5.         return mIBinder;  
  6.     }  
  7.     forActivity mActivity;  
  8.     int count=0;  
  9.     forService.Stub mIBinder  = new forService.Stub() {  
  10.           
  11.         @Override  
  12.         public void registerTestCall(forActivity fa) throws RemoteException {  
  13.             mActivity = fa;  
  14.         }  
  15.           
  16.         @Override  
  17.         public void callBack() throws RemoteException {  
  18.             mActivity.perAction();  
  19.             mActivity.showString(++count);  
  20.         }  
  21.     };  
  22. }  

它这里相对就简单了,基本不用多说了吧,这里要注意的就是
[java]  view plain  copy
  1. public IBinder onBind(Intent intent) {  
  2.         return mIBinder;  
  3.     }  
它返回的是当前new出来的forService对象.也就是我们前面ServiceConnection回调拿到的IBinder,

那这里就慢慢明朗了,整个相互间的通讯也就清楚了,当按下btnCallBack按钮的时候,首先会调用forService中的callBack方法,而callBack方法的实现中又调用了forActivity的perAction.通过forActivity和forService的这次握手,就达到了mAIDLActivity和mAIDLService一直及时通讯

说到这里有朋友跟我说ContentProvider就可以直接实现两个应用间的数据传递了啊,为什么还要用AIDL,我转头一声呵呵,我列出下面几个区分点估计大家就明白了

1.ContentProvider是单向性的,不及时的,而AIDL是双向性,及时的。就这么来说吧。ContentProvider就好比你看到一个漂亮的妹子,你一直看着她,但是她却对你无视,你看不清楚她身体的变化;AIDL就是你看到那个漂亮的妹子,她也看着,你下面的异样,立即反馈给了她,而你也看到了她嘴边的异样,这比喻好理解吗?哈哈哈

 好了中间有些地方如果有错或者大家要补充的直接留言吧,然后恳请转载的指明地址,不然又是一堆废文到处跑。

下篇博文准备分析下IBinder和Binder!

参考网友论文

http://blog.youkuaiyun.com/saintswordsman/article/details/5130947

源码下载

http://download.youkuaiyun.com/detail/eran12101030/7993485

原文地址:http://blog.youkuaiyun.com/eran12101030/article/details/39672189

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值