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 を使用して 1 つの解決策を試しました。ただし、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。存在しないContentProviderfor 権限を見つけようとします。mnt

MediaStoreを使用するのではなく、 をcontent://media/...介して排他的に取得する必要がある Urisのみを処理できます。MediaStoreUri.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 の将来のバージョンでそれが変わる可能性があります。


2番目の例は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 */);

これは、行が 0で、最初の行がないために失敗したCursorIndexOutOfBoundsException場合につながります。カーソルは最初の行の前 (-1) にとどまり、そのインデックスは存在しません。これは、ファイルがデータベースで見つからなかったことを意味します。cursorcursor.moveToFirst()

それを防ぐには、最初の行がある場合に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()行数ではなく、列数です。で要求した列数と常に同じである必要がありますcolumnscursor.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 に答える