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

Android基于点击事件的5秒音频录制与保存实现咨询

Android 5秒固定时长音频录制+存储实现方案

1. 前置权限配置

首先在AndroidManifest.xml中添加对应权限,需注意不同Android版本的权限差异:

  • Android 13(API 33)及以上:添加RECORD_AUDIO、READ_MEDIA_AUDIO(仅存储到公共目录时需要)
  • Android 10(API 29)- Android 12L:添加RECORD_AUDIO、WRITE_EXTERNAL_STORAGE(仅存储到公共目录时需要)
  • Android 9及以下:添加RECORD_AUDIO、WRITE_EXTERNAL_STORAGE

录音权限属于敏感权限,必须在用户点击按钮时动态申请,授权通过后才能启动录制逻辑

2. 5秒固定时长音频录制实现

推荐使用MediaRecorder实现录制,逻辑轻量符合你的业务需求,核心实现代码如下(Kotlin示例):

// 全局变量声明
private var mediaRecorder: MediaRecorder? = null
private var recordTimer: CountDownTimer? = null
private val REQUEST_RECORD_PERM = 1001

// 交互按钮点击逻辑
recordBtn.setOnClickListener {
    // 先校验录音权限
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.RECORD_AUDIO), REQUEST_RECORD_PERM)
        return@setOnClickListener
    }
    // 初始化录制配置
    mediaRecorder = MediaRecorder().apply {
        setAudioSource(MediaRecorder.AudioSource.MIC)
        setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
        setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
        setAudioEncodingBitRate(128000)
        setAudioSamplingRate(44100)
    }
    // 生成临时输出文件(应用专属目录,无需额外权限)
    val tempAudioFile = File(getExternalFilesDir(Environment.DIRECTORY_MUSIC), "temp_record_${System.currentTimeMillis()}.m4a")
    mediaRecorder?.setOutputFile(tempAudioFile.absolutePath)
    mediaRecorder?.prepare()
    mediaRecorder?.start()
    
    // 启动5秒倒计时,到点自动停止录制
    recordTimer = object : CountDownTimer(5000, 1000) {
        override fun onTick(millisUntilFinished: Long) {
            // 可选:更新UI显示剩余录制时长
        }
        override fun onFinish() {
            stopRecord()
            // 此处tempAudioFile即为录制完成的文件,可直接传入你的自研识别算法处理
        }
    }.start()
}

// 停止录制、释放资源方法
private fun stopRecord() {
    runCatching {
        mediaRecorder?.stop()
        mediaRecorder?.release()
    }
    mediaRecorder = null
    recordTimer?.cancel()
    recordTimer = null
}

// 页面销毁时强制释放资源,避免泄漏
override fun onDestroy() {
    super.onDestroy()
    stopRecord()
}

如果你的自研算法需要原始PCM音频流处理,可以替换MediaRecorder为AudioRecord实现,直接读取录制的字节流即可。

3. 音频文件存储实现

3.1 存储到应用专属目录

该路径无需额外存储权限,仅当前应用可访问,应用卸载时文件会同步删除,适合直接供内部业务流程调用的场景
你可以直接把上述tempAudioFile重命名到你指定的应用专属目录即可,路径获取方式:

  • 外部专属目录:context.getExternalFilesDir(Environment.DIRECTORY_MUSIC)
  • 内部专属目录:context.filesDir

3.2 存储到公共音频目录

该路径下的文件可被其他应用、系统文件管理器访问,Android 10及以上无需申请存储权限,实现代码如下:

fun saveAudioToPublicDir(context: Context, sourceFile: File, saveFileName: String) {
    val contentValues = ContentValues().apply {
        put(MediaStore.Audio.Media.DISPLAY_NAME, saveFileName)
        put(MediaStore.Audio.Media.MIME_TYPE, "audio/m4a")
        put(MediaStore.Audio.Media.RELATIVE_PATH, "${Environment.DIRECTORY_MUSIC}/你的应用文件夹名")
        put(MediaStore.Audio.Media.IS_PENDING, 1)
    }
    val contentUri = context.contentResolver.insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, contentValues)
    contentUri?.let { uri ->
        context.contentResolver.openOutputStream(uri)?.use { outputStream ->
            FileInputStream(sourceFile).use { inputStream ->
                inputStream.copyTo(outputStream)
            }
        }
        // 标记文件写入完成,对其他应用可见
        contentValues.clear()
        contentValues.put(MediaStore.Audio.Media.IS_PENDING, 0)
        context.contentResolver.update(uri, contentValues, null, null)
    }
}

内容的提问来源于stack exchange,提问作者Hiếu Pham

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 02:36:08