2

With Scoped Storage, getExternalStoragePublicDirectory is deprecated and Android documentation says

This method was deprecated in API level 29. To improve user privacy, direct access to shared/external storage devices is deprecated. When an app targets Build.VERSION_CODES.Q, the path returned from this method is no longer directly accessible to apps. Apps can continue to access content stored on shared/external storage by migrating to alternatives such as Context#getExternalFilesDir(String), MediaStore, or Intent#ACTION_OPEN_DOCUMENT.

However setDestinationInExternalPublicDir is not deprecated. Currently I am usingdownloadManager to download a pdf and save it at a folder with Downloads directory as the root (by passind dir as DIRECTORY_DOWNLOADS to setDestinationInExternalPublicDir). Then I create a FILE object using the deprecated getExternalStoragePublicDirectory() method and fire an intent for all the appropriate apps to handle PDF viewing.

My issue is, when I keep requestLegacyExternalStorage flag as true, it works fine (my target sdk is 29). However when I omit it, it works fine sometimes but other times the PDF viewer opens the file and then immediately closes it. I tried to read the file in my app itself to see what is going wrong and I got Access Denied exception. This makes sense since with scoped storage, getExternalStoragePublicDirectory() returns inaccessible path. But how is this intermittent as other times it works fine?

Adding to the question, I cannot understand why my setting requestLegacyExternalStorage flag should have any effect. All I am doing is saving the pdf using the NOT deprecated setDestinationInExternalPublicDir method in DownloadManager to a subfolder in Download directory. Then I create a FILE (yes, I know through a deprecated getExternalStoragePublicDirectory which may not be accessible - but I dont care since I am not accessing it), get uri from it and fire intent - Hence should the behaviour not solely depend on the pdf viewer apps whether they can access the legacy folders (that is if they are on API<=28 or on 29 with requestLegacyExternalStorage set as true)? - This is just for understanding the concept, surely I need to handle this and store it at some accessible location.

This brings to my last query. To handle this issue, I have an option to use MediaStore.Downloads which also downloads the file at Downloads directory. Can I still use DownloadManager to download it at that location. Android Documentation says that even for scoped storage to fire intent and give permission to other apps all we need to do is giving this permission: FLAG_GRANT_READ_URI_PERMISSION (which I am already doing). So does that mean that all paths can be this way made accessible to intent receiving apps? If not, then if MediaStore.Downloads store at Downloads directory and other apps can access it through SAF then should it not be accessible through intent firing? If yes, why my current implementation is intermittently failing.

Any lead will be highly appreciated. Thanks.

1 Answers1

-1

Then I create a FILE object using the deprecated getExternalStoragePublicDirectory() method and fire an intent for all the appropriate apps to handle PDF viewing.

That is not the way to go.

Instead you should register a broadcast receiver for ACTION_DOWNLOAD_COMPLETE.

In onReceive() you can obtain an uri for the downloaded file.

Use that uri with a grant read permission flag for your intent ACTION_VIEW.

blackapps
  • 8,011
  • 2
  • 11
  • 25