React Native for OpenHarmony 三方库 react-native-volume-control 1.0.1 适配实战媒体音量、量化与事件监听这篇文章适合第一次接触系统音频 API 的 RN 开发者。我们会区分媒体音量、铃声音量和通话音量说明 0 到 1 的浮点值如何变成系统整数档位并展示订阅、取消订阅以及恢复用户原设置的完整过程。适配仓库oh-react-native/react-native-volume-control交付分支main适配 TAG1.0.1-ohos-1.0.0受测提交b8208c8faa5e18eab5e1a00ebe17b1c84d41222f配套源码react-native-volume-control一、这个库到底控制什么react-native-volume-control 的名字很容易让人误会成“控制手机所有声音”。实际上它控制的是媒体音量也就是音乐、视频和游戏这一路音频铃声、通知、闹钟和通话音量属于不同的音频流。本次适配保留上游 getVolume、change 和 VolumeControlEvents 三个公开入口让 JS 能读取媒体音量、请求修改媒体音量并观察设备音量键或系统变化。上游类型把 getVolume 写成 number但 Android/iOS 实现和调用示例都使用 Promise。适配以真实运行契约为准getVolume() 返回 Promise结果是 0 到 1 的归一化数change(value) 保持 void 风格系统写入在原生侧异步排队VolumeControlEvents 负责变化事件。没有把“写入请求已提交”虚构成“系统已经返回确认”。适配前检查了 oh-react-native 组织、CPF-RN 组织 和中心清单覆盖去 scope 名称及 rntpc 前缀没有发现同上游的有效鸿蒙仓库。上游版本为 1.0.1原仓库 LICENSE 与 npm 元数据声明存在差异交付中保留原文件并在报告中注明不拿别的库的许可证覆盖。图 1验证开始时系统媒体音量为 8/20库 getter 返回 0.40底部独立探针读取系统整数档位两个来源互相核对。二、受测环境和交付目录环境为 React Native 0.84.1、React 19.2.3、RNOH 0.84.3、DevEco Studio 26.0.0 Release、HarmonyOS SDK 26.0.0ROM 为 OpenHarmony-7.0.0.105。最终仓库保留 JS 入口、Spec、ArkTS、C 方法登记、CMake、HAR、双语 README、测试、spec.json、检查报告和许可证node_modules、oh_modules、HAP、签名和证据留在活动目录。实际受测提交、TAG 和安装包在文首链接锁定。媒体音量是系统整数档位。手机本次最大档位为 20库对外把档位除以最大值返回 0.40。输入 0.349 不可能原样保存正确结果应是 floor(0.349 × 20) 6也就是 0.30。读者若用“返回值必须等于输入”作为断言会误判系统量化为库错误。三、从 JS 到 Audio API业务调用 - VolumeControlEvents / getVolume / change - NativeVolumeControl TurboModule Spec - RNOH C Package - ArkTS VolumeControlTurboModule - HarmonyOS AudioManager 的 MEDIA 音频流首次添加 JS 监听时原生侧注册一个媒体流观察器增加第二个监听不重复注册。只有档位真正变化才派发事件移除最后一个监听后取消观察。每轮订阅使用世代标识已经取消的旧回调即使排队到达也不能写入新一轮状态。SDK 当前把 setVolume 标记为 deprecated建议应用让用户通过系统音量面板操作。但上游 change(value) 的能力就是程序写入音量面板无法实现同一契约。本次在受测 ROM 的普通签名宿主中验证了真实写入因此保留该实现文章不把这个结果扩大成所有未来 ROM 都保证可写。读写成功也不等于用户主观听感评测。四、实际修改的文件JS 入口和 TypeScript Spec 保持上游 API 形状并把 getVolume 的异步返回写进类型。harmony/ 下加入 HAR、oh-package.json5、build-profile.json5、hvigorfile.ts 和 module.json5。ArkTS TurboModule 使用系统 AudioManager 读取 MEDIA 档位、执行写入并注册变化观察。C Package 的 methodMap_ 与 JS/ArkTS 模块名一致CMake target 由自动链接接入宿主。change 对输入做有限性、数字类型和 0 到 1 范围检查写入任务按调用顺序排队getVolume 等待已提交的写入再读取。事件桥接在首订阅和末订阅边界启动/停止避免组件卸载后仍收到回调。这些文件都来自最终受测提交。没有把验证宿主或临时探针上传到库仓库防止消费者误把 QA 代码当正式 API。五、用真实 tgz 接入宿主受测使用与文首 TAG 对应的 react-native-volume-control-1.0.1.tgz。把 tgz 放入独立宿主后运行export RNOH_HOST$HOME/rnoh-qa export EVIDENCE_DIR$RNOH_HOST/evidence/react-native-volume-control mkdir -p $EVIDENCE_DIR cd $RNOH_HOST npm install $HOME/Downloads/react-native-volume-control-1.0.1.tgz --save-exact ./node_modules/.bin/react-native link-harmony cd harmony ohpm install --all cd .. ./node_modules/.bin/react-native bundle-harmony --dev false --sourcemap-output $EVIDENCE_DIR/bundle.map hvigorw assembleHap --mode module -p productdefault --no-daemon等待 npm 结束后使用宿主的本地 CLI检查 source map 是否来自 tgz 安装目录再构建签名 HAP。build 通过和音量真的改变是两层证据必须分开记录。真机安装建议显式指定设备并在验证期间临时保持常亮hdc list targets export DEVICE_ID$(hdc list targets | awk NF {print $1; exit}) hdc -t $DEVICE_ID install $RNOH_HOST/output/tested.hap hdc -t $DEVICE_ID shell power-shell wakeup hdc -t $DEVICE_ID shell power-shell timeout -o 2147483647 hdc -t $DEVICE_ID shell aa start -a EntryAbility -b com.example.rnqa hdc -t $DEVICE_ID shell uitest screenCap -p /data/local/tmp/volume.png hdc -t $DEVICE_ID file recv /data/local/tmp/volume.png $EVIDENCE_DIR/volume.png恢复原超时后再结束验证常亮设置和媒体音量恢复是两件事二者都不能省略。六、业务侧读写和监听示例import VolumeControl, {VolumeControlEvents} from react-native-volume-control; const current await VolumeControl.getVolume(); if (current ! null) { console.log(媒体音量, current); } const subscription VolumeControlEvents.addListener(VolumeChanged, event { console.log(新的媒体音量, event.volume); }); try { VolumeControl.change(0.6); } finally { subscription.remove(); }上面的 remove 要放在组件的清理函数或 finally 中。change 的返回值不能被当成“写入已完成”的 Promise需要确认结果时等待事件或再次调用 getVolume。业务只想显示音量时可以订阅事件业务只想设置一次时可以设置后读取但不要同时注册多个原生观察器。七、真机逐项验证第一步记录原值 8/20确保测试结束能恢复。第二步读取 getter确认 0.40。第三步写入 0.349系统变为 6/20库返回 0.30。第四步连续写入 0.10、0.60、0.35验证队列按调用顺序执行。第五步注入设备音量增加事件核对独立探针和 JS 事件。第六步重复移除监听、移除最后一个监听恢复原档位并再次读取。图 2请求 0.349 后真实系统档位为 6/20规范化结果是 0.30。图 3连续写入保持顺序NaN、Infinity、字符串、负数、超过 1 和缺失参数均被拒绝。图 4系统从 7/20 变为 8/20库事件和 getter 都得到 0.40。截图中的浮层由设备输入接口触发。图 5监听 A 重复移除后不再回调监听 B 仍能收到 0.25。图 6移除最后一个监听后没有新事件finally 通过独立恢复入口把媒体音量恢复到原来的 8/20。六张图片分别对应六个场景。mock 测试覆盖系统拒绝、越界、销毁和重试真机覆盖读取、量化、连续写入、事件、取消订阅、恢复和两个不同进程冷启动。发布文章只保留仓库和文档链接读者复现时应以自己的设备截图、日志和 HAP 哈希为准。八、踩坑、限制与结论一次取证失败来自 hdc shellexecFile 参数数组会在手机端再次解释日志正则中的竖线被当成管道导致早期断言丢失。修复后改为从受测宿主 PID 启动前就持续采集并对同一 HAP 重跑全部场景。这个经验说明“最后一次读取日志”不能代替连续采集。当前实现只承诺受测 ROM 上的媒体流读写。铃声、通知、闹钟、通话、蓝牙路由、其他 ROM、长期后台运行和主观音质均未覆盖SDK 的 deprecated 标记也意味着未来系统可能收紧写权限。应用应准备写入失败后的提示和系统面板降级路径。九、参考链接上游 npm 包 react-native-volume-control适配仓库首页main 分支1.0.1-ohos-1.0.0 TAGOpenHarmony Audio APIReact Native NativeEventEmitter 文档欢迎加入 RN for OpenHarmony 社区。
阅读完成 · 觉得有帮助?