/** {@inheritDoc} */ @Override public List<Album> loadInBackground() { final ArrayList<Album> mAlbumsList = Lists.newArrayList(); // Create the Cursor Cursor mCursor; try { mCursor = makeCursor(getContext()); } catch (Throwable e) { return Collections.EMPTY_LIST; } // Gather the data if (mCursor != null && mCursor.moveToFirst()) { do { mAlbumsList.add(getAlbumEntryFromCursor(mCursor)); // String an = mCursor.getString(1) != null ? mCursor.getString(1) : "n/a"; // String art = mCursor.getString(2) != null ? mCursor.getString(2) : "n/a"; // LOGGER.info("Adding id: " + mCursor.getLong(0) + " - albumName: " + an + " - artist: " + // art); } while (mCursor.moveToNext()); } // Close the cursor if (mCursor != null) { mCursor.close(); } return mAlbumsList; }
/** * This {@link ArrayAdapter} is used to display the albums for a particular artist for {@link * ArtistAlbumFragment} . * * @author Andrew Neal ([email protected]) */ public class ArtistAlbumAdapter extends ArrayAdapter<Album> { /** The header view */ private static final int ITEM_VIEW_TYPE_HEADER = 0; /** * The data in the list. */ private static final int ITEM_VIEW_TYPE_MUSIC = 1; /** Number of views (ImageView, TextView, header) */ private static final int VIEW_TYPE_COUNT = 3; /** LayoutInflater */ private final LayoutInflater mInflater; /** Fake header */ private final View mHeader; /** The resource Id of the layout to inflate */ private final int mLayoutId; /** Image cache and image fetcher */ private final ImageFetcher mImageFetcher; /** Used to set the size of the data in the adapter */ private List<Album> mCount = Lists.newArrayList(); /** * Constructor of <code>ArtistAlbumAdapter</code> * * @param context The {@link Context} to use * @param layoutId The resource Id of the view to inflate. */ public ArtistAlbumAdapter(final Activity context, final int layoutId) { super(context, 0); // Used to create the custom layout mInflater = LayoutInflater.from(context); // Cache the header mHeader = mInflater.inflate(R.layout.faux_carousel, null); // Get the layout Id mLayoutId = layoutId; // Initialize the cache & image fetcher mImageFetcher = ApolloUtils.getImageFetcher(context); } /** {@inheritDoc} */ @Override public View getView(final int position, View convertView, final ViewGroup parent) { // Return a faux header at position 0 if (position == 0) { return mHeader; } // Recycle MusicHolder's items MusicHolder holder; if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(mLayoutId, parent, false); holder = new MusicHolder(convertView); // Remove the background layer holder.mOverlay.get().setBackgroundColor(0); convertView.setTag(holder); } else { holder = (MusicHolder) convertView.getTag(); } // Retrieve the album final Album album = getItem(position - 1); final String albumName = album.mAlbumName; // Set each album name (line one) holder.mLineOne.get().setText(albumName); // Set the number of songs (line two) holder .mLineTwo .get() .setText(MusicUtils.makeLabel(getContext(), R.plurals.Nsongs, album.mSongNumber)); // Set the album year (line three) holder.mLineThree.get().setText(album.mYear); // Asynchronously load the album images into the adapter mImageFetcher.loadAlbumImage(album.mArtistName, albumName, album.mAlbumId, holder.mImage.get()); // Play the album when the artwork is touched playAlbum(holder.mImage.get(), position); return convertView; } /** {@inheritDoc} */ @Override public boolean hasStableIds() { return true; } /** {@inheritDoc} */ @Override public int getCount() { final int size = mCount.size(); return size == 0 ? 0 : size + 1; } /** {@inheritDoc} */ @Override public long getItemId(final int position) { if (position == 0) { return -1; } return position - 1; } /** {@inheritDoc} */ @Override public int getViewTypeCount() { return VIEW_TYPE_COUNT; } /** {@inheritDoc} */ @Override public int getItemViewType(final int position) { if (position == 0) { return ITEM_VIEW_TYPE_HEADER; } return ITEM_VIEW_TYPE_MUSIC; } /** * Starts playing an album if the user touches the artwork in the list. * * @param album The {@link ImageView} holding the album * @param position The position of the album to play. */ private void playAlbum(final ImageView album, final int position) { album.setOnClickListener( new OnClickListener() { @Override public void onClick(final View v) { final long id = getItem(position - 1).mAlbumId; final long[] list = MusicUtils.getSongListForAlbum(getContext(), id); MusicUtils.playAll(getContext(), list, 0, false); } }); } /** Method that unloads and clears the items in the adapter */ public void unload() { clear(); } /** @param pause True to temporarily pause the disk cache, false otherwise. */ public void setPauseDiskCache(final boolean pause) { if (mImageFetcher != null) { mImageFetcher.setPauseDiskCache(pause); } } /** @param album The key used to find the cached album to remove */ public void removeFromCache(final Album album) { if (mImageFetcher != null) { mImageFetcher.removeFromCache( ImageFetcher.generateAlbumCacheKey(album.mAlbumName, album.mArtistName)); } } /** @param data The {@link List} used to return the count for the adapter. */ public void setCount(final List<Album> data) { mCount = data; } /** Flushes the disk cache. */ public void flush() { mImageFetcher.flush(); } }
/** * Used to query {@link MediaStore.Audio.Media.EXTERNAL_CONTENT_URI} and return the Song for a * particular album. * * @author Andrew Neal ([email protected]) */ public class AlbumSongLoader extends WrappedAsyncTaskLoader<List<Song>> { /** * @param context The {@link Context} to use. * @param albumId The Id of the album the songs belong to. * @return The {@link Cursor} used to run the query. */ public static final Cursor makeAlbumSongCursor(final Context context, final Long albumId) { // Match the songs up with the artist final StringBuilder selection = new StringBuilder(); selection.append(AudioColumns.IS_MUSIC + "=1"); selection.append(" AND " + MediaColumns.TITLE + " != ''"); selection.append(" AND " + AudioColumns.ALBUM_ID + "=" + albumId); return context .getContentResolver() .query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, new String[] { /* 0 */ BaseColumns._ID, /* 1 */ MediaColumns.TITLE, /* 2 */ AudioColumns.ARTIST, /* 3 */ AudioColumns.ALBUM, /* 4 */ AudioColumns.DURATION }, selection.toString(), null, PreferenceUtils.getInstace(context).getAlbumSongSortOrder()); } /** The Id of the album the songs belong to. */ private final Long mAlbumID; /** The {@link Cursor} used to run the query. */ private Cursor mCursor; /** The result */ private final ArrayList<Song> mSongList = Lists.newArrayList(); /** * Constructor of <code>AlbumSongHandler</code> * * @param context The {@link Context} to use. * @param albumId The Id of the album the songs belong to. */ public AlbumSongLoader(final Context context, final Long albumId) { super(context); mAlbumID = albumId; } /** {@inheritDoc} */ @Override public List<Song> loadInBackground() { // Create the Cursor mCursor = makeAlbumSongCursor(getContext(), mAlbumID); // Gather the data if (mCursor != null && mCursor.moveToFirst()) { do { // Copy the song Id final String id = mCursor.getString(0); // Copy the song name final String songName = mCursor.getString(1); // Copy the artist name final String artist = mCursor.getString(2); // Copy the album name final String album = mCursor.getString(3); // Copy the duration final String duration = mCursor.getString(4); // Make the duration label final int seconds = Integer.valueOf(duration != null ? duration : "0") / 1000; final String durationFormatted = MusicUtils.makeTimeString(getContext(), seconds); // Create a new song final Song song = new Song(id, songName, artist, album, durationFormatted); // Add everything up mSongList.add(song); } while (mCursor.moveToNext()); } // Close the cursor if (mCursor != null) { mCursor.close(); mCursor = null; } return mSongList; } }
/** * Used to return the current playlist or queue. * * @author Andrew Neal ([email protected]) */ public class QueueLoader extends WrappedAsyncTaskLoader<List<Song>> { /** The result */ private final ArrayList<Song> mSongList = Lists.newArrayList(); /** The {@link Cursor} used to run the query. */ private NowPlayingCursor mCursor; /** * Constructor of <code>QueueLoader</code> * * @param context The {@link Context} to use */ public QueueLoader(final Context context) { super(context); } /** {@inheritDoc} */ @Override public List<Song> loadInBackground() { // Create the Cursor mCursor = new NowPlayingCursor(getContext()); // Gather the data if (mCursor != null && mCursor.moveToFirst()) { do { // Copy the song Id final long id = mCursor.getLong(0); // Copy the song name final String songName = mCursor.getString(1); // Copy the artist name final String artist = mCursor.getString(2); // Copy the album name final String album = mCursor.getString(3); // Copy the duration final long duration = mCursor.getLong(4); // Convert the duration into seconds final int durationInSecs = (int) duration / 1000; // Create a new song final Song song = new Song(id, songName, artist, album, durationInSecs); // Add everything up mSongList.add(song); } while (mCursor.moveToNext()); } // Close the cursor if (mCursor != null) { mCursor.close(); mCursor = null; } return mSongList; } /** * Creates the {@link Cursor} used to run the query. * * @param context The {@link Context} to use. * @return The {@link Cursor} used to run the song query. */ public static final Cursor makeQueueCursor(final Context context) { final Cursor cursor = new NowPlayingCursor(context); return cursor; } }
/** * Used to query {@link MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI} and return the genres on a * user's device. * * @author Andrew Neal ([email protected]) */ public class GenreLoader extends WrappedAsyncTaskLoader<List<Genre>> { /** The result */ private final ArrayList<Genre> mGenreList = Lists.newArrayList(); /** The {@link Cursor} used to run the query. */ private Cursor mCursor; /** * Constructor of <code>GenreLoader</code> * * @param context The {@link Context} to use */ public GenreLoader(final Context context) { super(context); } /** {@inheritDoc} */ @Override public List<Genre> loadInBackground() { // Create the Cursor mCursor = makeGenreCursor(getContext()); // Gather the data if (mCursor != null && mCursor.moveToFirst()) { do { // Copy the genre id final long id = mCursor.getLong(0); // Copy the genre name final String name = mCursor.getString(1); // Create a new genre final Genre genre = new Genre(id, name); // Add everything up mGenreList.add(genre); } while (mCursor.moveToNext()); } // Close the cursor if (mCursor != null) { mCursor.close(); mCursor = null; } return mGenreList; } /** * Creates the {@link Cursor} used to run the query. * * @param context The {@link Context} to use. * @return The {@link Cursor} used to run the genre query. */ public static final Cursor makeGenreCursor(final Context context) { final StringBuilder selection = new StringBuilder(); selection.append(MediaStore.Audio.Genres.NAME + " != ''"); return context .getContentResolver() .query( MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI, new String[] { /* 0 */ BaseColumns._ID, /* 1 */ GenresColumns.NAME }, selection.toString(), null, MediaStore.Audio.Genres.DEFAULT_SORT_ORDER); } }