Android-Binder(一)

学习自

《Android开发艺术探索》

https://www.jianshu.com/p/bdef9e3178c9

https://blog.csdn.net/u011240877/article/details/72765136

Binder漫谈

Binder是IBinder接口的一个实现类,inder是连接系统的各种Manager和其对应的Service的桥梁,Binder主要用于Service中。

Android系统的分层

对Android系统的分层了解了之后,我们会对IPC有一个更清晰的认知,所以我们来看一看系统的分层

我们来依次看一下各层的职责:

  • Linux Kernel(Linux内核层), 这一层中主要是各种硬件的驱动,Binder IPC的驱动也是在此层的
  • HAL(硬件抽象层),对内核层的封装,为系统服务层提提供可调用的接口,以JNI的方式。
  • Android System Service(Android 系统服务层), Android系统的核心服务,为应用层提供调用的接口
  • Binder IPC Proxys(Binder IPC的代理层),是应用层和系统服务层之间的桥梁,实现跨进程通信
  • Application Freamwork(应用程序框架层), 这一程就是我们的SDK,提供我们日常开发所用到的类库

其中Linux内核层好硬件抽象层,都是以C/C++来实现,硬件抽象层会编译为so文件,已JNI的方式提供给系统服务层调用,系统服务层通过Java实现,该层中的服务随着手机的开机而启动(不关机就会一直运行),这些服务负责Activity的管理,Window的管理等等。因为系统服务层是通过Java实现的所以,他们肯定是运行与一个独立的 Dalvik 中。

因为我们程序员自己开发的程序和系统的服务都分别运行在不同的虚拟机中,之间的通信就只能靠 IPC技术来完成了,为了方便Coder调用系统服务接口Google提供了一系统服务相对应的Manager。其调用关系如下:

从AIDL开始

AIDL(Android Interface Definition Language) Androd 接口定义语言,通过AIDL可以实现IPC,通过AIDL定义的接口我们可以完成客户端和服务的跨进程通信,使用了AIDL的话在编译的时候系统会自动帮我们生成 Binder .

AIDL支持的数据类型

  1. Java 的基本数据类型
  2. List 和 Map
    • 元素必须是 AIDL 支持的数据类型
    • Server 端具体的类里则必须是 ArrayList 或者 HashMap
  3. 其他 AIDL 生成的接口
  4. 实现 Parcelable 的实体

建立AIDL相关的文件

建立需要的实体类 Book 实现Parcelable接口

package top.littledavid.studyipc.beans

import android.os.Parcel
import android.os.Parcelable /**
* Created by IT on 7/30/2018.
*/
class Book(val bookId: Int, val bookName: String, val author: String) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readInt(),
parcel.readString(),
parcel.readString()) {
} override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeInt(bookId)
parcel.writeString(bookName)
parcel.writeString(author)
} override fun describeContents(): Int {
return 0
} override fun toString(): String {
return "Book(bookId=$bookId, bookName='$bookName', author='$author')"
} companion object CREATOR : Parcelable.Creator<Book> {
override fun createFromParcel(parcel: Parcel): Book {
return Book(parcel)
} override fun newArray(size: Int): Array<Book?> {
return arrayOfNulls(size)
}
}
}

建立AIDL目录,随便输入一名称,建立起目录解构即可,然后把文件删掉,我们自家定义我们自己的文件

建立实体类映射文件 Book.aidl 要在aidl 下与Book 实体类相同的包下才行,否则会报错,无法通过编译,实体类的包接口是 top.littledavid.studyipc.beans->beans 所以aidl下的 Book.aidl包也要一样才行

//实体映射包名一定要和实体定义的包名相同
package top.littledavid.studyipc.beans;
//定义映射
parcelable Book;

定义 IBookManager.aidl 其中定义了IPC操作的方法

// IBookManager.aidl
package top.littledavid.studyipc; // Declare any non-default types here with import statements
import top.littledavid.studyipc.beans.Book; interface IBookManager {
List<top.littledavid.studyipc.beans.Book> getBookList();
//这是如果不是使用的基础数据类型,一定要使用方向类型标识 : in ,out ,inout
void addBook(in Book book);
}

整体目录解构如下

编译成功后会在 项目路径\app\build\generated\source\aidl\debug\top\littledavid\studyipc (包名可能不同)下生成一个 IBookManager.java ,其中实现了IPC相关的代码。

建立Service

class BookService : Service() {
private lateinit var mBookList: MutableList<Book> override fun onBind(intent: Intent?): IBinder {
mBookList = mutableListOf()
Log.e("TAG", "OnBind")
return mIBinder
} //实现AIDL定义的接口
private val mIBinder = object : IBookManager.Stub() {
override fun getBookList(): List<Book> {
return this@BookService.mBookList.toList()
} override fun addBook(book: Book) {
this@BookService.mBookList.add(book)
}
}
}

在Minefast文件中配置服务

<service
android:name=".BookService"
android:enabled="true"
android:exported="true"
android:process=":remote" />

进行IPC

在Activity中进行IPC

class MainActivity : AppCompatActivity() {
private var mIBookManager: IBookManager? = null private val mConn = object : ServiceConnection {
override fun onServiceDisconnected(name: ComponentName?) {
mIBookManager = null
} override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
//将IBinder转换为AIDL接口
mIBookManager = IBookManager.Stub.asInterface(service)
}
} override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//开启服务
val serviceBindIntent = android.content.Intent(this, BookService::class.java)
this.bindService(serviceBindIntent, mConn, Context.BIND_AUTO_CREATE)
} //添加书籍信息
fun addBook(view: View) {
val book = Book(1, "Android开发艺术探索", "任玉刚老师")
this.mIBookManager!!.addBook(book) loadBookInfo()
} private fun loadBookInfo() {
val bookList = mIBookManager!!.bookList
val stringBuilder = StringBuilder()
bookList.forEach {
stringBuilder.append(it.toString() + "\r\n")
}
this.bookInfoTV.text = stringBuilder.toString()
} override fun onDestroy() {
super.onDestroy()
this.unbindService(mConn)
}
}

总结

磕磕绊绊的总算完成了AIDL的IPC,非常感谢参考文档中国的博主的无私奉献。下一章我们来看一看Binder的原理。

Android-Binder(一)的更多相关文章

  1. [转]Android Binder设计与实现 - 设计篇

    摘要 Binder是Android系统进程间通信(IPC)方式之一.Linux已经拥有管道,system V IPC,socket等IPC手段,却还要倚赖Binder来实现进程间通信,说明Binder ...

  2. (转)Android Binder设计与实现 – 设计篇

    原文地址(貌似已打不开):Android Binder设计与实现 – 设计篇 ------------------------------------------------------------- ...

  3. 图解Android - Binder 和 Service

    在 Zygote启动过程 一文中我们说道,Zygote一生中最重要的一件事就是生下了 System Server 这个大儿子,System Server 担负着提供系统 Service的重任,在深入了 ...

  4. Android Binder设计与实现 - 设计篇

    要 Binder是Android系统进程间通信(IPC)方式之一.Linux已经拥有管道,system V IPC,socket等IPC手段,却还要倚赖Binder来实现进程间通信,说明Binder具 ...

  5. Android Binder机制详解:手写IPC通信

    想要掌握一样东西,最好的方式就是阅读理解它的源码.想要掌握Android Binder,最好的方式就是写一个AIDL文件,然后查看其生成的代码.本文的思路也是来自于此. 简介 Binder是Andro ...

  6. Android开发之漫漫长途 Ⅷ——Android Binder(也许是最容易理解的)

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  7. Android Binder IPC详解-Android学习之旅(96)

    linux内存空间与BInder Driver Android进程和linux进程一样,他们只运行在进程固有的虚拟空间中.一个4GB的虚拟地址空间,其中3GB是用户空间,1GB是内核空间 ,用户空间是 ...

  8. ANDROID BINDER机制浅析

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

  9. (原创)Android Binder设计与实现 - 实现篇(1)

    本文属于原创作品,转载请注明出处并放于明显位置,原文地址:http://www.cnblogs.com/albert1017/p/3849585.html 前言 在学习Android的Binder机制 ...

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

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

随机推荐

  1. Python基础数据类型-字典(dict)

    Python基础数据类型-字典(dict) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客使用的是Python3.6版本,以及以后分享的每一篇都是Python3.x版本的哟 ...

  2. 数据库类型与JDBC TYPE 和Java类型对应关系

    https://blog.csdn.net/seelye/article/details/40105969

  3. [原]JUnit 自定义扩展思路

    1. 理解Annotation,http://www.cnblogs.com/mandroid/archive/2011/07/18/2109829.html 2. JUNIT整体执行过程分析,htt ...

  4. J2EE规范 - 13种规范

    J2EE是由SUN提出的用于简化开发企业级应用程序的一系列规范的组合,J2EE基于中间层集成的框架的方式为应用开发提供了一个统一的开发平台.基于容器管理.组件化的模型为企业建立一个高可用性,高可靠性可 ...

  5. java整理的一些面试资料

    平时逛博客的时候收集了一些认为不错的java面试题  以后跳槽的时候可以来这里刷一刷 1:后端技术精选 https://www.cnblogs.com/javazhiyin/tag/Java面试题/

  6. 存储之磁盘阵列RAID

         存储之磁盘阵列RAID RAID是由美国加州大学伯克利分校的D.A. Patterson教授在1988年提出的.RAID名为独立冗余磁盘阵列(RedundantArray of Indepe ...

  7. oracle数据库如何创建用户和角色,并给其赋权?

    一.创建用户并赋予权限 1.创建用户 create user wangxiangyu identified by wangxiangyu; 2.赋权 grant dba to wangxiangyu; ...

  8. 特性(C# 和 Visual Basic)

    特性提供功能强大的方法,用以将元数据或声明信息与代码(程序集.类型.方法.属性等)相关联. 特性与程序实体关联后,即可在运行时使用名为“反射”的技术查询特性. 有关更多信息,请参见 反射(C# 和 V ...

  9. DOM事件阶段以及事件捕获与事件冒泡先后执行顺序

    平时浏览这么多技术文章,如过不去实践.深入弄透它,这个技术点很快就会在脑海里模糊.要加深印象,就得好好过一遍.重要的事情说三遍,重要的知识写一遍. 开发过程中我们都希望使用别人成熟的框架,因为站在巨人 ...

  10. 浅谈js设计模式 — 命令模式

    命令模式最常见的应用场景是:有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么.此时希望用一种松耦合的方式来设计程序,使得请求发送者和请求接收者能够消除彼此之间的耦 ...