我正在尝试使用MediaStore.Video.query()方法从视频文件(标题,语言,艺术家)中检索元数据。但是,该方法始终返回null。代码如下:
String[] columns = {
MediaStore.Video.VideoColumns._ID,
MediaStore.Video.VideoColumns.TITLE,
MediaStore.Video.VideoColumns.ARTIST
};
Cursor cursor = MediaStore.Video.query(getApplicationContext().getContentResolver(), videoUri,columns);
if (cursor != null) {
cursor.moveToNext();
}
String title = cursor.getString(cursor.getColumnIndex(MediaStore.Video.VideoColumns.TITLE));
有关如何使用android返回视频元数据的任何建议吗?
==更新
当我在很多地方搜索时,我尝试了一个使用CursorLoader的解决方案。但是,CursorLoader中的方法loadInBackground()也返回null。代码如下所示:
String[] columns = {
MediaStore.Video.VideoColumns.TITLE
};
Uri videoUri = Uri.parse("content://mnt/sdcard/Movies/landscapes.mp4");
CursorLoader loader = new CursorLoader(getBaseContext(), videoUri, columns, null, null, null);
Cursor cursor = loader.loadInBackground();
cursor.moveToFirst();
String title = cursor.getString(cursor.getColumnIndex(MediaStore.Video.VideoColumns.TITLE));
答案 0 :(得分:15)
Uri.parse("content://mnt/sdcard/Movies/landscapes.mp4")
不是MediaStore
的Uri。它会尝试为不存在的权限ContentProvider
找到mnt
。
MediaStore
只能处理content://media/...
Uris,您应该通过MediaStore
专门处理,而不是Uri.parse()
。
在您的情况下,请使用以下示例
Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
String[] columns = {
MediaStore.Video.VideoColumns._ID,
MediaStore.Video.VideoColumns.TITLE,
MediaStore.Video.VideoColumns.ARTIST
};
String selection = MediaStore.Video.VideoColumns.DATA + "=?";
String selectionArgs[] = { "/mnt/sdcard/Movies/landscapes.mp4" };
Cursor cursor = context.getContentResolver().query(uri, columns, selection, selectionArgs, null);
MediaStore.Video.VideoColumns.DATA
字段包含视频的路径,您可以通过这种方式搜索某个视频。至少目前,Android的未来版本可能会改变它。
你的第二个例子是以错误的方式使用CursorLoader
。如果您自己致电loader.loadInBackground()
,则将数据加载到前台。参见例如http://mobile.tutsplus.com/tutorials/android/android-sdk_loading-data_cursorloader/
接下来你要做的是
Cursor cursor = getCursor();
cursor.moveToFirst();
String title = cursor.getString(/* some index */);
如果您的CursorIndexOutOfBoundsException
有0行且cursor
失败,则会导致cursor.moveToFirst()
,因为没有第一行。光标停留在第一行(在-1之前),并且该索引不存在。这意味着在您的情况下,在数据库中找不到该文件。
要防止使用moveToFirst
的返回值 - 如果有第一行,则只有true
。
Cursor cursor = getCursor(); // from somewhere
if (cursor.moveToFirst()) {
String title = cursor.getString(/* some index */);
}
一个更完整的示例,包括检查null
并在所有情况下关闭cursor
Cursor cursor = getCursor(); // from somewhere
String title = "not found";
if (cursor != null) {
if (cursor.moveToFirst()) {
title = cursor.getString(/* some index */);
}
cursor.close();
}
我想您尝试查找的文件要么未在数据库中编入索引(重新启动会强制索引器再次运行),要么路径错误。
或者您使用的路径实际上是符号链接,在这种情况下,MediaStore可能使用不同的路径。
使用它来摆脱符号链接
String path = "/mnt/sdcard/Movies/landscapes.mp4";
try {
path = new File(path).getCanonicalPath();
} catch (IOException e) {
e.printStackTrace();
}
是的,我现在测试了它并抛出了IndexOutOfBoundsException。当我使用cursor.getColumnCount()时,它返回1
cursor.getColumnCount()
是列数,而不是行数。它应始终与您在columns
中请求的列数相同。如果要检查行数,则需要检查cursor.getCount()
。
尝试将MediaStore已知的所有视频转储到logcat中,以防它未按预期显示。
public static void dumpVideos(Context context) {
Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
String[] projection = { MediaStore.Video.VideoColumns.DATA };
Cursor c = context.getContentResolver().query(uri, projection, null, null, null);
int vidsCount = 0;
if (c != null) {
vidsCount = c.getCount();
while (c.moveToNext()) {
Log.d("VIDEO", c.getString(0));
}
c.close();
}
Log.d("VIDEO", "Total count of videos: " + vidsCount);
}
答案 1 :(得分:2)
我更新了你的代码,它可以工作,只需检查一下
public static void dumpVideos(Context context) {
Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
String[] projection = { MediaStore.Video.VideoColumns.DATA };
Cursor c = context.getContentResolver().query(uri, projection, null, null, null);
int vidsCount = 0;
if (c != null) {
c.moveToFirst();
vidsCount = c.getCount();
do {
Log.d("VIDEO", c.getString(0));
}while (c.moveToNext());
c.close();
}
Log.d("VIDEO", "Total count of videos: " + vidsCount);
}