Android麦克风直连扬声器程序UI卡顿问题排查
排查Android音频传输导致UI卡顿的问题
嘿,我一眼就揪出了导致UI卡顿的核心问题,咱们一步步拆解修复:
核心问题:错误启动线程阻塞UI线程
你现在直接调用record.run(),但run()只是Thread类的普通方法,直接调用会让录音、播放的循环逻辑完全在UI线程里执行!UI线程被这个死循环占满,自然会出现卡顿、无响应——好在音频传输本身是IO操作,所以还能正常跑,但UI肯定崩了。
正确做法是调用record.start(),这才会真正创建一个后台线程来执行run()里的逻辑,不会阻塞UI线程。
其他优化细节(避免潜在问题)
除了线程启动的问题,还有几个细节能让代码更健壮:
- 用
volatile修饰isRecording:保证这个变量在多线程间的可见性,避免后台线程无法及时感知停止信号 - 添加
try-finally资源释放块:防止异常情况下AudioRecord/AudioTrack无法正常释放,导致资源泄漏 - 优化缓冲区定义:你在Record类里定义了short数组,但run()里又重新定义byte数组,统一用byte数组更贴合AudioRecord的read方法
- 增加初始化校验:创建AudioRecord/AudioTrack可能失败(比如权限没申请、设备不支持参数),需要校验状态避免崩溃
修改后的完整代码
// 先确保已申请RECORD_AUDIO权限 private volatile boolean isRecording = false; private static final int sampleRateInHz = 44100; // 建议使用标准采样率 // 初始化逻辑 int RecordBufferSize = AudioRecord.getMinBufferSize(sampleRateInHz, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); int TrackBufferSize = AudioTrack.getMinBufferSize(sampleRateInHz, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT); AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); Record record = new Record(); record.start(); // 这里改成start()! public class Record extends Thread { public void run() { isRecording = true; android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO); AudioRecord arec = null; AudioTrack atrack = null; byte[] buffer = new byte[RecordBufferSize]; try { arec = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRateInHz, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, RecordBufferSize); atrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRateInHz, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, TrackBufferSize, AudioTrack.MODE_STREAM); // 检查Audio组件是否初始化成功 if (arec.getState() != AudioRecord.STATE_INITIALIZED || atrack.getState() != AudioTrack.STATE_INITIALIZED) { throw new IllegalStateException("AudioRecord或AudioTrack初始化失败"); } atrack.setPlaybackRate(sampleRateInHz); arec.startRecording(); atrack.play(); while (isRecording) { int audioLength = arec.read(buffer, 0, RecordBufferSize); if (audioLength > 0) { atrack.write(buffer, 0, audioLength); } } } catch (Exception e) { e.printStackTrace(); } finally { // 确保资源被释放 if (arec != null) { arec.stop(); arec.release(); } if (atrack != null) { atrack.stop(); atrack.release(); } isRecording = false; } } }
额外提醒
- 别忘了在AndroidManifest.xml里添加权限:
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
- Android 6.0及以上版本需要动态申请RECORD_AUDIO权限,否则AudioRecord会初始化失败。
内容的提问来源于stack exchange,提问作者anoopknr
相关产品推荐
相关产品推荐

