diff options
author | Danny Baumann <dannybaumann@web.de> | 2013-08-06 18:28:42 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@cyanogenmod.org> | 2013-08-06 18:28:42 +0000 |
commit | d2ec987449f68c4894ad7de48adc8ee66392554b (patch) | |
tree | 0f2369bcb7aa367e8f09982aefa3b4763914103d /src | |
parent | 5fc2d658b9b3ae102cc80215e52fd63c6bf561ba (diff) | |
parent | 4d248fc6726028898b4e17ab34704f45114a99d6 (diff) | |
download | android_packages_apps_Eleven-d2ec987449f68c4894ad7de48adc8ee66392554b.tar.gz android_packages_apps_Eleven-d2ec987449f68c4894ad7de48adc8ee66392554b.tar.bz2 android_packages_apps_Eleven-d2ec987449f68c4894ad7de48adc8ee66392554b.zip |
Merge "Add support for new remote control interfaces in API 18." into cm-10.2
Diffstat (limited to 'src')
-rw-r--r-- | src/com/andrew/apollo/MusicPlaybackService.java | 201 | ||||
-rw-r--r-- | src/com/andrew/apollo/utils/ApolloUtils.java | 11 |
2 files changed, 147 insertions, 65 deletions
diff --git a/src/com/andrew/apollo/MusicPlaybackService.java b/src/com/andrew/apollo/MusicPlaybackService.java index ec1df5a..de28f89 100644 --- a/src/com/andrew/apollo/MusicPlaybackService.java +++ b/src/com/andrew/apollo/MusicPlaybackService.java @@ -43,6 +43,7 @@ import android.os.PowerManager.WakeLock; import android.os.RemoteException; import android.os.SystemClock; import android.provider.MediaStore; +import android.provider.MediaStore.Audio.AlbumColumns; import android.provider.MediaStore.Audio.AudioColumns; import android.util.Log; @@ -80,6 +81,12 @@ public class MusicPlaybackService extends Service { public static final String PLAYSTATE_CHANGED = "com.andrew.apollo.playstatechanged"; /** + * Indicates that music playback position within + * a title was changed + */ + public static final String POSITION_CHANGED = "com.android.apollo.positionchanged"; + + /** * Indicates the meta data has changed in some way, like a track change */ public static final String META_CHANGED = "com.andrew.apollo.metachanged"; @@ -289,6 +296,14 @@ public class MusicPlaybackService extends Service { }; /** + * The columns used to retrieve any info from the current album + */ + private static final String[] ALBUM_PROJECTION = new String[] { + MediaStore.Audio.Albums.ALBUM, MediaStore.Audio.Albums.ARTIST, + MediaStore.Audio.Albums.LAST_YEAR + }; + + /** * Keeps a mapping of the track history */ private static final LinkedList<Integer> mHistory = Lists.newLinkedList(); @@ -364,6 +379,12 @@ public class MusicPlaybackService extends Service { private Cursor mCursor; /** + * The cursor used to retrieve info on the album the current track is + * part of, if any. + */ + private Cursor mAlbumCursor; + + /** * Monitors the audio state */ private AudioManager mAudioManager; @@ -597,12 +618,32 @@ public class MusicPlaybackService extends Service { mAudioManager.registerRemoteControlClient(mRemoteControlClient); // Flags for the media transport control that this client supports. - final int flags = RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS + int flags = RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS | RemoteControlClient.FLAG_KEY_MEDIA_NEXT | RemoteControlClient.FLAG_KEY_MEDIA_PLAY | RemoteControlClient.FLAG_KEY_MEDIA_PAUSE | RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE | RemoteControlClient.FLAG_KEY_MEDIA_STOP; + + if (ApolloUtils.hasJellyBeanMR2()) { + flags |= RemoteControlClient.FLAG_KEY_MEDIA_POSITION_UPDATE; + + mRemoteControlClient.setOnGetPlaybackPositionListener( + new RemoteControlClient.OnGetPlaybackPositionListener() { + @Override + public long onGetPlaybackPosition() { + return position(); + } + }); + mRemoteControlClient.setPlaybackPositionUpdateListener( + new RemoteControlClient.OnPlaybackPositionUpdateListener() { + @Override + public void onPlaybackPositionUpdate(long newPositionMs) { + seek(newPositionMs); + } + }); + } + mRemoteControlClient.setTransportControlFlags(flags); } @@ -635,10 +676,7 @@ public class MusicPlaybackService extends Service { mPlayerHandler.removeCallbacksAndMessages(null); // Close the cursor - if (mCursor != null) { - mCursor.close(); - mCursor = null; - } + closeCursor(); // Unregister the mount listener unregisterReceiver(mIntentReceiver); @@ -841,10 +879,7 @@ public class MusicPlaybackService extends Service { mPlayer.stop(); } mFileToPlay = null; - if (mCursor != null) { - mCursor.close(); - mCursor = null; - } + closeCursor(); if (goToIdle) { scheduleDelayedShutdown(); mIsSupposedToBePlaying = false; @@ -889,10 +924,7 @@ public class MusicPlaybackService extends Service { if (mPlayListLen == 0) { stop(true); mPlayPos = -1; - if (mCursor != null) { - mCursor.close(); - mCursor = null; - } + closeCursor(); } else { if (mPlayPos >= mPlayListLen) { mPlayPos = 0; @@ -937,23 +969,56 @@ public class MusicPlaybackService extends Service { } mPlayListLen += addlen; if (mPlayListLen == 0) { - mCursor.close(); - mCursor = null; + closeCursor(); notifyChange(META_CHANGED); } } /** - * @param lid The list ID - * @return The cursor used for a specific ID + * @param trackId The track ID */ - private Cursor getCursorForId(final long id) { - final Cursor c = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, - PROJECTION, "_id=" + id, null, null); - if (c != null) { - c.moveToFirst(); + private void updateCursor(final long trackId) { + updateCursor("_id=" + trackId, null); + } + + private void updateCursor(final String selection, final String[] selectionArgs) { + closeCursor(); + + mCursor = openCursorAndGoToFirst(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, + PROJECTION, selection, selectionArgs); + + long albumId = getAlbumId(); + if (albumId >= 0) { + mAlbumCursor = openCursorAndGoToFirst(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, + ALBUM_PROJECTION, "_id=" + albumId, null); + } else { + mAlbumCursor = null; + } + } + + private Cursor openCursorAndGoToFirst(Uri uri, String[] projection, + String selection, String[] selectionArgs) { + Cursor c = getContentResolver().query(uri, projection, + selection, selectionArgs, null, null); + if (c == null) { + return null; + } + if (!c.moveToFirst()) { + c.close(); + return null; } return c; + } + + private void closeCursor() { + if (mCursor != null) { + mCursor.close(); + mCursor = null; + } + if (mAlbumCursor != null) { + mAlbumCursor.close(); + mAlbumCursor = null; + } } /** @@ -973,20 +1038,16 @@ public class MusicPlaybackService extends Service { */ private void openCurrentAndMaybeNext(final boolean openNext) { synchronized (this) { - if (mCursor != null) { - mCursor.close(); - mCursor = null; - } + closeCursor(); if (mPlayListLen == 0) { return; } stop(false); - mCursor = getCursorForId(mPlayList[mPlayPos]); + updateCursor(mPlayList[mPlayPos]); while (true) { if (mCursor != null - && mCursor.getCount() != 0 && openFile(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI + "/" + mCursor.getLong(IDCOLIDX))) { break; @@ -994,10 +1055,7 @@ public class MusicPlaybackService extends Service { // if we get here then opening the file failed. We can close the // cursor now, because // we're either going to create a new one next, or stop trying - if (mCursor != null) { - mCursor.close(); - mCursor = null; - } + closeCursor(); if (mOpenFailedCounter++ < 10 && mPlayListLen > 1) { final int pos = getNextPosition(false); if (pos < 0) { @@ -1011,7 +1069,7 @@ public class MusicPlaybackService extends Service { mPlayPos = pos; stop(false); mPlayPos = pos; - mCursor = getCursorForId(mPlayList[mPlayPos]); + updateCursor(mPlayList[mPlayPos]); } else { mOpenFailedCounter = 0; Log.w(TAG, "Failed to open file for playback"); @@ -1226,6 +1284,13 @@ public class MusicPlaybackService extends Service { private void notifyChange(final String what) { if (D) Log.d(TAG, "notifyChange: what = " + what); + // Update the lockscreen controls + updateRemoteControlClient(what); + + if (what.equals(POSITION_CHANGED)) { + return; + } + final Intent intent = new Intent(what); intent.putExtra("id", getAudioId()); intent.putExtra("artist", getArtistName()); @@ -1239,9 +1304,6 @@ public class MusicPlaybackService extends Service { musicIntent.setAction(what.replace(APOLLO_PACKAGE_NAME, MUSIC_PACKAGE_NAME)); sendStickyBroadcast(musicIntent); - // Update the lockscreen controls - updateRemoteControlClient(what); - if (what.equals(META_CHANGED)) { // Increase the play count for favorite songs. if (mFavoritesCache.getSongId(getAudioId()) != null) { @@ -1275,11 +1337,15 @@ public class MusicPlaybackService extends Service { * @param what The broadcast */ private void updateRemoteControlClient(final String what) { - if (what.equals(PLAYSTATE_CHANGED)) { - mRemoteControlClient.setPlaybackState(mIsSupposedToBePlaying - ? RemoteControlClient.PLAYSTATE_PLAYING - : RemoteControlClient.PLAYSTATE_PAUSED); - } else if (what.equals(META_CHANGED)) { + int playState = mIsSupposedToBePlaying + ? RemoteControlClient.PLAYSTATE_PLAYING + : RemoteControlClient.PLAYSTATE_PAUSED; + + if (ApolloUtils.hasJellyBeanMR2() && what.equals(POSITION_CHANGED)) { + mRemoteControlClient.setPlaybackState(playState, position(), 1.0f); + } else if (what.equals(PLAYSTATE_CHANGED)) { + mRemoteControlClient.setPlaybackState(playState); + } else if (what.equals(META_CHANGED) || what.equals(QUEUE_CHANGED)) { Bitmap albumArt = getAlbumArt(); if (albumArt != null) { // RemoteControlClient wants to recycle the bitmaps thrown at it, so we need @@ -1293,6 +1359,8 @@ public class MusicPlaybackService extends Service { mRemoteControlClient .editMetadata(true) .putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, getArtistName()) + .putString(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST, + getAlbumArtistName()) .putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, getAlbumName()) .putString(MediaMetadataRetriever.METADATA_KEY_TITLE, getTrackName()) .putLong(MediaMetadataRetriever.METADATA_KEY_DURATION, duration()) @@ -1405,19 +1473,12 @@ public class MusicPlaybackService extends Service { return; } mPlayPos = pos; - Cursor mCursor = getContentResolver().query( - MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, new String[] { - "_id" - }, "_id=" + mPlayList[mPlayPos], null, null); - if (mCursor == null || mCursor.getCount() == 0) { + updateCursor(mPlayList[mPlayPos]); + if (mCursor == null) { SystemClock.sleep(3000); - mCursor = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, - PROJECTION, "_id=" + mPlayList[mPlayPos], null, null); - } - if (mCursor != null) { - mCursor.close(); - mCursor = null; + updateCursor(mPlayList[mPlayPos]); } + closeCursor(); mOpenFailedCounter = 20; openCurrentAndNext(); if (!mPlayer.isInitialized()) { @@ -1515,18 +1576,12 @@ public class MusicPlaybackService extends Service { }; } try { - mCursor = resolver.query(uri, PROJECTION, where, selectionArgs, null); + updateCursor(where, selectionArgs); if (mCursor != null) { - if (mCursor.getCount() == 0) { - mCursor.close(); - mCursor = null; - } else { - mCursor.moveToNext(); - ensurePlayListCapacity(1); - mPlayListLen = 1; - mPlayList[0] = mCursor.getLong(IDCOLIDX); - mPlayPos = 0; - } + ensurePlayListCapacity(1); + mPlayListLen = 1; + mPlayList[0] = mCursor.getLong(IDCOLIDX); + mPlayPos = 0; } } catch (final UnsupportedOperationException ex) { } @@ -1687,6 +1742,20 @@ public class MusicPlaybackService extends Service { } /** + * Returns the artist name + * + * @return The current song artist name + */ + public String getAlbumArtistName() { + synchronized (this) { + if (mAlbumCursor == null) { + return null; + } + return mAlbumCursor.getString(mAlbumCursor.getColumnIndexOrThrow(AlbumColumns.ARTIST)); + } + } + + /** * Returns the album ID * * @return The current song album ID @@ -1741,7 +1810,9 @@ public class MusicPlaybackService extends Service { } else if (position > mPlayer.duration()) { position = mPlayer.duration(); } - return mPlayer.seek(position); + long result = mPlayer.seek(position); + notifyChange(POSITION_CHANGED); + return result; } return -1; } @@ -2259,7 +2330,7 @@ public class MusicPlaybackService extends Service { if (service.mCursor != null) { service.mCursor.close(); } - service.mCursor = service.getCursorForId(service.mPlayList[service.mPlayPos]); + service.updateCursor(service.mPlayList[service.mPlayPos]); service.notifyChange(META_CHANGED); service.updateNotification(); service.setNextTrack(); diff --git a/src/com/andrew/apollo/utils/ApolloUtils.java b/src/com/andrew/apollo/utils/ApolloUtils.java index 707967b..5e60dca 100644 --- a/src/com/andrew/apollo/utils/ApolloUtils.java +++ b/src/com/andrew/apollo/utils/ApolloUtils.java @@ -71,6 +71,17 @@ public final class ApolloUtils { } /** + * Used to determine if the device is running + * Jelly Bean MR2 (Android 4.3) or greater + * + * @return True if the device is running Jelly Bean MR2 or greater, + * false otherwise + */ + public static final boolean hasJellyBeanMR2() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2; + } + + /** * Used to determine if the device is a tablet or not * * @param context The {@link Context} to use. |