知识总结 插件化学习 Binder机制原理

Binder是android系统特有IPC方式,安卓平台中的各种服务交互基本都是Binder机制实现,理解和掌握Binder机制的实现原理可有效提升软件性能优化点,同时Binder机制的应用也是动态代理方式实现插件化基础。

安卓插件化学习 Binder机制原理分析

网上虽然已有很多Binder类似的优秀分析,本文处于自我学习目的,把我学理解和认识的东西记录一下。
Binder属于android平台特有的IPC通道,也是进程间数据交互的核心内容。
安卓平台IPC方式总的来说有5种:1、文件操作;2、Messenger;3、Provider; 4、AIDL;5、Socket。
这五种方式中,2、3、4的实现都用到了Binder机制,这里主要以AIDL的使用讲解Binder。

Binder设计结构理解

1、通信进程两端两个重要对象:一个是本地端的Proxy远程引用对象,一个是远程端的Stub实体对象
2、client端Proxy对象可以根据所定义的继承IInterface接口的相关约定方法来操作server端Stub实体类。
3、Android中在使用系统服务的时候通过getSystemService方法获取到的其实都是Stub把远端的Binder转化的对象,因为系统服务都是在system_server进程中,所以肯定是跨进程获取对象的,那么这个Binder对象其实就是上面的Proxy对象
4、除client和Proxy进程外,还存在者一个serverManager所在的进程(0号引用获取),用来存储proxy引用与stub实体的对应关系。
5、简单理解:ProxyBinder的transact方法调用后会同步(可异步)调用到Stub类的onTransact.这中间进程间数据的一次拷贝都是在系统空间的Binder驱动中完成。

image.png

Binder的使用

Binder的使用基本存在与多进程的App中,大家工作的项目中很可能甚少接触底层数据在进程间的传递,特别是业务需求多的应用。然后本地工具类应用如卫士类的产品研发会很经常的应用到Binder,并且会在不同的场合自定义Binder的数据传递方式,这里也很感谢之前工作项目“手机卫士”的实际应用机会。

标准AIDL使用Binder

AIDL( Android Interface definition language)安卓进程间通信接口语言,我们可以通过这种方式定义接口,完成两个或多个进程间的信息传递。

1. 定义.aidl 接口文件

首先要定义进程间需要完成什么操作,传递什么数据,根据需求定义方法接口。

    package com.canking.binder.aidl;    
    import com.canking.binder.aidl.Data;  
        interface AIDLService {     
          void setData(Data cb);     
    }    

2. 编译项目生产java文件

定义完.aidl 文件有,通过as build项目后,IDE会帮我们生产对应的java文件在gen目录下。

    public interface AIDLService extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.canking.binder.aidl.AIDLService {
        private static final java.lang.String DESCRIPTOR = "com.canking.binder.aidl.AIDLService";

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.canking.binder.aidl.AIDLService,
         * generating a proxy if needed.
         */
        public static com.canking.binder.aidl.AIDLService asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.canking.binder.aidl.AIDLService))) {
                return ((com.canking.binder.aidl.AIDLService) iin);
            }
            return new com.canking.binder.aidl.AIDLService.Stub.Proxy(obj);
        }

        @Override
        public android.os.IBinder asBinder() {
            return this;
        }

        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_onCallback: {
                    data.enforceInterface(DESCRIPTOR);
                    android.os.Bundle _arg0;
                    if ((0 != data.readInt())) {
                        _arg0 = android.os.Bundle.CREATOR.createFromParcel(data);
                    } else {
                        _arg0 = null;
                    }
                    android.os.Bundle _result = this.setData(_arg0);
                    reply.writeNoException();
                    if ((_result != null)) {
                        reply.writeInt(1);
                        _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
                    } else {
                        reply.writeInt(0);
                    }
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.canking.binder.aidl.AIDLService {
            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;
            }

            @Override
            public android.os.Bundle onCallback(android.os.Bundle extra) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                android.os.Bundle _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    if ((extra != null)) {
                        _data.writeInt(1);
                        extra.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_onCallback, _data, _reply, 0);
                    _reply.readException();
                    if ((0 != _reply.readInt())) {
                        _result = android.os.Bundle.CREATOR.createFromParcel(_reply);
                    } else {
                        _result = null;
                    }
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_onCallback = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }

    public android.os.Bundle setData(android.os.Bundle extra) throws android.os.RemoteException;
    }

3. 定义远端实体对象

     public class AIDLServiceImpl extends AIDLService.Stub {
       @Override
       public boolean setData() {
        doSomeThing();
        return true;
       }
     }
     
    @Override
    public IBinder onBind(Intent intent) {
        return AIDLServiceImpl;
    }

继承Stub类实现方法,并且通过Service的onBind()或Provider的call()提供接口返回给client端。

当然,也可以不定义aidl文件,自己定义Stub类及proxy类,好处是按照自己的需求自定义Stub的达到自定义Parcel读取方式及实现逻辑来解决一些业务需求问题,比如复杂继承类的传递。

4. Client端获取远端ProxyBinder

3中定义好Binder对象后,这个Binder就可以跨进程调用类,获取这个远端binder引用的方法有很多,利用Service启动方法中的ServiceConnection来返回onBinder里的对象。或者用Provider的call根据标记返回指定Binder对象(封装在Bundle中)。

安卓源码ServiceManager分析

ServiceManager是一个全局的manager、调用了Jni函数,实现addServicew getService checkService listService等函数,
Server进程先注册一些service到SercviceManager中。
Client想获得一些service,就要到Service中去获取该Service。
这样,Server和Client之间就可以进行通讯了,
Server和Client之间的通讯都是通过Binder进行的。

——————
欢迎转载,请标明出处:常兴E站 www.canking.win

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,710评论 4 376
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,839评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,295评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,776评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,198评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,074评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,200评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,986评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,733评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,877评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,348评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,675评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,393评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,209评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,212评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,003评论 2 280

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,112评论 18 139
  • 原文:http://weishu.me/2016/01/12/binder-index-for-newer/ 要点...
    指尖流逝的青春阅读 2,587评论 0 13
  • 毫不夸张地说,Binder是Android系统中最重要的特性之一;正如其名“粘合剂”所喻,它是系统间各个组件的桥梁...
    weishu阅读 17,565评论 29 246
  • Binder浅析 1. 背景知识 Binder在Android系统中是用来进行进程间通信的,所以在介绍Binder...
    蕉下孤客阅读 2,185评论 0 8
  • Binder牌胶水,如雷贯耳,在Android中无处不在,是每个Android程序猿居家旅行必备。有了它的存在,我...
    geniusmart阅读 3,765评论 5 30