HarmonyOS 6.1.1 Notification:施工区域提醒没听到时, 沙箱铃声该怎样提示下一步
施工区域 C-088 出现越界提醒时,值守人员最容易把“没有听到声音”理解为“施工人员没有收到通知”。这两个判断之间隔着不少状态:提醒声音可能还没有写入应用沙箱,声音 URI 可能没有通过校验,通知权限可能未开启,publish 也可能尚未被调用。即使 publish 的 Promise 已经返回,通知中心是否可见、真机上是否真的听见声音,也仍需要分开观察。
本页把声音资源、通知权限、发布请求、系统到达、真机听觉和人工处置放在同一条状态链里。它的目的不是替现场确认“越界事实”或“人员已经处置”,而是让值守人员知道:当前缺的是哪一层,下一步该检查什么,哪些信息可以留给人工接手。
一、没听到提醒时,先别把所有问题叫成“通知失败”
1.1 用户没有听到声音,至少可能是三种不同状态
在施工提醒场景中,“没有听到”只是用户的观察,不是原因。页面需要先把它拆成三个可行动的问题:
- 声音文件尚不可用:页面还没有把原始 WAV 写入 EL1 沙箱,或没有得到合规的
uri::声音值。这时不能进入通知发布。 - 通知请求尚未完成:可能是系统通知权限未开启、发布前条件不满足,或调用
publish时返回错误。这时页面不能把声音问题归给设备音量。 - 发布后尚未观察到声音:
publish已返回时,才可以进入“通知中心是否可见”和“真机是否听见”两项人工核验;两者仍然不是同一件事。
这三个问题对应不同的下一步。若用户只看到一个笼统的红色“提醒失败”,就会不断重选文件,或者反复点击发布,却不知道自己卡在文件、权限还是设备观察阶段。对产品来说,真正要降低的是这种无目标重试的认知成本。

场景解说:本图待展示施工提醒页面初始的声音资源、权限、发布、通知到达与真机听觉状态。它能证明页面尚在等待操作,不能证明施工区域已经越界或任何通知已送达。
1.2 施工边界参考点不是本篇的通知结论
页面左侧会显示施工区域 C-088 的 Map Kit 参考点和“越界阈值 150m”文案。这个地图区域帮助用户理解当前提醒属于哪一个现场场景,但它不是通知到达、声音播放或人员位置的证据。
当前页面也明确区分了地图控制器是否就绪、参考 Marker 是否添加成功。即使地图区域显示正常,也不能由此推导通知权限已开、声音资源可用或设备会播放铃声;反过来,声音资源准备完成也不能确认人员真实越界。把地图参考与通知状态并排展示,是为了让用户不丢失场景,而不是把两个证据层合并成“施工风险已闭环”。
当地图初始化失败或参考点添加失败时,值守人员可以记录当前页面错误并按现场流程继续人工处置,但不应把这类地图状态写入通知发布结论。本文只处理 Notification 的沙箱声音配置和后续观察链,越界距离与现场位置仍需由独立的巡检记录核验。
1.3 页面应先回答“现在能做什么”,再让用户点击
初始状态下,用户最需要的不是一段 NotificationKit 介绍,而是一条清楚的操作顺序:先准备短音,再核对授权并发布,最后分别观察通知与声音。工程将两个主要操作做成“1. 准备沙箱短音”和“2. 发布越界提醒”,并在它们下方保留“记录系统到达”“确认真机听见”“记录人工处置”三个不同入口。
这样的顺序减少了两个误解:第一,文件“已选择”不等于已经能够作为 NotificationRequest.sound 使用;第二,点击发布不等于系统通知已到达或声音已被听见。用户在每一步都应读取页面当前的状态文本,而不是只凭按钮点击过一次来判断完成度。
二、沙箱铃声准备完成,到底能说明什么
2.1 页面复制的是声音文件,不是“声音已经播放”
施工提醒的短音来自工程 rawfile 中的 article11_notice.wav。点击准备后,页面先切到 EL1 区域,在应用 filesDir 下创建目标文件,再把原始字节写入 article88_construction_notice.wav。写入后还会比较源文件字节数、实际写入字节数和目标文件大小。
const targetPath = `${applicationContext.filesDir}/${this.sandboxFileName}`;
const sourceBytes = await getContext(this).resourceManager.getRawFileContent(this.rawFileName);
const targetFile = fileIo.openSync(targetPath,
fileIo.OpenMode.WRITE_ONLY | fileIo.OpenMode.CREATE | fileIo.OpenMode.TRUNC);
const bytesWritten = fileIo.writeSync(targetFile.fd, sourceBytes.buffer as ArrayBuffer);
const targetStat = await fileIo.stat(targetPath);
if (bytesWritten !== sourceBytes.byteLength || targetStat.size !== sourceBytes.byteLength) {
throw new Error('写入核对失败');
}
这段代码能证明页面尝试把工程内的原始短音写到应用 EL1 沙箱,并以字节数与目标大小核对本次写入。它不能证明系统通知已经引用这个文件,更不能证明任何设备扬声器已经播放声音。
对值守人员而言,页面显示“正在写入 EL1 沙箱 WAV 并生成 URI”时,最合理的动作是等待资源状态结束;显示“沙箱短音已准备,URI 校验通过”时,才可以进入发布条件检查。若页面显示“资源准备失败,未调用 publish”,应先保留错误文本,不要把失败动作包装为“已通知但未听见”。

场景解说:本图待展示“准备沙箱短音”入口及资源准备中的状态文案。它能证明用户正在发起本地文件准备,不能证明通知请求已经发送。
2.2 字节数相同,是文件写入事实,不是铃声效果结论
页面同时显示源文件大小和目标文件大小。这个对照能让用户发现“原始资源读到了,但目标文件没有完整写入”这类本地问题,也能避免把空路径直接带进后面的发布步骤。
不过,两个大小相同支持的结论非常有限:它只说明这一次页面拿到的字节数与目标文件大小相符。它不说明文件的内容一定适合当前系统策略,不说明通知服务已经接受了声音 URI,也不说明用户设备处于可听见的音量、焦点或勿扰状态。
因此,页面文案不应在此阶段写“铃声设置成功”。更准确的是“声音文件已准备,待核对通知权限和发布请求”。这种文案既承认用户已完成的一步,也把尚未发生的步骤留在界面上,避免用户提前离开页面。
2.3 uri:: 是发布前门槛,不是一个可以隐藏的实现细节
文件准备完成后,工程通过 fileUri.getUriFromPath() 取得文件 URI,再组装 uri::${convertedFileUri} 作为声音值。页面会检查该值以 uri:: 开头,并拒绝包含 ../ 或 /.. 的路径形式:
const convertedFileUri = fileUri.getUriFromPath(targetPath);
const sound = `uri::${convertedFileUri}`;
if (!this.isValidSound(sound)) throw new Error(`sound URI 不合规:${sound}`);
this.fileUriValue = convertedFileUri;
this.soundValue = sound;
this.resourceState = 'ready';
这段代码能证明页面在本地构造并检查通知请求要使用的声音 URI,且只在检查通过后把资源状态写为 ready。它不能证明 URI 已经被通知框架消费,也不能保证系统会以用户预期的音量或设备输出方式播放。
从产品视角看,uri:: 不必被写成一串让用户背诵的技术字符,但页面需要把它的结果翻译为可判断的状态:例如“声音路径已生成,等待发布条件”或“声音路径不合规,未调用发布”。这样用户知道自己遇到的是配置门槛,而不会去记录一条不存在的“未到达通知”。

场景解说:本图待展示源/目标文件大小、EL1 沙箱路径、fileUri 与
uri::声音值的准备结果。它能证明页面完成了本地配置检查,不能证明设备已经播放铃声。
2.4 文件准备失败时,页面应把“未发布”说完整
工程在资源准备失败时,会把资源状态设为 failed,并把发布状态标为失败,同时显示“资源准备失败,未调用 publish”。这比“声音异常”更适合现场判断,因为它告诉用户:本次没有任何已经交给通知服务的请求,因此无需去通知中心寻找不存在的提醒。
用户可按以下顺序处理:先记录错误文本与当前触发时间;确认原始资源是否可用、沙箱写入是否完成;再重新准备一次。若现场任务不能等待文件问题解决,可使用“记录人工处置”保留当前人工动作,但文案仍需明确该记录不代表通知或声音已到达。
这里的人工出口不是为了掩盖失败,而是为了保留任务连续性。它接住的是“本次页面没能走到发布”的事实,不替页面虚构一条消息已经发给施工人员的结果。
三、通知发布前,用户还要跨过哪两道门
3.1 资源已就绪,不等于页面有资格调用 publish
点击“发布越界提醒”后,工程会先检查资源是否为 ready,并再次检查声音值是否合规。任何一项不满足时,页面停止在“资源未就绪,未调用 publish”,同时给出“请先完成 EL1 声音写入和 uri:: sound 校验”的错误提示。
if (this.resourceState !== 'ready' || !this.isValidSound(this.soundValue)) {
this.publishState = 'failed';
this.statusMessage = '资源未就绪,未调用 publish';
this.errorMessage = '请先完成 EL1 声音写入和 uri:: sound 校验';
return;
}
这段代码能证明发布动作不会跳过声音资源门槛。它不能证明资源 ready 后系统通知权限一定已经开放,也不能证明越界提醒已经被发布。
页面把“未调用 publish”写出来的意义在于减少误报:用户不需要猜测失败发生在本地配置还是系统服务。只要当前状态仍是未调用,下一步就应该留在文件准备,而不是切换到通知中心或询问施工人员是否听见。
3.2 通知权限是一项独立条件,不能被文件状态染绿
声音资源通过校验后,页面还会调用 notificationManager.isNotificationEnabled()。若当前未开启,再请求用户启用并重新核对结果;若最终仍未启用,页面将权限标为 denied,并写明“通知权限未启用,未调用 publish”。
if (await notificationManager.isNotificationEnabled()) {
this.permissionState = 'granted';
return true;
}
await notificationManager.requestEnableNotification(context);
const enabled = await notificationManager.isNotificationEnabled();
this.permissionState = enabled ? 'granted' : 'denied';
这段代码能证明页面把系统通知开关单独检查,并以最终核对结果决定是否继续发布。它不能证明权限为 granted 后通知一定会出现在通知中心,也不能证明自定义声音一定被设备听见。
产品文案上要避免把“允许通知”写成“提醒已送达”。前者描述的是系统授权条件,后者需要发布返回与后续人工观察。用户看到权限未开启时,可以主动打开授权或交由设备管理员处理;用户看到权限已开启时,才进入真正的发布请求,而不是直接勾选“已提醒现场”。

场景解说:本图待展示资源已就绪后发起发布、核对通知权限的页面状态。它能证明页面正在检查发布前条件,不能证明通知中心已经出现提醒。
3.3 等待中的状态也要有边界,避免重复发出同一提醒
工程把发布过程区分为 idle、publishing、published 和 failed。当状态已是 publishing 时,再次点击不会重新发起一轮相同请求。页面还会记录一次触发时间和请求标识,帮助用户知道当前屏幕上的状态属于哪一次操作。
这对施工提醒尤其有价值:用户等待权限弹窗或发布 Promise 返回时,最容易因界面没有立即响声而连续点击。如果页面没有显示“正在发布越界提醒”以及本次请求标识,重复点击可能让用户失去对“哪一条通知正在被观察”的判断。当前请求标识能支持页面内回看,但不等于后台业务单号,也不等于通知中心已经显示。
在等待状态下,用户应做的是看权限与发布状态是否变化;不要先记录系统到达,也不要先确认真机听见。若等待最终转为失败,保存错误文本后走人工处置;若转为 published,再开始分层观察通知到达和声音效果。
四、publish 返回后,为什么页面仍不能说“提醒已到达”
4.1 发布请求返回,说明的是服务接受请求这一层
满足资源和权限条件后,工程构造包含标题、文本和声音值的 NotificationRequest,然后调用 notificationManager.publish(request)。Promise 正常返回后,页面显示“publish Promise 已返回,系统到达和声音待分别核验”。
const request: notificationManager.NotificationRequest = {
id: this.notificationId,
content: {
contentType: notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: {
title: '施工区域越界提醒',
text: '施工区域 C-088,已越界 150m,请确认现场位置'
}
},
sound: this.soundValue
};
await notificationManager.publish(request);
this.publishState = 'published';
这段代码能证明页面已带着当前声音值调用发布接口,且 Promise 在本次运行中正常返回。它不能证明系统通知中心已经展示内容,不能证明设备实际播放短音,也不能证明施工人员看见或处理了提醒。
这个区别应直接写在成功文案中。若只显示“发布成功”,值守人员很容易把页面的技术返回理解成现场人员已被触达。对账号7的读者来说,更有用的结果是:“发布请求已返回,接下来请分别观察通知中心和真机声音。”
4.2 “记录系统到达”需要用户看见系统层的事实
页面提供“记录系统到达”按钮,但它只在发布状态为 published 后才允许形成到达记录。点击后,页面将到达状态改为 observed,并记录当前观察时间。这个动作的含义是操作人员已经在系统通知中心观察到提醒;不是页面凭借发布返回自动把到达状态染绿。
如果发布尚未成功,点击该按钮会保留错误“尚无成功发布请求,不能记录系统到达”。这类阻止文案很关键:它让用户知道自己缺的是先前的发布条件,而不是让一个“到达”按钮成为可以任意补填的结果。
即使到达状态已经记录,也只支持“操作人员观察到通知中心存在提醒”的结论。它不支持“施工人员本人已看到”,也不支持“自定义声音已经播放”。这些仍要分别核对,不能用一个观察按钮替两项事实盖章。
4.3 “确认真机听见”必须保留为人工感知,不伪装成程序回执
自定义铃声是否实际可听,受设备、系统策略、输出通道和现场环境影响。工程不会因为 publish 返回就把听觉状态设为已确认;它初始为 pending_device,由真机操作人员在发布成功后手动点击“确认真机听见”才会变为 confirmed。
这意味着用户在模拟器中看见资源准备、权限核对与发布返回时,不应写“铃声已播放”。模拟器页面可以帮助核对配置和反馈,但它不能替真机听觉做证。若暂时没有支持设备或现场太嘈杂,最准确的状态应是“待真机核验”,而不是“失败”或“已听见”。

场景解说:本图待展示
publish已返回后,系统到达与真机听觉仍分别待核验的状态。它能证明页面没有把发布结果扩大为到达或听觉结论,不能证明任何人员已经收到提醒。
4.4 四个绿灯并不互相替代
用户在页面上可能会看到“声音资源 ready”“权限 granted”“发布 published”“系统到达 observed”几种正向状态。它们不应合并成一条“提醒已闭环”:
| 页面状态 | 支持的判断 | 仍不能推出的判断 |
|---|---|---|
声音资源 ready |
本地沙箱文件与 URI 检查通过 | 通知已发布、声音已播放 |
权限 granted |
当前通知开关允许继续尝试发布 | 通知中心已出现提醒 |
发布 published |
本次 publish Promise 已返回 |
系统到达、真机听觉、人员处理 |
到达 observed |
操作人员记录看见了通知中心提醒 | 施工人员已阅读、声音已被听见 |
听觉 confirmed |
真机操作人员人工确认听到声音 | 越界事实已核实、现场处置已完成 |
这个表格不是为了增加操作步骤,而是为了让用户不必靠猜测把状态串起来。对现场来说,真正重要的是知道哪一项已经有证据、哪一项还待人工核验;任何尚缺的层都应继续显示在页面上,而不是被“完成”标签遮住。
五、没有观察到提醒时,如何让任务继续而不伪造结果
5.1 先记录当前缺口,不要反复选择同一个文件
没有听见声音时,先看状态链停在哪一层:资源准备失败就检查文件和 URI;权限拒绝就处理系统授权;发布失败就记录错误文本;发布已返回但未观察到通知中心或声音,就保留“待观察”而不是回到文件选择。
尤其是发布已返回之后,反复重新准备声音文件并不能说明第一次请求哪里出了问题。页面已经把“声音资源”“权限 / 发布”“系统到达”“真机听觉”分开显示,用户应优先依据这几行状态决定下一步。这样既减少无效重复操作,也避免多个触发时间和请求标识互相覆盖,导致后续人工核验不知道在核对哪一次提醒。
5.2 人工处置记录承接的是任务,不是通知结果
当资源、权限或发布任一环节失败时,现场仍可能需要继续处理施工风险。页面允许点击“记录人工处置”,并写入人工记录时间,但状态文案明确为“人工处置已记录;不代表系统通知或声音已到达”。
这种设计保留了值守人员已经采取行动的事实,同时不会把人工电话、现场确认或纸面登记伪装成 Notification 的送达回执。后续接手人员至少能分清两件事:一是系统通知链在什么状态停住,二是现场有没有另外启动人工处置。两者都很重要,但不能相互替代。

场景解说:本图待展示发布失败或待观察时的错误信息、触发时间、请求标识和人工处置记录。它能证明页面保留了当前处置状态,不能证明人工处置已经完成现场风险核验。
5.3 一条适合交接的状态摘要,应包含四层信息
当值守班次交接时,不建议只留“通知没响”这种结论。更可核对的摘要应依次说明:
- 文件层:EL1 沙箱声音是否已准备,是否完成源/目标大小与 URI 校验。
- 发布层:通知权限处于什么状态,本次是否真的进入
publish,请求是在返回还是失败。 - 观察层:通知中心是否由操作人员观察到,真机声音是否已由人工确认,未观察到时缺什么条件。
- 人工层:是否已记录人工处置;它承接的是什么行动,不能替代哪一项系统证据。
例如可以写:“本页已完成 EL1 声音文件与 URI 校验,通知权限已核对;本次 publish 返回后,通知中心到达待观察、真机声音待设备核验;现场人工处置已另行记录,未据此认定系统通知已送达。”这段摘要不会制造后台事实,但能让下一位值守人员立刻知道该从哪个状态继续。
5.4 施工越界与通知链应在交接中保持两条线
本页通知正文使用“施工区域 C-088,已越界 150m,请确认现场位置”作为提醒文本,但页面自身的地图参考点和本地通知状态不能证明真实人员位置或越界事实。交接时应把“现场越界待巡检记录确认”和“通知链当前处于发布/观察/人工处置哪个状态”分别写出。
这样做不是弱化提醒,而是避免产品状态误导现场判断:一条成功发布的通知,不会把参考 Marker 自动升级为真实越界;一次人工处置,也不能自动让系统到达状态变成已观察。把两条线分开,用户才能在紧急情况下既不丢失现场任务,也不夸大页面能证明的结果。
必要条件|运行门禁
G1:SDK/API门禁
确认 HarmonyOS 6.1.1 API 24 已安装,Hvigor 能构建 entry 模块。


G2:Kit门禁
确认本文页面的 Kit import 可解析,并使用 API 24 支持的接口。
G3:模块/页面门禁
确认 Stage 模块、页面路由、设备类型和相关模块配置完整。
G4:权限门禁
确认静态声明存在;Camera/AI字幕等运行时能力在真正调用前完成动态授权。

G5:系统能力门禁
确认目标设备声明并实际提供所需摄像头、麦克风、地图、视觉或文件能力。任一门禁未通过,停止进入核心操作。

MapKit文章在 G5 放行前增加服务配置门禁:AppGallery Connect 中已选择正确项目,应用包名和签名证书与工程一致,MapKit 服务已开通且应用服务凭据/授权配置已完成。不得在文章或源码中暴露服务密钥。



更多推荐


所有评论(0)