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
相关产品推荐
相关产品推荐

