/* * Copyright (C) 2017 Team Gateship-One * (Hendrik Borghorst & Frederik Luetkes) * * The AUTHORS.md file contains a detailed contributors list: * <https://github.com/gateship-one/odyssey/blob/master/AUTHORS.md> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package org.gateshipone.odyssey.utils; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.util.Pair; import org.gateshipone.odyssey.adapter.ScrollSpeedAdapter; import org.gateshipone.odyssey.artworkdatabase.ArtworkManager; import org.gateshipone.odyssey.artworkdatabase.ImageNotFoundException; import org.gateshipone.odyssey.models.AlbumModel; import org.gateshipone.odyssey.models.ArtistModel; import org.gateshipone.odyssey.models.GenericModel; import org.gateshipone.odyssey.models.TrackModel; import org.gateshipone.odyssey.viewitems.CoverLoadable; /** * Loader class for covers */ public class AsyncLoader extends AsyncTask<AsyncLoader.CoverViewHolder, Void, Bitmap> { private static final String TAG = AsyncLoader.class.getSimpleName(); private CoverViewHolder mCover; private final Context mContext; private long mStartTime; public AsyncLoader(Context context) { mContext = context; } /** * Wrapper class for covers */ public static class CoverViewHolder { public Pair<Integer, Integer> imageDimension; public CoverLoadable coverLoadable; public ArtworkManager artworkManager; public GenericModel modelItem; public ScrollSpeedAdapter mAdapter; } @Override protected Bitmap doInBackground(CoverViewHolder... params) { // Save the time when loading started for later duration calculation mStartTime = System.currentTimeMillis(); mCover = params[0]; Bitmap image = null; // Check if model item is artist or album if (mCover.modelItem instanceof ArtistModel) { ArtistModel artist = (ArtistModel) mCover.modelItem; try { // Check if image is available. If it is not yet fetched it will throw an exception // If it was already searched for and not found, this will be null. image = mCover.artworkManager.getArtistImage(artist); } catch (ImageNotFoundException e) { // Check if fetching for this item is already ongoing if (!artist.getFetching()) { // If not set it as ongoing and request the image fetch. mCover.artworkManager.fetchArtistImage(artist, mContext); artist.setFetching(true); } } } else if (mCover.modelItem instanceof AlbumModel) { AlbumModel album = (AlbumModel) mCover.modelItem; String albumURL = album.getAlbumArtURL(); if (albumURL != null && !albumURL.isEmpty()) { return decodeSampledBitmapFromResource(albumURL, mCover.imageDimension.first, mCover.imageDimension.second); } try { // Check if image is available. If it is not yet fetched it will throw an exception. // If it was already searched for and not found, this will be null. image = mCover.artworkManager.getAlbumImage(album); } catch (ImageNotFoundException e) { // Check if fetching for this item is already ongoing if (!album.getFetching()) { // If not set it as ongoing and request the image fetch. mCover.artworkManager.fetchAlbumImage(album, mContext); album.setFetching(true); } } } else if (mCover.modelItem instanceof TrackModel) { TrackModel track = (TrackModel) mCover.modelItem; // get album informations for the current track AlbumModel album = MusicLibraryHelper.createAlbumModelFromKey(track.getTrackAlbumKey(), mContext); if (album != null) { String albumURL = album.getAlbumArtURL(); if (albumURL != null && !albumURL.isEmpty()) { return decodeSampledBitmapFromResource(albumURL, mCover.imageDimension.first, mCover.imageDimension.second); } try { // Check if image is available. If it is not yet fetched it will throw an exception. // If it was already searched for and not found, this will be null. image = mCover.artworkManager.getAlbumImage(album); } catch (ImageNotFoundException e) { // Check if fetching for this item is already ongoing if (!album.getFetching()) { // If not set it as ongoing and request the image fetch. mCover.artworkManager.fetchAlbumImage(album, mContext); album.setFetching(true); } } } } return image; } /** * Resize retrieved bitmap if necessary */ private Bitmap decodeSampledBitmapFromResource(String pathName, int reqWidth, int reqHeight) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(pathName, options); // Calculate inSampleSize if (reqWidth == 0 && reqHeight == 0) { // check if the layout of the view already set options.inSampleSize = 1; } else { options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); } // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(pathName, options); } /** * Calculate sample size to resize the bitmap */ private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; // Calculate the largest inSampleSize value that is a power of 2 and // keeps both height and width larger than the requested height and width. while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) { inSampleSize *= 2; } } return inSampleSize; } @Override protected void onPostExecute(Bitmap result) { super.onPostExecute(result); // set mCover if exists if (result != null) { if (mCover.mAdapter != null) { mCover.mAdapter.addImageLoadTime(System.currentTimeMillis() - mStartTime); } mCover.coverLoadable.setImage(result); } } }