You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

react-native-audio-recorder-player调用stopRecorder()安卓真机崩溃排查与解决

问题分析与解决方案

我之前也碰到过类似的Android真机录制崩溃问题,结合你的代码和环境配置,梳理出几个核心原因及对应的解决办法:

1. 存储路径硬编码+编码格式不匹配

你的Android路径用了sdcard/audio-${new Date().getTime()}.mp3,这里有两个明显的问题:

  • 路径兼容性差:不同Android设备的外部存储路径并不统一,直接写sdcard/在部分机型上会触发找不到路径的错误;而且Android 10+的Scoped Storage机制限制了直接访问根目录,容易引发权限或IO异常。
  • 编码与容器格式不兼容:你设置的编码是AudioEncoderAndroidType.AAC,但输出文件后缀是.mp3——AAC编码的音频和MP3容器格式不匹配,Android的MediaRecorder在停止录制时很可能因为格式解析错误直接崩溃。

解决办法

  • 改用标准存储路径,推荐借助react-native-fs库获取兼容的目录:
    import RNFS from 'react-native-fs';
    
    const path = Platform.select({
      ios: `audio-${new Date().getTime()}.m4a`,
      android: `${RNFS.ExternalDirectoryPath}/audio-${new Date().getTime()}.m4a`
    });
    
  • 保持编码和后缀一致:AAC编码对应.m4a.aac后缀;如果一定要用MP3,需要将AudioEncoderAndroid改为AudioEncoderAndroidType.MPEG_4(注意:部分Android设备可能不支持MP3编码)。

2. 监听器移除方式错误

你调用audioRecorderPlayer.removeRecordBackListener()时没有传入监听器的引用ID,这个库的addRecordBackListener会返回一个唯一监听ID,直接调用无参的移除方法可能无法正确清理监听器,进而引发内存泄漏或录制停止时的崩溃。

解决办法
useRef保存监听器ID,移除时精准传入:

import { useRef } from 'react';

// 组件内定义引用
const recordListenerRef = useRef(null);

// 启动录制函数
async function handleRecord() {
  try {
    // ... 权限校验、路径配置、audioSet逻辑 ...
    const result = await audioRecorderPlayer.startRecorder(path, audioSet);
    setRecord(true);
    // 保存监听器ID
    recordListenerRef.current = audioRecorderPlayer.addRecordBackListener(e => {
      // 可留空,但建议不要直接return,比如打印下进度便于调试
      // console.log('录制进度:', e.current_position);
      return;
    });
  } catch (err) {
    console.error('启动录制失败:', err);
  }
}

// 停止录制函数
async function onStopRecord() {
  try {
    // 先移除监听器再停止录制
    if (recordListenerRef.current) {
      audioRecorderPlayer.removeRecordBackListener(recordListenerRef.current);
      recordListenerRef.current = null;
    }
    const result = await audioRecorderPlayer.stopRecorder();
    setRecord(false);
    setFiles([
     ...files,
     { uri: result, type: "audio/m4a", name: `audio-${new Date().getTime()}.m4a` }
    ]);
  }catch(error){
    Alert.alert( "Erro", error.message || JSON.stringify(error) );
  }
}

3. 库版本兼容性问题

你使用的react-native-audio-recorder-player@2.6.0-rc3是候选发布版本,本身可能存在未修复的bug;再加上你的React Native版本是0.63.3(相对老旧),两者的兼容性适配可能存在漏洞,这在Android真机上更容易暴露。

解决办法

  • 升级到该库的正式稳定版,比如2.6.0正式版(查看库的Release Notes确认适配RN0.63.x);
  • 如果升级后问题依旧,可尝试降级到2.5.x版本,这个版本适配旧RN版本的稳定性更好。

4. 权限申请不完整

虽然你调用了getPermissions(),但可能没覆盖Android全版本的权限要求:

  • 确保AndroidManifest.xml中添加了必要权限:
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    
  • 针对Android 10+,要确保动态权限申请逻辑正确获取到了存储权限,避免因权限不足导致录制停止时的IO异常。

建议先从路径和格式匹配入手调试,这是最常见的崩溃诱因,再依次排查监听器、库版本和权限问题,应该能解决Android真机上的崩溃问题。

内容的提问来源于stack exchange,提问作者AlecsanderFarias

火山引擎 最新活动