1.BInder驱动机制说明

首先Binder是用于进程间通讯,这个我们都知道,但是它是基于Binder驱动来完成进程间通讯的。Binder驱动是一个驱动程序,而这个驱动程序存在于Linux内核层,Linux内核层又可以说是操作系统层,是进程的管理者。

一个进程A要调用进程B的一个方法,这个进程A就需要获取进程B的Binder代理对象,这个BInder代理对象就是进程B的BInder本地对象。当然这个Binder本地对象需要我们在进程B去实现在Service里面,实现的同时还要实现进程A想要调用方法。而在进程A里也要实现Binder代理对象。 进程A调用Binder代理对象时会通知Binder驱动,Binder驱动又会去调用进程B实现的Binder本地对象到实现的方法。

这里要注意为何BInder驱动能够知道进程A和进程B的所在,首先进程也可以看做内存里的一个地址,然后无论是BInder代理对象和Binder本地对象都会实现IBinder接口,都会在ServiceManager里注册地址通过所在的Service的名字(比如:Action)注册的,这样一来双方通过像是访问Service就可以访问对方的IBinder实现类。首先要注意无论是注册还是传递数据、回调数据都是通过Binder驱动实现,具体Binder驱动如何实现我们不需要知道,我们所能做的就是实现BInder本地对象和Binder代理对象。

2.BInder的使用方法

Server端负责实现Binder本地对象,Client负责实现Binder代理对象,实现Client端要调用Server完成两个不同计算函数。这里既然要调用两个函数,我们就要教两者学会如何分辨,就像使用handler一样,通过数字来分辨,毕竟占用字节少。

mPlusBinder.transact(0x110, _data, _reply, 0);

因为调用函数会有返回值,所以我们在使用Binder代理对象调用函数时需要首先传输数据过去,然后在接收数据。

                _data.writeInterfaceToken("CalcPlusService");_data.writeInt(36);_data.writeInt(12);mPlusBinder.transact(0x111, _data, _reply, 0);_reply.readException();_result = _reply.readInt();

同时Server端需要首先接收函数,进过计算再返回值

                    data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 = data.readInt();int _arg1;_arg1 = data.readInt();int _result = _arg0 * _arg1;reply.writeNoException();reply.writeInt(_result);

完整实例代码如下

BinderServer的代码

public class CalcPlusService extends Service
{private static final String DESCRIPTOR = "CalcPlusService";private static final String TAG = "CalcPlusService";public void onCreate(){Log.e(TAG, "onCreate");}@Overridepublic int onStartCommand(Intent intent, int flags, int startId){Log.e(TAG, "onStartCommand");return super.onStartCommand(intent, flags, startId);}public IBinder onBind(Intent t){Log.e(TAG, "onBind");return mBinder;}public void onDestroy(){Log.e(TAG, "onDestroy");super.onDestroy();}public boolean onUnbind(Intent intent){Log.e(TAG, "onUnbind");return super.onUnbind(intent);}public void onRebind(Intent intent){Log.e(TAG, "onRebind");super.onRebind(intent);}private MyBinder mBinder = new MyBinder();private class MyBinder extends Binder{@Overrideprotected boolean onTransact(int code, Parcel data, Parcel reply,int flags) throws RemoteException{switch (code){case 0x110:{data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 = data.readInt();int _arg1;_arg1 = data.readInt();int _result = _arg0 * _arg1;reply.writeNoException();reply.writeInt(_result);return true;}case 0x111:{data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 = data.readInt();int _arg1;_arg1 = data.readInt();int _result = _arg0 / _arg1;reply.writeNoException();reply.writeInt(_result);return true;}}return super.onTransact(code, data, reply, flags);}};}  <service android:name="com.example.zhy_binder.CalcPlusService" ><intent-filter><action android:name="com.zhy.aidl.calcplus" /><category android:name="android.intent.category.DEFAULT" /></intent-filter>
</service>

BinderClient

public class MainActivity extends Activity
{private IBinder mPlusBinder;private ServiceConnection mServiceConnPlus = new ServiceConnection(){@Overridepublic void onServiceDisconnected(ComponentName name){Log.e("client", "mServiceConnPlus onServiceDisconnected");}@Overridepublic void onServiceConnected(ComponentName name, IBinder service){Log.e("client", " mServiceConnPlus onServiceConnected");mPlusBinder = service;}};@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void bindService(View view){Intent intentPlus = new Intent();intentPlus.setAction("com.zhy.aidl.calcplus");boolean plus = bindService(intentPlus, mServiceConnPlus,Context.BIND_AUTO_CREATE);Log.e("plus", plus + "");}public void unbindService(View view){unbindService(mServiceConnPlus);}public void mulInvoked(View view){if (mPlusBinder == null){Toast.makeText(this, "未连接服务端或服务端被异常杀死", Toast.LENGTH_SHORT).show();} else{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();int _result;try{_data.writeInterfaceToken("CalcPlusService");_data.writeInt(50);_data.writeInt(12);mPlusBinder.transact(0x110, _data, _reply, 0);_reply.readException();_result = _reply.readInt();Toast.makeText(this, _result + "", Toast.LENGTH_SHORT).show();} catch (RemoteException e){e.printStackTrace();} finally{_reply.recycle();_data.recycle();}}}public void divInvoked(View view){if (mPlusBinder == null){Toast.makeText(this, "未连接服务端或服务端被异常杀死", Toast.LENGTH_SHORT).show();} else{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();int _result;try{_data.writeInterfaceToken("CalcPlusService");_data.writeInt(36);_data.writeInt(12);mPlusBinder.transact(0x111, _data, _reply, 0);_reply.readException();_result = _reply.readInt();Toast.makeText(this, _result + "", Toast.LENGTH_SHORT).show();} catch (RemoteException e){e.printStackTrace();} finally{_reply.recycle();_data.recycle();}}}
}<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:onClick="bindService"android:text="BindService" /><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:onClick="unbindService"android:text="UnbindService" /><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:onClick="mulInvoked"android:text="50*12" /><Buttonandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:onClick="divInvoked"android:text="36/12" /></LinearLayout>

Binder的使用方法和源码解析相关推荐

  1. Google Test(GTest)使用方法和源码解析——模板类测试技术分析和应用

    写C++难免会遇到模板问题,如果要针对一个模板类进行测试,似乎之前博文中介绍的方式只能傻乎乎的一个一个特化类型后再进行测试.其实GTest提供了两种测试模板类的方法,本文我们将介绍方法的使用,并分析其 ...

  2. Google Test(GTest)使用方法和源码解析——参数自动填充技术分析和应用

    在我们设计测试用例时,我们需要考虑很多场景.每个场景都可能要细致地考虑到到各个参数的选择.比如我们希望使用函数IsPrime检测10000以内字的数字,难道我们要写一万行代码么?(转载请指明出于bre ...

  3. Google Test(GTest)使用方法和源码解析——私有属性代码测试技术分析

    有些时候,我们不仅要测试类暴露出来的公有方法,还要测试其受保护的或者私有方法.GTest测试框架提供了一种方法,让我们可以测试类的私有方法.但是这是一种侵入式的,会破坏原来代码的结构,所以我觉得还是谨 ...

  4. Google Test(GTest)使用方法和源码解析——预处理技术分析和应用

    预处理 在<Google Test(GTest)使用方法和源码解析--概况>最后一部分,我们介绍了GTest的预处理特性.现在我们就详细介绍该特性的使用和相关源码.(转载请指明出于brea ...

  5. Google Test(GTest)使用方法和源码解析——断言的使用方法和解析

    在之前博文的基础上,我们将介绍部分断言的使用,同时穿插一些源码.(转载请指明出于breaksoftware的csdn博客) 断言(Assertions) 断言是GTest局部测试中最简单的使用方法,我 ...

  6. Google Test(GTest)使用方法和源码解析——Listener技术分析和应用

    在<Google Test(GTest)使用方法和源码解析--结果统计机制分析>文中,我么分析了GTest如何对测试结果进行统计的.本文我们将解析其结果输出所使用到的Listener机制. ...

  7. Google Test(GTest)使用方法和源码解析——结果统计机制分析

    在分析源码之前,我们先看一个例子.以<Google Test(GTest)使用方法和源码解析--概况 >一文中最后一个实例代码为基准,修改最后一个"局部测试"结果为错误 ...

  8. Google Test(GTest)使用方法和源码解析——自动调度机制分析

    在<Google Test(GTest)使用方法和源码解析--概况 >一文中,我们简单介绍了下GTest的使用和特性.从这篇博文开始,我们将深入代码,研究这些特性的实现.(转载请指明出于b ...

  9. Google Test(GTest)使用方法和源码解析——概况

    GTest是很多开源工程的测试框架.虽然介绍它的博文非常多,但是我觉得可以深入到源码层来解析它的实现原理以及使用方法.这样我们不仅可以在开源工程中学习到实用知识,还能学习到一些思想和技巧.我觉得有时候 ...

最新文章

  1. 【Android 应用开发】Google 官方 EasyPermissions 权限申请库 ( 简介 | 权限申请处理细节 | 添加依赖 | 界面权限申请结果处理 | 权限申请结果回调接口 )
  2. C# 如何获取屏幕分辨率缩放比例
  3. (pytorch-深度学习系列)使用softmax回归实现对Fashion-MNIST数据集进行分类-学习笔记
  4. java arraylist6_java 集合 ArrayList
  5. 初步理解NServiceBus
  6. mysql 优化-总结
  7. vuex状态持久化_Vuex数据状态持久化-vuex-persistedstate
  8. 2018 IEEE International Conference on Cyborg and Bionic Systems (CBS)国际会议的组织和参入感悟
  9. 通信工程cdma篇-网优网规基础
  10. Salesforce chatter:userPhotoUpload Component 使用
  11. ZXing二维码自定义绘画文字
  12. 最先进的Git分布式仓库系统——是如何提升编程效率的?
  13. cf 830 D1. Balance (Easy version)
  14. 【AI视野·今日CV 计算机视觉论文速览 第157期】Mon, 16 Sep 2019
  15. matlab pi表示,在matlab绘图中,x=0:0.1:4*pi;此语句中,0,0.1,4*... MATLAB中,x=0:pi/100:2*pi;表示什么意思?...
  16. openGauss十月社区运作报告
  17. Sql Server 字符串、日期函数 收藏
  18. TeamViewer账号未激活问题
  19. G - Gluttonous Goop
  20. properties中的编码如何生成:例如\u7AD9\u70B9这种

热门文章

  1. 感恩节|感恩有您,一路相伴
  2. 4.0、软件测试——等价类划分以及练习
  3. 2022年终总结-找回初心
  4. 微信群运营7大运营要点,了解一下?
  5. Docker配置镜像加速(CentOS 7系统)
  6. GIS-WKT、WKB与GeoJSON
  7. 数组和链表的区别详解
  8. jmockit,mockito和powermock
  9. 删除数据库中的重复数据,只保留一条
  10. 全媒体运营师胡耀文教你:怎样让“用户留存分析模型”更好用