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

