expo-audio无法录制语音消息,调用stop()抛出异常问题求助
Expo Audio 语音录制功能异常修复方案
问题描述
使用新版expo-audio开发语音消息录制应用,按官方文档编写代码后功能失效:
- 执行
startRecording后,audioRecorder.isRecording始终为false(预期应为true) - 调用
stopRecording时抛出异常:
[Error: Call to function 'AudioRecorder.stop' has been rejected. → Caused by: java.lang.IllegalStateException]
原代码片段:
const startRecording = async () => { await audioRecorder.prepareToRecordAsync(); audioRecorder.record(); setRecording(audioRecorder.isRecording); }; const stopRecording = async () => { await audioRecorder.stop(); setRecording(audioRecorder.isRecording); setAudioUri(audioRecorder.uri ?? ""); };
核心问题分析
- 异步操作未等待:
audioRecorder.record()是异步方法,调用后立刻读取isRecording时,状态还未更新,导致拿到旧值。 - 权限缺失:新版expo-audio要求提前申请录音权限,无权限时录制会静默失败,状态不会切换。
- Recorder实例初始化错误:若
audioRecorder未通过Audio.Recorder.createAsync()正确创建,后续所有录制操作都会无效。
修复步骤
1. 前置处理录音权限
在组件初始化时申请录音权限,无权限时终止录制流程:
import { Audio, PermissionsAndroid, Platform } from 'expo'; const requestRecordingPermission = async () => { if (Platform.OS === 'android') { const permissionResult = await PermissionsAndroid.request( PermissionsAndroid.PERMISSIONS.RECORD_AUDIO ); return permissionResult === PermissionsAndroid.RESULTS.GRANTED; } // iOS权限由Expo自动处理,返回true即可 return true; }; // 组件挂载时申请权限 useEffect(() => { requestRecordingPermission(); }, []);
2. 修正录制流程的异步逻辑
改用recordAsync()(返回Promise)等待录制启动完成,同时确保Recorder实例正确创建:
const [audioRecorder, setAudioRecorder] = useState(null); const [recording, setRecording] = useState(false); const [audioUri, setAudioUri] = useState(""); const startRecording = async () => { const hasPermission = await requestRecordingPermission(); if (!hasPermission) { alert('请授予录音权限以继续'); return; } // 创建Recorder实例(必须步骤) const recorder = await Audio.Recorder.createAsync({ android: { extension: '.m4a', outputFormat: Audio.RECORDING_OPTION_ANDROID_OUTPUT_FORMAT_MPEG_4, audioEncoder: Audio.RECORDING_OPTION_ANDROID_AUDIO_ENCODER_AAC, sampleRate: 44100, numberOfChannels: 2, bitRate: 128000, }, ios: { extension: '.m4a', audioQuality: Audio.RECORDING_OPTION_IOS_AUDIO_QUALITY_HIGH, sampleRate: 44100, numberOfChannels: 2, bitRate: 128000, }, }); await recorder.prepareToRecordAsync(); await recorder.recordAsync(); // 等待录制启动完成 setAudioRecorder(recorder); setRecording(true); }; const stopRecording = async () => { if (!audioRecorder) return; const result = await audioRecorder.stopAndUnloadAsync(); setRecording(false); setAudioUri(result.uri ?? ""); // 释放Recorder资源 setAudioRecorder(null); };
3. 实时同步录制状态(可选优化)
通过状态监听回调替代主动读取,确保状态同步准确:
useEffect(() => { if (!audioRecorder) return; const statusListener = audioRecorder.addRecordingStatusListener((status) => { setRecording(status.isRecording); }); // 组件卸载时移除监听 return () => statusListener.remove(); }, [audioRecorder]);
内容的提问来源于stack exchange,提问作者Ben Phung
相关产品推荐
相关产品推荐

