4

I had to convert a Uri to a string so that I could serialize that Uri.

Intent openFileIntent = new Intent(Intent.ACTION_GET_CONTENT);
openFileIntent.addCategory(Intent.CATEGORY_OPENABLE);
openFileIntent.setType("audio/mpeg");
startActivityForResult(openFileIntent, PICK_MP3_FILE);

...then on activity result...

public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data)
    {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == PICK_MP3_FILE)
        {
            if (resultCode == RESULT_OK)
            {
                try
                {
                    if (data != null)
                    {
                        Uri mp3AudioFile;
                        if ((mp3AudioFile = data.getData()) != null)
                        {
                            myObject.setMp3Path(mp3AudioFile.getPath());
                            myObject.Save();

                        }
                    }
                } catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        }
    }

I closed the app and opened again. When I try to open that Uri with:

Uri uri = Uri.parse(myObject.getMp3Path();

I get an error:

java.lang.SecurityException: Permission Denial: reading com.android.providers.downloads.DownloadStorageProvider uri content://com.android.providers.downloads.documents/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2Faudio.mp3 from pid=601, uid=10107 requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs

My Manifest has the following permissions:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
DevJayJay
  • 51
  • 4

3 Answers3

3

We need to provide persistent Uri permission.


JAVA

 Intent openFileIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
 openFileIntent.addCategory(Intent.CATEGORY_OPENABLE);
 openFileIntent.setType("audio/mpeg");
 startActivityForResult(openFileIntent, PICK_MP3_FILE);

Also, a note worth mentioning is persistent permission is available only to Intent.ACTION_OPEN_DOCUMENT and NOT Intent.ACTION_GET_CONTENT whereas the latter one is like a one-time thing.

Dr.jacky
  • 3,341
  • 6
  • 53
  • 91
Akin Okegbile
  • 1,108
  • 19
  • 36
  • @blackapps His problem wasn't the string or the URL generation. it was the permission to access the url. – Akin Okegbile Jul 15 '20 at 15:16
  • You should take time to edit your own answer below. Just saying. p.s. I didnt downvote you. – Akin Okegbile Jul 15 '20 at 15:38
  • `We need to provide persistent Uri permission.` As you cannot provide anything here you probably mean: `We need to receive persistent Uri permission in onActivityResult.`. – blackapps Jul 15 '20 at 15:44
  • Btw this problem just returned. If I save the filename and restart the phone I lose the permissions on that file. Can someone please help? Is there a way to perpetually grant access to mp3 file in the dowload or other folder? – DevJayJay Jul 27 '20 at 13:30
  • I was gonna give this answer. It seemed like common sense looking at the error code, but ive never implemented this type of intent so I backed off... – Nate T Jul 27 '20 at 14:19
  • @DevJayJay. Are you using ```Intent.ACTION_GET_DOCUMENT``` unknowingly? Do a global search for that just in case. – Akin Okegbile Jul 27 '20 at 14:36
  • 2
    Nevermind I just figured out what the problem was. I had to persist the permission with takePersistableUriPermission() and Intent.FLAG_GRANT_READ_URI_PERMISSION. It was actually in the documentation but I wasn't sure I was doing the correct process. Anyone out there reading this wanting to persist the permissions through reboot don't forget to use takePersistableUriPersmission()!! – DevJayJay Jul 27 '20 at 16:00
  • Look at the edit history.. It was in the original answer :p. Remind me to stick to guns next time lmao – Akin Okegbile Jul 27 '20 at 17:02
1

To do that I used getPath().

You should use toString() instead.

 String scheme = uri.toString();

 Uri uri = Uri.parse(scheme);
blackapps
  • 8,011
  • 2
  • 11
  • 25
0

The permission denial issue needs to be dealt with the first time you receive a URI.

    private val pickImage = registerForActivityResult(
        ActivityResultContracts.StartActivityForResult()
    ) { result: ActivityResult ->
        if (result.resultCode == Activity.RESULT_OK) {
            //  you will get result here in result.data
            val uri = result.data?.data!!
            requireActivity().contentResolver.takePersistableUriPermission(
                uri,
                Intent.FLAG_GRANT_READ_URI_PERMISSION
            )
            // Do something else with the URI. E.g, save the URI as a string in the database
        }
    }
Booo
  • 71
  • 1
  • 6