开发者社区> 技术小胖子> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

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文件:

[java] view plain copy
  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,代码如下:

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

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

最后记得在AndroidManifest中注册

[html] view plain copy
  1. <service android:name="com.example.zhy_binder.CalcService" >  
  2.            <intent-filter>  
  3.                <action android:name="com.zhy.aidl.calc" />  
  4.   
  5.                <category android:name="android.intent.category.DEFAULT" />  
  6.            </intent-filter>  
  7.        </service>  


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

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

2、客户端

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

布局文件:

[html] view plain copy
  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.   
  7.     <Button  
  8.         android:layout_width="fill_parent"  
  9.         android:layout_height="wrap_content"  
  10.         android:onClick="bindService"  
  11.         android:text="BindService" />  
  12.   
  13.     <Button  
  14.         android:layout_width="fill_parent"  
  15.         android:layout_height="wrap_content"  
  16.         android:onClick="unbindService"  
  17.         android:text="UnbindService" />  
  18.   
  19.     <Button  
  20.         android:layout_width="fill_parent"  
  21.         android:layout_height="wrap_content"  
  22.         android:onClick="addInvoked"  
  23.         android:text="12+12" />  
  24.   
  25.     <Button  
  26.         android:layout_width="fill_parent"  
  27.         android:layout_height="wrap_content"  
  28.         android:onClick="minInvoked"  
  29.         android:text="50-12" />  
  30.   
  31. </LinearLayout>  


主Activity

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

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

直接看运行结果:

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

[html] view plain copy
  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

[html] view plain copy
  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被调用,连接也是不会断开的,那么什么时候会端口呢?

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

点击停止,此时查看log

[html] view plain copy
  1. 08-09 23:04:21.433: E/client(30146): onServiceDisconnected  

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

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

3、分析AIDL生成的代码

 

1、服务端

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

[java] view plain copy
  1. private final ICalcAIDL.Stub mBinder = new ICalcAIDL.Stub()  
  2.     {  
  3.   
  4.         @Override  
  5.         public int add(int x, int y) throws RemoteException  
  6.         {  
  7.             return x + y;  
  8.         }  
  9.   
  10.         @Override  
  11.         public int min(int x, int y) throws RemoteException  
  12.         {  
  13.             return x - y;  
  14.         }  
  15.   
  16.     };  


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

[java] view plain copy
  1. public static abstract class Stub extends android.os.Binder implements com.zhy.calc.aidl.ICalcAIDL  


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

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

[java] view plain copy
  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与服务端连接

[java] view plain copy
  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.   
  10.         @Override  
  11.         public void onServiceConnected(ComponentName name, IBinder service)  
  12.         {  
  13.             Log.e("client", "onServiceConnected");  
  14.             mCalcAidl = ICalcAIDL.Stub.asInterface(service);  
  15.         }  
  16.     };  


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

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

[java] view plain copy
  1. return new com.zhy.calc.aidl.ICalcAIDL.Stub.Proxy(obj);  


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

直接看Proxy中的add方法

[java] view plain copy
  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用于实现两个数的乘和除

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


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

记得在AndroidMenifest中注册

[html] view plain copy
  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、客户端代码

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

首先布局文件:

[html] view plain copy
  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.   
  7.     <Button  
  8.         android:layout_width="fill_parent"  
  9.         android:layout_height="wrap_content"  
  10.         android:onClick="bindService"  
  11.         android:text="BindService" />  
  12.   
  13.     <Button  
  14.         android:layout_width="fill_parent"  
  15.         android:layout_height="wrap_content"  
  16.         android:onClick="unbindService"  
  17.         android:text="UnbindService" />  
  18.   
  19.     <Button  
  20.         android:layout_width="fill_parent"  
  21.         android:layout_height="wrap_content"  
  22.         android:onClick="mulInvoked"  
  23.         android:text="50*12" />  
  24.       
  25.     <Button  
  26.         android:layout_width="fill_parent"  
  27.         android:layout_height="wrap_content"  
  28.         android:onClick="divInvoked"  
  29.         android:text="36/12" />  
  30.   
  31. </LinearLayout>  


可以看到加入了乘和除

然后是Activity的代码

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


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

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

下面看运行结果:

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

 

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

 

测试代码点击下载

代码先安装server端的代码,然后再安装client端的。。。

 

    本文转自 一点点征服   博客园博客,原文链接:http://www.cnblogs.com/ldq2016/p/7307015.html,如需转载请自行联系原作者



版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Android开发之Activity转场动画
引子 相信开发过iOS的程序员都知道iOS ViewController之间的跳转动画非常多,很酷对不对?这让开发Android的羡慕不已,曾几何时,Android中的Activity跳转是何等的生硬,But,在Android 5.0以后,Google也为Activity的转场设计了更加友好的动画效果。
765 0
应用保活终极总结(二):Android6.0及以上的保活实践(进程防杀篇)
原作者:“裂缝中的阳光dg”,本文现已重新修订并整理发布,感谢原作者的无私分享。 1、前言 在Android 4.4及以后的系统中,应用能否常驻内存,一直以来都是相当头疼的事情,尤其移动端IM、消息推送这类应用,为了保证“全时在线”的概念,真是费尽了心思。
1494 0
21114
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载