React Native Expo测量分贝实现枪声触发计时器开发问题咨询
问题原因与修复方案
1. 初版代码标红报错原因
componentDidMount、componentWillUnmount是类组件专属的生命周期API,既不能从react包中导入,也不能直接在函数式组件内部声明,所以会直接触发语法报错。
2. useEffect版本无法运行的核心问题
- 没有给
useEffect添加空依赖数组,导致每次组件重渲染都会重复执行启停逻辑、重复注册回调,逻辑完全混乱 - 没有提前申请麦克风录音权限,没有权限的情况下系统会直接拦截录音逻辑,不会返回任何分贝数据
- 未配置iOS/Android对应平台的权限声明,权限申请会直接被系统驳回
3. 前置配置要求
先完成对应平台的权限配置,再修改代码:
iOS配置
在项目ios目录下的Info.plist文件中添加麦克风使用说明:
<key>NSMicrophoneUsageDescription</key> <string>需要访问麦克风来测量射击产生的分贝值</string>
配置完成后执行pod install更新原生依赖。
Android配置
在项目android/app/src/main目录下的AndroidManifest.xml中添加录音权限声明:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
4. 修正后可运行代码
import React, { useState, useEffect } from "react"; import { StyleSheet, Text, PermissionsAndroid, Platform } from "react-native"; import Title from "../components/Title"; import { Button, Input } from "react-native-elements"; import RNSoundLevel from "react-native-sound-level"; const CreateGunScreen = ({ navigation }) => { const [name, setName] = useState(""); const [errorMessage, setErrorMessage] = useState(""); // 申请录音权限 const requestRecordPermission = async () => { if (Platform.OS === 'ios') return true; try { const granted = await PermissionsAndroid.request( PermissionsAndroid.PERMISSIONS.RECORD_AUDIO, { title: "麦克风权限申请", message: "需要访问麦克风来测量射击分贝值", buttonPositive: "同意" } ); return granted === PermissionsAndroid.RESULTS.GRANTED; } catch (err) { console.warn("权限申请错误:", err); return false; } }; const startMeasuring = async () => { const hasPermission = await requestRecordPermission(); if (!hasPermission) { setErrorMessage("未获得麦克风权限,无法测量分贝"); return; } try { // 可自定义采样参数,interval为数据返回间隔,单位毫秒 RNSoundLevel.start({ sampleRate: 22050, channelCount: 1, format: "pcm_16bit", interval: 100, }); RNSoundLevel.onNewFrame = (data) => { // data.value即为当前实时分贝值,范围为-160~0,数值越大音量越高 console.log("实时分贝数据:", data); }; } catch (err) { console.log("启动测量失败:", err); setErrorMessage("启动分贝测量失败"); } }; useEffect(() => { startMeasuring(); return () => { RNSoundLevel.stop(); RNSoundLevel.onNewFrame = null; }; }, []); // 空依赖数组保证仅在组件首次挂载和卸载时执行 return ( <> <Title text="Create Gun" /> <Input label="name" value={name} onChangeText={setName} autoCapitalize="none" autoCorrect={false} containerStyle={styles.input} /> {errorMessage ? ( <Text style={styles.errorMessage}>{errorMessage}</Text> ) : null} <Button title="Cancel" type="clear" style={{ alignSelf: "center", marginVertical: 10, }} onPress={() => navigation.navigate("Guns")} /> </> ); }; const styles = StyleSheet.create({ input: { marginHorizontal: 20, marginVertical: 10, }, errorMessage: { color: 'red', marginHorizontal: 20, } }); export default CreateGunScreen;
5. 额外排查项
如果修改后仍无日志输出,请确认:
- 必须在真机上运行测试,模拟器没有麦克风硬件,无法返回真实音频数据
- 修改配置后需要完全重新编译项目,不能仅刷新JS bundle
- 检查是否安装了正确版本的
react-native-sound-level依赖,版本不兼容也会导致无数据返回
内容的提问来源于stack exchange,提问作者Danny Verdel
相关产品推荐
相关产品推荐

