这篇文章根据最近工作上对安卓本地服务的理解,同时也参考了其他人的文章,自己按照相同的框架做了一个diyservice,代码很简单,由此先记下:
服务器端:
头文件:diyservice.h
#ifndef __DIY_SERVICE_H__
#define __DIY_SERVICE_H__
#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <utils/threads.h>
namespace android
{
//定义接口同时用于客户端和服务端
class IDiyService: public IInterface
{
public:
DECLARE_META_INTERFACE(DiyService);
virtual int getNumber(int arg0) = 0;
};
//定义服务端代码 用于继承
class BnDiyService: public BnInterface<IDiyService>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
//定义交互的内容
enum
{
GET_NUMBER = IBinder::FIRST_CALL_TRANSACTION,
};
class BpDiyService: public BpInterface<IDiyService>
{
public:
//这个构造函数的参数impl就是remote的来历。具体要看BpInterface
BpDiyService(const sp<IBinder>& impl): BpInterface<IDiyService>(impl)
{
}
int getNumber(int arg0)
{
Parcel data;
Parcel reply;
data.writeInt32(arg0);
remote()->transact(GET_NUMBER, data, &reply);
return reply.readInt32();
}
};
//实现了IDiyService的asinterface函数,这个函数其实是使用得到的Bpbinder对象作为参数来创建BpDiyService对象。
IMPLEMENT_META_INTERFACE(DiyService, "android.DiyService.IDiyService");
//服务端实现类,具体实现在下面的cpp里面
class diyservice:public BnDiyService
{
public:
int getNumber(int arg0);
};
}
#endif
CPP文件:diyservice.cpp
#include <cutils/log.h>
#include <cutils/properties.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include "diyservice.h"
namespace android
{
//实现服务端如何处理客户端提交过来的请求。这里主要涉及到Parcel这个结构体的使用方法。
status_t BnDiyService::onTransact(uint32_t code, const Parcel&data, Parcel*reply, uint32_t flags)
{
int ret = 0;
switch(code)
{
case GET_NUMBER:
ret = getNumber(data.readInt32());
reply->writeInt32(ret);
return NO_ERROR;
break;
}
return NO_ERROR;
}
//没有更多作用,只是实现IDiyService接口的这个虚函数。
int diyservice::getNumber(int arg0)
{
return arg0;
}
}
对应的Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= diyservice.cpp
LOCAL_SHARED_LIBRARIES:= libutils libutils libbinder
LOCAL_C_INCLUDES := $(TOP)/frameworks/base/include
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:= libdiyservice
LOCAL_PRELINK_MODULE:= false
include $(BUILD_SHARED_LIBRARY)
注意这里是编译成了LIB库文件。
下面是这个服务器的进行代码:
main.cpp
#include <cutils/log.h>
#include <cutils/properties.h>
#include <sys/types.h>
#include <unistd.h>
#include <cutils/log.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include "../diyservice.h"
using namespace android;
int main()
{
sp<ProcessState> proc(ProcessState::self());
//得到ServiceManager,其实它也是一个服务。只是服务端在内核中。
sp<IServiceManager> sm = defaultServiceManager();
//调用它的addService接口添加我们刚定义的服务到ServiceManager.
sm->addService(String16("service.diysvc"),new diyservice());
//最后两个其实就对内核设备节点进行一个poll的过程,一直等待内核数据的到来。
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
对应的Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= main.cpp
LOCAL_SHARED_LIBRARIES:= libutils libdiyservice libbinder
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:= diytest
include $(BUILD_EXECUTABLE)
客户端程序:
testService.cpp
#include <cutils/log.h>
#include <cutils/properties.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/BpBinder.h>
#include "../diyservice.h"
using namespace android;
int main(int argc,char *argv[])
{
sp<IBinder> TestAbinder;
Parcel data, reply;
int send;
int sum=0;
if(argc < 2)
return 0;
send = atoi(argv[1]);
LOGI("testService main is call...");
//首先还是要取得SensorManger这个中间人。
sp<IServiceManager> sm = defaultServiceManager();
sp<IDiyService> Diy_service;
while(1)
{
//然后调用它的getService,这个函数会到内核去查询属于我们要的service的句柄,然后通过这个句柄建立Bpbinder对象。
TestAbinder = sm->getService(String16("service.diysvc"));
LOGE("TestA::getAddService %p/n",sm.get());
if (TestAbinder == 0)
{
LOGE("TestAService not published, waiting...");
usleep(1000000);
continue;
}
else
{
LOGI("TestA::getAddService success...");
break;
}
}
printf("handle:%d\n",((BpBinder *)(TestAbinder.get()))->handle());
//有了这个对象后再调用IDiyService的asInterface对象后,会产生BpDiyService这个对象,然后返回。
Diy_service = interface_cast<IDiyService>(TestAbinder);
//最后调用BpDiyService的getNumber函数,这个函数会具体的向内核发出请求,并得到响应。
sum = Diy_service->getNumber(send);
LOGI("GET_NUMBER value = %d",sum);
return 0;
}
对应的Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= testService.cpp
LOCAL_SHARED_LIBRARIES:= libutils libdiyservice libbinder
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:= testdiyService
include $(BUILD_EXECUTABLE)
编译好后通过adb push到安卓手机后就可以运行了。