You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android Q写入getExternalFilesDir()子目录触发ENOENT错误原因咨询

问题原因分析与解决方案

先帮你拆解清楚这个问题的来龙去脉:

1. 先搞懂getExternalFilesDir(null)的特性

在Android Q及以上版本中,context.getExternalFilesDir(null)返回的路径是/storage/emulated/0/Android/data/[你的包名]/files——这个目录是系统为你的应用自动创建的专属存储目录,应用拥有完整读写权限,不需要额外申请存储权限,也不存在访问限制。

2. 为什么加包名子目录会触发ENOENT错误?

你之前的代码在这个已存在的目录下拼接了包名,得到路径/storage/emulated/0/Android/data/com.mp.test/files/com.mp.test,问题就出在这个com.mp.test子目录上:

  • 这个子目录并没有被提前创建
  • 看你的资产复制代码,只有当遍历到的资产是目录类型时,才会调用outDir.mkdirs()创建对应子目录;
  • 但从日志来看,第一个要处理的资产是0.key(文件类型),此时com.mp.test父目录还不存在,直接尝试创建0.key文件时,系统找不到父目录,就抛出了ENOENT (No such file or directory)错误。

说白了就是:要写的文件的父目录不存在,又没提前创建,自然写不了文件。

3. 两种解决方案

方案一:主动创建子目录再返回路径

如果确实需要这个包名子目录,在返回路径前先主动创建它:

public String getAppAssetsExtractingPath() { 
    Context context = _activity.getApplicationContext(); 
    File externalFilesDir = context.getExternalFilesDir(null);
    // 创建包名子目录
    File targetDir = new File(externalFilesDir, _activity.getPackageName());
    if (!targetDir.exists()) {
        // mkdirs会递归创建所有不存在的父目录
        targetDir.mkdirs();
    }
    return targetDir.getAbsolutePath(); 
}

方案二:直接用系统提供的专属目录

其实getExternalFilesDir(null)返回的目录本身就是和你的包名绑定的专属目录,完全不需要再额外嵌套一层包名子目录。直接用这个路径,既不会有目录不存在的问题,也符合Android Q的存储规范:

public String getAppAssetsExtractingPath() { 
    return _activity.getApplicationContext().getExternalFilesDir(null).getAbsolutePath(); 
}

这样你的资产复制代码就能正常运行,不会再触发ENOENT错误了。

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

火山引擎 最新活动