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会管理当应用处于活动状态时直接将调用发布到线程,如果应用处于暂停或后台,则将其排队。

架构

"An overview Qt for Android's Architecture"

Qt类

以下几节将介绍各种Qt Android类及其功能以及在Qt应用中的作用。

公共Java绑定

这些是公共类,它们封装了面向用户的核心类的内部实现细节,例如ActivityServiceApplication。这些类默认用于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插件、主应用库以及任何第三方库的列表,这些列表存储在应用下的libs.xml资源文件中。一旦完成下文所述的所有前置步骤,便使用System.load()加载库。

类加载器

在加载Qt库或初始化代表之前,QtLoader对象在早期就设置好了。这是因为类加载器是由QJniObject用来找到Java类,并且与QJniObject进行JNI调用的必要条件。

设置环境变量和应用参数

在加载库之前,Qt必须将环境变量以元数据形式传递至Android配置文件中,以便设置。这一步骤使得基于设置为元数据的配置标志,初始化某些模块成为可能。其中一些元数据也会被传播到作为启动时传递给应用的参数列表中。

setActivity()、setContext()和setService

多种Qt模块可能需要在Java端进行一些初始化工作,这些工作需要ActivityService的上下文。这些模块实现了一个接收Activity、Service或Context作为参数的静态方法。

void setActivity(Activity activity)
{
    m_activity = activity;
    // Other logic
}

然后,在加载本地共享库之前,QtLoader将以加载器的父上下文调用这些方法。

Qt for Android处理Android Activity生命周期的机制

Qt for Android不提供用于直接处理Android活动生命周期回调(如onCreate()、onStart()、onResume()、onPause()、onStop()和onDestroy())的API。相反,它自动处理这些回调用。以下各节概述了这些行为。

注意:这些生命周期事件被转换为QGuiApplication::applicationStateChanged信号。

上下文管理

QAndroidApplication可以提供一个AndroidContext作为QJniObject,这对于与Android系统交互是必需的。这个上下文可以是Activity或Service。如果有Activity,它将是最近启动的Activity,不考虑是否存在Services。如果只有Services,它将是最近启动的Service。

注意: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公司在芬兰和/或其他国家的商标。所有其他商标均为各自所有者的财产。