MediaRecorder.prepare()调用失败抛出异常,求解决办法
解决MediaRecorder prepare()失败的问题
以下是针对你遇到的问题的具体修复步骤:
1. 修正错误的存储路径
你直接使用"/Internal storage/recorded/asdf.mp4"不符合Android存储访问规则,系统会拒绝该路径的访问请求。推荐使用应用专属外部存储目录(Android 10+无需额外写权限,且卸载应用时文件会被自动清理):
private fun startRecording(button: Button) { // 获取应用专属外部存储的音乐目录,若外部存储不可用则 fallback 到内部存储 val outputDir = getExternalFilesDir(Environment.DIRECTORY_MUSIC) ?: filesDir val recordDir = File(outputDir, "recorded") // 确保目标目录存在,不存在则创建 if (!recordDir.exists()) { recordDir.mkdirs() } val outputFile = File(recordDir, "asdf.mp4") recorder = MediaRecorder().apply { setAudioSource(MediaRecorder.AudioSource.MIC) setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) setOutputFile(outputFile.absolutePath) // 使用合法的文件路径 setAudioEncoder(MediaRecorder.AudioEncoder.AAC) try { prepare() start() button.text = "mic started" } catch (er: IllegalStateException) { button.text = "IllegalStateException" er.printStackTrace() } catch (e: IOException) { button.text = "prepare failed" Log.e(LOG_TAG, "media recorder prepare() failed", e) // 打印完整异常堆栈 } } }
2. 补充动态权限申请
Android 6.0(API 23)及以上版本,危险权限(如RECORD_AUDIO、WRITE_EXTERNAL_STORAGE)仅在Manifest中声明是不够的,必须在运行时主动申请:
第一步:确认Manifest权限
确保AndroidManifest.xml中已添加权限(适配Android 10+的存储规则):
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <!-- 仅Android 10及以下版本需要写外部存储权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
第二步:实现动态权限申请逻辑
在你的Activity中添加权限检查和申请代码:
private val REQUEST_RECORD_PERMISSIONS = 1001 private val requiredPermissions = arrayOf( Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE ) // 录音按钮点击事件绑定此方法,而非直接调用startRecording fun onRecordButtonClick(button: Button) { val missingPermissions = requiredPermissions.filter { ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED } if (missingPermissions.isNotEmpty()) { ActivityCompat.requestPermissions( this, missingPermissions.toTypedArray(), REQUEST_RECORD_PERMISSIONS ) } else { startRecording(button) } } // 处理权限申请结果 override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == REQUEST_RECORD_PERMISSIONS) { val allGranted = grantResults.all { it == PackageManager.PERMISSION_GRANTED } if (allGranted) { // 权限全部通过,启动录音(替换为你的按钮控件ID) startRecording(findViewById(R.id.your_record_button)) } else { findViewById<Button>(R.id.your_record_button).text = "权限被拒绝,无法录音" } } }
3. 确认MediaRecorder配置顺序
MediaRecorder的配置顺序必须严格遵循以下流程,否则会抛出IllegalStateException:setAudioSource → setOutputFormat → setOutputFile → setAudioEncoder
你的当前代码顺序是正确的,后续修改代码时注意不要打乱该顺序。
4. 查看完整异常日志
在IOException的catch块中,将异常对象传入Log.e方法,打印完整的异常堆栈信息,可帮助你定位具体错误原因(比如目录创建失败、路径无效等):
catch (e: IOException) { button.text = "prepare failed" Log.e(LOG_TAG, "media recorder prepare() failed", e) }
内容的提问来源于stack exchange,提问作者swaroop bappanad
相关产品推荐
相关产品推荐

