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

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;
        }
    }
}

额外提醒

  1. 别忘了在AndroidManifest.xml里添加权限:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
  1. Android 6.0及以上版本需要动态申请RECORD_AUDIO权限,否则AudioRecord会初始化失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:14:37