HarmonyOS鸿蒙Next中长时任务通知能否不显示进度UI

HarmonyOS鸿蒙Next中长时任务通知能否不显示进度UI 参考官方文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/continuous-task

业务场景:给打印机发送打印任务时需要用到长时任务持续发送数据,但是可能同时给多个打印机提交任务,任务进度是没法获取的。

如果长时任务设置为DATA_TRANSFER(数据传输)类型时,长时任务10分钟后会被系统自动取消,导致数据传输中断,如果中途更新长时任务必须为实况窗,实况窗又带进度条

我试着改用MULTI_DEVICE_CONNECTION(多设备互联)类型,长时任务通知会显示“正在运行分布式任务”,通知文字无法修改内容,而且和打印业务没有关联。

问题1:更新长时任务的实况窗有一个进度条UI,当前不传进度值也显示了进度条UI。是否能设置成不显示?

问题2:长时任务通知内容“正在运行分布式任务”,文字不符合打印业务场景,是否可以修改?

问题3:是否有别的方案呢?


更多关于HarmonyOS鸿蒙Next中长时任务通知能否不显示进度UI的实战教程也可以访问 https://www.itying.com/category-93-b0.html

15 回复

这个问题不要只当成“能不能隐藏进度条”的 UI 问题看。长时任务的 type 会影响系统保活策略、实况窗/通知模板和用户可感知状态,不能为了避开进度 UI 随便换成不匹配的类型。

打印场景可以这样拆:

  1. 如果 App 只是把任务下发给打印机,后续由打印机自己执行,建议前台完成下发后用普通文本通知展示“已发送/打印完成/失败”,不用长时任务硬撑。

  2. 如果 App 必须在后台持续传输数据,DATA_TRANSFER 语义更接近,但公开模板下通常不能把进度区域完全改成纯文本。拿不到百分比时,可以用阶段状态代替:排队中、连接打印机、发送数据、等待打印机处理。

  3. MULTI_DEVICE_CONNECTION 不建议只为隐藏进度而使用,它的系统文案和语义是分布式连接,和打印任务不完全一致,审核和用户理解都容易别扭。

  4. 多台打印机同时打印时,建议做任务队列摘要,例如“3 个打印任务进行中”,不要每个都拉一个长时任务通知。

类比一下:长时任务通知像系统给用户看的“施工告示牌”,可以写阶段和状态,但不能把告示牌伪装成另一个工程。参考:

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/continuous-task

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/notification-with-text

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/liveviewkit-development-notes

更多关于HarmonyOS鸿蒙Next中长时任务通知能否不显示进度UI的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


图片

我现在长时任务通知就是为了给打印机传输数据的,并且所有打印任务公用一个长时任务。每个打印任务有自己的进度,如图中另一个通知“正在发送第X页”。

如果时间大于3分钟,用worker开启子线程

如果打印任务超过 10 分钟后数据传输中断,worker 只能解决线程阻塞问题,不能替代后台保活。你这个场景核心还是长时任务类型、真实业务和进度更新要匹配:打印数据持续传输更接近 DATA_TRANSFER,如果还涉及蓝牙链路,再按实际连接方式评估 bluetoothInteraction。需要注意数据传输类长时任务如果长时间不更新进度,尤其首次超过 10 分钟没有有效进度更新,系统可能会取消任务。建议把打印队列集中管理:长任务只覆盖当前正在传输的队列,按页/字节持续更新实况窗进度,完成或失败后主动停止;不要只开一个长时任务但通知和进度长期不变。

这类打印任务要先区分“长时任务类型”和“通知模板”两个问题。DATA_TRANSFER 能表达数据传输,但它对应的实况窗更偏进度型任务;如果业务完全拿不到进度,公开参数里通常不能把系统进度区域彻底改成自定义纯文本。

建议这样设计:

  1. 如果能估算任务阶段,就用阶段型状态代替百分比,例如排队、连接打印机、传输中、等待设备响应、完成。
  2. 如果完全无进度,避免伪造百分比;可以只在业务 UI 内展示多打印机队列,系统通知只承担“任务仍在进行”的提示。
  3. MULTI_DEVICE_CONNECTION 的系统文案和能力语义绑定,不建议为了隐藏进度而强行换类型,否则文案和打印业务不一致。
  4. 真正的数据发送放到 taskpool/Worker/native 线程,前台页面只订阅状态,避免页面销毁影响任务调度。
  5. 多台打印机同时任务时,最好做一个任务管理器,按设备维护连接、超时、重试和取消,不要每个页面各自维护长时任务。

如果打印属于高频核心场景,建议把“不带进度的打印长时任务模板”作为能力诉求反馈给官方,现有公开模板不一定能完全贴合。

有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html,

感谢提供解决方案,我把模板适配问题已经反馈给官方。

这三个问题可以直接合并回答:1)DATA_TRANSFER 触发的实况窗进度样式,公开能力下不能完全去掉,哪怕你不传确定进度,也常会显示系统的不确定态进度;2)MULTI_DEVICE_CONNECTION 那句“正在运行分布式任务”属于系统预定义文案,开发者不能自定义成“正在打印”;3)你的打印场景如果重点是“长连接不断”和“多设备并发”,其实更像设备连接场景,不像标准的数据传输进度场景。比较务实的做法是:用 MULTI_DEVICE_CONNECTION 保活连接,再自己发普通通知展示‘哪台打印机/当前状态’,把业务文案放到你自己的通知里,不要强行让系统长时任务文案承载业务语义。

你的场景其实比较典型:

APP
 ↓
发现打印机
 ↓
建立连接
 ↓
持续发送打印数据
 ↓
10分钟以上
 ↓
不能中断

但 HarmonyOS 长时任务目前主要是围绕:

  • 导航
  • 通话
  • 录音
  • 文件传输
  • 外卖
  • 打车
  • 运动

这些有明确进度或状态的场景设计的。

打印这种:

连接时长未知
进度未知
可能几十分钟
可能多个设备同时打印

其实和系统预设模型不太匹配。


问题1:实况窗进度条能否隐藏?

目前:

DATA_TRANSFER

对应的实况窗模板属于:

Progress Layout

即进度型布局。

系统会自动渲染:

[=====>     ]

这种进度UI。

即使:

progress = undefined

或者:

progress = 0

仍然会保留进度区域。

目前没有公开API支持:

隐藏进度条
改成纯文本状态
自定义布局

实况窗样式由系统统一管理,开发者只能填充数据,不能修改结构。

所以:

答案

不能隐藏

至少当前公开能力做不到。


问题2:“正在运行分布式任务” 能否修改?

你切换成:

MULTI_DEVICE_CONNECTION

后出现:

正在运行分布式任务

实际上是系统级文案。

类似:

正在导航
正在录音
正在通话

属于:

系统预定义任务类型

不是应用通知文案。

开发者无法修改。

否则大家都可以:

正在赚钱...
正在领红包...
正在发货...

系统任务类型就失去意义了。

所以:

答案

不能修改

这是系统固定文案。


问题3:打印业务推荐方案

这里反而建议不要把打印理解成:

DATA_TRANSFER

而应该理解成:

打印会话

方案一(推荐)

使用:

MULTI_DEVICE_CONNECTION

维持后台连接。

同时自己发:

notificationManager.publish(...)

普通通知。

例如:

正在打印
HP Smart Tank 790

已连接
已发送 128MB 数据
点击查看详情

这样:

  • 后台不会因为10分钟被杀
  • 通知内容完全可控
  • 多台打印机可显示多个通知

这是最符合打印场景的。


方案二

如果你其实是:

WiFi打印
蓝牙打印
IPP打印

本质属于设备连接。

那:

MULTI_DEVICE_CONNECTION

反而比:

DATA_TRANSFER

更符合系统设计意图。

因为系统关注的是:

持续保持设备连接

而不是:

传输了多少MB

方案三

如果打印机协议支持断点续传:

发送一段
结束任务
发送一段
结束任务

可以拆成多个短任务。

不过大部分打印机SDK做不到。

一般不推荐。


关于10分钟自动结束

你提到:

DATA_TRANSFER
10分钟后自动取消

这个行为实际上是 HarmonyOS 后台任务策略的一部分。

系统要求:

数据传输任务
必须持续更新状态

否则认为:

任务失活

从而回收。

因此:

打印这种未知进度长连接

天然不适合 DATA_TRANSFER。


我的建议

对于打印业务:

长时任务:
MULTI_DEVICE_CONNECTION

用户展示:
普通通知

通知内容:
打印机名称
连接状态
任务状态
页数统计(如果能获取)

不要依赖:

DATA_TRANSFER + 实况窗

因为:

  • 进度条无法隐藏
  • 样式不可定制
  • 10分钟限制明显
  • 多打印机场景体验差

这也是目前最符合 HarmonyOS 长时任务设计思路的实现方式。

  1. 参看《实况窗设计指南》。进度条属于扩展区,可选。
  2. 打印这个场景不适用这个长时任务类型。
  3. 长时任务+实况窗这个方案,就可以。用多线程管理下。 多线程大概框架:
import { common } from '@kit.AbilityKit';
import { taskpool } from '@kit.ArkTS';
import { Available, deviceInfo } from '@kit.BasicServicesKit';

// 必须用 @Concurrent ,才能被 TaskPool 调度
@Concurrent
async function doWork(context: common.UIAbilityContext): Promise<string> {
  return new Promise(async (resolve, reject) => {
    try {
      //TODO  处理业务事务
      //TODO resolve();

    } catch (e) {
      reject(e);
    }
  });
}

@Entry
@Component
struct Index {
  @State progressText: string = '准备开始';
  context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext;

  // 多个任务要处理, 可根据业务修改
  private tasks: string[] = [''];

  // 多线程批量
  async doTasks() {
    this.progressText = '多线程开始...';

    // 控制并发数量
    @Available({ minApiVersion: 'OpenHarmony 18' })
    let asyncRunner: taskpool.AsyncRunner = new taskpool.AsyncRunner(2);

    for (let i = 0; i < this.tasks.length; i++) {

      // 提交到 TaskPool 并发执行
      const task: taskpool.Task = new taskpool.Task(doWork,this.context);
      if (deviceInfo.sdkApiVersion >= 18) {
        asyncRunner.execute(task).catch(() => {
          // TODO: Implement error handling.
        });
      } else {
        // Fallback to an earlier version
        taskpool.execute(task).catch(() => {
          // TODO: Implement error handling.
        });
      }
    }
  }

  build() {
    Column() {
      Button('开始下载')
        .margin(20)
        .onClick(() => {
          this.doTasks();
        });

      Text(this.progressText)
        .fontSize(14)
        .margin(10)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

先回答你的第一个问题。不行的,当长时任务类型为DATA_TRANSFER时,系统在任务持续一段时间后(如接近10分钟限制)要求更新任务状态,此时会触发实况窗(Live Window)通知。实况窗默认会包含进度指示器,即使你不传递进度值,系统仍会显示一个不确定状态的进度条(例如循环动画)。目前没有直接的API参数可以完全隐藏该进度条UI。这是系统为保障用户体验和任务透明度所做的设计,开发者无法移除。

再说问题2,当长时任务通知内容“正在运行分布式任务”是否可以修改?这也不行的。当长时任务类型设置为MULTI_DEVICE_CONNECTION时,通知栏显示的文字(如“正在运行分布式任务”)是由系统预定义的,开发者无法通过公开API修改该固定文案。这种类型的通知内容与多设备协同场景强绑定,旨在向用户明确提示当前任务性质,因此不支持自定义。

至于问题3嘛,肯定替代方案还是有的,这里我给你一个思路吧。考虑使用TaskPool管理多个LongTask,或结合Service Ability与WorkScheduler实现灵活的后台调度。比如将每个打印任务封装为一个独立的LongTask,通过TaskPool管理。LongTask在后台运行时不强制要求显示系统通知,但需注意其生命周期受系统调度影响,可能不适合极端长时间运行。

import { taskpool } from '@kit.ArkTS';
@Concurrent
async function printTask(): Promise<void> {
  // 发送打印数据
}
// 创建并执行长时任务
let longTask = new taskpool.LongTask(printTask);
taskpool.execute(longTask);

长时任务开发指导 (TaskPool)-长时任务并发场景-应用多线程开发实践-ArkTS并发-ArkTS(方舟编程语言)-应用框架 - 华为HarmonyOS开发者

感谢提供解决方案,LongTask这个方案实现起来感觉更复杂,而且我现在要解决的就是超过10分钟以上的打印任务数据传输中断问题。

taskpool超过三分钟就嗝屁了,

可以。在HarmonyOS NEXT中,通过 NotificationRequest.setOngoing(true) 标识长时任务,并设置 NotificationContent 不包含 ProgressValue 字段(如仅文本或图标),即可不显示进度UI。

  • 问题1:实况窗(Live View)进度条无法隐藏。即使不传入进度值,系统会显示不确定进度条,这是实况窗的固定样式,不支持配置去除。
  • 问题2:MULTI_DEVICE_CONNECTION 类型的通知文字为系统预设,无法自定义修改。
  • 问题3:目前长时任务 DATA_TRANSFER 类型超过10分钟必须接入实况窗来保活,无法绕过进度条UI。若打印业务无法接受进度显示,可改用短时任务(5分钟内)分片传输,但需自行处理断点续传;或使用系统打印框架(Print API)将持续传输交给系统管理,但需评估是否满足自定义协议。
回到顶部