将 Uri 发送到 MediaMetadataRetriever 中的 setDataSource() 时出现 IllegalArgumentException
IllegalArgumentException when sending Uri to setDataSource() in MediaMetadataRetriever
我遇到过类似的问题:-
MediaMetadataRetriever setdatasource IllegalArgumentException
IllegalArgumentException in setDataSource for MediaPlayer
MediaMetadataRetriever setDataSource throws IllegalArgumentException
所有建议我添加外部存储权限或该路径可能错误或 invalid.The 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 :-
Arrays.asList(songUri)
可以是多个也可以只有一个Uri。
当我调试这个方法的 Uri 时:-content://com.android.externalstorage.documents/document/primary%3ADownload%2F01-1085088-Full%20Song-Track%201%20_%20Sakkarathil%20amma.mp3
我确定音频文件在那里,我在另一个应用程序中打开了它。
我从 sharedpreferences 中获取 Uri 是这样的:-
Uri.parse(pref.getString("gotsong",""))//get the song Uri
我在 sharedpreferences 中这样设置 Uri :-
editor.putString("gotsong", uri.toString());// save the song uri
其实如果我不是从共享首选项中检索而是直接从文件中获取,也不例外。
public class IllegalArgumentException
extends RuntimeException
Thrown to indicate that a method has been passed an illegal or inappropriate argument.
这是原来的 setDataSource()
method.I 指出异常抛出的地方 :-
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());
}
显然 Uri 不为空,所以它是其他 3 个原因之一,其中一个在 FileNotFoundException 中,另外两个我不明白。
我的问题其实和这个问题类似:-Save uri to sharedPreferences and play with mediaplayer
我发现问题是如果 Uri 被保存在 Sharedpreferences 中而没有读取和写入 Uri 的权限,特别是 Uri Iam 针对音频文件之类的文件,那么该方法适用于例如我发送文件Uri 直接,如果我保存在共享 pref 中包含文件的文件夹路径,然后提取 Uris 并将它们发送到该方法,或者如果我授予这些权限以在共享 pref 中保存 file 然后检索并发送到方法。
所以我实现了 Recek 的回答:-
首先我的意图是ACTION_OPEN_DOCUMENT:-
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);
-保存到共享首选项。并检索 normally.Whats 有趣的是,直接来自文件的 Uri 如下所示:-content://com.android.externalstorage.documents/document/primary%3ADownload%2FDeath%20Grips%20-%20Get%20Got.mp3
如果未保存在共享首选项中,则获取结果。
然而,从新 Intent 中得到的结果看起来是这样的:- content://com.android.providers.downloads.documents/document/433
能救的那个
编辑
也可以在没有读取 Uri 权限的情况下保存和检索文件夹树 Uri,只有文件树需要 Uri permission.I 试图从 Uri 树获取文件夹树但是这在获取文件时不起作用,the Uri 必须来自 Intent。
与你的路径中的utf8字符串有关。
所以在使用它之前,你需要从 Utf8 中解码 url。那肯定有用。
URLDecoder.decode(video, "UTF-8")
我遇到过类似的问题:-
MediaMetadataRetriever setdatasource IllegalArgumentException
IllegalArgumentException in setDataSource for MediaPlayer
MediaMetadataRetriever setDataSource throws IllegalArgumentException
所有建议我添加外部存储权限或该路径可能错误或 invalid.The 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 :-
Arrays.asList(songUri)
可以是多个也可以只有一个Uri。
当我调试这个方法的 Uri 时:-content://com.android.externalstorage.documents/document/primary%3ADownload%2F01-1085088-Full%20Song-Track%201%20_%20Sakkarathil%20amma.mp3
我确定音频文件在那里,我在另一个应用程序中打开了它。
我从 sharedpreferences 中获取 Uri 是这样的:-
Uri.parse(pref.getString("gotsong",""))//get the song Uri
我在 sharedpreferences 中这样设置 Uri :-
editor.putString("gotsong", uri.toString());// save the song uri
其实如果我不是从共享首选项中检索而是直接从文件中获取,也不例外。
public class IllegalArgumentException extends RuntimeException Thrown to indicate that a method has been passed an illegal or inappropriate argument.
这是原来的 setDataSource()
method.I 指出异常抛出的地方 :-
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());
}
显然 Uri 不为空,所以它是其他 3 个原因之一,其中一个在 FileNotFoundException 中,另外两个我不明白。
我的问题其实和这个问题类似:-Save uri to sharedPreferences and play with mediaplayer
我发现问题是如果 Uri 被保存在 Sharedpreferences 中而没有读取和写入 Uri 的权限,特别是 Uri Iam 针对音频文件之类的文件,那么该方法适用于例如我发送文件Uri 直接,如果我保存在共享 pref 中包含文件的文件夹路径,然后提取 Uris 并将它们发送到该方法,或者如果我授予这些权限以在共享 pref 中保存 file 然后检索并发送到方法。
所以我实现了 Recek 的回答:-
首先我的意图是ACTION_OPEN_DOCUMENT:-
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);
-保存到共享首选项。并检索 normally.Whats 有趣的是,直接来自文件的 Uri 如下所示:-content://com.android.externalstorage.documents/document/primary%3ADownload%2FDeath%20Grips%20-%20Get%20Got.mp3
如果未保存在共享首选项中,则获取结果。
然而,从新 Intent 中得到的结果看起来是这样的:- content://com.android.providers.downloads.documents/document/433
能救的那个
编辑
也可以在没有读取 Uri 权限的情况下保存和检索文件夹树 Uri,只有文件树需要 Uri permission.I 试图从 Uri 树获取文件夹树但是这在获取文件时不起作用,the Uri 必须来自 Intent。
与你的路径中的utf8字符串有关。 所以在使用它之前,你需要从 Utf8 中解码 url。那肯定有用。
URLDecoder.decode(video, "UTF-8")