Java 向MediaMetadataRetriever中的setDataSource()发送Uri时发生IllegalArgumentException

Java 向MediaMetadataRetriever中的setDataSource()发送Uri时发生IllegalArgumentException,java,android,uri,media,Java,Android,Uri,Media,我也问过类似的问题:- 我添加了外部存储权限,或者该路径可能错误或无效。setDataSource()方法可以同时使用Context和Uri。当我发送它们时,我会收到IllegalArgumentException 以下是我发送到Uri的方法:- static List<String> getMusicNames(Context context,List<Uri> Uris){//get the music names List<String> m

我也问过类似的问题:-

我添加了外部存储权限,或者该路径可能错误或无效。
setDataSource()
方法可以同时使用
Context
Uri
。当我发送它们时,我会收到IllegalArgumentException

以下是我发送到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;
它可以是多个Uri,也可以只是一个Uri

当我调试这个程序时,会显示到方法:-
content://com.android.externalstorage.documents/document/primary%3ADownload%2F01-1085088首完整的%20Song曲目%201%20_u%20Sakkarathil%20amma.mp3

我确信音频文件在那里,我在另一个应用程序中打开了它

我从SharedReference获取Uri,如下所示:-

Uri.parse(pref.getString("gotsong",""))//get the song Uri
我在SharedReferences中设置Uri如下:-

editor.putString("gotsong", uri.toString());// save the song uri
事实上,若我并没有从共享首选项中检索,而是直接从文件中获取,那个么也并没有例外

根据甲骨文

公共类IllegalArgumentException 扩展运行时异常 抛出以指示已向方法传递非法或不适当的参数

这是原始的
setDataSource()
方法。我已经指出了引发异常的位置:-

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());
}
public void setDataSource(上下文,Uri)
抛出IllegalArgumentException、SecurityException{
if(uri==null){

抛出新的IllegalArgumentException()// 我发现问题在于,如果Uri保存在SharedReferences中而没有读写Uri的权限,则会出现IllegalArgumentException,特别是针对音频文件之类的文件的Uri Iam。因此,该方法适用于以下情况:例如,如果我直接发送文件Uri,如果我保存的文件夹路径包含共享pref中的文件,则提取URI并将其发送到该方法,或者如果我授予这些权限以在shared pref中保存文件,则检索并发送到该方法

因此,我实施了雷克的回答:

首先,我制定了“意向为行动”的开放文件:-

     intent.setType("audio/*");
                intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
                intent.addCategory(Intent.CATEGORY_OPENABLE);
在第一次获得意图后,我添加了此部分:-

     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);
-保存到共享pref.并正常检索。有趣的是,直接来自该文件的Uri如下所示:-
content://com.android.externalstorage.documents/document/primary%3ADownload%2FDeath%20Grips%20-%20Get%20Get.mp3

如果未保存在共享优先级中,则获取结果

然而,从新的意图中得到的结果看起来是这样的:-
content://com.android.providers.downloads.documents/document/433

可以拯救的人

编辑


此外,文件夹树Uri可以在没有读取Uri权限的情况下保存和检索,只有文件树需要Uri权限。我尝试从Uri树获取文件夹树,但这在获取文件时无效,Uri必须来自Intent。

它与路径中的Utf8字符串相关。 因此,在使用它之前,您需要从Utf8解码url。然后它肯定会工作

URLDecoder.decode(video, "UTF-8")
URLDecoder.decode(video, "UTF-8")