android - Firebase 存储下载文件到 Android 上的 URI
问题描述
在图库或相机中选择图像后,我使用 Firebase 存储来存储图像。我有一个函数createUriForFile()
用于获取URI
在本地存储图像。选择图像后,它会存储在正确的位置,并且使用 glide 和createUriForFile()
以前一样,它会显示并正确上传到 Firebase。但是当我使用其他模拟器而不是拍摄图像的模拟器并尝试下载图像时,它会抛出一个Java.io.IOException: no such file or directory
. 我不明白为什么,因为URI
除了下载它以将其保存在设备上之外,一切都适用于特定的。
我知道 Firebase 的设置和代码是正确的,因为当我使用 aFile
作为目标而不是URI
图像时,会下载并显示图像(API <= 28)。但自 Android 29 以来,我们不能再使用直接文件访问(我想将图像存储在共享文件夹中以在图库中显示)。我知道您可以使用inputStream
,outputStream
但这似乎与getFile()
接受URI
as 参数一样有用。所以我认为这一定是我做错了。它不适用于 API 29 和 <= 28。目录是在应用程序尝试下载文件时创建的,它在保存和上传时工作,所以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 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>
推荐阅读
- android - Android Studio 和 OpenCV “编译错误”、“无法解析可样式化的符号”
- wpf - 如何在 WPF 的单列中绘制多个“堆栈”
- c# - 检查绝对uri是否包含给定相对uri的最佳方法
- javascript - Using Async/Await with Fetch in a JavaScript map function not executing in order
- c# - How can I use PlayerPrefs to save the color values of the object?
- javascript - 删除 1 行或多行后如何显示总行数然后显示总行数?
- c++ - A* 算法似乎在循环运行,我做错了什么?
- sql-server - PostgreSQL bytea to Base64 like SQL Server
- asp.net-core - 如何绑定没有 Content-Type Web API .Net core 2.1 的 POST 请求?
- c# - 删除实体框架核心中按约定添加的外键