Android NDK开发入门2之适应idm环境
环境搭建
Android NDK开发实战之环境搭建篇(so库,Gemini ai)-CSDN博客
初始配置
前面已经运行了一个简单的初始程序,现在我们来往初始程序添加类和函数,并成功运行的实验。
一级配置
第一层配置主要是cmake文件环境和一些编译选项。

build配置 可参考:
#build配置externalNativeBuild {cmake {path file('src/main/cpp/CMakeLists.txt')version '3.22.1'//cpp 编译选项cppFlags '-fexceptions -std=c++11'//设置c++stl为动态库 默认是静态库 arguments '-DANDROID_STL=c++_shared'}}


二级cmake配置
主要配置生成的动态库名称,具体看注释
为了测试 我们创建一个hello类
#include "iostream"
class hello {
public:std::string getVersion();
};
#include "hello.h"
std::string hello::getVersion(){return "v1.0 hello word";
}
#include <jni.h>
#include <string>#include "hello.h"
extern "C" JNIEXPORT jstring JNICALL
//stringFromJNI是c++function名称
Java_com_example_first_1ndk_1cpp_MainActivity_stringFromJNI(JNIEnv* env,jobject /* this */) {std::string helo = "Hello from first native C++ ";hello h;helo += h.getVersion();return env->NewStringUTF(helo.data());
}
更改cmake,把cpp文件加入
#cmake最低版本
cmake_minimum_required(VERSION 3.22.1)#最终项目名称 通过${CMAKE_PROJECT_NAME}获得
project("first_ndk_cpp")add_library(#生成的动态库名称${CMAKE_PROJECT_NAME}#生成库类型:SHARED动态 默认静态SHARED#相关cpp文件 假设有全局变量,交叉使用需要注意编译顺序。native-lib.cpphello.cpp)target_link_libraries(#最终生成目标库名称${CMAKE_PROJECT_NAME}# 链接其他目标库androidlog)
MainActivity
MainActivity 通常被认为是 Android 应用程序的主要入口点。

public class MainActivity extends AppCompatActivity {// 静态初始化块, 程序启动时调用static {//加载名为 first_ndk_cpp 的动态库System.loadLibrary("first_ndk_cpp");}private ActivityMainBinding binding;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//视图绑定binding = ActivityMainBinding.inflate(getLayoutInflater());setContentView(binding.getRoot());// Example of a call to a native methodTextView tv = binding.sampleText;tv.setText(stringFromJNI()); //java调用}/**这声明了一个名为 stringFromJNI 的本地方法。该实现位于 first_ndk_cpp 库中。*/public native String stringFromJNI();
}
运行
最后运行输出

小结
熟悉基本配置,知道增加类代码如何重新编译成动态库使用。
动态库实战
场景:编译两份版本动态库 分别输出v1和v2,然后切换运行。
设置动态库导出路劲
前面操作,我们成功编译出动态库。但是路劲很隐蔽,其次规范处理。

实现方法
CMakeLists.txt 设置导出so路劲:
CMAKE_ARCHIVE_OUTPUT_DIRECTORY :默认存放静态库的⽂件夹位置; CMAKE_LIBRARY_OUTPUT_DIRECTORY :默认存放动态库的⽂件夹位置;
# 第一种做法:单独设置动态库的默认输出路径
# 将动态库输出到 `main/jniLibs/${ANDROID_ABI}` 目录
# ${ANDROID_ABI} 是 Gradle 配置的 ABI 策略(如 armeabi-v7a, arm64-v8a 等)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY${CMAKE_CURRENT_SOURCE_DIR}/../libs/jniLibs/${ANDROID_ABI})# 第二种做法:设置动态库和静态库的默认输出路径
# 将动态库和静态库输出到 `main/jniLibs/${ANDROID_ABI}` 目录
# 注意:LIBRARY_OUTPUT_PATH 是旧版 CMake 的变量,
#推荐使用 CMAKE_LIBRARY_OUTPUT_DIRECTORY 和 CMAKE_ARCHIVE_OUTPUT_DIRECTORY
set(LIBRARY_OUTPUT_PATH${CMAKE_CURRENT_SOURCE_DIR}/../libs/jniLibs/${ANDROID_ABI})


根据这个方法步骤编译两个版本
主要区别:
std::string hello::getVersion(){return "v2.0 hello word";
}

尝试版本切换

//定义项目的源代码和资源文件的目录结构sourceSets {main {//指定 JNI 库文件(.so 文件)的存放目录jniLibs.srcDirs = ['src/main/libs/jniLibs']}}
小结
学习如何指定动态库导出路劲,并根据动态库切换,实现多种版本调用。
特定cpu架构实战
上述讨论了如何导出不同的动态库,现在如果只想根据x86架构导出单个so库如何实现?
先看看为什么需要指定cpu
⽣成指定cpu平台对应的so库⽂件

应⽤⼆进制接⼝(ABI),包含的内容:
1、可执⾏⼆进制⽂件的格式以及⽀持的内容类型,⼆进制⽂件如:程序、共享库...
2、可使⽤的CPU指令集
3、运⾏时内存存储和加载的字节顺序
4、应⽤和系统之间传递数据的规范,以及系统调⽤函数时,如何使⽤堆栈、寄存器
5、如何重整C++名称
abi与 指令集

Android 支持多种 CPU 架构,每种架构对应不同的 ABI。以下是常见的 CPU 架构及其对应的 ABI:
| CPU 架构 | ABI | 说明 |
|---|---|---|
| ARMv5 | armeabi | 32 位 ARM 架构,已过时,Android NDK r17 已不再支持。 |
| ARMv7 | armeabi-v7a | 32 位 ARM 架构,支持硬件浮点运算和 NEON 指令集。 |
| ARMv8 | arm64-v8a | 64 位 ARM 架构,支持 AArch64 指令集。 |
| MIPS | mips | 32 位 MIPS 架构,已过时,Android NDK r17 已不再支持。 |
| MIPS64 | mips64 | 64 位 MIPS 架构,已过时,Android NDK r17 已不再支持。 |
| x86 | x86 | 32 位 Intel x86 架构,主要用于模拟器和部分低端设备。 |
| x86_64 | x86_64 | 64 位 Intel x86 架构,主要用于模拟器和高性能设备。 |
ABI 兼容性是指应用程序在不同 CPU 架构上的运行能力。以下是各 ABI 的兼容性说明:
| ABI | 兼容性说明 |
|---|---|
armeabi | 兼容 ARMv5 和 ARMv7,但不兼容 ARMv8(64 位)。 |
armeabi-v7a | 兼容 ARMv7,但不兼容 ARMv5 和 ARMv8(64 位)。 |
arm64-v8a | 兼容 ARMv8(64 位),但不兼容 ARMv5 和 ARMv7(32 位)。 |
mips | 仅兼容 MIPS 架构,已过时。 |
mips64 | 仅兼容 MIPS64 架构,已过时。 |
x86 | 兼容 x86 架构,同时兼容 armeabi 和 armeabi-v7a(通过二进制翻译运行)。 |
x86_64 | 兼容 x86_64 架构,同时兼容 arm64-v8a(通过二进制翻译运行)。 |
x86 和 x86_64 的特殊性
x86:主要用于模拟器和部分低端设备。通过二进制翻译,可以运行 armeabi 和 armeabi-v7a 的代码,但性能较低。
x86_64:主要用于模拟器和高性能设备。通过二进制翻译,可以运行 arm64-v8a 的代码。
ABI 配置
在 Android 项目中,可以通过 Gradle 配置支持的 ABI。
android {defaultConfig {ndk {abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'}}
}
小结
ARM 架构:armeabi-v7a 和 arm64-v8a 是当前主流的架构。
x86 架构:主要用于模拟器,通过二进制翻译可以运行 ARM 架构的代码。
ABI 配置:通过 Gradle 的 abiFilters 指定支持的 ABI。
问题
当遇到不能run,编译没错误信息,则进行sync now即可解决

学习资料分享
0voice · GitHub
相关文章:
Android NDK开发入门2之适应idm环境
环境搭建 Android NDK开发实战之环境搭建篇(so库,Gemini ai)-CSDN博客 初始配置 前面已经运行了一个简单的初始程序,现在我们来往初始程序添加类和函数,并成功运行的实验。 一级配置 第一层配置主要是cmake文件环境和一些编译选项。 build配置 可参…...
如何隐藏 Nginx 版本号 并自定义服务器信息,提升安全性
🏡作者主页:点击! Nginx-从零开始的服务器之旅专栏:点击! 🐧Linux高级管理防护和群集专栏:点击!点击!点击! ⏰️创作时间:2025年1月8日8点14分…...
鸿蒙的APP真机调试以及发布
目录: 1、创建好鸿蒙项目2、创建AGC项目3、实现自动签名3.1、手动方式创建签名文件和密码 4、运行项目5、无线真机调试 1、创建好鸿蒙项目 2、创建AGC项目 (1)在File->Project Structure->Project->Signing Configs中进行登录。(未…...
图像处理|膨胀操作
在图像处理领域,形态学操作是一种基于图像形状的操作,用于分析和处理图像中对象的几何结构。**膨胀操作(Dilation)**是形态学操作的一种,它能够扩展图像中白色区域(前景)或减少黑色区域…...
攻防世界 ics-07
点击之后发现有个项目管理能进,点进去,点击看到源码,如下三段 <?php session_start(); if (!isset($_GET[page])) { show_source(__FILE__); die(); } if (isset($_GET[page]) && $_GET[page] ! index.php) { include(flag.php);…...
C# 之某度协议登录,JS逆向,手机号绑定,获取CK
.NET兼职社区 .NET兼职社区 .NET兼职社区 .NET兼职社区 有需要指导,请私信我留言V或者去社区找客服。...
js适配器模式
适配器模式通过把一个类的接口变换成客户端所期待的另一种接口,可以帮我们解决不兼容的问题。 应用 // Ajax适配器函数,入参与旧接口保持一致 async function AjaxAdapter(type, url, data, success, failed) {const type type.toUpperCase()let resul…...
小徐影城管理系统(源码+数据库+文档)
亲测完美运行带论文:文末获取源码 文章目录 项目简介(论文摘要)运行视频包含的文件列表(含论文)前端运行截图后端运行截图 项目简介(论文摘要) 随着现在网络的快速发展,网上管理系统…...
Linux第101步_了解LCD屏驱动“panel-simple.c”
了解LCD屏驱动“panel-simple.c”有助于修改屏驱动。自己另外单独写屏驱动,这是不现实的,所以学会在源程序的基础上修改,才是最佳的学习方法,这就是我们学习框架的主要原因。在Limux系统中,主流的显示框架有两种:DRM(D…...
【实用技能】如何使用 .NET C# 中的 Azure Key Vault 中的 PFX 证书对 PDF 文档进行签名
TX Text Control 是一款功能类似于 MS Word 的文字处理控件,包括文档创建、编辑、打印、邮件合并、格式转换、拆分合并、导入导出、批量生成等功能。广泛应用于企业文档管理,网站内容发布,电子病历中病案模板创建、病历书写、修改历史、连续打…...
前端基础函数算法整理应用(sort+reduce+date+双重for循环)
文章目录 基础函数算法reduce 函数算法sort 函数算法时间排序1. 对日期字符串数组进行排序2. 对包含日期对象的数组进行排序3. 对包含时间戳的数组进行排序4. 对包含日期时间信息的对象数组进行排序 基础函数算法 一、排序算法 冒泡排序(Bubble Sort) …...
鸿蒙MPChart图表自定义(六)在图表中绘制游标
在鸿蒙开发中,MPChart 是一个非常强大的图表库,它可以帮助我们创建各种精美的图表。今天,我们将继续探索鸿蒙MPChart的自定义功能,重点介绍如何在图表中绘制游标。 OpenHarmony三方库中心仓 一、效果演示 以下是效果演示图&…...
poi-tl+kkviewfile实现生成pdf业务报告
需求背景,需要把ai生成的一些业务数据,生成一份pdf报告 需求分析 简单来说,就是json生成pdf的方案。 直接生成pdf。适合一些pdf样式简单的场景,一般就是纯文本按序渲染,或者是纯表格。如果需要一些复杂的排布&#x…...
【Uniapp-Vue3】scroll-view可滚动视图区域组件
如果我们有一个区域有限的大盒子(黑),而我们要在盒子中装的东西(灰)过多,我们就会用到滚动视图: 表现在代码上就是下面这个样子: <template><view class"scrollView&…...
asp.net core webapi中的数据注解与数据验证
在这一课中,主要讲解了如何在 Web API 中使用数据注解(Data Annotations)和进行数据验证,以确保请求数据的有效性和完整性。 在 Web API 中,数据验证是确保客户端传递的数据符合业务规则和格式要求的关键步骤。数据注…...
PixPin—— 高效截图工具的下载与使用攻略
在日常的工作和学习中,一款好用的截图工具能极大地提高我们的效率。今天就来给大家介绍一款功能强大的截图工具 ——PixPin。 下载篇 PixPin 的下载非常简单,只需访问下载网站,在首页就能找到适合你操作系统的下载链接。如果你使用的是 Win…...
Go语言的 的多态性(Polymorphism)基础知识
Go语言的多态性(Polymorphism)基础知识 在编程语言中,多态性是一个核心概念,它允许同一接口被不同的数据类型所实现,从而在不影响代码结构的情况下增强代码的灵活性和可扩展性。在Go语言中,多态性通过接口…...
Vue框架主要用来做什么?Vue框架的好处和特性.
在快速发展的互联网时代,前端开发技术的变革日新月异,为开发者带来了前所未有的机遇与挑战。Vue.js,作为前端开发领域的一颗璀璨新星,以其轻量级、高效灵活的特性,赢得了广大开发者的青睐。本文将深入探讨Vue框架的主要…...
科普CMOS传感器的工作原理及特点
在当今数字化成像的时代,图像传感器无疑是幕后的关键 “功臣”,它宛如一位神奇的 “光影魔法师”,通过光电效应这一奇妙的物理现象,将光子巧妙地转换成电荷,为图像的诞生奠定基础。而在众多类型的图像传感器中…...
tensorflow 内存错误
使用tensorflow训练多个模型时,训练过程中容易出现内存错误,在这里记录一下解决办法。希望能帮到各位。 2025-01-02 22:31:03.489713: W tensorflow/core/common_runtime/bfc_allocator.cc:275] Allocator (GPU_0_bfc) ran out of memory trying to all…...
19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...
qt+vs Generated File下的moc_和ui_文件丢失导致 error LNK2001
qt 5.9.7 vs2013 qt add-in 2.3.2 起因是添加一个新的控件类,直接把源文件拖进VS的项目里,然后VS卡住十秒,然后编译就报一堆 error LNK2001 一看项目的Generated Files下的moc_和ui_文件丢失了一部分,导致编译的时候找不到了。因…...
python基础语法Ⅰ
python基础语法Ⅰ 常量和表达式变量是什么变量的语法1.定义变量使用变量 变量的类型1.整数2.浮点数(小数)3.字符串4.布尔5.其他 动态类型特征注释注释是什么注释的语法1.行注释2.文档字符串 注释的规范 常量和表达式 我们可以把python当作一个计算器,来进行一些算术…...
【Redis】Redis从入门到实战:全面指南
Redis从入门到实战:全面指南 一、Redis简介 Redis(Remote Dictionary Server)是一个开源的、基于内存的键值存储系统,它可以用作数据库、缓存和消息代理。由Salvatore Sanfilippo于2009年开发,因其高性能、丰富的数据结构和广泛的语言支持而广受欢迎。 Redis核心特点:…...
IP选择注意事项
IP选择注意事项 MTP、FTP、EFUSE、EMEMORY选择时,需要考虑以下参数,然后确定后选择IP。 容量工作电压范围温度范围擦除、烧写速度/耗时读取所有bit的时间待机功耗擦写、烧写功耗面积所需要的mask layer...
