Android无法列出SongsManager文件夹内文件问题求助
解决Android中读取SongsManager文件夹时listFiles()返回空的问题
问题分析
你的代码在访问Environment.DIRECTORY_MUSIC根目录时能正常列出子文件夹,但进入SongsManager/子文件夹后,listFiles()返回空值,尽管该文件夹存在且标记为可读取。这主要和**Android 10+的分区存储机制(Scoped Storage)**以及权限配置有关,尤其你的targetSdk为33(Android 13),权限规则更严格。
解决方案
1. 修正权限配置与授权逻辑
- Android 13媒体权限适配:将
READ_EXTERNAL_STORAGE替换为READ_MEDIA_AUDIO,Android 13对媒体权限进行了细分,针对音频文件的读取需要专属权限:<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" /> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" /> - MANAGE_EXTERNAL_STORAGE权限的特殊授权:该权限属于系统特殊权限,无法通过普通权限申请流程获取,必须引导用户到系统设置页面手动开启:
注意:仅当应用确实需要访问所有文件时才使用此权限,优先选择分区存储兼容的API。fun checkManageStoragePermission(context: Context) { if (!Environment.isExternalStorageManager()) { val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION) intent.data = Uri.parse("package:${context.packageName}") context.startActivity(intent) } }
2. 改用MediaStore API读取音频文件
分区存储机制下,直接使用File API访问公共目录子文件夹可能受限,推荐使用MediaStore API查询音频文件:
suspend fun loadLocalSongsViaMediaStore(context: Context) { val projection = arrayOf( MediaStore.Audio.Media._ID, MediaStore.Audio.Media.DISPLAY_NAME, MediaStore.Audio.Media.DATA ) // 筛选SongsManager目录下的音频文件 val selection = "${MediaStore.Audio.Media.DATA} LIKE ?" val selectionArgs = arrayOf("%SongsManager%") context.contentResolver.query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, selection, selectionArgs, null )?.use { cursor -> val nameColumn = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME) while (cursor.moveToNext()) { val fileName = cursor.getString(nameColumn) Log.i("fileName:", fileName) } } }
3. 优化File API路径拼接
避免手动拼接路径时可能出现的分隔符错误,改用File类的构造方法直接拼接:
val baseFile = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC), "SongsManager")
4. 触发媒体文件扫描(针对新添加文件)
如果SongsManager内的文件是刚添加的,可能未被系统媒体库索引,可触发扫描更新:
fun scanMediaFolder(context: Context, folderPath: String) { MediaScannerConnection.scanFile( context, arrayOf(folderPath), arrayOf("audio/*") ) { path, uri -> Log.i("MediaScanner", "扫描完成: $path") } }
总结
优先使用MediaStore API适配分区存储规则,确保权限正确申请与授予——尤其是Android 13的细分媒体权限和MANAGE_EXTERNAL_STORAGE的特殊授权流程。若必须使用File API,务必确认用户已手动开启全文件访问权限。
内容的提问来源于stack exchange,提问作者stephen wang
相关产品推荐
相关产品推荐

