今日网上看到有人用C++实现了binder通讯的小例子,但是没有给出完整的demo,自己弄了过来整理了一下,可以在真机上运行。基本架构都是一样,代码就不分析了,要分析又得说一遍binder的机制,反正就可以把它当作一个模板来用了,要增加或修改函数,也就是在ITest中增加virtual函数,分别在bp, bn,class Test端实现,并在onTransact中增加case分支即可,够简单吧,代码如下:
binder_test.h:
#ifndef __BINDER_TEST_H
#define __BINDER_TEST_H
#include <binder/Parcel.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <binder/IBinder.h>
#include <binder/IInterface.h>
#include <unistd.h>
#include <stdio.h>
#include <utils/misc.h>
#include <utils/Atomic.h>
#include <utils/Log.h>
namespace android
{
class ITest : public IInterface
{
public:
DECLARE_META_INTERFACE(Test);
virtual void getTest() = 0;
};
class BnTest: public BnInterface<ITest>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
class Test : public BnTest
{
public:
//Test(){ALOGE("got the service");};
//~Test();
virtual void getTest(){ALOGE("got the service");};
void print(){ALOGE("got the service");};
};
enum {
PRINT = IBinder::FIRST_CALL_TRANSACTION,
};
class BpTest : public BpInterface<ITest>
{
public:
BpTest(const sp<IBinder>& impl ):BpInterface<ITest>(impl)
{
}
virtual void getTest()
{
printf("in the get Test\n");
Parcel data, reply;
data.writeInterfaceToken(ITest::getInterfaceDescriptor());
remote()->transact(PRINT, data, &reply);
printf("send Print %d\n",reply.readInt32());
}
};
IMPLEMENT_META_INTERFACE(Test,"android.TestServer.ITest");
status_t BnTest::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code)
{
case PRINT:
{
printf("got the client msg\n");
CHECK_INTERFACE(ITest, data, reply);
getTest();
reply->writeInt32(100);
return NO_ERROR;
}break;
default:break;
}
return NO_ERROR;
}
}// namespace android
#endif
binder_test_client.cpp:
#include "binder_test.h"
using namespace android;
int main(int argc, char *argv[])
{
sp<IBinder> binder;
sp<ProcessState> proc(ProcessState::self());
//get service manager
sp<IServiceManager> sm = defaultServiceManager();
do{
binder = sm->getService(String16("service.testmanager"));
if(binder != 0)
break;
sleep(1);
}while(true);
const sp<ITest>& bts = interface_cast<ITest>(binder);
ALOGE("bindertest client is starting.....");
bts->getTest();
return 0;
}
binder_test_service.cpp:
#include "binder_test.h"
using namespace android;
int main(int argc, char *argv[])
{
sp<ProcessState> proc(ProcessState::self());
//get service manager
sp<IServiceManager> sm = defaultServiceManager();
sm->addService(String16("service.testmanager"),new Test());
ALOGE("bindertest service is starting.....");
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}
Android.mk:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
binder_test_service.cpp
LOCAL_SHARED_LIBRARIES := \
libutils \
libbinder
# FIXME The duplicate audioflinger is temporary
LOCAL_C_INCLUDES := binder_test.h
LOCAL_MODULE:= bindertestservice
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
binder_test_client.cpp
LOCAL_SHARED_LIBRARIES := \
libutils \
libbinder
# FIXME The duplicate audioflinger is temporary
LOCAL_C_INCLUDES := binder_test.h
LOCAL_MODULE:= bindertestclient
include $(BUILD_EXECUTABLE)