Android添加一个Native Service
来源:互联网 发布:网络arp检测工具 编辑:程序博客网 时间:2024/05/18 21:49
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
方法,publish
和publishAndJoinThreadPool
函数实现了该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
- Android添加一个Native Service
- 如何添加一个Native Service
- 添加Android Native Service方法
- 如何创建一个Android Native Binder Service
- Android 6.0一个完整的native service
- Android添加一个系统service
- 添加native service
- Android系统开发之七:添加Android Native Service方法
- Android framwork service添加(manager 远程调service,service jni调native code)
- Android framwork service添加(manager 远程调service,service jni调native code)
- android 5.1 如何添加一个系统service
- Android系统添加一个自己的service
- Android Service Framework (Native层的一个例子)
- 制作android native service
- 制作android native service
- android native service
- 【Android Native Code开发系列】六 一个Native Service的完整示例
- 黑马程序员 oc随机 点语法
- HDOJ Cyclic Nacklace 3746【KMP】
- Android MenuItem 设置文字颜色-TextColor的设置
- 详细图解Oracle Exadata存储系统
- oracle 修改数据表字段
- Android添加一个Native Service
- caffe 网络结构几个部分简单介绍
- poj2828(线段树)
- Java中的泛型方法
- UVaOJ 490
- MATLAB聚类
- 设计模式
- vim+tags 安装使用
- Netty官方指南: User guide for 4.x