目录
1、Android 版本和 API 的对应关系?
2、ABI是什么
2.1、x86_64
2.2、x86
2.3、arm64-v8a
2.4、armeabi-v7a
3、不同架构的特点
3.1、32位 ARM 架构 (ARMv7)
3.2、64位 ARM 架构 (ARMv8-A)
3.3、32位 Intel 架构 (x86)
3.4、64位 Intel 架构 (x86-64)
4、ARM 架构与 Intel 架构的区别
5、什么是RISC和CISC
5.1、RISC(精简指令集计算机)
5.2、CISC(复杂指令集计算机)
5.3、主要区别
5.4、举例说明
5.4.1、RISC 架构示例:ARM 架构
5.4.2、CISC 架构示例:x86 架构
5.4.3、比较
6、为什么Qt安卓默认使用Clang编译器?
7、LLVM 工具链是什么,Qt安卓程序会用到它吗?
8、NDK和JDK分别是干什么的,Qt安卓程序为什么需要它们?
8.1、NDK
8.2、JDK
8.3、在 Qt 应用构建中的作用
8.3.1、NDK 的作用
8.3.2、JDK 的作用
8.3.3、构建流程概述
9、Gradle是什么,Qt安卓程序为什么需要它?
9.1、Gradle 的主要用途
9.2、构建 Qt 的 Android 应用时 Gradle 的主要作用
10、安卓应用程序文件格式
11、Android SDK的作用是什么,为什么Qt安卓需要它?
12、版本兼容性
13、qt creator 的安卓设备配置中的“安卓OpenSSL设置”有什么作用?
13.1、OpenSSL 是什么?
13.2、在 Qt for Android 中的作用
13.3、在pro文件配置 OpenSSL 的例子
14、-settings.json 构建过程文件
15、AndroidManifest.xml
16、build.gradle 构建过程文件
17、gradle.properties 构建过程文件
18、gradlew 构建过程文件
19、local.properties 构建过程文件
20、Gradle Wrapper
1、Android 版本和 API 的对应关系?
Android 版本与其对应的 API 级别之间存在一一对应的关系。
API 级别是一个整数,代表了 Android 平台的一个特定版本,并且随着每个新版本的发布而递增。
API 级别决定了应用能够访问哪些功能和行为,以及它能在哪个最低版本的 Android 上运行。
例如:
2、ABI是什么
ABI(Application Binary Interface)是特定硬件平台和操作系统之间的二进制接口。它定义了编译器如何生成机器码以及如何使用寄存器和内存来处理函数调用、数据类型等。
对于Android平台而言,不同的设备可能有不同的CPU架构。因此,为了确保应用程序能够在不同类型的设备上正确运行,开发者需要为每种CPU架构构建相应的原生代码。
x86_64、x86、arm64-v8a、armeabi-v7a是 Android 设备上常见的几种ABI类型。
2.1、x86_64
- 用途:这是一种 64 位 Intel 架构,常见于基于 Intel 处理器的 Android 设备,例如一些平板电脑。
- 特点:与 x86 架构兼容,提供 64 位计算能力。
- 兼容性:适用于运行 Android 5.0(API 级别 21)及以上版本的设备。
2.2、x86
- 用途:这是一种 32 位 Intel 架构,同样用于基于 Intel 处理器的 Android 设备。
- 特点:与 x86_64 架构相比,性能较低,但仍然广泛存在于一些早期或低端设备上。
- 兼容性:适用于运行 Android 4.0(API 级别 14)及以上版本的设备。
2.3、arm64-v8a
- 用途:这是 64 位 ARM 架构的一种实现,用于基于 ARM 的现代 Android 设备。
- 特点:提供更高的性能和更好的能效,通常用于较新的高端和中端设备。
- 兼容性:适用于运行 Android 5.0(API 级别 21)及以上版本的设备。
2.4、armeabi-v7a
- 用途:这是一种 32 位 ARM 架构,用于基于 ARM 的 Android 设备。
- 特点:支持硬件浮点运算,通常用于较旧的设备或低端设备。
- 兼容性:适用于运行 Android 2.3(API 级别 9)及以上版本的设备。
3、不同架构的特点
3.1、32位 ARM 架构 (ARMv7)
- 使用精简指令集计算 (RISC)。
- 适用于移动设备,如智能手机和平板电脑。
- 较低的功耗和较好的能效。
- 一般用于嵌入式系统和移动操作系统。
- 支持单精度和双精度浮点运算。
- 最多支持4GB的物理内存地址空间。
3.2、64位 ARM 架构 (ARMv8-A)
- 基于RISC。
- 支持更大的内存地址空间(理论上最大可达16EB)。
- 更好的性能和安全性特性。
- 支持虚拟化技术。
- 能够兼容32位应用程序。
- 在服务器、工作站和高性能计算领域得到广泛应用。
3.3、32位 Intel 架构 (x86)
- 使用复杂指令集计算 (CISC)。
- 最初为个人电脑设计。
- 支持大量的软件和硬件。
- 最多支持4GB的物理内存地址空间。
- 相对较高的功耗。
3.4、64位 Intel 架构 (x86-64)
- 基于CISC。
- 广泛应用于个人电脑和服务器。
- 支持更大的内存地址空间(理论上最大可达16EB)。
- 向后兼容32位代码。
- 强大的浮点运算能力和多媒体处理能力。
- 高性能和广泛的软件支持。
4、ARM 架构与 Intel 架构的区别
随着技术的发展变化,这些特点会跟着变化。目前而言,它们大概的区别:
指令集:
- ARM:RISC,简单指令集,较少的指令数量,每个指令执行单一操作。
- Intel:CISC,复杂指令集,较多的指令数量,某些指令可以执行多个操作。
能效:
- ARM:通常更节能,适合移动设备。
- Intel:更高的性能,但通常能耗较高。
性能:
- ARM:在低功耗设备上表现出色。
- Intel:在高性能计算任务中表现优异。
兼容性:
- ARM:广泛用于移动设备和嵌入式系统。
- Intel:主要应用于桌面计算机和服务器。
5、什么是RISC和CISC
这是两种不同的计算机架构设计哲学,它们影响着处理器的设计和性能。
5.1、RISC(精简指令集计算机)
特点:
- 简单指令:RISC 架构强调使用少量的简单指令,每条指令通常只完成一项任务。
- 固定长度:大多数 RISC 指令有固定的长度,便于硬件设计和解码。
- 寄存器到寄存器操作:RISC 处理器倾向于使用寄存器到寄存器的操作,减少了对内存的访问,提高了执行速度。
- 负载/存储架构:RISC 架构通常只允许在特定的指令(如 Load 和 Store)中访问内存,其他指令仅在寄存器间操作数据。
- 单周期指令:多数 RISC 指令在一个时钟周期内完成。
- 流水线执行:RISC 架构非常适合使用流水线技术来加速指令执行。
优点:
- 简单性:指令集简单,易于解码和执行。
- 高效率:减少内存访问,提高执行效率。
- 低功耗:适合移动设备和嵌入式系统。
缺点:
- 指令级并行性:需要编译器支持来提取指令级并行性。
- 复杂操作:复杂操作可能需要多条指令组合完成。
5.2、CISC(复杂指令集计算机)
特点:
- 复杂指令:CISC 架构包含大量指令,每条指令可以完成复杂的操作。
- 变长指令:指令长度不固定,增加了指令解码的复杂性。
- 多种寻址方式:支持多种寻址方式,如立即数、寄存器间接寻址等。
- 内存操作:CISC 架构中的指令可以直接访问内存,减少了寄存器的数量。
- 多周期指令:许多指令需要多个时钟周期来完成。
优点:
- 单指令多数据:某些指令可以同时处理多个数据,提高性能。
- 向后兼容性:通常支持较老的指令集,便于维护和升级。
缺点:
- 复杂性:复杂的指令集增加了设计和解码的难度。
- 低效率:复杂的指令可能导致效率低下,尤其是在流水线处理中。
- 功耗:通常比 RISC 架构的处理器功耗更高。
5.3、主要区别
指令集复杂度:
- RISC:简单指令集,每条指令完成一个任务。
- CISC:复杂指令集,每条指令可能完成多个任务。
指令执行周期:
- RISC:多数指令在一个时钟周期内完成。
- CISC:许多指令需要多个时钟周期来完成。
寻址模式:
- RISC:支持较少的寻址模式,通常通过寄存器操作。
- CISC:支持多种寻址模式,包括直接内存访问。
硬件实现:
- RISC:更易于硬件实现,适合流水线和并行处理。
- CISC:硬件实现更为复杂,可能需要微代码支持。
适用领域:
- RISC:广泛用于移动设备、嵌入式系统和高性能计算。
- CISC:主要用于桌面计算机和服务器。
RISC 和 CISC 代表了两种不同的设计理念。RISC 架构通常更简单、更易于设计,适合移动设备和嵌入式系统;而 CISC 架构则提供了更丰富的指令集,适用于需要执行复杂任务的桌面和服务器环境。随着技术的发展,现代处理器往往融合了两者的优点,例如采用 RISC 核心的处理器可能还会包含一些 CISC 的元素,以提高性能和兼容性。
5.4、举例说明
使用加法指令(ADD)作为示例,这是一个非常基础且常用的指令,在不同的架构中都有相应的实现。
5.4.1、RISC 架构示例:ARM 架构
指令格式:ADD <目标寄存器>, <一个操作数寄存器>, <第二个操作数寄存器>
示例:ARM ADD 指令
指令:ADD R1, R2, R3
说明:将 R2 和 R3 中的值相加,并将结果存储到 R1 中。
5.4.2、CISC 架构示例:x86 架构
指令格式:ADD <目标寄存器或内存位置>, <操作数寄存器或立即数>
示例:x86 ADD 指令
指令:ADD EAX, EBX
说明:将 EBX 寄存器中的值加到 EAX 寄存器中。
5.4.3、比较
指令格式:
- RISC:指令格式简单,每个指令完成一个特定的任务。
- CISC:指令格式较为复杂,一条指令可能完成多个任务。
寄存器到寄存器操作:
- RISC:通常只允许寄存器到寄存器的操作,不允许直接访问内存。
- CISC:支持寄存器到寄存器操作,也支持寄存器到内存或内存到寄存器的操作。
执行周期:
- RISC:大多数指令可以在一个时钟周期内完成。
- CISC:许多指令可能需要多个时钟周期才能完成,特别是涉及内存访问的情况。
指令集大小:
- RISC:指令集较小,指令数量有限。
- CISC:指令集较大,指令数量较多。
寻址模式:
- RISC:通常支持较少的寻址模式,如寄存器直接寻址。
- CISC:支持多种寻址模式,如立即数寻址、寄存器间接寻址等。
6、为什么Qt安卓默认使用Clang编译器?
1、兼容性和一致性:
- Qt 项目本身在很多平台上使用 Clang 作为编译器之一,因此在 Android 平台上继续使用 Clang 可以保证代码的一致性。
- Clang 与 LLVM 工具链紧密集成,提供了许多高级特性,如静态分析器、调试器等,这对于跨平台开发非常有用。
2、跨平台支持:
- Clang 是一个高度可移植的编译器,它可以在多种操作系统上编译代码,这使得 Qt 项目能够在多个平台上使用相同的工具链。
- 对于 Android 平台来说,Clang 通过 Android NDK 提供支持,这使得它成为 Qt for Android 的自然选择。
3、社区和生态系统的支持:
- Clang 在开发者社区中有广泛的接受度和支持,这意味着有许多资源可用,如文档、教程和工具,这有助于加快开发过程。
- 许多其他流行的开发框架和工具也使用 Clang,这有助于形成一个统一的生态系统。
4、NDK 集成:
- Android NDK 主要支持 Clang 作为编译器,因此 Qt 项目使用 Clang 可以更好地与 NDK 集成。
- NDK 的 Clang 版本通常经过特别优化,以适应 Android 平台的需求,包括支持特定的 ABI 和架构。
总之,Qt for Android 选择 Clang 作为默认编译器是为了保证代码的一致性、性能、跨平台支持、社区支持以及与 Android NDK 的良好集成。虽然理论上也可以使用其他编译器(如 GCC),但 Clang 提供了更好的体验和支持。
7、LLVM 工具链是什么,Qt安卓程序会用到它吗?
LLVM (Low Level Virtual Machine) 工具链是一个开源的编译器基础设施项目,它包含了一系列工具和库,用于构建高质量的编译器、解释器和其他语言处理工具。
Qt for Android 使用了 LLVM 工具链来进行 Android 应用程序的构建。
8、NDK和JDK分别是干什么的,Qt安卓程序为什么需要它们?
8.1、NDK
Android Native Development Kit 是 Android 平台上的一组工具,允许开发者使用 C 或 C++ 编写原生应用程序。NDK 主要用于以下几个方面:
- 编写原生代码:如果应用程序需要高性能的操作(比如图形处理、音频处理或者复杂的数学运算),可以使用 NDK 来编写 C/C++ 代码。
- 使用原生库:NDK 允许在 Android 应用中直接使用现有的 C/C++ 库,而不需要重新编写 Java 版本。
- 跨平台共享代码:如果应用在多个平台上都有版本,NDK 可以使得不同平台上复用一部分相同的 C/C++ 代码。
8.2、JDK
Java Development Kit 是 Java 开发工具包,它包含了编译、调试和运行 Java 程序所需的所有工具。JDK 包括了 Java 编译器(javac)、Java 运行时环境(JRE)、Java 类库以及其他开发工具和文档。JDK 主要用于以下几个方面:
- 编译 Java 代码:将 Java 源代码编译成字节码 (.class 文件)。
- 运行 Java 应用:JDK 包含 JRE,可以运行 Java 应用程序。
- 调试 Java 程序:提供了调试工具,如 jdb(Java Debugger)。
- 访问 Java 类库:JDK 包含了大量的标准类库,为开发者提供了丰富的功能。
8.3、在 Qt 应用构建中的作用
NDK 和 JDK 在构建 Qt 的 Android 应用程序时分别负责编译 C++ 代码和 Java 代码,并最终生成可部署的 APK 文件。
8.3.1、NDK 的作用
- 构建 Qt 的 C++ 代码:Qt 是基于 C++ 的框架,因此需要 NDK 来编译 Qt 库中的 C++ 代码,并将其转换为目标平台的机器代码。
- 构建应用程序的 C++ 部分:如果应用程序中有 C++ 代码,那么也需要通过 NDK 来编译这部分代码。
8.3.2、JDK 的作用
- 构建 Java 部分:虽然 Qt 主要是 C++ 的框架,但它也支持使用 Java 代码来构建 Android 应用的部分功能,例如与 Android 平台交互的功能。
- 打包应用程序:构建 Qt 应用程序时,需要使用 JDK 中的工具(如 jar 和 javac)来打包 Java 代码,并将其与 C++ 代码一起组成完整的 APK 文件。
8.3.3、构建流程概述
- 配置环境:首先需要设置好 NDK 和 JDK 的路径,确保 Qt 可以找到这些工具。
- 编译 Qt:如果使用的是预编译的 Qt 版本,则这一步骤可以跳过;否则,需要使用 NDK 来编译 Qt 库。
- 编译应用程序:使用 Qt 的 qmake 和 make 工具来编译应用程序。这个过程会调用 NDK 中的工具来编译 C++ 代码。
- 打包:最后,使用 JDK 中的工具来打包整个应用,包括 Java 代码、C++ 代码以及资源文件等,形成最终的 APK 文件。
9、Gradle是什么,Qt安卓程序为什么需要它?
Gradle 是一个基于 Groovy 语言的自动化构建工具,它可以用来管理软件项目的构建、测试、发布等任务。Gradle 使用一种称为“构建脚本”的方式来定义项目构建的过程,并且能够与多种编程语言和平台集成。Gradle 提供了许多高级特性,例如依赖管理、多项目构建、插件扩展性等。
9.1、Gradle 的主要用途
- 构建自动化:Gradle 能够自动执行一系列的构建任务,如编译源代码、运行单元测试、打包项目等。
- 依赖管理:Gradle 可以管理项目依赖的外部库,自动下载并解决依赖之间的冲突。
- 任务定制:Gradle 支持自定义构建任务,可以根据项目需求灵活地调整构建过程。
- 多项目构建:对于包含多个子项目的大型项目,Gradle 可以高效地管理它们之间的依赖关系和构建顺序。
- 插件扩展:Gradle 支持插件系统,可以通过安装不同的插件来增加额外的功能,如 Android 插件、Java 插件等。
9.2、构建 Qt 的 Android 应用时 Gradle 的主要作用
- Android构建系统集成:Qt虽然主要使用qmake或CMake作为其C++代码的构建系统,但在构建Android应用时,需要与Android的构建系统集成。Gradle是Android的官方构建工具,它提供了与Android SDK和NDK的紧密集成,能够处理Android特有的构建任务,如APK的打包、签名等。
- 简化构建过程:Gradle通过自动化许多Android相关的构建步骤(如处理资源文件、AndroidManifest.xml文件等),简化了Qt Android应用的构建过程。这减少了手动配置和错误的可能性,提高了构建效率。
- 依赖管理:对于Android应用来说,除了Qt库之外,还可能依赖其他Android特有的库或第三方库。Gradle的依赖管理功能允许开发者轻松管理这些依赖项的版本和下载,确保项目的稳定性和一致性。
- 与Android Studio的集成:Android Studio是Android开发的官方IDE,它内置了对Gradle的支持。使用Gradle作为Qt Android应用的构建工具,可以更好地与Android Studio集成,方便开发者在统一的开发环境中进行编码、调试和构建。
10、安卓应用程序文件格式
APK (Android Package Kit):是一个压缩文件,包含了应用程序的所有必要文件,如编译后的代码(DEX字节码)、资源文件、原生库(如果有的话)以及清单文件(AndroidManifest.xml)。
AAB (Android App Bundle):是Google推出的一种新的应用程序分发格式,它不是直接安装在设备上的,而是由Google Play动态地向用户设备交付所需的组件。
11、Android SDK的作用是什么,为什么Qt安卓需要它?
是一套工具集合,用于开发 Android 平台上的应用程序。它包含了开发、测试和调试 Android 应用所需的各种工具和库。Android SDK 是 Android 开发的基础,为开发者提供了全面的支持。
Qt for Android 需要 Android SDK 主要是因为 SDK 提供了访问 Android 平台功能的 API、编译和打包应用所需的工具,以及进行应用测试和调试的环境和工具。没有 Android SDK,Qt 将无法充分利用 Android 平台的优势,也无法生成和部署针对 Android 设备的 Qt 应用程序。
- 访问 Android 平台功能:Android SDK 提供了大量的 API,允许开发者访问和操作 Android 设备上的各种硬件和软件功能。这些功能包括但不限于网络连接(如 WiFi、蓝牙、移动网络)、传感器数据(如加速度计、陀螺仪、GPS)、存储管理(内部存储、外部存储、数据库)、用户权限管理等。Qt 通过封装这些 API,使得开发者可以在 Qt 应用程序中直接使用这些功能,而无需深入了解 Android 的底层实现。
- 编译和打包:Qt for Android 应用的构建过程确实依赖于 Android SDK 中的工具。这些工具包括 aapt(用于处理资源文件)、dx(用于将 Java 字节码转换为 Dalvik 字节码,现在更多的是使用 D8/R8)、zipalign(用于优化 APK 文件以提高运行时性能)等。Qt 的构建系统(如 qmake 或 CMake)会调用这些工具来生成最终的 APK 文件。
- 测试和调试:Android SDK 提供了多种测试和调试工具,这些工具对于开发高质量的 Qt for Android 应用至关重要。例如,Android Emulator 允许开发者在没有实际 Android 设备的情况下模拟 Android 环境,从而测试应用在不同设备和 Android 版本上的表现。另外,ADB(Android Debug Bridge)工具允许开发者从计算机向连接的 Android 设备发送命令,进行调试、安装和卸载应用等操作。
12、版本兼容性
Qt SDK 通常会指定支持的 Android SDK 和 Android NDK 的版本范围。开发者需要使用在 Qt SDK 文档中列出的版本范围内或兼容的 Android SDK 和 Android NDK。
- Android SDK:Qt SDK 需要特定版本的 Android SDK 来编译和打包应用,特别是用于处理资源文件和生成 APK 文件的工具。
- Android NDK:Qt SDK 通常会指定支持的 Android NDK 版本,因为 Qt 项目中的 C++ 代码需要通过 NDK 中的工具链来编译。
13、qt creator 的安卓设备配置中的“安卓OpenSSL设置”有什么作用?
13.1、OpenSSL 是什么?
OpenSSL 是一个强大的安全套接字层密码库,包含 SSL v3、TLS v1 - v1.3 协议的实现,以及常用的密码算法、安全随机数生成器、PBKDF2 函数等。它广泛应用于加密通信、安全数据传输等领域。
13.2、在 Qt for Android 中的作用
当 Qt 应用程序中使用与网络相关的功能时,尤其是涉及到 SSL/TLS 加密的数据传输时,例如使用 QSslSocket 类来建立安全连接,就需要 OpenSSL 库的支持。
在 Android 平台上,如果应用程序需要进行 SSL/TLS 连接,那么就需要在构建配置中指定是否启用 OpenSSL 支持。这是因为 Android 设备上的 OpenSSL 版本可能与应用程序使用的版本不同,或者设备上根本没有安装 OpenSSL。
13.3、在pro文件配置 OpenSSL 的例子
# 假设OpenSSL库的头文件在/path/to/openssl/include目录下
# OpenSSL库的库文件在/path/to/openssl/libs/armeabi-v7a目录下(注意:这里需要根据你的目标架构调整路径)
# Android特定配置
android {
# 添加OpenSSL库的链接标志
LIBS += -lssl -lcrypto
# 添加OpenSSL库的头文件路径
INCLUDEPATH += /path/to/openssl/include
# 添加OpenSSL库的库文件路径
# 注意:这里使用的是QMAKE的内置变量ANDROID_ABI来动态选择库文件路径
# 如果你知道你的目标架构,也可以直接指定路径,如:-L/path/to/openssl/libs/armeabi-v7a
LIBS += -L$${ANDROID_ABI_DIR}/openssl/libs
# 如果你需要为不同的ABI指定不同的库文件路径,可以添加条件判断
# 例如,为armeabi-v7a和arm64-v8a分别指定路径
# equals(ANDROID_ABI, armeabi-v7a): LIBS += -L/path/to/openssl/libs/armeabi-v7a
# equals(ANDROID_ABI, arm64-v8a): LIBS += -L/path/to/openssl/libs/arm64-v8a
# 注意:上面的ANDROID_ABI_DIR是假设的变量,实际中可能需要你根据Qt Creator或Android NDK提供的实际路径来设置
# 如果Qt Creator没有直接提供这样的变量,你可能需要手动设置或使用其他方法来动态获取ABI目录
}
14、-settings.json 构建过程文件
在工程构建过程中会生成这个json格式的过程文件。这是由 Qt 的构建系统 qmake 生成的。
这个文件的存在主要是为了记录构建和部署过程中需要的各种配置信息,以便在后续的部署或调试过程中可以自动地、准确地使用这些信息。
这个文件会被 androiddeployqt
工具读取,该工具是用来帮助部署 Qt 应用到 Android 设备上的。
下面是这个文件内容的解析:
{
"description": "This file is generated by qmake to be read by androiddeployqt and should not be modified by hand.",
"qt": "E:/qt6Android/6.7.2/android_armv7",
"qtDataDirectory": ".",
"qtLibExecsDirectory": "libexec",
"qtLibsDirectory": "lib",
"qtPluginsDirectory": "plugins",
"qtQmlDirectory": "qml",
"sdk": "F:/jdk17/android-sdk",
"sdkBuildToolsRevision": "34.0.0",
"ndk": "F:/jdk17/android-sdk/ndk/26.1.10909125",
"toolchain-prefix": "llvm",
"tool-prefix": "llvm",
"ndk-host": "windows-x86_64",
"architectures": {"armeabi-v7a":"arm-linux-androideabi"},
"android-min-sdk-version": "23",
"android-target-sdk-version": "34",
"rcc-binary": "E:/qt6Android/6.7.2/mingw_64/bin/rcc.exe",
"qml-importscanner-binary": "E:/qt6Android/6.7.2/mingw_64/bin/qmlimportscanner.exe",
"qml-root-path": "D:/Documents/untitled6",
"stdcpp-path": "F:/jdk17/android-sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/windows-x86_64/sysroot/usr/lib",
"application-binary": "untitled6"
}
- description:描述了文件的目的和警告不要手动修改此文件。
- qt:指定了 Qt 的安装路径。在这个例子中,Qt 的版本为 6.7.2,并且针对的是 Android ARMv7 架构。
- qtDataDirectory:指定 Qt 数据文件所在的相对目录。在这个例子中,数据文件位于当前目录下。
- qtLibExecsDirectory:指定 Qt 的 libexec 目录(即存放一些可执行脚本和二进制文件的目录)。
- qtLibsDirectory:指定 Qt 的库文件所在目录。
- qtPluginsDirectory:指定 Qt 的插件所在目录。
- qtQmlDirectory:指定 Qt 的 QML 文件所在目录。
- sdk:指定 Android SDK 的安装路径。
- sdkBuildToolsRevision:指定 Android SDK Build Tools 的版本号。
- ndk:指定 Android NDK 的安装路径。
- toolchain-prefix 和 tool-prefix:指定编译工具链的前缀,这里使用的是 LLVM 工具链。
- ndk-host:指定 NDK 构建主机平台。
- architectures:指定目标架构及其对应的交叉编译器前缀。在这个例子中,目标架构为 armeabi-v7a,对应的前缀为 arm-linux-androideabi。
- android-min-sdk-version:指定应用支持的最低 Android SDK 版本。
- android-target-sdk-version:指定应用的目标 Android SDK 版本。
- rcc-binary:指定 Qt 的资源编译器 (Resource Compiler) 的路径。
- qml-importscanner-binary:指定 Qt 的 QML 导入扫描器的路径。
- qml-root-path:指定 QML 文件的根路径。
- stdcpp-path:指定标准 C++ 库的路径。
- application-binary:指定最终生成的应用程序二进制文件的名称。
15、AndroidManifest.xml
- 这是 Android 应用程序的核心配置文件,它定义了应用的基本属性和组成组件。
- 当使用 Qt 构建 Android 应用时,qmake 会自动检测和生成一个基本的 AndroidManifest.xml 文件。这个文件通常包含了应用运行所需的最小配置,例如应用的包名、主 Activity 的定义、权限声明等。
- 如果没有提供自己的 AndroidManifest.xml 文件,那么 qmake 会生成一个默认的配置文件,这个文件足以让应用运行起来。但是,为了满足特定的需求,比如添加自定义的 Activity 或者声明额外的权限,开发者需要自己创建并定制 AndroidManifest.xml 文件。
16、build.gradle 构建过程文件
build.gradle 文件是 Gradle 构建脚本的一部分,用于定义 Android 应用程序的构建配置。
build.gradle 文件主要负责以下几个方面:
- 确保 Gradle 可以找到构建工具和必要的依赖。
- 应用 Android 构建插件。
- 配置 Android 构建环境,包括 SDK 版本、编译选项、资源和依赖管理。
- 定义了应用的默认配置,比如支持的 ABI 类型和最低/最高 SDK 版本。
- 这个文件是在构建 Qt for Android 项目时自动生成的,并且可能会根据不同的 Qt 项目有所不同。如果想要添加额外的功能或者配置,可以直接修改这个文件。
下面是这个文件内容的解析:
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.4.1'
}
}
repositories {
google()
mavenCentral()
}
apply plugin: 'com.android.application'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
implementation 'androidx.core:core:1.13.1'
}
android {
/*******************************************************
* The following variables:
* - androidBuildToolsVersion,
* - androidCompileSdkVersion
* - qtAndroidDir - holds the path to qt android files
* needed to build any Qt application
* on Android.
*
* are defined in gradle.properties file. This file is
* updated by QtCreator and androiddeployqt tools.
* Changing them manually might break the compilation!
*******************************************************/
namespace androidPackageName
compileSdkVersion androidCompileSdkVersion
buildToolsVersion androidBuildToolsVersion
ndkVersion androidNdkVersion
// Extract native libraries from the APK
packagingOptions.jniLibs.useLegacyPackaging true
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = [qtAndroidDir + '/src', 'src', 'java']
aidl.srcDirs = [qtAndroidDir + '/src', 'src', 'aidl']
res.srcDirs = [qtAndroidDir + '/res', 'res']
resources.srcDirs = ['resources']
renderscript.srcDirs = ['src']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs']
}
}
tasks.withType(JavaCompile) {
options.incremental = true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
abortOnError false
}
// Do not compress Qt binary resources file
aaptOptions {
noCompress 'rcc'
}
defaultConfig {
resConfig "en"
minSdkVersion qtMinSdkVersion
targetSdkVersion qtTargetSdkVersion
ndk.abiFilters = qtTargetAbiList.split(",")
}
}
buildscript 块:
- repositories:指定了 Gradle 应该从哪些仓库(repository)下载依赖。
- dependencies:指定用于构建过程的依赖项。在这个例子中,它声明了 Android Gradle 插件版本 7.4.1。
全局 repositories 块:
- 类似于 buildscript 块中的 repositories,这里定义了构建项目时应该使用的仓库。
apply plugin:'com.android.application':
- 这一行应用了 Android 应用插件,它会告诉 Gradle 使用 Android 构建规范来构建应用。
dependencies 块:
- implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']): 表示从 libs 目录下的 .jar 和 .aar 文件添加依赖。
- implementation 'androidx.core:core:1.13.1':添加了 AndroidX Core 库的依赖。
android 块:
- 这部分配置了 Android 特有的构建选项。
- namespace androidPackageName:设置了应用的包名空间,通常会在 gradle.properties 中定义。
- compileSdkVersion,buildToolsVersion,ndkVersion:分别定义了编译 SDK 版本、构建工具版本和 NDK 版本,这些值同样来自 gradle.properties。
- packagingOptions.jniLibs.useLegacyPackaging true:配置了 JNI 库的打包方式。
- sourceSets:定义了源文件的位置,包括 Java 代码、资源文件、JNI 库等。
- tasks.withType(JavaCompile):配置了 Java 编译任务,启用了增量编译。
- compileOptions:设定了 Java 编译的目标和源兼容性版本。
- lintOptions:配置了 lint 工具的行为,这里设置为即使有 lint 错误也不中断构建。
- aaptOptions:配置了 aapt (Android Asset Packaging Tool) 的行为,这里指定了不压缩 .rcc 文件。
defaultConfig 块
- 包含了应用的默认配置,如最低 SDK 版本、目标 SDK 版本、NDK ABI 过滤器等。
- resConfig "en": 设置了资源的配置,这里只包含英语。
- minSdkVersion,targetSdkVersion:分别定义了应用支持的最低和目标 SDK 版本。
- ndk.abiFilters:指定了要包含的 ABI 架构类型。
17、gradle.properties 构建过程文件
这个文件是 Gradle 用来存储项目的构建属性的地方。这些属性可以覆盖默认设置,或者为构建过程提供必要的配置信息。当构建一个 Qt for Android 项目时,这个文件被创建以确保构建系统知道如何正确地配置并构建应用程序。
这个文件通常是由 Qt Creator 或者其他构建工具自动生成的,并且不应该手动编辑,除非开发者知道自己在做什么。这些配置值被 build.gradle 文件引用,以确保构建过程正确执行。
下面是这个文件内容的解析:
# Project-wide Gradle settings.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2500m -XX:MaxMetaspaceSize=768m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# Enable building projects in parallel
org.gradle.parallel=true
# Gradle caching allows reusing the build artifacts from a previous
# build with the same inputs. However, over time, the cache size will
# grow. Uncomment the following line to enable it.
#org.gradle.caching=true
#org.gradle.configuration-cache=true
# Allow AndroidX usage
android.useAndroidX=true
androidBuildToolsVersion=34.0.0
androidCompileSdkVersion=android-34
androidNdkVersion=26.1.10909125
androidPackageName=org.qtproject.example.untitled6
buildDir=build
qt5AndroidDir=E:/qt6Android/6.7.2/android_armv7/./src/android/java
qtAndroidDir=E:/qt6Android/6.7.2/android_armv7/./src/android/java
qtMinSdkVersion=23
qtTargetAbiList=armeabi-v7a
qtTargetSdkVersion=34
- JVM Arguments (org.gradle.jvmargs):
- -Xmx2500m:设置了最大堆内存大小为 2500 MB。
- -XX:MaxMetaspaceSize=768m:设置了元空间的最大大小为 768 MB,元空间用于存储类元数据。
- -XX:+HeapDumpOnOutOfMemoryError:当发生内存溢出错误时,将生成堆转储文件以供调试。
- -Dfile.encoding=UTF-8:设置了文件编码为 UTF-8。
- Parallel Building (org.gradle.parallel):true: 启用了并行构建,这可以加速构建过程,尤其是在多核处理器上。
- Gradle Caching:这部分被注释掉了,如果取消注释,将会启用 Gradle 的缓存功能,这意味着 Gradle 将会尝试从远程缓存服务器获取之前构建的结果以重用。
- Allow AndroidX Usage (android.useAndroidX):true: 允许使用 AndroidX 库而不是旧的支持库。
- Android Build Tools Version (androidBuildToolsVersion):34.0.0: 指定了 Android 构建工具的版本。
- Android Compile SDK Version (androidCompileSdkVersion):android-34: 指定了 Android 编译 SDK 的版本。
- Android NDK Version (androidNdkVersion):26.1.10909125: 指定了 Android NDK 的版本。
- Package Name (androidPackageName):org.qtproject.example.untitled6: 指定了 Android 应用程序的包名。
- Build Directory (buildDir):build: 指定了构建输出的目录。
- Qt Android Directory (qt5AndroidDir 和 qtAndroidDir):E:/qt6Android/6.7.2/android_armv7/./src/android/java: 指定了 Qt for Android 的源代码目录。
- Minimum SDK Version (qtMinSdkVersion):23: 指定了应用程序支持的最低 Android API 级别。
- Target ABI List (qtTargetAbiList):armeabi-v7a: 指定了应用程序支持的目标架构。
- Target SDK Version (qtTargetSdkVersion):34: 指定了应用程序的目标 Android API 级别。
18、gradlew 构建过程文件
gradlew 是一个由 Gradle 提供的可执行脚本文件,它是一个方便的封装器,允许开发者在项目根目录下直接运行 Gradle 构建任务。对于不同的操作系统,该文件有两种形式:
- 在 Unix/Linux/macOS 系统中,文件名为 gradlew,并且是一个可执行的 shell 脚本。
- 在 Windows 系统中,文件名为 gradlew.bat,并且是一个批处理文件。
这个脚本的主要作用是:
- 自动管理 Gradle 版本:gradlew 会查找本地的 Gradle 分发版本,如果没有找到,则会从互联网下载指定版本的 Gradle 并将其安装到项目的 .gradle 目录中。这样可以确保项目总是使用正确的 Gradle 版本来构建,而不需要手动安装 Gradle 到系统中。
- 简化命令行操作:可以简单地通过 ./gradlew <task> (在 Unix/Linux/macOS 上)或 gradlew <task> (在 Windows 上)来运行任何 Gradle 构建任务。例如可以运行 ./gradlew build 来构建整个项目,或者运行 ./gradlew clean 来清理之前的构建产物。
- 自动配置环境:gradlew 会自动配置必要的环境变量,如 JAVA_HOME 和 GRADLE_HOME,确保构建过程能够顺利进行。
- 统一的构建入口点:不管操作系统是什么,gradlew 都提供了一个统一的方式来启动构建流程,这对于团队协作和持续集成/持续部署(CI/CD)流程非常有用。
想要构建一个 APK 文件,可以运行:
19、local.properties 构建过程文件
在构建Qt Android应用程序的过程中,local.properties 文件并不是由Qt构建系统直接生成的,而是由 Android NDK构建系统的一部分所使用的。这个文件的作用主要是帮助构建系统找到必要的Android SDK和NDK的位置,从而确保构建过程可以正确地使用这些工具和库。
当使用Qt Creator或其他构建工具来构建针对Android的目标时,Qt会利用CMake等工具与Android NDK进行交互。在这个过程中,local.properties 文件可能会被创建或者更新,它包含了一些重要的构建配置信息,例如:
- sdk.dir:指定了Android SDK的根目录位置。
- ndk.dir:指定了Android NDK的根目录位置。
- sdk.version:指定了SDK的版本号。
20、Gradle Wrapper
Gradle Wrapper 是一种机制,允许项目包含下载和运行 Gradle 所需的所有内容。这意味着开发人员不需要在他们的机器上预先安装 Gradle,Gradle Wrapper 会自动下载和使用项目所需的 Gradle 版本。
Gradle Wrapper 的组成部分:
- gradle-wrapper.jar:一个可执行的 JAR 文件,用于启动 Gradle。它负责下载和运行指定版本的 Gradle 分发包。
- gradle-wrapper.properties:一个文本文件,用于指定 Gradle 分发包的下载位置以及其他配置信息。它告诉 Gradle Wrapper 如何下载 Gradle 分发包以及在哪里存储它。
下面是 gradle-wrapper.properties 文件内容的解析:
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
- distributionBase=GRADLE_USER_HOME:指定Gradle分发包的基目录。这里的值GRADLE_USER_HOME 意味着Gradle将查找用户的.gradle目录作为默认的分发包存储位置。
- distributionPath=wrapper/dists:指定相对于 distributionBase 的子路径,其中包含实际的Gradle分发包。这里的值意味着分发包将被放置在GRADLE_USER_HOME/wrapper/dists目录下。
- distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip:指定了从哪里下载Gradle分发包。这里的URL指向Gradle 8.3的二进制分发包。
- networkTimeout=10000:设置了网络请求超时的时间,单位是毫秒。这里的值10000毫秒等于10秒。
- validateDistributionUrl=true:指定是否验证distributionUrl。如果设置为true,则会检查URL的有效性,确保可以从该URL下载正确的分发包。
- zipStoreBase=GRADLE_USER_HOME:类似于 distributionBase,但它用于指定ZIP文件存储的基目录。这通常与 distributionBase 相同。
- zipStorePath=wrapper/dists:类似于 distributionPath,但它用于指定ZIP文件存储的具体路径。这通常与 distributionPath 相同。