Android11/12(targetSDK31)react-native-audio-recorder-player权限问题求助
解决方案:适配Android 11+ Scoped Storage,无需降低TargetSDKVersion
核心问题分析
你遇到的权限拒绝问题本质是Android 10(API 29)引入的Scoped Storage机制在TargetSDKVersion 31+时强制生效,直接写入sdcard/根目录属于被禁止的操作——哪怕添加requestLegacyExternalStorage或MANAGE_EXTERNAL_STORAGE也无法绕过(后者仅对文件管理器类应用开放,且Google Play会拒绝非必要使用该权限的应用)。
具体解决步骤
1. 清理无效权限配置
打开AndroidManifest.xml,删除以下无效配置:
android:requestLegacyExternalStorage="true"(TargetSDK 31+完全忽略该属性)android.permission.MANAGE_EXTERNAL_STORAGE(非合规场景会导致Play Store审核失败)
仅保留必要权限:
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <!-- Android 12及以下如需读取公共媒体库,保留此权限;Android 13+替换为READ_MEDIA_AUDIO --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
2. 修改音频存储路径:使用应用私有目录
直接写入应用私有目录无需额外存储权限(仅需RECORD_AUDIO),且不会触发Scoped Storage限制,是最优方案。
React Native端代码修改
借助react-native-fs获取应用外部私有目录,将录音路径指向该目录:
import AudioRecorderPlayer from 'react-native-audio-recorder-player'; import RNFS from 'react-native-fs'; const audioRecorderPlayer = new AudioRecorderPlayer(); // 获取应用外部私有音频存储目录 const getValidAudioPath = async () => { const dirPath = `${RNFS.ExternalDirectoryPath}/AudioRecords`; // 确保目录存在 await RNFS.mkdir(dirPath).catch(() => {}); return `${dirPath}/sound_${Date.now()}.mp3`; }; // 启动录音 const startRecording = async () => { const audioPath = await getValidAudioPath(); try { await audioRecorderPlayer.startRecorder(audioPath); console.log(`录音启动,路径:${audioPath}`); } catch (error) { console.error('录音失败:', error); } };
如果需要将录音文件同步到公共媒体库(如系统音乐文件夹),可通过MediaStore插入文件(无需WRITE_EXTERNAL_STORAGE权限,Android 10+自动授权),需补充原生模块或第三方库实现文件插入逻辑。
3. 确保动态申请RECORD_AUDIO权限
在启动录音前,必须动态申请录音权限:
import { PermissionsAndroid } from 'react-native'; const requestRecordPermission = async () => { const granted = await PermissionsAndroid.request( PermissionsAndroid.PERMISSIONS.RECORD_AUDIO, { title: '录音权限申请', message: '应用需要录音权限以录制音频', buttonNegative: '取消', buttonPositive: '允许', }, ); return granted === PermissionsAndroid.RESULTS.GRANTED; }; // 先申请权限再启动录音 const initRecording = async () => { const hasPermission = await requestRecordPermission(); if (hasPermission) { await startRecording(); } else { console.log('用户拒绝录音权限'); } };
4. 升级依赖库(可选)
当前使用的^3.5.3版本可能存在Scoped Storage适配遗留问题,建议升级到react-native-audio-recorder-player最新稳定版(查看Release Notes确认路径相关修复)。
验证效果
完成上述修改后,保持TargetSDKVersion为31,在Android 11/12设备上测试:
- 无权限拒绝错误,录音功能正常
- 符合Google Play的TargetSDKVersion要求(需≥31)
- 避免了降SDK带来的性能卡顿问题
内容的提问来源于stack exchange,提问作者Syed Ali Sultan Bukhari
相关产品推荐
相关产品推荐

