HarmonyOS鸿蒙Next中同个Ability创建了多个子窗口,在用UIAbilityContext.setMissionLabel()时会修改所有(同个Alibity创建)后台任务标题?
HarmonyOS鸿蒙Next中同个Ability创建了多个子窗口,在用UIAbilityContext.setMissionLabel()时会修改所有(同个Alibity创建)后台任务标题? 描述:同个Ability创建了多个子1窗口,在用UIAbilityContext.setMissionLabel()时会修改所有(同个Alibity创建)任务标题,这个有什么方式解决后台任务名称问题?
问题复现项目地址
https://gitee.com/code_yu/hongmeng-test
展示效果

关键代码
module.json5
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"phone"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
// 多窗口时必要的文件
"srcEntry": "./ets/application/AppAbility.ets",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:layered_image",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
]
},
{
"name": "WinAppAbility",
"srcEntry": "./ets/winappability/WinAppAbility.ets",
"description": "$string:WinAppAbility_desc",
"icon": "$media:layered_image",
"label": "$string:WinAppAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"launchType": "specified",
skills: [
{
actions: ["WinApp"],
},
]
}
],
"extensionAbilities": [
{
"name": "EntryBackupAbility",
"srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
"type": "backup",
"exported": false,
"metadata": [
{
"name": "ohos.extension.backup",
"resource": "$profile:backup_config"
}
],
}
]
}
}
Index.ets 页面点击事件,创建窗体
import { common } from '@kit.AbilityKit';
@Entry
@Component
struct Index {
@State appid: number = 0;
build() {
RelativeContainer() {
Button('创建窗口')
.id('HelloWorld')
.fontSize($r('app.float.page_text_font_size'))
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
.onClick(() => {
this.appid++
// 创建子窗口
let context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext
//启动一个新的UIAbility
context.startAbility({
action: 'WinApp',
parameters: {
appID: `${this.appid}`
},
})
})
Text('你可以多创建几个窗口,然后上滑查看后台任务列表就会发现标题是一样的').margin({top: 20}).fontColor("#f00")
}
.height('100%')
.width('100%')
}
}
WinAppAbility.ets
import { UIAbility, AbilityConstant, Want } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { hilog } from '@kit.PerformanceAnalysisKit';
const DOMAIN = 0x0001
export default class WebAbility extends UIAbility {
storage: LocalStorage = new LocalStorage();
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
if (want.parameters) {
const appID = want.parameters.appID as string
// 传递给页面
this.storage.setOrCreate('appID', appID);
// 设置后台任务名称,
// 问题就处在这,会修改所有窗口的标题
this.context.setMissionLabel(`${appID}`)
}
}
onWindowStageCreate(windowStage: window.WindowStage): void {
windowStage.loadContent('pages/WinApp', this.storage, async (err, data) => {
if (err.code) {
hilog.info(DOMAIN, 'WebApp', '创建应用失败: %{public}s', JSON.stringify(err));
return;
}
})
}
onDestroy() {
}
onWindowStageDestroy() {
}
onForeground() {
}
onBackground() {
}
onNewWant() {
}
}
WinApp.ets 页面
@Entry({ useSharedStorage: true })
@Component
struct WinApp {
@LocalStorageProp('appID') appID: string = '';
build() {
RelativeContainer() {
Text("窗口:" + this.appID)
.fontSize(40)
.fontWeight(FontWeight.Bold)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
})
}
.height('100%')
.width('100%')
}
}
“srcEntry”: “./ets/application/AppAbility.ets”( AbilityStage 文件)
import { AbilityStage,Want } from '@kit.AbilityKit';
export default class MyAbilityStage extends AbilityStage {
onCreate() {
}
// 多窗口时用到
onAcceptWant(want: Want) {
// 当打开的Ability 是 'WinAppAbility '时进行拦截
if (want && want.abilityName === 'WinAppAbility') {
// 业务需求: 当指定的文档窗口已打开就显示已存在的,否则新建一个窗口打开文档
if (want.parameters) {
return `WinAppAbility_${want.parameters.appID}`;
}
}
return '';
}
}
更多关于HarmonyOS鸿蒙Next中同个Ability创建了多个子窗口,在用UIAbilityContext.setMissionLabel()时会修改所有(同个Alibity创建)后台任务标题?的实战教程也可以访问 https://www.itying.com/category-93-b0.html
setMissionLabel当前不支持在多实例场景设置不同ability未不同label的功能。该功能从api20开始支持
更多关于HarmonyOS鸿蒙Next中同个Ability创建了多个子窗口,在用UIAbilityContext.setMissionLabel()时会修改所有(同个Alibity创建)后台任务标题?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
你把每个子窗口设计为独立的UIAbility实例,通过启动不同UIAbility实现独立任务标签控制呢?
在module.json5中为每个子窗口定义独立的UIAbility,并配置支持分屏:
"abilities": [
{
"name": "EntryAbility1",
"supportWindowMode": ["split"],
// 其他配置...
},
{
"name": "EntryAbility2",
"supportWindowMode": ["split"],
// 其他配置...
}
]
通过startAbility启动不同UIAbility实例,并在各自的onCreate生命周期中设置独立任务标签:
// 主Ability中启动子窗口
let want1: Want = {
bundleName: 'com.example.demo',
abilityName: 'EntryAbility1',
moduleName: ''
};
let option: StartOptions = {
windowMode: AbilityConstant.WindowMode.WINDOW_MODE_SPLIT_PRIMARY
};
context.startAbility(want1, option);
// 在EntryAbility1的onCreate中设置标签
import { UIAbility } from '@kit.AbilityKit';
export default class EntryAbility1 extends UIAbility {
onCreate() {
this.context.setMissionLabel('窗口1');
}
}
请检查一下 UIAbilitye的启动模式是否是 specified启动模式
假设应用有两个UIAbility实例,即EntryAbility和SpecifiedAbility。EntryAbility以specified模式启动SpecifiedAbility。基本原理如下:
- EntryAbility调用startAbility()方法,并在Want的parameters字段中设置唯一的Key值,用于标识SpecifiedAbility。
- 系统在拉起SpecifiedAbility之前,会先进入对应的AbilityStage的onAcceptWant()生命周期回调,获取用于标识目标UIAbility的Key值。
- 系统会根据获取的Key值来匹配UIAbility。
- 如果匹配到对应的UIAbility,则会启动该UIAbility实例,并进入onNewWant()生命周期回调。
- 如果无法匹配对应的UIAbility,则会创建一个新的UIAbility实例,并进入该UIAbility实例的onCreate()生命周期回调和onWindowStageCreate()生命周期回调。
有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html
我用的就是specified启动模式.
{
"name": "WebAbility",
"srcEntry": "./ets/webabilit/WebAbilit.ets",
"description": "$string:WebAbility_desc",
"icon": "$media:layered_image",
"label": "$string:WebAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"launchType": "specified",
skills: [
{
actions: ["WebApp"],
},
]
}
export default class MyAbilityStage extends AbilityStage {
onCreate() {
}
// 多窗口时用到
onAcceptWant(want: Want) {
// 当打开的Ability 是 'WebAbility'时进行拦截
if (want && want.abilityName === 'WebAbility') {
// 业务需求: 当指定的文档窗口已打开就显示已存在的,否则新建一个窗口打开文档
if (want.parameters) {
return `WebAppAbility_${want.parameters.appID}`;
}
}
return '';
}
}
我现在的流程就是你说的这样, 实例都没有任何问题,问题是后台任务名称使一样的,比如创建了三个子窗口,三个子窗口的后台窗口任务名称会变为一样,
我创建了一个简单的项目, 可以复现该问题, https://gitee.com/code_yu/hongmeng-test ,前辈帮忙看看,感谢,
WEB开发不太清楚,但是arkts有getuicontext可以获取当前页面对应的uiability实例,
在HarmonyOS Next中,同个Ability创建的多个子窗口共享同一个任务栈。使用UIAbilityContext.setMissionLabel()设置的是整个Ability任务栈的标签,因此会同时修改所有子窗口的后台任务标题。这是系统任务管理的默认行为,无法单独为子窗口设置独立的后台任务标题。
在HarmonyOS Next中,UIAbilityContext.setMissionLabel() 方法设置的是当前Ability实例对应的任务(Mission)标签。当同一个Ability(例如 WinAppAbility)通过 onAcceptWant 返回不同的实例名称(如 WinAppAbility_1、WinAppAbility_2)来创建多个窗口时,这些窗口本质上属于同一个Ability的不同实例,但它们共享同一个 UIAbilityContext。
问题根源:
setMissionLabel 是通过 this.context(即 UIAbilityContext)调用的。在当前的架构设计下,同一个Ability的多个实例共享的上下文在设置任务标签时,可能会作用于该Ability相关的所有任务实例,导致所有窗口的后台任务标题被同步修改。这是系统层面对Ability实例与任务管理的一种当前行为。
解决方案: 要解决每个子窗口在后台任务列表中显示独立标题的需求,目前的标准做法是 为每个需要独立标题的窗口使用独立的Ability。这是HarmonyOS多窗口和任务管理的推荐设计模式。
具体调整方案:
- 重构Ability设计:不要依赖同一个
WinAppAbility通过不同参数创建多实例。应为每个需要独立任务标签的窗口配置独立的Ability。 - 定义多个Ability:在
module.json5文件的abilities数组中,声明多个Ability。它们可以共享同一个srcEntry(指向同一个Ability类文件),但必须拥有不同的name和label。 - 独立启动:在
Index.ets的点击事件中,根据需求启动不同的Ability(例如通过不同的action或entity),而不是通过参数启动同一个Ability。 - 设置默认标签:每个独立Ability可以在其
module.json5的label字段设置不同的默认任务标签,也可以在运行时根据需要在各自的Ability实例中调用setMissionLabel。
修改示例概要:
module.json5中声明多个Ability:{ "abilities": [ { "name": "WinAppAbility1", "label": "窗口1", // 默认任务标签 "srcEntry": "./ets/winappability/WinAppAbility.ets", "skills": [{"actions": ["action.win.app1"]}] // ... }, { "name": "WinAppAbility2", "label": "窗口2", "srcEntry": "./ets/winappability/WinAppAbility.ets", "skills": [{"actions": ["action.win.app2"]}] // ... } ] }- 启动时指定对应的Ability:
context.startAbility({ action: 'action.win.app1', // 或 'action.win.app2' // ... })
总结: 在当前HarmonyOS Next的架构下,要实现多窗口在后台任务列表中拥有独立标题,最直接有效的方式是为每个窗口使用独立的Ability定义,而不是依赖同一个Ability的多个实例。这种方式符合系统任务管理模型,能确保每个任务标签独立可控。

