Android 11 从应用程序下载 PDF 无效

Downloading PDF from app is not working on Android 11

我想在我的应用程序中下载 PDF 并在 PDF 查看器中显示它。我没有使用临时文件,因为我不想使用随机文件名(在某些设备上它会导致“文件名太长”错误)。它在除 Android 11 以外的所有设备上都能完美运行。(我什至不需要在应用程序设置中打开存储权限即可下载该 PDF)。但以防万一我的清单中有 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

它导致了这个错误:

open failed: EACCES (Permission denied) Can't open file

这是用于下载数据并将其解析为我的 PDF 的代码:

val dlg = Dialog(a).apply {
            setMessage(R.string.downloading)
            setNegativeButton {
                downloadTask?.cancel()
            }
            show()
        }
        downloadTask = asyncTask({
            try {
                val dir = app.externalCacheDir!!
                dir.mkdirs()
                File(dir, "client-invoice.pdf").also { f ->
                    f.deleteOnExit()
                    URL(receiptUrl).openStream().use { s ->
                        FileOutputStream(f).use { d ->
                            s.copyTo(d)
                        }
                    }
                }
            } catch (e: IOException) {
                e
            }
        }, onDone = {
            downloadTask = null
            dlg.dismiss()
        }){ r->
            try {
                if (r is Exception) {
                    throw r
                } else if (r is File) {
                    tempFile = r
                    val int = Intent(Intent.ACTION_VIEW).apply {
                        setDataAndType(Uri.parse("file://" + r.absolutePath), "application/pdf")
                    }
                    startActivityForResult(int, 1)
                }
            } catch (e: ActivityNotFoundException) {
                tempFile?.delete()
                a.openPlayStoreLinkWithDialog("com.google.android.apps.pdfviewer", "PDF")
            } catch (e: Exception) {
                app.showToast(e.message?:"")
            }
        }

file 作为 Uri 方案实际上已从 Android 7.0 开始被禁止。你应该崩溃 FileUriExposedException。使用 FileProvidergetUriForFile() 让其他应用可以访问您的内容,因为它们无法访问您应用在外部存储上的应用特定位置中的文件。

然后,您可以摆脱为通过 FileUriExposedException.

而应用的任何 hack