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

栏目: Android · 发布时间: 6年前

内容简介:知识总结 插件化学习 Binder机制原理

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

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

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

网上虽然已有很多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驱动中完成。

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

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 AIDLServiceextends android.os.IInterface{
/**
 * Local-side IPC implementation stub class.
 */
public static abstract class Stubextends android.os.Binderimplements 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.AIDLServiceasInterface(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.IBinderasBinder(){
        return this;
    }

    @Override
    public boolean onTransact(intcode, android.os.Parcel data, android.os.Parcel reply,intflags)throwsandroid.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 Proxyimplements com.canking.binder.aidl.AIDLService{
        private android.os.IBinder mRemote;

        Proxy(android.os.IBinder remote) {
            mRemote = remote;
        }

        @Override
        public android.os.IBinderasBinder(){
            return mRemote;
        }

        public java.lang.StringgetInterfaceDescriptor(){
            return DESCRIPTOR;
        }

        @Override
        public android.os.BundleonCallback(android.os.Bundle extra)throwsandroid.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.BundlesetData(android.os.Bundle extra)throwsandroid.os.RemoteException;
}

3. 定义远端实体对象

 public class AIDLServiceImplextends 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


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

屏幕上的聪明决策

屏幕上的聪明决策

Shlomo Benartzi、Jonah Lehrer / 石磊 / 北京联合出版公司 / 2017-3 / 56.90

 为什么在手机上购物的人,常常高估商品的价值?  为什么利用网络订餐,人们更容易选择热量高的食物?  为什么网站上明明提供了所有选项,人们却还是选不到最佳的方案?  屏幕正在改变我们的思考方式,让我们变得更冲动,更容易根据直觉做出反应,进而做出错误的决策。在《屏幕上的聪明决策》一书中,什洛莫·贝纳茨教授通过引人入胜的实验及案例,揭示了究竟是什么影响了我们在屏幕上的决策。 ......一起来看看 《屏幕上的聪明决策》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具