Android NDK开发详解之JNI中的库文件
Android NDK开发详解之JNI中的库文件
- 简介
- 工作原理
- 流程
- 原生 activity 和应用
简介
本部分简要介绍了 NDK 的工作原理。Android NDK 是一组使您能将 C 或 C++(“原生代码”)嵌入到 Android 应用中的工具。能够在 Android 应用中使用原生代码对于想执行以下一项或多项操作的开发者特别有用:
在平台之间移植其应用。重复使用现有库,或者提供其自己的库供重复使用。在特定情况下提高性能,特别是像游戏这种计算密集型应用。
工作原理
本部分介绍了在为 Android 构建原生应用时使用的主要组件,并且介绍了构建和封装过程。
主要组件
在构建应用时,您应该已经了解以下组件:
原生共享库:NDK 从 C/C++ 源代码构建这些库或 .so 文件。原生静态库:NDK 也可构建静态库或 .a 文件,而您可将静态库关联到其他库。Java 原生接口 (JNI):JNI 是 Java 和 C++ 组件用于相互通信的接口。本指南假设您具备 JNI 知识;如需了解相关信息,请查阅 Java 原生接口规范。应用二进制接口 (ABI):ABI 可以非常精确地定义应用的机器代码在运行时应该如何与系统交互。NDK 根据这些定义构建 .so 文件。不同的 ABI 对应不同的架构:NDK 为 32 位 ARM、AArch64、x86 及 x86-64 提供 ABI 支持。如需了解详情,请参阅 Android ABI。清单:如果您编写的应用不包含 Java 组件,必须在清单中声明 NativeActivity 类。要详细了解如何执行此操作,请参阅使用 native_activity.h 接口。
流程
为 Android 开发原生应用的一般流程如下:
设计应用,确定要使用 Java 实现的部分,以及要以原生代码形式实现的部分。注意:虽然可以完全避免使用 Java,但您可能会发现 Android Java 框架对于控制显示和界面等任务很有用。像创建任何其他 Android 项目一样创建一个 Android 应用项目。如果要编写纯原生应用,请在 AndroidManifest.xml 中声明 NativeActivity 类。如需了解详情,请参阅原生 activity 和应用。在“JNI”目录中创建一个描述原生库(包括名称、标记、关联库和要编译的源文件)的 Android.mk 文件。或者,您也可以创建一个配置目标 ABI、工具链、发布/调试模式和 STL 的 Application.mk 文件。对于其中任何您未指明的项,将分别使用以下默认值:ABI:所有非弃用的 ABI模式:发布STL:系统将原生源代码放在项目的 jni 目录下。使用 ndk-build 编译原生(.so、.a)库。构建 Java 组件,生成可执行 .dex 文件。将所有内容封装到一个 APK 文件中,包括 .so、.dex 以及应用运行所需的其他文件。
原生 activity 和应用
Android SDK 提供了辅助类 NativeActivity,可用于编写完全原生的 activity。NativeActivity 可处理 Android 框架与原生代码之间的通信,因此您不必子类化该类或调用其方法,而只需在 AndroidManifest.xml 文件中将您的应用声明为原生应用,然后开始创建该原生应用。
使用 NativeActivity 的 Android 应用仍会在其自己的虚拟机中运行,与其他应用以沙盒的形式分隔。因此,您仍可通过 JNI 访问 Android 框架 API。在某些情况下(例如对于传感器、输入事件和资源),NDK 提供可使用的原生接口,而无需通过 JNI 调用。如需详细了解此类支持,请参阅原生 API。
无论是否要开发原生 activity,我们都建议使用传统 Android 构建工具创建项目。这样有助于确保使用正确的结构构建和封装 Android 应用。
Android NDK 为实现原生 activity 提供两个选项:
native_activity.h 头文件会定义 NativeActivity 类的原生版本。其中包含创建原生 activity 所需的回调接口和数据结构。由于应用的主线程会处理回调,因此回调实现不能阻止主线程,否则可能会收到 ANR(应用无响应)错误,因为主线程在回调返回之前无响应。android_native_app_glue.h 文件会定义基于 native_activity.h 接口构建的静态辅助库。它会派生出另一个线程,用于处理事件循环中的回调或输入事件等。将这些事件移至单独的线程可防止任何回调阻止主线程。
此外,<ndk_root>/sources/android/native_app_glue/android_native_app_glue.c 源代码也可供使用,使您能够修改实现。
如需详细了解如何使用此静态库,请查看原生 activity 示例应用及其文档。<ndk_root>/sources/android/native_app_glue/android_native_app_glue.h 文件中的注释提供了更多其他信息。
使用 native_activity.h 接口
要使用 native_activity.h 接口实现原生 activity,请执行以下操作:
在项目的根目录中创建一个 jni/ 目录。此目录用于存储所有原生代码。在 AndroidManifest.xml 文件中声明原生 activity。由于您的应用没有 Java 代码,因此请将 android:hasCode 设为 false。
<application android:label="@string/app_name" android:hasCode="false">
您必须将 activity 标记的 android:name 属性设置为 NativeActivity。
<activity android:name="android.app.NativeActivity"android:label="@string/app_name">
注意:您可以子类化 NativeActivity。如果子类化该类,请使用子类的名称,而不是 NativeActivity。
meta-data 标记的 android:value 属性会指定共享库的名称,其中包含应用的入口点(例如 C/C++ main),省略库名的 lib 前缀和 .so 后缀。
<manifest><application><activity><meta-data android:name="android.app.lib_name"android:value="native-activity" /><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application>
</manifest>
创建用于原生 activity 的文件,并实现 ANativeActivity_onCreate 变量中指定的函数。应用在原生 activity 启动时会调用此函数。此函数类似于 C/C++ 中的 main,它会接收 ANativeActivity 结构的指针,其中包含您需要编写的各个回调实现的函数指针。在 ANativeActivity->callbacks 中设置回调实现的适用回调函数指针。
将 ANativeActivity->instance 字段设置为您要使用的特定数据的任何实例的地址。
实现您希望 activity 在启动时执行的任何其他操作。
实现您在 ANativeActivity->callbacks 中设置的其余回调。如需详细了解何时调用回调,请参阅管理 activity 生命周期。
开发应用的其余部分。
在项目的 jni/ 目录中创建 Android.mk file,向构建系统描述您的原生模块。如需了解详情,请参阅 Android.mk。
创建 Android.mk 文件后,使用 ndk-build 命令编译原生代码。
cd <path>/<to>/<project>
$NDK/ndk-build
像平常一样构建和安装 Android 项目。如果原生代码存放在 jni/ 目录中,构建脚本会自动将从原生代码构建的 .so 文件封装到 APK 中。
相关文章:
Android NDK开发详解之JNI中的库文件
Android NDK开发详解之JNI中的库文件 简介工作原理流程原生 activity 和应用 简介 本部分简要介绍了 NDK 的工作原理。Android NDK 是一组使您能将 C 或 C(“原生代码”)嵌入到 Android 应用中的工具。能够在 Android 应用中使用原生代码对于想执行以下…...
KNN模型
使用K-Nearest Neighbors (KNN)算法进行分类。首先加载一个数据集,然后进行预处理,选择最佳的K值,并训练一个KNN模型。 # encodingutf-8 import numpy as np datas np.loadtxt(datingTestSet2.txt) # 加载数据集,返回一个numpy数…...
Python 学习1 基础
文章目录 基础字符串字面量常用的值类型注释变量print语句数据类型数据类型转换标识符运算符 字符串拓展小结 2023.10.28 周六 最近打算学一下Python,毕竟确实简单方便,而且那个编程语言排名还是在第一。不过不打算靠它吃饭,深不深入暂且不说…...
网络协议--TCP的超时与重传
21.1 引言 TCP提供可靠的运输层。它使用的方法之一就是确认从另一端收到的数据。但数据和确认都有可能会丢失。TCP通过在发送时设置一个定时器来解决这种问题。如果当定时器溢出时还没有收到确认,它就重传该数据。对任何实现而言,关键之处就在于超时和重…...
Thread
Thread 线程启动线程第一种创建线程线程的第二种创建方式使用匿名内部类完成线程的两种创建 Thread API线程的优先级线程提供的静态方法守护线程用户线程和守护线程的区别体现在进程结束时 多线并发安全问题同步块 线程 启动线程 启动线程:调用线程的start方法,而不是直接调用…...
FOC系列(二)----继续学习DRV8301芯片
一、 程序框图 跟随上篇博客咱们继续往下看,下面是芯片内部的程序框图: 1.1 BUCK电路 1.2 内部各电源 1.3 SPI通信、栅极驱动器和时序控制器 1.4 MOSFET驱动电路 1.5 电流采样放大电路 数据手册只是给出了这一部分框图,但是没有更加详细的介…...
A. Directional Increase -前缀和与差分理解 + 思维
题面 分析 观察指针移动的性质,可以发现每一段都是从起点走到终点,在原路返回,这样每一段也就表示,在起点处加一,在终点处减一,形成了很明显的差分结构,思考能否构造出a数组的关键就是他的前缀…...
openpnp - java调试环境 - 最好只保留一套jdk环境
文章目录 openpnp - java调试环境 - 最好只保留一套jdk环境概述END openpnp - java调试环境 - 最好只保留一套jdk环境 概述 没注意做了啥操作, 前天好好的, 昨天下午开始, 编译好的openpnp程序就无法正常打开了. 故障表现: 程序运行后, 最多只能看到欢迎对话框(显示版本和发…...
AI技术的钓鱼邮件有多强
如今,人工智能技术的迅猛发展给各个领域都带来了前所未有的变革和进步。2023年上半年ChatGPT的火爆出圈,让人们看到了AI惊艳表现的光彩一面,但同时黑暗的一面也正在暗自发力,野蛮生长。 AI技术不仅可用于维护网络安全,…...
vue/react项目刷新页面出现404报错的原因及解决办法
Vue项目打包部署到线上后,刷新页面会提示404,下面这篇文章主要给大家介绍了关于vue/react项目刷新页面出现404报错的原因及解决办法,文中将解决的办法介绍的很详细,需要的朋友可以参考下 背景解决办法 法1:将vue/react路由模式由history路由改为has…...
黑客技术(网络安全)——如何高效学习
前言 前几天发布了一篇 网络安全(黑客)自学 没想到收到了许多人的私信想要学习网安黑客技术!却不知道从哪里开始学起!怎么学 今天给大家分享一下,很多人上来就说想学习黑客,但是连方向都没搞清楚就开始学习…...
53.MongoDB分片集群高级集群架构详解
MongoDB分片集群架构详解 为什么要使用分片 分片(shard)是指在将数据进行水平切分之后,将其存储到多个不同的服务器节点上的一种扩展方式。 一个复制集能承载的容量和负载是有限的,遇到以下场景就需要考虑使用分片 存储容量需…...
Servlet 上下文参数
7)Servlet上下文对象:ServletContext生活中的例子:张三和李四在不远处窃窃私语,并且频繁的对着你坏笑。你肯定会跑过去问:你们俩在聊什么?注意:此处的聊什么,其实就是你在咨询他们聊天的上下文&…...
ChatGPT正在测试原生文件分析功能,DALL·E 3能P图啦!
10月29日,有部分用户在社交平台上分享,ChatGPT Plus正在测试原生文件上传、分析功能,可以通过文本问答的方式,对上传的PDF等数据文件进行提问、搜索。 例如,上传一份50页的员工手册PDF文件,然后向ChatGPT提…...
三相马达的电机故障维护
目录 电机故障维护编辑 更换电机操作 三相电路 热继电器 今天继续小编的工作经验的分享,今天就说说遇到的问题吧,今天组立熔接机出现故障,后面部分出现了“咕噜噜”的杂声,走到后面一听是电机发出的声音。没有办法了就开始拆…...
【易售小程序项目】后端部署、Uniapp项目Web部署
文章目录 Uniapp项目Web打包部署为什么不部署小程序Web打包前对项目进行调整网站、小程序切换增加constant.js来控制常量将js绑定到main.js的全局变量中 WebSocket差异监听键盘呼出导航条打包部署 后端项目打包部署打包前准备打包部署 Uniapp项目Web打包部署 为什么不部署小程…...
prometheus监控kafka
一、前言 关于对kafka的监控,要求高的话可以使用kafka-exorter和jmx-exporter一起收集监控数据,要求不高的情况下可以使用kafka-exporter收集监控数据即可 二、部署 kafka-exporter 部署kafka-exporter,我是在k8s集群中部署的 编辑yaml文件…...
【STL】:list用法详解
朋友们、伙计们,我们又见面了,本期来给大家解读一下有关list的使用,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成! C 语 言 专 栏:C语言:从入门到精通 数据结构…...
SQL Wildcards 通配符
SQL Wildcards 通配符 通配符用于替换字符串中的任何其他字符。 通配符与 SQL LIKE 运算符一起使用。在 WHERE 子句中使用LIKE运算符来搜索列中的指定模式。 有两个通配符与 LIKE 运算符一起使用: % - 百分号表示零个,一个或多个字符_ - 下…...
入门必学 | R语言for循环的常规应用
文章目录 何为判断语句在for循环中添加判断语句嵌套循环 在上一节中,我们介绍了迭代与for循环,并对for循环的结构与原理进行了深入的介绍。在这一节中,我们将分享for循环的常规应用,包括在其中加入判断语句与嵌套循环。 何为判断语…...
造相 Z-Image镜像使用指南:显存监控条预警机制与OOM防护策略
造相 Z-Image镜像使用指南:显存监控条预警机制与OOM防护策略 1. 引言:为什么你的AI绘画服务总崩溃? 如果你用过一些开源的文生图模型,大概率遇到过这种情况:兴致勃勃地输入一段描述,点击生成,…...
Keil开发中printf重定向的常见陷阱与高效配置指南
1. 为什么你的printf在Keil里"装死"? 第一次在Keil里用printf的新手,八成会遇到这样的灵异事件:明明代码逻辑没问题,烧录后串口助手却像黑洞一样安静。我当年调试STM32F103时,整整两天都在和这个"哑巴&…...
3D Face HRN快速上手:无需代码,Gradio界面三步完成人脸重建
3D Face HRN快速上手:无需代码,Gradio界面三步完成人脸重建 1. 从一张照片到3D人脸,只需三步点击 你是否曾想过,将一张普通的自拍照或证件照,瞬间转化为一张可用于3D建模、游戏角色或虚拟形象的“皮肤地图”…...
[特殊字符] Nano-Banana效果对比:Turbo LoRA vs 原生SDXL拆解精度实测
Nano-Banana效果对比:Turbo LoRA vs 原生SDXL拆解精度实测 最近在折腾AI生成产品拆解图,发现了一个挺有意思的项目——Nano-Banana。这玩意儿号称是专门为产品拆解、平铺展示风格设计的轻量级文生图系统。 我一开始用原生的SDXL模型生成拆解图…...
VRRP配置里这个‘坑’你踩过吗?详解track监视上行链路与流量黑洞问题
VRRP高可用架构中的隐形陷阱:深度解析上行链路监控与流量黑洞解决方案 当企业核心网络的网关设备突然"失联",但设备状态灯却依然闪烁着健康的绿色,这种看似矛盾的故障场景往往让运维团队陷入困境。上周深夜,某金融公司就…...
OpenClaw定时任务专家:用Qwen3-32B镜像实现凌晨自动备份与报表生成
OpenClaw定时任务专家:用Qwen3-32B镜像实现凌晨自动备份与报表生成 1. 为什么需要定时任务自动化 作为一个经常需要处理数据库和报表的开发者,我发现自己总是在重复同样的工作:每天凌晨备份数据库、生成统计报表、然后发送给相关同事。这种…...
抖音弹幕抓取终极指南:如何利用系统代理技术实现免费数据监听
抖音弹幕抓取终极指南:如何利用系统代理技术实现免费数据监听 【免费下载链接】DouyinBarrageGrab 基于系统代理的抖音弹幕wss抓取程序,能够获取所有数据来源,包括chrome,抖音直播伴侣等,可进行进程过滤 项目地址: h…...
免费开源策略卡牌:如何在无名杀中创造你的专属三国战场
免费开源策略卡牌:如何在无名杀中创造你的专属三国战场 【免费下载链接】noname 项目地址: https://gitcode.com/GitHub_Trending/no/noname 在当今数字游戏世界中,有一款独特的开源策略卡牌游戏正悄然改变着玩家与游戏的关系。这款名为"无…...
别再只用总基尼系数了!用Python实现Dagum分解,看清区域差距的‘里子’
用Python拆解经济差距:Dagum基尼系数分解实战指南 当一份区域经济报告只给出一个总的基尼系数时,就像医生只告诉你"体温偏高"却不说明是哪个器官发炎——数据研究者常陷入这种诊断困境。传统基尼系数虽能反映整体不平等程度,却无法…...
AgentScope-Java:以 Agentic 为核心设计,构建可推理、可记忆、可扩展的生产级智能体系统
AgentScope-Java:以 Agentic 为核心设计,构建可推理、可记忆、可扩展的生产级智能体系统 副标题:从 ReActAgent、ReMe 记忆管理到高并发工程化落地,系统讲透 AgentScope-Java 的架构原理与企业级实践 一、为什么企业需要的不是“接个大模型”,而是 Agentic 系统 过去两年…...
