Binder应用——Native层Binder通信实例

一、开发环境

Android 9.0

二、简介

在native层进行C++程序开发时,可以利用libbinder库进行进程间通信。libbinder的源码位于frameworks/native/libs/binder。

本文基于libbinder库实现两个可执行程序ServerDemo和ClientDemo,以及一个共享库libmybinder。

libmybinder用于实现接口,ServerDemo和ClientDemo代表binder通信的C/S端。

三、代码实现

  1. libmybinder
    首先我们需要自定义一个继承自IIterface的类,即IMyservice,来定义我们自定义的接口原型。
    这个类的必要内容都由 DECLARE_META_INTERFACE 和 IMPLEMENT_META_INTERFACE 两个宏来帮我们完成,我们仅需声明自定义的接口方法即可。
    之后,我们再定义两个分别继承自BpInterface<> 和 BnInterface<> 的类,即BpMyService 和 BnMyService,用以实现接口方法的数据传递。
    数据传递的核心方法便是 transact 和 onTransact,当BpMyService 调用 transact方法时,它将通过接口标号(这里是HELLO)找到对应的接口方法,并通过Parcel类型的两个参数分别传递数据和接收返回数据。
    #include <binder/IInterface.h>
    #include <binder/Parcel.h>
    #include <binder/IServiceManager.h>
    #include <binder/ProcessState.h>
    #include <binder/IPCThreadState.h>
    
    namespace android {
        class IMyService: public IInterface { // 注意类名必须以"I"开头
        public:
            DECLARE_META_INTERFACE(MyService); // 宏定义来自IInterface,完成了对必要成员的声明,宏的传参为类名去掉"I"
            virtual int32_t sayHello(String8 str, uint32_t num) = 0; // 自定义接口方法
        };
    
    // 接口方法的标号 enum { HELLO = 1, }; class BpMyService: public BpInterface<IMyService> { public: BpMyService(const sp<IBinder>& impl); virtual int32_t sayHello(String8 str, uint32_t num); }; class BnMyService: public BnInterface<IMyService> { public: virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0); virtual int32_t sayHello(String8 str, uint32_t num); }; }
    #include "IMyService.h"
    
    #include <stdio.h>
    
    namespace android {
        IMPLEMENT_META_INTERFACE(MyService, "android.demo.IMyService");
    
        BpMyService::BpMyService(const sp<IBinder>& impl):
                BpInterface<IMyService>(impl) {
        }
    
        int32_t BpMyService::sayHello(String8 str, uint32_t num) {
            printf("BpMyService::sayHello\n");
            Parcel data, reply;
            data.writeInterfaceToken(IMyService::getInterfaceDescriptor());
            data.writeString8(str);
            data.writeInt32(num);
            remote()->transact(HELLO, data, &reply);
            return reply.readInt32();
        }
    
        status_t BnMyService::onTransact(uint32_t code, const Parcel& data,
                Parcel* reply, uint32_t) {
            switch (code) {
                case HELLO: {
                    CHECK_INTERFACE(IMyService, data, reply);
                    printf("BnMyService::onTransact HELLO\n");
                    String8 str = data.readString8();
                    uint32_t num = data.readInt32();
                    reply->writeInt32(sayHello(str, num));
                    return NO_ERROR;
                }
                default:
                    break;
            }
            return NO_ERROR;
        }
    
        int32_t BnMyService::sayHello(String8 str, uint32_t num) {
            printf("BnMyService::sayHello %s, %d\n", str.string(), num);
            return num + 1;
        }
    }
    
  2. ServerDemo
    #include "IMyService.h"
    
    using namespace android;
    
    int main() {
        sp<IServiceManager> sm = defaultServiceManager();
        sm->addService(String16("android.myservice"), new BnMyService());
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();
    
        return 0;
    }
    
  3. ClientDemo
    #include "IMyService.h"
    
    using namespace android;
    
    int main() {
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder = sm->getService(String16("android.myservice"));
        sp<IMyService> service = interface_cast<IMyService>(binder);
        int ret = service->sayHello(String8("Hello, Binder!"), 100);
        printf("get ret from BnMyService: %d\n", ret);
    
        return 0;
    }
    

     

  4. Android.mk
    LOCAL_PATH := $(call my-dir)
    
    # MyService库
    include $(CLEAR_VARS)
    
    # 编译的源文件列表
    LOCAL_SRC_FILES := \
        IMyService.cpp
    
    # 生成的目标文件名
    LOCAL_MODULE := libmybinder
    LOCAL_MODULE_TAGS := optional
    
    # 添加其他依赖库(如果有)
    LOCAL_SHARED_LIBRARIES := libbinder \
        libutils
    
    include $(BUILD_SHARED_LIBRARY)
    
    
    # 服务端
    include $(CLEAR_VARS)
    
    # 编译的源文件列表
    LOCAL_SRC_FILES := \
        ServerDemo.cpp
    
    # 生成的目标文件名
    LOCAL_MODULE := serverDemo
    LOCAL_MODULE_TAGS := optional
    
    # 添加其他依赖库(如果有)
    LOCAL_SHARED_LIBRARIES := libbinder \
        libutils \
        libmybinder
    
    include $(BUILD_EXECUTABLE)
    
    
    # 客户端
    include $(CLEAR_VARS)
    
    # 编译的源文件列表
    LOCAL_SRC_FILES := \
        ClientDemo.cpp
    
    # 生成的目标文件名
    LOCAL_MODULE := clientDemo
    LOCAL_MODULE_TAGS := optional
    
    # 添加其他依赖库(如果有)
    LOCAL_SHARED_LIBRARIES := libbinder \
        libutils \
        libmybinder
    
    include $(BUILD_EXECUTABLE)

     

四、参考文章

《Binder系列8—如何使用Binder》

posted @ 2024-03-31 20:58  ZySong  阅读(218)  评论(0)    收藏  举报