ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

【句匠|18】HarmonyOS ArkTS 权限与隐私实战:让 module.json5、功能说明和拒绝路径一致

2026/9/13 20:33:38 拓冰建站 浏览量
【句匠|18】HarmonyOS ArkTS 权限与隐私实战:让 module.json5、功能说明和拒绝路径一致 【句匠18】HarmonyOS ArkTS 权限与隐私实战让 module.json5、功能说明和拒绝路径一致证据边界本文当前事实来自本轮对工程清单、TTS 页面、本地存储和设置页的静态复核。尚未执行候选包构建、依赖制品扫描、网络抓包、真机权限回归或 AGC 后台回读这些项目均保持“待核验”不会写成已通过。HarmonyOS 应用的权限合规不是把module.json5中的权限数量降到零也不是写一份措辞宽泛的隐私政策。真正可审核的闭环是源码确实需要某项系统能力清单只声明必要权限用户能理解触发场景拒绝或能力失败时核心流程仍有可用路径设置页的数据说明与实际存储一致AGC 隐私标签和商店文案也不能超出真实行为。本文基于句匠项目本地句匠工程路径已脱敏的真实源码核对entry/src/main/module.json5、AppScope/app.json5、EntryAbility.ets、PracticePage.ets、SettingsPage.ets和librarya/src/main/ets/utils/UserDataManager.ets。本文唯一源码标识当前 Bundle Name已脱敏。真实边界如下入口模块只声明ohos.permission.INTERNET练习页使用hms.ai.textToSpeech优先创建离线引擎失败后再尝试在线引擎没有发现相机、麦克风、位置、联系人、日历等权限声明也没有发现对应运行时授权代码。收藏、笔记、错题、学习进度、考试记录和设置通过 Preferences 保存在本机。源码目录搜索未找到项目内隐私政策或用户协议文件但这不能证明 AGC 后台没有托管材料因此本文不会虚构线上隐私链接或审核状态。一、从“功能—能力—权限”三张表开始权限审计最容易犯的错误是只看清单不看业务调用。正确顺序应是用户功能 → 使用的 Kit / API / SDK → 是否需要声明权限 → 是否需要运行时授权 → 拒绝或失败时的产品路径 → 隐私说明与 AGC 标签句匠当前最值得审计的能力是听音题发音。它不是录音不读取麦克风而是把题目文本交给 TTS 引擎进行朗读。对应权限边界与“语音输入”完全不同。二、module.json5 只声明了 INTERNET真实清单为requestPermissions: [ { name: ohos.permission.INTERNET } ]模块支持deviceTypes: [ phone, tablet, 2in1 ]INTERNET是普通网络权限声明不像相机、麦克风或位置那样需要在页面中弹出运行时授权框。因此项目中没有requestPermissionsFromUser()不能据此判断“漏写了拒绝回调”应先确认所用权限类别。三、网络权限为什么存在PracticePage.ets导入import textToSpeech from hms.ai.textToSpeech创建引擎时先尝试离线模式this.ttsEngine await textToSpeech.createEngine({ language: zh-CN, person: 0, online: 0 })离线创建失败后源码再尝试this.ttsEngine await textToSpeech.createEngine({ language: zh-CN, person: 0, online: 1 })因此INTERNET与在线 TTS 兜底存在可复核关系。不能把应用描述成“完全离线且不使用网络”也不能因为大多数题库数据在本地就删除网络权限而不验证在线发音回退。四、网络权限不等于任意联网声明INTERNET只表示应用具备网络访问基础条件不代表可以模糊描述数据行为。审核仍要回答哪个功能会触发网络上传或传输的是什么内容是否包含用户输入或个人信息网络失败后会怎样是否使用第三方或平台 SDK隐私政策与 AGC SDK/数据标签是否一致。当前源码可证明的是在线 TTS 回退。项目没有在业务页面中发现通用 HTTP 客户端、Web 组件、登录、广告、分析、推送或云同步调用。文章不会把“没有搜索到”升级成绝对安全结论依赖包与最终制品仍需发布前扫描。五、TTS 失败时仍保留可用路径PracticePage的注释明确写着// 始终弹出发音弹窗确保即使无 TTS 也能完成听音题页面先显示发音内容再在后台尽力初始化和调用 TTS。即使离线、在线引擎都不可用用户仍能看到文本不会因为网络故障完全卡死练习流程。这是一种“能力降级”不是“权限拒绝”。INTERNET没有运行时拒绝弹窗但网络可能断开SDK可能初始化失败设备可能不支持当前引擎。产品需要对这些失败给出可继续的结果。六、TTS 生命周期也属于隐私与稳定性源码在页面离开时停止并关闭引擎if (this.ttsEngine) { this.ttsEngine.stop() this.ttsEngine.shutdown() } this.ttsEngine undefined及时释放能避免后台继续朗读、重复占用服务或离开页面后仍产生用户不可预期行为。对于任何媒体或智能服务生命周期透明都是权限与隐私体验的一部分。如果未来加入麦克风语音输入不能复用当前结论。届时需要新增麦克风权限、运行时授权、使用前说明、拒绝状态、设置跳转和隐私材料更新。七、项目当前没有敏感运行时权限对入口与公共源码扫描没有发现以下权限或调用链账号登录相机麦克风精确/模糊位置联系人日历通话记录文件广泛访问通知授权这意味着当前版本无需为这些能力编造授权弹窗或拒绝页面。权限最小化的关键是“功能不存在就不声明”而不是为了未来可能使用而提前申请。同时要避免反向推断源码未声明敏感权限不代表可以跳过隐私政策。应用仍会保存学习数据并使用在线 TTS 兜底这些行为都需要准确说明。八、本地保存了哪些数据UserDataManager.ets定义并持久化favoriteRecords 收藏记录 noteRecords 用户笔记 wrongRecords 错题记录 bankProgress 题库进度 chapterProgress 章节进度 examHistory 考试历史 dailyReminderTime 每日提醒时间 examDurationSec 考试时长 autoNextQuestion 自动下一题存储使用preferences.getPreferencesSync( context, { name: dialect_quiz } )然后通过putSync(JSON.stringify(value))和flushSync()写盘。源码未显示上传、账号绑定、云备份或跨设备同步。九、本地数据不等于“无隐私数据”笔记内容、学习记录、错题和考试历史可能反映用户的学习行为。即使只保存在设备本地也应在隐私说明中告知保存目的数据类型保存位置是否上传如何清除卸载后的结果是否提供备份/导出。不能因为没有服务器就写“本应用不处理任何数据”。更准确的描述是“为提供收藏、笔记、错题和进度功能在设备本地保存必要学习数据源码当前未实现账号上传与云同步”。十、设置页提供了数据可见性与清除入口SettingsPage把本地数据分为收藏记录 笔记记录 错题记录 学习进度 考试历史并提供“清除所有学习数据”。清除需要再次点击确认Text( this.pendingClear ? 再次点击确认清除所有学习数据 : 清除所有学习数据 )这使破坏性操作有明确后果和二次确认。设置页还展示页面采用 ArkTS 与 ArkUI 构建数据保存在本机。这句话与当前 Preferences 实现一致但在线 TTS 兜底仍应在隐私政策或功能说明中单独说明不能让“数据保存在本机”被理解为整个应用绝不联网。十一、清除数据的真实边界“清除所有学习数据”应回写所有相关 Preferences 键并同步刷新AppStorage。前一篇对源码的核对已发现清除过程由多次独立写入组成不是事务。因此合规文案可以说“提供清除入口”但不应声称具备原子事务、不可恢复擦除、加密销毁或系统级安全删除。若中途异常多个键理论上可能处于部分清除状态。发布验证至少要检查清除前能看到记录数量第一次点击只进入确认态第二次点击后各列表和首页统计同步归零重启应用后数据不再恢复清除不影响内置题库与基础设置页面。十二、Preferences 的异常处理需要更透明persist()当前写法try { UserDataManager.prefs.putSync( key, JSON.stringify(value) ) UserDataManager.prefs.flushSync() } catch (_) {}异常被静默吞掉。页面可能已经更新内存状态但磁盘写入失败用户没有任何提示。对隐私和数据权利而言“点击清除”却未真正落盘是需要避免的状态。建议后续让持久化返回明确结果type SaveResult { ok: boolean errorMessage?: string }清除失败时保留确认状态并提示重试。这是改进建议不是当前实现。十三、权限拒绝路径应该按权限类型设计当前只有INTERNET没有系统运行时拒绝对话框所以拒绝路径主要表现为网络/TTS 不可用。如果未来增加敏感权限标准状态机可以是未询问 → 功能触发前解释用途 → 系统授权 → 已授权 / 已拒绝 → 拒绝后提供不依赖权限的路径 → 用户主动操作时再引导设置不得在启动时批量申请与当前操作无关的权限也不得在用户拒绝后循环弹窗。权限说明必须贴近真实功能触发点。十四、module.json5、功能说明与代码必须一一对应建议建立审计表清单项真实调用用户场景失败路径材料INTERNET在线 TTS 回退听音题发音弹窗仍显示文本隐私政策、SDK说明Preferences本地学习数据收藏/笔记/进度写入失败应提示数据说明、清除入口phone/tablet/2in1ArkUI 多端布局多设备使用小窗保持可用商店设备范围如果某项权限找不到真实调用应删除或补充证据如果代码新增敏感能力但清单没有声明应停止发布。表格的价值是让代码、manifest、产品与 AGC 不再各说各话。十五、第三方/平台 SDK 也要进入清单hms.ai.textToSpeech是审核材料中需要关注的能力来源。即使它由平台提供也要确认SDK用途在线/离线模式网络行为输入数据范围服务条款与隐私披露版本和实际依赖。不能只扫描http.createHttp()就断言“没有网络”。网络可能由 SDK 内部发起最终应结合官方文档、依赖清单、制品扫描和实际抓包验证。十六、源码里没有隐私文件意味着什么在本次限定源码搜索中没有找到以 privacy、隐私、agreement、用户协议命名的项目文件。这只能说明隐私材料不在当前源码目录中。可能的真实情况还包括AGC 托管隐私政策外部网站链接发布材料目录未包含在工程当前版本确实缺少材料。在没有登录 AGC 并回读公开链接前文章不能选择其中任何一种作为事实。队列也不能填入虚构 URL。十七、隐私政策至少要覆盖哪些事实基于当前源码可以准备待核验的事实清单应用名称与运营主体 本地保存的学习数据类型 保存目的与清除方式 在线 TTS 的触发条件 使用的 SDK/平台服务 是否存在账号、云同步、广告、分析、推送 权限名称与用途 用户权利与联系方式 政策生效和更新时间其中运营主体、联系方式、公开链接等不能由源码推断必须使用真实材料。PV、用户量、审核结果同样不得编造。十八、AGC 字段要与包内事实一致发布前需要对照bundleName: 当前 Bundle Name已脱敏 versionName: 1.0.0 versionCode: 10000000 权限: INTERNET 设备: phone / tablet / 2in1 网络能力: 在线 TTS 兜底 本地数据: 收藏、笔记、错题、进度、考试记录、设置如果 AGC 将应用标成“完全离线”就与在线 TTS 回退不一致如果隐私标签声称收集位置、联系人而包内没有对应功能也会造成不必要的审核风险。十九、发布前的最小验证矩阵场景预期首次启动不出现无关敏感权限弹窗无网络进入听音题发音弹窗可打开文本可见页面不崩溃在线 TTS 可用用户主动触发后正常朗读TTS 初始化失败核心答题流程仍可继续保存收藏/笔记页面更新重启后恢复清除全部数据二次确认页面归零重启不恢复卸载重装按系统行为重新开始不虚构云恢复依赖与制品扫描权限、SDK和网络行为与清单一致如果没有执行这些验证只能说“源码设计了降级/清除路径”不能说“真机验证已通过”。二十、把“声明权限”与“实际数据行为”分开取证module.json5能证明应用声明了什么权限却不能独立证明 SDK 实际发送了哪些字段、请求发往哪里、服务端保留多久。源码中的 TTS 创建参数可以证明页面设计了离线优先和在线回退但在线模式的传输内容、处理位置与留存规则需要官方服务说明、依赖版本和运行证据共同确认。文章与隐私政策都应保留这条边界。更稳的证据表包含四列声明证据、调用证据、运行证据、平台材料。声明证据来自清单调用证据来自明确的 Kit 或 API运行证据来自候选包抓包、系统权限页和失败场景平台材料来自保存后的 AGC 页面与公开政策。缺少任何一列时只能描述已经确认的范围。问题当前可证明仍待核验为什么需要网络在线 TTS 回退代码存在候选包是否还含其他网络行为是否上传学习记录业务源码使用本地 Preferences依赖与制品扫描、运行抓包AGC 如何披露可整理待填事实后台已保存字段与公开链接二十一、普通权限与敏感权限需要不同的失败路径INTERNET不走页面运行时授权因此没有系统拒绝按钮。对应测试应模拟断网、域名不可达、SDK 初始化失败和服务超时确认文本仍可见、答题仍可继续、页面不会循环重试。若未来加入麦克风、相机或位置则必须在用户触发功能时解释用途并覆盖首次拒绝、再次拒绝、永久拒绝和从设置返回。失败路径的目标不是强迫用户授权而是保持核心任务可理解、可退出。对于听音题语音不可用时展示题目文本属于能力降级对于必须依赖权限的拍摄功能则应停在明确空状态提供返回或打开设置入口。两类路径不能混用更不能把普通网络故障描述成用户拒绝权限。二十二、清除入口必须与数据分类逐项对账设置页展示“清除所有学习数据”时用户会自然理解为学习记录被移除但不一定期待提醒时间、考试时长等偏好恢复默认。产品说明应列出实际清除的六类记录并明确三项偏好继续保留。这样既符合源码也能避免“所有数据”造成过度承诺。清除范围收藏、笔记、错题、题库进度、章节进度、考试历史 保留设置每日提醒时间、考试时长、自动下一题 验证方法清除前快照 → 二次确认 → 页面回读 → 重启回读由于六类记录通过多次写入完成测试还要注入中途失败。若前三类已经清除而后三类仍保留页面不能只显示统一成功提示。改进方向是让服务返回每个键的结果或者在全部写入完成后重新读取并比较目标状态。二十三、隐私政策中的每句话都应能追到工程事实“数据保存在本机”需要对应 Preferences 或文件路径“不需要账号”需要对应没有登录入口与账号 SDK“可清除”需要对应可达的设置入口和重启回读“语音服务可能联网”需要对应在线 TTS 触发条件。运营主体、联系方式、生效日期和公开链接则必须来自真实发布材料不能由源码推断。写作时避免绝对句。例如“绝不联网”与在线回退冲突“不处理任何数据”与笔记、错题和考试历史冲突“删除后不可恢复”又缺少安全擦除证据。更准确的表述是说明目的、位置、触发条件与用户操作并把未确认的 SDK 行为交给正式材料核验。二十四、上线前用候选包完成四组一致性回归第一组检查工程清单与安装后的系统权限页第二组在有网、断网和语音服务不可用环境下验证听音题第三组新增、重启、清除并再次重启核对本地数据第四组解析候选包依赖和网络行为再与 AGC 标签、商店说明、隐私政策逐项比较。任何不一致都应阻止提交。状态含义允许的结论passed候选包已执行且证据一致写明设备、版本与结果failed已执行并发现不一致记录问题和修复计划not run未执行或环境不足只描述源码设计不宣称通过本轮文章核对属于静态证据整理因此构建、抓包、设备和 AGC 状态仍是not run。把它们清楚写出比用模糊的“已符合隐私要求”更能帮助后续发布人员避免误判。二十五、变更权限或 SDK 时重新走完整闭环权限与隐私不是一次性文档。新增账号、云同步、反馈上传、广告、分析、推送、麦克风或文件访问后都要重新核对清单、运行时说明、拒绝路径、数据分类、第三方清单、隐私政策和 AGC 标签。即使权限名称没有变化SDK 从离线实现切换为在线实现也可能改变数据行为。建议在代码评审中增加固定检查项新增依赖是否联网新增字段是否包含个人或学习数据失败时是否保留核心路径清除入口是否覆盖新数据隐私材料是否同步更新候选包是否重新完成断网与权限回归。把这些问题放在合并前比发布前临时补文案更可靠。二十六、结语让权限、功能和材料共享同一份事实句匠当前可确认的权限面较小入口模块声明网络权限练习页为 TTS 设计离线优先与在线回退学习记录和设置保存在本地。设置页提供二次确认的学习数据清除入口但真实清除范围是六类学习记录三项偏好继续保留。仍需通过候选包验证的部分包括依赖网络行为、在线 TTS 数据边界、异常写盘反馈、真机断网表现和 AGC 已保存材料。可靠合规不是用一句“完全离线”概括而是让工程声明、服务行为、页面体验与平台材料能够相互核对。AI 辅助声明本文在人工核对工程清单、TTS、本地存储和设置页后使用 AI 辅助整理结构、润色表达并生成三张示意图。未执行的构建、抓包、设备和 AGC 回读均未描述为已完成。CSDN-SERIES:ALL-163176399