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

Android API<23时MediaRecorder.setAudioSource调用失败问题求助

嘿,我来帮你搞定这个API低于23时MediaRecorder.setAudioSource调用失败的问题~

解决API版本低于23时MediaRecorder.setAudioSource调用失败的问题

1. 先确认权限声明的正确性

你已经添加了RECORD_AUDIO权限,但要确保它在AndroidManifest.xml的<manifest>标签下(不是<application>内部),完整的声明应该是这样的:

<uses-permission android:name="android.permission.RECORD_AUDIO" />

如果你的分贝计需要临时保存录音文件,还得加上WRITE_EXTERNAL_STORAGE权限(低版本设备可能需要),不过如果只是实时计算分贝,这个权限可以不用。

2. 调整权限检查逻辑,覆盖低版本设备

你的当前代码只处理了API23+的动态权限请求,但对于API低于23的设备,权限是安装时授予的,也存在用户后续在设置里取消权限的可能(虽然不多见)。所以修改你的startRecorder方法,把权限检查覆盖所有版本:

// 先定义一个权限请求码(类内声明即可)
private static final int REQUEST_RECORD_AUDIO_PERMISSION = 100;

public void startRecorder() {
    // 先检查录音权限,不管API版本
    if (ContextCompat.checkSelfPermission(Noise.this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            // API<23无法动态请求权限,直接提示用户去设置里开启
            Toast.makeText(Noise.this, "请前往应用设置开启录音权限哦", Toast.LENGTH_SHORT).show();
            return;
        } else {
            // API23+的动态权限请求
            ActivityCompat.requestPermissions(Noise.this, 
                new String[]{Manifest.permission.RECORD_AUDIO}, 
                REQUEST_RECORD_AUDIO_PERMISSION);
        }
    } else {
        // 权限已确认,放心初始化MediaRecorder
        initMediaRecorder();
    }
}

// 处理API23+的权限请求回调
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_RECORD_AUDIO_PERMISSION) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            initMediaRecorder();
        } else {
            Toast.makeText(this, "没有录音权限的话,分贝计没法工作哦", Toast.LENGTH_SHORT).show();
        }
    }
}

// 把MediaRecorder初始化单独抽成方法,逻辑更清晰
private void initMediaRecorder() {
    MediaRecorder recorder = new MediaRecorder();
    try {
        // 严格按照顺序初始化,低版本设备对顺序要求很高!
        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        // 用缓存目录存临时文件,不需要外部存储权限
        recorder.setOutputFile(getCacheDir().getAbsolutePath() + "/temp_noise.3gp");
        
        recorder.prepare();
        recorder.start();
        // 这里可以开始处理分贝计算逻辑啦
    } catch (IOException e) {
        e.printStackTrace();
        Toast.makeText(this, "录音器初始化失败啦", Toast.LENGTH_SHORT).show();
    }
}

3. 注意MediaRecorder的初始化顺序!

低版本设备对MediaRecorder的初始化顺序要求非常严格,必须按照创建实例 → 设置音频源 → 设置输出格式 → 设置音频编码器 → 设置输出文件 → prepare → start的顺序来,哪怕调换其中一步都可能导致调用失败,一定要检查你的代码顺序是否正确。

4. 适配特殊旧设备

有些特别老的设备可能对MediaRecorder.AudioSource.MIC支持不好,可以尝试换成MediaRecorder.AudioSource.DEFAULT试试,大部分情况下MIC是没问题的,但可以作为备选方案。

另外,旧设备尽量避免在后台启动录音,确保应用在前台时才触发录制逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:28:24