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!
Thanks to @CommonsWare's hint, I solved the problem. I made two changes:
For Android 7.0 and up, I used FileProvider.getUriForFile()
instead of Uri.fromFile()
as suggested by @CommonsWare.
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:
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.
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.