Android Studio Kotlin:录音播放按钮点击崩溃,无法播放音频文件
录音播放失败问题排查与修复
问题根源分析
从错误提示和代码来看,导致播放失败的核心问题有以下几点:
- 文件路径无效:代码中拼接路径时出现了双斜杠
//,Environment.getExternalStorageDirectory().absolutePath本身已以/结尾,直接拼接/recorded_audio.mp3会生成/storage/emulated//0/recorded_audio.mp3这种系统无法识别的路径。 - 录制格式与文件名不匹配:点击录制时设置的输出格式是
THREE_GPP,但文件名后缀用了.mp3,3GP格式的文件无法被MediaPlayer以MP3格式解析,直接导致文件损坏。 - MediaRecorder重复初始化:初始化阶段创建了一个MediaRecorder实例,点击录制按钮时又重新new了一个,未处理旧实例可能引发资源冲突或录制逻辑异常。
- 权限缺失:如果未申请录音权限(
RECORD_AUDIO)和存储权限(Android 13及以下需WRITE_EXTERNAL_STORAGE/READ_EXTERNAL_STORAGE,Android 13+需READ_MEDIA_AUDIO),音频文件无法正常写入存储,播放时自然找不到文件。 - MediaPlayer资源泄漏:每次点击播放都新建MediaPlayer实例,但未在播放完成后释放,既浪费资源也可能引发播放异常。
修复后的完整代码
val hintBar: TextView = findViewById(R.id.hint_bar) // 用File构造方法避免路径拼接错误,统一格式为3GP匹配录制配置 val outputFile = File(Environment.getExternalStorageDirectory(), "recorded_audio.3gp") val filePath = outputFile.absolutePath recordingStatusTextView = findViewById(R.id.recording_status) startRecordingButton = findViewById(R.id.start_recording) stopRecordingButton = findViewById(R.id.stop_recording) var mediaRecorder: MediaRecorder? = null lateinit var mediaPlayer: MediaPlayer startRecordingButton.setOnClickListener { mediaRecorder?.release() // 释放旧实例,避免资源泄漏 mediaRecorder = MediaRecorder().apply { setAudioSource(MediaRecorder.AudioSource.MIC) setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP) setOutputFile(filePath) setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB) try { prepare() start() recordingStatusTextView.text = "Recording..." } catch (e: IllegalStateException) { e.printStackTrace() recordingStatusTextView.text = "录制失败: ${e.message}" } catch (e: IOException) { e.printStackTrace() recordingStatusTextView.text = "录制失败: ${e.message}" } hintBar.visibility = View.VISIBLE } } stopRecordingButton.setOnClickListener { try { mediaRecorder?.stop() mediaRecorder?.release() mediaRecorder = null recordingStatusTextView.text = "Recording Stopped" } catch (e: IllegalStateException) { e.printStackTrace() recordingStatusTextView.text = "停止失败: ${e.message}" } catch (e: IOException) { e.printStackTrace() recordingStatusTextView.text = "停止失败: ${e.message}" } hintBar.visibility = View.GONE } val playButton = findViewById<Button>(R.id.play_button) playButton.setOnClickListener { // 先释放之前的MediaPlayer实例,避免冲突 if (::mediaPlayer.isInitialized && mediaPlayer.isPlaying) { mediaPlayer.stop() mediaPlayer.release() } mediaPlayer = MediaPlayer() try { mediaPlayer.setDataSource(filePath) mediaPlayer.prepare() mediaPlayer.start() // 监听播放完成,自动释放资源 mediaPlayer.setOnCompletionListener { it.release() } } catch (e: IOException) { Toast.makeText(this, "无法播放音频文件: ${e.message}", Toast.LENGTH_SHORT).show() Log.e("MediaPlayer", e.toString()) } }
额外注意事项
- 权限申请:在AndroidManifest.xml中添加必要权限,并在运行时动态申请:
<!-- Android 12及以下 --> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Android 13+ --> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
- MP3格式录制:如果需要录制MP3格式,需调整MediaRecorder配置为
OutputFormat.MPEG_4搭配AudioEncoder.AAC,同时文件名后缀用.mp3。
内容的提问来源于stack exchange,提问作者user19297482
相关产品推荐
相关产品推荐

