Android Binder机制:编写自己的本地服务

来源:互联网 发布:淘宝上有二手市场吗 编辑:程序博客网 时间:2024/06/05 02:40

原址

前面几篇博客中系统地介绍了本地服务的注册、检索以及使用过程。这篇博客我们将完成一个属于自己的本地服务:AllenService。

由前面的学习知道,要完成一个自己的本地服务,需要有IAllenService接口、BnAllenService服务Stub、AllenService、BpAllenService。UML图如下:

AllenService

各文件的路径如下:

  • frameworks/base/include/allen/IAllenService.h,AllenService.h

  • frameworks/base/libs/allen/IAllenService.cpp,AllenService.cpp

  • frameworks/base/cmds/allen/main_allenclient.cpp,main_allenservice.cpp

1.IAllenService.h文件

该头文件中包含了接口描述符以及枚举类。另外,与Android中的服务接口文件类似,这里将BnAllenService的定义也放在该头文件中,所以该头文件的代码如下:

123456789101112131415161718192021222324252627282930313233343536373839404142434445
#ifndef FRAMEWORKS_BASE_INCLUDE_IALLENSERVICE_H_#define FRAMEWORKS_BASE_INCLUDE_IALLEN_SERVICE_H_#include <utils/Errors.h>#include <utils/KeyedVector.h>#include <utils/RefBase.h>#include <utils/String8.h>#include <binder/IInterface.h>#include <binder/Parcel.h>#include <AllenService.h>namespace android{    #define MATH_ERROR int32(-1)    #define ALLEN_DESCRIPTOR "android.allen.IAllenService"    enum{        ALLEN_PRINT=IBinder::FIRST_CALL_TRANSACTION,        ALLEN_ADD,        ALLEN_SUB    };    class IAllenService:public IInterface    {        public:            //宏定义            DECLARE_META_INTERFACE(AllenService);            virtual status_t print(const char*str)=0;            virtual int32 add(int32 a,int32 b)=0;            virtual int32 sub(int32 a,int32 b)=0;    };    class BnAllenService:public BnInterface<IAllenService>    {        public:            virtual status_t onTransact(uint32_t code,                                        const Parcel& data,                                        Parcel*reply,                                        uint32_t flags=0);    };};//namespace android#endif
  1. AllenService.h

AllenService头文件的代码如下:

12345678910111213141516171819202122232425262728293031323334
#ifndef FRAMEWORKS_BASE_INCLUDE_ALLEN_ALLENSERVICE_H_#define FRAMEWORKS_BASE_INCLUDE_ALLEN_ALLENSERVICE_H_#include <utils/Log.h>#include <utils/threads.h>#include <utils/List.h>#include <utils/Errors.h>#include <utils/KeyedVector.h>#include <utils/String8.h>#include <utils/Vector.h>#include <IAllenService.h>namespace android{    class AllenService:public BnAllenService{        public:            static void instantiate();            virtual status_t print(const char*str);            virtual int32 add(int32 a,int32 b);            virtual int32 sub(int32 a,int32 b);            virtual status_t onTransact(                    uint32_t code,                    const Parcel& data,                    Parcel* reply,                    uint32_t flags);        private:            AllenService();            virtual ~AllenService();    };}; //namespace android#endif
  1. IAllenService.cpp

该文件中不仅有IAllenService中宏接口的实现,还有BnAllenService的实现,另外,还有BpAllenService的定义以及实现。

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
#include <stdint.h>#include <sys/types.h>#include <binder/Parcel.h>#include <binder/IMemory.h>#include <allen/IAllenService.h>#include <allen/AllenService.h>#include <utils/Errors.h>namespace android{    class BpAllenService: public BpInterface<IAllenService>    {        public:            BpAllenService(const sp<IBinder>& impl):BpInterface<IAllenService>(impl)            {            }            virtual status_t print(const char*str)            {                Parcel data,reply;                data.writeInterfaceToken(IAllenService::getInterfaceDescriptor());                data.writeCString(str);                status_t status=remote()->transact(ALLEN_PRINT,data,&reply);                if(status!=NO_ERROR){                    LOGE("print str error:%s",strerror(-status));                }else{                    status=reply.readInt32();                }                return status;            }            virtual int32 add(int32 a,int32 b)            {                Parcel data,reply;                data.writeInterfaceToken(IAllenService::getInterfaceDescriptor());                data.writeInt32(a);                data.writeInt32(b);                status_t status=remote()->transact(ALLEN_ADD,data,&reply);                return reply.readInt32();            }            virtual int32 sub(int32 a,int32 b)            {                Parcel data,reply;                data.writeInterfaceToken(IAllenService::getInterfaceDescriptor());                data.writeInt32(a);                data.writeInt32(b);                status_t status=remote()->transact(ALLEN_SUB,data,&reply);                return reply.readInt32();            }    };    //宏实现    IMPLEMENT_META_INTERFACE(AllenService,ALLEN_DESCRIPTOR)    status BnAllenService::onTransact(uint32_t code,const Parcel& data,Parcel* reply,uint32_t flags)    {        switch(code){            case ALLEN_PRINT:{                CHECK_INTERFACE(IAllenService,data,reply);                const char*str=data.readCString();                reply->writeInt32(print(str));                return NO_ERROR;            }break;            case ALLEN_ADD:{                CHECK_INTERFAC(IAllenService,data,reply);                int32 a=data.readInt32();                int32 b=data.readInt32();                reply->writeInt32(this->add(a,b));                return NO_ERROR;            }break;            case ALLEN_SUB:{                CHECK_INTERFACE(IAllenService,data,reply);                int32 a=data.readInt32();                int32 b=data.readInt32();                reply->writeInt32(this->sub(a,b));                return NO_ERROR;            }break;            default:                return BBinder::onTransact(code,data,reply,flags);        }    }};

4.AllenService.cpp

该文件实现服务接口。代码如下:

12345678910111213141516171819202122232425
namespace android{    void AllenService::instantiate(){        defaultServiceManager()->addService(            String16(ALLEN_DESCRIPTOR),new AllenService());    }    status_t AllenService::print(const char*str){        LOGI("%s\n",str);        printf("%s\n",str);        return NO_ERROR;    }    int32 AllenService::add(int32 a,int32 b){        LOGI("a=%d,b=%d",a,b);        return a+b;    }    int32 AllenService::sub(int32 a,int32 b){        LOGI("a=%d,b=%d",a,b);        return a-b;    }};

5.main_allenservice.cpp

创建好AllenService后,如果想要运行它,就需要有服务客户端和Service Server进程,服务代理运行在服务客户端中,服务运行在Service Server进程中。如下图所示:

client_vs_service

main_allenservice.cpp的代码如下:

12345678910111213
int main(int argc,char** argv){    sp<ProcessState>proc(ProcessState::self());    sp<IServiceManager>sm=defaultServiceManager();    LOGI("ServiceManager: %p",sm.get());    AllenService::instantiate();    ProcessState::self()->startThreadPool();    ProcessState::self()->joinThreadPool();    return 0;}

6.main_allenclient.cpp

main_allenclient.cpp的代码如下:

12345678910111213141516171819202122232425
int main(int argc,char *argv[]){    LOGI("allenservice cleint is now starting");    sp<IServiceManager>sm=defaultServiceManager();    sp<IBinder>binder;    sp<IAllenService>allenService;    do{        binder=sm->getService(String16(ALLEN_DESCRIPTOR));        if(binder!=0)        {            break;        }        LOGI("AllenService is not working,try again...");        usleep(500000);    }while(true);    allenService=interface_cast<IAllenService>(binder);    allenService->print("Hello world!\nI'm Allen and I'm coning.\n");    allenService->add(3,6);    allenService->sub(1,1);    return 0;}

7.编译AllenService系统服务

若想编译AllenService服务代码,需要将AllenService的源码包含进Android平台源码中,再进行整体编译。首先保证头文件在/frameworks/base/include/allen下,源代码文件在/frameworks/base/libs/allen下,而后编写Android.mk文件,编写完成后,将其放到源代码目录中,以便将源代码与Android平台代码一起编译。
Android.mk文件内容如下:

1234567891011121314151617
LOCAL_PATH:=$(call my-dir)include &(CLEAR_VARS)LOCAL_SRC_FILES:= \    IAllenService.cpp \    AllenService.cppLOCAL_SHARED_LIBRARES :=\    libcutils \    libutils \    libbinder \LOCAL_PRELINK_MODULE := falseLOCAL_MODULE :=liballeninclude $(BUILD_SHARED_LIBRARY)

接着,编写运行main_allenservice.cpp和main_allenclient.cpp的Android.mk文件,内容如下:

123456789101112131415161718192021222324252627282930
LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES:= \    main_allenserver.cppLOCAL_SHARED_LIBRARIES := \    libutils \    libbinder \    liballen    base := $(LOCAL_APTH)/../..LOCAL_MODULE:= allenserviceincldue $(BUILD_EXECUTABLE)include $(CLEAR_VARS)LOCAL_SRC_FILES:= \    main_allenclient.cppLOCAL_SHARED_LIBRARIES := \    libutils \    libbinder \    liballenbase :=$(LOCAL_PATH)/../..    LOCAL_MODULE:=allenclientinclude $(BUILD_EXECUTABLE)

 Mar 1st2016 11:59 am  android_deep_analysis

阅读全文
0 0