Android 进阶技术篇专题Android Framework源码分析Android框架

Android Binder机制扫盲

2018-06-13  本文已影响11人  01_小小鱼_01

由于Android系统保护机制(沙箱机制),两个进程是各自运行在自己的进程空间之中的,相互之间进行隔离并不能够直接进行通讯(确保一个进程挂掉了,不会影响另外一个进程的运行)。

一、为什么使用Binder机制

Android系统是基于Linux系统的,我们知道Linux 系统之中常见的进程之间的通讯就有共享内存、消息队列、管道、Socket等。那为什么Android 系统不直接采用Linux 的进程之间的通讯方式,而是采用Binder机制,C/S模式来实现进程之间的通讯呢?

我想主要有以下三个方面的原因。

二、几个重要的概念
Binder中各角色之间关系
三、AIDL 示例

在Android开发过程中,我们一般是采用编写AIDL文件的形式来描述服务器提供哪些接口。
IDataManager.aidl 文件

// 无论应用的类是否和aidl文件在同一包下,都需要显示import
import org.github.lion.aidl_demo.Data;
interface IDataManager {
    /** AIDL 支持的数据类型划分为四类
     * 第一类是 Java 编程语言中的基本类型
     * 第二类包括 String、List、Map 和 CharSequence
     * 第三类是其他 AIDL 生成的 interface
     * 第四类是实现了 Parcelable protocol 的自定义类
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean
                    , float aFloat, double aDouble, String aString);
    int getDataTypeCount();
    List<Data> getData();
    String getUrlContent(String url);
}

自定义实现Parcelable接口类型

/** 必须实现Parcelable接口
 *  1. 定义CREATOR对象
 */
public class Data implements Parcelable {

    ...

    protected Data(Parcel in) {
        ...
    }

    public static final Creator<Data> CREATOR = new Creator<Data>() {
        @Override
        public Data createFromParcel(Parcel in) {
            return new Data(in);
        }

        @Override
        public Data[] newArray(int size) {
            return new Data[size];
        }
    };
}

服务端的实现

private static final IDataManager.Stub mBinder = new IDataManager.Stub() {

    @Override
    public void basicTypes(int anInt, long aLong, boolean aBoolean
                           , float aFloat, double aDouble, String aString) 
                           throws RemoteException {
    }

    @Override
    public int getDataTypeCount() throws RemoteException {
        // todo return some data
        return 0;
    }

    @Override
    public List<Data> getData() throws RemoteException {
        // todo return some data
        return null;
    }

    @Override
    public String getUrlContent(String url) throws RemoteException {
        // todo return some data
        return null;
    }
};

@Override
public IBinder onBind(Intent intent) {
    return mBinder;
}

客户端实现

private IDataManager dataManagerService = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    // 绑定服务
    bindService(new Intent(this, DataManagerService.class), dataServiceConnection,
            Context.BIND_AUTO_CREATE);
}

private ServiceConnection dataServiceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {       
        // 返回IBinder 对象,封装为代理类
        dataManagerService = IDataManager.Stub.asInterface(service);
    }
    @Override
    public void onServiceDisconnected(ComponentName name) {
        dataManagerService = null;
    }
};

接下来我们看看Android Studio帮我们自动生成的Java文件里面的内容。

// IDataManager2 直接继承了IInterface
public interface IDataManager2 extends IInterface {
    // 返回值为基本数据类型,定义接口时不需要做特殊处理
    int getDataCount() throws RemoteException;
    // 自定义的返回数据类型需要实现Parcelable接口,进程间通信不能直接共享内存,需要将对象持久化。
    // 所以自定义的类需要实现Parcelable接口
    List<Data2> getData() throws RemoteException;
}

//内部抽象类集成Binder实现了IDataManager2(Stub)接口
public abstract class DataManagerNative extends Binder implements IDataManager2 {

    // Binder描述符,唯一标识符
    private static final String DESCRIPTOR = "com.github.onlynight.aidl_demo2.aidl.IDataManager2";

    // 每个方法对应的ID
    private static final int TRANSACTION_getDataCount = IBinder.FIRST_CALL_TRANSACTION;
    private static final int TRANSACTION_getData = IBinder.FIRST_CALL_TRANSACTION + 1;

    public DataManagerNative() {
        attachInterface(this, DESCRIPTOR);
    }

    /**
     * 将Binder转化为IInterface接口
     *
     * @param binder
     * @return
     */
    public static IDataManager2 asInterface(IBinder binder) {
        if (binder == null) {
            return null;
        }
        //同一进程内直接返回
        IInterface iin = binder.queryLocalInterface(DESCRIPTOR);
        if ((iin != null) && (iin instanceof IDataManager2)) {
            return (IDataManager2) iin;
        }

        //不在同一进程使用代理获取远程服务
        return new Proxy(binder);
    }

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

    /**
     * 我们查看Binder的源码就可以看出实际上transact方法真正的执行体
     * 是这个onTransact方法。
     *
     * @param code  服务器回掉的方法ID,每一个方法都有一个唯一id,
     *              这样方法回调时可通过id判断回调的方法。
     * @param data  输入的参数,传递给服务端的参数
     * @param reply 输出的参数,服务器返回的数据
     * @param flags 默认传入0
     * @return
     * @throws RemoteException 远端服务器无响应抛出该错误。
     */
    @Override
    protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        switch (code) {
            case TRANSACTION_getDataCount: {
                data.enforceInterface(DESCRIPTOR);
                int _result = this.getDataCount();
                reply.writeNoException();
                reply.writeInt(_result);
                return true;
            }
            case TRANSACTION_getData: {
                data.enforceInterface(DESCRIPTOR);
                List<Data2> _result = this.getData();
                reply.writeNoException();
                reply.writeTypedList(_result);
                return true;
            }
        }
        return super.onTransact(code, data, reply, flags);
    }

    /**
     * 代理类,调用transact方法。
     */
    private static class Proxy implements IDataManager2 {

        private IBinder remote;

        Proxy(IBinder remote) {
            this.remote = remote;
        }

        public String getInterfaceDescriptor() {
            return DESCRIPTOR;
        }

        @Override
        public int getDataCount() throws RemoteException {
            // 输入参数
            Parcel _data = Parcel.obtain();

            //输出参数
            Parcel _reply = Parcel.obtain();
            int _result;
            try {
                _data.writeInterfaceToken(DESCRIPTOR);
                remote.transact(TRANSACTION_getDataCount, _data, _reply, 0);
                _reply.readException();
                _result = _reply.readInt();
            } finally {
                _reply.recycle();
                _data.recycle();
            }
            return _result;
        }

        @Override
        public List<Data2> getData() throws RemoteException {
            Parcel _data = Parcel.obtain();
            Parcel _reply = Parcel.obtain();
            List<Data2> _result;
            try {
                _data.writeInterfaceToken(DESCRIPTOR);
                remote.transact(TRANSACTION_getData, _data, _reply, 0);
                _reply.readException();
                _result = _reply.createTypedArrayList(Data2.CREATOR);
            } finally {
                _reply.recycle();
                _data.recycle();
            }
            return _result;
        }

        @Override
        public IBinder asBinder() {
            return remote;
        }
    }
}

参考博客:
1. binder守护进程servicemanager简介
2. Android Binder机制(一) Binder的设计和框架
3. 一篇文章了解相见恨晚的 Android Binder 进程间通讯机制

上一篇下一篇

猜你喜欢

热点阅读