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的面向对象-类的数据属性和实例的数据属性相结合-无命名看你懵逼不懵逼系列

    1. class Chinese: country='China' def __init__(self,name): self.name=name def play_ball(self,ball): ...

  2. python教程2:list和tuple

    list和tuple都是数组,区别在于list可以随意增删改查,而tuple在赋值了之后只能查看了,所以tuple是比较安全的相对于list来说 list 定义一个list数组,名字就叫list,可以 ...

  3. JavaScript继承详解(一)

    面向对象与基于对象 几乎每个开发人员都有面向对象语言(比如C++.C#.Java)的开发经验. 在传统面向对象的语言中,有两个非常重要的概念 - 类和实例. 类定义了一类事物公共的行为和方法:而实例则 ...

  4. shell 循环数组

    循环数组 ;i<${#o[*]};i++)) do echo ${o[$i]} done

  5. opacity设定图片透明度

    实例 1 - 创建透明图像 定义透明效果的 CSS3 属性是 opacity. 首先,我们将展示如何通过 CSS 来创建透明图像. 常规图像: 带有透明度的相同图像: 请看下面的 CSS: img { ...

  6. JavaScript 中创建三种消息框:警告框、确认框、提示框。

    网址:http://www.w3school.com.cn/js/js_popup.asp 警告框 警告框经常用于确保用户可以得到某些信息. 当警告框出现后,用户需要点击确定按钮才能继续进行操作. 语 ...

  7. python的一个小原理

    在许多语言当中,类似于a.b()这样的调用方法是一个整体,但在Python中,它其实是两部分:获取属性a.b,调用().所以也可以写成: c = a.b c() 2.关于继承 class a: num ...

  8. JDK1.8源码Collections

    正文: 一.概述: 此类完全由在 collection 上进行操作或返回 collection 的静态方法组成.它包含在 collection 上操作的多态算法,即“包装器”,包装器返回由指定 col ...

  9. Linux Core Dump【转】

    转自:http://www.cnblogs.com/hazir/p/linxu_core_dump.html 当程序运行的过程中异常终止或崩溃,操作系统会将程序当时的内存状态记录下来,保存在一个文件中 ...

  10. 源码安装svn 1.8.9

    2014年5月25日 12:26:14 需要文件: svn apr apr-util sqlite3 serf svn : http://subversion.apache.org/download/ ...