我用 ArkUI 做了个声境护照:专注时长换算成飞行里程

张开发
2026/4/20 15:32:33 15 分钟阅读

分享文章

我用 ArkUI 做了个声境护照:专注时长换算成飞行里程
起因十几个专注 App 全删了我不是意志力不够是这件事本身太无聊了。Forest、潮汐、番茄ToDo每一个都下载、用几天、删掉。25 分钟到了铃声一响一个数字加一就结束了。功能没问题但坚持本身没有任何值得记录的感觉。于是我开始做声境护照Sonic Passport——把每次专注包装成一段「声音旅行」专注时长换算成飞行里程积累里程解锁新的城市声景每次结束生成一张战报卡片。鸿蒙版的特殊挑战iOS 版先做出来的上架 App Store 之后我决定移植到 HarmonyOS。上手算顺SwiftUI 转过来思路基本一致。声明式 UI、状态驱动概念层面没什么障碍。但细节差异挺多尤其是音频和手势这块。声境护照的核心体验之一是「雷达音效界面」——用户在一个圆形雷达盘上拖拽音效球Orb每个 Orb 对应一种环境声雨声、咖啡馆噪音、键盘声等拖拽位置决定音量和声场比例。这个交互在 iOS 上用手势识别做得比较顺移植到 ArkTS 重新写了一遍。ArkUI 的PanGesture处理拖拽配合State驱动 Orb 坐标更新核心结构大概这样State orbPositions: Array{ x: number; y: number } [ { x: 120, y: 80 }, { x: 60, y: 150 }, ] gesture( PanGesture() .onActionUpdate((event: GestureEvent) { this.orbPositions[this.activeIndex] { x: this.orbPositions[this.activeIndex].x event.offsetX, y: this.orbPositions[this.activeIndex].y event.offsetY, } this.updateAudioVolume(this.activeIndex) }) ) 最后的解法很土但有效。说一下走了哪些弯路第一个方案在 onActionUpdate 里加了 setTimeout 做节流帧率根本跟不上手指Orb 总是慢半拍换成用 animateTo 包裹坐标更新想让移动顺滑但 animateTo 会对状态变更做插值音量更新和视觉位置之间出现时序冲突声音和拖拽完全对不上。最终方案是直接更新 State 坐标在 updateAudioVolume 里手动加时间戳判断每 16ms 最多触发一次音量计算。没有任何黑科技就是最朴素的限频。 ## 数据模型里程和章节系统 专注会话对应 FocusLog记录时长minutes、开始小时hour用来分析高峰时段、关联任务、声景 ID以及 comboIndex——连续专注的第几段用来触发 combo 里程奖励。 远征章节系统Expedition是游戏化的核心。每个章节对应一座城市包含若干任务任务类型分三种完成次数sessionCount、累计分钟数focusMinutes、深度专注次数deepFocusCount。 deepFocusCount 单独拎出来是因为有人开着计时器刷手机照样能完成一个番茄这个指标本身就不够用。我的定义是超过 20 分钟不中断才算一次深度专注更能反映真实的专注质量。任务进度从 FocusLog 列表实时计算不手动维护计数器这样历史数据能随时重算不会出现改了逻辑之后数据对不上的问题。 ## 会话战报的推荐逻辑 每次专注结束App 弹出一张战报显示时长、效率指数、获得的经验值以及一条「下一步建议」。 这条建议的生成逻辑是先看今天计划还差几段再看连续打卡天数组合出对应文案。连续天数不到 2 天提示「建议先连续 3 天完成每日最小闭环」连续 5 天以上提示「你已连续 N 天重点是稳定复用」。 说实话这套逻辑实现起来不复杂但比「加油继续专注」这种废话有用得多。至少我自己用的时候看到「今天还差 2 段达成日计划」会真的再开一段。 ## 声景京都、雨夜和咖啡馆 目前鸿蒙版上线了几个核心声景京都是第一个后续跟着远征章节陆续解锁更多城市。 声景是混合音轨雨声、环境人声、城市 ambient 可以通过雷达 Orb 自由混合用户可以存下自己的混音比例下次直接用同一套配置进入专注。有几个测试用户说「终于可以把键盘声和雨声同时开着了」。说实话我写这篇文章的时候也开着。 ## 上线情况 声境护照 iOS 版 App Store ID 是 6759910553目前是 1.3 版本。鸿蒙版刚完成核心功能移植上架审核阶段。 我做鸿蒙版的原因说直白点是想验证这个产品在另一个平台是否跑得通顺便蹭一点新平台红利动机就这么简单。ArkUI 的开发体验比一年前好了很多Canvas 绘制、动画、手势这些常用的东西基本都有对应方案有些边界情况文档还不够细得自己试费时间但说不上是阻碍。 ## 一个还没解决的问题求路过的同学指点 多个 AVPlayer 实例在后台同时播放时偶发全部静音概率大概三四成规律不明显。重新 resume 有时能恢复有时不行。 我排查过几个方向后台任务类型声明ohos.permission.KEEP_BACKGROUND_RUNNING已经加上了AudioRenderer 的打断策略设成了 INTERRUPT_MODE_INDEPENDENT_MODE想让多个流互不干扰也试过把所有 Orb 对应的音频流统一托管给一个 AudioRenderer 做混音但这样失去了单独控制每路音量的灵活性方案暂时搁置了。 怀疑的方向是后台焦点切换时 AudioSession 状态没有正确恢复但鸿蒙这块的文档比较简略我还没找到明确的排查路径。如果你在 HarmonyOS 上做过多路音频后台播放欢迎评论区说一声或者私信我都行。

更多文章