当前位置: 首页 > 知识库问答 >
问题:

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

慕容坚
2023-03-14

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

我所知道的获取歌曲流派的方法是创建另一个带有歌曲ID的光标,如下所示:

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

但是,如果我在列出所有歌曲的光标中执行此操作,加载时间将大大增加。(我手机上的歌曲数量,从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();
}

有什么方法可以改进这段代码,以避免嵌套的光标?我已经找到了专辑艺术的解决方法。有可能以某种方式将它们结合起来吗?一个CursorJoiner是否适用于此?问题是,要想获得这一类型,你需要有媒体id。谢谢。


共有1个答案

金晗日
2023-03-14

SO用户Suhaib Roomey最近发布了这篇文章(从mediastore的audio_流派地图获取流派id和音频id)。也许它能帮助你实现目标

 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);
 类似资料:
  • 问题内容: 假设我有一个.class文件,可以获取该类中包含的所有方法吗? 问题答案: 要了解所有方法,请在控制台中使用以下语句: 要么 或例如:

  • 让我们想象一下Elasticsearch索引,其中每个文档代表一个国家。Country具有城市字段,该字段定义为嵌套的。 示例映射(为了本示例的简洁性而简化): 我插入到索引中的文档如下所示: 是否可以组成一个返回所有城市(所有国家)并支持排序的查询 第一个返回页面(回复)将包含捷克共和国的10个城市,第二个页面将包含10个城市,其中四个(最后一个)来自捷克共和国,六个来自斯洛伐克。 我正在研究复

  • 我有一个相当典型的场景,其中有一个main@实体,他内部的所有内容都是可嵌入的(因此,没有父实体,内部的所有内容都没有意义)。现在JPA 2.0阻止我在另一个@ElementCollection中定义的@Embeddeble中嵌套一个@ElementCollection: JSR-317 2.6可嵌入类和基本类型的集合包含在元素集合中的可嵌入类(包括另一个可嵌入类中的可嵌入类)不得包含元素集合,也

  • 问题内容: 我有简单的redis列表键=>“ supplier_id” 现在,我只需要它检索列表的所有值,而无需实际遍历列表或从列表中弹出该值 从列表中检索所有值的示例现在,我遍历了redis的长度 在 没有迭代的情况下 可以通过更好的redis建模来完成这件事吗?谁能建议 问题答案: 要使用Redis检索列表中的所有项目,则无需迭代和获取每个单独的项目。这确实是低效的。 您只需要使用LRANGE

  • 我在React/React native中创建了一个音乐应用程序,为此我需要一个音乐API,它能为我提供一个音乐曲目和其他与音乐相关的东西,有人能建议我一个API能这样做吗????

  • 音频播放 AudioSource 组件参考 兼容性说明