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

Android 11+下应用自有文件列表失效(compileSdk升级至35后)

问题描述

我将mp3、mp4、jpg及应用自有aw格式文件存储在应用的cache目录中,使用如下代码清理临时文件:

private fun deleteTmp() {
    val rootFolder = File(context.cacheDir.absolutePath)
    val mp4 = ".*\\.mp4"
    val mp3 = ".*\\.mp3"
    val jpg = ".*\\.jpg"
    val gif = ".*\\.gif"
    val aw = ".*\\.aw"
    val folder = File("$rootFolder/")
    val files = folder.listFiles { _, name ->
        (name.matches(mp4.toRegex()) || name.matches(mp3.toRegex())
                || name.matches(jpg.toRegex()) || name.matches(gif.toRegex()) || name.matches(aw.toRegex()))
    }
    if (files != null) {
        for (file in files) {
            file.delete()
        }
    }
}

compileSdk从29升级至35前代码运行正常,升级后listFiles仅能获取文件夹,无法识别文件。已知访问应用自有文件无需权限,且这些文件均为自行创建。尝试使用filesDir无效,直接调用context.cacheDir.listFiles()同样仅返回文件夹(路径为/data/user/0/com.xxx.xxx/cache)。不想向用户申请权限,希望找到应用内部操作的解决方法。

可行解决方法
  • 改用Files.walk遍历目录
    放弃listFiles,使用Java NIO的Files.walk遍历cache目录,高版本Android兼容性更好,能准确获取所有文件和文件夹,过滤目标格式后删除:

    private fun deleteTmp() {
        val cachePath = context.cacheDir.toPath()
        Files.walk(cachePath)
            .filter { path ->
                val fileName = path.fileName.toString()
                fileName.endsWith(".mp4") || fileName.endsWith(".mp3") ||
                fileName.endsWith(".jpg") || fileName.endsWith(".gif") || fileName.endsWith(".aw")
            }
            .forEach { path ->
                try {
                    Files.delete(path)
                } catch (e: IOException) {
                    // 处理删除失败场景,比如文件被占用
                    e.printStackTrace()
                }
            }
    }
    
  • 检查文件实际存储路径
    确认文件是否真的在cacheDir根目录,而非子文件夹。升级compileSdk后,部分文件创建逻辑可能因路径处理变化导致文件存入子目录,原代码仅遍历根目录会遗漏。可打印cache目录所有内容验证:

    private fun checkCacheFiles() {
        Files.walk(context.cacheDir.toPath())
            .forEach { path ->
                Log.d("CacheFileCheck", path.toString())
            }
    }
    

    若文件在子目录,需调整遍历范围或修改文件创建时的存储路径。

  • 替换listFiles的过滤器逻辑
    改用FileFilter直接判断File对象是否为文件且符合后缀,避免仅通过文件名匹配的误判:

    private fun deleteTmp() {
        val folder = context.cacheDir
        val files = folder.listFiles { file ->
            file.isFile && (
                file.name.endsWith(".mp4") || file.name.endsWith(".mp3") ||
                file.name.endsWith(".jpg") || file.name.endsWith(".gif") || file.name.endsWith(".aw")
            )
        }
        files?.forEach { it.delete() }
    }
    
  • 同步升级targetSdkVersion
    若仅升级compileSdk而targetSdkVersion停留在29,可能出现行为不一致。建议将targetSdkVersion同步升级到35,确保应用行为符合高版本Android规范,减少兼容性问题。

内容的提问来源于stack exchange,提问作者Diego Perez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 00:22:36