Shortcut Doesn't Launch The File In Android Q

1

Edit:

I am getting below logs in system_process when I click the pinned shortcut:

2019-10-26 20:00:16.086 2047-3533/system_process I/ActivityTaskManager: START u0 {act=android.intent.action.VIEW dat=file:///storage/emulated/0/Download/AAD.pdf typ=application/pdf flg=0x10000000 cmp=com.google.android.apps.docs/com.google.android.apps.viewer.PdfViewerActivity bnds=[439,84][641,337]} from uid 10147
2019-10-26 20:00:16.100 2047-2047/system_process W/ActivityManager: Unable to start service Intent { act=android.service.appprediction.AppPredictionService cmp=com.google.android.as/com.google.android.apps.miphone.aiai.app.AiAiPredictionService } U=0: not found
2019-10-26 20:00:16.100 2047-2047/system_process W/RemoteAppPredictionService: could not bind to Intent { act=android.service.appprediction.AppPredictionService cmp=com.google.android.as/com.google.android.apps.miphone.aiai.app.AiAiPredictionService } using flags 67108865

In short, pinned shortcut isn't getting opened in Android 10 but works in older versions. In Android 10, when I click the shortcut, Drive PDF Viewer opens but actual file is shown with black space and within a second, the app closes.

OLD:

My Android app targets API level 28. It pins shortcut of a PDF file to home screen and clicking on the icon opens the file obviously. Till Android Pie, it worked really fine. But when I tested it on API 29, clicking the icon opens the PDF Viewer and force closes with no error. Here's the relevant code.

private fun addShortcutInOreo(path1: String, pdfName: String) {
        val file = File(path1)
        try {
            Log.d("Data", file.path)
            val pdfIntent = Intent(Intent.ACTION_VIEW)

            val uri = Uri.fromFile(file)

            pdfIntent.setDataAndType(uri, "application/pdf")
            pdfIntent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
            pdfIntent.flags = Intent.FLAG_GRANT_WRITE_URI_PERMISSION

            Log.d("DataPath", uri.path)
            Log.d("DataPath", pdfName)

            if (Build.VERSION.SDK_INT > 25) {
                val shortcutManager = getSystemService(ShortcutManager::class.java)

                // Check which icon is to be pinned
                image = if (blueIcon.isChecked)
                    R.drawable.pdf
                else
                    R.drawable.pdf2

                // Create a shortcut
                val shortcut = ShortcutInfo.Builder(this, pdfName)
                        .setShortLabel(pdfName)
                        .setLongLabel(pdfName)
                        .setIcon(Icon.createWithResource(this, image))
                        .setIntent(pdfIntent)
                        .build()

                shortcutManager.requestPinShortcut(shortcut, null)
            }
        } catch (e: Exception) {
            errorMessage(e)
        }

    }

The logged data is here. First line shows file path. Second line shows the Uri. Third line simply gives the extracted File Name. I did this just to check if everything is fine with my code.

2019-08-02 13:43:14.160 3306-3306/com.parassidhu.pdfpin D/Data: /storage/emulated/0/Download/Nakal.pdf
2019-08-02 13:43:14.160 3306-3306/com.parassidhu.pdfpin D/DataPath: file:///storage/emulated/0/Download/Nakal.pdf
2019-08-02 13:43:14.160 3306-3306/com.parassidhu.pdfpin D/DataPath: Nakal

The logs are the same for API 28:

2019-08-02 13:55:07.853 5341-5341/com.parassidhu.pdfpin D/Data: /storage/emulated/0/Download/Nakal.pdf
2019-08-02 13:55:07.853 5341-5341/com.parassidhu.pdfpin D/DataPath: file:///storage/emulated/0/Download/Nakal.pdf
2019-08-02 13:55:07.853 5341-5341/com.parassidhu.pdfpin D/DataPath: Nakal

Since there's no error, I'm scratching my head as what could be gone wrong. I have read about Scoped Storage in Android Q but that doesn't apply here as I am not targeting Q. I have read about other behaviour changes in Android Q but none does apply as far as I read.

What could be the issue? Thanks for reading!

android
android-shortcutmanager
asked on Stack Overflow Aug 2, 2019 by Paras Sidhu • edited Oct 26, 2019 by Paras Sidhu

2 Answers

1

Uri.fromFile() has been effectively banned since Android 7.0, as it triggers a FileUriExposedException.

Use FileProvider in your app and FileProvider.getUriForFile() to create the Uri to use in your Intent.

answered on Stack Overflow Oct 26, 2019 by CommonsWare
1

Thanks to @CommonsWare's hint, I solved the problem. I made two changes:

  1. For Android 7.0 and up, I used FileProvider.getUriForFile() instead of Uri.fromFile() as suggested by @CommonsWare.

  2. Instead of using setFlags() (In Kotlin's syntax, it's intent.flags = <flag>), I used addFlags() and passed Intent.FLAG_GRANT_READ_URI_PERMISSION.

Explanation:

  1. The first change was really necessary since using the Uri.fromFile() method caused FileUriExposedException for Android 7.0+. Not in the app since when the shortcut is clicked, started activity doesn't belong to my app. That is why I couldn't catch it.

  2. This change was the main culprit I guess. If we don't add the given flag, the PDF opening activity (or app) doesn't have the permission to read the file contents (or uri). That is why the activity opens for a second and closes since it's unable to read the file.

Regarding the setFlags() vs addFlags(), since setFlags() removes existing flags and adds the specified flag, it didn't work. But addFlags() retains the existing flags and adds the specified flag. Hence addFlags() worked.

answered on Stack Overflow Oct 28, 2019 by Paras Sidhu

User contributions licensed under CC BY-SA 3.0