Android C++ 端 Binder 通信

106 阅读4分钟

服务端

书写思路:

Server 端继承自 BBinder

class BBinder : public IBinder

继承的关键方法:

//注册到 ServiceManager 的名称
public:
virtual const String16 &getInterfaceDescriptor() const {
    return myDescriptor;
};

//用于发送数据
protected:
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t    transact(   uint32_t code,
                                const Parcel& data,
                                Parcel* reply,
                                uint32_t flags = 0) final;

//用于接收数据
// NOLINTNEXTLINE(google-default-arguments)
virtual status_t    onTransact( uint32_t code,
                                const Parcel& data,
                                Parcel* reply,
                                uint32_t flags = 0);

onTransact 如何解析数据并发送给客户端: 首先判断 code,然后从 data 中 readStrongBinder 获取 iBinder 对象,创建一个新的 Parcel 对象并写入数据,最后通过 iBinder 的 transact 方法,回调给客户端数据。当然也可以从 data 中读取其他从客户端写入的信息。

将服务端注册到 ServiceManager

#include <binder/IServiceManager.h>

int main(){
    sp<IServiceManager> sm = defaultServiceManager();
    sp<MySampleService> mySampleService = new MySampleService();
    sm->addService(String16(SAMPLE_SERVICE_DES),mySampleService);

    ALOGD("Service addService");
    printf("server before joinThreadPool \n");
    IPCThreadState::self() ->joinThreadPool(true);
    printf("server after joinThreadPool \n");
    return 0;
}

服务端代码

#include <binder/IServiceManager.h>
#include <binder/IBinder.h>
#include <binder/Parcel.h>
#include <binder/ProcessState.h>
#include <binder/IPCThreadState.h>

using namespace android;
#ifdef LOG_TAG
#undef LOG_TAG
#endif

#define LOG_TAG "myCppBinder"
#define SAMPLE_SERVICE_DES "my_hello"
#define SAMPLE_CB_SERVICE_DES "android.os.MySampleCallBack"
#define SRV_CODE 1
#define CB_CODE 1

class MySampleService : public BBinder {
private:
    String16 myDescriptor;
    sp <IBinder> callback;

public:
    MySampleService() {
        ALOGE("My Server ---------------------------%d", __LINE__);
        myDescriptor = String16(SAMPLE_SERVICE_DES);
    }

    virtual ~MySampleService() {
    }

    virtual const String16 &getInterfaceDescriptor() const {
        return myDescriptor;
    };

protected:

    void callFunction(int val) {
        ALOGE("Server ----------------------- %d", __LINE__);
        ALOGI("Service: %s(), %d, val = %d", __FUNCTION__, __LINE__, val);
    }

    virtual status_t onTransact(uint32_t
    code,
    const Parcel &data, Parcel
    *reply,
    uint32_t flags = 0
    ) {
        ALOGD("Service onTransact,line = %d, code = %d", __LINE__, code);
        String8 str_1;
        bool ret;
        switch (code) {
            case SRV_CODE:
                //read Client pass IBinder Object
                callback = data.readStrongBinder();
                ret = data.checkInterface(callback.get());
                ALOGD("Service onTransact,checkInterface line = %d, ret = %d", __LINE__, ret);
                str_1 = data.readString8();
                ALOGD("Service onTransact,readString8 line = %d, ret = %s", __LINE__, str_1.string());

                if (callback != NULL) {
                    Parcel _data, _replay;
                    _data.writeInt32(1);
                    _data.writeInt32(2);
                    _data.writeInt32(3);

                    _data.writeString8(String8("who..."));
                    _data.writeString8(String8("are..."));
                    _data.writeString8(String8("you..."));

                    callback->transact(CB_CODE, _data, &_replay, 0);
                }
                callFunction(6666);
                break;
            default:
                return BBinder::onTransact(CB_CODE, data, reply, flags);
        }
        return 0;
    }
};

int main(){
    sp<IServiceManager> sm = defaultServiceManager();
    sp<MySampleService> mySampleService = new MySampleService();
    sm->addService(String16(SAMPLE_SERVICE_DES),mySampleService);

    ALOGD("Service addService");
    printf("server before joinThreadPool \n");
    IPCThreadState::self() ->joinThreadPool(true);
    printf("server after joinThreadPool \n");
    return 0;
}

客户端

书写思路:

MySampleCallBack 思路和 Server 基本一样。只是不需要从 data 中获取 iBinder 对象。直接从 ServiceManager 中获取。

class MySampleCallBack : public BBinder

int main() {
    sp <IServiceManager> sm = defaultServiceManager();
    sp <IBinder> iBinder = sm->getService(String16(SAMPLE_SERVICE_DES));
    if (iBinder == NULL) {
        ALOGW("client can't find service");
        return -1;
    }
    Parcel _data, _replay;
    sp <MySampleCallBack> mySampleCallBack = new MySampleCallBack();
    _data.writeStrongBinder(mySampleCallBack);
    _data.writeInterfaceToken(String16(SAMPLE_CB_SERVICE_DES));
    _data.writeString8(String8("Hello My Server!!"));
    iBinder->transact(SRV_CODE, _data, &_replay, 0);
    printf("Client before joinThreadPool \n");
    IPCThreadState::self()->joinThreadPool(true);
    printf("Client ------------------------------ main end");
    return 0;
}

客户端代码

#include <binder/IServiceManager.h>
#include <binder/IBinder.h>
#include <binder/Parcel.h>
#include <binder/ProcessState.h>
#include <binder/IPCThreadState.h>

#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <binder/Binder.h>

using namespace android;
#ifdef LOG_TAG
#undef LOG_TAG
#endif

#define LOG_TAG "binderCallbackClient"
#define SAMPLE_SERVICE_DES "my_hello" //和服务端一致
#define SAMPLE_CB_SERVICE_DES "android.os.MySampleCallBack" //和服务端一致
#define SRV_CODE 1
#define CB_CODE 1

class MySampleCallBack : public BBinder {
private:
    String16 myDescriptor;
public:
    MySampleCallBack() {
        ALOGE("Client ------------------------------ %d", __LINE__);
        myDescriptor = String16(SAMPLE_CB_SERVICE_DES);
    }

    virtual ~MySampleCallBack() {}

    virtual const String16 &getInterfaceDescriptor() const {
        return myDescriptor;
    }

protected:
    void callFunction(int val) {
        ALOGD("---------callback client ok --------- line: %d, val :%d", __LINE__, val);
    }

    virtual status_t onTransact(uint32_t code,
                                const Parcel &data,
                                Parcel *reply,
                                uint32_t flags = 0) {
        ALOGD("Client onTransact, line = %d, code = %d", __LINE__, code);
        int val_1, val_2, val_3;
        String8 str_1, str_2, str_3;

        switch (code) {
            case SRV_CODE: {
                val_1 = data.readInt32();
                val_2 = data.readInt32();
                val_3 = data.readInt32();

                ALOGE("Client ------------------------------ %d, read int32 = %d", __LINE__, val_1);
                ALOGE("Client ------------------------------ %d, read int32 = %d", __LINE__, val_2);
                ALOGE("Client ------------------------------ %d, read int32 = %d", __LINE__, val_3);

                str_1 = data.readString8();
                str_2 = data.readString8();
                str_3 = data.readString8();

                ALOGE("Client ------------------------------ %d, read String = %s", __LINE__,
                      str_1.string());
                ALOGE("Client ------------------------------ %d, read String = %s", __LINE__,
                      str_2.string());
                ALOGE("Client ------------------------------ %d, read String = %s", __LINE__,
                      str_3.string());

                callFunction(12349);
                break;
            }
            default: {
                return BBinder::onTransact(code, data, reply, flags);
            }
        }

        return 0;
    }
};

int main() {
    sp <IServiceManager> sm = defaultServiceManager();
    sp <IBinder> iBinder = sm->getService(String16(SAMPLE_SERVICE_DES));
    if (iBinder == NULL) {
        ALOGW("client can't find service");
        return -1;
    }
    Parcel _data, _replay;
    sp <MySampleCallBack> mySampleCallBack = new MySampleCallBack();
    _data.writeStrongBinder(mySampleCallBack);
    _data.writeInterfaceToken(String16(SAMPLE_CB_SERVICE_DES));
    _data.writeString8(String8("Hello My Server!!"));
    iBinder->transact(SRV_CODE, _data, &_replay, 0);
    printf("Client before joinThreadPool \n");
    IPCThreadState::self()->joinThreadPool(true);
    printf("Client ------------------------------ main end");
    return 0;
}

打印结果

1979  1979 E myCppBinder: My Server ---------------------------25
1979  1979 D myCppBinder: Service addService
1981  1981 E binderCallbackClient: Client ------------------------------ 27
1979  1979 D myCppBinder: Service onTransact,line = 49, code = 1
1981  1981 D binderCallbackClient: Client onTransact, line = 46, code = 1598968902
1979  1979 D myCppBinder: Service onTransact,checkInterface line = 57, ret = 1
1979  1979 D myCppBinder: Service onTransact,readString8 line = 59, ret = Hello My Server!!
1981  1981 D binderCallbackClient: Client onTransact, line = 46, code = 1
1981  1981 E binderCallbackClient: Client ------------------------------ 56, read int32 = 1
1981  1981 E binderCallbackClient: Client ------------------------------ 57, read int32 = 2
1981  1981 E binderCallbackClient: Client ------------------------------ 58, read int32 = 3
1981  1981 E binderCallbackClient: Client ------------------------------ 64, read String = who...
1981  1981 E binderCallbackClient: Client ------------------------------ 66, read String = are...
1981  1981 E binderCallbackClient: Client ------------------------------ 68, read String = you...
1981  1981 D binderCallbackClient: ---------callback client ok --------- line: 39, val :12349
1979  1979 E myCppBinder: Server ----------------------- 39
1979  1979 I myCppBinder: Service: callFunction(), 40, val = 6666