此文章主要目的:在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
#include
#include
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
#include
#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)
3.接下来就是启动服务端的应用程序
创建目录svcserver 再创建如下文件
JACK_server.cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include "../service/JACK_Service.h"
#include "../log.h"
using namespace android;
int main(int arg, char** argv)
{
DebugPrint(" server - ain() begin\n");
sp proc(ProcessState::self());
sp 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;
}
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)
ps进程列表可以看到相关进程
4.客户端的实现
创建目录svcclient再创建相关文件
JACK_Client.h
#ifndef ANDROID_JACK_CLIENT_H
#define ANDROID_JACK_CLIENT_H
#include
namespace android
{
class JACK_Client
{
public:
int setN(int n);
String8 setString8(String8 str);
private:
static void getJACK_Service();
};
}
#endif
JACK_Client.cpp
#include
#include
#include "JACK_Client.h"
#include "../log.h"
#include
namespace android
{
sp 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 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;
}
}
}
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)
5.客户端的应用程序实现
创建目录svctest和相关文件
test.cpp
#include
#include "../svcclient/JACK_Client.h"
#include "../log.h"
#include
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;
}
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)
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
include $(call all-subdir-makefiles)
如果希望开机启动binder服务
可以在init.rc下实现service
service JACK_server /system/bin/JACK_server
class main
oneshot