You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 20:45:06