Back to project page Muse.
The source code is released under:
Apache License
If you think the Android project Muse listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package com.prt2121.muse; //www . j a va 2s . c om import android.app.Activity; import android.content.ComponentName; import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.content.ServiceConnection; import android.database.Cursor; import android.net.Uri; import android.os.IBinder; import android.os.RemoteException; import android.provider.BaseColumns; import android.provider.MediaStore; import android.provider.MediaStore.Audio.AlbumColumns; import android.provider.MediaStore.Audio.ArtistColumns; import android.provider.MediaStore.Audio.AudioColumns; import android.provider.MediaStore.Audio.Playlists; import android.provider.MediaStore.Audio.PlaylistsColumns; import android.provider.MediaStore.MediaColumns; import java.util.Arrays; import java.util.WeakHashMap; /** * A collection of helpers directly related to music or Apollo's service. */ public final class MusicUtils { public static IPlayerService mService = null; private static int sForegroundActivities = 0; private static final WeakHashMap<Context, ServiceBinder> mConnectionMap; private static final long[] sEmptyList; private static ContentValues[] mContentValuesCache = null; static { mConnectionMap = new WeakHashMap<Context, ServiceBinder>(); sEmptyList = new long[0]; } /* This class is never initiated */ public MusicUtils() { } /** * @param context The {@link Context} to use * @param callback The {@link ServiceConnection} to use * @return The new instance of {@link ServiceToken} */ public static final ServiceToken bindToService(final Context context, final ServiceConnection callback) { Activity realActivity = ((Activity) context).getParent(); if (realActivity == null) { realActivity = (Activity) context; } final ContextWrapper contextWrapper = new ContextWrapper(realActivity); contextWrapper.startService(new Intent(contextWrapper, PlayerService.class)); final ServiceBinder binder = new ServiceBinder(callback); if (contextWrapper.bindService( new Intent().setClass(contextWrapper, PlayerService.class), binder, 0)) { mConnectionMap.put(contextWrapper, binder); return new ServiceToken(contextWrapper); } return null; } /** * @param token The {@link ServiceToken} to unbind from */ public static void unbindFromService(final ServiceToken token) { if (token == null) { return; } final ContextWrapper mContextWrapper = token.mWrappedContext; final ServiceBinder mBinder = mConnectionMap.remove(mContextWrapper); if (mBinder == null) { return; } mContextWrapper.unbindService(mBinder); if (mConnectionMap.isEmpty()) { mService = null; } } public static final class ServiceBinder implements ServiceConnection { private final ServiceConnection mCallback; /** * Constructor of <code>ServiceBinder</code> * * @param callback The {@link ServiceConnection} to use */ public ServiceBinder(final ServiceConnection callback) { mCallback = callback; } @Override public void onServiceConnected(final ComponentName className, final IBinder service) { mService = IPlayerService.Stub.asInterface(service); if (mCallback != null) { mCallback.onServiceConnected(className, service); } } @Override public void onServiceDisconnected(final ComponentName className) { if (mCallback != null) { mCallback.onServiceDisconnected(className); } mService = null; } } public static final class ServiceToken { public ContextWrapper mWrappedContext; /** * Constructor of <code>ServiceToken</code> * * @param context The {@link ContextWrapper} to use */ public ServiceToken(final ContextWrapper context) { mWrappedContext = context; } } /** * Used to make number of labels for the number of artists, albums, songs, * genres, and playlists. * * @param context The {@link Context} to use. * @param pluralInt The ID of the plural string to use. * @param number The number of artists, albums, songs, genres, or playlists. * @return A {@link String} used as a label for the number of artists, * albums, songs, genres, and playlists. */ public static final String makeLabel(final Context context, final int pluralInt, final int number) { return context.getResources().getQuantityString(pluralInt, number, number); } /** * Changes to the next track */ public static void next() { try { if (mService != null) { mService.next(); } } catch (final RemoteException ignored) { } } /** * Changes to the previous track. * * The AIDL isn't used here in order to properly use the previous action. */ public static void previous(final Context context) { final Intent previous = new Intent(context, PlayerService.class); previous.setAction(PlayerService.PREVIOUS_ACTION); context.startService(previous); } /** * Plays or pauses the music. */ public static void playOrPause() { try { if (mService != null) { if (mService.isPlaying()) { mService.pause(); } else { mService.play(); } } } catch (final Exception ignored) { } } /** * Cycles through the repeat options. */ public static void cycleRepeat() { try { if (mService != null) { switch (mService.getRepeatMode()) { case PlayerService.REPEAT_NONE: mService.setRepeatMode(PlayerService.REPEAT_ALL); break; case PlayerService.REPEAT_ALL: mService.setRepeatMode(PlayerService.REPEAT_CURRENT); if (mService.getShuffleMode() != PlayerService.SHUFFLE_NONE) { mService.setShuffleMode(PlayerService.SHUFFLE_NONE); } break; default: mService.setRepeatMode(PlayerService.REPEAT_NONE); break; } } } catch (final RemoteException ignored) { } } /** * Cycles through the shuffle options. */ public static void cycleShuffle() { try { if (mService != null) { switch (mService.getShuffleMode()) { case PlayerService.SHUFFLE_NONE: mService.setShuffleMode(PlayerService.SHUFFLE_NORMAL); if (mService.getRepeatMode() == PlayerService.REPEAT_CURRENT) { mService.setRepeatMode(PlayerService.REPEAT_ALL); } break; case PlayerService.SHUFFLE_NORMAL: mService.setShuffleMode(PlayerService.SHUFFLE_NONE); break; case PlayerService.SHUFFLE_AUTO: mService.setShuffleMode(PlayerService.SHUFFLE_NONE); break; default: break; } } } catch (final RemoteException ignored) { } } /** * @return True if we're playing music, false otherwise. */ public static final boolean isPlaying() { if (mService != null) { try { return mService.isPlaying(); } catch (final RemoteException ignored) { } } return false; } /** * @return The current shuffle mode. */ public static final int getShuffleMode() { if (mService != null) { try { return mService.getShuffleMode(); } catch (final RemoteException ignored) { } } return 0; } /** * @return The current repeat mode. */ public static final int getRepeatMode() { if (mService != null) { try { return mService.getRepeatMode(); } catch (final RemoteException ignored) { } } return 0; } /** * @return The current track name. */ public static final String getTrackName() { if (mService != null) { try { return mService.getTrackName(); } catch (final RemoteException ignored) { } } return null; } /** * @return The current artist name. */ public static final String getArtistName() { if (mService != null) { try { return mService.getArtistName(); } catch (final RemoteException ignored) { } } return null; } /** * @return The current album name. */ public static final String getAlbumName() { if (mService != null) { try { return mService.getAlbumName(); } catch (final RemoteException ignored) { } } return null; } /** * @return The current album Id. */ public static final long getCurrentAlbumId() { if (mService != null) { try { return mService.getAlbumId(); } catch (final RemoteException ignored) { } } return -1; } /** * @return The current song Id. */ public static final long getCurrentAudioId() { if (mService != null) { try { return mService.getAudioId(); } catch (final RemoteException ignored) { } } return -1; } /** * @return The current artist Id. */ public static final long getCurrentArtistId() { if (mService != null) { try { return mService.getArtistId(); } catch (final RemoteException ignored) { } } return -1; } /** * @return The audio session Id. */ public static final int getAudioSessionId() { if (mService != null) { try { return mService.getAudioSessionId(); } catch (final RemoteException ignored) { } } return -1; } /** * @return The queue. */ public static final long[] getQueue() { try { if (mService != null) { return mService.getQueue(); } else { } } catch (final RemoteException ignored) { } return sEmptyList; } /** * @param id The ID of the track to remove. * @return removes track from a playlist or the queue. */ public static final int removeTrack(final long id) { try { if (mService != null) { return mService.removeTrack(id); } } catch (final RemoteException ingored) { } return 0; } /** * @return The position of the current track in the queue. */ public static final int getQueuePosition() { try { if (mService != null) { return mService.getQueuePosition(); } } catch (final RemoteException ignored) { } return 0; } /** * @param cursor The {@link Cursor} used to perform our query. * @return The song list for a MIME type. */ public static final long[] getSongListForCursor(Cursor cursor) { if (cursor == null) { return sEmptyList; } final int len = cursor.getCount(); final long[] list = new long[len]; cursor.moveToFirst(); int columnIndex = -1; try { columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Audio.Playlists.Members.AUDIO_ID); } catch (final IllegalArgumentException notaplaylist) { columnIndex = cursor.getColumnIndexOrThrow(BaseColumns._ID); } for (int i = 0; i < len; i++) { list[i] = cursor.getLong(columnIndex); cursor.moveToNext(); } cursor.close(); cursor = null; return list; } /** * @param context The {@link Context} to use. * @param id The ID of the artist. * @return The song list for an artist. */ public static final long[] getSongListForArtist(final Context context, final long id) { final String[] projection = new String[]{ BaseColumns._ID }; final String selection = AudioColumns.ARTIST_ID + "=" + id + " AND " + AudioColumns.IS_MUSIC + "=1"; Cursor cursor = context.getContentResolver().query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, selection, null, AudioColumns.ALBUM_KEY + "," + AudioColumns.TRACK); if (cursor != null) { final long[] mList = getSongListForCursor(cursor); cursor.close(); cursor = null; return mList; } return sEmptyList; } /** * @param context The {@link Context} to use. * @param id The ID of the album. * @return The song list for an album. */ public static final long[] getSongListForAlbum(final Context context, final long id) { final String[] projection = new String[]{ BaseColumns._ID }; final String selection = AudioColumns.ALBUM_ID + "=" + id + " AND " + AudioColumns.IS_MUSIC + "=1"; Cursor cursor = context.getContentResolver().query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, selection, null, AudioColumns.TRACK + ", " + MediaStore.Audio.Media.DEFAULT_SORT_ORDER); if (cursor != null) { final long[] mList = getSongListForCursor(cursor); cursor.close(); cursor = null; return mList; } return sEmptyList; } /** * Plays songs by an artist. * * @param context The {@link Context} to use. * @param artistId The artist Id. * @param position Specify where to start. */ public static void playArtist(final Context context, final long artistId, int position) { final long[] artistList = getSongListForArtist(context, artistId); if (artistList != null) { playAll(context, artistList, position, false); } } /** * @param context The {@link Context} to use. * @param id The ID of the genre. * @return The song list for an genre. */ public static final long[] getSongListForGenre(final Context context, final long id) { final String[] projection = new String[]{ BaseColumns._ID }; final StringBuilder selection = new StringBuilder(); selection.append(AudioColumns.IS_MUSIC + "=1"); selection.append(" AND " + MediaColumns.TITLE + "!=''"); final Uri uri = MediaStore.Audio.Genres.Members.getContentUri("external", Long.valueOf(id)); Cursor cursor = context.getContentResolver().query(uri, projection, selection.toString(), null, null); if (cursor != null) { final long[] mList = getSongListForCursor(cursor); cursor.close(); cursor = null; return mList; } return sEmptyList; } /** * @param context The {@link Context} to use * @param uri The source of the file */ public static void playFile(final Context context, final Uri uri) { if (uri == null || mService == null) { return; } // If this is a file:// URI, just use the path directly instead // of going through the open-from-filedescriptor codepath. String filename; String scheme = uri.getScheme(); if ("file".equals(scheme)) { filename = uri.getPath(); } else { filename = uri.toString(); } try { mService.stop(); mService.openFile(filename); mService.play(); } catch (final RemoteException ignored) { } } /** * @param context The {@link Context} to use. * @param list The list of songs to play. * @param position Specify where to start. * @param forceShuffle True to force a shuffle, false otherwise. */ public static void playAll(final Context context, final long[] list, int position, final boolean forceShuffle) { if (list.length == 0 || mService == null) { return; } try { if (forceShuffle) { mService.setShuffleMode(PlayerService.SHUFFLE_NORMAL); } else { mService.setShuffleMode(PlayerService.SHUFFLE_NONE); } final long currentId = mService.getAudioId(); final int currentQueuePosition = getQueuePosition(); if (position != -1 && currentQueuePosition == position && currentId == list[position]) { final long[] playlist = getQueue(); if (Arrays.equals(list, playlist)) { mService.play(); return; } } if (position < 0) { position = 0; } mService.open(list, forceShuffle ? -1 : position); mService.play(); } catch (final RemoteException ignored) { } } /** * @param list The list to enqueue. */ public static void playNext(final long[] list) { if (mService == null) { return; } try { mService.enqueue(list, PlayerService.NEXT); } catch (final RemoteException ignored) { } } /** * Returns The ID for a playlist. * * @param context The {@link Context} to use. * @param name The name of the playlist. * @return The ID for a playlist. */ public static final long getIdForPlaylist(final Context context, final String name) { Cursor cursor = context.getContentResolver().query( MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, new String[]{ BaseColumns._ID }, PlaylistsColumns.NAME + "=?", new String[]{ name }, PlaylistsColumns.NAME); int id = -1; if (cursor != null) { cursor.moveToFirst(); if (!cursor.isAfterLast()) { id = cursor.getInt(0); } cursor.close(); cursor = null; } return id; } /** * Returns the Id for an artist. * * @param context The {@link Context} to use. * @param name The name of the artist. * @return The ID for an artist. */ public static final long getIdForArtist(final Context context, final String name) { Cursor cursor = context.getContentResolver().query( MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI, new String[]{ BaseColumns._ID }, ArtistColumns.ARTIST + "=?", new String[]{ name }, ArtistColumns.ARTIST); int id = -1; if (cursor != null) { cursor.moveToFirst(); if (!cursor.isAfterLast()) { id = cursor.getInt(0); } cursor.close(); cursor = null; } return id; } /** * Returns the ID for an album. * * @param context The {@link Context} to use. * @param albumName The name of the album. * @param artistName The name of the artist * @return The ID for an album. */ public static final long getIdForAlbum(final Context context, final String albumName, final String artistName) { Cursor cursor = context.getContentResolver().query( MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, new String[]{ BaseColumns._ID }, AlbumColumns.ALBUM + "=? AND " + AlbumColumns.ARTIST + "=?", new String[]{ albumName, artistName }, AlbumColumns.ALBUM); int id = -1; if (cursor != null) { cursor.moveToFirst(); if (!cursor.isAfterLast()) { id = cursor.getInt(0); } cursor.close(); cursor = null; } return id; } /** * Plays songs from an album. * * @param context The {@link Context} to use. * @param albumId The album Id. * @param position Specify where to start. */ public static void playAlbum(final Context context, final long albumId, int position) { final long[] albumList = getSongListForAlbum(context, albumId); if (albumList != null) { playAll(context, albumList, position, false); } } /* */ public static void makeInsertItems(final long[] ids, final int offset, int len, final int base) { if (offset + len > ids.length) { len = ids.length - offset; } if (mContentValuesCache == null || mContentValuesCache.length != len) { mContentValuesCache = new ContentValues[len]; } for (int i = 0; i < len; i++) { if (mContentValuesCache[i] == null) { mContentValuesCache[i] = new ContentValues(); } mContentValuesCache[i].put(Playlists.Members.PLAY_ORDER, base + offset + i); mContentValuesCache[i].put(Playlists.Members.AUDIO_ID, ids[offset + i]); } } /** * @param context The {@link Context} to use. * @param name The name of the new playlist. * @return A new playlist ID. */ public static final long createPlaylist(final Context context, final String name) { if (name != null && name.length() > 0) { final ContentResolver resolver = context.getContentResolver(); final String[] projection = new String[]{ PlaylistsColumns.NAME }; final String selection = PlaylistsColumns.NAME + " = '" + name + "'"; Cursor cursor = resolver.query(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, projection, selection, null, null); if (cursor.getCount() <= 0) { final ContentValues values = new ContentValues(1); values.put(PlaylistsColumns.NAME, name); final Uri uri = resolver.insert(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, values); return Long.parseLong(uri.getLastPathSegment()); } if (cursor != null) { cursor.close(); cursor = null; } return -1; } return -1; } /** * @param context The {@link Context} to use. * @param playlistId The playlist ID. */ public static void clearPlaylist(final Context context, final int playlistId) { final Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId); context.getContentResolver().delete(uri, null, null); return; } /** * @param context The {@link Context} to use. * @param id The id of the album. * @return The song count for an album. */ public static final String getSongCountForAlbum(final Context context, final long id) { if (id == -1) { return null; } Uri uri = ContentUris.withAppendedId(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, id); Cursor cursor = context.getContentResolver().query(uri, new String[]{ AlbumColumns.NUMBER_OF_SONGS }, null, null, null); String songCount = null; if (cursor != null) { cursor.moveToFirst(); if (!cursor.isAfterLast()) { songCount = cursor.getString(0); } cursor.close(); cursor = null; } return songCount; } /** * @param context The {@link Context} to use. * @param id The id of the album. * @return The release date for an album. */ public static final String getReleaseDateForAlbum(final Context context, final long id) { if (id == -1) { return null; } Uri uri = ContentUris.withAppendedId(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, id); Cursor cursor = context.getContentResolver().query(uri, new String[]{ AlbumColumns.FIRST_YEAR }, null, null, null); String releaseDate = null; if (cursor != null) { cursor.moveToFirst(); if (!cursor.isAfterLast()) { releaseDate = cursor.getString(0); } cursor.close(); cursor = null; } return releaseDate; } /** * @return The path to the currently playing file as {@link String} */ public static final String getFilePath() { try { if (mService != null) { return mService.getPath(); } } catch (final RemoteException ignored) { } return null; } /** * @param from The index the item is currently at. * @param to The index the item is moving to. */ public static void moveQueueItem(final int from, final int to) { try { if (mService != null) { mService.moveQueueItem(from, to); } else { } } catch (final RemoteException ignored) { } } /** * Toggles the current song as a favorite. */ public static void toggleFavorite() { try { if (mService != null) { mService.toggleFavorite(); } } catch (final RemoteException ignored) { } } /** * @return True if the current song is a favorite, false otherwise. */ public static final boolean isFavorite() { try { if (mService != null) { return mService.isFavorite(); } } catch (final RemoteException ignored) { } return false; } /** * @param context The {@link Context} to sue * @param playlistId The playlist Id * @return The track list for a playlist */ public static final long[] getSongListForPlaylist(final Context context, final long playlistId) { final String[] projection = new String[]{ MediaStore.Audio.Playlists.Members.AUDIO_ID }; Cursor cursor = context.getContentResolver().query( MediaStore.Audio.Playlists.Members.getContentUri("external", Long.valueOf(playlistId)), projection, null, null, MediaStore.Audio.Playlists.Members.DEFAULT_SORT_ORDER); if (cursor != null) { final long[] list = getSongListForCursor(cursor); cursor.close(); cursor = null; return list; } return sEmptyList; } /** * Plays a user created playlist. * * @param context The {@link Context} to use. * @param playlistId The playlist Id. */ public static void playPlaylist(final Context context, final long playlistId) { final long[] playlistList = getSongListForPlaylist(context, playlistId); if (playlistList != null) { playAll(context, playlistList, -1, false); } } /** * Called when one of the lists should refresh or requery. */ public static void refresh() { try { if (mService != null) { mService.refresh(); } } catch (final RemoteException ignored) { } } /** * Seeks the current track to a desired position * * @param position The position to seek to */ public static void seek(final long position) { if (mService != null) { try { mService.seek(position); } catch (final RemoteException ignored) { } } } /** * @return The current position time of the track */ public static final long position() { if (mService != null) { try { return mService.position(); } catch (final RemoteException ignored) { } } return 0; } /** * @return The total length of the current track */ public static final long duration() { if (mService != null) { try { return mService.duration(); } catch (final RemoteException ignored) { } } return 0; } /** * @param position The position to move the queue to */ public static void setQueuePosition(final int position) { if (mService != null) { try { mService.setQueuePosition(position); } catch (final RemoteException ignored) { } } } /** * Clears the qeueue */ public static void clearQueue() { try { mService.removeTracks(0, Integer.MAX_VALUE); } catch (final RemoteException ignored) { } } /** * Used to build and show a notification when Apollo is sent into the * background * * @param context The {@link Context} to use. */ public static void notifyForegroundStateChanged(final Context context, boolean inForeground) { int old = sForegroundActivities; if (inForeground) { sForegroundActivities++; } else { sForegroundActivities--; } if (old == 0 || sForegroundActivities == 0) { final Intent intent = new Intent(context, PlayerService.class); intent.setAction(PlayerService.FOREGROUND_STATE_CHANGED); intent.putExtra(PlayerService.NOW_IN_FOREGROUND, sForegroundActivities != 0); context.startService(intent); } } }