Android AudioRecorder资源未正常释放导致创建失败问题求助
解决AudioRecord多次使用后资源泄漏导致创建失败的问题
我之前也碰到过一模一样的AudioRecord资源泄漏问题,你的报错日志里的createRecord returned error -1本质就是系统音频输入资源没有被正确释放,导致后续尝试创建新的AudioRecord实例时,系统没有可用资源分配给你了。重启应用能恢复,是因为重启会让系统强制回收该应用占用的所有音频资源。
先分析下你现有代码里的几个潜在问题:
- 资源释放逻辑只在
try块的末尾执行,如果循环过程中抛出异常,会直接跳去catch块,stop()和release()根本不会被调用,Recorder就会一直占用资源 micRunning变量如果没有用volatile修饰,多线程环境下可能出现线程不可见性问题,导致循环无法及时退出,Recorder长时间占用资源- 调用
stop()和release()前没有检查Recorder的当前状态,可能在错误状态下调用这些方法,导致资源释放不彻底
给你几个具体的修复方案:
1. 用finally块确保资源必被释放
不管代码是否抛出异常,finally块里的逻辑都会执行,这是保证资源释放的关键:
// 确保micRunning是线程安全的,用volatile修饰 private volatile boolean micRunning = false; private AudioRecord recorder = null; public void startRecording() { try { int bufferSize = AudioRecord.getMinBufferSize(FREQUENCY, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT)*2; recorder = new AudioRecord.Builder() .setAudioSource(MediaRecorder.AudioSource.VOICE_RECOGNITION) .setAudioFormat(new AudioFormat.Builder() .setEncoding(AudioFormat.ENCODING_PCM_16BIT) .setSampleRate(FREQUENCY) .setChannelMask(AudioFormat.CHANNEL_IN_MONO) .build()) .setBufferSizeInBytes(bufferSize) .build(); recorder.startRecording(); micRunning = true; while (micRunning) { byte[] tempBuffer = new byte[bufferSize]; int readSize = recorder.read(tempBuffer,0,bufferSize); // 注意:要检查read的返回值,避免处理无效数据 if (readSize > 0) { byte[] ba = new Resampler().reSample(tempBuffer, 16, 8000, 16000); sendMicData(ba); } } } catch (Exception e) { e.printStackTrace(); } finally { // 确保Recorder资源被释放 if (recorder != null) { // 先检查状态,避免在未初始化的状态下调用stop if (recorder.getState() == AudioRecord.STATE_INITIALIZED) { // 还要检查是否正在录制 if (recorder.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) { recorder.stop(); Log.d("Mic", "Call Stop: " + recorder.getState()); } } recorder.release(); recorder = null; // 置为null,避免后续误操作 Log.d("Mic", "Call Release"); Log.d("Mic", "All done state: " + recorder); } micRunning = false; } } public void stopRecording() { micRunning = false; }
2. 避免重复创建Recorder的错误逻辑
每次启动录音前,一定要确保之前的Recorder已经被完全释放:
- 在
startRecording()方法开头,先检查recorder是否不为null,如果是,先调用上面的释放逻辑 - 不要在循环内部重复创建Recorder实例,确保一个录音周期对应一个Recorder实例
3. 检查音频资源的占用情况(调试用)
如果你还是不确定资源是否泄漏,可以在创建Recorder前后,用adb命令查看系统音频资源的占用情况:
adb shell dumpsys media.audio_flinger
在输出里查找Record Tracks相关的内容,看看有没有未被释放的录音轨道。
这样修改后,应该就能解决多次运行后创建AudioRecord失败的问题了,既保证了资源的正确释放,也避免了无效的状态调用。
内容的提问来源于stack exchange,提问作者Emil Borconi
相关产品推荐
相关产品推荐

