0

I went through similar questions:-

MediaMetadataRetriever setdatasource IllegalArgumentException

IllegalArgumentException in setDataSource for MediaPlayer

MediaMetadataRetriever setDataSource throws IllegalArgumentException

Log

All either proposed I add external storage permission or that path maybe wrong or invalid.The setDataSource() method can take both Context and Uri .When I send them I get IllegalArgumentException .

Here is the method I send to the Uri:-

static List<String> getMusicNames(Context context,List<Uri> Uris){//get the music names


List<String> musicNames=new ArrayList<String>();


for(Uri uri:Uris){
    MediaMetadataRetriever mData = new MediaMetadataRetriever();
    mData.setDataSource(context, uri);//<<<<<at this line the error
    musicNames.add(mData.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE));


}//returning the music names
return musicNames;

}

I send the Uri like this :-

Arrays.asList(songUri)

It can be multiple or just one Uri.

When I was debugging this the Uri that goes to the method :-content://com.android.externalstorage.documents/document/primary%3ADownload%2F01-1085088-Full%20Song-Track%201%20_%20Sakkarathil%20amma.mp3

Iam sure the audio file is there and I opened it in another app.

Uri value

I get the Uri from sharedpreferences like this:-

Uri.parse(pref.getString("gotsong",""))//get the song Uri

I set the Uri in sharedpreferences like that :-

editor.putString("gotsong", uri.toString());// save the song uri

actually there is no exception if I didn't retrieve from shared preferences and got from file directly.

According to oracle IllegalArgumentException

public class IllegalArgumentException extends RuntimeException Thrown to indicate that a method has been passed an illegal or inappropriate argument.

This is the original setDataSource() method.I've indicated where the exception is thrown :-

public void setDataSource(Context context, Uri uri)
    throws IllegalArgumentException, SecurityException {
    if (uri == null) {
        throw new IllegalArgumentException()//<<<<<<<<<<<<<<<<<<<<<<<<<<<HERE
    }

    String scheme = uri.getScheme();
    if(scheme == null || scheme.equals("file")) {
        setDataSource(uri.getPath());
        return;
    }

    AssetFileDescriptor fd = null;
    try {
        ContentResolver resolver = context.getContentResolver();
        try {
            fd = resolver.openAssetFileDescriptor(uri, "r");
        } catch(FileNotFoundException e) {
            throw new IllegalArgumentException();//<<<<<<<<<<<<<<<<<<<<<<<<<<<HERE
        }
        if (fd == null) {
            throw new IllegalArgumentException();//<<<<<<<<<<<<<<<<<<<<<<<<<<<HERE
        }
        FileDescriptor descriptor = fd.getFileDescriptor();
        if (!descriptor.valid()) {
            throw new IllegalArgumentException();//<<<<<<<<<<<<<<<<<<<<<HERE
        }
        // Note: using getDeclaredLength so that our behavior is the same
        // as previous versions when the content provider is returning
        // a full file.
        if (fd.getDeclaredLength() < 0) {
            setDataSource(descriptor);
        } else {
            setDataSource(descriptor, fd.getStartOffset(), fd.getDeclaredLength());
        }
        return;
    } catch (SecurityException ex) {
    } finally {
        try {
            if (fd != null) {
                fd.close();
            }
        } catch(IOException ioEx) {
        }
    }
    setDataSource(uri.toString());
}

Obviously the Uri is not null so its one of these other 3 reasons which one in FileNotFoundException ,and the other 2 I don't understand.

My issue is actually similar to this question :-Save uri to sharedPreferences and play with mediaplayer

Omar Boshra
  • 447
  • 7
  • 21

2 Answers2

1

I found out the problem was that IllegalArgumentException comes if the Uri was saved in Sharedpreferences without permission to read and write Uri specifically the Uri Iam targeting for a file like audio file .So the method works for e.g if I send file Uri directly , If I save the folder path that has the files in shared pref then extract the Uris and sent them to the method or if I make these permissions to save a file in shared pref then retrieve and send to the method.

so I implemented Recek's answer :-

https://stackoverflow.com/a/46506626/7552894

First I made the intend as ACTION_OPEN_DOCUMENT:-

     intent.setType("audio/*");
                intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
                intent.addCategory(Intent.CATEGORY_OPENABLE);

Where I added this part after getting the intent first time:-

     this.grantUriPermission(this.getPackageName(), data.getData(), Intent.FLAG_GRANT_READ_URI_PERMISSION);
        final int takeFlags = data.getFlags()
                & (Intent.FLAG_GRANT_READ_URI_PERMISSION
                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);            // Check for the freshest data.
        //noinspection WrongConstant
        this.getContentResolver().takePersistableUriPermission(data.getData(), takeFlags);

-saved to shared pref .And retrieved normally.Whats interesting is that the Uri that comes directly from the file looks like so:-content://com.android.externalstorage.documents/document/primary%3ADownload%2FDeath%20Grips%20-%20Get%20Got.mp3

gets result if not saved in shared pref.

However the one got from the new intent looks liks so:- content://com.android.providers.downloads.documents/document/433

the one that can be saved.

Edit

also folder tree Uri can be saved and retrieved without the read Uri permissions ,only file tree needs Uri permission.I tried to get folder tree from Uri tree But that doesn't work in getting the files ,the Uri must come from Intent.

Omar Boshra
  • 447
  • 7
  • 21
0

It is related to Utf8 string in your path. So before using it, you need to decode the url from Utf8. Then it surely works.

URLDecoder.decode(video, "UTF-8")
Ares
  • 2,504
  • 19
  • 19