Android下在C++环境实现native层binder服务

xiaoxiao2021-02-28  107

此文章主要目的:在Android 6.0 arm 64位环境下使用C++编程实现binder通讯服务端和客户端

即native层binder服务通讯实现

此例子同时实现了int和string数据通讯接口

程序框架图

1.在Android源码目录下存放代码树形结构

development目录下创建相关文件列表

jack_server/ ├── Android.mk ├── log.h ├── service │   ├── Android.mk │   ├── JACK_Service.cpp │   └── JACK_Service.h ├── svcclient │   ├── Android.mk │   ├── JACK_Client.cpp │   └── JACK_Client.h ├── svcserver │   ├── Android.mk │   └── JACK_server.cpp └── svctest     ├── Android.mk     └── test.cpp

2.首先实现服务端

创建目录service 再创建如下三个文件

JACK_Service.h

#ifndef ANDROID_JACK_SERVICE_H #define ANDROID_JACK_SERVICE_H #include <utils/RefBase.h> #include <binder/IInterface.h> #include <binder/Parcel.h> namespace android { class JACK_Service : public BBinder { private: //mutable Mutex m_Lock; //int32_t m_NextConnId; public: static int Instance(); JACK_Service(); virtual ~JACK_Service(); virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t); }; } #endif

JACK_Service.cpp

#include <binder/IServiceManager.h> #include <binder/IPCThreadState.h> #include "JACK_Service.h" #include "../log.h" namespace android { //static struct sigaction oldact; static pthread_key_t sigbuskey; int JACK_Service::Instance() { DebugPrint("JACK_Service Instantiate\n"); int ret = defaultServiceManager()->addService( String16("jack.svc"), new JACK_Service()); DebugPrint(" JACK_Service ret = %d\n", ret); return ret; } JACK_Service::JACK_Service() { DebugPrint(" JACK_Service create\n"); //m_NextConnId = 1; pthread_key_create(&sigbuskey,NULL); } JACK_Service::~JACK_Service() { pthread_key_delete(sigbuskey); DebugPrint(" JACK_Service destory\n"); } status_t JACK_Service::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case 0: { pid_t pid = data.readInt32(); int num = data.readInt32(); num += 1000; reply->writeInt32(num); return NO_ERROR; } break; case 1: { pid_t pid = data.readInt32(); String8 str = data.readString8(); DebugPrint(" case 1 = %s \n",str.string()); String8 add_str = String8("jack_service get ")+str; //str = add_str + str; reply->writeString8(add_str); return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } } }Android.mk

LOCAL_PATH:=$(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:=JACK_Service.cpp LOCAL_SHARED_LIBRARIES:=libutils libbinder LOCAL_MODULE_TAGS:=optional LOCAL_MODULE:=libJACK_Service LOCAL_PRELINK_MODULE:=false include $(BUILD_SHARED_LIBRARY)

即可通过当前目录下mm 生成 out目录/system/lib64/下libJACK_Service.so 服务端

3.接下来就是启动服务端的应用程序

创建目录svcserver 再创建如下文件

JACK_server.cpp

#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <grp.h> #include <binder/IPCThreadState.h> #include <binder/ProcessState.h> #include <binder/IServiceManager.h> #include <utils/Log.h> #include "../service/JACK_Service.h" #include "../log.h" using namespace android; int main(int arg, char** argv) { DebugPrint(" server - ain() begin\n"); sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); //LOGI("ServiceManager: %p\n", sm.get()); DebugPrint(" server - erviceManager: %p\n", sm.get()); int ret = JACK_Service::Instance(); DebugPrint(" server - JACK_Service::Instance return %d\n", ret); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); return 0; } Android.mk

LOCAL_PATH:=$(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:=JACK_server.cpp LOCAL_SHARED_LIBRARIES:=libutils libbinder libJACK_Service LOCAL_MODULE_TAGS:=optional LOCAL_MODULE:=JACK_server include $(BUILD_EXECUTABLE) 当前目录执行mm即可生成out目录/system/bin/下  JACK_server可执行bin文件,在开发板上直接执行即可启动binder服务端

ps进程列表可以看到相关进程

4.客户端的实现

创建目录svcclient再创建相关文件

JACK_Client.h

#ifndef ANDROID_JACK_CLIENT_H #define ANDROID_JACK_CLIENT_H #include <binder/Parcel.h> namespace android { class JACK_Client { public: int setN(int n); String8 setString8(String8 str); private: static void getJACK_Service(); }; } #endif

JACK_Client.cpp

#include <binder/IServiceManager.h> #include <binder/IPCThreadState.h> #include "JACK_Client.h" #include "../log.h" #include<android/log.h> namespace android { sp<IBinder> binder; int JACK_Client::setN(int n) { getJACK_Service(); Parcel data, reply; data.writeInt32(getpid()); data.writeInt32(n); DebugPrint(" client - binder->transact()\n"); binder->transact(0, data, &reply); int r = reply.readInt32(); return r; } String8 JACK_Client::setString8(String8 str) { getJACK_Service(); Parcel data, reply;//获取或创建Parcel对象 data.writeInt32(getpid());//写入Parcel数据 data.writeString8(str); //ALOGE("chyj send %s",str.string()); DebugPrint(" client - binder->transact() send %s \n",str.string()); binder->transact(1, data, &reply);//通过Binder传递数据 1是函数顺序号,必须对应 String8 r = reply.readString8();//reply接收数据 DebugPrint(" setString8 reply %s \n",r.string()); //ALOGE("chyj reply %s",r.string()); return r; } void JACK_Client::getJACK_Service() { sp<IServiceManager> sm = defaultServiceManager(); binder = sm->getService(String16("jack.svc")); DebugPrint(" client - etService: %p\n", sm.get()); if(binder == 0) { DebugPrint(" JACK_Service not published, waiting..."); return; } } } Android.mk

LOCAL_PATH:=$(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:=JACK_Client.cpp LOCAL_SHARED_LIBRARIES:=libutils libbinder LOCAL_LDLIBS := -lm -llog #解决undefined reference to `__android_log_print' LOCAL_MODULE_TAGS:=optional LOCAL_MODULE:=libJACK_Client LOCAL_PRELINK_MODULE:=false include $(BUILD_SHARED_LIBRARY)

当前目录mm编译out目录/system/lib64/下生成 libJACK_Client.so

5.客户端的应用程序实现

创建目录svctest和相关文件

test.cpp

#include <stdio.h> #include "../svcclient/JACK_Client.h" #include "../log.h" #include <utils/String8.h> using namespace android; int main(int argc, char** argv) { JACK_Client client; DebugPrint(" start test"); int ret = client.setN(2017); DebugPrint("setN return: %d\n", ret); String8 send = String8("hello I'm string"); String8 str = client.setString8(send); DebugPrint("setString8 return: %s\n",str.string()); //ALOGE("chyj setString8 return %s",str.string()); return 0; } Android.mk

LOCAL_PATH:=$(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:=test.cpp LOCAL_SHARED_LIBRARIES:=libJACK_Client libutils LOCAL_LDLIBS := -lm -llog #解决undefined reference to `__android_log_print' LOCAL_MODULE_TAGS:=optional LOCAL_MODULE:=JACK_svctest include $(BUILD_EXECUTABLE) 当前目录mm生成out目录/system/bin/下 JACK_svctest,在板子上执行可执行文件即可和服务端实现通讯

6.最后是整体编译的文件

在最外层目录jack_server创建

log.h用于打印控制调试用

log.h

#define __DEBUG__ #define TAG "chyj" #ifdef __DEBUG__ //改进方法 #define DebugPrint(fmt,args...) printf("[file:%s fun:%s line:%d tag:%s]: " fmt "\n", __FILE__, __FUNCTION__, __LINE__, TAG, ##args); #else #define DebugPrint(fmt,args...) #endif Android.mk

include $(call all-subdir-makefiles)

至此全部代码源码已准备齐全,对应生成文件编译即可实现binder服务在C++环境通讯访问

如果希望开机启动binder服务

可以在init.rc下实现service

service JACK_server /system/bin/JACK_server class main oneshot

转载请注明原文地址: https://www.6miu.com/read-45508.html

最新回复(0)