Kotlin读取安卓SD卡文件夹音频文件,getExternalStorageDirectory废弃后实现求助
原因分析
- 硬编码
/sdcard/路径不兼容:不同安卓设备的外置存储挂载路径存在差异,直接写死路径大概率会出现目录找不到的问题 - 权限未真正生效:安卓6.0及以上版本仅在Manifest中声明存储权限无效,需要主动触发动态权限申请,用户同意后才能获得读取权限;安卓10及以上版本默认开启分区存储,普通应用无法直接访问外置存储根目录的公共文件夹
getExternalFilesDir()使用认知偏差:该API获取的是应用专属的外部存储目录(对应路径为外部存储/Android/data/你的应用包名/files/),仅你的应用可访问,不需要权限,适合存放应用私有文件,和原来getExternalStorageDirectory()获取的公共存储根目录定位不同
解决方法
方案1:使用应用专属目录(推荐,无需权限)
如果这些音频文件仅你的应用使用,直接用getExternalFilesDir()创建专属目录存放即可,代码示例:
fun getaudio() { // 传入"Audio"会自动在应用专属目录下创建Audio子文件夹 val appAudioDir = getExternalFilesDir("Audio") if (appAudioDir != null && appAudioDir.exists() && appAudioDir.isDirectory) { val files = appAudioDir.listFiles() Log.d("mytag", "No of files is ${files?.size ?: 0}") } }
方案2:访问公共存储的Audiobooks目录
如果需要读取其他应用存入公共目录的音频,按系统版本适配:
- Manifest配置
<!-- 安卓9及以下需要读存储权限 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- 安卓10临时绕过分区存储限制,安卓11及以上不生效 --> <application android:requestLegacyExternalStorage="true" ...> </application> - 动态申请权限
页面启动时主动申请读取存储权限,用户同意后再执行读取文件逻辑 - 修正路径与读取逻辑
不要硬编码/sdcard/,用官方API获取公共存储路径:fun getaudio() { val publicRoot = Environment.getExternalStorageDirectory().absolutePath val dir = File("$publicRoot/Audiobooks/01 Furies of Calderon") if (dir.exists() && dir.isDirectory) { val files = dir.listFiles() Log.d("mytag", "No of files is ${files?.size ?: 0}") } else { Log.d("mytag", "目录不存在,请检查路径") } } - 安卓11及以上适配
安卓11以后requestLegacyExternalStorage失效,直接用MediaStore查询公共目录的音频文件即可:fun getAudioFromPublicDir() { val projection = arrayOf( MediaStore.Audio.Media._ID, MediaStore.Audio.Media.DISPLAY_NAME, MediaStore.Audio.Media.RELATIVE_PATH ) // 筛选对应目录下的音频 val selection = "${MediaStore.Audio.Media.RELATIVE_PATH} LIKE ?" val selectionArgs = arrayOf("%Audiobooks/01 Furies of Calderon/%") contentResolver.query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, selection, selectionArgs, null )?.use { cursor -> val fileCount = cursor.count Log.d("mytag", "No of files is $fileCount") while (cursor.moveToNext()) { val fileName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME)) Log.d("mytag", "找到音频:$fileName") } } }
内容的提问来源于stack exchange,提问作者Himasnhu
相关产品推荐
相关产品推荐

