HarmonyOS鸿蒙PC的QT应用开发:QT项目运行原理与 EmbeddedUIExtensionAbility介绍
好消息,2026年3.31日,QT官方正式发布鸿蒙版QT。本次开源发布正式推出面向鸿蒙系统平板和PC设备的Qt 5.12.12 LTS 适配版本,在完整保留 Qt 5.12.12 核心能力(含界面渲染、信号槽机制、跨平台 I/O、网络通信及数据库模块)的基础上,深度适配鸿蒙系统架构。本版本可降低开发者跨平台移植成本,加速 Qt 与鸿蒙生态融合,助力多场景鸿蒙应用高效开发。
QT官方鸿蒙版开源地址:https://wiki.qt.io/Qt5.12.12_Open_Source_Release_for_HarmonyOS_zh
QT官方文档地址:https://wiki.qt.io/Qt_for_OpenHarmony/zh

前言
在 HarmonyOS 上运行 Qt 应用,跟传统的PC上的QT应用不同。
传统的PC上的QT应用是使用QtCreator开发完成后,直接编译为可执行文件exe.。 而鸿蒙版QT的开发流程,则是使用鸿蒙版QT的SDK和qmake工具链,最终的编译产物为.so. 之后呢还需要鸿蒙的QT工程项目模版,把so加载进去,将应用编译打包为hap或app包。
在HarmonyOS 上运行 Qt 应用,通常需要三层协作:系统 Ability 与窗口、ArkUI 中的原生节点(XComponent),以及 Qt 平台的 QPA 插件(本模板中为 libqohos.so)。当产品希望在「不整页跳转」的前提下,把 Qt 界面嵌进另一个界面的指定区域时,系统提供了 EmbeddedUIExtensionAbility(嵌入式 UI 扩展能力):由宿主页面的 EmbeddedComponent 发起一次嵌入会话,扩展侧在独立能力中加载页面并完成绘制与交互。
本文以鸿蒙项目模版,仓库内 ohostemplateforqtapplication_20260331 为例,介绍下QT项目结构运行原理与 EmbeddedUIExtensionAbility。
ohostemplateforqtapplication是用于构建最终 OpenHarmony Qt 应用程序的 DevEco 项目模板。这将用于在 HarmonyOS 设备上运行 Qt 应用程序。 开发者也可以从以下链接获取最新项目工程模版: http://codereview.qtcompany.cn:29416/template/
从 应用级 app.json5、工程级 build-profile.json5、模块级 module.json5 到 ArkTS 与原生库调用关系,说明模板工程的运行原理,并单独梳理 EmbeddedUIExtensionAbility 在本项目中的职责与数据流。文中代码与配置均来自当前仓库快照;系统 API 行为以你所使用的 HarmonyOS SDK 版本及官方文档为准。
1. 核心概念
1.1 Qt 在鸿蒙模板中的位置
- 入口形态:模板将 主界面 实现为
UIAbility子类QAbility,生命周期各阶段委托给libqohos.so暴露的 NAPI(代码中以import qpa from 'libqohos.so'引用),由 Qt for OpenHarmony / HarmonyOS 的 QPA 与系统窗口、输入等对接。 - 绘制落点:ArkUI 页面通过
XComponent,type: XComponentType.NODE,libraryname: 'qohos'创建原生节点;QPA 在该节点上挂载 Qt 的渲染与事件循环逻辑。主窗口与嵌入扩展会话各对应一套页面与节点,但共用同一套qohos原生模块名。 - 业务库:实际运行的 Qt 可执行形态为共享库(如
libcalculator.so),名称在QtAppConstants.ets的APP_LIBRARY_NAME中配置,并需与entry/libs/<ABI>/下放置的.so一致。
1.2 EmbeddedUIExtensionAbility 在本项目中的角色
- 系统定义:
EmbeddedUIExtensionAbility是嵌入式 UI 类扩展能力,与 UIExtension 会话(UIExtensionContentSession) 绑定;每次嵌入对应一次会话创建与销毁。 - 模板封装:
QBaseEmbeddedUiExtensionAbility继承系统基类,在onCreate、onSessionCreate、onSessionDestroy、onDestroy中统一转发到qpa.handleQEmbeddedUiExtensionAbility*;并在首次创建时用uiExtensionMode: true初始化 Qt 应用上下文,使 QPA 按「扩展嵌入」路径而非普通全屏 Ability 路径工作。 - 双扩展名:
module.json5声明了两个嵌入式扩展:QEmbeddedUiExtensionAbility(extensionProcessMode: "instance")与QBundledEmbeddedUiExtensionAbility(extensionProcessMode: "bundle"),便于在同一模板内对比或选用不同进程/打包语义(具体调度以系统实现为准)。
1.3 宿主侧 EmbeddedComponent
- 使用位置:模板在 feature 模块
qEmbeddedUiExtensionHost中提供演示 AbilityEmbedQtAbility,其页面通过EmbeddedComponent(want, EmbeddedType.EMBEDDED_UI_EXTENSION)指定要拉起的扩展能力名称与参数。 - Want 约定:
EmbedQtAbility将bundleName设为当前应用包名,abilityName设为QEmbeddedUiExtensionAbility,并把启动参数中以io.qt.为前缀的项传入扩展,供 Qt 侧读取。
2. 工程与模块结构
2.1 应用标识(AppScope/app.json5)
应用级配置定义包名与版本信息,嵌入场景下 Want.bundleName 必须与之一致(模板在代码中用 getBundleInfoForSelfSync 取当前包名,避免硬编码错误)。
//:ohostemplateforqtapplication_20260331/AppScope/app.json5{"app":{"bundleName":"com.ohos.ohosqttemplate","configuration":"$profile:configuration","vendor":"example","versionCode":1000000,"versionName":"1.0.0","icon":"$media:app_icon","label":"$string:app_name"}}2.2 多模块工程(build-profile.json5)
工程级 build-profile.json5 声明两个模块:entry(主模块,含 Qt 与嵌入式扩展)与 qEmbeddedUiExtensionHost(feature,演示嵌入宿主)。构建产物为同一应用包内的多个 HAP/HSP(以实际打包方式为准),因此 feature 中的 EmbeddedComponent 可以指向 entry 中声明的 embeddedUI 能力。
与 SDK 相关的字段示例(签名等本地路径略):
compatibleSdkVersion、targetSdkVersion:决定可用的 Ability / Extension API 集。modules数组:每项name+srcPath对应磁盘上的子工程目录。
2.3 entry 模块配置要点(entry/src/main/module.json5)
下列字段直接影响运行时行为,建议对照阅读。
| 配置项 | 本模板取值 | 含义说明 |
|---|---|---|
type | entry | 应用主模块。 |
srcEntry | ./ets/qabilitystage/QAbilityStage.ets | 指定 AbilityStage 实现,用于多实例、多进程键值与 Qt 全局初始化钩子。 |
mainElement | QAbility | 默认启动的 UIAbility 名称。 |
deviceTypes | tablet、2in1 | 声明支持的设备类型;注释中说明 phone 与最小化还原存在已知问题(QTFOROH-1076)。 |
abilities → QAbility | launchType: "specified"、isolationProcess: true | 多实例与独立进程相关配置,与 QAbilityStage.onAcceptWant / onNewProcessRequest 配合。 |
extensionAbilities | 两条 type: "embeddedUI" | 声明嵌入式 UI 扩展;extensionProcessMode 分别为 instance 与 bundle。 |
嵌入式扩展与主 Ability 的声明片段如下:
//:ohostemplateforqtapplication_20260331/entry/src/main/module.json5"extensionAbilities":[{"name":"QEmbeddedUiExtensionAbility","srcEntry":"./ets/qability/QEmbeddedUiExtensionAbility.ets","icon":"$media:layered_image","type":"embeddedUI","description":"","exported":true,"extensionProcessMode":"instance"},{"name":"QBundledEmbeddedUiExtensionAbility","srcEntry":"./ets/qability/QBundledEmbeddedUiExtensionAbility.ets","icon":"$media:layered_image","type":"embeddedUI","description":"","exported":true,"extensionProcessMode":"bundle"}],"abilities":[{"name":"QAbility","srcEntry":"./ets/qability/QAbility.ets","launchType":"specified",// ..."exported":true,"isolationProcess":true,要点:type 必须为 embeddedUI,否则系统不会按嵌入式 UI 扩展路由;exported: true 允许同应用内通过 Want 访问该能力名称。
2.4 feature 宿主模块(qEmbeddedUiExtensionHost/src/main/module.json5)
该模块 仅声明普通 UIAbility,不声明 extensionAbilities;嵌入的扩展能力仍落在 entry 中,由运行时根据包内合并后的清单解析。
//:ohostemplateforqtapplication_20260331/qEmbeddedUiExtensionHost/src/main/module.json5{"module":{"name":"qEmbeddedUiExtensionHost","type":"feature","description":"$string:module_desc","mainElement":"EmbedQtAbility","deviceTypes":["2in1","tablet"],"deliveryWithInstall":true,"installationFree":false,"pages":"$profile:main_pages","abilities":[{"name":"EmbedQtAbility","srcEntry":"./ets/embedqtability/EmbedQtAbility.ets",// ..."exported":true,"skills":[{"entities":["entity.system.home"],"actions":["action.system.home"]}]}],}}mainElement: "EmbedQtAbility" 表示从桌面图标等方式启动该 feature 时,默认进入嵌入演示 Ability。
3. 代码链路:从进程启动到 Qt 绘制
3.1 AbilityStage 与 Qt 单次初始化(QAbilityStage.ets)
QAbilityStage 在普通模式与扩展模式下都会调用 qpa.setupQtApplication,区别是 uiExtensionMode 与 abilityClassName。扩展能力首次 onCreate 时走 initQtAppContextInUiExtensionMode,确保 QPA 以嵌入扩展语义初始化。
//:ohostemplateforqtapplication_20260331/entry/src/main/ets/qabilitystage/QAbilityStage.etsprivatestaticinitQtAppContextImpl(appContext: common.ApplicationContext, abilityClassName:string, uiExtensionMode:boolean):void{if(!QAbilityStage.setupQtApplicationCalled){ hilog.info(LOG_DOMAIN,LOG_TAG,'QAbilityStage::initQtAppContextImpl: init with uiExtensionMode='+ uiExtensionMode); QAbilityStage.setupQtApplicationCalled =true; qpa.setupQtApplication({ appContext: appContext, modules: QtUtils.getModulesMapForQt(), appName:APP_LIBRARY_NAME, appArgs: QAbilityStage.appArgs, abilityClassName: abilityClassName, uiExtensionMode: uiExtensionMode, _unusedQChildProcess:newQChildProcess(),});}else{ hilog.info(LOG_DOMAIN,LOG_TAG,'QAbilityStage::initQtAppContextImpl: already initialized');}}publicstaticinitQtAppContextIfNeeded(appContext: common.ApplicationContext):void{ QAbilityStage.initQtAppContextImpl(appContext, QAbility.name,false);}publicstaticinitQtAppContextInUiExtensionMode(appContext: common.ApplicationContext, abilityClassName:string):void{ QAbilityStage.initQtAppContextImpl(appContext, abilityClassName,true);}APP_LIBRARY_NAME 来自 QtAppConstants.ets(当前为 libcalculator.so),需与部署到设备上的 Qt 应用库文件名一致。
//:ohostemplateforqtapplication_20260331/entry/src/main/ets/common/QtAppConstants.etsexportconstAPP_LIBRARY_NAME='libcalculator.so';exportconstLOG_DOMAIN=0x0000;exportconstLOG_TAG='ohosQtTemplate';3.2 主 UIAbility:QAbility.ets
主入口将系统回调逐一交给 QPA,形成与原生鸿蒙应用一致的「创建 → 窗口阶段 → 前后台 → 销毁」节奏。
//:ohostemplateforqtapplication_20260331/entry/src/main/ets/qability/QAbility.etsonCreate(want: Want, launchParam: AbilityConstant.LaunchParam){ hilog.info(LOG_DOMAIN,LOG_TAG,'QAbility::onCreate(): want.parameters: '+JSON.stringify(want.parameters)); QAbilityStage.initQtAppContextIfNeeded(this.context.getApplicationContext()); qpa.handleAbilityOnCreate(this, want, launchParam);}onDestroy():void|Promise<void>{ hilog.info(LOG_DOMAIN,LOG_TAG,'QAbility::onDestroy()');return qpa.handleAbilityOnDestroy(this);}// ...onWindowStageCreate(windowStage: Window.WindowStage){ hilog.info(LOG_DOMAIN,LOG_TAG,'QAbility::onWindowStageCreate(): this.launchWant.parameters: '+JSON.stringify(this.launchWant.parameters)); qpa.handleAbilityOnWindowStageCreate(this, windowStage);}3.3 嵌入式扩展基类:QBaseEmbeddedUiExtensionAbility.ets
扩展侧在 onCreate 中调用 initQtAppContextInUiExtensionMode,随后各会话阶段同样进入 QPA。子类 QEmbeddedUiExtensionAbility / QBundledEmbeddedUiExtensionAbility 仅区分日志用的类名,行为一致。
//:ohostemplateforqtapplication_20260331/entry/src/main/ets/qability/QBaseEmbeddedUiExtensionAbility.etsonCreate(launchParam: AbilityConstant.LaunchParam):void{ hilog.info(LOG_DOMAIN,LOG_TAG,'%{public}s::onCreate()',this.getClassName()); QAbilityStage.initQtAppContextInUiExtensionMode(this.context.getApplicationContext(),this.getClassName()); qpa.handleQEmbeddedUiExtensionAbilityOnCreate(this, launchParam);}onDestroy():void|Promise<void>{ hilog.info(LOG_DOMAIN,LOG_TAG,'%{public}s::onDestroy()',this.getClassName());return qpa.handleQEmbeddedUiExtensionAbilityOnDestroy(this);}onSessionCreate(want: Want, session: UIExtensionContentSession):void{ hilog.info(LOG_DOMAIN,LOG_TAG,'%{public}s::onSessionCreate()',this.getClassName()); qpa.handleQEmbeddedUiExtensionAbilityOnSessionCreate(this, want, session);}onSessionDestroy(session: UIExtensionContentSession):void{ hilog.info(LOG_DOMAIN,LOG_TAG,'%{public}s::onSessionDestroy()',this.getClassName()); qpa.handleQEmbeddedUiExtensionAbilityOnSessionDestroy(this, session);}3.4 XComponent 与 qohos:主窗口与扩展会话页面
主窗口节点页面(示例为 MainWindowNativeNode.ets)与扩展内页面 UiExtensionNativeNode.ets 结构相同:在 Stack 中放置 XComponent,指定 libraryname: 'qohos',由 QPA 注册的 native 模块承接 Qt 场景图。
//:ohostemplateforqtapplication_20260331/entry/src/main/ets/pages/MainWindowNativeNode.etsbuild(){Stack(){if(this.createInfo !==undefined){XComponent({ type: XComponentType.NODE, id:this.createInfo.xComponentId, libraryname:'qohos'}).onAttach(this.createInfo.onAttach).onAppear(this.createInfo.onAppear).onDisAppear(this.createInfo.onDisAppear).width('100%').height('100%')}}//:ohostemplateforqtapplication_20260331/entry/src/main/ets/pages/UiExtensionNativeNode.etsif(this.createInfo !==undefined){XComponent({ type: XComponentType.NODE, id:this.createInfo.xComponentId, libraryname:'qohos'}).onAppear(this.createInfo.onAppear).onDisAppear(this.createInfo.onDisAppear).onAttach(()=>{if(this.createInfo !==undefined){this.createInfo.onAttach?.(this.getUIContext());}else{ hilog.error(LOG_DOMAIN,LOG_TAG,'Cannot call onAttach, createInfo is undefined');}}).width('100%').height('100%')}3.5 嵌入演示:EmbedQtAbility → Index → EmbeddedComponent
EmbedQtAbility 在 onWindowStageCreate 中过滤 io.qt.* 参数,构造指向 QEmbeddedUiExtensionAbility 的 Want,写入 LocalStorage 后加载 pages/Index。
//:ohostemplateforqtapplication_20260331/qEmbeddedUiExtensionHost/src/main/ets/embedqtability/EmbedQtAbility.etsonWindowStageCreate(windowStage: window.WindowStage):void{const qtParameterPrefix:string='io.qt.';let qtParameters: Record<string, Object>={};if(this.launchWant.parameters){ Object.keys(this.launchWant.parameters).filter(key => key.startsWith(qtParameterPrefix)).forEach(qtKey => qtParameters[qtKey]=this.launchWant.parameters![qtKey]);}let localStorageProperties: Record<string, Want>={}; localStorageProperties[EmbedQtAbility.EMBEDDED_QT_START_WANT_PROP_NAME]={ bundleName: bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT).name, abilityName:'QEmbeddedUiExtensionAbility', parameters: qtParameters,}; windowStage.loadContent('pages/Index',newLocalStorage(localStorageProperties))}Index.ets 取出上述 Want,交给 EmbeddedComponentImpl。
//ohostemplateforqtapplication_20260331/qEmbeddedUiExtensionHost/src/main/ets/pages/Index.ets@Entry@Component struct Index {private want: Want = LocalStorage.getShared().get<Want>(EmbedQtAbility.EMBEDDED_QT_START_WANT_PROP_NAME)as Want;build(){Row(){Column(){EmbeddedComponentImpl({want:this.want}).width('100%').height('100%')}.width('100%')}.height('100%')}}EmbeddedComponentImpl.ets 中 EmbeddedComponent 的 want 不可省略,否则无法拉起嵌入式扩展;onTerminated / onError 用于观测嵌入失败或扩展退出。
//ohostemplateforqtapplication_20260331/qEmbeddedUiExtensionHost/src/main/ets/components/EmbeddedComponentImpl.etsbuild(){Row(){Column(){Text("Hello from EmbeddedComponentImpl")// This is the embedded component used to embed Qt application. Don't remove it.EmbeddedComponent(this.want, EmbeddedType.EMBEDDED_UI_EXTENSION).width('100%').height('90%').onTerminated((info: TerminationInfo)=>{console.warn(`Terminarion: code = ${info.code}, want = ${JSON.stringify(info.want)}`);}).onError((error: BusinessError)=>{console.error(`Error: code = ${error.code}, message = '${JSON.stringify(error.message)}'`);})}.width('100%')}.height('100%')}3.6 原生侧 entry 库(entry/src/main/cpp)
模板附带最小 libentry.so(hello.cpp + NAPI),与 libqohos.so、Qt 应用及 Qt 依赖库 分工不同:前者多为示例或胶水代码,Qt 运行主体由 QPA 与 Qt 共享库承担。CMake 仅声明 entry 与 libace_napi.z.so 链接,实际 Qt 库通过 entry/libs/<ABI>/ 部署。
#ohostemplateforqtapplication_20260331/entry/src/main/cpp/CMakeLists.txt cmake_minimum_required(VERSION 3.4.1) project(ohosQtTemplate) set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${NATIVERENDER_ROOT_PATH}${NATIVERENDER_ROOT_PATH}/include) add_library(entry SHARED hello.cpp) target_link_libraries(entry PUBLIC libace_napi.z.so)4. 生命周期与数据流小结
4.1 主 Ability 与扩展 Ability 对比
| 阶段 | QAbility(UIAbility) | QBaseEmbeddedUiExtensionAbility |
|---|---|---|
| 应用级 Qt 初始化 | initQtAppContextIfNeeded,uiExtensionMode: false | initQtAppContextInUiExtensionMode,uiExtensionMode: true |
| 窗口 | onWindowStageCreate 等,由 QPA 绑定主 WindowStage | 无独立「全屏窗口阶段」语义;由 onSessionCreate 进入会话 UI |
| 会话 | 不适用 | onSessionCreate / onSessionDestroy 对应每次嵌入 |
| 原生绘制载体 | MainWindowNativeNode 中 XComponent | UiExtensionNativeNode 中 XComponent |
4.2 整体数据流(示意)
entry
qEmbeddedUiExtensionHost
Want 指向同包扩展
EmbedQtAbility
LocalStorage 中的 Want
EmbeddedComponent
QEmbeddedUiExtensionAbility
libqohos.so / QPA
UiExtensionNativeNode XComponent
5. 集成与调试时注意点
- 库文件部署:将 Qt 应用依赖的qt库的
.so、libqohos.so及依赖的 Qt 模块库复制到entry/libs/<ABI>/(如arm64-v8a、x86_64),与模拟器或真机 ABI 一致。 - 应用库名:修改
QtAppConstants.ets中APP_LIBRARY_NAME,与目标.so文件名一致。 - 设备类型:entry 与 host 模块当前均面向 平板 / 2in1;若需手机,需评估
module.json5注释中的最小化还原问题后再改deviceTypes。 - 嵌入目标:演示页默认拉起
QEmbeddedUiExtensionAbility;若需改用QBundledEmbeddedUiExtensionAbility,应同步修改EmbedQtAbility.ets中的abilityName与测试场景。 - 日志:统一 TAG 为
ohosQtTemplate(见QtAppConstants.ets),便于在 HiLog 中过滤主流程与扩展流程。
6. 与传统 PC 桌面 Qt 应用的差异
- 进程与入口不是 main() 独占
系统先按鸿蒙规则拉起 Ability。全屏场景走 QAbility(UIAbility);需要嵌在别的界面里时走 EmbeddedUIExtensionAbility 子类,由宿主页面的 EmbeddedComponent 触发会话。 - Qt 由 QPA 插件接入系统,而不是直接对接 Win32/X11
ArkTS 通过 import qpa from ‘libqohos.so’ 把 onCreate / onWindowStageCreate / 前后台 / 销毁 以及扩展侧的 onSessionCreate / onSessionDestroy 等转给 Qt for OHOS 的 QPA(libqohos.so)。也就是说:鸿蒙生命周期 → NAPI → QPA → Qt 事件循环与窗口逻辑。 - 绘制表面是 ArkUI 的 XComponent,而不是系统原生 HWND 一层到底
主窗口和嵌入场景都在 ArkUI 里用 XComponent,type: NODE,libraryname: ‘qohos’ 留出一块原生区域;QPA 在这块 NODE 上挂接 OpenGL/渲染与输入。模板里对应 MainWindowNativeNode.ets 与 UiExtensionNativeNode.ets。 - “可执行文件”形态是共享库 + 配置名
业务 Qt 程序一般是 entry/libs// 下的 .so(如 QtAppConstants.ets 里的 APP_LIBRARY_NAME),再配合 libqohos.so 和 Qt 依赖库 一起打包进 HAP。没有传统 PC 上那种用户双击的单一 .exe 作为主入口(入口是鸿蒙 Ability)。 - 全局初始化与多实例
QAbilityStage 里 setupQtApplication 只应执行一次,并区分普通模式与 uiExtensionMode: true 的嵌入模式;module.json5 里 launchType / isolationProcess 等与 onAcceptWant / onNewProcessRequest 一起服务于多实例、进程隔离等鸿蒙能力。
本模板工程中,Qt 并不是「从 main() 起独占进程、直接对接 Win32/X11/Wayland/Cocoa」的传统桌面形态,而是落在 HarmonyOS Ability 模型 之内:由 QAbility(UIAbility)或 EmbeddedUIExtensionAbility 子类 作为系统入口,经 libqohos.so 将 Ability / Session 生命周期交给 QPA,再把界面画在 ArkUI XComponent(libraryname: 'qohos') 所暴露的原生节点上。
除下表外,还可记住三点:入口在 Ability 而非仅 main()、平台抽象层是 ohos QPA 而非 windows/xcb 等、业务常以 .so + APP_LIBRARY_NAME 形式部署于 entry/libs/<ABI>/。
| 维度 | 传统 PC(Windows / Linux / macOS) | 本鸿蒙 Qt 模板(ohostemplateforqtapplication_20260331) |
|---|---|---|
| 程序入口 | main() 中创建 QApplication / QGuiApplication 并 exec() | 系统拉起 UIAbility / ExtensionAbility;ArkTS 在 onCreate、onWindowStageCreate 等回调中调用 qpa.handleAbilityOnCreate 等,由 QPA 驱动 Qt |
| 平台插件(QPA) | windows、xcb / wayland、cocoa 等,直连各 OS 窗口与输入栈 | libqohos.so,衔接 Ability、WindowStage、扩展 Session 与 XComponent |
| 窗口与 UI 框架 | 以 Qt 窗口(QWidget / QWindow)为主,占满或管理自有层级 | ArkUI 页面 + XComponent 原生区域;全屏走 MainWindowNativeNode,嵌入走 UiExtensionNativeNode;宿主侧可用 EmbeddedComponent 拉起 EmbeddedUIExtensionAbility |
| 打包与部署 | 安装目录或安装包中的 可执行文件(.exe / ELF)及依赖 DLL/so | HAP 模块;Qt 应用多为 entry/libs/<ABI>/ 下的 .so,与 libqohos.so、Qt 依赖库 一并随包安装;入口能力名在 module.json5,应用库名在 QtAppConstants.ets 的 APP_LIBRARY_NAME |
| 生命周期 | 进程启动到退出大致对应应用存活期,前后台多与窗口最小化等相关 | 与 Ability 前后台、WindowStage 创建销毁、嵌入场景的 onSessionCreate / onSessionDestroy 强绑定,需与 QPA 对齐 |
| 设备与系统能力 | 由桌面环境与用户权限模型决定 | 受 module.json5 中 deviceTypes、权限声明、多模块(entry + feature) 及 真机/模拟器 ABI 约束 |
桌面 Qt 可概括为「Qt 即应用外壳」;鸿蒙模板则是「系统 Ability + ArkUI 壳 + XComponent 锚点 + ohos QPA」承载 Qt;嵌入能力再叠一层 同包 embeddedUI 扩展与 EmbeddedComponent。从 PC 迁来时,需改写入口与打包形态,并在调试中习惯用 HiLog 与 Ability 状态 观察运行阶段,而非仅依赖桌面上的进程列表或控制台。
总结
鸿蒙版 Qt 项目模板 ohostemplateforqtapplication_20260331 通过 QAbility + libqohos.so 实现常规全屏 Qt 应用,通过 QBaseEmbeddedUiExtensionAbility + module.json5 中 embeddedUI 声明 提供可被 EmbeddedComponent 嵌入的能力,并在 feature 模块 中用 EmbedQtAbility → EmbeddedComponent 走完端到端演示链路。
理解本模板的关键在于:清单中的 extensionProcessMode 与 type: embeddedUI、ArkTS 侧对 QPA 的生命周期转发,以及 XComponent NODE 与 libraryname: 'qohos' 作为 Qt 渲染锚点。在此基础上的业务开发,主要集中在 Qt 侧功能、APP_LIBRARY_NAME 与 Want 参数约定,以及权限与 deviceTypes 的调整。
最后,欢迎加入开源鸿蒙开发者社区交流:https://harmonypc.ZEEKLOG.net/
附录:延伸阅读
以下链接供查阅嵌入式 UI 扩展与 HarmonyOS Ability 相关内容:
- HarmonyOS 嵌入式 UI 扩展组件实战 - 博客园
- HarmonyOS 应用开发中 EmbeddedUIExtensionAbility:跨进程 UI 嵌入 - SegmentFault
- 知乎专栏
- https://wiki.qt.io/Qt_for_OpenHarmony/zh?login=from_ZEEKLOG
- https://wiki.qt.io/Qt5.12.12_Open_Source_Release_for_HarmonyOS_zh
官方文档请优先参考:HarmonyOS 开发者官网。