Android本地服务编写实践

来源:互联网 发布:电脑程序员工资多少 编辑:程序博客网 时间:2024/05/22 00:31
     在android系统中服务是个非常常见的东东,平台的各个层次都有服务这个概念。一开始接触是有点头晕的,不过循序渐进的学习,理清思路还是很有必要的。本地层的服务涉及最广,也最具代表性,今天就先编写个本地层的服务。      android中media类的服务就属于本地层中的服务了,服务使用C/C++实现,一般是一个可执行的二进制文件放在 /system/bin/目录下,由init.rc脚本开机启动,  运用层通过jni+binder来调用。下面我来写个简单的本地层服务CustomNativeService, 然后实现一个android.myservice.CustonNativeService的API类给运用层调用。      写一个服务,首先要搞清楚这个服务提供什么功能,也就是服务接口,这个很关键。CustomNativeService提供一个getState()的服务接口,知道这个后我们实现服务 的接口类ICustomNativeService, 包含一个头文件ICustomNativeService.h ,一个实现文件ICustonNativeService.cpp 。并同时实现binder通信的Bn端和Bp端,然后实现 服务的本地部分CustomNativeService.cpp ,生成可执行文件CustomNativeService。文件层次为:--external\myservice\CustomNativeService\    --common\        --ICustomNativeService.h        --ICustomNativeService.cpp    --CustomNativeService.cpp    --Android.mk   ICustomNativeService.h代码:    #ifndef ICUSTOM_NATIVE_SERVICE_H    #define ICUSTOM_NATIVE_SERVICE_H    #include<utils/RefBase.h>    #include<binder/IInterface.h>    #include<binder/Parcel.h>    using namespace android; //命名空间别搞错,否则编译不过    class ICustomNativeService : public IInterface    {       public :                                        //这些声明是public的,这个很关键         DECLARE_META_INTERFACE(CustomNativeService);  //这个宏主要为接口类声明了一个descriptor属性和一个asInterface方法         virtual int32_t getState() = 0;               //声明我们要提供服务接口    };   /*      下面声明调用服务binder通信时的Bn端,Binder通信时,Bn端为服务的桩(Stub),实现BBinder接口(主要是OnTransact方法)。Bp端为客户端代理,      实现IBinder接口(主要是Transact方法)。每次通信都是客户端调用IBinder的Transact方法,同时触发服务端BBinder的onTransact方法的调用。   */   class BnCustomNativeService : public BnInterface<ICustomNativeService>   {      public:        virtual status_t onTransact(uint32_t code ,const Parcel &data,Parcel *reply,uint32_t flag=0);   };   #endifICustomNativeService.cpp代码:#include"ICustomNativeService.h"#include<utils/Log.h>#define LOG_TAG "ICustomNativeService"using namespace android;enum{    GET_STATE = IBinder::FIRST_CALL_TRANSACTION,    NONE};/*实现通信的Bp端*/class BpCustomNativeService : public BpInterface<ICustomNativeService>{    public:        BpCustomNativeService(const sp<IBinder> &impl) : BpInterface<ICustomNativeService>(impl) {}        int32_t getState()  //客户端调用接口        {            SLOGD("Bp->getState");            Parcel data , reply;            data.writeInterfaceToken(ICustomNativeService::getInterfaceDescriptor());            remote()->transact(GET_STATE,data,&reply);            int32_t state = reply.readInt32();            return state;        }};IMPLEMENT_META_INTERFACE(CustomNativeService,"native.ICustomNativeService");  //这个是头文件中和声明宏对应的实现宏,注意要放在BpCustomNativeService的实现之后。/*重写onTransact方法,注意类型要完全对应,否者会引起onTransact的调用错误*/status_t BnCustomNativeService::onTransact(uint32_t code,const Parcel &data,Parcel *reply,uint32_t flag){  switch(code)  {      case GET_STATE :          {              SLOGD("Bn->getState");              CHECK_INTERFACE(ICustomNativeService,data,reply);              int32_t state = (int32_t)getState();              reply->writeInt32(state);              return NO_ERROR;          }      default:          {              return BBinder::onTransact(code,data,reply,flag);          }  }}CustomNativeService.cpp代码:#include"ICustomNativeService.h"#include<binder/IServiceManager.h>#include<binder/IPCThreadState.h>#include<utils/Log.h>#define LOG_TAG "CustomNativeService"class CustomNativeService : public BnCustomNativeService{    public :   //国际惯例,这两个函数先实现着     CustomNativeService() {}     virtual ~CustomNativeService() {}    public :     int32_t getState()  //实现服务接口     {         SLOGD("getState");         return 168;     }/*android中所有的服务,包括运用层中的服务,都需要向ServiceManager注册,顾名思义,它是管理服务的*/    static void instantiate()     {          /*通过defaultServiceManager方法得到ServiceManager,然后通过addService注册服务*/         defaultServiceManager()->addService(String16("CustomNativeService"),new CustomNativeService());     }};/*实现main,启动binder通信线程池*/     int main(int argc ,char **argv)     {         SLOGD("run main");        CustomNativeService::instantiate();        ProcessState::self()->startThreadPool();        IPCThreadState::self()->joinThreadPool();         return 0;     } Android.mk代码:LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES := \        common/ICustomNativeService.cpp \        CustomNativeService.cpp \LOCAL_SHARED_LIBRARIES := libutils libbinder libcutilsLOCAL_MODULE_TAGS := optionalLOCAL_MODULE := CustomNativeServiceinclude $(BUILD_EXECUTABLE)这样,执行 mmm  external\myservice\CustomNativeService\,就可以得到可执行文件CustomNativeService,在init.rc中添加:service cns /system/bin/CustomNativeService ,在平台启动时CustomNativeService就会跑起来了。下一步来实现一个类,android.myservice.CustomNativeService作为API来调用本地服务的getState方法。分两部分,java部分和JNI部分。java部分: 在framework/base/core/java/android/目录下新建myservice文件夹,在里面新建CustomNativeService.java文件,代码如下:package android.myservice;import android.content.Context;public class CustomNativeService{    Context mContext;    public CustomNativeService(Context mContext)    {        this.mContext = mContext;    }    native int getState();    public int getServiceState()    {       return  getState();    }}JNI部分: 在framework/base/core/jni/下面新建myservice文件夹,在里面新建CustomNativeServiceJNI.cpp ,代码如下:#define LOG_TAG "CustomNativeServiceJNI"#include<ICustomNativeService.h>#include<binder/IServiceManager.h>#include<utils/RefBase.h>#include<binder/IBinder.h>#include<jni.h>#include<JNIHelp.h>#include<android_runtime/AndroidRuntime.h>#include<utils/Log.h>using namespace android;int getState(){    SLOGD("getstate");   sp<IBinder> iBinder = defaultServiceManager()->getService(String16("CustomNativeService"));   if(iBinder != NULL)   {       sp<ICustomNativeService> service = ICustomNativeService::asInterface(iBinder);       return (int)service->getState();   }   else   {       SLOGE("get service failed!");       return 0;   }}static JNINativeMethod method_table[] ={    {"getState","()I",(void*)getState},};int register_android_myservice_CustomNativeService(JNIEnv *env){    return AndroidRuntime::registerNativeMethods(env,"android/myservice/CustomNativeService",method_table,NELEM(method_table));}编写JNI要仔细,这段JNI在libandroid_runtime.so中,如果有错误会导致手机开机停留在开机动画界面。在framework/base/core/jni/Android.mk中加入: LOCAL_SRC_FILES:= \         ......      myservice/CustomNativeServiceJNI.cpp \      ../../../../external/myservice/CustomNativeService/common/ICustomNativeService.cpp \LOCAL_C_INCLUDES += \         ......       external/myservice/CustomNativeService/common \在framework/base/core/jni/AndroidRuntime.cpp中:声明: extern int register_android_myservice_CustomNativeService(JNIEnv *env);在 static const RegJNIRec gRegJNI[] = {  加入:   ......   REG_JNI(register_android_myservice_CustomNativeService),   ......注意,更新API要执行命令 make update-api,然后再执行 make 即可。在运用层中使用服务时,引包即可:import android.myservice.CustomNativeService;    CustomNativeService cns = new CustomNativeService(this);   //注意,this是要继承了Context的    cns.getServiceState();

原创粉丝点击