跨进程C/S native service服务编写
纯Native的Service表示代码都在Native层,前面的文章讲到了两个service进程通过这binder中的onTransacton进行通讯,而这篇文章主要讲利用C/S结构的方法,利用IInte易做图ce进行相互访问。
以具体代码为例:
test.cpp :
using namespace android;
int main(int argc, char** argv)
{
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
LOGI("ServiceManager: %p", sm.get());
sm->addService("test.service",new Test); //这里加入serviceManager中
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
//在2.3版本中可以定义用一句话代替上面的代码:
TestService::publishAndJoinThreadPool();
return 0;
}
BinderService中定义如下:
static void publishAndJoinThreadPool() {
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SERVICE::getServiceName()), new SERVICE());
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
这里定义的是跨进程的C/S结构,所以分为本地服务端BnTest及客户端BpTest,为隐藏性Bp与Bn的定义与实现都入在BnTest.cpp中。
BnXX代表服务端,Bp代码客户端
头文件ITest.h定义如下:
#define ANDROID_ITEST_H
#ifndef ANDROID_ITEST_H
class ITest: public IInte易做图ce
{
protected:
enum
{
TEST_GETTEST = 0,
TEST_SETTEST,
};
public:
DECLARE_META_INTERFACE(Test); //声明重要宏定义
//定义纯虚函数
virtual void getTest() = 0;
virtual void setTest() = 0;
};
//BnTest 声明
class BnTest: public BnInte易做图ce<ITest>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
// ----------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_ITEST_H
接口实现ITest.cpp
namespace android {
//BpTest实现
class BpTest : public BpInte易做图ce<ITest>
{
public:
BpTest(const sp<IBinder>& impl)
: BpInte易做图ce<ITest>(impl)
{
}
virtual void getTest()
{
Parcel data,reply;
data.writeInte易做图ceToken(ITest::getInte易做图ceDescriptor());
//TODO... 使用类似的writeXXX函数
remote()->transact(TEST_GETTEST,data,&reply);
int ret = reply.readXXX();
return ;
}
virtual void setTest()
{
Parcel data,reply;
data.writeInte易做图ceToken(ITest::getInte易做图ceDescriptor());
//TODO... 使用类死的writeXXX函数
remote()->transact(TEST_SETTEST,data,&reply);
int ret = reply.readXXX();
return ;
}
};
//BnTest实现
//重要的一个定义实现
IMPLEMENT_META_INTERFACE(Test, "android.test.ITest");
status_t BnTest::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code){
case TEST_GETTEST:{
CHECK_INTERFACE(ITest, data, reply);
//TODO... setTest()
}break;
case TEST_GETTEST:{
CHECK_INTERFACE(ITest, data, reply);
//TODO... getTest()
}break;
default:
break;
}
}
// ----------------------------------------------------------------------
}
从上面所述,很多代码都基本上是一致的形式,只是往其中添加上不同的处理代码而已,重要的是利用Parcel对象进行序列化。
后面讲讲客户端和服务端如何实现及调用情况:
客户端如何调用:
static sp<ITest> getTestSerivce()
{
sp<IBinder> binder;
static sp<ITest> sTestManager = NULL;
if(sTestManager != NULL)
return sTestManager;
sp<IServiceManager> sm = defaultServiceManager();
do {
binder = sm->getService(String16("test.service"));
if (binder == 0) {
LOGW("TestService not published, waiting...");
usleep(500000); // 0.5 s
}
} while(binder == 0);
if(sTestManager == NULL){
sTestManager = inte易做图ce_cast<ITest>(binder);
}
return sTestManager;
}
利用getTestSerivce函数获取到客户端管理器句柄,然后利用sTestManager->setTest/getTest调用
这是一种常用的客户端访问service的函数实现方法。
服务端实现:
class TestService:
public BinderService<TestService>, //2.3 存在,而2.2版本实现instantiate()函数
public BnTest,
protected Thread
{
public:
static void instantiate();
static char const* getServiceName() { return "test.service"; }
//服务端实现接口函数
virtual void getTest() ;
virtual void setTest() ;
};
void TestService::instantiate() {
defaultServiceManager()->addService(
String16("test.service"), new TestService());
}
2.3版本如此做法,在BinderService类中做了此事情:
class BinderService
{
public:
static status_t publish() {
sp<IServiceManager> sm(defaultServiceManager());
return sm->addService(String16(SERVICE::getServiceName()), new SERVICE());
}
static void instantiate() { publish(); }
...
};
ok,跨进程的C/S结构代码框架就是这样
补充:移动开发 , Android ,