资讯详情

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

📅 2026/10/27 9:59:51 | 华诺云谱 👁 阅读
【笔下生辉|18】HarmonyOS ArkTS 权限与隐私实战:让 module.json5、功能说明和拒绝路径一致
做 HarmonyOS 5.0 应用上架时权限与隐私最容易出现的风险并不是某一处代码写错而是几个材料之间互相说不清module.json5里声明了一组权限页面功能却没有对应入口源码里没有联网介绍文案却写成在线服务本地只保存学习记录隐私说明却含糊写成可能上传运行时没有任何权限申请测试报告却还在描述拒绝授权后的降级流程。审核和真实用户都不会只看一个文件最终要看的是声明、功能、数据、拒绝路径是否一致。本文复核的是「笔下生辉」真实源码包名标记为com.jiaweikang.one17。当前源码的权限边界非常明确entry/src/main/module.json5没有requestPermissions也没有ohos.permission.INTERNET入口EntryAbility只做窗口、安全区、浅色模式、断点系统和本地数据初始化HomePage、Index等页面使用本地题库、router和AppStorage完成应用内部流程UserDataManager通过 Preferences 保存收藏、笔记、错题、进度、考试历史和偏好设置。也就是说本篇讨论的是一个离线题库类 ArkTS 应用如何把“不申请权限”这件事讲清楚而不是假装源码里已经有账号、云同步、推送、拍照或定位能力。1. 先定边界权限不是越少越好而是必须和功能一致很多项目会把“无权限”当成一句宣传语但工程上真正需要证明的是应用没有声明权限、没有运行时请求、没有隐藏网络入口、没有把本地数据上传也没有把用户引导到需要敏感能力的流程里。只有这些同时成立“无权限”才是可复核的结论。「笔下生辉」当前的源码边界可以拆成四层核验层真实文件复核结论权限声明entry/src/main/module.json5未声明requestPermissions未声明ohos.permission.INTERNET入口能力EntryAbility.ets初始化本地数据、断点、安全区和窗口不触发权限请求页面功能Index.ets、HomePage.ets本地页面切换、本地题库入口、学习统计和导航数据存储UserDataManager.ets通过 Preferences 保存本地学习数据和偏好这四层是一条链。只要其中一环改变隐私材料和发布材料就要跟着改变。例如未来新增拍照识别错题那么module.json5需要声明相机权限页面需要解释相机用途运行时需要处理允许、拒绝和再次说明隐私政策也要说明图像是否只本地处理。如果未来新增云同步即使没有使用敏感权限也要重新检查网络权限、账号体系、服务器位置、数据上传字段、注销和清除路径。当前源码没有这些能力所以文章不能为了显得完整而编造“授权弹窗”“云端同步”“服务端加密”“拒绝后只读模式”。这类段落看起来像隐私合规实际会制造更大的不一致。2. module.json5不声明 requestPermissions就是第一条可验证证据先看entry/src/main/module.json5。这个文件是 HarmonyOS 模块能力的公开边界审核和发布材料都会围绕它确认应用实际请求了什么能力。当前模块声明了应用入口、设备类型、Ability、图标和启动窗口资源但没有requestPermissions字段。核心结构可以概括为{ module: { type: entry, deviceTypes: [phone, tablet, 2in1], mainElement: EntryAbility, abilities: [ { name: EntryAbility, exported: true, skills: [ { entities: [entity.system.home], actions: [action.system.home] } ] } ] } }这段声明传递出几个信息。第一应用面向phone、tablet、2in1权限和隐私说明要覆盖多设备体验但并没有因为多设备就自动产生跨设备同步能力。多设备适配只说明 UI 和包能力支持这些终端不等价于数据跨端流转。第二当前只有一个主入口EntryAbility公开给系统启动。没有额外的后台服务、卡片服务、分享服务、文件服务或其他需要额外权限说明的 Ability。后续如果新增服务型 Ability必须重新核对是否引入后台行为、外部唤起、跨应用调用或系统能力使用。第三没有requestPermissions是一个明确结论不是“忘记写权限”。只有当源码功能确实需要敏感能力时才应该添加权限。离线题库、收藏、错题、笔记、学习进度和本地设置不需要网络、定位、相机、麦克风、通讯录、日历或文件读取权限。当前不声明权限反而是和功能匹配的做法。这里还有一个容易误判的细节源码的题库内容里可能出现“网络热词”等业务分类文字但这不是ohos.permission.INTERNET。权限复核不能只按关键词搜索INTERNET就下结论需要看命名空间、文件位置和代码语义。出现在题目分类里的“网络”是学习内容不是应用能力。3. EntryAbility入口初始化不等于权限申请权限隐私复核的第二步是看入口是否在启动时偷偷申请系统能力。EntryAbility.ets的职责比较集中设置应用浅色模式、初始化本地数据管理器、设置几个AppStorage默认值、注册断点系统、创建窗口、记录状态栏和导航栏安全区。可以把启动过程压缩成下面的伪代码onCreate(want, launchParam) { this.context.getApplicationContext().setColorMode(COLOR_MODE_LIGHT) UserDataManager.init(this.context) AppStorage.setOrCreate(currentTabIndex, 0) AppStorage.setOrCreate(favoriteTabIndex, 0) AppStorage.setOrCreate(topAvoidAreaHeightPx, 0) AppStorage.setOrCreate(navigationIndicatorHeightPx, 0) BreakpointSystem.register() } onWindowStageCreate(windowStage) { const mainWindow await windowStage.getMainWindow() mainWindow.setWindowLayoutFullScreen(true) updateAvoidArea(mainWindow) windowStage.loadContent(pages/SplashPage) }这里没有权限申请 API也没有网络初始化、账号初始化、推送注册、广告 SDK、分析 SDK 或 Web 容器启动。UserDataManager.init(this.context)使用的是应用上下文来打开 Preferences本质是本地轻量存储不是对外传输数据。BreakpointSystem.register()是布局断点系统服务于不同屏幕宽度下的页面适配。安全区监听用于避免状态栏和底部导航遮挡内容也不涉及用户隐私。这类入口代码有两个合规价值。一是它能证明应用启动不依赖敏感授权。用户第一次打开应用时不会被相机、定位、通知、文件、通讯录等弹窗打断。对于离线学习工具这符合最小权限原则也降低了审核中“权限用途不明确”的风险。二是它能证明拒绝路径当前不是必需项。因为没有运行时权限申请就不存在“用户拒绝权限后如何继续”的产品分支。文案里如果还写“拒绝授权后进入基础模式”反而不准确。正确表述应该是当前版本不申请运行时权限如果未来新增敏感能力必须补齐拒绝说明和降级路径。4. 页面层HomePage 和 Index 只做本地流程不制造隐形数据出口Index.ets是主页面聚合层负责在首页、题库、考试、收藏、我的等页面之间切换并根据断点和安全区控制布局。它使用StorageLink连接当前 tab、错题数量、断点类型、顶部安全区和底部导航避让高度。页面切换是本地状态切换不需要读取设备敏感信息也不需要联网。HomePage.ets更能体现产品能力边界。它从本地 mock 数据中读取BANKS、CATEGORIES、TOTAL_QUESTIONS、TOTAL_REGIONS用StatService.summarize汇总本地学习数据然后通过router.pushUrl进入分类、搜索、题库、考试、错题等本地页面。这个路径里没有fetch、HTTP 客户端、WebView也没有登录态、支付态或广告态。从权限与隐私角度看这意味着首页展示的数据来源是明确的页面数据来源是否需要权限是否上传题库数量、地区数量本地题库常量否否学习统计本地记录汇总否否分类入口本地分类数据否否搜索入口本地题库搜索否否错题、收藏、笔记入口Preferences 本地数据否否这张表对发布材料很重要。应用介绍可以说“本地题库学习、错题整理、收藏笔记、学习进度记录”但不能说“云端同步”“多端账号共享”“智能推荐服务端分析”。当前源码没有实现这些能力写进去会让功能说明、隐私说明和真实代码冲突。同样隐私政策也不应该套用过宽的模板。比如“我们会收集设备信息、网络日志、位置信息用于优化服务”这类句子如果当前应用并没有对应代码和权限就会制造不必要的审核风险。离线应用的材料应该更收敛说明本地保存什么、为什么保存、是否上传、用户如何清理或重置。5. UserDataManagerPreferences 保存的是学习状态不是身份数据当前应用真正持久化的数据集中在librarya/src/main/ets/utils/UserDataManager.ets。它通过preferences打开名为language_correction_master的本地存储把 JSON 序列化后的数据写入 Preferences并用flushSync()落盘。可复核的数据键包括favoriteRecords noteRecords wrongRecords bankProgress examHistory chapterProgress dailyReminderTime examDurationSec autoNextQuestion从职责结构看module.json5负责声明边界EntryAbility负责把应用拉起并初始化本地服务HomePage和Index只消费本地状态UserDataManager才是本地数据读写入口。这个结构能避免页面直接散落 Preferences 调用也让后续做权限复核时有一个清楚的检查点。这些字段可以分成三类。第一类是学习行为记录收藏、笔记、错题、题库进度、章节进度和考试历史。这些数据和题目学习体验直接相关用于恢复用户上次学习状态、展示学习统计、支持错题复盘。它们不是账号身份不包含通讯录、定位、相册、录音、支付或社交关系。第二类是学习偏好每日提醒时间、考试时长、自动下一题。这些是本地交互偏好作用范围在应用内。当前源码没有看到推送注册或系统通知权限申请因此“每日提醒时间”更适合被描述为本地偏好设置不能扩展成已经具备系统通知能力。第三类是 AppStorage 镜像状态。UserDataManager.init会把 Preferences 中读出的记录写入AppStorage页面再通过StorageLink使用这些数据。这个路径保持了页面和持久化层之间的边界页面消费状态数据管理器负责读取、解析、写入和刷新。从写入路径看可以简化为private static persist(key: string, value: object): void { this.prefs.putSync(key, JSON.stringify(value)) this.prefs.flushSync() }从页面消费路径看则是先由入口初始化再把结果放入应用级状态UserDataManager.init(this.context) AppStorage.setOrCreate(currentTabIndex, 0) AppStorage.setOrCreate(favoriteTabIndex, 0)这类本地存储仍然需要隐私说明但说明重点不是“我们如何上传”而是“我们在本机保存哪些学习数据以及用途是什么”。如果产品提供清空错题、清空收藏、清空笔记等入口文案应说明这些操作会影响本地记录如果没有统一清除所有数据的入口就不要在材料里承诺“一键删除所有本地数据”。6. 拒绝路径当前没有权限申请就不要虚构拒绝分支很多权限合规文章会强调“必须处理拒绝授权”。这个原则本身是对的但要基于真实能力。当前版本没有运行时权限申请所以它的拒绝路径结论应该写成场景当前源码状态正确处理首次启动不申请权限直接进入本地学习流程使用题库读取本地数据不需要授权弹窗收藏/笔记/错题写入 Preferences不需要授权弹窗搜索题目本地搜索不需要网络授权拒绝权限无运行时权限申请不虚构拒绝 UI这不是“少做了拒绝路径”而是“功能不需要权限因此没有拒绝路径”。如果未来新增敏感能力拒绝路径才会成为必做项。例如新能力可能新增声明必须补齐的拒绝路径拍照识别错题相机权限拒绝后允许手动输入或继续普通题库学习系统通知提醒通知相关授权拒绝后保留应用内提醒设置不显示误导性成功状态云同步网络权限、账号与隐私材料拒绝登录或断网时保留本地学习记录导入文件文件访问能力拒绝后说明无法导入但不影响已有本地题库因此权限与隐私的核心不是写一个万能弹窗而是让能力变化带动四个位置一起变化module.json5、运行时代码、页面降级说明、隐私与发布材料。只改其中一个位置就会出现不一致。7. 文案怎么写功能说明要跟源码一样克制基于当前源码应用发布说明可以围绕本地学习能力展开本地题库学习与分类练习收藏、笔记、错题和学习进度记录模拟考试和历史记录适配手机、平板、2in1 设备当前版本不需要登录、不包含支付、广告、推送、社交或 UGC。隐私说明也应该对应这些事实应用在本机保存学习记录、笔记、收藏、错题、进度和偏好这些数据用于恢复学习状态、统计学习情况和支持复盘当前源码未发现上传同步、外部网络请求或账号绑定流程当前module.json5未声明运行所需敏感权限如果未来增加网络、账号、通知、相机或文件导入能力应在版本说明、隐私政策和权限说明中同步更新。不建议写的内容包括“我们会收集设备唯一标识用于用户画像”“错题数据会同步到云端”“用户可通过账号在多端恢复数据”“拒绝定位后将无法使用附近服务”“应用会根据网络热度推荐内容”。这些能力在当前源码中没有证据。尤其是“网络热词”这类题库主题不应被包装成联网推荐能力。发布材料和技术文章都要避免把业务内容关键词误写成系统能力。8. 工程检查方法先扫声明再扫代码再对材料我在复核这类 HarmonyOS 应用时会按固定顺序走一遍不直接从隐私政策模板开始。第一步看module.json5。确认是否有requestPermissions、是否有INTERNET、是否有额外 Ability、Service、Extension 或后台入口。这里是硬边界。第二步扫入口和页面。重点看EntryAbility、主页面、设置页、导入导出页、搜索页、分享页、反馈页、关于页。确认有没有运行时权限请求、HTTP、WebView、账号 SDK、广告 SDK、推送 SDK、支付 SDK、分析 SDK。第三步扫数据层。确认 Preferences、RDB、文件、缓存分别保存什么是否包含身份信息、敏感内容、儿童信息或可上传内容。当前「笔下生辉」的数据集中在 Preferences字段语义都指向本地学习状态。第四步对文档和发布材料。把源码事实映射到功能说明、隐私政策、权限说明、审核自检报告和 AGC 材料。如果文档说“已移除 INTERNET、离线题库定位、本地保存学习记录”就要确认源码仍然维持这个状态。第五步记录未来变更触发条件。权限和隐私不是一次性工作。只要新增网络、账号、云同步、通知、拍照、文件导入、分享、反馈、统计或第三方 SDK就必须重新做一轮。9. 常见问题和修正方式问题一module.json5 没有权限但文案写了在线服务。修正方式是删掉或改写在线服务描述除非源码真实加入了网络能力并同步更新权限、隐私和用户路径。不要为了文案好看而给离线应用加“云端”“智能服务”等词。问题二源码只保存本地学习记录隐私政策却套用了收集设备信息的模板。修正方式是把隐私政策缩小到真实数据字段。能说清“收藏、笔记、错题、进度、考试历史、偏好设置”就够了不要引入没有代码支撑的数据类型。问题三新增了功能但忘了更新拒绝路径。如果未来加入相机、通知、文件导入等能力页面必须处理拒绝授权。拒绝不是错误弹窗结束而是要让用户知道哪些功能不可用、哪些本地能力仍可继续使用。问题四把题库里的业务词当成系统能力。例如题库分类中出现“网络热词”这不是联网。工程复核要结合文件路径和语义不能只按关键词做结论。问题五本地 Preferences 被忽略。不联网不代表没有隐私材料。本地保存的学习记录仍然是用户数据应该在材料中说明用途和范围只是不应夸大成上传或云端处理。10. 小结权限与隐私一致性是发布前的工程交叉检查「笔下生辉」当前版本的权限与隐私边界比较清楚module.json5没有requestPermissions和ohos.permission.INTERNET入口没有运行时权限请求页面使用本地题库和本地路由数据通过 Preferences 保存学习状态与偏好。这个结论可以从源码复核而不是从宣传语推断。真正需要坚持的是一致性功能说明不超过源码隐私政策不超过数据事实拒绝路径不虚构未来新增敏感能力时同步修改声明、运行时代码、页面降级和发布材料。对 HarmonyOS 5.0 应用来说这比堆砌一份通用隐私模板更可靠也更容易通过后续维护。本篇文章的封面使用当前文章独立的media/cover.png不同于同一软件合集复用的应用级collection-cover.png合集封面保持统一合集内每篇文章封面保持不同便于跨平台发布时区分文章和集合。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑