diff --git a/app/src/main/java/com/kabouzeid/gramophone/helper/MediaSessionHelper.java b/app/src/main/java/com/kabouzeid/gramophone/helper/MediaSessionHelper.java
new file mode 100644
index 00000000..373a0ef3
--- /dev/null
+++ b/app/src/main/java/com/kabouzeid/gramophone/helper/MediaSessionHelper.java
@@ -0,0 +1,70 @@
+package com.kabouzeid.gramophone.helper;
+
+import android.media.RemoteControlClient;
+import android.os.Build;
+import android.support.v4.media.session.MediaSessionCompat;
+import android.support.v4.media.session.PlaybackStateCompat;
+
+public class MediaSessionHelper {
+
+ public static void applyState(MediaSessionCompat session, PlaybackStateCompat playbackState) {
+ session.setPlaybackState(playbackState);
+ ensureTransportControls(session, playbackState);
+ }
+
+ private static void ensureTransportControls(MediaSessionCompat session, PlaybackStateCompat playbackState) {
+ long actions = playbackState.getActions();
+ Object rccObj = session.getRemoteControlClient();
+
+ if (actions != 0
+ && Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH
+ && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP
+ && rccObj != null) {
+
+ int transportControls = 0;
+
+ if ((actions & PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS) != 0) {
+ transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS;
+ }
+
+ if ((actions & PlaybackStateCompat.ACTION_REWIND) != 0) {
+ transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_REWIND;
+ }
+
+ if ((actions & PlaybackStateCompat.ACTION_PLAY) != 0) {
+ transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_PLAY;
+ }
+
+ if ((actions & PlaybackStateCompat.ACTION_PLAY_PAUSE) != 0) {
+ transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE;
+ }
+
+ if ((actions & PlaybackStateCompat.ACTION_PAUSE) != 0) {
+ transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_PAUSE;
+ }
+
+ if ((actions & PlaybackStateCompat.ACTION_STOP) != 0) {
+ transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_STOP;
+ }
+
+ if ((actions & PlaybackStateCompat.ACTION_FAST_FORWARD) != 0) {
+ transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_FAST_FORWARD;
+ }
+
+ if ((actions & PlaybackStateCompat.ACTION_SKIP_TO_NEXT) != 0) {
+ transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_NEXT;
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ if ((actions & PlaybackStateCompat.ACTION_SEEK_TO) != 0) {
+ transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_POSITION_UPDATE;
+ }
+
+ if ((actions & PlaybackStateCompat.ACTION_SET_RATING) != 0) {
+ transportControls |= RemoteControlClient.FLAG_KEY_MEDIA_RATING;
+ }
+ }
+ ((RemoteControlClient) rccObj).setTransportControlFlags(transportControls);
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/kabouzeid/gramophone/helper/PlayingNotificationHelper.java b/app/src/main/java/com/kabouzeid/gramophone/helper/PlayingNotificationHelper.java
index 99a5e777..a84aa05e 100644
--- a/app/src/main/java/com/kabouzeid/gramophone/helper/PlayingNotificationHelper.java
+++ b/app/src/main/java/com/kabouzeid/gramophone/helper/PlayingNotificationHelper.java
@@ -5,16 +5,15 @@ package com.kabouzeid.gramophone.helper;
*/
import android.app.Notification;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.support.v4.media.session.MediaSessionCompat;
import android.support.v7.app.NotificationCompat;
-import android.view.View;
-import android.widget.RemoteViews;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.model.Song;
@@ -22,192 +21,101 @@ import com.kabouzeid.gramophone.service.MusicService;
import com.kabouzeid.gramophone.ui.activities.MusicControllerActivity;
import com.kabouzeid.gramophone.util.MusicUtil;
import com.nostra13.universalimageloader.core.ImageLoader;
-import com.nostra13.universalimageloader.core.assist.FailReason;
-import com.nostra13.universalimageloader.core.assist.ImageSize;
-import com.nostra13.universalimageloader.core.assist.ViewScaleType;
-import com.nostra13.universalimageloader.core.imageaware.NonViewAware;
-import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
public class PlayingNotificationHelper {
public static final String TAG = PlayingNotificationHelper.class.getSimpleName();
- public static final int NOTIFICATION_ID = 1337;
- private final MusicService service;
+ public static Notification buildNotification(final Context context, MediaSessionCompat.Token sessionToken, final Song song, final boolean isPlaying) {
- private final NotificationManager notificationManager;
- private Notification notification = null;
+ NotificationCompat.MediaStyle style = new NotificationCompat.MediaStyle()
+ .setMediaSession(sessionToken)
+ .setShowActionsInCompactView(0, 1, 2);
- private RemoteViews notificationLayout;
- private RemoteViews notificationLayoutExpanded;
+ style.setShowCancelButton(true);
+ style.setCancelButtonIntent(retrievePlaybackAction(context, 3));
- private Song currentSong;
- private String currentAlbumArtUri;
+ Bitmap albumArt = ImageLoader.getInstance().loadImageSync(MusicUtil.getAlbumArtUri(song.albumId).toString());
+ if (albumArt == null) {
+ albumArt = BitmapFactory.decodeResource(context.getResources(), R.drawable.default_album_art);
+ }
- public PlayingNotificationHelper(final MusicService service) {
- this.service = service;
- notificationManager = (NotificationManager) service
- .getSystemService(Context.NOTIFICATION_SERVICE);
- }
-
- public void buildNotification(final Song song, final boolean isPlaying) {
- currentSong = song;
- notificationLayout = new RemoteViews(service.getPackageName(),
- R.layout.notification_playing);
- notificationLayoutExpanded = new RemoteViews(service.getPackageName(),
- R.layout.notification_playing_expanded);
-
- notification = new NotificationCompat.Builder(service)
+ return new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_notification)
- .setContentIntent(getOpenMusicControllerPendingIntent())
- .setCategory(NotificationCompat.CATEGORY_PROGRESS)
- .setPriority(NotificationCompat.PRIORITY_MAX)
+ .setLargeIcon(albumArt)
+ .setContentIntent(getOpenMusicControllerPendingIntent(context))
+ .setContentTitle(song.title)
+ .setContentText(song.artistName)
+ .setSubText(song.albumName)
+ .setWhen(0)
+ .setShowWhen(false)
+ .setStyle(style)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
- .setContent(notificationLayout)
- .setStyle(new NotificationCompat.MediaStyle())
+
+ .addAction(R.drawable.ic_skip_previous_white_36dp,
+ "",
+ retrievePlaybackAction(context, 2))
+
+ .addAction(isPlaying ? R.drawable.ic_pause_white_36dp : R.drawable.ic_play_arrow_white_36dp,
+ "",
+ retrievePlaybackAction(context, 0))
+
+ .addAction(R.drawable.ic_skip_next_white_36dp,
+ "",
+ retrievePlaybackAction(context, 1))
+
+ .setOnlyAlertOnce(true)
.build();
- notification.bigContentView = notificationLayoutExpanded;
-
- setUpCollapsedLayout();
- setUpExpandedLayout();
- loadAlbumArt();
- setUpPlaybackActions(isPlaying);
- setUpExpandedPlaybackActions(isPlaying);
-
- service.startForeground(NOTIFICATION_ID, notification);
}
- private PendingIntent getOpenMusicControllerPendingIntent() {
- Intent result = new Intent(service, MusicControllerActivity.class);
- TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(service);
+ private static PendingIntent getOpenMusicControllerPendingIntent(final Context context) {
+ Intent result = new Intent(context, MusicControllerActivity.class);
+ TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(context);
taskStackBuilder.addParentStack(MusicControllerActivity.class);
taskStackBuilder.addNextIntent(result);
return taskStackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
}
- private void setUpExpandedPlaybackActions(boolean isPlaying) {
- notificationLayoutExpanded.setOnClickPendingIntent(R.id.button_toggle_play_pause,
- retrievePlaybackActions(1));
-
- notificationLayoutExpanded.setOnClickPendingIntent(R.id.button_next,
- retrievePlaybackActions(2));
-
- notificationLayoutExpanded.setOnClickPendingIntent(R.id.button_prev,
- retrievePlaybackActions(3));
-
- notificationLayoutExpanded.setOnClickPendingIntent(R.id.button_quit,
- retrievePlaybackActions(4));
-
- notificationLayoutExpanded.setImageViewResource(R.id.button_toggle_play_pause,
- isPlaying ? R.drawable.ic_pause_white_48dp : R.drawable.ic_play_arrow_white_48dp);
- }
-
- private void setUpPlaybackActions(boolean isPlaying) {
- notificationLayout.setOnClickPendingIntent(R.id.button_toggle_play_pause,
- retrievePlaybackActions(1));
-
- notificationLayout.setOnClickPendingIntent(R.id.button_next,
- retrievePlaybackActions(2));
-
- notificationLayout.setOnClickPendingIntent(R.id.button_quit,
- retrievePlaybackActions(4));
-
- notificationLayout.setImageViewResource(R.id.button_toggle_play_pause,
- isPlaying ? R.drawable.ic_pause_white_48dp : R.drawable.ic_play_arrow_white_48dp);
- }
-
- private PendingIntent retrievePlaybackActions(final int which) {
- Intent action;
- PendingIntent pendingIntent;
- final ComponentName serviceName = new ComponentName(service, MusicService.class);
+ private static PendingIntent retrievePlaybackAction(final Context context, final int which) {
+ String actionString = null;
switch (which) {
- case 1:
- action = new Intent(MusicService.ACTION_TOGGLE_PLAYBACK);
- action.setComponent(serviceName);
- pendingIntent = PendingIntent.getService(service, 1, action, 0);
- return pendingIntent;
- case 2:
- action = new Intent(MusicService.ACTION_SKIP);
- action.setComponent(serviceName);
- pendingIntent = PendingIntent.getService(service, 2, action, 0);
- return pendingIntent;
- case 3:
- action = new Intent(MusicService.ACTION_REWIND);
- action.setComponent(serviceName);
- pendingIntent = PendingIntent.getService(service, 3, action, 0);
- return pendingIntent;
- case 4:
- action = new Intent(MusicService.ACTION_QUIT);
- action.setComponent(serviceName);
- pendingIntent = PendingIntent.getService(service, 4, action, 0);
- return pendingIntent;
- default:
+ case 0:
+ actionString = MusicService.ACTION_TOGGLE_PLAYBACK;
break;
+ case 1:
+ actionString = MusicService.ACTION_SKIP;
+ break;
+ case 2:
+ actionString = MusicService.ACTION_REWIND;
+ break;
+ case 3:
+ actionString = MusicService.ACTION_QUIT;
+ break;
+ }
+ if (actionString != null) {
+ final ComponentName serviceName = new ComponentName(context, MusicService.class);
+ Intent actionIntent = new Intent(actionString);
+ actionIntent.setComponent(serviceName);
+ return PendingIntent.getService(context, 0, actionIntent, 0);
}
return null;
}
- private void setUpCollapsedLayout() {
- if (currentSong != null) {
- notificationLayout.setTextViewText(R.id.song_title, currentSong.title);
- notificationLayout.setTextViewText(R.id.song_artist, currentSong.artistName);
- }
- }
-
- private void setUpExpandedLayout() {
- if (currentSong != null) {
- notificationLayoutExpanded.setTextViewText(R.id.song_title, currentSong.title);
- notificationLayoutExpanded.setTextViewText(R.id.song_artist, currentSong.artistName);
- notificationLayoutExpanded.setTextViewText(R.id.album_title, currentSong.albumName);
- }
- }
-
- private void loadAlbumArt() {
- currentAlbumArtUri = MusicUtil.getAlbumArtUri(currentSong.albumId).toString();
- ImageLoader.getInstance().displayImage(currentAlbumArtUri, new NonViewAware(new ImageSize(-1, -1), ViewScaleType.CROP), new SimpleImageLoadingListener() {
- @Override
- public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
- if (currentAlbumArtUri.equals(imageUri))
- // copy() prevents the original bitmap in the memory cache from being recycled by the remote views
- setAlbumArt(loadedImage.copy(loadedImage.getConfig(), true));
- }
-
- @Override
- public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
- if (currentAlbumArtUri.equals(imageUri))
- setAlbumArt(null);
- }
- });
- }
-
- private void setAlbumArt(Bitmap albumArt) {
- if (albumArt != null) {
- notificationLayout.setImageViewBitmap(R.id.album_art, albumArt);
- notificationLayoutExpanded.setImageViewBitmap(R.id.album_art, albumArt);
- } else {
- notificationLayout.setImageViewResource(R.id.album_art, R.drawable.default_album_art);
- notificationLayoutExpanded.setImageViewResource(R.id.album_art, R.drawable.default_album_art);
- }
- notificationManager.notify(NOTIFICATION_ID, notification);
- }
-
- public void killNotification() {
- service.stopForeground(true);
- notification = null;
- }
-
- public void updatePlayState(final boolean isPlaying) {
- if (notification == null || notificationManager == null) {
- return;
- }
- if (notificationLayout != null) {
- notificationLayout.setImageViewResource(R.id.button_toggle_play_pause,
- isPlaying ? R.drawable.ic_pause_white_48dp : R.drawable.ic_play_arrow_white_48dp);
- }
- if (notificationLayoutExpanded != null) {
- notificationLayoutExpanded.setImageViewResource(R.id.button_toggle_play_pause,
- isPlaying ? R.drawable.ic_pause_white_48dp : R.drawable.ic_play_arrow_white_48dp);
- }
- notificationManager.notify(NOTIFICATION_ID, notification);
- }
+// private void loadAlbumArt() {
+// currentAlbumArtUri = MusicUtil.getAlbumArtUri(currentSong.albumId).toString();
+// ImageLoader.getInstance().displayImage(currentAlbumArtUri, new NonViewAware(new ImageSize(-1, -1), ViewScaleType.CROP), new SimpleImageLoadingListener() {
+// @Override
+// public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
+// if (currentAlbumArtUri.equals(imageUri))
+// // copy() prevents the original bitmap in the memory cache from being recycled by the remote views
+// setAlbumArt(loadedImage.copy(loadedImage.getConfig(), true));
+// }
+//
+// @Override
+// public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
+// if (currentAlbumArtUri.equals(imageUri))
+// setAlbumArt(null);
+// }
+// });
+// }
}
diff --git a/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java b/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java
index 86cdf726..5a964b58 100644
--- a/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java
+++ b/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java
@@ -1,5 +1,7 @@
package com.kabouzeid.gramophone.service;
+import android.app.Notification;
+import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
@@ -10,10 +12,8 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.media.AudioManager;
-import android.media.MediaMetadata;
import android.media.MediaPlayer;
import android.media.audiofx.AudioEffect;
-import android.media.session.PlaybackState;
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
@@ -33,6 +33,7 @@ import android.widget.Toast;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.appwidget.MusicPlayerWidget;
+import com.kabouzeid.gramophone.helper.MediaSessionHelper;
import com.kabouzeid.gramophone.helper.PlayingNotificationHelper;
import com.kabouzeid.gramophone.helper.ShuffleHelper;
import com.kabouzeid.gramophone.misc.AppKeys;
@@ -56,6 +57,8 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
public static final String PHONOGRAPH_PACKAGE_NAME = "com.kabouzeid.gramophone";
public static final String MUSIC_PACKAGE_NAME = "com.android.music";
+ public static final int NOTIFICATION_ID = 1337;
+
public static final String ACTION_TOGGLE_PLAYBACK = "com.kabouzeid.gramophone.action.TOGGLE_PLAYBACK";
public static final String ACTION_PLAY = "com.kabouzeid.gramophone.action.PLAY";
public static final String ACTION_RESUME = "com.kabouzeid.gramophone.action.RESUME";
@@ -69,7 +72,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
public static final String PLAYSTATE_CHANGED = "com.kabouzeid.gramophone.playstatechanged";
public static final String REPEATMODE_CHANGED = "com.kabouzeid.gramophone.repeatmodechanged";
public static final String SHUFFLEMODE_CHANGED = "com.kabouzeid.gramophone.shufflemodechanged";
- public static final String POSITION_CHANGED = "com.kabouzeid.phonograph.positionchanged";
+ public static final String POSITION_IN_SONG_CHANGED = "com.kabouzeid.phonograph.positionchanged";
private static final int FOCUSCHANGE = 5;
private static final int DUCK = 6;
@@ -97,14 +100,14 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
private boolean thingsRegistered;
private boolean saveQueuesAgain;
private boolean isSavingQueues;
- private PlayingNotificationHelper playingNotificationHelper;
private AudioManager audioManager;
- private MediaSessionCompat mSession;
+ private MediaSessionCompat mediaSession;
private PowerManager.WakeLock wakeLock;
private String currentAlbumArtUri;
private MusicPlayerHandler playerHandler;
private boolean fadingDown = false;
private HandlerThread handlerThread;
+ private NotificationManager notificationManager;
private final BroadcastReceiver becomingNoisyReceiver = new BroadcastReceiver() {
@Override
@@ -129,7 +132,6 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
isPlayerPrepared = false;
playingQueue = new ArrayList<>();
originalPlayingQueue = new ArrayList<>();
- playingNotificationHelper = new PlayingNotificationHelper(this);
shuffleMode = PreferenceManager.getDefaultSharedPreferences(this).getInt(AppKeys.SP_SHUFFLE_MODE, 0);
repeatMode = PreferenceManager.getDefaultSharedPreferences(this).getInt(AppKeys.SP_REPEAT_MODE, 0);
@@ -143,18 +145,16 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
handlerThread.start();
playerHandler = new MusicPlayerHandler(this, handlerThread.getLooper());
- registerEverything();
+ notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
setUpMediaSession();
+
+ registerEverything();
}
private void setUpMediaSession() {
- Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
- mediaButtonIntent.setComponent(new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class));
- PendingIntent mediaPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0);
-
- mSession = new MediaSessionCompat(this, "Phonograph", new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class), mediaPendingIntent);
- mSession.setCallback(new MediaSessionCompat.Callback() {
+ mediaSession = new MediaSessionCompat(this, "Phonograph", new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class), getMediaButtonIntent());
+ mediaSession.setCallback(new MediaSessionCompat.Callback() {
@Override
public void onPause() {
pausePlaying(false);
@@ -186,7 +186,8 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
stopPlaying();
}
});
- mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
+ mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
+ MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
}
private void registerEverything() {
@@ -205,17 +206,10 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
return audioManager;
}
- private void initRemoteControlClient() {
-// Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
-// mediaButtonIntent.setComponent(new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class));
-// PendingIntent mediaPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0);
-// remoteControlClient = new RemoteControlClient(mediaPendingIntent);
-// remoteControlClient.setTransportControlFlags(
-// RemoteControlClient.FLAG_KEY_MEDIA_PLAY |
-// RemoteControlClient.FLAG_KEY_MEDIA_PAUSE |
-// RemoteControlClient.FLAG_KEY_MEDIA_NEXT |
-// RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS);
-// getAudioManager().registerRemoteControlClient(remoteControlClient);
+ private PendingIntent getMediaButtonIntent() {
+ Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+ mediaButtonIntent.setComponent(new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class));
+ return PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0);
}
@Override
@@ -292,7 +286,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
private void killEverythingAndReleaseResources() {
stopPlaying();
- playingNotificationHelper.killNotification();
+ stopForeground(true);
savePosition();
saveQueues();
stopSelf();
@@ -306,8 +300,8 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
player.release();
player = null;
}
- mSession.setActive(false);
- mSession.release();
+ mediaSession.setActive(false);
+ mediaSession.release();
notifyChange(PLAYSTATE_CHANGED);
}
@@ -383,13 +377,8 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDataSource(getApplicationContext(), trackUri);
player.prepareAsync();
- } catch (Exception e) {
- player.reset();
- player = null;
- notifyChange(PLAYSTATE_CHANGED);
-
- Toast.makeText(getApplicationContext(), getResources().getString(R.string.unplayable_file), Toast.LENGTH_SHORT).show();
- return;
+ } catch (Exception ignored) {
+ // handled in onError()
}
currentSongId = playingQueue.get(getPosition()).id;
notifyChange(META_CHANGED);
@@ -426,24 +415,26 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
final Song song = playingQueue.get(getPosition());
int playState = isPlaying()
- ? PlaybackState.STATE_PLAYING
- : PlaybackState.STATE_PAUSED;
+ ? PlaybackStateCompat.STATE_PLAYING
+ : PlaybackStateCompat.STATE_PAUSED;
- if (what.equals(PLAYSTATE_CHANGED) || what.equals(POSITION_CHANGED)) {
- mSession.setPlaybackState(new PlaybackStateCompat.Builder()
- .setState(playState, getSongProgressMillis(), 1.0f).build());
+ if (what.equals(PLAYSTATE_CHANGED) || what.equals(POSITION_IN_SONG_CHANGED)) {
+ MediaSessionHelper.applyState(mediaSession, new PlaybackStateCompat.Builder()
+ .setActions(getAvailablePlaybackStateActions())
+ .setState(playState, player != null ? getSongProgressMillis() : 0, 1.0f).build());
} else if (what.equals(META_CHANGED)) {
- mSession.setMetadata(new MediaMetadataCompat.Builder()
- .putString(MediaMetadata.METADATA_KEY_ARTIST, song.artistName)
- .putString(MediaMetadata.METADATA_KEY_ALBUM, song.albumName)
- .putString(MediaMetadata.METADATA_KEY_TITLE, song.title)
- .putLong(MediaMetadata.METADATA_KEY_DURATION, song.duration)
- .putLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER, getPosition() + 1)
- .putLong(MediaMetadata.METADATA_KEY_NUM_TRACKS, getPlayingQueue().size())
+ mediaSession.setMetadata(new MediaMetadataCompat.Builder()
+ .putString(MediaMetadataCompat.METADATA_KEY_ARTIST, song.artistName)
+ .putString(MediaMetadataCompat.METADATA_KEY_ALBUM, song.albumName)
+ .putString(MediaMetadataCompat.METADATA_KEY_TITLE, song.title)
+ .putLong(MediaMetadataCompat.METADATA_KEY_DURATION, song.duration)
+ .putLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER, getPosition() + 1)
+ .putLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS, getPlayingQueue().size())
.build());
- mSession.setPlaybackState(new PlaybackStateCompat.Builder()
- .setState(playState, getSongProgressMillis(), 1.0f).build());
+ MediaSessionHelper.applyState(mediaSession, new PlaybackStateCompat.Builder()
+ .setActions(getAvailablePlaybackStateActions())
+ .setState(playState, player != null ? getSongProgressMillis() : 0, 1.0f).build());
}
currentAlbumArtUri = MusicUtil.getAlbumArtUri(song.albumId).toString();
@@ -474,14 +465,34 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
}
private void updateMediaSessionBitmap(final Bitmap albumArt) {
- MediaMetadataCompat current = mSession.getController().getMetadata();
+ MediaMetadataCompat current = mediaSession.getController().getMetadata();
if (current == null) current = new MediaMetadataCompat.Builder().build();
- mSession.setMetadata(new MediaMetadataCompat.Builder(current)
- .putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, albumArt)
+ mediaSession.setMetadata(new MediaMetadataCompat.Builder(current)
+ .putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, albumArt)
.build());
}
+ private long getAvailablePlaybackStateActions() {
+ if (getPlayingQueue() == null || getPlayingQueue().isEmpty()) {
+ return 0;
+ }
+
+ long actions = PlaybackStateCompat.ACTION_PLAY_PAUSE;
+ if (isPlaying()) {
+ actions |= PlaybackStateCompat.ACTION_PAUSE;
+ } else {
+ actions |= PlaybackStateCompat.ACTION_PLAY;
+ }
+ if (getPosition() > 0) {
+ actions |= PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS;
+ }
+ if (getPosition() < getPlayingQueue().size() - 1) {
+ actions |= PlaybackStateCompat.ACTION_SKIP_TO_NEXT;
+ }
+ return actions;
+ }
+
private void setUpMediaPlayerIfNeeded() {
if (player == null) {
player = new MediaPlayer();
@@ -496,7 +507,14 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
}
private void updateNotification() {
- playingNotificationHelper.buildNotification(playingQueue.get(position), isPlaying());
+ final boolean isPlaying = isPlaying();
+ Notification notification = PlayingNotificationHelper.buildNotification(this, mediaSession.getSessionToken(), getPlayingQueue().get(getPosition()), isPlaying);
+ if (isPlaying)
+ startForeground(NOTIFICATION_ID, notification);
+ else {
+ notificationManager.notify(NOTIFICATION_ID, notification);
+ stopForeground(false);
+ }
}
private void updateWidgets() {
@@ -568,6 +586,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
player.reset();
player = null;
notifyChange(PLAYSTATE_CHANGED);
+ Toast.makeText(getApplicationContext(), getResources().getString(R.string.unplayable_file), Toast.LENGTH_SHORT).show();
return false;
}
@@ -723,7 +742,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
}
public void resumePlaying(boolean forceNoFading) {
- mSession.setActive(true);
+ mediaSession.setActive(true);
if (!forceNoFading && PreferenceUtils.getInstance(this).fadePlayPauseAndInterruptions()) {
playerHandler.removeMessages(FADEDOWNANDPAUSE);
playerHandler.sendEmptyMessage(FADEUPANDRESUME);
@@ -805,6 +824,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
public void seekTo(int millis) {
player.seekTo(millis);
+ notifyChange(POSITION_IN_SONG_CHANGED);
}
public boolean isPlayerPrepared() {
@@ -864,7 +884,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
private void notifyChange(final String what) {
updateMediaSession(what);
- if (what.equals(POSITION_CHANGED)) {
+ if (what.equals(POSITION_IN_SONG_CHANGED)) {
return;
}
@@ -887,7 +907,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
if (what.equals(PLAYSTATE_CHANGED)) {
final boolean isPlaying = isPlaying();
- playingNotificationHelper.updatePlayState(isPlaying);
+ updateNotification();
MusicPlayerWidget.updateWidgetsPlayState(this, isPlaying);
} else if (what.equals(META_CHANGED)) {
updateNotification();
@@ -962,7 +982,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
service.fadingDown = true;
service.notifyChange(PLAYSTATE_CHANGED);
}
- currentPlayPauseFadeVolume -= .1f;
+ currentPlayPauseFadeVolume -= .2f;
if (currentPlayPauseFadeVolume > 0f) {
sendEmptyMessageDelayed(FADEDOWNANDPAUSE, 10);
} else {
@@ -980,7 +1000,7 @@ public class MusicService extends Service implements MediaPlayer.OnPreparedListe
service.notifyChange(PLAYSTATE_CHANGED);
}
service.resume();
- currentPlayPauseFadeVolume += .1f;
+ currentPlayPauseFadeVolume += .2f;
if (currentPlayPauseFadeVolume < 1.0f) {
sendEmptyMessageDelayed(FADEUPANDRESUME, 10);
} else {
diff --git a/app/src/main/res/drawable-hdpi/ic_pause_white_36dp.png b/app/src/main/res/drawable-hdpi/ic_pause_white_36dp.png
new file mode 100644
index 00000000..ea4357b9
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_pause_white_36dp.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_pause_white_48dp.png b/app/src/main/res/drawable-hdpi/ic_pause_white_48dp.png
deleted file mode 100644
index 72dfa9fa..00000000
Binary files a/app/src/main/res/drawable-hdpi/ic_pause_white_48dp.png and /dev/null differ
diff --git a/app/src/main/res/drawable-hdpi/ic_play_arrow_white_36dp.png b/app/src/main/res/drawable-hdpi/ic_play_arrow_white_36dp.png
new file mode 100644
index 00000000..da31b445
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_play_arrow_white_36dp.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_play_arrow_white_48dp.png b/app/src/main/res/drawable-hdpi/ic_play_arrow_white_48dp.png
deleted file mode 100644
index 043acd80..00000000
Binary files a/app/src/main/res/drawable-hdpi/ic_play_arrow_white_48dp.png and /dev/null differ
diff --git a/app/src/main/res/drawable-hdpi/ic_skip_next_white_36dp.png b/app/src/main/res/drawable-hdpi/ic_skip_next_white_36dp.png
new file mode 100644
index 00000000..cbfb262d
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_skip_next_white_36dp.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_skip_previous_white_36dp.png b/app/src/main/res/drawable-hdpi/ic_skip_previous_white_36dp.png
new file mode 100644
index 00000000..39d15055
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_skip_previous_white_36dp.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_pause_white_36dp.png b/app/src/main/res/drawable-mdpi/ic_pause_white_36dp.png
new file mode 100644
index 00000000..418c664c
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_pause_white_36dp.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_pause_white_48dp.png b/app/src/main/res/drawable-mdpi/ic_pause_white_48dp.png
deleted file mode 100644
index 14b6d17d..00000000
Binary files a/app/src/main/res/drawable-mdpi/ic_pause_white_48dp.png and /dev/null differ
diff --git a/app/src/main/res/drawable-mdpi/ic_play_arrow_white_36dp.png b/app/src/main/res/drawable-mdpi/ic_play_arrow_white_36dp.png
new file mode 100644
index 00000000..fbdf1da0
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_play_arrow_white_36dp.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_play_arrow_white_48dp.png b/app/src/main/res/drawable-mdpi/ic_play_arrow_white_48dp.png
deleted file mode 100644
index a55d1992..00000000
Binary files a/app/src/main/res/drawable-mdpi/ic_play_arrow_white_48dp.png and /dev/null differ
diff --git a/app/src/main/res/drawable-mdpi/ic_skip_next_white_36dp.png b/app/src/main/res/drawable-mdpi/ic_skip_next_white_36dp.png
new file mode 100644
index 00000000..893cf2c6
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_skip_next_white_36dp.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_skip_previous_white_36dp.png b/app/src/main/res/drawable-mdpi/ic_skip_previous_white_36dp.png
new file mode 100644
index 00000000..b5395b6a
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_skip_previous_white_36dp.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_pause_white_36dp.png b/app/src/main/res/drawable-xhdpi/ic_pause_white_36dp.png
new file mode 100644
index 00000000..500cb7bf
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_pause_white_36dp.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_pause_white_48dp.png b/app/src/main/res/drawable-xhdpi/ic_pause_white_48dp.png
deleted file mode 100644
index dd4bfdba..00000000
Binary files a/app/src/main/res/drawable-xhdpi/ic_pause_white_48dp.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_play_arrow_white_36dp.png b/app/src/main/res/drawable-xhdpi/ic_play_arrow_white_36dp.png
new file mode 100644
index 00000000..1eb926d2
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_play_arrow_white_36dp.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_play_arrow_white_48dp.png b/app/src/main/res/drawable-xhdpi/ic_play_arrow_white_48dp.png
deleted file mode 100644
index 7cc00847..00000000
Binary files a/app/src/main/res/drawable-xhdpi/ic_play_arrow_white_48dp.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_skip_next_white_36dp.png b/app/src/main/res/drawable-xhdpi/ic_skip_next_white_36dp.png
new file mode 100644
index 00000000..fa85f189
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_skip_next_white_36dp.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_skip_previous_white_36dp.png b/app/src/main/res/drawable-xhdpi/ic_skip_previous_white_36dp.png
new file mode 100644
index 00000000..d5347eec
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_skip_previous_white_36dp.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_pause_white_36dp.png b/app/src/main/res/drawable-xxhdpi/ic_pause_white_36dp.png
new file mode 100644
index 00000000..60798c76
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_pause_white_36dp.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_pause_white_48dp.png b/app/src/main/res/drawable-xxhdpi/ic_pause_white_48dp.png
deleted file mode 100644
index 6365bd74..00000000
Binary files a/app/src/main/res/drawable-xxhdpi/ic_pause_white_48dp.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_play_arrow_white_36dp.png b/app/src/main/res/drawable-xxhdpi/ic_play_arrow_white_36dp.png
new file mode 100644
index 00000000..ad5a0ef5
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_play_arrow_white_36dp.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_play_arrow_white_48dp.png b/app/src/main/res/drawable-xxhdpi/ic_play_arrow_white_48dp.png
deleted file mode 100644
index de7f9bdb..00000000
Binary files a/app/src/main/res/drawable-xxhdpi/ic_play_arrow_white_48dp.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_skip_next_white_36dp.png b/app/src/main/res/drawable-xxhdpi/ic_skip_next_white_36dp.png
new file mode 100644
index 00000000..ac38e6d4
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_skip_next_white_36dp.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_skip_previous_white_36dp.png b/app/src/main/res/drawable-xxhdpi/ic_skip_previous_white_36dp.png
new file mode 100644
index 00000000..fbb27ab3
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_skip_previous_white_36dp.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_pause_white_36dp.png b/app/src/main/res/drawable-xxxhdpi/ic_pause_white_36dp.png
new file mode 100644
index 00000000..4b4daad4
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_pause_white_36dp.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_pause_white_48dp.png b/app/src/main/res/drawable-xxxhdpi/ic_pause_white_48dp.png
deleted file mode 100755
index 903bd9ab..00000000
Binary files a/app/src/main/res/drawable-xxxhdpi/ic_pause_white_48dp.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_play_arrow_white_36dp.png b/app/src/main/res/drawable-xxxhdpi/ic_play_arrow_white_36dp.png
new file mode 100644
index 00000000..4ee72e52
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_play_arrow_white_36dp.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_play_arrow_white_48dp.png b/app/src/main/res/drawable-xxxhdpi/ic_play_arrow_white_48dp.png
deleted file mode 100755
index f4f713e8..00000000
Binary files a/app/src/main/res/drawable-xxxhdpi/ic_play_arrow_white_48dp.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_skip_next_white_36dp.png b/app/src/main/res/drawable-xxxhdpi/ic_skip_next_white_36dp.png
new file mode 100644
index 00000000..a84f3422
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_skip_next_white_36dp.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_skip_previous_white_36dp.png b/app/src/main/res/drawable-xxxhdpi/ic_skip_previous_white_36dp.png
new file mode 100644
index 00000000..d2e06a92
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_skip_previous_white_36dp.png differ
diff --git a/app/src/main/res/layout-v21/notification_playing.xml b/app/src/main/res/layout-v21/notification_playing.xml
deleted file mode 100644
index 2baa5969..00000000
--- a/app/src/main/res/layout-v21/notification_playing.xml
+++ /dev/null
@@ -1,88 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout-v21/notification_playing_expanded.xml b/app/src/main/res/layout-v21/notification_playing_expanded.xml
deleted file mode 100644
index ba3172c2..00000000
--- a/app/src/main/res/layout-v21/notification_playing_expanded.xml
+++ /dev/null
@@ -1,114 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/notification_playing.xml b/app/src/main/res/layout/notification_playing.xml
deleted file mode 100644
index c7f21c1b..00000000
--- a/app/src/main/res/layout/notification_playing.xml
+++ /dev/null
@@ -1,88 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/notification_playing_expanded.xml b/app/src/main/res/layout/notification_playing_expanded.xml
deleted file mode 100644
index 263e5102..00000000
--- a/app/src/main/res/layout/notification_playing_expanded.xml
+++ /dev/null
@@ -1,121 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-