Qt for HarmonyOS/user development/application continuation guild zh: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
| Line 1: | Line 1: | ||
__TOC__ | |||
== 简介 == | == 简介 == | ||
本文面向 Qt 开发者,介绍如何在 HarmonyOS | 本文面向 Qt 开发者,介绍如何在 HarmonyOS 上实现“应用接续”(跨设备迁移应用状态)。QtOhosExtras 模块已封装鸿蒙 <code>onContinue</code>/<code>onNewWant</code> 等流程,开发者仅需使用 Qt 接口完成迁移请求、数据封装与目标端恢复。 | ||
== 能力与模块 == | == 能力与模块 == | ||
* '''能力''':在设备间迁移当前应用状态,支持快速预热(ContinueQuickStart)与源端保留/退出。 | |||
* '''模块''':<code>qtohosextras</code> | |||
* | ** '''核心类''':<code>QOhosAbilityContext</code>、<code>QOhosOnContinueContext</code>、<code>QOhosWantInfo</code> | ||
** '''工具函数''':<code>QtOhosExtras::tryGetOnContinueData</code> | |||
* '''数据通道''':<100KB 通过 Want parameters 携带(Base64 的 <code>QByteArray</code>,键名 <code>__io_qt_on_continue_migration_data</code>);传输更多数据的功能 Qt 暂未实现,将会在后续版本提供。 | |||
** <code>QOhosAbilityContext</code> | |||
** <code>QtOhosExtras::tryGetOnContinueData</code> | |||
* | |||
== 工作流程 == | == 工作流程 == | ||
# 源端收到迁移请求(<code>continueRequestReceived</code>) → 序列化业务状态 → 同意/拒绝 → 按需决定源端是否退出。 | |||
# 源端收到迁移请求(<code>continueRequestReceived</code>) | # 目标端通过启动或 <code>newWantInfoReceived</code> 收到 Want → 用 <code>tryGetOnContinueData()</code> 恢复状态。 | ||
# '''可选''':配置 ContinueQuickStart 预热;动态开关迁移能力;控制源端保留/退出。 | |||
# | |||
# | |||
== 核心 API 速览 == | == 核心 API 速览 == | ||
{| class="wikitable" | {| class="wikitable" | ||
! API | ! API !! 说明 | ||
|- | |- | ||
| <code>QOhosAbilityContext::continueRequestReceived</code> || | | <code>QOhosAbilityContext::continueRequestReceived</code> || 源端迁移请求信号 | ||
|- | |- | ||
| <code>QOhosOnContinueContext</code> || | | <code>QOhosOnContinueContext</code> || 提供同意/拒绝/版本不匹配响应,设置源端是否退出 | ||
|- | |- | ||
| <code>QOhosAbilityContext::newWantInfoReceived</code> || | | <code>QOhosAbilityContext::newWantInfoReceived</code> || 目标端接收新 Want 信号(热启动) | ||
|- | |- | ||
| <code>QOhosWantInfo::launchReason()</code> || | | <code>QOhosWantInfo::launchReason()</code> || 获取启动原因:<code>StartAbility</code> / <code>PrepareContinuation</code> / <code>Continuation</code> | ||
|- | |- | ||
| <code>QtOhosExtras::tryGetOnContinueData(const QOhosWant &want)</code> || 提取迁移数据(返回 <code>QSharedPointer | | <code>QtOhosExtras::tryGetOnContinueData(const QOhosWant &want)</code> || 提取迁移数据(返回 <code>QSharedPointer<QByteArray></code>) | ||
|- | |- | ||
| <code>QOhosAbilityContext::setContinuationActive(bool)</code> || 动态开关迁移能力 | | <code>QOhosAbilityContext::setContinuationActive(bool)</code> || 动态开关迁移能力 | ||
|- | |- | ||
| <code>QOhosOnContinueContext::setExitAppOnSourceDeviceAfterMigration(bool)</code> || | | <code>QOhosOnContinueContext::setExitAppOnSourceDeviceAfterMigration(bool)</code> || 控制源端是否在成功迁移后退出 | ||
|} | |} | ||
== 源端实现(发起迁移) == | == 源端实现(发起迁移) == | ||
# '''监听迁移请求''':连接 <code>continueRequestReceived</code> 信号。 | |||
# '''校验版本/业务条件''':检查 <code>ctx->sourceApplicationVersionCode()</code>。 | |||
# '''序列化状态并响应''': | |||
#* 同意:<code>setAgreeResponse(serialized)</code> (数据需 <100KB)。 | |||
#* 版本不匹配:<code>setMismatchResponse()</code>。 | |||
#* 拒绝:<code>setRejectResponse()</code>。 | |||
# '''是否保留源端''':调用 <code>setExitAppOnSourceDeviceAfterMigration(false)</code>(默认值为 true,即退出)。 | |||
# '''动态开关''':根据业务逻辑调用 <code>setContinuationActive(bool)</code>。 | |||
'''示例(同意迁移,保留源端):''' | |||
<source lang="cpp"> | |||
auto ability = QOhosAbilityContext::getInstanceForMainWindow(window.windowHandle()); | auto ability = QOhosAbilityContext::getInstanceForMainWindow(window.windowHandle()); | ||
QObject::connect(ability.get(), &QOhosUiAbilityContext::continueRequestReceived, | QObject::connect(ability.get(), &QOhosUiAbilityContext::continueRequestReceived, | ||
| Line 92: | Line 56: | ||
QByteArray payload = /* serialize state (<100KB) */; | QByteArray payload = /* serialize state (<100KB) */; | ||
ctx->setAgreeResponse(payload); | ctx->setAgreeResponse(payload); | ||
ctx->setExitAppOnSourceDeviceAfterMigration(false); // | ctx->setExitAppOnSourceDeviceAfterMigration(false); // 需要保留源端 | ||
} else { | } else { | ||
ctx->setMismatchResponse(); | ctx->setMismatchResponse(); | ||
} | } | ||
}); | }); | ||
</ | </source> | ||
== 目标端实现(接收与恢复) == | == 目标端实现(接收与恢复) == | ||
# '''冷启动获取''':<code>auto wantInfo = QOhosAppContext::getAppLaunchWantInfo();</code> | |||
# '''运行时获取''':监听 <code>QOhosAbilityContext::newWantInfoReceived</code> 信号。 | |||
# '''场景区分''':检查 <code>launchReason()</code> 是否为 <code>Continuation</code>。 | |||
# '''提取数据''':使用 <code>QtOhosExtras::tryGetOnContinueData</code>。 | |||
# '''恢复 UI''':反序列化数据还原业务状态。 | |||
'''示例(处理冷启动与热启动):''' | |||
<source lang="cpp"> | |||
// 1. 冷启动处理 | |||
< | |||
// | |||
if (auto launchInfo = QOhosAppContext::getAppLaunchWantInfo()) { | if (auto launchInfo = QOhosAppContext::getAppLaunchWantInfo()) { | ||
auto data = QtOhosExtras::tryGetOnContinueData(launchInfo->want()); | auto data = QtOhosExtras::tryGetOnContinueData(launchInfo->want()); | ||
if (data) { /* | if (data) { /* 反序列化并恢复状态 */ } | ||
} | } | ||
// | // 2. 热启动处理(应用已在后台运行) | ||
auto ability = QOhosAbilityContext::getInstanceForMainWindow(window.windowHandle()); | auto ability = QOhosAbilityContext::getInstanceForMainWindow(window.windowHandle()); | ||
QObject::connect(ability.get(), &QOhosUiAbilityContext::newWantInfoReceived, | QObject::connect(ability.get(), &QOhosUiAbilityContext::newWantInfoReceived, | ||
| Line 132: | Line 84: | ||
if (info->launchReason() == QOhosWantInfo::LaunchReason::Continuation) { | if (info->launchReason() == QOhosWantInfo::LaunchReason::Continuation) { | ||
auto data = QtOhosExtras::tryGetOnContinueData(info->want()); | auto data = QtOhosExtras::tryGetOnContinueData(info->want()); | ||
if (data) { /* | if (data) { /* 反序列化并恢复状态 */ } | ||
} | } | ||
}); | }); | ||
</ | </source> | ||
== 快速预热(ContinueQuickStart) == | == 快速预热(ContinueQuickStart) == | ||
* '''适用场景''':希望目标端先拉起界面占位,待数据传输完成后再刷新内容。 | |||
* '''配置''':在 <code>module.json5</code> 目标 Ability 的 <code>continueType</code> 字段末尾添加 <code>_ContinueQuickStart</code>。 | |||
* '''流程''':系统先触发 <code>PrepareContinuation</code>(预热),随后触发 <code>Continuation</code>(携带数据)。 | |||
'''示例(区分预热与正式数据):''' | |||
<source lang="cpp"> | |||
< | |||
QObject::connect(ability.get(), &QOhosUiAbilityContext::newWantInfoReceived, | QObject::connect(ability.get(), &QOhosUiAbilityContext::newWantInfoReceived, | ||
[](const QSharedPointer<QOhosWantInfo> &info) { | [](const QSharedPointer<QOhosWantInfo> &info) { | ||
switch (info->launchReason()) { | switch (info->launchReason()) { | ||
case QOhosWantInfo::LaunchReason::PrepareContinuation: | case QOhosWantInfo::LaunchReason::PrepareContinuation: | ||
// | // 执行轻量级初始化或显示加载占位图 | ||
break; | break; | ||
case QOhosWantInfo::LaunchReason::Continuation: | case QOhosWantInfo::LaunchReason::Continuation: | ||
auto data = QtOhosExtras::tryGetOnContinueData(info->want()); | auto data = QtOhosExtras::tryGetOnContinueData(info->want()); | ||
if (data) { /* | if (data) { /* 恢复完整业务状态 */ } | ||
break; | break; | ||
default: | default: | ||
break; | break; | ||
} | } | ||
}); | }); | ||
</ | </source> | ||
== 注意事项 == | == 注意事项 == | ||
* '''显式响应''':未响应迁移请求默认视为拒绝,务必在回调中明确处理。 | |||
* '''线程安全''':回调在 Qt 主线程执行,但仍需注意避免耗时的同步操作阻塞 UI。 | |||
* '''数据限制''':目前仅支持 <100KB 数据。若超出此限制,迁移可能会失败。 | |||
* '''向前兼容''':迁移数据建议携带版本号,以便目标端处理来自旧版本源端的接续数据。 | |||
== 参考资源 == | |||
* '''示例代码''':<code>qtohosextras/examples/qtohosextras/applicationcontinuation/main.cpp</code> | |||
* | * '''源码实现''':<code>qtohosextras/src/ohosextras/qohosabilitycontext.cpp</code> | ||
* | * '''外部链接''':[https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/app-continuation HarmonyOS 应用接续官方指南] | ||
* | |||
Revision as of 07:08, 25 December 2025
简介
本文面向 Qt 开发者,介绍如何在 HarmonyOS 上实现“应用接续”(跨设备迁移应用状态)。QtOhosExtras 模块已封装鸿蒙
onContinue
/
onNewWant
等流程,开发者仅需使用 Qt 接口完成迁移请求、数据封装与目标端恢复。
能力与模块
- 能力:在设备间迁移当前应用状态,支持快速预热(ContinueQuickStart)与源端保留/退出。
- 模块:
qtohosextras- 核心类:、
QOhosAbilityContext、QOhosOnContinueContextQOhosWantInfo - 工具函数:
QtOhosExtras::tryGetOnContinueData
- 核心类:
- 数据通道:<100KB 通过 Want parameters 携带(Base64 的 ,键名
QByteArray);传输更多数据的功能 Qt 暂未实现,将会在后续版本提供。__io_qt_on_continue_migration_data
工作流程
- 源端收到迁移请求() → 序列化业务状态 → 同意/拒绝 → 按需决定源端是否退出。
continueRequestReceived - 目标端通过启动或 收到 Want → 用
newWantInfoReceived恢复状态。tryGetOnContinueData()
- 可选:配置 ContinueQuickStart 预热;动态开关迁移能力;控制源端保留/退出。
核心 API 速览
| API | 说明 |
|---|---|
QOhosAbilityContext::continueRequestReceived
|
源端迁移请求信号 |
QOhosOnContinueContext
|
提供同意/拒绝/版本不匹配响应,设置源端是否退出 |
QOhosAbilityContext::newWantInfoReceived
|
目标端接收新 Want 信号(热启动) |
QOhosWantInfo::launchReason()
|
获取启动原因:StartAbility
PrepareContinuation
Continuation
|
QtOhosExtras::tryGetOnContinueData(const QOhosWant &want)
|
提取迁移数据(返回 QSharedPointer<QByteArray>
|
QOhosAbilityContext::setContinuationActive(bool)
|
动态开关迁移能力 |
QOhosOnContinueContext::setExitAppOnSourceDeviceAfterMigration(bool)
|
控制源端是否在成功迁移后退出 |
源端实现(发起迁移)
- 监听迁移请求:连接 信号。
continueRequestReceived - 校验版本/业务条件:检查 。
ctx->sourceApplicationVersionCode()
- 序列化状态并响应:
- 同意:(数据需 <100KB)。
setAgreeResponse(serialized)
- 版本不匹配:。
setMismatchResponse()
- 拒绝:。
setRejectResponse()
- 同意:
- 是否保留源端:调用 (默认值为 true,即退出)。
setExitAppOnSourceDeviceAfterMigration(false)
- 动态开关:根据业务逻辑调用 。
setContinuationActive(bool)
示例(同意迁移,保留源端):
auto ability = QOhosAbilityContext::getInstanceForMainWindow(window.windowHandle());
QObject::connect(ability.get(), &QOhosUiAbilityContext::continueRequestReceived,
[](auto ctx) {
auto appVersion = QOhosAppContext::instance()->getBundleInfo()->versionCode();
if (ctx->sourceApplicationVersionCode() == appVersion) {
QByteArray payload = /* serialize state (<100KB) */;
ctx->setAgreeResponse(payload);
ctx->setExitAppOnSourceDeviceAfterMigration(false); // 需要保留源端
} else {
ctx->setMismatchResponse();
}
});
目标端实现(接收与恢复)
- 冷启动获取:
auto wantInfo = QOhosAppContext::getAppLaunchWantInfo();
- 运行时获取:监听 信号。
QOhosAbilityContext::newWantInfoReceived
- 场景区分:检查 是否为
launchReason()
。Continuation - 提取数据:使用 。
QtOhosExtras::tryGetOnContinueData
- 恢复 UI:反序列化数据还原业务状态。
示例(处理冷启动与热启动):
// 1. 冷启动处理
if (auto launchInfo = QOhosAppContext::getAppLaunchWantInfo()) {
auto data = QtOhosExtras::tryGetOnContinueData(launchInfo->want());
if (data) { /* 反序列化并恢复状态 */ }
}
// 2. 热启动处理(应用已在后台运行)
auto ability = QOhosAbilityContext::getInstanceForMainWindow(window.windowHandle());
QObject::connect(ability.get(), &QOhosUiAbilityContext::newWantInfoReceived,
[](const QSharedPointer<QOhosWantInfo> &info) {
if (info->launchReason() == QOhosWantInfo::LaunchReason::Continuation) {
auto data = QtOhosExtras::tryGetOnContinueData(info->want());
if (data) { /* 反序列化并恢复状态 */ }
}
});
快速预热(ContinueQuickStart)
- 适用场景:希望目标端先拉起界面占位,待数据传输完成后再刷新内容。
- 配置:在 目标 Ability 的
module.json5
字段末尾添加continueType。_ContinueQuickStart - 流程:系统先触发 (预热),随后触发
PrepareContinuation(携带数据)。Continuation
示例(区分预热与正式数据):
QObject::connect(ability.get(), &QOhosUiAbilityContext::newWantInfoReceived,
[](const QSharedPointer<QOhosWantInfo> &info) {
switch (info->launchReason()) {
case QOhosWantInfo::LaunchReason::PrepareContinuation:
// 执行轻量级初始化或显示加载占位图
break;
case QOhosWantInfo::LaunchReason::Continuation:
auto data = QtOhosExtras::tryGetOnContinueData(info->want());
if (data) { /* 恢复完整业务状态 */ }
break;
default:
break;
}
});
注意事项
- 显式响应:未响应迁移请求默认视为拒绝,务必在回调中明确处理。
- 线程安全:回调在 Qt 主线程执行,但仍需注意避免耗时的同步操作阻塞 UI。
- 数据限制:目前仅支持 <100KB 数据。若超出此限制,迁移可能会失败。
- 向前兼容:迁移数据建议携带版本号,以便目标端处理来自旧版本源端的接续数据。
参考资源
- 示例代码:
qtohosextras/examples/qtohosextras/applicationcontinuation/main.cpp
- 源码实现:
qtohosextras/src/ohosextras/qohosabilitycontext.cpp
- 外部链接:HarmonyOS 应用接续官方指南