如何使用MediaStore API结合AudioRecord实现安卓音频录制
AudioRecord适配MediaStore API实现方案
前置依赖配置
- Android 6.0及以上版本需动态申请
RECORD_AUDIO权限 - Android 9及以下版本额外需要申请
WRITE_EXTERNAL_STORAGE权限 - TargetSdk >= 29(Android 10)无需申请存储权限,直接使用MediaStore操作公共媒体目录即可
适配后完整代码
原有AudioRecord的采集逻辑完全复用,仅修改文件写入相关的逻辑即可,适配后代码如下:
// 1. 构造MediaStore音频元数据,代替原有直接创建本地File的逻辑 ContentValues audioValues = new ContentValues(); audioValues.put(MediaStore.Audio.Media.DISPLAY_NAME, "test.pcm"); audioValues.put(MediaStore.Audio.Media.MIME_TYPE, "audio/pcm"); // API 29及以上可以指定存储子路径,低版本可删除该行,默认存至Music根目录 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { audioValues.put(MediaStore.Audio.Media.RELATIVE_PATH, Environment.DIRECTORY_MUSIC + "/CustomRecord"); // 录制过程中标记为待处理,避免其他应用访问 audioValues.put(MediaStore.Audio.Media.IS_PENDING, 1); } // 2. 插入元数据获取音频Uri Uri audioUri = getContentResolver().insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, audioValues); if (audioUri == null) { // 插入失败处理逻辑 return; } try { // 3. 通过Uri打开输出流,替换原有FileOutputStream OutputStream outputStream = getContentResolver().openOutputStream(audioUri); BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream); DataOutputStream dataOutputStream = new DataOutputStream(bufferedOutputStream); // 以下AudioRecord采集逻辑和原有实现完全一致,无需修改 int minBufferSize = AudioRecord.getMinBufferSize(11025, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT); short[] audioData = new short[minBufferSize]; AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, 11025, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize); audioRecord.startRecording(); while(recording){ int numberOfShort = audioRecord.read(audioData, 0, minBufferSize); for(int i = 0; i < numberOfShort; i++){ dataOutputStream.writeShort(audioData[i]); } } if(!recording){ audioRecord.stop(); dataOutputStream.close(); audioRecord.release(); // 建议补充资源释放逻辑 } // 4. 录制完成后更新状态,通知系统文件已可访问 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { ContentValues updateValues = new ContentValues(); updateValues.put(MediaStore.Audio.Media.IS_PENDING, 0); getContentResolver().update(audioUri, updateValues, null, null); } } catch (IOException e) { e.printStackTrace(); }
关键修改说明
仅文件存储逻辑做了适配,AudioRecord采集逻辑完全保留,不影响你自定义采样率、声道、位深的需求。
- 不再直接构造本地File对象,改为先向MediaStore插入音频元数据获取对应的Uri,通过Uri操作文件
- 输出流从直接读取本地文件路径改为通过
ContentResolver.openOutputStream(uri)获取 - 新增录制状态标记
IS_PENDING,避免录制过程中其他应用扫描到未完成的音频文件
注意事项
- 如果需要生成可直接播放的WAV格式文件,只需在PCM数据写入完成后,在文件开头补充对应参数的WAV头信息即可,MediaStore相关逻辑无需修改
- 后续访问录制的音频可以直接使用返回的
audioUri,无需再通过本地文件路径读取 - 低版本Android系统兼容只需删除
RELATIVE_PATH和IS_PENDING相关的版本判断逻辑即可,其余代码通用
内容的提问来源于stack exchange,提问作者Abdellah SAYOUL
相关产品推荐
相关产品推荐

