Android 基于Message的进程间通信 Messenger完全解析

1、概述

Binder能干什么?Binder可以提供系统中任何程序都可以访问的全局服务。这个功能当然是任何系统都应该提供的,下面我们简单看一下Android的Binder的框架

Android Binder框架分为服务器接口、Binder驱动、以及客户端接口;简单想一下,需要提供一个全局服务,那么全局服务那端即是服务器接口,任何程序即客户端接口,它们之间通过一个Binder驱动访问。

服务器端接口:实际上是Binder类的对象,该对象一旦创建,内部则会启动一个隐藏线程,会接收Binder驱动发送的消息,收到消息后,会执行Binder对象中的onTransact()函数,并按照该函数的参数执行不同的服务器端代码。

Binder驱动:该对象也为Binder类的实例,客户端通过该对象访问远程服务。

客户端接口:获得Binder驱动,调用其transact()发送消息至服务器

如果大家对上述不了解,没关系,下面会通过例子来更好的说明,实践是检验真理的唯一标准嘛

2、AIDL的使用

如果对Android比较熟悉,那么一定使用过AIDL,如果你还不了解,那么也没关系,下面会使用一个例子展示AIDL的用法。

我们使用AIDL实现一个跨进程的加减法调用

1、服务端

新建一个项目,创建一个包名:com.zhy.calc.aidl,在包内创建一个ICalcAIDL文件:

  1. package com.zhy.calc.aidl;  
  2. interface ICalcAIDL  
  3. {
  4.     int add(int x , int y);  
  5.     int min(int x , int y );  
  6. }

注意,文件名为ICalcAIDL.aidl

然后在项目的gen目录下会生成一个ICalcAIDL.Java文件,暂时不贴这个文件的代码了,后面会详细说明

然后我们在项目中新建一个Service,代码如下:

  1. package com.example.zhy_binder;  
  2. import com.zhy.calc.aidl.ICalcAIDL;  
  3. import android.app.Service;  
  4. import android.content.Intent;  
  5. import android.os.IBinder;  
  6. import android.os.RemoteException;  
  7. import android.util.Log;  
  8. public class CalcService extends Service  
  9. {
  10.     private static final String TAG = “server”;  
  11.     public void onCreate()  
  12.     {
  13.         Log.e(TAG, “onCreate”);  
  14.     }
  15.     public IBinder onBind(Intent t)  
  16.     {
  17.         Log.e(TAG, “onBind”);  
  18.         return mBinder;  
  19.     }
  20.     public void onDestroy()  
  21.     {
  22.         Log.e(TAG, “onDestroy”);  
  23.         super.onDestroy();  
  24.     }
  25.     public boolean onUnbind(Intent intent)  
  26.     {
  27.         Log.e(TAG, “onUnbind”);  
  28.         return super.onUnbind(intent);  
  29.     }
  30.     public void onRebind(Intent intent)  
  31.     {
  32.         Log.e(TAG, “onRebind”);  
  33.         super.onRebind(intent);  
  34.     }
  35.     private final ICalcAIDL.Stub mBinder = new ICalcAIDL.Stub()  
  36.     {
  37.         @Override  
  38.         public int add(int x, int y) throws RemoteException  
  39.         {
  40.             return x + y;  
  41.         }
  42.         @Override  
  43.         public int min(int x, int y) throws RemoteException  
  44.         {
  45.             return x – y;  
  46.         }
  47.     };
  48. }

在此Service中,使用生成的ICalcAIDL创建了一个mBinder的对象,并在Service的onBind方法中返回

*后记得在AndroidManifest中注册

  1. <service android:name=“com.example.zhy_binder.CalcService” >  
  2.            <intent-filter>  
  3.                <action android:name=“com.zhy.aidl.calc” />  
  4.                <category android:name=“android.intent.category.DEFAULT” />  
  5.            </intent-filter>  
  6.        </service>  

这里我们指定了一个name,因为我们一会会在别的应用程序中通过Intent来查找此Service;这个不需要Activity,所以我也就没写Activity,安装完成也看不到安装图标,悄悄在后台运行着。

到此,服务端编写完毕。下面开始编写客户端

2、客户端

客户端的代码比较简单,创建一个布局,里面包含4个按钮,分别为绑定服务,解除绑定,调用加法,调用减法

布局文件:

  1. <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”  
  2.     xmlns:tools=“http://schemas.android.com/tools”  
  3.     android:layout_width=“match_parent”  
  4.     android:layout_height=“match_parent”  
  5.     android:orientation=“vertical” >  
  6.     <Button  
  7.         android:layout_width=“fill_parent”  
  8.         android:layout_height=“wrap_content”  
  9.         android:onClick=“bindService”  
  10.         android:text=“BindService” />  
  11.     <Button  
  12.         android:layout_width=“fill_parent”  
  13.         android:layout_height=“wrap_content”  
  14.         android:onClick=“unbindService”  
  15.         android:text=“UnbindService” />  
  16.     <Button  
  17.         android:layout_width=“fill_parent”  
  18.         android:layout_height=“wrap_content”  
  19.         android:onClick=“addInvoked”  
  20.         android:text=“12+12” />  
  21.     <Button  
  22.         android:layout_width=“fill_parent”  
  23.         android:layout_height=“wrap_content”  
  24.         android:onClick=“minInvoked”  
  25.         android:text=“50-12” />  
  26. </LinearLayout>  

主Activity

  1. package com.example.zhy_binder_client;  
  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.util.Log;  
  10. import android.view.View;  
  11. import android.widget.Toast;  
  12. import com.zhy.calc.aidl.ICalcAIDL;  
  13. public class MainActivity extends Activity  
  14. {
  15.     private ICalcAIDL mCalcAidl;  
  16.     private ServiceConnection mServiceConn = new ServiceConnection()  
  17.     {
  18.         @Override  
  19.         public void onServiceDisconnected(ComponentName name)  
  20.         {
  21.             Log.e(“client”, “onServiceDisconnected”);  
  22.             mCalcAidl = null;  
  23.         }
  24.         @Override  
  25.         public void onServiceConnected(ComponentName name, IBinder service)  
  26.         {
  27.             Log.e(“client”, “onServiceConnected”);  
  28.             mCalcAidl = ICalcAIDL.Stub.asInterface(service);
  29.         }
  30.     };
  31.     @Override  
  32.     protected void onCreate(Bundle savedInstanceState)  
  33.     {
  34.         super.onCreate(savedInstanceState);  
  35.         setContentView(R.layout.activity_main);
  36.     }
  37.     /** 
  38.      * 点击BindService按钮时调用 
  39.      * @param view 
  40.      */  
  41.     public void bindService(View view)  
  42.     {
  43.         Intent intent = new Intent();  
  44.         intent.setAction(“com.zhy.aidl.calc”);  
  45.         bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE);
  46.     }
  47.     /** 
  48.      * 点击unBindService按钮时调用 
  49.      * @param view 
  50.      */  
  51.     public void unbindService(View view)  
  52.     {
  53.         unbindService(mServiceConn);
  54.     }
  55.     /** 
  56.      * 点击12+12按钮时调用 
  57.      * @param view 
  58.      */  
  59.     public void addInvoked(View view) throws Exception  
  60.     {
  61.         if (mCalcAidl != null)  
  62.         {
  63.             int addRes = mCalcAidl.add(12, 12);  
  64.             Toast.makeText(this, addRes + “”, Toast.LENGTH_SHORT).show();  
  65.         } else  
  66.         {
  67.             Toast.makeText(this, “服务器被异常杀死,请重新绑定服务端”, Toast.LENGTH_SHORT)  
  68.                     .show();
  69.         }
  70.     }
  71.     /** 
  72.      * 点击50-12按钮时调用 
  73.      * @param view 
  74.      */  
  75.     public void minInvoked(View view) throws Exception  
  76.     {
  77.         if (mCalcAidl != null)  
  78.         {
  79.             int addRes = mCalcAidl.min(58, 12);  
  80.             Toast.makeText(this, addRes + “”, Toast.LENGTH_SHORT).show();  
  81.         } else  
  82.         {
  83.             Toast.makeText(this, “服务端未绑定或被异常杀死,请重新绑定服务端”, Toast.LENGTH_SHORT)  
  84.                     .show();
  85.         }
  86.     }
  87. }

很标准的绑定服务的代码。

直接看运行结果:

%title插图%num

我们首先点击BindService按钮,查看log

  1. 08-09 22:56:38.959: E/server(29692): onCreate
  2. 08-09 22:56:38.959: E/server(29692): onBind
  3. 08-09 22:56:38.959: E/client(29477): onServiceConnected

可以看到,点击BindService之后,服务端执行了onCreate和onBind的方法,并且客户端执行了onServiceConnected方法,标明服务器与客户端已经联通

然后点击12+12,50-12可以成功的调用服务端的代码并返回正确的结果

下面我们再点击unBindService

  1. 08-09 22:59:25.567: E/server(29692): onUnbind
  2. 08-09 22:59:25.567: E/server(29692): onDestroy

由于我们当前只有一个客户端绑定了此Service,所以Service调用了onUnbind和onDestory

然后我们继续点击12+12,50-12,通过上图可以看到,依然可以正确执行,也就是说即使onUnbind被调用,连接也是不会断开的,那么什么时候会端口呢?

即当服务端被异常终止的时候,比如我们现在在手机的正在执行的程序中找到该服务:

%title插图%num

点击停止,此时查看log

  1. 08-09 23:04:21.433: E/client(30146): onServiceDisconnected

可以看到调用了onServiceDisconnected方法,此时连接被断开,现在点击12+12,50-12的按钮,则会弹出Toast服务端断开的提示。

说了这么多,似乎和Binder框架没什么关系,下面我们来具体看一看AIDL为什么做了些什么。

3、分析AIDL生成的代码

1、服务端

先看服务端的代码,可以看到我们服务端提供的服务是由

  1. private final ICalcAIDL.Stub mBinder = new ICalcAIDL.Stub()  
  2.     {
  3.         @Override  
  4.         public int add(int x, int y) throws RemoteException  
  5.         {
  6.             return x + y;  
  7.         }
  8.         @Override  
  9.         public int min(int x, int y) throws RemoteException  
  10.         {
  11.             return x – y;  
  12.         }
  13.     };

ICalcAILD.Stub来执行的,让我们来看看Stub这个类的声明:

  1. public static abstract class Stub extends android.os.Binder implements com.zhy.calc.aidl.ICalcAIDL  

清楚的看到这个类是Binder的子类,是不是符合我们文章开通所说的服务端其实是一个Binder类的实例

接下来看它的onTransact()方法:

  1. @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException  
  2. {
  3. switch (code)  
  4. {
  5. case INTERFACE_TRANSACTION:  
  6. {
  7. reply.writeString(DESCRIPTOR);
  8. return true;  
  9. }
  10. case TRANSACTION_add:  
  11. {
  12. data.enforceInterface(DESCRIPTOR);
  13. int _arg0;  
  14. _arg0 = data.readInt();
  15. int _arg1;  
  16. _arg1 = data.readInt();
  17. int _result = this.add(_arg0, _arg1);  
  18. reply.writeNoException();
  19. reply.writeInt(_result);
  20. return true;  
  21. }
  22. case TRANSACTION_min:  
  23. {
  24. data.enforceInterface(DESCRIPTOR);
  25. int _arg0;  
  26. _arg0 = data.readInt();
  27. int _arg1;  
  28. _arg1 = data.readInt();
  29. int _result = this.min(_arg0, _arg1);  
  30. reply.writeNoException();
  31. reply.writeInt(_result);
  32. return true;  
  33. }
  34. }
  35. return super.onTransact(code, data, reply, flags);  
  36. }

文章开头也说到服务端的Binder实例会根据客户端依靠Binder驱动发来的消息,执行onTransact方法,然后由其参数决定执行服务端的代码。

可以看到onTransact有四个参数

code , data ,replay , flags

code 是一个整形的唯一标识,用于区分执行哪个方法,客户端会传递此参数,告诉服务端执行哪个方法

data客户端传递过来的参数

replay服务器返回回去的值

flags标明是否有返回值,0为有(双向),1为没有(单向)

我们仔细看case TRANSACTION_min中的代码

data.enforceInterface(DESCRIPTOR);与客户端的writeInterfaceToken对用,标识远程服务的名称

int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();

接下来分别读取了客户端传入的两个参数

int _result = this.min(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);

然后执行this.min,即我们实现的min方法;返回result由reply写回。

add同理,可以看到服务端通过AIDL生成Stub的类,封装了服务端本来需要写的代码。

2、客户端

客户端主要通过ServiceConnected与服务端连接

  1. private ServiceConnection mServiceConn = new ServiceConnection()  
  2.     {
  3.         @Override  
  4.         public void onServiceDisconnected(ComponentName name)  
  5.         {
  6.             Log.e(“client”, “onServiceDisconnected”);  
  7.             mCalcAidl = null;  
  8.         }
  9.         @Override  
  10.         public void onServiceConnected(ComponentName name, IBinder service)  
  11.         {
  12.             Log.e(“client”, “onServiceConnected”);  
  13.             mCalcAidl = ICalcAIDL.Stub.asInterface(service);
  14.         }
  15.     };

如果你比较敏锐,应该会猜到这个onServiceConnected中的IBinder实例,其实就是我们文章开通所说的Binder驱动,也是一个Binder实例

在ICalcAIDL.Stub.asInterface中*终调用了:

  1. return new com.zhy.calc.aidl.ICalcAIDL.Stub.Proxy(obj);  

这个Proxy实例传入了我们的Binder驱动,并且封装了我们调用服务端的代码,文章开头说,客户端会通过Binder驱动的transact()方法调用服务端代码

直接看Proxy中的add方法

  1. @Override public int add(int x, int y) throws android.os.RemoteException  
  2. {
  3. android.os.Parcel _data = android.os.Parcel.obtain();
  4. android.os.Parcel _reply = android.os.Parcel.obtain();
  5. int _result;  
  6. try {  
  7. _data.writeInterfaceToken(DESCRIPTOR);
  8. _data.writeInt(x);
  9. _data.writeInt(y);
  10. mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);  
  11. _reply.readException();
  12. _result = _reply.readInt();
  13. }
  14. finally {  
  15. _reply.recycle();
  16. _data.recycle();
  17. }
  18. return _result;  
  19. }

首先声明两个Parcel对象,一个用于传递数据,一个用户接收返回的数据

_data.writeInterfaceToken(DESCRIPTOR);与服务器端的enforceInterfac对应

_data.writeInt(x);
_data.writeInt(y);写入需要传递的参数

mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);

终于看到了我们的transact方法,*个对应服务端的code,_data,_repay分别对应服务端的data,reply,0表示是双向的

_reply.readException();
_result = _reply.readInt();

*后读出我们服务端返回的数据,然后return。可以看到和服务端的onTransact基本是一行一行对应的。

到此,我们已经通过AIDL生成的代码解释了Android Binder框架的工作原理。Service的作用其实就是为我们创建Binder驱动,即服务端与客户端连接的桥梁。

AIDL其实通过我们写的aidl文件,帮助我们生成了一个接口,一个Stub类用于服务端,一个Proxy类用于客户端调用。那么我们是否可以不通过写AIDL来实现远程的通信呢?下面向大家展示如何完全不依赖AIDL来实现客户端与服务端的通信。

4、不依赖AIDL实现程序间通讯

1、服务端代码

我们新建一个CalcPlusService.java用于实现两个数的乘和除

  1. package com.example.zhy_binder;  
  2. import android.app.Service;  
  3. import android.content.Intent;  
  4. import android.os.Binder;  
  5. import android.os.IBinder;  
  6. import android.os.Parcel;  
  7. import android.os.RemoteException;  
  8. import android.util.Log;  
  9. public class CalcPlusService extends Service  
  10. {
  11.     private static final String DESCRIPTOR = “CalcPlusService”;  
  12.     private static final String TAG = “CalcPlusService”;  
  13.     public void onCreate()  
  14.     {
  15.         Log.e(TAG, “onCreate”);  
  16.     }
  17.     @Override  
  18.     public int onStartCommand(Intent intent, int flags, int startId)  
  19.     {
  20.         Log.e(TAG, “onStartCommand”);  
  21.         return super.onStartCommand(intent, flags, startId);  
  22.     }
  23.     public IBinder onBind(Intent t)  
  24.     {
  25.         Log.e(TAG, “onBind”);  
  26.         return mBinder;  
  27.     }
  28.     public void onDestroy()  
  29.     {
  30.         Log.e(TAG, “onDestroy”);  
  31.         super.onDestroy();  
  32.     }
  33.     public boolean onUnbind(Intent intent)  
  34.     {
  35.         Log.e(TAG, “onUnbind”);  
  36.         return super.onUnbind(intent);  
  37.     }
  38.     public void onRebind(Intent intent)  
  39.     {
  40.         Log.e(TAG, “onRebind”);  
  41.         super.onRebind(intent);  
  42.     }
  43.     private MyBinder mBinder = new MyBinder();  
  44.     private class MyBinder extends Binder  
  45.     {
  46.         @Override  
  47.         protected boolean onTransact(int code, Parcel data, Parcel reply,  
  48.                 int flags) throws RemoteException  
  49.         {
  50.             switch (code)  
  51.             {
  52.             case 0x110:  
  53.             {
  54.                 data.enforceInterface(DESCRIPTOR);
  55.                 int _arg0;  
  56.                 _arg0 = data.readInt();
  57.                 int _arg1;  
  58.                 _arg1 = data.readInt();
  59.                 int _result = _arg0 * _arg1;  
  60.                 reply.writeNoException();
  61.                 reply.writeInt(_result);
  62.                 return true;  
  63.             }
  64.             case 0x111:  
  65.             {
  66.                 data.enforceInterface(DESCRIPTOR);
  67.                 int _arg0;  
  68.                 _arg0 = data.readInt();
  69.                 int _arg1;  
  70.                 _arg1 = data.readInt();
  71.                 int _result = _arg0 / _arg1;  
  72.                 reply.writeNoException();
  73.                 reply.writeInt(_result);
  74.                 return true;  
  75.             }
  76.             }
  77.             return super.onTransact(code, data, reply, flags);  
  78.         }
  79.     };
  80. }

我们自己实现服务端,所以我们自定义了一个Binder子类,然后复写了其onTransact方法,我们指定服务的标识为CalcPlusService,然后0x110为乘,0x111为除;

记得在AndroidMenifest中注册

  1. <service android:name=“com.example.zhy_binder.CalcPlusService” >  
  2.            <intent-filter>  
  3.                <action android:name=“com.zhy.aidl.calcplus” />  
  4.                <category android:name=“android.intent.category.DEFAULT” />  
  5.            </intent-filter>  
  6.        </service>  

服务端代码结束。

2、客户端代码

单独新建了一个项目,代码和上例很类似

首先布局文件:

  1. <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”  
  2.     xmlns:tools=“http://schemas.android.com/tools”  
  3.     android:layout_width=“match_parent”  
  4.     android:layout_height=“match_parent”  
  5.     android:orientation=“vertical” >  
  6.     <Button  
  7.         android:layout_width=“fill_parent”  
  8.         android:layout_height=“wrap_content”  
  9.         android:onClick=“bindService”  
  10.         android:text=“BindService” />  
  11.     <Button  
  12.         android:layout_width=“fill_parent”  
  13.         android:layout_height=“wrap_content”  
  14.         android:onClick=“unbindService”  
  15.         android:text=“UnbindService” />  
  16.     <Button  
  17.         android:layout_width=“fill_parent”  
  18.         android:layout_height=“wrap_content”  
  19.         android:onClick=“mulInvoked”  
  20.         android:text=“50*12” />  
  21.     <Button  
  22.         android:layout_width=“fill_parent”  
  23.         android:layout_height=“wrap_content”  
  24.         android:onClick=“divInvoked”  
  25.         android:text=“36/12” />  
  26. </LinearLayout>  

可以看到加入了乘和除

然后是Activity的代码

  1. package com.example.zhy_binder_client03;  
  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.widget.Toast;  
  13. public class MainActivity extends Activity  
  14. {
  15.     private IBinder mPlusBinder;  
  16.     private ServiceConnection mServiceConnPlus = new ServiceConnection()  
  17.     {
  18.         @Override  
  19.         public void onServiceDisconnected(ComponentName name)  
  20.         {
  21.             Log.e(“client”, “mServiceConnPlus onServiceDisconnected”);  
  22.         }
  23.         @Override  
  24.         public void onServiceConnected(ComponentName name, IBinder service)  
  25.         {
  26.             Log.e(“client”, ” mServiceConnPlus onServiceConnected”);  
  27.             mPlusBinder = service;
  28.         }
  29.     };
  30.     @Override  
  31.     protected void onCreate(Bundle savedInstanceState)  
  32.     {
  33.         super.onCreate(savedInstanceState);  
  34.         setContentView(R.layout.activity_main);
  35.     }
  36.     public void bindService(View view)  
  37.     {
  38.         Intent intentPlus = new Intent();  
  39.         intentPlus.setAction(“com.zhy.aidl.calcplus”);  
  40.         boolean plus = bindService(intentPlus, mServiceConnPlus,  
  41.                 Context.BIND_AUTO_CREATE);
  42.         Log.e(“plus”, plus + “”);  
  43.     }
  44.     public void unbindService(View view)  
  45.     {
  46.         unbindService(mServiceConnPlus);
  47.     }
  48.     public void mulInvoked(View view)  
  49.     {
  50.         if (mPlusBinder == null)  
  51.         {
  52.             Toast.makeText(this, “未连接服务端或服务端被异常杀死”, Toast.LENGTH_SHORT).show();  
  53.         } else  
  54.         {
  55.             android.os.Parcel _data = android.os.Parcel.obtain();
  56.             android.os.Parcel _reply = android.os.Parcel.obtain();
  57.             int _result;  
  58.             try  
  59.             {
  60.                 _data.writeInterfaceToken(“CalcPlusService”);  
  61.                 _data.writeInt(50);  
  62.                 _data.writeInt(12);  
  63.                 mPlusBinder.transact(0x110, _data, _reply, 0);  
  64.                 _reply.readException();
  65.                 _result = _reply.readInt();
  66.                 Toast.makeText(this, _result + “”, Toast.LENGTH_SHORT).show();  
  67.             } catch (RemoteException e)  
  68.             {
  69.                 e.printStackTrace();
  70.             } finally  
  71.             {
  72.                 _reply.recycle();
  73.                 _data.recycle();
  74.             }
  75.         }
  76.     }
  77.     public void divInvoked(View view)  
  78.     {
  79.         if (mPlusBinder == null)  
  80.         {
  81.             Toast.makeText(this, “未连接服务端或服务端被异常杀死”, Toast.LENGTH_SHORT).show();  
  82.         } else  
  83.         {
  84.             android.os.Parcel _data = android.os.Parcel.obtain();
  85.             android.os.Parcel _reply = android.os.Parcel.obtain();
  86.             int _result;  
  87.             try  
  88.             {
  89.                 _data.writeInterfaceToken(“CalcPlusService”);  
  90.                 _data.writeInt(36);  
  91.                 _data.writeInt(12);  
  92.                 mPlusBinder.transact(0x111, _data, _reply, 0);  
  93.                 _reply.readException();
  94.                 _result = _reply.readInt();
  95.                 Toast.makeText(this, _result + “”, Toast.LENGTH_SHORT).show();  
  96.             } catch (RemoteException e)  
  97.             {
  98.                 e.printStackTrace();
  99.             } finally  
  100.             {
  101.                 _reply.recycle();
  102.                 _data.recycle();
  103.             }
  104.         }
  105.     }
  106. }

为了明了,我直接在mulInvoked里面写了代码,和服务端都没有抽象出一个接口。首先绑定服务时,通过onServiceConnected得到Binder驱动即mPlusBinder;

然后准备数据,调用transact方法,通过code指定执行服务端哪个方法,代码和上面的分析一致。

下面看运行结果:

%title插图%num

是不是很好的实现了我们两个应用程序间的通讯,并没有使用aidl文件,也从侧面分析了我们上述分析是正确的。

 

好了,就到这里,相信大家看完这篇博文,对aidl和Binder的理解也会更加深刻。