跨進程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的專欄

相關文章
相關標籤/搜索