热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Androidnative层服务例子Bp和Bn

转入android阵地,被各种权限所阻挠,app写个jni各种没有权限,只能开个native服务,本来android的服务&

转入android阵地,被各种权限所阻挠,app写个jni各种没有权限,只能开个native服务,本来android的服务,就是基于Binder机制所建立的,如果写个简单的服务 只需继承自Bindler, 实现onsTransact(). 参考现成的工程都是 很复杂的 Bp + Bn 好繁杂的样子,所以这里写了个 Bp+Bn 的最简单demo以观其骨架。  工整,perfect!
功能: 一个服务程序,一个测试服务的程序,测试服务程序调用服务中的 say_hello() ,服务端say_hello

环境: android源码,纯native c++ 程序 (不得不BB一下csdn,用Markdownd编辑一贴代码就炸,用文本编辑贴个图就如下,这个鸟样)

代码主题结构:

201908.24 补充:

==========================补充分割线==============================================================

上图补充说明,  BpTestService代理  fun1(),fun2 调用 remote()->  , 这里是关键,在里面实际上 remote()调用已经进入内核调用了,即本进程调用驱动,自己在这里阻塞,Binder驱动从 parcle中解出参数, (parcle实际上是一个共享内存的实现,所以通过parcle传递的”数据“可以跨进程)。 同时,注册的服务端有一个BInder驱动在不停地轮询查看是否有 人请求,这个时候就会获得参数,然后服务侧的进程 开始启动,调用对应函数,完事把结果 打包到parcle传递给驱动,驱动返回到Bp侧,Bp侧进程拿到结果继续执行。

图解:

至于Binder传递数据的过程,有很多博客介绍,比传统ipc通信少一次拷贝,这里不做讨论。

====================补充分割线====================================================================

文件总览:

代码:

/*
* ITestService.h
*/
#ifndef ITESTSERVICE_HEAD_H_
#define ITESTSERVICE_HEAD_H_
#define FORBID_CONSTRUCTORS(name) \name(const name &); \name &operator=(const name &)#include
#include #define TEST_SERVER "TestService_na_tuo_nao_hai" using namespace android;enum {TEST_SER_OPENDOOR,TEST_SER_SAYHELLO,
};class ITestService: public IInterface
{
public ://申明为 interface 这是一个android源码 /frameworks/native/binder IInterface.h中的一个宏定义//注意这里有个坑,用这个宏定义之后一定还要配合另一个宏://IMPLEMENT_META_INTERFACE 在.cpp同时使用,不然编译报错不看宏定义原意真是一脸懵逼DECLARE_META_INTERFACE(TestService);//以下是服务可以提供的方法调用,全部申明为纯虚函数virtual void open_the_door() = 0;virtual void say_hello() = 0;
private://这是一个虚类,禁止构造FORBID_CONSTRUCTORS(ITestService);};
#endif

/*
* ITestService.cpp
*/
#include "ITestService.h"#include "BpTestService.h" //??? 为何要这个头文件? 下面这个宏,展开后会实现一个 asInterface()
//该函数内部 new Bp##INTERFACE(obj); 所以一般看到 Bp类的声明定义都放在 I*.cpp 中
//这里如果缺少这个头文件,报错 error: unknown type name 'BpTestService';IMPLEMENT_META_INTERFACE(TestService, "TestService_na_tuo_nao_hai");

/*
* BpTestService.h
*/
#ifndef BPTESTSERVICE_HEAD__
#define BPTESTSERVICE_HEAD__
#include "ITestService.h"using namespace android;
//注意, 类名, I* Bn* Pn* 三个前缀不同,后面保持一致,不然宏定义又会各种未定义未实现的错误
class BpTestService : public BpInterface
{public://一定要实现这个类型的构造函数 理由看下面注释BpTestService(const sp& impl): BpInterface(impl){}//但是你会发现,最终调用,Bn 实例化了对象,而这个Bp没有主动实例化对象????怎么用?//其实Bp的实例化对象 也在之前的宏定义 IMPLEMENT_META_INTERFACE 中定义的函数//asInterface()中实现实例化对象了 , 所以第一次调用 asInterface() 的时候即 new 了本Bp对象,并且指定调用的// 上面的BpTestService(const sp& impl) 带参数的构造函数//实现全部的 ITestService提供的方法调用//所以到这里,该类已经不是纯虚函数了,可以创建对象了。 Bp 完成virtual void open_the_door() ;virtual void say_hello() ;
};
#endif

/*
* BpTestService.cpp
*/#include "BpTestService.h"void BpTestService::open_the_door()
{
//远程调用 Bn的OnTranscat()Parcel data, reply;data.writeInterfaceToken(ITestService::getInterfaceDescriptor());//Bn端配合检查,避免服务调用错误remote()->transact(TEST_SER_OPENDOOR, data, &reply);
}void BpTestService::say_hello()
{//同理Parcel data, reply;data.writeInterfaceToken(ITestService::getInterfaceDescriptor());//Bn端配合检查,避免服务调用错误remote()->transact(TEST_SER_SAYHELLO, data, &reply);
}

/*
* BnTestService.h
*/
#ifndef BNTESTSERVICE_HEAD__
#define BNTESTSERVICE_HEAD__
#include "ITestService.h"using namespace android;//注意, 类名, I* Bn* Pn* 三个前缀不同,后面保持一致,不然宏定义又会各种未定义未实现的错误
class BnTestService : public BnInterface
{//该类没有完全 实现 ITestService 中的纯虚函数,继承过来纯虚函数,所以自身还是虚类,不能用来创建对象
//所以后续,还有Real_TestService_Bn来实现//但是这里有一个 onTransact 被实现了,这个很重要,ITestService 提供的服务调用全部在它里面转调
//所以这类是一个 转换层。public:virtual int onTransact( uint32_t code,const Parcel& data,Parcel* reply,uint32_t flags = 0);
};
#endif

/*
* BnTestService.cpp
*/
#include "BnTestService.h"int BnTestService::onTransact( uint32_t code,const Parcel& data,Parcel* reply,uint32_t flags )
{//Bn 全部通过改函数转调 到ITestService 公共接口对应的虚函数switch(code){case TEST_SER_OPENDOOR:{//这是 基类ITestService 中的纯虚函数,实现在 派生类Real_TestService_Bn中//所以这个调用会实际调用到 Real_TestService_Bn::open_the_door();CHECK_INTERFACE(ITestService, data, reply);//只是个检查,需要Bp端配合// data.writeInterfaceToken(ITestService::getInterfaceDescriptor()) 使用open_the_door();reply->writeInt32(0);return NO_ERROR;}break;case TEST_SER_SAYHELLO:{//同理open_the_door CHECK_INTERFACE(ITestService, data, reply);say_hello();reply->writeInt32(0);return NO_ERROR;}break;default:return BBinder::onTransact(code, data, reply, flags);}return NO_ERROR;
}

/*
* Real_TestService_Bn.h
*/
#ifndef REAL_TEST_SERVICE_BN_HEAD__
#define REAL_TEST_SERVICE_BN_HEAD__
#include "BnTestService.h"//#define TEST_SERVER "TestService_na_tuo_nao_hai"
class Real_TestService_Bn : public BnTestService
{
public ://必备,服务发布static void publishService();//因为基类 ITestService 的宏定义 DECLARE_META_INTERFACE 中把其析构函数申明成虚函数了。//避免把本 类的对象指针 向上转型成 基类指针,然后析构的时候,只调用到基类的析构。所以这里派生类//的析构函数也申明成 虚函数virtual ~Real_TestService_Bn();//这里就要全部实现父类的纯虚函数virtual void open_the_door() ;virtual void say_hello() ;private://static ,一个服务就行static Real_TestService_Bn* sTestService;
};
#endif

/*
* Real_TestService_Bn.cpp
*/
#include "Real_TestService_Bn.h"#include Real_TestService_Bn* Real_TestService_Bn::sTestService = NULL;
void Real_TestService_Bn::publishService()
{if(sTestService == NULL){sTestService = new Real_TestService_Bn();//注册服务defaultServiceManager()->addService(String16(TEST_SERVER),sTestService);}
}Real_TestService_Bn:: ~Real_TestService_Bn()
{}void Real_TestService_Bn::open_the_door()
{//服务提供的功能printf("open_the_door!! welcom ![%d%s]\n",__LINE__,__FUNCTION__);
}void Real_TestService_Bn::say_hello()
{//服务提供的功能printf("say_hello !! hello! [%d%s]\n",__LINE__,__FUNCTION__);
}

/*
* Main_TestService.cpp
*/
#include "Real_TestService_Bn.h"#include
#include
#include int main(int argc , const char* argv[])
{Real_TestService_Bn::publishService();ProcessState::self()->startThreadPool();IPCThreadState::self()->joinThreadPool();
}

/*
* Main_Client.cpp
*/
#include "BpTestService.h"//客户端,只需要Bp代理#include int main(int argc, const char*argv[])
{//首先,获取服务. 通过名称确定sp binder = defaultServiceManager()->getService(String16(TEST_SERVER));//这里就搞事情了, 这个 interface_cast 函数就是 之前在 ITestService.cpp 中用 宏IMPLEMENT_META_INTERFACE//定义的一个模板函数,其内部会调用 一次 new Bp##INTERFACE(obj); (只会创建一个,后续直接获取)//这个 构造函数就是 BpTestService 中要求实现的那个构造函数。 sp Bp_client = interface_cast(binder); //现在,Bn 和Bp 对象都有了。 本程序拥有 Bp对象,服务程序用于Bn对象。//不过 interface_cast 模板函数返回的是 Bn Bp的统一基类 ITestService*//下面这个调用过程,虚函数的一个经典释义: 以基类之指针指向派生类之对象,调用的是派生类的方法// 所以 先调用到Bp中的 对应实现 open_the_door();->//然后Bp中用remote() 进行了一波远程调用操作,全部调用到 Bn的 onTransact ->//还是虚函数的作用,Bn的onTranscat调用全部到了 BnTestService中实现的 onTranscat()->//而这个 BnTestService中的onTranscat(),其实又没做正经事,有把所有case 都一一对应到其派生类 Real_TestService_Bn 中的各个函数//这样就从Bp的 open_the_door() -> Bn::onTranscat -> Bn::open_the_door()Bp_client->open_the_door();Bp_client->say_hello();}

#Android.mk
ROOT_DIR := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PATH := $(ROOT_DIR)#头文件目录
LOCAL_C_INCLUDES := $(TOP)/frameworks/native/include/gui
LOCAL_C_INCLUDES += $(TOP)/frameworks/native/include/input
LOCAL_C_INCLUDES += $(TOP)/frameworks/base/include/#需要连接的库
LOCAL_SHARED_LIBRARIES += liblog
LOCAL_SHARED_LIBRARIES += libutils
LOCAL_SHARED_LIBRARIES += libcutils
LOCAL_SHARED_LIBRARIES += libc
LOCAL_SHARED_LIBRARIES += libbinder#编译的源文件
LOCAL_SRC_FILES := ITestService.cpp \BpTestService.cpp \BnTestService.cpp \Real_TestService_Bn.cpp \Main_TestService.cpp LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS += -DPLATFORM_ANDROID
#编译输出的模块名称
LOCAL_MODULE:= wang_test_server#编译为可执行程序
include $(BUILD_EXECUTABLE)
#include $(BUILD_SHARED_LIBRARY)#==================================================================================
#分割线---------------------------------------------------------------------
#测试服务
#==================================================================================
#ROOT_DIR := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PATH := $(ROOT_DIR)#头文件目录
LOCAL_C_INCLUDES := $(TOP)/frameworks/native/include/gui
LOCAL_C_INCLUDES += $(TOP)/frameworks/native/include/input
LOCAL_C_INCLUDES += $(TOP)/frameworks/base/include/#需要连接的库
LOCAL_SHARED_LIBRARIES += liblog
LOCAL_SHARED_LIBRARIES += libutils
LOCAL_SHARED_LIBRARIES += libcutils
LOCAL_SHARED_LIBRARIES += libc
LOCAL_SHARED_LIBRARIES += libbinder#编译的源文件
#这两处 ITestService.cpp 和BpTestService.cpp 同服务端编译有些重叠
#因为 ITestService.cpp 是 Bp和Bn共用的,都需要,而ITestService.cpp 其中又需要 依赖 BpTestService.cpp
#所以一般 BpTestService.cpp 和 ITestService.cpp 写在一起编译成一个库 ,这里全部单独分开,为了方便看其本质
LOCAL_SRC_FILES := ITestService.cpp \BpTestService.cpp \Main_Client.cpp LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS += -DPLATFORM_ANDROID
#编译输出的模块名称
LOCAL_MODULE:= wang_test_server_client#编译为可执行程序
include $(BUILD_EXECUTABLE)
#include $(BUILD_SHARED_LIBRARY)


推荐阅读
  • 手把手教你构建简易JSON解析器
    本文将带你深入了解JSON解析器的构建过程,通过实践掌握JSON解析的基本原理。适合所有对数据解析感兴趣的开发者。 ... [详细]
  • OpenWrt 是一款高度可定制的嵌入式 Linux 发行版,广泛应用于无线路由器等领域,拥有超过百个预装软件包。本文详细探讨如何在 OpenWrt 上通过 Luci 构建自定义模块,以扩展其功能。 ... [详细]
  • 本文介绍了如何在 Linux 系统上构建网络路由器,特别关注于使用 Zebra 软件实现动态路由功能。通过具体的案例,展示了如何配置 RIP 和 OSPF 协议,以及如何利用多路由器查看工具(MRLG)监控网络状态。 ... [详细]
  • 本文深入探讨了Java注解的基本概念及其在现代Java开发中的应用。文章不仅介绍了如何创建和使用自定义注解,还详细讲解了如何利用反射机制解析注解,以及Java内建注解的使用场景。 ... [详细]
  • 本文介绍了如何在三台CentOS 7.5虚拟机上通过Docker部署RabbitMQ集群,包括环境准备、容器创建、集群配置及故障处理等内容。 ... [详细]
  • 本文详细介绍了C++标准模板库(STL)中各容器的功能特性,并深入探讨了不同容器操作函数的异常安全性。 ... [详细]
  • 首先说一下,这是我在CSDN上的第一个文章,其实这个账号早在几年前就申请了,不过当时只是为了下载一个资源,而且也不怎么懂信息技术相关的领域,后来就再也没怎么动过,直到今天我才开始使用这个账号 ... [详细]
  • 本文深入探讨了企业级开发框架NHibernate和Spring.NET的关键特性之一——面向方面编程(AOP)。文章不仅介绍了AOP的基本概念及其如何增强面向对象编程(OOP),还详细说明了Spring.NET中AOP的具体应用,包括事务管理和自定义方面的实现。 ... [详细]
  • 今天我在操作Git时遇到了一个问题,即我的仓库进入了分离的HEAD状态,这与之前讨论过的‘即使本地有更改,git push仍显示所有内容最新’的问题类似。 ... [详细]
  • Redis 教程01 —— 如何安装 Redis
    本文介绍了 Redis,这是一个由 Salvatore Sanfilippo 开发的键值存储系统。Redis 是一款开源且高性能的数据库,支持多种数据结构存储,并提供了丰富的功能和特性。 ... [详细]
  • 本文探讨了为何采用RESTful架构及其优势,特别是在现代Web应用开发中的重要性。通过前后端分离和统一接口设计,RESTful API能够提高开发效率,支持多种客户端,并简化维护。 ... [详细]
  • UnityNGUIScrollView苹果式滑动
    又回来写博客了,这回已经开始上班了,所以就发一发工作中解决的难题吧。单个展示Panel(苹果式)以前对UI的滑动组件很烦心,不是很会用,这回项目要求写一个类似于苹果的文件滑动效果, ... [详细]
  • 开发笔记:新手DVWACSRF
    开发笔记:新手DVWACSRF ... [详细]
  • 本文通过具体示例探讨了在 C++ 中使用 extern "C" 的重要性及其作用,特别是如何影响编译后的对象文件中的符号名称。 ... [详细]
  • 本文详细介绍了Java中`org.sakaiproject.site.api.Site.addPage()`方法的功能和使用方法,并提供了多个实际项目中的代码示例。 ... [详细]
author-avatar
v88v的秋天
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有