Android无需嵌套游标即可获得所有音乐和流派。 (MediaStore.Audio ...)

时间:2016-10-27 18:11:15

标签: java android android-cursor mediastore

我的应用需要列出设备上的所有音乐,包括:歌曲标题,艺术家,专辑,流派等。

我知道如何获得一首歌的流派,就是用这样的歌曲ID创建另一个Cursor

Uri uri = MediaStore.Audio.Genres.getContentUriForAudioId("external", (int) id);
Cursor genresCursor = mContentResolver.query(uri, genresProjection, null, null, null);

但是,如果我在列出所有歌曲的Cursor内执行此操作,则加载时间会增加很多。 (对于我手机上的歌曲数量,从0.5秒到3秒左右)。

这是我的代码:

// If you change this to `false`, it will load a lot quicker.
private static final boolean LOAD_GENRE = true;

private static String[] mediaProjection = {
        MediaStore.Audio.AudioColumns._ID,
        MediaStore.Audio.AudioColumns.DATA,
        MediaStore.Audio.AudioColumns.TITLE,
        MediaStore.Audio.AudioColumns.ARTIST,
        MediaStore.Audio.AudioColumns.ALBUM,
        MediaStore.Audio.AudioColumns.ALBUM_ID,
        MediaStore.Audio.AudioColumns.DURATION
};
private static String[] genresProjection = {
        MediaStore.Audio.GenresColumns.NAME
};

private ArrayList<MediaMetadataCompat> getAllMusic() {
    Uri uriAudio = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
    Cursor cursor = mContentResolver.query(uriAudio, mediaProjection, null, null, null);

    if (cursor != null) {
        int count = cursor.getCount();

        if (count > 0) {
            ArrayList<MediaMetadataCompat> audioFiles = new ArrayList<>();

            while (cursor.moveToNext()) {
                MediaMetadataCompat song = buildFromCursor(cursor);
                if (song != null) {
                    audioFiles.add(song);
                }
            }
            cursor.close();

            return audioFiles;
        }
    }
    return new ArrayList<>();
}

private MediaMetadataCompat buildFromCursor(Cursor cursor, boolean loadGenre) {
    long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.AudioColumns._ID));
    String data = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.AudioColumns.DATA));
    String title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.AudioColumns.TITLE));
    String artist = ...;
    String album = ...;
    long albumId = ...;
    long duration = ...;

    //File file = new File(data);
    //if (!file.exists()) {
    //    Log.e(TAG, "Skipping song because it does not exist: " + title);
    //    return null;
    //}


    Uri uri = MediaStore.Audio.Genres.getContentUriForAudioId("external", (int) id);

    if (LOAD_GENRE) {
        String genre = null;
        Cursor genresCursor = mContentResolver.query(uri, genresProjection, null, null, null);
        if (genresCursor != null && genresCursor.moveToFirst()) {
            int genreColumnIndex = genresCursor.getColumnIndex(MediaStore.Audio.GenresColumns.NAME);
            do {
                String genreColumn = genresCursor.getString(genreColumnIndex);
                if (genre == null) {
                    genre = genreColumn;
                } else {
                    genre += " " + genre;
                }
            } while (genresCursor.moveToNext());
            genresCursor.close();
        }
    }

    // Workaround to avoid ANOTHER cursor to load album art.
    Uri albumArtUri = ContentUris.withAppendedId(Uri.parse("content://media/external/audio/albumart"), albumId);

    MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder()
            .putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, String.valueOf(id))
            .put...
            .put...;


    return builder.build();
}

有什么方法可以改进这段代码,以避免嵌套Cursor?我已经找到了专辑封面的解决方法。是否有可能以某种方式组合它们? CursorJoiner会为此工作吗?问题是要获得类型,您需要拥有媒体ID。感谢。

1 个答案:

答案 0 :(得分:0)

SO用户Suhaib Roomey最近发布了此消息 (get genre_id and audio_id from audio_genres_map from mediastore)。也许它有助于你想要实现的目标

 String[] genresProjection = {
        Audio.Genres.Members.AUDIO_ID,
        Audio.Genres.Members.GENRE_ID
 };
       context.getContentResolver().query(Uri.parse("content://media/external/audio/genres/all/members"), genresProjection, null, null, null);