当前位置:操作系统 > 安卓/Android >>

跨进程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 ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,