Search code examples
androidandroid-permissionsandroid-file

Downloading PDF from app is not working on Android 11


I want to download PDF in my app and show it in PDF viewer. I'm not using temp file, because I don't want to have randomized file name (on some devices it caused "file name too long" error). It is working perfectly on all devices except Android 11. (I dont even need to have storage permission turned on in app settings in order to download that PDF). But just in case I have <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> and <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> in my manifest.

It is causing this error:

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

Here is code used for downloading and parsing data to my 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?:"")
            }
        }

Solution

  • file as a Uri scheme effectively has been banned since Android 7.0. You should be crashing with a FileUriExposedException. Use FileProvider and getUriForFile() to make your content available to other apps, as they cannot access files in your app's app-specific locations on external storage.

    Then, you can get rid of whatever hack you applied to get past the FileUriExposedException.