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

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

2012-02-10 11:30:18     我来讲两句       收藏     我要投稿框架

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



以具体代码为例:ui

test.cpp :spa

using namespace android;code


int main(int argc, char** argv)对象

{接口

    sp<ProcessState> proc(ProcessState::self());进程

    sp<IServiceManager> sm = defaultServiceManager();ip

    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结构代码框架就是这样子了,比较明了。


 


    //在2.3版本中能够定义TestService::



摘自 andyhuabing的专栏