• 添加native service


    客户端在请求 service 的服务时使用了一个具有相同接口的 Proxy 类。native service 这具体实现这个接口,所以 android 提供了 IInterface 类,其是”base class for Binder interfaces”,所以我们的 IZxTask 类继承它:

    class IZxTask : public IInterface {
    public:
        enum { TASK_GET_PID = IBinder::FIRST_CALL_TRANSACTION,
        };
    
        virtual int getPid() = 0;
    
        DECLARE_META_INTERFACE(ZxTask);
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    IMPLEMENT_META_INTERFACE(ZxTask, "android.hardware.IZxTask");
    • 1

    必须以 I 开头,因为后面会用到一些宏,比如 DECLARE_META_INTERFACE,I 开头是写到宏里面的,所以我们只要传入了 ZxTask 就行了。我们的 Native Service 提供一个接口就是返回 Service 的进程号。 
    下面我们就需要开始分化实现,一个是客户端,一个是 native service。 
    先来看代理类

    class BpZxTask : public BpInterface<IZxTask> {
    public:
        BpZxTask(const sp<IBinder>& binder)
            : BpInterface<IZxTask>(binder)
        {
        }
    
        virtual int getPid()
        {
            Parcel data, reply;
            data.writeInterfaceToken(IZxTask::getInterfaceDescriptor());
            remote()->transact(TASK_GET_PID, data, &reply);
            return reply.readInt32();
        }
    };
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    BpInterface 模板类,其中的 p 就是代理的意思。其以我们前面定义的 Interface 为模板参数。 
    BpInterface 声明如下:

    template<typename INTERFACE>
    class BpInterface : public INTERFACE, public BpRefBase
    {
    public:
                                    BpInterface(const sp<IBinder>& remote);
    
    protected:
        virtual IBinder*            onAsBinder();
    };
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    我们的 BpZxTask 需要实现我们定义的接口类中的接口函数。在实现中,我们是客户端,我们需要向 native service 提申请,我们使用 remote 获得关联 service 的 IBinder 对象,然后通过 transact 提交,通过 reply 获得返回值。

    下面来看 BnInterface 的实现。

    class BnZxTask : public BnInterface<IZxTask> {
    public:
        virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    status_t BnZxTask::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    {
    
        switch (code) {
        case TASK_GET_PID: {
            CHECK_INTERFACE(IZxTask, data, reply);
            int32_t pid = getPid();
            reply->writeInt32(pid);
            return NO_ERROR;
    
        } break;
    
        default:
            return BBinder::onTransact(code, data, reply, flags);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    我们在 bpinterface 的 transact 调用会回调 bninterface 的 onTransact 来处理,我们根据 code 参数来进行请求的区分。

    BnInterface 类模板其声明如下:

     template<typename INTERFACE>
    class BnInterface : public INTERFACE, public BBinder
    {
    public:
        virtual sp<IInterface>      
            queryLocalInterface(const String16& _descriptor);
        virtual const String16&     getInterfaceDescriptor() const;
    
    protected:
        virtual IBinder*            onAsBinder();
    };
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    其一个父类是继承自 IInterface 的接口类,一个是代表 Binder service 服务端的 BBinder 类。

    下面来实现 native service。

    class ZxTaskService : public BinderService<ZxTaskService>, public BnZxTask {
    public:
        virtual int getPid();
        static char const* getServiceName() { return "ZxTask"; }
        friend class BinderService<ZxTaskService>;
    };
    
    int ZxTaskService::getPid()
    {
        return getpid();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    我们在此实现服务提供的 getPid 接口就 ok,BinderService 模板为我们启动一个 Service 实现了逻辑封装。 
    BinderService 实现如下:

    template<typename SERVICE>
    class BinderService
    {
    public:
        static status_t publish(bool allowIsolated = false) {
            sp<IServiceManager> sm(defaultServiceManager());
            return sm->addService(
                    String16(SERVICE::getServiceName()),
                    new SERVICE(), allowIsolated);
        }
    
        static void publishAndJoinThreadPool(bool allowIsolated = false) {
            publish(allowIsolated);
            joinThreadPool();
        }
    
        static void instantiate() { publish(); }
    
        static status_t shutdown() { return NO_ERROR; }
    
    private:
        static void joinThreadPool() {
            sp<ProcessState> ps(ProcessState::self());
            ps->startThreadPool();
            ps->giveThreadPoolName();
            IPCThreadState::self()->joinThreadPool();
        }
    };
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    其要求模板参数实现getServiceName方法,publishpublishAndJoinThreadPool函数实现了该 service 添加到 SM 的逻辑,publish 只是 add,而publishAndJoinThreadPool会启动该 service。

    这里我们就完成了 native service 的开发,我们将其编成库。 
    Android.mk

    LOCAL_PATH:= $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_SRC_FILES := 
                                    ZxTask.cpp 
                                    ZxTaskService.cpp
    
    
    LOCAL_C_INCLUDES := 
                                    system/core/include 
                                    frameworks/native/include
    
    
    
    LOCAL_SHARED_LIBRARIES := 
                                                    libbinder 
                                                    libutils 
    
    
    LOCAL_MODULE:= libzxtask
    
    include $(BUILD_SHARED_LIBRARY)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    我们写一个 service 的可执行程序。 
    main.cpp

    #include "service/ZxTaskService.h"
    
    
    int main()
    {
        /* code */
        android::ZxTaskService::publishAndJoinThreadPool();
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    Android.mk

    LOCAL_PATH:= $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_SRC_FILES := 
                                    main.cpp 
    
    
    
    LOCAL_C_INCLUDES := frameworks/base/zxTask
    
    LOCAL_MODULE:= zxtaskservice
    
    LOCAL_SHARED_LIBRARIES := libzxtask libutils libbinder
    
    include $(BUILD_EXECUTABLE)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    写一个测试客户端

    main.cpp

    #include "service/ZxTask.h"
    #include <binder/IServiceManager.h>
    #include <unistd.h>
    #include <stdio.h>
    
    int main()
    {
        using namespace android;
        sp<IServiceManager> sm =defaultServiceManager();  
        printf("%s
    ", "get serviceManager");
        sp<IBinder> binder =sm->getService(String16("ZxTask"));  
        sp<IZxTask> mTask =interface_cast<IZxTask>(binder);  
        printf("ZxTask Service pid %d, client pid:%d",mTask->getPid(), getpid());  
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    Android.mk

    LOCAL_PATH:= $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_SRC_FILES := 
                                    main.cpp 
    
    
    
    LOCAL_C_INCLUDES := frameworks/base/zxTask
    
    
    LOCAL_MODULE:= zxtaskclient
    
    LOCAL_SHARED_LIBRARIES := libzxtask libutils libbinder
    
    include $(BUILD_EXECUTABLE)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    其中用到了interface_cast

    template<typename INTERFACE>
    inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
    {
        return INTERFACE::asInterface(obj);
    }
    • 1
    • 2
    • 3
    • 4
    • 5

    其使用了 asInterface 函数,而这个函数就是我们在 IZxTask 里面使用DECLARE_META_INTERFACE声明的。

    #define DECLARE_META_INTERFACE(INTERFACE)                           
        static const android::String16 descriptor;                      
        static android::sp<I##INTERFACE> asInterface(                   
                const android::sp<android::IBinder>& obj);              
        virtual const android::String16& getInterfaceDescriptor() const;
        I##INTERFACE();                                                 
        virtual ~I##INTERFACE();
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    其声明了一个描述的类属性,我们使用的asInterface函数。 
    看下IMPLEMENT_META_INTERFACE宏。

    #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)              
        const android::String16 I##INTERFACE::descriptor(NAME);    
        const android::String16&                                   
                I##INTERFACE::getInterfaceDescriptor() const {     
            return I##INTERFACE::descriptor;                       
        }                                                          
        android::sp<I##INTERFACE> I##INTERFACE::asInterface(       
                const android::sp<android::IBinder>& obj)          
        {                                                          
            android::sp<I##INTERFACE> intr;                        
            if (obj != NULL) {                                     
                intr = static_cast<I##INTERFACE*>(                 
                    obj->queryLocalInterface(                      
                            I##INTERFACE::descriptor).get());      
                if (intr == NULL) {                                
                    intr = new Bp##INTERFACE(obj);                 
                }                                                  
            }                                                      
            return intr;                                           
        }                                                          
        I##INTERFACE::I##INTERFACE() { }                           
        I##INTERFACE::~I##INTERFACE() { }                          
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    主要看asInterface的实现。其会调用 IBinder 的 queryLocalInterface 查询我们的接口对象,这里使用了基类指针,如果没有就 new 出来。我们的 BpZxTask 只有在这个函数中使用,这也是为什么我在实现时,指示全部把它放在了 cpp 文件中。

    intr = new Bp##INTERFACE(obj); 
    • 1

    这一句表明我们的 Proxy 类一定以 Bp 开头且 IBinder 对象作为构造的参数传入,实现了 proxy 和 IBinder 对象的绑定。

      sp<IBinder> binder =sm->getService(String16("ZxTask"));  
    • 1

    根据 service 名获得这个 service 的 IBinder 对象,使用interface_cast实现了客户端的 Proxy 和 service 的 IBinder 的绑定,然后我们在 getPid 中就可以调用 IBinder 的 transact 函数,这样就和 remote 通讯上,回调到 native service 的 onTransact 的接口,然后处理了将结果返回,这样就实现了 client 和 service 的通讯。

    运行如下图:

    此处输入图片的描述

    代码例子:https://git.oschina.net/zhouX/servicedemo.git

  • 相关阅读:
    httpclient妙用一 httpclient作为客户端调用soap webservice(转)
    WebService学习总结(转)
    C++的override和final
    C++类const和static成员初始化
    C++数据存储方式
    C++类成员存储大小
    内联函数
    C++接口的概念
    C++深拷贝和浅拷贝
    C++构造函数以及何时被调用
  • 原文地址:https://www.cnblogs.com/yldf/p/11900136.html
Copyright © 2020-2023  润新知