【问题标题】:Getting album art for all music files获取所有音乐文件的专辑封面
【发布时间】:2014-05-15 15:46:00
【问题描述】:

我正在尝试获取手机上所有歌曲的专辑封面。我正在使用 MediaStore 来获取所有歌曲的标题、艺术家等。我应该如何获取专辑封面?我尝试使用 MediaMetaDataRetriever,但对如何将它用于多个文件感到困惑。任何人都可以调整这段代码吗?

活动类:

public void getSongList() {
    // retrieve song info
    ContentResolver musicResolver = getContentResolver();
    Uri musicUri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
    Cursor musicCursor = musicResolver.query(musicUri, null, null, null,
            null);
    metaRetriver.setDataSource(MainActivity.this,musicUri); // now how to loop over this

    if (musicCursor != null && musicCursor.moveToFirst()) {
        // get columns
        int titleColumn = musicCursor.getColumnIndex(MediaColumns.TITLE);
        int idColumn = musicCursor.getColumnIndex(BaseColumns._ID);
        int artistColumn = musicCursor.getColumnIndex(AudioColumns.ARTIST);

        // add songs to list
        do {
            long thisId = musicCursor.getLong(idColumn);
            String thisTitle = musicCursor.getString(titleColumn);
            String thisArtist = musicCursor.getString(artistColumn);
            songList.add(new Song(thisId, thisTitle, thisArtist));
        } while (musicCursor.moveToNext());

    }

【问题讨论】:

    标签: android android-mediaplayer mediastore


    【解决方案1】:

    获得专辑 ID 后,您可以从同一个光标中获取该 ID,您可以查询不同的 URI 以获取封面艺术路径。请参阅下面的示例,大致了解我是如何做到的:

    private static String getCoverArtPath(Context context, long androidAlbumId) {
        String path = null;
        Cursor c = context.getContentResolver().query(
                MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
                new String[]{MediaStore.Audio.Albums.ALBUM_ART},
                MediaStore.Audio.Albums._ID + "=?",
                new String[]{Long.toString(androidAlbumId)},
                null);
        if (c != null) {
            if (c.moveToFirst()) {
                path = c.getString(0);
            }
            c.close();
        }
        return path;
    }
    

    您可以使用类似这样的方式(未经测试)通过 id 获取所有专辑封面的地图

    private static Map<Long, String> getCoverArtPaths(Context context) {
        String HashMap<Long, String> map = new HashMap<Long, String>();
        Cursor c = context.getContentResolver().query(
                MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
                new String[]{MediaStore.Audio.Albums._ID, MediaStore.Audio.Albums.ALBUM_ART},
                null,
                null,
                null);
        if (c != null) {
            for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {
                map.add(c.getLong(0), c.getString(1));
            }
            c.close();
        }
        // returns a mapping of Album ID => art file path
        return map;
    }
    

    【讨论】:

    • 感谢马特的回答。我已经在上面发布了我的答案。但是我在 create 设备上获取大约 300 首歌曲的专辑封面时会出现 2-3 秒的延迟。有什么办法可以加快速度吗?
    • 是的,您可以在一个查询中获取所有内容。您可以删除 WHERE 参数,并遍历所有专辑,获取他们的专辑封面,或者使用专辑 ID 构建 WHERE IN 子句。请记住,如果您要使用 '?' 绑定参数,则限制为 999 个。
    • 你能给我代码怎么做吗?获取专辑封面需要很长时间。我也尝试使用 Async Task 。但仍然加载专辑封面需要时间。
    • 查看编辑 - 你应该能够得到一张地图,然后对你的路径进行简单的查找。应该在 1 个事务中查询新地图,因此应该更快。
    • 也尝试了您的解决方案。但它没有做任何改变。我猜问题出在 4 行: String pathId=map.get(thisId); metaRetriver.setDataSource(pathId);尝试 { 艺术 = metaRetriver.getEmbeddedPicture(); BitmapFactory.Options opt = new BitmapFactory.Options(); opt.inScaled=真; songImage = BitmapFactory .decodeByteArray(art, 0, art.length,opt); }
    【解决方案2】:

    我让它像这样工作。希望它可以帮助某人:)

     public void getSongList() {
        // retrieve song info
    
        ContentResolver musicResolver = getContentResolver();
        Uri musicUri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
        Cursor musicCursor = musicResolver.query(musicUri, null, null, null,
                null);
    
    
        if (musicCursor != null && musicCursor.moveToFirst()) {
            // get columns
            int titleColumn = musicCursor.getColumnIndex(MediaColumns.TITLE);
            int idColumn = musicCursor.getColumnIndex(BaseColumns._ID);
            int artistColumn = musicCursor.getColumnIndex(AudioColumns.ARTIST);
            int column_index = musicCursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
    
            // add songs to list
            do {
                long thisId = musicCursor.getLong(idColumn);
                String pathId = musicCursor.getString(column_index);
                Log.d(this.getClass().getName(), "path id=" + pathId);
    
                metaRetriver.setDataSource(pathId);
                try { 
                    art = metaRetriver.getEmbeddedPicture();
                    Options opt = new Options();
                    opt.inSampleSize = 2;
                    songImage = BitmapFactory .decodeByteArray(art, 0, art.length,opt);
                }
                catch (Exception e) 
                { imgAlbumArt.setBackgroundColor(Color.GRAY); 
                }
    
                String thisTitle = musicCursor.getString(titleColumn);
                String thisArtist = musicCursor.getString(artistColumn);
                songList.add(new Song(thisId, thisTitle, thisArtist,songImage));
                //              if(songImage!=null)
                //              {
                //              songImage.recycle();
                //              }
            } while (musicCursor.moveToNext());
    
        }
    

    【讨论】:

    • 效果很好。谢谢! +1
    【解决方案3】:

    快速渲染

    如果您使用 recylerview、listview 来渲染歌曲列表,并且由于从歌曲路径获取专辑封面而变得缓慢,那么您可以首先检查 ImageView 是否已经设置了背景图像,然后不处理任何内容。即使歌曲列表很大,它也会减少大量处理并加快滚动速度。我面临同样的问题。我只是做了同样的事情,并且专辑封面的 recyclerview 渲染变得平滑,否则它在滚动过程中卡住了。 我想这会帮助别人。

    我的 recyclerview 代码:

     @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            try {
                if (holder instanceof MusicAdapter.MusicViewHolder) {
                    MusicAdapter.MusicViewHolder vh = (MusicAdapter.MusicViewHolder) holder;
                    vh.tvTitle.setText(musicList.get(position).title.toString());
                    vh.tvArtistAndAblum.setText(musicList.get(position).artist.toString() + " | " + musicList.get(position).album.toString());
                    Drawable background = vh.ivMusicIcon.getBackground();
                    if(background == null) {
                        String pathId = musicList.get(position).path;
                        MediaMetadataRetriever metaRetriver = new MediaMetadataRetriever();
                        metaRetriver.setDataSource(pathId);
                        try {
                            byte[] art = metaRetriver.getEmbeddedPicture();
                            BitmapFactory.Options opt = new BitmapFactory.Options();
                            opt.inSampleSize = 2;
                            Bitmap songImage = BitmapFactory.decodeByteArray(art, 0, art.length,opt);
                            BitmapDrawable ob = new BitmapDrawable(context.getResources(), songImage);
                            vh.ivMusicIcon.setBackground(ob);
                        }
                        catch (Exception e)
                        {
                            vh.ivMusicIcon.setImageResource(R.drawable.compact_disc);
                        }
    
                    }
    
                } else if (holder instanceof FooterViewHolder) {
                    FooterViewHolder vh = (FooterViewHolder) holder;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2021-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-28
      • 1970-01-01
      • 2023-01-02
      • 1970-01-01
      相关资源
      最近更新 更多