Android添加一個Native Service

來源:互聯網
上載者:User

標籤:android   native   service   binder   

Native Service其實就是一個linux守護進程,提供一些服務,不過由於android的進程間通訊使用了Binder機制,那麼我們就需要按照android的規則來實現我們的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);};
IMPLEMENT_META_INTERFACE(ZxTask, "android.hardware.IZxTask");

必須以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();    }};

BpInterface模板類,其中的p就是代理的意思。其以我們前面定義的Interface為模板參數。
BpInterface聲明如下:

template<typename INTERFACE>class BpInterface : public INTERFACE, public BpRefBase{public:                                BpInterface(const sp<IBinder>& remote);protected:    virtual IBinder*            onAsBinder();};

我們的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);};
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);    }}

我們在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();};

其一個父類是繼承自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();}

我們在此實現服務提供的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();    }};

其要求模板參數實現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.cppLOCAL_C_INCLUDES :=                                 system/core/include                                 frameworks/native/includeLOCAL_SHARED_LIBRARIES :=                                                 libbinder                                                 libutils LOCAL_MODULE:= libzxtaskinclude $(BUILD_SHARED_LIBRARY)

我們寫一個service的可執行程式。
main.cpp

#include "service/ZxTaskService.h"int main(){    /* code */    android::ZxTaskService::publishAndJoinThreadPool();    return 0;}

Android.mk

LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES :=                                 main.cpp LOCAL_C_INCLUDES := frameworks/base/zxTaskLOCAL_MODULE:= zxtaskserviceLOCAL_SHARED_LIBRARIES := libzxtask libutils libbinderinclude $(BUILD_EXECUTABLE)

寫一個測試用戶端

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\n", "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;}

Android.mk

LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES :=                                 main.cpp LOCAL_C_INCLUDES := frameworks/base/zxTaskLOCAL_MODULE:= zxtaskclientLOCAL_SHARED_LIBRARIES := libzxtask libutils libbinderinclude $(BUILD_EXECUTABLE)

其中用到了interface_cast

template<typename INTERFACE>inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj){    return INTERFACE::asInterface(obj);}

其使用了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();

其聲明了一個描述的類屬性,我們使用的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() { }                          \

主要看asInterface的實現。其會調用IBinder的queryLocalInterface查詢我們的介面對象,這裡使用了基類指標,如果沒有就new出來。我們的BpZxTask只有在這個函數中使用,這也是為什麼我在實現時,指示全部把它放在了cpp檔案中。

intr = new Bp##INTERFACE(obj); 

這一句表明我們的Proxy類一定以Bp開頭且IBinder對象作為構造的參數傳入,實現了proxy和IBinder對象的綁定。

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

根據service名獲得這個service的IBinder對象,使用interface_cast實現了用戶端的Proxy和service的IBinder的綁定,然後我們在getPid中就可以調用IBinder的transact函數,這樣就和remote通訊上,回調到native service的onTransact的介面,然後處理了將結果返回,這樣就實現了client和service的通訊。

運行如:

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

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

Android添加一個Native Service

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.