Android AudioRecord.READ_NON_BLOCKING在三星平板上失效的解决求助
针对AudioRecord非阻塞读取在三星平板失效的解决思路
1. 调整休眠时长与读取策略
固定40ms休眠在不同设备的音频缓冲速度差异极大,三星平板可能需要更长的缓冲时间。可以尝试:
- 动态计算休眠时长:基于采样率、声道数和编码格式算出每毫秒产生的字节数,再结合当前缓冲大小估算所需缓冲时间,示例代码:
// 计算每秒采样字节数 int bytesPerSecond = sampleRate * channelCount * (ENCODING == AudioFormat.ENCODING_PCM_16BIT ? 2 : 1); // 计算填满currentBufferSize所需的最小毫秒数,再加10ms冗余 int sleepMs = (currentBufferSize * 1000 / bytesPerSecond) + 10; Thread.sleep(sleepMs); - 循环重试非阻塞读取:如果第一次
read返回0(无数据),短时间内重试2-3次,避免单次休眠不足导致读取失败:int retryCount = 3; while (retryCount > 0 && sampled == 0) { Thread.sleep(10); sampled = recorder.read(samples, 0, currentBufferSize, AudioRecord.READ_NON_BLOCKING); retryCount--; }
2. 验证AudioRecord初始化参数的设备兼容性
三星部分平板对音频参数的支持更严格,检查以下几点:
- 确认
audioSource使用MediaRecorder.AudioSource.MIC,避免使用VOICE_COMMUNICATION等小众音源; - 检查
sampleRate是否为设备支持的标准值:部分旧平板可能仅支持44100Hz而非8000Hz,可通过AudioRecord.getMinBufferSize验证参数有效性,若返回ERROR_BAD_VALUE则切换备选采样率; - 优先使用
AudioFormat.CHANNEL_IN_MONO作为声道数,双声道输入在旧设备上可能无法正常工作。
3. 改用非阻塞读取的替代方案
如果必须避免主线程阻塞,除了READ_NON_BLOCKING,还可以:
- 使用回调机制:通过
setRecordPositionUpdateListener设置监听器,当缓冲达到指定大小后触发回调,无需主动休眠:recorder.setRecordPositionUpdateListener(new AudioRecord.OnRecordPositionUpdateListener() { @Override public void onPeriodicNotification(AudioRecord recorder) { int read = recorder.read(samples, 0, currentBufferSize); // 处理读取到的音频数据 } @Override public void onMarkerReached(AudioRecord recorder) {} }); // 设置每currentBufferSize个采样点触发一次回调 recorder.setPositionNotificationPeriod(currentBufferSize / (channelCount * (ENCODING == AudioFormat.ENCODING_PCM_16BIT ? 2 : 1))); - 将读取逻辑放在独立线程中使用阻塞读取:既保证数据读取稳定性,又不会影响主线程,这也是Android官方推荐的音频录制方式。
4. 检查权限与系统限制
- 移除
CAPTURE_AUDIO_OUTPUT权限:该权限为系统级保护权限,普通应用无法获取,录音仅需RECORD_AUDIO权限,多余权限可能导致部分设备权限验证异常; - 确认运行时权限:Android 6.0及以上需动态申请
RECORD_AUDIO权限,即使Manifest中声明,也要确保应用实际获得该权限,三星设备对权限校验更严格。
内容的提问来源于stack exchange,提问作者michferrero
相关产品推荐
相关产品推荐

