【问题标题】:Firebase storage download file to URI on AndroidFirebase 存储下载文件到 Android 上的 URI
【发布时间】:2020-01-31 22:24:19
【问题描述】:

在图库或​​相机中选择图像后,我使用 Firebase 存储来存储它们。我有一个函数createUriForFile() 用于获取URI 以在本地存储图像。选择图像后,它会存储在正确的位置,并且使用 glide 和与以前相同的createUriForFile(),它会显示并正确上传到 Firebase。但是当我使用其他模拟器而不是拍摄图像的模拟器并尝试下载图像时,它会抛出Java.io.IOException: no such file or directory。我不明白为什么,因为除了下载它以将其保存在设备上之外,一切都适用于特定的URI

我知道 Firebase 的设置和代码是正确的,因为当我使用 File 而不是 URI 作为目标时,图像被下载并显示(API inputStream 和outputStream,但这似乎很有效,因为getFile() 接受URI 作为参数。所以我认为这一定是我做错了。它不适用于 API 29 和 URI 似乎没问题。

我已将fileprovider 添加到清单文件中,并将路径添加到 xml 文件中。

创建UriForFile:

EXTERNAL_PICTURE_RELATIVE_PATH = Environment.DIRECTORY_PICTURES + File.separator + baseActivity.getString(R.string.app_name);
EXTERNAL_PICTURE_STORAGE_DIR = baseActivity.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath() + File.separator + EXTERNAL_PICTURE_RELATIVE_PATH;

public Uri createUriForFile(String fileName, String parentId)
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
    {
        //check if there is already an entry in ContentResolver
        Uri uriFromContentResolver = getUriFromContentResolver(fileName);
        if(uriFromContentResolver != null)
        {
            return uriFromContentResolver;
        }else
        {
            ContentResolver resolver = baseActivity.getApplicationContext().getContentResolver();
            ContentValues contentValues = new ContentValues();
            contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);
            contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpg");
            contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, EXTERNAL_PICTURE_RELATIVE_PATH);
            return resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
        }
    }else
    {
        checkAndCreatePictureDir(parentId);
        File pictureFile = new File(EXTERNAL_PICTURE_STORAGE_DIR + File.separator + parentId + File.separator + fileName);

        return FileProvider.getUriForFile(baseActivity.getBaseContext(), baseActivity.getApplicationContext().getPackageName() + ".fileprovider", pictureFile);
    }
}

错误的堆栈跟踪:

E/StorageException: StorageException has occurred.
An unknown error occurred, please check the HTTP result code and inner exception for server response.
 Code: -13000 HttpResult: 200
No such file or directory
java.io.IOException: No such file or directory
    at java.io.UnixFileSystem.createFileExclusively0(Native Method)
    at java.io.UnixFileSystem.createFileExclusively(UnixFileSystem.java:281)
    at java.io.File.createNewFile(File.java:1008)
    at com.google.firebase.storage.FileDownloadTask.processResponse(com.google.firebase:firebase-storage)
    at com.google.firebase.storage.FileDownloadTask.run(com.google.firebase:firebase-storage)
    at com.google.firebase.storage.StorageTask.lambda$getRunnable$7(com.google.firebase:firebase-storage@@19.1.0:1072)
    at com.google.firebase.storage.StorageTask$$Lambda$12.run(Unknown Source:2)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    at java.lang.Thread.run(Thread.java:764)

非常感谢任何帮助或提示。

【问题讨论】:

  • 能否分享完整的堆栈跟踪,而不仅仅是第一行?
  • 添加了堆栈跟踪。

标签: android uri firebase-storage ioexception


【解决方案1】:

需要在Android Manifest中声明权限并声明元数据标签

    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths"/>
    </provider>

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <files-path
        name="external_files"
        path="." />
</paths>

【讨论】:

  • 对不起,忘了说我有这套。
【解决方案2】:

在寻找解决方案时,我仔细检查了 Firebase 文档。我发现了这个:

getFile(Uri destinationUri)
Asynchronously downloads the object at this StorageReference to a specified system filepath.

虽然我前几次没有看到它,并且它说它可以接受URI,但它显然仍然需要系统上文件的真实路径。所以我决定使用inputStreamoutputStream 通过ContentResolver 写入数据

【讨论】:

  • 但是你给出的是一个模糊的答案,你没有展示如何解决它,也没有步骤或代码。
猜你喜欢
  • 2020-01-31
  • 1970-01-01
  • 2017-08-20
  • 2017-08-22
  • 2017-02-15
  • 1970-01-01
  • 1970-01-01
  • 2017-05-06
  • 2018-08-12
相关资源
最近更新 更多