Binder应用——Native层Binder通信实例
一、开发环境
Android 9.0
二、简介
在native层进行C++程序开发时,可以利用libbinder库进行进程间通信。libbinder的源码位于frameworks/native/libs/binder。
本文基于libbinder库实现两个可执行程序ServerDemo和ClientDemo,以及一个共享库libmybinder。
libmybinder用于实现接口,ServerDemo和ClientDemo代表binder通信的C/S端。
三、代码实现
- 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; } } - 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; } - 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; } - 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)

浙公网安备 33010602011771号