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

已存在文件仍报File does not exist异常的Android开发问题

问题原因分析

你遇到的核心问题是混淆了Content URI和本地文件路径:

  • 通过ACTION_OPEN_DOCUMENT获取的Uri是Content URI(格式为content://xxx),它指向系统文件管理器提供的内容,并非本地文件系统的真实路径。
  • 直接用uri.getPath()创建File对象,File类无法解析这种Content URI,自然会判断文件不存在。
代码错误点
  1. 错误的URI转File方式:new File(uri.getPath())完全无效,因为uri.getPath()在这里返回的是/com.android.externalstorage.documents/document/primary%3Aestonia.map,这不是本地文件系统的路径。
  2. 权限调用顺序问题:takePersistableUriPermission应该在尝试访问文件前调用,但这不是导致文件不存在的直接原因。
修复方案

根据openMap()方法的参数要求,有两种修复方式:

方式一:直接使用InputStream(推荐)

如果openMap()可以接受InputStream,直接通过ContentResolver打开流:

final ActivityResultLauncher<Intent> sARL = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
    @Override
    public void onActivityResult(ActivityResult result) {
        if (result.getResultCode() == Activity.RESULT_OK){
            Intent data = result.getData();
            assert data != null;
            Uri uri = data.getData();
            // 先获取持久权限
            getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
            
            try {
                // 打开输入流
                InputStream inputStream = getContentResolver().openInputStream(uri);
                // 假设openMap支持InputStream参数,调整方法参数即可
                openMap(inputStream);
            } catch (IOException e) {
                Log.e("File", "Failed to open file stream", e);
            }
        }
    }
});

方式二:复制到应用私有目录(如果必须用File对象)

如果openMap()只能接受File对象,需要将Content URI对应的文件复制到应用的私有存储目录,再使用这个本地文件:

final ActivityResultLauncher<Intent> sARL = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
    @Override
    public void onActivityResult(ActivityResult result) {
        if (result.getResultCode() == Activity.RESULT_OK){
            Intent data = result.getData();
            assert data != null;
            Uri uri = data.getData();
            getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
            
            try {
                // 创建应用私有目录下的临时文件
                File localFile = new File(getFilesDir(), "temp_map.map");
                // 复制文件内容
                try (InputStream in = getContentResolver().openInputStream(uri);
                     OutputStream out = new FileOutputStream(localFile)) {
                    byte[] buffer = new byte[1024];
                    int length;
                    while ((length = in.read(buffer)) > 0) {
                        out.write(buffer, 0, length);
                    }
                }
                // 现在可以用这个本地文件调用openMap
                if (localFile.exists()) {
                    openMap(localFile);
                }
            } catch (IOException e) {
                Log.e("File", "Failed to copy file", e);
            }
        }
    }
});
额外说明
  • ACTION_OPEN_DOCUMENT是基于内容提供者的文件选择方式,不要试图将其转换为真实文件路径,这在Android 10+的分区存储机制下是被限制的。
  • 持久权限takePersistableUriPermission确保你在重启应用后仍能访问该文件,这部分是正确的,但要注意调用时机。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 10:45:36