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

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权限的特殊授权:该权限属于系统特殊权限,无法通过普通权限申请流程获取,必须引导用户到系统设置页面手动开启:
    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)
        }
    }
    
    注意:仅当应用确实需要访问所有文件时才使用此权限,优先选择分区存储兼容的API。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 06:50:13