Qt for Android 工作原理
如果你是一名开发者,正在寻找 Qt 如何支持 Android 平台的高级概述,请访问此页面。
启动 Qt 应用程序
与原生 Android 应用类似,Qt MainActivity 的 onCreate() 函数在应用程序启动时以及在 Activity 创建时被早期调用。这就是 Android Qt 平台抽象 (QPA) 的大部分初始化发生的地方。最重要的部分包括
- 加载 Qt 和主应用程序的库。
- 初始化代理,负责初始化渲染表面和顶层布局,以及注册各种监听器,如输入、显示、触摸处理程序等。
在加载 Qt 库时,JavaVM 被缓存,同时首先加载 QtCore。这是在 JNI_OnLoad() 函数下完成的,该函数在通过 System.load() 调用同步调用时调用。每个 Qt 模块都可能为此函数实现一些特定于模块的初始化,例如注册原生 JNI 方法。
一旦所有 Qt 模块库都已加载,Qt 将加载 Android QPA 插件和主应用程序库。一旦顶层 QtLayout
布局完成填充其内容,Qt 应用程序的 main()
处理程序就会被定位并调用。这将启动 C++ Qt 应用程序并通常启动主事件循环。
Android QPA
Android QPA 的作用是将 Android (Java/Kotlin) 端与原生 Qt (C++) 端粘合在一起。它处理来自 Qt 到 Android 的各种事件和信号的传播。这一责任包括信号处理、触摸事件、UI 元素和渲染等。此层还负责应用程序启动初始化以及在应用程序退出或销毁时清理。
线程
使用 Qt for Android 应用程序时,Qt 通常有两个关注的线程。第一个是 Qt 启动的 QtThread
。第二个是 Android UI 线程。
QtThread
在例如加载库之前,Qt 应用程序首先实现并发起此线程。此线程称为 qtMainLoopThread
。所有后续操作都是在该线程下执行的
- Qt 库加载。
- 在 JNI_OnLoad() 中完成的操作。
- 启动原生应用程序。
- 执行
main()
。
Android UI 线程
与Android应用类似,影响UI的操作应在UI线程中运行。Qt会在底层处理所有预期在UI中运行的内部调用。此外,Qt提供API QAndroidApplication::runOnAndroidMainThread,允许从C++代码中在此线程下运行操作。使用此API,Qt会管理当应用处于活动状态时直接将调用发布到线程,如果应用处于暂停或后台,则将其排队。
架构
Qt类
以下几节将介绍各种Qt Android类及其功能以及在Qt应用中的作用。
公共Java绑定
这些是公共类,它们封装了面向用户的核心类的内部实现细节,例如Activity、Service和Application。这些类默认用于Qt Android应用,并在Android清单文件中引用。构建系统和部署工具负责将它们包含在构建中。
用户可以使用这些类来更改或扩展默认行为。例如,要在onCreate()添加自定义用户定义的逻辑,可以使用以下方法:
public class MyActivity extends QtActivity { @Override protected void onCreate(Bundle bundle) { // code before Qt is initialized super.onCreate(bundle); // code after Qt is initialized } }
注意:您必须编辑AndroidManifest.xml文件以使用自定义的Activity或绑定类,否则仍将使用默认类。
设置主题
在扩展QtActivity时,您可以使用setTheme()来设置特定的Android主题。然而,由于Qt默认会设置主题,该调用必须在调用父类的onCreate()之前执行才能生效。例如,您可以使用:
@Override protected void onCreate(Bundle bundle) { setTheme(android.R.style.Theme_DeviceDefault_DayNight); super.onCreate(bundle); }
默认情况下,对于Android 10及更高版本,Qt使用Theme_DeviceDefault_DayNight风格,对于早期版本使用Theme_Holo_Light风格。
附加一个应用程序参数
要附加额外的应用程序参数(即作为Java/Kotlin传递给应用(main()
函数的参数),请在扩展QtActivity后执行以下操作
@Override protected void onCreate(Bundle bundle) { appendApplicationParameters("--flag value"); super.onCreate(bundle); }
这与直接使用CMake变量QT_ANDROID_APPLICATION_ARGUMENTS相似。使用这两种方法的参数都可以接受空格或制表符作为分隔符,将最终传递给应用的参数列表使用QProcess::splitCommand解析。
使用QtLoader加载Qt库
每个Qt Android应用都需要确保在调用任何模块的功能之前,首先加载数据库中的每个本地Qt或第三方库。构建系统维护一个各种Qt库依赖、QPA插件、主应用库以及任何第三方库的列表,这些列表存储在应用下的
类加载器
在加载Qt库或初始化代表之前,
设置环境变量和应用参数
在加载库之前,Qt必须将环境变量以元数据形式传递至Android配置文件中,以便设置。这一步骤使得基于设置为元数据的配置标志,初始化某些模块成为可能。其中一些元数据也会被传播到作为启动时传递给应用的参数列表中。
setActivity()、setContext()和setService
多种Qt模块可能需要在Java端进行一些初始化工作,这些工作需要Activity或Service的上下文。这些模块实现了一个接收Activity、Service或Context作为参数的静态方法。
void setActivity(Activity activity) { m_activity = activity; // Other logic }
然后,在加载本地共享库之前,
Qt for Android处理Android Activity生命周期的机制
Qt for Android不提供用于直接处理Android活动生命周期回调(如onCreate()、onStart()、onResume()、onPause()、onStop()和onDestroy())的API。相反,它自动处理这些回调用。以下各节概述了这些行为。
注意:这些生命周期事件被转换为QGuiApplication::applicationStateChanged信号。
上下文管理
注意:Qt for Android不支持多个Activity。
回调
设计QtActivityBase类是为了将Activity的各个功能实现的细节保持在Qt for Android包内部保密。这个类是Android生命周期与Qt框架之间的中介者,将Android生命周期回调转换为Qt应用可以响应的信号和操作。
onCreate
当活动创建时,QtActivityBase初始化Qt环境。这包括加载Qt库、设置QJniObject使用的类加载器、解析应用的元数据以及准备Qt应用程序的执行。它确保处理所有针对活动特定必需的初始化。
onStart()
调用Android的Activity.OnStart().
onResume()
当活动进入前台时,QtActivityBase将Qt应用程序恢复。它确保暂停的进程或操作继续,并为用户的交互重新准备好应用程序。它将重新注册onPause()停止的显示管理器监听器。
onPause()
如果其他活动部分遮挡了Activity,QtActivityBase将暂停Qt应用程序。它将保存应用程序状态或释放应用程序不在前台时不需要的资源。
onStop()
当活动不再可见时,QtActivityBase停止Qt应用程序,这涉及到更广泛的状态保存和资源释放,为潜在销毁做准备。
注意:此时QtThread被挂起。
onDestroy()
如果活动已结束或被系统销毁,QtActivityBase将清理与Qt应用程序关联的所有资源。它确保正常关闭并执行所有必要的清理操作。
此集成允许开发者专注于构建他们的Qt应用程序,无需担心Android生命周期的复杂性,因为QtActivityBase在幕后管理这些复杂性。
启动画面管理
QAndroidApplication可以通过淡入效果隐藏启动画面,这可以与应用的启动序列同步,通常在onCreate()之后。
更多关于Qt for Android
2021 Qt世界峰会的视频概述了Qt for Android。
"一个链接到YouTube视频的议程图片"
© 2024 Qt公司有限。本文件中包含的文档贡献是各自所有者的版权。本文件中的文档是在自由软件基金会根据其于发布的情况下,在GNU自由文档许可证版本1.3的条款下提供的。Qt及其相关标志是Qt公司在芬兰和/或其他国家的商标。所有其他商标均为各自所有者的财产。