1

I have been trying to display a pdf file choosing some pdf app installed on my Android 10 mobile phone. This is the code I'm using:

Activity

        File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/sample.pdf");

                    if(file.exists()) {

                        Uri path = FileProvider.getUriForFile(this, this.getApplicationContext().getPackageName() + ".provider", file);

                        this.grantUriPermission(this.getPackageName(), path, Intent.FLAG_GRANT_READ_URI_PERMISSION);
                        Intent pdfOpenintent = new Intent(Intent.ACTION_VIEW);
                        pdfOpenintent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
                        pdfOpenintent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
                        pdfOpenintent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);


                        pdfOpenintent.setDataAndType(path, "application/pdf");


                        try {
                           // ((Activity) ctx).startActivityForResult(pdfOpenintent, 6);
                           this.startActivity(pdfOpenintent);
                        } catch (ActivityNotFoundException e) {

                        }
                    }  else
                        Toast.makeText(this, "No file found" , Toast.LENGTH_LONG).show();

AndroidManifest


    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.VIBRATE" />

........


        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths" />
        </provider>

provider_paths

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>

When I choose one of the pdf apps some of them crashes and If I choose Drive pdf Viewer it shows me the name of the file but the screen gets black, so I presume that I'm not opening in the correct way the pdf apps.

As you can see on the Activity I placed several flags, because it seems that new android versions need some kind of permissions to access internal storage.

  • See this answer https://stackoverflow.com/a/62505153/1133011 – David Kroukamp Nov 25 '20 at 04:42
  • I saw the answer but it doesn´t help me, because my pdf file is located on the download folder, so I don´t need to copy from assets, and the way it opens the pdf is the same I do and I don´t know what else is missing in my code. I found this [https://stackoverflow.com/questions/57933151/how-to-open-pdf-file-from-internal-storage-in-pie](https://stackoverflow.com/questions/57933151/how-to-open-pdf-file-from-internal-storage-in-pie) with the same issue but no correct answer. I don´t think using PdfViewPager should be the solution – user14702307 Nov 26 '20 at 18:26
  • The point of the link was to show its the exact same thing as it copies from the asset folder to the public documents folder, thereafter it opens the PDF from the documents folder which should be EXACTLY what you are doing. So if you followed the link I gave exactly and created the `GenericFileProvider` and followed all other steps I'm not sure besides asking you if you have give the permission to read and write to external storage in your manifest and that your app has granted these permissions – David Kroukamp Nov 26 '20 at 19:29
  • I updated the above code of my manifest so you can see all the permissions I have. I followed this [link](https://stackoverflow.com/questions/38200282/android-os-fileuriexposedexception-file-storage-emulated-0-test-txt-exposed/38858040#38858040) for the GenericFileProvider. On my mobile phone once the app is installed I allow the storage permission. Everything seems to be correct, but when I try to open the file with pdf reader I got the message "cannot open document" and my app doesn't crash – user14702307 Nov 26 '20 at 23:47
  • Just one more question if you try open the file yourself without your app... does it work? – David Kroukamp Nov 27 '20 at 04:18
  • Yes, it does. Furthermore I moved the pdf file to another folder thinking that maybe the problem is with the download folder and changed the external path and the "file" variable to that folder but nothing happened. – user14702307 Nov 27 '20 at 14:08

2 Answers2

0

setFlags() wipes out any previous flags that you have set on the Intent. So, you have three setFlags() calls, and only the last one matters.

Either:

  • Have one setFlags() call, or
  • Use addFlags() instead of setFlags(), at least for the second and subsequent calls
CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I kept addFlags() with read and write permission and then I kept setFlags() with read permission (in both cases I commented the other flags and grantUriPermission()) and nothing happens. It seems I'm not placing the correct permissions – user14702307 Nov 25 '20 at 01:48
  • I found this link [link](https://stackoverflow.com/questions/62486764/cant-open-file-from-intent-in-android-10) from CommonsWare where he suggested to use setFlags() with read and write permission. I did the same and nothing at all. Something is missing in my code – user14702307 Nov 25 '20 at 02:31
  • @user14702307: [This sample Java app](https://gitlab.com/commonsguy/cw-jetpack-java/-/tree/v1.1/PdfProvider) demonstrates using `FileProvider` to allow other apps to view a PDF file. – CommonsWare Nov 25 '20 at 11:46
  • I couldn´t execute your sample because of some security reasons on my office but I read your code and I guess the difference between yours and mine is that you use file-path instead of external-path in provider_paths.xml. I use the last one, because this is the way I found to get into download folder of the internal storage combining with Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS). If you recommend the file-path option I don´t know how to do the same using getFilesDir(). And I´m not quite sure whether this change will resolve my proble or not. – user14702307 Nov 26 '20 at 18:09
0

Problem solved. This code should be placed on Manifest according to this link:

<!-- This attribute is "false" by default on apps targeting
     Android 10 or higher. -->
  <application android:requestLegacyExternalStorage="true" ... >
    ...
  </application>