• 【Android】进程间通信IPC——Binder


    Binder是Android中的跨进程通信方式,bindService的时候,服务端返回Binder对象,通过该对象客户端可以从服务端获取数据。
    在进程间通信IPC——AIDL中创建了ICustomAidlInterface.aidl。
    以下是根据ICustomAidlInterface.aidl生成的ICustomAidlInterface.Java接口类。

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

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

    /**
    * Cast an IBinder object into an com.sjl.exercise.ICustomAidlInterface interface,
    * generating a proxy if needed.
    */
    public static com.sjl.exercise.ICustomAidlInterface asInterface(android.os.IBinder obj) {
    if ((obj == null)) {
    return null;
    }
    //④
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    if (((iin != null) && (iin instanceof com.sjl.exercise.ICustomAidlInterface))) {
    return ((com.sjl.exercise.ICustomAidlInterface) iin);
    }
    return new com.sjl.exercise.ICustomAidlInterface.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 {
    //③
    java.lang.String descriptor = DESCRIPTOR;
    switch (code) {
    case INTERFACE_TRANSACTION: {
    reply.writeString(descriptor);
    return true;
    }
    case TRANSACTION_getCurrentTime: {
    data.enforceInterface(descriptor);
    java.lang.String _result = this.getCurrentTime();
    reply.writeNoException();
    reply.writeString(_result);
    return true;
    }
    case TRANSACTION_insertUser: {
    data.enforceInterface(descriptor);
    com.sjl.exercise.bean.UserBean _arg0;
    if ((0 != data.readInt())) {
    _arg0 = com.sjl.exercise.bean.UserBean.CREATOR.createFromParcel(data);
    } else {
    _arg0 = null;
    }
    this.insertUser(_arg0);
    reply.writeNoException();
    return true;
    }
    case TRANSACTION_getUsers: {
    data.enforceInterface(descriptor);
    java.util.List<com.sjl.exercise.bean.UserBean> _result = this.getUsers();
    reply.writeNoException();
    reply.writeTypedList(_result);
    return true;
    }
    case TRANSACTION_clearUser: {
    data.enforceInterface(descriptor);
    this.clearUser();
    reply.writeNoException();
    return true;
    }
    default: {
    return super.onTransact(code, data, reply, flags);
    }
    }
    }

    private static class Proxy implements com.sjl.exercise.ICustomAidlInterface {
    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 java.lang.String getCurrentTime() throws android.os.RemoteException {
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    java.lang.String _result;
    try {
    _data.writeInterfaceToken(DESCRIPTOR);
    //⑤
    mRemote.transact(Stub.TRANSACTION_getCurrentTime, _data, _reply, 0);
    _reply.readException();
    _result = _reply.readString();
    } finally {
    _reply.recycle();
    _data.recycle();
    }
    return _result;
    }

    @Override
    public void insertUser(com.sjl.exercise.bean.UserBean userBean) throws android.os.RemoteException {
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    try {
    _data.writeInterfaceToken(DESCRIPTOR);
    if ((userBean != null)) {
    _data.writeInt(1);
    userBean.writeToParcel(_data, 0);
    } else {
    _data.writeInt(0);
    }
    mRemote.transact(Stub.TRANSACTION_insertUser, _data, _reply, 0);
    _reply.readException();
    } finally {
    _reply.recycle();
    _data.recycle();
    }
    }

    @Override
    public java.util.List<com.sjl.exercise.bean.UserBean> getUsers() throws android.os.RemoteException {
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    java.util.List<com.sjl.exercise.bean.UserBean> _result;
    try {
    _data.writeInterfaceToken(DESCRIPTOR);
    mRemote.transact(Stub.TRANSACTION_getUsers, _data, _reply, 0);
    _reply.readException();
    _result = _reply.createTypedArrayList(com.sjl.exercise.bean.UserBean.CREATOR);
    } finally {
    _reply.recycle();
    _data.recycle();
    }
    return _result;
    }

    @Override
    public void clearUser() throws android.os.RemoteException {
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    try {
    _data.writeInterfaceToken(DESCRIPTOR);
    mRemote.transact(Stub.TRANSACTION_clearUser, _data, _reply, 0);
    _reply.readException();
    } finally {
    _reply.recycle();
    _data.recycle();
    }
    }
    }
    //②
    static final int TRANSACTION_getCurrentTime = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_insertUser = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    static final int TRANSACTION_getUsers = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
    static final int TRANSACTION_clearUser = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
    }
    //①
    public java.lang.String getCurrentTime() throws android.os.RemoteException;

    public void insertUser(com.sjl.exercise.bean.UserBean userBean) throws android.os.RemoteException;

    public java.util.List<com.sjl.exercise.bean.UserBean> getUsers() throws android.os.RemoteException;

    public void clearUser() throws android.os.RemoteException;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    ICustomAidlInterface类最下面的①就是对应aidl文件里声明的几个方法,②所在声明了对应方法的int值,在抽象方法Stub#onTransact方法中可以看到③处正是用②中声明的int值区分调用的对应方法的。

    public interface ICustomAidlInterface extends android.os.IInterface {

    public static abstract class Stub extends android.os.Binder implements com.sjl.exercise.ICustomAidlInterface {
    private static final java.lang.String DESCRIPTOR = "com.sjl.exercise.ICustomAidlInterface";

    ...
    @Override
    public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
    //③
    java.lang.String descriptor = DESCRIPTOR;
    switch (code) {
    case INTERFACE_TRANSACTION: {
    reply.writeString(descriptor);
    return true;
    }
    case TRANSACTION_getCurrentTime: {
    data.enforceInterface(descriptor);
    java.lang.String _result = this.getCurrentTime();
    reply.writeNoException();
    reply.writeString(_result);
    return true;
    }
    case TRANSACTION_insertUser: {
    data.enforceInterface(descriptor);
    com.sjl.exercise.bean.UserBean _arg0;
    if ((0 != data.readInt())) {
    _arg0 = com.sjl.exercise.bean.UserBean.CREATOR.createFromParcel(data);
    } else {
    _arg0 = null;
    }
    this.insertUser(_arg0);
    reply.writeNoException();
    return true;
    }
    case TRANSACTION_getUsers: {
    data.enforceInterface(descriptor);
    java.util.List<com.sjl.exercise.bean.UserBean> _result = this.getUsers();
    reply.writeNoException();
    reply.writeTypedList(_result);
    return true;
    }
    case TRANSACTION_clearUser: {
    data.enforceInterface(descriptor);
    this.clearUser();
    reply.writeNoException();
    return true;
    }
    default: {
    return super.onTransact(code, data, reply, flags);
    }
    }
    }

    private static class Proxy implements com.sjl.exercise.ICustomAidlInterface {
    ...
    //②
    static final int TRANSACTION_getCurrentTime = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_insertUser = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    static final int TRANSACTION_getUsers = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
    static final int TRANSACTION_clearUser = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
    }
    //①
    public java.lang.String getCurrentTime() throws android.os.RemoteException;

    public void insertUser(com.sjl.exercise.bean.UserBean userBean) throws android.os.RemoteException;

    public java.util.List<com.sjl.exercise.bean.UserBean> getUsers() throws android.os.RemoteException;

    public void clearUser() throws android.os.RemoteException;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    Stub构造函数里传入IInterface和DESCRIPTOR,客户端通过绑定服务获取到aidl接口时使用了ICustomAidlInterface.Stub.asInterface(service)方法,在静态抽象类Stub中④处Stub#asInterface方法中可以看到使用Binder#queryLocalInterface方法获取本地aidl接口,如果有则返回本地找到的aidl接口,如果没有就返回定义的Proxy代理类(queryLocalInterface方法就是比对DESCRIPTOR来确认是否返回对应的IInterface,在不同进程时无法找到对应的IInterface,只能通过代理类Proxy来进行aidl方法调用)。

    public interface ICustomAidlInterface extends android.os.IInterface {
    /**
    * Local-side IPC implementation stub class.
    */
    public static abstract class Stub extends android.os.Binder implements com.sjl.exercise.ICustomAidlInterface {
    private static final java.lang.String DESCRIPTOR = "com.sjl.exercise.ICustomAidlInterface";
    ...
    public static com.sjl.exercise.ICustomAidlInterface asInterface(android.os.IBinder obj) {
    if ((obj == null)) {
    return null;
    }
    //④
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    if (((iin != null) && (iin instanceof com.sjl.exercise.ICustomAidlInterface))) {
    return ((com.sjl.exercise.ICustomAidlInterface) iin);
    }
    return new com.sjl.exercise.ICustomAidlInterface.Stub.Proxy(obj);
    }

    private static class Proxy implements com.sjl.exercise.ICustomAidlInterface {
    ...
    }
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    查看Proxy类可以看到它的IPC都是mRemote实现的,而在对应的方法中都使用了mRemote.transact方法,传入方法对应的int值、客户端传入参数data和服务端返回结果reply

    private static class Proxy implements com.sjl.exercise.ICustomAidlInterface {
    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 java.lang.String getCurrentTime() throws android.os.RemoteException {
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    java.lang.String _result;
    try {
    _data.writeInterfaceToken(DESCRIPTOR);
    //⑤
    mRemote.transact(Stub.TRANSACTION_getCurrentTime, _data, _reply, 0);
    _reply.readException();
    _result = _reply.readString();
    } finally {
    _reply.recycle();
    _data.recycle();
    }
    return _result;
    }

    }

    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    Binder#transact代码如下,最终调用了Binder#onTransact,也就是Binder#onTransact

    /**
    * Default implementation rewinds the parcels and calls onTransact. On
    * the remote side, transact calls into the binder to do the IPC.
    */
    public final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply,
    int flags) throws RemoteException {
    if (false) Log.v("Binder", "Transact: " + code + " to " + this);

    if (data != null) {
    data.setDataPosition(0);
    }
    boolean r = onTransact(code, data, reply, flags);
    if (reply != null) {
    reply.setDataPosition(0);
    }
    return r;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    Binder#onTransact方法如下,通过code确定调用的对应方法,data获取传入参数,reply设置返回值

    @Override
    public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
    java.lang.String descriptor = DESCRIPTOR;
    switch (code) {
    case TRANSACTION_insertUser: {
    data.enforceInterface(descriptor);
    com.sjl.exercise.bean.UserBean _arg0;
    if ((0 != data.readInt())) {
    _arg0 = com.sjl.exercise.bean.UserBean.CREATOR.createFromParcel(data);
    } else {
    _arg0 = null;
    }
    this.insertUser(_arg0);
    reply.writeNoException(http://www.my516.com);
    return true;
    }
    case TRANSACTION_getUsers: {
    data.enforceInterface(descriptor);
    java.util.List<com.sjl.exercise.bean.UserBean> _result = this.getUsers();
    reply.writeNoException();
    reply.writeTypedList(_result);
    return true;
    }
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    总结:
    服务端:服务端返回实现IBinder接口的对象;
    客户端:客户端如果在本地找到aidl实例直接转换使用,否则通过Proxy代理调用;
    通讯:本地客户端强制转换可调用调用方法,其他进程客户端需要通过Proxy代理调用方法;
    --------------------- 

  • 相关阅读:
    分享memcache和memcached安装过程(转)
    ios画图总结
    mac os下通过命令行的方式编译c++代码并在xcode里引用
    ubuntu访问windows共享文件夹
    为iphone 及iphone simulator编译boost库
    ubuntu 11.10 x64 安装oracle 11gR2时碰到的问题及解决方法
    模拟器与真机下ffmpeg的编译方法(总结版)
    ios 在View里绘图
    memcached1.4.4在ubuntu下编译的注意事项
    Google Code 服务试用
  • 原文地址:https://www.cnblogs.com/ly570/p/11014139.html
Copyright © 2020-2023  润新知