@hxa-rn/react-native-volume-manager
v2.0.8-beta.1
Published
React Native module which adds the ability to change the system volume on iOS and Android, listen to volume changes and supress the native volume UI to build your own volume slider or UX.
Downloads
203
Readme
react-native-volume-manager
本项目基于 react-native-volume-manager开发。如果在使用过程中有任何问题,欢迎在AtomGit提交Issue,会及时跟进。
项目介绍
@hxa-rn/react-native-volume-manager 是 react-native-volume-manager 2.0.8 的 HarmonyOS 适配包,面向 React Native for OpenHarmony 应用提供系统音量读取、音量变化监听、铃声模式读取与监听、设备静音状态查询等能力。
本包包含 TurboModule 原生实现,通过 @kit.AudioKit 访问 HarmonyOS 音频能力。音频会话、静音兼容及前台媒体音量写入采用明确的近似映射;铃声模式写入、DND 授权等能力继续受控降级。
集成指南
npm install @hxa-rn/react-native-volume-managerpeerDependencies:react、react-native(>= 0.72)。
包内声明了 harmony.alias: "react-native-volume-manager"。业务代码继续从原包名导入:
import { VolumeManager, getVolume } from 'react-native-volume-manager';工程支持 RNOH Autolinking 时无需手工注册。若项目未启用 Autolinking,需要将包内 volume_manager.har 接入 Harmony 工程,并在 C++ 与 ArkTS 两侧注册 VolumeManagerPackage。
如需使用 HarmonyOS 的 setVolume / showNativeVolumeUI 近似能力,还必须在应用 ArkUI 页面挂载宿主:
// ArkTS(与 RNApp 同级)
import { VolumePanelHost } from '@hxa-rn/react-native-volume-manager';
VolumePanelHost()宿主必须挂载。默认关闭系统音量条,并挂 (-1,-1) 抑制硬件键系统条。setVolume(..., { showUI: true }) 只让本次写入弹出官方条(不传 position)。showNativeVolumeUI({ enabled }) 不改音量、也不立刻出条,只决定之后按硬件音量键是否出条。
使用说明
import React, { useEffect, useState } from 'react';
import { Button, Text, View } from 'react-native';
import {
addVolumeListener,
getRingerMode,
getVolume,
isAndroidDeviceSilent,
} from 'react-native-volume-manager';
export default function VolumeExample() {
const [message, setMessage] = useState('待读取');
useEffect(() => {
const subscription = addVolumeListener((event) => {
setMessage(`音量事件:${event.volume} / ${event.type ?? 'unknown'}`);
});
return () => subscription.remove();
}, []);
const readStatus = async () => {
try {
const volume = await getVolume();
const ringerMode = await getRingerMode();
const silent = await isAndroidDeviceSilent();
setMessage(
`音量=${volume.volume.toFixed(2)},铃声模式=${ringerMode},静音=${silent}`
);
} catch (error) {
setMessage(`读取失败:${String(error)}`);
}
};
return (
<View>
<Button title="读取音频状态" onPress={readStatus} />
<Text>{message}</Text>
</View>
);
}import { VolumeManager } from 'react-native-volume-manager';
export async function adjustMediaVolume(value: number, showUI: boolean) {
await VolumeManager.setVolume(value, { showUI });
return VolumeManager.getVolume();
}
export async function allowHardwareVolumeHud(enabled: boolean) {
await VolumeManager.showNativeVolumeUI({ enabled });
}铃声模式监听必须成对释放:
import {
addRingerListener,
removeRingerListener,
} from 'react-native-volume-manager';
const subscription = addRingerListener((event) => {
console.log(event.status, event.mode);
});
removeRingerListener(subscription);import React from 'react';
import { View, Text, Button } from 'react-native';
import {
useRingerMode,
RINGER_MODE,
} from 'react-native-volume-manager';
const modeText = {
[RINGER_MODE.silent]: 'Silent',
[RINGER_MODE.normal]: 'Normal',
[RINGER_MODE.vibrate]: 'Vibrate',
};
export default function RingerExample() {
const { mode, error, setMode } = useRingerMode();
return (
<View>
<Text>Ringer Mode: {mode !== undefined ? modeText[mode] : null}</Text>
<Button title="Silent" onPress={() => setMode(RINGER_MODE.silent)} />
<Button title="Normal" onPress={() => setMode(RINGER_MODE.normal)} />
<Button title="Vibrate" onPress={() => setMode(RINGER_MODE.vibrate)} />
<Text>{error?.message}</Text>
</View>
);
}import React from 'react';
import { View, Text } from 'react-native';
import { useSilentSwitch } from 'react-native-volume-manager';
export default function SilentSwitchExample() {
const status = useSilentSwitch();
return (
<View>
{status ? (
<View>
<Text>Is Muted: {status.isMuted ? 'YES' : 'NO'}</Text>
<Text>Is Initial Query: {status.initialQuery ? 'YES' : 'NO'}</Text>
</View>
) : (
<Text>Fetching...</Text>
)}
</View>
);
}接口文档
读取与监听
| 接口 | 参数 | 返回值 | HarmonyOS 说明 |
| --- | --- | --- | --- |
| getVolume() | 无 | Promise<VolumeResult> | 返回主音量及可用音频流的归一化值 |
| addVolumeListener(callback) | 音量事件回调 | EmitterSubscription | 监听 RNVMEventVolume |
| getRingerMode() | 无 | Promise<0 \| 1 \| 2 \| undefined> | 0 静音、1 振动、2 正常 |
| isAndroidDeviceSilent() | 无 | Promise<boolean \| null> | 基于铃声模式和媒体音量判断 |
| addRingerListener(callback) | 铃声事件回调 | 订阅对象 | 监听 RNVMSilentEvent;鸿蒙事件 mode 为 SILENT / VIBRATE / NORMAL,不含 MUTED |
| removeRingerListener(subscription) | 订阅对象 | void | 停止铃声事件转发并移除 JS 订阅 |
写入与平台专属接口
| 接口 | 参数 | 返回值 | HarmonyOS 说明 |
| --- | --- | --- | --- |
| setVolume(value, config?) | value: 0–1,config: {playSound?, type?, showUI?} | Promise<void> | 要求挂载 Host;映射到前台 MEDIA 原始音量等级;showUI 只控制本次写入是否弹出官方音量条 |
| setRingerMode(mode) | 0 \| 1 \| 2 | Promise<0 \| 1 \| 2 \| undefined> | 受控降级,返回请求值 |
| checkDndAccess() | 无 | Promise<boolean \| undefined> | 返回 false |
| requestDndAccess() | 无 | Promise<boolean \| undefined> | 返回 false,不跳转 |
| showNativeVolumeUI(config) | {enabled: boolean} | Promise<void> | 不改音量、不立刻出条;enabled=true 拆掉 (-1,-1) 抑制器,之后按音量键能出系统条;enabled=false 再挂抑制器 |
| enable(enabled?, async?) | 布尔值 | Promise<void> | 近似映射音频会话激活/停用;启用采用混音策略 |
| setActive(value?, async?) | 布尔值 | Promise<void> | 近似映射 activateAudioSession / deactivateAudioSession |
| setCategory(value, mixWithOthers?) | 音频会话类别 | Promise<void> | 近似映射 DEFAULT / MIX_WITH_OTHERS / PAUSE_OTHERS 并发策略 |
| setMode(value) | 音频会话模式 | Promise<void> | API20 映射 MEDIA / GAME / VOICE_COMMUNICATION 场景 |
| enableInSilenceMode(enabled?) | 布尔值 | Promise<void> | iOS 专属,受控降级 |
| addSilentListener(callback) | 静音开关回调 | 订阅对象 | 返回铃声/媒体静音兼容事件 {isMuted, initialQuery} |
| setNativeSilenceCheckInterval(value) | 毫秒数 | void | 事件驱动,无轮询需求,受控降级 |
Hooks、常量与类型
| 名称 | 说明 |
| --- | --- |
| useRingerMode() | 读取铃声模式并提供设置函数;HarmonyOS 设置操作为受控降级 |
| useSilentSwitch(interval?) | iOS 为物理静音开关;HarmonyOS 返回铃声/媒体静音兼容状态 |
| RINGER_MODE | { silent: 0, vibrate: 1, normal: 2 } |
| AndroidVolumeTypes | music / call / system / ring / alarm / notification |
| VolumeResult | 至少包含 volume,音量事件可包含 type |
| Mode | 上游类型含 SILENT / VIBRATE / NORMAL / MUTED;鸿蒙铃声事件不写 MUTED |
快速验证(运行 Example)
前置条件
| 依赖 | 版本要求 | |------|----------| | Node.js | >= 18 | | DevEco Studio | 5.0+ / 6.0+ | | HarmonyOS SDK | API 12+ |
运行步骤
1. 克隆仓库
git clone https://gitcode.com/hxa-rn/react-native-volume-manager.git
cd react-native-volume-manager
git checkout br_rnoh0.722. 安装仓库开发依赖
npm install --legacy-peer-depsExample 已改为从 npm 公仓安装 @hxa-rn/[email protected],不再使用本地 file:../xxx.tgz,运行 Example 不必再执行 npm pack。
3. 进入 example 目录,安装依赖
cd example
npm install --legacy-peer-deps4. 生成 JS Bundle
npm run dev产物:harmony/entry/src/main/resources/rawfile/bundle.harmony.js
5. 用 DevEco Studio 打开鸿蒙工程
- 打开 DevEco Studio
- 选择
example/harmony目录 - 等待 Sync 完成
6. 编译并运行 HAP
在 DevEco Studio 中点击运行按钮,将 HAP 安装到设备/模拟器。
注意:Example 中已预置插件依赖和 Package 注册,无需手动配置 Link。
约束与限制
| 项目 | 要求或限制 |
| --- | --- |
| 包版本 | 2.0.8-beta.1 |
| React Native | >= 0.72 |
| Node.js | >= 18 |
| HarmonyOS SDK | compatibleSdkVersion 6.0.0(20),API 20+ |
| 权限 | 无额外系统权限 |
| 能力 | HarmonyOS 行为 |
| --- | --- |
| getVolume、addVolumeListener | 原生实现;返回 0–1 归一化音量 |
| getRingerMode、addRingerListener、isAndroidDeviceSilent | 原生实现 |
| setVolume | 通过已挂载的 VolumePanelHost 近似调节前台 MEDIA 音量;showUI 只控制本次是否弹出官方音量条 |
| setRingerMode | 受控降级;第三方应用不能直接设置铃声模式 |
| checkDndAccess、requestDndAccess | 无等价公开 API,返回 false,不跳转设置页 |
| showNativeVolumeUI | 只记后续硬件键策略,不改音量、不立刻出条;enabled=false 用 (-1,-1) 抑制硬件键系统条 |
| enable、setActive、setCategory、setMode | 映射 HarmonyOS AudioSessionManager,属于近似实现 |
| addSilentListener、useSilentSwitch | 以铃声模式与媒体静音状态模拟,不代表物理静音开关 |
| enableInSilenceMode、setNativeSilenceCheckInterval | 无等价语义,安全 no-op |
system 与 notification 没有独立的 HarmonyOS 音量类型,当前映射到最接近的 RINGTONE 流。API20 下音量与铃声监听均可在订阅移除时真实注销;应用仍应在 React 组件卸载时释放 JS 订阅。
HarmonyOS 不允许三方应用通过命令式 API 静默改系统音量。本包使用官方 AVVolumePanel:Host 保持挂载,默认挂 (-1,-1) 抑制器。setVolume(..., { showUI: true }) 本次出官方条(不传 position,通常在右上角);showNativeVolumeUI 不立刻出条,只决定之后硬件键是否出条。该方案仅支持前台 MEDIA 音量,非 music 类型会映射到 MEDIA;后台调节和按流精确写入仍不可用。官方条显示时可能吞掉部分点击。
开源license
本项目基于 MIT 协议,详见 LICENSE 文件。
问题反馈渠道
欢迎在 AtomGit 提交 Issue。也可通过以下地址反馈:
- https://gitcode.com/hxa-rn/react-native-volume-manager
- https://gitcode.com/hxa-rn/react-native-volume-manager/issues
