跨进程C/S native service服务编写

http://blog.csdn.net/andyhuabing/article/details/7246716

纯Native的Service表示代码都在Native层,前面的文章讲到了两个service进程通过这binder中的onTransacton进行通讯,而这篇文章主要讲利用C/S结构的方法,利用IInterface进行相互访问。


以具体代码为例:
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 IInterface
{
protected:
enum
{
TEST_GETTEST = 0,
TEST_SETTEST,
};
public:
DECLARE_META_INTERFACE(Test); //声明重要宏定义
//定义纯虚函数
virtual void getTest() = 0;
virtual void setTest() = 0;
};


//BnTest 声明
class BnTest: public BnInterface<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 BpInterface<ITest>
{
public:
    BpTest(const sp<IBinder>& impl)
        : BpInterface<ITest>(impl)
    {
    }

    
    virtual void getTest()
    {
    Parcel data,reply;
    data.writeInterfaceToken(ITest::getInterfaceDescriptor());
    
    //TODO... 使用类似的writeXXX函数
    remote()->transact(TEST_GETTEST,data,&reply);
    int ret = reply.readXXX();
    return ;
    }
    
    virtual void setTest()
    {
    Parcel data,reply;
    data.writeInterfaceToken(ITest::getInterfaceDescriptor());
    
    //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 = interface_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结构代码框架就是这样子了,比较明了。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值