Android-Binder原理浅析

学习自

《Android开发艺术探索》

写在前头

在上一章,我们简单的了解了一下Binder并且通过 AIDL完成了一个IPC的DEMO。你可能会好奇为什么,上一章说是介绍Binder大的IPC通信呢,为什么又扯到AIDL了,通过本章就可以解除我们的疑惑。

IBookManager

在上一章中,说到了使用AIDL成功编译后会生成一个.Java的文件,我们的Dome中生成的文件是 IBookManager.java 下面我们来看一下其中的源码,如下所示(生成的代码没有缩进,找了个工具格式化了一下). 其中主要的地方都写了注释。

/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: F:\\MyCode\\Android\\StudyIPC\\app\\src\\main\\aidl\\top\\littledavid\\studyipc\\IBookManager.aidl
*/
package top.littledavid.studyipc; public interface IBookManager extends android.os.IInterface {
public java.util.List<top.littledavid.studyipc.beans.Book> getBookList()
throws android.os.RemoteException; //这是如果不是使用的基础数据类型,一定要使用方向类型标识 : in ,out ,inout
public void addBook(top.littledavid.studyipc.beans.Book book)
throws android.os.RemoteException; /** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements top.littledavid.studyipc.IBookManager {
//Binder的唯一标识
private static final java.lang.String DESCRIPTOR = "top.littledavid.studyipc.IBookManager";
//方法的标识
static final int TRANSACTION_getBookList = (android.os.IBinder.FIRST_CALL_TRANSACTION +
0);
//方法的标识
static final int TRANSACTION_addBook = (android.os.IBinder.FIRST_CALL_TRANSACTION +
1); /** Construct the stub at attach it to the interface. */
public Stub() {
this.attachInterface(this, DESCRIPTOR);
} /**
* Cast an IBinder object into an top.littledavid.studyipc.IBookManager interface,
* generating a proxy if needed.
* 将IBinder对象转化为我们定义的AIDL接口,如果需要的话则生成代理类
*/
public static top.littledavid.studyipc.IBookManager asInterface(
android.os.IBinder obj) {
if ((obj == null)) {
return null;
} android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); /**
如果iin不为null表示Binder运行与本地进程
否则则是运行在其他的进程
则通过代理来实现通信
*/
if (((iin != null) &&
(iin instanceof top.littledavid.studyipc.IBookManager))) {
return ((top.littledavid.studyipc.IBookManager) iin);
} return new top.littledavid.studyipc.IBookManager.Stub.Proxy(obj);
} @Override
public android.os.IBinder asBinder() {
return this;
} /**
此方法运行在服务端,处理我们的RPC
此方法如果返回为false那么客户端的请求将会失败
可以利用此方法来做权限验证
*/
@Override
public boolean onTransact(int code, android.os.Parcel data,
android.os.Parcel reply, int flags)
throws android.os.RemoteException {
//根据code的不同调用不同的方法
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR); return true;
} case TRANSACTION_getBookList: {
data.enforceInterface(DESCRIPTOR); java.util.List<top.littledavid.studyipc.beans.Book> _result = this.getBookList();
reply.writeNoException();
reply.writeTypedList(_result); return true;
} case TRANSACTION_addBook: {
data.enforceInterface(DESCRIPTOR); top.littledavid.studyipc.beans.Book _arg0;
//从_data中取得参数调用
if ((0 != data.readInt())) {
_arg0 = top.littledavid.studyipc.beans.Book.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
} this.addBook(_arg0);
reply.writeNoException(); return true;
}
} return super.onTransact(code, data, reply, flags);
} private static class Proxy implements top.littledavid.studyipc.IBookManager {
private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) {
mRemote = remote;
} @Override
public android.os.IBinder asBinder() {
return mRemote;
} public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
//getBookList的方法流程和addBook方法的流程相似
//这里就不多做解释
@Override
public java.util.List<top.littledavid.studyipc.beans.Book> getBookList()
throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.util.List<top.littledavid.studyipc.beans.Book> _result; try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getBookList, _data,
_reply, 0);
_reply.readException();
_result = _reply.createTypedArrayList(top.littledavid.studyipc.beans.Book.CREATOR);
} finally {
_reply.recycle();
_data.recycle();
} return _result;
} //这是如果不是使用的基础数据类型,一定要使用方向类型标识 : in ,out ,inout
@Override
public void addBook(top.littledavid.studyipc.beans.Book book)
throws android.os.RemoteException {
//方法的参数
android.os.Parcel _data = android.os.Parcel.obtain();
//方法的返回值
android.os.Parcel _reply = android.os.Parcel.obtain(); try {
_data.writeInterfaceToken(DESCRIPTOR);
//写入参数
if ((book != null)) {
_data.writeInt(1);
book.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
//发起RPC(远程调用请求)
mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
}
}

类的整体结构如下

首先是一个Java接口,该接口就是我们通过 AIDL 定义的接口,这个接口并没有什么特殊,其中的嵌套类才是我们需要注意的地方,Stub嵌套类继承自Binder同时也实现了IBookManager接口,是本地IPC的实现类,我们就是通过 asInterface 方法,获取IBookManager对象的实例完成IPC操作。在Stub的类中还有一个嵌套类,是一个代理类,这个代理类真正实现了我们在AIDL中定义的方法并完成了IPC通信。

类成员的详细的解释

__DECRIPTOR: __Binder的唯一标识一般使用全类名表示

__asInterface方法: __用户将服务端的Binder对象转化为客户端所需要的 AIDL对象,在此方法中分为两种情况,如果服务端和客户端位于同一个进程,那么返回的就是我们在Service中定义的Stub对象自身,否则返回封装后代理对象。

__asBinder方法: __返回当前的Binder对象

__onTransact方法: __此方法运行在服务端的Binder线程池中,当客户发起跨线程请求的时候,远程请求会通过系统的封装后,由此方法处理。此方法通过code参数来区分执行的方法时什么,如果需要当执行完毕后先_reply中写入返回值信息。如果此方法的返回值为false,那么请求会失败,我们可以在此方法中做权限的过滤。

__addBook方法: __getBookList方法和此方法的业务逻辑类似,所以这里仅仅介绍一种,在方法中首先会创建代表输入参数和返回值的Parcel对象_data和_reply,然后将方法所需的参数写入到_data中,紧接着就发送了远程调用请求,因为此方法并没有返回值,所以并没有来获取返回值。

Binder-IPC的流程

下面是一个IPC的简单的流程图,来自《Android开发艺术探索-55页》

总结

使用AIDL就是为了生成上面的那个类,AIDL只是提供了一种更为快捷的方式来生成上面的那个接口,其实我们完全可以自己动手写那个接口也可以完成IPC通信,并且在沙面的代码中我们发现了其中大量使用了Parcel类,这也是为什么我们的实体类要实现Parcelable接口的原因。关于手写IBookManager接口可以参考任玉刚老师的《Android开发艺术探索》,在这里我就不误导大家了。毕竟Binder是一个非常深入的概念如果深究的话会涉及到很多的Android底层的知识,我也不会

Android-Binder原理浅析的更多相关文章

  1. ANDROID BINDER机制浅析

    Binder是Android上一种IPC机制,重要且较难理解.由于Linux上标准IPC在灵活和可靠性存在一定不足,Google基于OpenBinder的设计和构想实现了Binder. 本文只简单介绍 ...

  2. Android Binder实现浅析-Binder驱动

    简介 Android是如何实现跨进程通信的,大家熟悉的Binder是什么,怎么设计的,进程间的数据如何发送接收的.本文将以及解析,并对Binder驱动实现.Native层实现.Java层实现三块做一个 ...

  3. Android Vsync 原理浅析

    Preface Android中,Client测量和计算布局,SurfaceFlienger(server)用来渲染绘制界面,client和server的是通过匿名共享内存(SharedClient) ...

  4. Android IdleHandler 原理浅析

    IdleHandler:空闲监听器(就像我没事做了,在群里发了个表情,这时候其他人就知道我很闲了) 在每次next获取消息进行处理时,发现没有可以处理的消息(队列空,只有延时消息并且没到时间,同步阻塞 ...

  5. Android aidl Binder框架浅析

      转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38461079 ,本文出自[张鸿洋的博客] 1.概述 Binder能干什么?B ...

  6. Binder的工作原理浅析

    在Android开发中,Binder主要用于Service中,包括AIDL和Messenger,其中Messenger的底层实现就是AIDL,所以我们这里通过AIDL来分析一下Binder的工作机制. ...

  7. 写给 Android 应用工程师的 Binder 原理剖析

    写给 Android 应用工程师的 Binder 原理剖析 一. 前言 这篇文章我酝酿了很久,参考了很多资料,读了很多源码,却依旧不敢下笔.生怕自己理解上还有偏差,对大家造成误解,贻笑大方.又怕自己理 ...

  8. 图文详解 Android Binder跨进程通信机制 原理

    图文详解 Android Binder跨进程通信机制 原理 目录 目录 1. Binder到底是什么? 中文即 粘合剂,意思为粘合了两个不同的进程 网上有很多对Binder的定义,但都说不清楚:Bin ...

  9. Android 进阶8:进程通信之 Binder 机制浅析

    读完本文你将了解: IBinder Binder Binder 通信机制 Binder 驱动 Service Manager Binder 机制跨进程通信流程 Binder 机制的优点 总结 Than ...

随机推荐

  1. SQL Server优化的方法

    SQL Server优化的方法<一>   查询速度慢的原因很多,常见如下几种:   1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷)   2.I/O吞吐量小,形成了 ...

  2. P3089 [USACO13NOV]POGO的牛Pogo-Cow

    P3089 [USACO13NOV]POGO的牛Pogo-Cow FJ给奶牛贝西的脚安装上了弹簧,使它可以在农场里快速地跳跃,但是它还没有学会如何降低速度. FJ觉得让贝西在一条直线的一维线路上进行练 ...

  3. 作为一个有B格的前端工程师需要掌握的一些知识

    如果说你3年还在不停地切页面的... 那么你对http协议的了解程度 你的原生的javascript的掌握程度 你的页面的优化的理念 你在写页面是否会有什么独特地技巧 你对ajax的get和post方 ...

  4. vue中,写在methods里的B方法去调A方法的数据,访问不到?

    今天在写项目的时候,发现了一个京城性忽略的问题,在vue的methods的方法里面定义了两个方法,如下: getTaskList() { api.growthDetails.taskList({ ap ...

  5. CSS Pseudo-classes

    先来一条金科玉律: 伪类的效果可以通过添加一个实际的类来达到:伪元素的效果可以通过添加一个实际的元素来达到. 第一部分,Pseudo-classes,伪类 一.链接系 (这个应该是最熟悉的啦.) a: ...

  6. 【源码阅读】VS调试mimikatz-改造法国神器mimikatz执行就获取明文密码

    0x1 概要 记得某位同学提起在XXX得到了一个一键生成明文的工具,觉得很是神奇... 然而我一看图标就知道是mimikatz,这工具是开源的,只要改两行代码就可以实现写死命令了. 顺带讲讲编译过程中 ...

  7. http和socket之长连接和短连接区别【转】

    转自:https://blog.csdn.net/mengyafei43/article/details/25195445 TCP/IP TCP/IP是个协议组,可分为三个层次:网络层.传输层和应用层 ...

  8. Android Studio引用第三方jar包(例如:使用LitePal)

    如何使用LitePal的教程网上很多,不过对于新手,这些教程中遗漏了将第三方jar包拷贝到app->libs路径下后,还需要add as library. 下载LitePal 这时操作步骤如下: ...

  9. 在VMware上安装Ubuntu软件步骤与遇到的相关问题及解决方案

    图解演示环境版本: 本机系统: WIN10 虚拟机:VMware Workstation 12(中文版) 安装目标:Ubuntu Desktop 12.04 LTS  (请点击这里)先下载好iso镜像 ...

  10. SNMP中MIB2所有主要节点

    系统组:system组包含以下对象集(.1.3.6.1.2.1.1): 对象名:sysDescr(1) OID:system.1 对象类型:DisplayString[255] 访问模式:只读 描述: ...