Native Service初体验

来源:互联网 发布:大数据工程师年薪 编辑:程序博客网 时间:2024/05/29 04:10

    众所周知,Android的服务分Native Service和Android Service两种,为什么一上来就整Native Service呢,原因很简单,因为C++比较上手啊,才怪吐舌头,是因为老大让我做个Service与应用的调研啦。

    接下来就是菜鸟的基本路线,在拿到Android的工程后,了解基本编译指令后,就开始在网上搜索,于是找到博文为Android添加底层核心服务,然后依葫芦画瓢,在framework/base目录下添加自己的工作目录xService,并在里面分别建立两个目录,一个是libxService,用于实现xService类,一个是xServer,用于添加服务到Service Manager中。

    我这里只展示下主要代码,xService类instantiate:

int xService::instantiate(){    sp<IBinder> binder;    sp<IServiceManager> sm = defaultServiceManager();    ALOGD("[xiao] xService instantiate with %p", sm.get());    // 这里主要把xService这个服务添加到Binder Driver中,服务名为guilh.x    int r = sm->addService(String16("xService"), new xService());    ALOGD("[xiao] xService result=%d", r);    return r;}
    这里需要注意的是日志的输出,原文中的LOGE、LOGV之类是一概编译不过的,事实上Native层的输出可以使用cutils/log.h中的ALOG系列,即在前加个A。

    然后就是响应调用:

status_t xService::onTransact(uint32_t code, const Parcel& data, Parcel *reply, uint32_t flags){    ALOGD("[xiao] onTrasact()->enter with code: %d", code);    switch (code) // 根据code的不同执行不同的操作    {    case 0:        {            pid_t pid = data.readInt32();            int num = data.readInt32();            if (8 == num)            {                reply->writeInt32(8);                reply->writeString8(String8("hello world by String8!"));            }            else if (16 == num)            {                reply->writeInt32(16);                reply->writeString16(String16("hello world by String16!"));            }            else            {                reply->writeInt32(num+1000);            }            return NO_ERROR;        }    default:        return BBinder::onTransact(code, data, reply, flags);}
    因为应用层的Parcel类只有readString方法,所以这里我做了个分支确认下实际对应的Native层是哪种String,事实上在我测试中显示是String16类型的。
    另需要注意的有两点:

    1、在写添加服务到Service Manager的应用时,需添加下面这一句,以便让应用生成到system/bin目录下,否则会生成到symbol/system/bin,那么在init.rc中添加因无法找到应用,无法自启动服务。

LOCAL_MODULE_TAGS := eng

    2、如何修改init.rc的问题,如果只是remake工程,可直接修改生成的中间文件mediatek/config/out/[pName]/init.rc或out/target/product/[pName]/root/init.rc,其中[pName]为
实际工程名称,但这种修改会在new后还原,如需在根本上修改,在我这边使用的MTK项目中,则需修改mediatek/config/mt6572/init.rc,不过这个需new才会生效。在init.rc的末尾添加以下这一句:

service xService /system/bin/xServer    class main

    至于在应用中调用服务接口,如按原文做法:   

 IBinder binder = ServiceManager.getService("xService");// 取得服务
    则只能做为内置应用,如想用像普通应用那样在Eclipse中开发调试,刚需可采用以下方法获取服务:

private IBinder getBinderObj(){    IBinder binder = null;    try{        Method m = Class.forName("android.os.ServiceManager").getMethod("getService", new Class[]{String.class});        if(m != null){            Log.d(TAG, "getBinderObj Method:"+m.toString());        }else{            Log.d(TAG, "getBinderObj Method null");        }        binder = (IBinder)m.invoke(null, new Object[]{"xService"});        if(binder != null){            Log.d(TAG, "getBinderObj binder:"+binder.toString());        }else{            Log.d(TAG, "getBinderObj binder null");        }    }catch(Exception e){        Log.d(TAG, "getBinderObj exception:"+e.toString());    }    return binder;}
    这样即可很方便的测试服务。

0 0
原创粉丝点击