• Android-Binder(一)


    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有一个更清晰的认知,所以我们来看一看系统的分层

    2628445-566420f14d7f4c79.png | left | 486x740

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

    • 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。其调用关系如下:

    image.png | left | 794x112

    从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目录,随便输入一名称,建立起目录解构即可,然后把文件删掉,我们自家定义我们自己的文件

    image.png | left | 784x577

    建立实体类映射文件 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);
    }
    
    

    整体目录解构如下

    image.png | left | 452x531

    编译成功后会在 项目路径appuildgeneratedsourceaidldebug oplittledavidstudyipc (包名可能不同)下生成一个 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() + "
    ")
            }
            this.bookInfoTV.text = stringBuilder.toString()
        }
    
        override fun onDestroy() {
            super.onDestroy()
            this.unbindService(mConn)
        }
    }
    

    总结

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

  • 相关阅读:
    flex 图表使用百分比示例
    flex 图标设置百分比或者其它符号
    大学生求职(打油诗一首)
    flex 图表categoryField设置 labelFunction使用
    如何配置EclipseMe
    google chart图表使用
    Codeforces #Round 632 div2 A~C
    牛客的两道dfs
    约数
    Atcoder ABC162 D RGB Triplets
  • 原文地址:https://www.cnblogs.com/slyfox/p/9392443.html
Copyright © 2020-2023  润新知