Получение отдельного образа mp3-файла происходит слишком медленно

Я пытаюсь получить образ mp3-файла на свой телефон. Я боролся несколько дней, и теперь я знаю;

  • Во-первых, я использую поставщика контента с этим кодом

        `       Uri allSongsUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0";
                String[] projection = {
                        MediaStore.Audio.Media.TITLE,
                        MediaStore.Audio.Media.ARTIST,
                        MediaStore.Audio.Media.DATA,
                        MediaStore.Audio.Media.DISPLAY_NAME,
                        MediaStore.Audio.Media.DURATION,
                        MediaStore.Audio.Media.ALBUM,
                        MediaStore.Audio.Media.ALBUM_ID,
                        MediaStore.Audio.Media.ALBUM_KEY,
                        MediaStore.Audio.Media.DATE_MODIFIED
                };
                String sortOrder = MediaStore.Video.Media.DATE_MODIFIED + " DESC";
    

    И я создаю свой курсор так:

    Cursor cursor = ctx.getContentResolver().query(allSongsUri, projection, null, null, sortOrder);

Там у меня есть все мои mp3 файлы. Все нормально. Теперь я хочу получить их обложку.

  • Если я использую метод getEmbeddedPicture MediaMetadataRetriver, подобный этому

    mediaMetadataRetriever.setDataSource(localeMusic.getPath()); 
    localeMusic.setImage(mediaMetadataRetriever.getEmbeddedPicture());
    

    это заняло около 6-7 секунд с файлом почти 40-50. Потому что getEmbeddedPicture() слишком медленный!.

  • Также попытался получить album_id и запросить другой курсор в MediaStore.Audio.Albums, и я увидел, что все идентификаторы альбомов одинаковы, потому что все они представляют собой одну и ту же папку. Я не хочу показывать изображение их альбома. Я хочу показать обложку файла. Я пробовал это как здесь Но там мы получаем изображение альбома файла. Это не я спрашиваю.

Где я могу найти путь к изображению файла? Где класс MetadataRetriever может получить его с помощью getEmbeddedPicture? Где эта встроенная картинка?

Спасибо. С наилучшими пожеланиями


person Tayfun Cesur    schedule 13.10.2018    source источник
comment
В чем проблема моего вопроса, почему минус балл?   -  person Tayfun Cesur    schedule 16.10.2018


Ответы (2)


mediaMetadataRetriever.getEmbeddedPicture() — это нативный метод, и каждый вызов нативного метода имеет свою цену, поскольку вызовы JNI требуют времени. Таким образом, если вы повторяете такие вызовы, вы можете потерять много времени. Вы можете попытаться вызвать этот метод асинхронно по запросу и кэшировать результат. Попробуйте совместить с glide. Это решит две ваши проблемы одновременно, вызовы glide, естественно, независимы. , поэтому вам не нужно реализовывать класс AsyncTask, также он кэширует ваши изображения.

Это основное использование скольжения:

Glide.with(context).load(mediaMetadataRetriever.getEmbeddedPicture());

Я рекомендую вам прочитать документы glide. У него много других особенностей.

Надеюсь это поможет.

person Sinan Ceylan    schedule 13.10.2018
comment
Спасибо за помощь, Синан. Я попробовал ваше предложение, но теперь у меня все то же изображение. Я думаю, что мы должны использовать какое-то поле первого курсора и использовать его для второго курсора album_art. Потому что второй курсор не знает, какой альбом песен брать? Я пробовал с идентификатором альбома, но это не сработало, потому что песни, находящиеся в одной папке, имеют одинаковое изображение. - person Tayfun Cesur; 13.10.2018
comment
Уважаемый Синан, я думаю, вы перебираете курсор альбомов. Но я не хочу альбомов. Мне нужно получить индивидуальную обложку файла. - person Tayfun Cesur; 13.10.2018
comment
@TayfunCesur Я понимаю. Вы используете AsyncTask? - person Sinan Ceylan; 14.10.2018
comment
Да. Но AsyncTask в этом случае не помогает. Потому что процесс занимает слишком много времени. - person Tayfun Cesur; 14.10.2018
comment
mediaMetadataRetriever.getEmbeddedPicture() — это нативный метод, и каждый вызов нативного метода имеет свою цену, поскольку вызовы JNI требуют времени. Вы можете попробовать совместить асинхронный процесс со скольжением. github.com/bumptech/glide - person Sinan Ceylan; 14.10.2018
comment
Это точно гениальный Синан! Я объединил glide и metadataretiever следующим образом: Glide.with(context).load(mediaMetadataRetriever.getEmbeddedPicture()) и теперь он работает намного быстрее! Ты обалденный!. Я думаю, вы должны отредактировать свой ответ следующим образом, и я отмечу ваш ответ. Адамсинн :) - person Tayfun Cesur; 14.10.2018
comment
Я рад видеть, что это работает для вас. Спасибо за ваши комплименты и адамсин :). Кстати, я отредактировал свой ответ. - person Sinan Ceylan; 14.10.2018
comment
Да, glide — отличная библиотека, если у вас есть время посмотреть ее исходники. Но, Глайд не единственный, есть Пикассо и Волей. - person Sinan Ceylan; 14.10.2018
comment
Я думаю, что скольжение является лучшим из них. Гугл тоже предлагает - person Tayfun Cesur; 14.10.2018
comment
Если вы используете RecyclerView, не забудьте переопределить onViewRecycled и вызвать Glide.with(context).clear(holder.imgThumbnail);, это также ускорит работу recyclerView. - person Pierre; 14.11.2019

Вы можете получить обложку альбома, как указано здесь

https://stackoverflow.com/a/17574629/3825975

В принципе,

Cursor cursor = getContentResolver().query(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, 
                new String[] {MediaStore.Audio.Albums._ID, MediaStore.Audio.Albums.ALBUM_ART}, 
                MediaStore.Audio.Albums._ID+ "=?", 
                new String[] {String.valueOf(albumId)}, 
                null);

if (cursor.moveToFirst()) {
    String path = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ART));
    // do whatever you need to do
}

Но чтобы получить индивидуальное оформление песни, я помню, как это делал. Надеюсь, поможет.

float ht_px = TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP, 50, getResources().getDisplayMetrics());
        float wt_px = TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP, 50, getResources().getDisplayMetrics());

        Bitmap artwork, bitmap2 = null;

        MediaMetadataRetriever mmr = new MediaMetadataRetriever();
        byte[] rawArt;
        BitmapFactory.Options bfo = new BitmapFactory.Options();

        try {
            mmr.setDataSource(songUri);  //songUri is the uri of the song. You need to extract this from the song id
            rawArt = mmr.getEmbeddedPicture();
            if (rawArt != null)
                bitmap2 = BitmapFactory.decodeByteArray(rawArt, 0, rawArt.length, bfo);
            if (bitmap2 == null)
                bitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.def_icon);
            artwork = Bitmap.createScaledBitmap(bitmap2, (int) ht_px, (int) wt_px, true);   //This is the bitmap you need
        } catch (Exception e) {
            //Exception handling
        }
    }
person varunkr    schedule 13.10.2018
comment
Спасибо за ваше предложение. Мне нужно получить отдельные обложки песен, и я уже попробовал MediaMetadataRetriever. Я сказал это в своем вопросе выше. Это слишком медленный способ - person Tayfun Cesur; 13.10.2018
comment
Действительно? Возможно, вы загружали увеличенное изображение. Смотрите, я ограничил высоту и ширину. Я создал музыкальный проигрыватель, и он работал хорошо. Я уверен, что это должно работать для вашего случая. - person varunkr; 13.10.2018
comment
Дело в mmr.getEmbeddedPicture() и декодировании этого массива byre. После этого нет проблем с масштабированием - person Tayfun Cesur; 13.10.2018
comment
@TayfunCesur Хорошо, понятно. Если я правильно помню, этот процесс может быть долгим, как вы сказали. Вам нужно загрузить изображения в фоновом режиме в первый раз, а затем кэшировать их, чтобы вам не нужно было загружать их снова. Так что вам придется сделать это только один раз. После этого вы можете просто использовать их повторно. В первый раз можно сделать это в заставке или показать пользователю какой-нибудь загрузчик и т.п. - person varunkr; 13.10.2018
comment
Звучит отлично. Я не понимал, как ОС Android делает это слишком быстро. Теперь я думаю, что они делают это таким образом: D Спасибо. я попробую это - person Tayfun Cesur; 13.10.2018