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

来源:互联网 发布:mac窗口缩小快捷键 编辑:程序博客网 时间:2024/06/05 03:30

此文章主要目的:在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.cppLOCAL_SHARED_LIBRARIES:=libutils libbinderLOCAL_MODULE_TAGS:=optionalLOCAL_MODULE:=libJACK_ServiceLOCAL_PRELINK_MODULE:=falseinclude $(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.cppLOCAL_SHARED_LIBRARIES:=libutils libbinder libJACK_ServiceLOCAL_MODULE_TAGS:=optionalLOCAL_MODULE:=JACK_serverinclude $(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.cppLOCAL_SHARED_LIBRARIES:=libutils libbinder LOCAL_LDLIBS    := -lm -llog #解决undefined reference to `__android_log_print'LOCAL_MODULE_TAGS:=optionalLOCAL_MODULE:=libJACK_ClientLOCAL_PRELINK_MODULE:=falseinclude $(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.cppLOCAL_SHARED_LIBRARIES:=libJACK_Client libutilsLOCAL_LDLIBS    := -lm -llog #解决undefined reference to `__android_log_print'LOCAL_MODULE_TAGS:=optionalLOCAL_MODULE:=JACK_svctestinclude $(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




原创粉丝点击