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

Android Kotlin中如何封装自定义MediaRecorder?新手代码相关咨询

嘿,作为Kotlin新手,封装自定义MediaRecorder确实能让你的代码更整洁、复用性更强,还能把录制相关的逻辑都集中管理起来。我来给你一步步实现一个实用的封装类,适配你的场景~

1. 创建自定义音频录制封装类

我们可以写一个CustomAudioRecorder类,把初始化、开始录制、停止录制、释放资源这些核心逻辑都封装进去,还能处理空安全和异常:

import android.media.MediaRecorder
import android.os.Build
import java.io.File
import java.io.IOException

class CustomAudioRecorder private constructor(
    private val outputFile: File
) {
    private var mediaRecorder: MediaRecorder? = null
    var isRecording = false
        private set

    // 伴生对象,提供创建实例的方法(处理初始化失败的情况)
    companion object {
        fun create(outputFilePath: String): CustomAudioRecorder? {
            val outputFile = File(outputFilePath)
            // 确保父目录存在
            outputFile.parentFile?.let { parent ->
                if (!parent.exists() && !parent.mkdirs()) {
                    return null
                }
            }
            return try {
                CustomAudioRecorder(outputFile)
            } catch (e: IOException) {
                e.printStackTrace()
                null
            }
        }
    }

    init {
        initMediaRecorder()
    }

    private fun initMediaRecorder() {
        mediaRecorder = MediaRecorder().apply {
            // 设置音频源为麦克风
            setAudioSource(MediaRecorder.AudioSource.MIC)
            // 设置输出格式为MPEG_4
            setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
            // 注意:你原来的代码写错了!应该设置音频编码器,不是输出格式
            setAudioEncoder(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                MediaRecorder.AudioEncoder.AAC_ELD
            } else {
                MediaRecorder.AudioEncoder.AAC
            })
            // 设置输出文件路径
            setOutputFile(outputFile.absolutePath)
            // 准备录制
            prepare()
        }
    }

    // 开始录制
    fun startRecording(): Boolean {
        return try {
            mediaRecorder?.start()
            isRecording = true
            true
        } catch (e: IllegalStateException) {
            e.printStackTrace()
            false
        }
    }

    // 停止录制
    fun stopRecording() {
        if (isRecording) {
            try {
                mediaRecorder?.stop()
            } catch (e: IllegalStateException) {
                // 处理录制未开始就停止的异常
                e.printStackTrace()
            } finally {
                isRecording = false
            }
        }
    }

    // 释放资源(一定要调用,避免内存泄漏)
    fun release() {
        mediaRecorder?.reset()
        mediaRecorder?.release()
        mediaRecorder = null
    }
}
2. 在你的AudioRecorderDialogFragment中使用封装类

现在你可以替换原来的startVoiceRecorder方法,用这个封装类来简化逻辑:

import android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.fragment.app.DialogFragment

class AudioRecorderDialogFragment : DialogFragment() {
    private var customRecorder: CustomAudioRecorder? = null

    fun startVoiceRecorder(voiceFilename: String) {
        // 先检查权限(RECORD_AUDIO和存储权限,记得在Manifest里声明)
        if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.RECORD_AUDIO)
            != PackageManager.PERMISSION_GRANTED ||
            ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED
        ) {
            // 请求权限,这里可以自己实现权限请求逻辑
            requestPermissions(arrayOf(Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE), 1001)
            return
        }

        // 创建录制实例
        customRecorder = CustomAudioRecorder.create(voiceFilename)?.apply {
            // 开始录制
            if (!startRecording()) {
                // 处理录制启动失败的情况,比如弹Toast提示用户
                Toast.makeText(requireContext(), "录制启动失败", Toast.LENGTH_SHORT).show()
                release()
                customRecorder = null
            }
        }
    }

    // 停止录制的方法(比如用户点击停止按钮时调用)
    fun stopVoiceRecorder() {
        customRecorder?.stopRecording()
        customRecorder?.release()
        customRecorder = null
    }

    // 别忘了在Fragment生命周期结束时释放资源
    override fun onDestroy() {
        super.onDestroy()
        customRecorder?.release()
        customRecorder = null
    }
}
一些关键注意点
  • 权限处理:一定要在AndroidManifest.xml中声明RECORD_AUDIO和存储权限,并且在运行时请求,否则录制会失败。
  • 编码器修正:你原来的代码里setAudioEncoder用了MediaRecorder.OutputFormat.MPEG_4,这是错误的,应该用AudioEncoder枚举里的值,我在封装类里已经修正了。
  • 资源释放:必须在不需要录制的时候调用release()方法,避免内存泄漏和占用系统资源。
  • 异常处理:封装类里加了异常捕获,避免因为初始化失败、录制状态异常导致崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:16:45