Completely switched to MediaSession

This commit is contained in:
Karim Abou Zeid 2017-03-17 22:08:05 +01:00
commit 826d874758
3 changed files with 120 additions and 147 deletions

View file

@ -98,12 +98,6 @@
android:name=".service.MusicService" android:name=".service.MusicService"
android:enabled="true" /> android:enabled="true" />
<receiver android:name=".service.MediaButtonIntentReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
<meta-data <meta-data
android:name="com.crashlytics.ApiKey" android:name="com.crashlytics.ApiKey"
android:value="b23725bd3d266aa65c5a3dd1816b2f801524a189" /> android:value="b23725bd3d266aa65c5a3dd1816b2f801524a189" />

View file

@ -14,9 +14,8 @@ import android.graphics.Bitmap;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.media.AudioManager; import android.media.AudioManager;
import android.media.MediaMetadataRetriever;
import android.media.RemoteControlClient;
import android.media.audiofx.AudioEffect; import android.media.audiofx.AudioEffect;
import android.media.session.MediaSession;
import android.os.Binder; import android.os.Binder;
import android.os.Build; import android.os.Build;
import android.os.Handler; import android.os.Handler;
@ -30,6 +29,10 @@ import android.preference.PreferenceManager;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaButtonReceiver;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.widget.Toast; import android.widget.Toast;
import com.bumptech.glide.BitmapRequestBuilder; import com.bumptech.glide.BitmapRequestBuilder;
@ -50,7 +53,7 @@ import com.kabouzeid.gramophone.provider.MusicPlaybackQueueStore;
import com.kabouzeid.gramophone.provider.SongPlayCountStore; import com.kabouzeid.gramophone.provider.SongPlayCountStore;
import com.kabouzeid.gramophone.service.notification.PlayingNotification; import com.kabouzeid.gramophone.service.notification.PlayingNotification;
import com.kabouzeid.gramophone.service.notification.PlayingNotificationImpl; import com.kabouzeid.gramophone.service.notification.PlayingNotificationImpl;
import com.kabouzeid.gramophone.service.notification.PlayingNotificationImpl21; import com.kabouzeid.gramophone.service.notification.PlayingNotificationImpl24;
import com.kabouzeid.gramophone.service.playback.Playback; import com.kabouzeid.gramophone.service.playback.Playback;
import com.kabouzeid.gramophone.util.MusicUtil; import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.PreferenceUtil; import com.kabouzeid.gramophone.util.PreferenceUtil;
@ -129,11 +132,11 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
private int repeatMode; private int repeatMode;
private boolean queuesRestored; private boolean queuesRestored;
private boolean pausedByTransientLossOfFocus; private boolean pausedByTransientLossOfFocus;
private boolean receiversAndRemoteControlClientRegistered;
private PlayingNotification playingNotification; private PlayingNotification playingNotification;
private AudioManager audioManager; private AudioManager audioManager;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private RemoteControlClient remoteControlClient; private MediaSessionCompat mediaSession;
private MediaButtonIntentReceiver mediaButtonIntentReceiver = new MediaButtonIntentReceiver();
private PowerManager.WakeLock wakeLock; private PowerManager.WakeLock wakeLock;
private PlaybackHandler playerHandler; private PlaybackHandler playerHandler;
private final AudioManager.OnAudioFocusChangeListener audioFocusListener = new AudioManager.OnAudioFocusChangeListener() { private final AudioManager.OnAudioFocusChangeListener audioFocusListener = new AudioManager.OnAudioFocusChangeListener() {
@ -147,6 +150,8 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
private HandlerThread queueSaveHandlerThread; private HandlerThread queueSaveHandlerThread;
private SongPlayCountHelper songPlayCountHelper = new SongPlayCountHelper(); private SongPlayCountHelper songPlayCountHelper = new SongPlayCountHelper();
private ThrottledSeekHandler throttledSeekHandler; private ThrottledSeekHandler throttledSeekHandler;
private boolean becomingNoisyReceiverRegistered;
private IntentFilter becomingNoisyReceiverIntentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
private final BroadcastReceiver becomingNoisyReceiver = new BroadcastReceiver() { private final BroadcastReceiver becomingNoisyReceiver = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, @NonNull Intent intent) { public void onReceive(Context context, @NonNull Intent intent) {
@ -180,6 +185,8 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
playback = new MultiPlayer(this); playback = new MultiPlayer(this);
playback.setCallbacks(this); playback.setCallbacks(this);
setupMediaSession();
// queue saving needs to run on a separate thread so that it doesn't block the playback handler events // queue saving needs to run on a separate thread so that it doesn't block the playback handler events
queueSaveHandlerThread = new HandlerThread("QueueSaveHandler", Process.THREAD_PRIORITY_BACKGROUND); queueSaveHandlerThread = new HandlerThread("QueueSaveHandler", Process.THREAD_PRIORITY_BACKGROUND);
queueSaveHandlerThread.start(); queueSaveHandlerThread.start();
@ -187,12 +194,10 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
uiThreadHandler = new Handler(); uiThreadHandler = new Handler();
registerReceiversAndRemoteControlClient();
registerReceiver(widgetIntentReceiver, new IntentFilter(APP_WIDGET_UPDATE)); registerReceiver(widgetIntentReceiver, new IntentFilter(APP_WIDGET_UPDATE));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
playingNotification = new PlayingNotificationImpl21(); playingNotification = new PlayingNotificationImpl24();
} else { } else {
playingNotification = new PlayingNotificationImpl(); playingNotification = new PlayingNotificationImpl();
} }
@ -209,16 +214,9 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
restoreState(); restoreState();
sendBroadcast(new Intent("com.kabouzeid.gramophone.PHONOGRAPH_MUSIC_SERVICE_CREATED")); mediaSession.setActive(true);
}
private void registerReceiversAndRemoteControlClient() { sendBroadcast(new Intent("com.kabouzeid.gramophone.PHONOGRAPH_MUSIC_SERVICE_CREATED"));
if (!receiversAndRemoteControlClientRegistered) {
registerReceiver(becomingNoisyReceiver, new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
getAudioManager().registerMediaButtonEventReceiver(new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class));
initRemoteControlClient();
receiversAndRemoteControlClientRegistered = true;
}
} }
private AudioManager getAudioManager() { private AudioManager getAudioManager() {
@ -228,21 +226,62 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
return audioManager; return audioManager;
} }
@SuppressWarnings("deprecation") private void setupMediaSession() {
private void initRemoteControlClient() { ComponentName mediaButtonReceiverComponentName = new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class);
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
mediaButtonIntent.setComponent(new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class)); mediaButtonIntent.setComponent(mediaButtonReceiverComponentName);
remoteControlClient = new RemoteControlClient(PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0));
remoteControlClient.setTransportControlFlags( PendingIntent mediaButtonReceiverPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0);
RemoteControlClient.FLAG_KEY_MEDIA_PLAY |
RemoteControlClient.FLAG_KEY_MEDIA_PAUSE | mediaSession = new MediaSessionCompat(this, "Phonograph", mediaButtonReceiverComponentName, mediaButtonReceiverPendingIntent);
RemoteControlClient.FLAG_KEY_MEDIA_NEXT | mediaSession.setCallback(new MediaSessionCompat.Callback() {
RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS); @Override
getAudioManager().registerRemoteControlClient(remoteControlClient); public void onPlay() {
play();
}
@Override
public void onPause() {
pause();
}
@Override
public void onSkipToNext() {
playNextSong(true);
}
@Override
public void onSkipToPrevious() {
back(true);
}
@Override
public void onStop() {
quit();
}
@Override
public void onSeekTo(long pos) {
seek((int) pos);
}
@Override
public boolean onMediaButtonEvent(Intent mediaButtonEvent) {
mediaButtonIntentReceiver.onReceive(MusicService.this, mediaButtonEvent);
return true;
}
});
mediaSession.setFlags(MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS
| MediaSession.FLAG_HANDLES_MEDIA_BUTTONS);
mediaSession.setMediaButtonReceiver(mediaButtonReceiverPendingIntent);
} }
@Override @Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) { public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
MediaButtonReceiver.handleIntent(mediaSession, intent);
if (intent != null) { if (intent != null) {
if (intent.getAction() != null) { if (intent.getAction() != null) {
restoreQueuesAndPositionIfNecessary(); restoreQueuesAndPositionIfNecessary();
@ -268,8 +307,6 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
playNextSong(true); playNextSong(true);
break; break;
case ACTION_STOP: case ACTION_STOP:
stop();
break;
case ACTION_QUIT: case ACTION_QUIT:
return quit(); return quit();
} }
@ -282,6 +319,11 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
@Override @Override
public void onDestroy() { public void onDestroy() {
unregisterReceiver(widgetIntentReceiver); unregisterReceiver(widgetIntentReceiver);
if (becomingNoisyReceiverRegistered) {
unregisterReceiver(becomingNoisyReceiver);
becomingNoisyReceiverRegistered = false;
}
mediaSession.setActive(false);
quit(); quit();
releaseResources(); releaseResources();
getContentResolver().unregisterContentObserver(mediaStoreObserver); getContentResolver().unregisterContentObserver(mediaStoreObserver);
@ -311,15 +353,6 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
return true; return true;
} }
private void unregisterReceiversAndRemoteControlClient() {
if (receiversAndRemoteControlClientRegistered) {
unregisterReceiver(becomingNoisyReceiver);
getAudioManager().unregisterRemoteControlClient(remoteControlClient);
getAudioManager().unregisterMediaButtonEventReceiver(new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class));
receiversAndRemoteControlClientRegistered = false;
}
}
private static final class QueueSaveHandler extends Handler { private static final class QueueSaveHandler extends Handler {
@NonNull @NonNull
private final WeakReference<MusicService> mService; private final WeakReference<MusicService> mService;
@ -399,7 +432,6 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
} }
private int quit() { private int quit() {
unregisterReceiversAndRemoteControlClient();
pause(); pause();
playingNotification.stop(); playingNotification.stop();
@ -407,6 +439,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
return START_STICKY; return START_STICKY;
} else { } else {
closeAudioEffectSession(); closeAudioEffectSession();
getAudioManager().abandonAudioFocus(audioFocusListener);
stopSelf(); stopSelf();
return START_NOT_STICKY; return START_NOT_STICKY;
} }
@ -427,14 +460,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
} }
playback.release(); playback.release();
playback = null; playback = null;
} mediaSession.release();
public void stop() {
pausedByTransientLossOfFocus = false;
savePositionInTrack();
playback.stop();
notifyChange(PLAY_STATE_CHANGED);
getAudioManager().abandonAudioFocus(audioFocusListener);
} }
public boolean isPlaying() { public boolean isPlaying() {
@ -499,31 +525,29 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
return (getAudioManager().requestAudioFocus(audioFocusListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED); return (getAudioManager().requestAudioFocus(audioFocusListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
} }
private void updateRemoteControlClient() { private void updateMediaSession() {
updateRemoteControlClient(PreferenceUtil.getInstance(this).albumArtOnLockscreen(), PreferenceUtil.getInstance(this).blurredAlbumArt()); final Song song = getCurrentSong();
final MediaMetadataCompat.Builder metaData = new MediaMetadataCompat.Builder()
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, song.artistName)
.putString(MediaMetadataCompat.METADATA_KEY_ALBUM_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_YEAR, song.year)
.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, null);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
metaData.putLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS, getPlayingQueue().size());
} }
private void updateRemoteControlClient(boolean showAlbumArt, final boolean blurAlbumArt) { if (PreferenceUtil.getInstance(this).albumArtOnLockscreen()) {
final Song song = getCurrentSong();
remoteControlClient
.editMetadata(!showAlbumArt)
.putString(MediaMetadataRetriever.METADATA_KEY_TITLE, song.title)
.putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, song.albumName)
.putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, song.artistName)
.putString(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST, song.artistName)
.putLong(MediaMetadataRetriever.METADATA_KEY_DURATION, song.duration)
.putLong(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER, song.trackNumber)
// .putLong(MediaMetadataRetriever.METADATA_KEY_YEAR, song.year) // throws java.lang.IllegalArgumentException: Invalid type 'long' for key 8 on some Android versions
.apply();
if (showAlbumArt) {
final Point screenSize = Util.getScreenSize(MusicService.this); final Point screenSize = Util.getScreenSize(MusicService.this);
final BitmapRequestBuilder<?, Bitmap> request = SongGlideRequest.Builder.from(Glide.with(MusicService.this), song) final BitmapRequestBuilder<?, Bitmap> request = SongGlideRequest.Builder.from(Glide.with(MusicService.this), song)
.checkIgnoreMediaStore(MusicService.this) .checkIgnoreMediaStore(MusicService.this)
.asBitmap().build(); .asBitmap().build();
if (blurAlbumArt) { if (PreferenceUtil.getInstance(this).blurredAlbumArt()) {
request.transform(new BlurTransformation.Builder(MusicService.this).build()); request.transform(new BlurTransformation.Builder(MusicService.this).build());
} }
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
@ -533,28 +557,21 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
@Override @Override
public void onLoadFailed(Exception e, Drawable errorDrawable) { public void onLoadFailed(Exception e, Drawable errorDrawable) {
super.onLoadFailed(e, errorDrawable); super.onLoadFailed(e, errorDrawable);
updateRemoteControlClientBitmap(null); mediaSession.setMetadata(metaData.build());
} }
@Override @Override
public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) { public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
updateRemoteControlClientBitmap(copy(resource)); metaData.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, copy(resource));
mediaSession.setMetadata(metaData.build());
} }
}); });
} }
}); });
} else { } else {
updateRemoteControlClientBitmap(null); mediaSession.setMetadata(metaData.build());
}
} }
private void updateRemoteControlClientBitmap(final Bitmap albumArt) {
//noinspection deprecation
remoteControlClient
.editMetadata(false)
.putBitmap(RemoteControlClient.MetadataEditor.BITMAP_KEY_ARTWORK, albumArt)
.apply();
} }
private static Bitmap copy(Bitmap bitmap) { private static Bitmap copy(Bitmap bitmap) {
@ -787,8 +804,11 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
if (!playback.isInitialized()) { if (!playback.isInitialized()) {
playSongAt(getPosition()); playSongAt(getPosition());
} else { } else {
registerReceiversAndRemoteControlClient();
playback.start(); playback.start();
if (!becomingNoisyReceiverRegistered) {
registerReceiver(becomingNoisyReceiver, becomingNoisyReceiverIntentFilter);
becomingNoisyReceiverRegistered = true;
}
if (notHandledMetaChangedForCurrentTrack) { if (notHandledMetaChangedForCurrentTrack) {
handleChangeInternal(META_CHANGED); handleChangeInternal(META_CHANGED);
notHandledMetaChangedForCurrentTrack = false; notHandledMetaChangedForCurrentTrack = false;
@ -957,13 +977,25 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
appWidgetSmall.notifyChange(this, what); appWidgetSmall.notifyChange(this, what);
} }
private static final long MEDIA_SESSION_ACTIONS = PlaybackStateCompat.ACTION_PLAY
| PlaybackStateCompat.ACTION_PAUSE
| PlaybackStateCompat.ACTION_PLAY_PAUSE
| PlaybackStateCompat.ACTION_SKIP_TO_NEXT
| PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
| PlaybackStateCompat.ACTION_STOP
| PlaybackStateCompat.ACTION_SEEK_TO;
private void handleChangeInternal(@NonNull final String what) { private void handleChangeInternal(@NonNull final String what) {
switch (what) { switch (what) {
case PLAY_STATE_CHANGED: case PLAY_STATE_CHANGED:
final boolean isPlaying = isPlaying(); final boolean isPlaying = isPlaying();
playingNotification.update(); playingNotification.update();
//noinspection deprecation mediaSession.setPlaybackState(
remoteControlClient.setPlaybackState(isPlaying ? RemoteControlClient.PLAYSTATE_PLAYING : RemoteControlClient.PLAYSTATE_PAUSED); new PlaybackStateCompat.Builder()
.setActions(MEDIA_SESSION_ACTIONS)
.setState(isPlaying ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED,
getPosition(), 1)
.build());
if (!isPlaying && getSongProgressMillis() > 0) { if (!isPlaying && getSongProgressMillis() > 0) {
savePositionInTrack(); savePositionInTrack();
} }
@ -971,7 +1003,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
break; break;
case META_CHANGED: case META_CHANGED:
playingNotification.update(); playingNotification.update();
updateRemoteControlClient(); updateMediaSession();
savePosition(); savePosition();
savePositionInTrack(); savePositionInTrack();
final Song currentSong = getCurrentSong(); final Song currentSong = getCurrentSong();
@ -982,6 +1014,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
songPlayCountHelper.notifySongChanged(currentSong); songPlayCountHelper.notifySongChanged(currentSong);
break; break;
case QUEUE_CHANGED: case QUEUE_CHANGED:
updateMediaSession();
saveState(); saveState();
if (playingQueue.size() > 0) { if (playingQueue.size() > 0) {
prepareNext(); prepareNext();
@ -996,6 +1029,10 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
return playback.getAudioSessionId(); return playback.getAudioSessionId();
} }
public MediaSessionCompat getMediaSession() {
return mediaSession;
}
public void releaseWakeLock() { public void releaseWakeLock() {
if (wakeLock.isHeld()) { if (wakeLock.isHeld()) {
wakeLock.release(); wakeLock.release();
@ -1018,7 +1055,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
break; break;
case PreferenceUtil.ALBUM_ART_ON_LOCKSCREEN: case PreferenceUtil.ALBUM_ART_ON_LOCKSCREEN:
case PreferenceUtil.BLURRED_ALBUM_ART: case PreferenceUtil.BLURRED_ALBUM_ART:
updateRemoteControlClient(); updateMediaSession();
break; break;
case PreferenceUtil.COLORED_NOTIFICATION: case PreferenceUtil.COLORED_NOTIFICATION:
playingNotification.update(); playingNotification.update();
@ -1128,7 +1165,6 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
case FOCUS_CHANGE: case FOCUS_CHANGE:
switch (msg.arg1) { switch (msg.arg1) {
case AudioManager.AUDIOFOCUS_GAIN: case AudioManager.AUDIOFOCUS_GAIN:
service.registerReceiversAndRemoteControlClient();
if (!service.isPlaying() && service.pausedByTransientLossOfFocus) { if (!service.isPlaying() && service.pausedByTransientLossOfFocus) {
service.play(); service.play();
service.pausedByTransientLossOfFocus = false; service.pausedByTransientLossOfFocus = false;
@ -1140,7 +1176,6 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
case AudioManager.AUDIOFOCUS_LOSS: case AudioManager.AUDIOFOCUS_LOSS:
// Lost focus for an unbounded amount of time: stop playback and release media playback // Lost focus for an unbounded amount of time: stop playback and release media playback
service.pause(); service.pause();
service.unregisterReceiversAndRemoteControlClient();
break; break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:

View file

@ -9,9 +9,7 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.media.session.MediaSession;
import android.os.Build; import android.os.Build;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v7.app.NotificationCompat; import android.support.v7.app.NotificationCompat;
import android.support.v7.graphics.Palette; import android.support.v7.graphics.Palette;
import android.text.TextUtils; import android.text.TextUtils;
@ -23,13 +21,10 @@ import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.glide.SongGlideRequest; import com.kabouzeid.gramophone.glide.SongGlideRequest;
import com.kabouzeid.gramophone.glide.palette.BitmapPaletteWrapper; import com.kabouzeid.gramophone.glide.palette.BitmapPaletteWrapper;
import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.service.MediaButtonIntentReceiver;
import com.kabouzeid.gramophone.service.MusicService; import com.kabouzeid.gramophone.service.MusicService;
import com.kabouzeid.gramophone.ui.activities.MainActivity; import com.kabouzeid.gramophone.ui.activities.MainActivity;
import com.kabouzeid.gramophone.util.PreferenceUtil; import com.kabouzeid.gramophone.util.PreferenceUtil;
import hugo.weaving.DebugLog;
import static android.content.Context.NOTIFICATION_SERVICE; import static android.content.Context.NOTIFICATION_SERVICE;
import static com.kabouzeid.gramophone.service.MusicService.ACTION_REWIND; import static com.kabouzeid.gramophone.service.MusicService.ACTION_REWIND;
import static com.kabouzeid.gramophone.service.MusicService.ACTION_SKIP; import static com.kabouzeid.gramophone.service.MusicService.ACTION_SKIP;
@ -39,13 +34,12 @@ import static com.kabouzeid.gramophone.service.MusicService.ACTION_TOGGLE_PAUSE;
* @author Karim Abou Zeid (kabouzeid) * @author Karim Abou Zeid (kabouzeid)
*/ */
public class PlayingNotificationImpl21 implements PlayingNotification { public class PlayingNotificationImpl24 implements PlayingNotification {
private static final int NOTIFY_MODE_FOREGROUND = 1; private static final int NOTIFY_MODE_FOREGROUND = 1;
private static final int NOTIFY_MODE_BACKGROUND = 0; private static final int NOTIFY_MODE_BACKGROUND = 0;
private MusicService service; private MusicService service;
private MediaSessionCompat mediaSession;
private NotificationManager notificationManager; private NotificationManager notificationManager;
private int notifyMode = NOTIFY_MODE_BACKGROUND; private int notifyMode = NOTIFY_MODE_BACKGROUND;
@ -56,53 +50,6 @@ public class PlayingNotificationImpl21 implements PlayingNotification {
public synchronized void init(MusicService service) { public synchronized void init(MusicService service) {
this.service = service; this.service = service;
notificationManager = (NotificationManager) service.getSystemService(NOTIFICATION_SERVICE); notificationManager = (NotificationManager) service.getSystemService(NOTIFICATION_SERVICE);
setupMediaSession();
}
@DebugLog
private void setupMediaSession() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mediaSession = new MediaSessionCompat(service, "Phonograph");
mediaSession.setCallback(new MediaSessionCompat.Callback() {
@Override
public void onPlay() {
service.play();
}
@Override
public void onPause() {
service.pause();
}
@Override
public void onSkipToNext() {
service.playNextSong(true);
}
@Override
public void onSkipToPrevious() {
service.back(true);
}
@Override
public void onStop() {
service.stop();
}
@Override
public void onSeekTo(long pos) {
service.seek((int) pos);
}
});
PendingIntent pi = PendingIntent.getBroadcast(service, 0,
new Intent(service, MediaButtonIntentReceiver.class),
PendingIntent.FLAG_UPDATE_CURRENT);
mediaSession.setMediaButtonReceiver(pi);
mediaSession.setFlags(MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS
| MediaSession.FLAG_HANDLES_MEDIA_BUTTONS);
}
} }
@Override @Override
@ -174,7 +121,7 @@ public class PlayingNotificationImpl21 implements PlayingNotification {
.addAction(nextAction); .addAction(nextAction);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder.setStyle(new NotificationCompat.MediaStyle().setMediaSession(mediaSession.getSessionToken()).setShowActionsInCompactView(0, 1, 2)) builder.setStyle(new NotificationCompat.MediaStyle().setMediaSession(service.getMediaSession().getSessionToken()).setShowActionsInCompactView(0, 1, 2))
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC); .setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
if (PreferenceUtil.getInstance(service).coloredNotification()) if (PreferenceUtil.getInstance(service).coloredNotification())
builder.setColor(color); builder.setColor(color);
@ -184,9 +131,7 @@ public class PlayingNotificationImpl21 implements PlayingNotification {
return; // notification has been stopped before loading was finished return; // notification has been stopped before loading was finished
updateNotifyModeAndPostNotification(builder.build()); updateNotifyModeAndPostNotification(builder.build());
} }
}); });
} }
}); });
} }
@ -224,6 +169,5 @@ public class PlayingNotificationImpl21 implements PlayingNotification {
public synchronized void stop() { public synchronized void stop() {
stopped = true; stopped = true;
service.stopForeground(true); service.stopForeground(true);
mediaSession.release();
} }
} }