我知道有很多类似的主题,但是它们要么过时了,要么不适合pdf。
我的问题是,我如何从云firestore下载pdf并将其保存到内部存储?我的正常方法是使用下载管理器并将pdf保存到外部存储,但由于这不再工作,因为存储的作用域,我需要找到一种新的方法。
目前,我只知道如何创建一个临时文件,并从firestore下载pdf到这个临时文件,但不知道如何保存它。
旧方法(带Downloadmanager)
class PDFDownloader(private val context: Context) {
private val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
private val downloadDirectory = Environment.DIRECTORY_DOCUMENTS
private val authority = "${BuildConfig.APPLICATION_ID}.fileprovider"
private val pdfIntent = Intent(Intent.ACTION_VIEW).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
// DOWNLOADING THE PDF INTO EXTERNAL STORAGE
suspend fun downloadPDF(pdfUri: String, fileName: String) {
val pdfUrl = Firebase.storage.getReferenceFromUrl(pdfUri).downloadUrl.await()
// NOT WORKING ANYMORE BECAUSE OF SCOPED STORAGE
val request = DownloadManager.Request(pdfUrl)
.setTitle(fileName)
.setDestinationInExternalFilesDir(context, downloadDirectory, "$fileName.pdf")
downloadManager.enqueue(request)
}
// RETRIEVING THE PDF FROM EXTERNAL STORAGE
suspend fun getPDFFileAndOpen(fileName: String) {
val regex = "$fileName.pdf"
withContext(Dispatchers.IO) {
val fileList = context.getExternalFilesDir(downloadDirectory)?.listFiles()
val file = fileList?.find { it.name == regex }
pdfIntent.setDataAndType(FileProvider.getUriForFile(context, authority, file), "application/pdf")
context.startActivity(intent)
}
}
}
新方法(不含Downloadmanager)
class PDFDownloaderWithoutManager(private val context: Context) {
override suspend fun downloadPDF(uri: StorageReference, fileName: String) {
withContext(Dispatchers.IO) {
// Step 1: Creating a temporary file
val tempFile = File(context.filesDir, "$fileName.pdf")
// Step 2: Downloading the pdf from cloud-firestore into tempFile
uri.getFile(tempFile).await()
// Step 3: Saving the file into internal storage
// OR SAVING INTO EXTERNAL STORAGE WITH SCOPED STORAGE
// (I take whats easier)
?????????????????????????????????????????????????????
}
}
}
// RETRIEVING THE PDF FROM INTERNAL STORAGE
suspend fun getPDFFileAndOpen(fileName: String) {
val regex = "$fileName.pdf"
????????????????????????????????????????????????????????????
}
还有一个方法uri.getFile("URI TO SAVE FILE TO)
,但我也不知道如何使用。
编辑
使用下载管理器按预期工作,它成功地从firestore下载了文件(耶)。唯一的问题是,我不能在安卓11上打开pdf了。我得到以下错误:
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=content://com.example.app.fileprovider/external_files/Documents/Kalibrierung und Überprüfung.pdf typ=application/pdf flg=0x10000001 }
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:2067)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1727)
at android.app.ContextImpl.startActivity(ContextImpl.java:1023)
at android.app.ContextImpl.startActivity(ContextImpl.java:994)
at android.content.ContextWrapper.startActivity(ContextWrapper.java:403)
at com.example.app.business.domain.validator.document.FileLegacyValidator.openPdf(FileLegacyValidator.kt:38)
at com.example.app.business.domain.validator.document.FileLegacyValidator.openPDFFileOrNull(FileLegacyValidator.kt:35)
at com.example.app.presentation.documents.DocumentViewModel$setStateEvent$1$1.invokeSuspend(DocumentViewModel.kt:36)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
这是不工作:context.startActivity(intent)
编辑:在您最近一次编辑问题后回答不相关。
如果你打算使用外部存储,方法如下:
val isExternalStorageWritable =
(Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED)
if (!isExternalStorageWritable ) {
// handle error: Storage not available
return
}
val rootFolder = context.getExternalFilesDir(null)
val downloadsFolder = File(rootFolder, "downloads")
val isDownloadsFolderCreated = downloadsFolder.mkdirs()
if (!isDownloadsFolderCreated) {
// handle error: unable to create folder
return
}
val tempInputStream = FileInputStream(tempFile)
val targetFile = File(downloadsFolder, "targetFileName.pdf")
val isTargetFileCreated = targetFile.createNewFile()
if (!isTargetFileCreated) {
// handle error: unable to create file
return
}
FileOutputStream(targetFile).use { outputStream ->
tempInputStream.copyTo(outputStream)
}
确保从后台线程或IO协程中调用这个。
我已经修复了这个问题。我一直认为我的模拟器已经安装了PDF阅读器(因为其他模拟器也安装了),但它没有。由于没有PDF阅读器,无法打开活动。
修复:安装PDF阅读器