6

我正在尝试使用 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));
4

2 回答 2

15

Uri.parse("content://mnt/sdcard/Movies/landscapes.mp4")不是 的 Uri MediaStore。它会尝试寻找一个不存在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如果您cursor有 0 行并且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);
}
于 2012-11-29T13:05:58.183 回答
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);
}
于 2014-02-28T05:02:03.287 回答