diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 642ddad9..6e0cd7d5 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -98,12 +98,6 @@
android:name=".service.MusicService"
android:enabled="true" />
-
-
-
-
-
-
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 387e6d55..28db5203 100644
--- a/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java
+++ b/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java
@@ -14,9 +14,8 @@ import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
-import android.media.MediaMetadataRetriever;
-import android.media.RemoteControlClient;
import android.media.audiofx.AudioEffect;
+import android.media.session.MediaSession;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
@@ -30,6 +29,10 @@ import android.preference.PreferenceManager;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
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 com.bumptech.glide.BitmapRequestBuilder;
@@ -50,7 +53,7 @@ import com.kabouzeid.gramophone.provider.MusicPlaybackQueueStore;
import com.kabouzeid.gramophone.provider.SongPlayCountStore;
import com.kabouzeid.gramophone.service.notification.PlayingNotification;
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.util.MusicUtil;
import com.kabouzeid.gramophone.util.PreferenceUtil;
@@ -129,11 +132,11 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
private int repeatMode;
private boolean queuesRestored;
private boolean pausedByTransientLossOfFocus;
- private boolean receiversAndRemoteControlClientRegistered;
private PlayingNotification playingNotification;
private AudioManager audioManager;
@SuppressWarnings("deprecation")
- private RemoteControlClient remoteControlClient;
+ private MediaSessionCompat mediaSession;
+ private MediaButtonIntentReceiver mediaButtonIntentReceiver = new MediaButtonIntentReceiver();
private PowerManager.WakeLock wakeLock;
private PlaybackHandler playerHandler;
private final AudioManager.OnAudioFocusChangeListener audioFocusListener = new AudioManager.OnAudioFocusChangeListener() {
@@ -147,6 +150,8 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
private HandlerThread queueSaveHandlerThread;
private SongPlayCountHelper songPlayCountHelper = new SongPlayCountHelper();
private ThrottledSeekHandler throttledSeekHandler;
+ private boolean becomingNoisyReceiverRegistered;
+ private IntentFilter becomingNoisyReceiverIntentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
private final BroadcastReceiver becomingNoisyReceiver = new BroadcastReceiver() {
@Override
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.setCallbacks(this);
+ setupMediaSession();
+
// 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.start();
@@ -187,12 +194,10 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
uiThreadHandler = new Handler();
- registerReceiversAndRemoteControlClient();
-
registerReceiver(widgetIntentReceiver, new IntentFilter(APP_WIDGET_UPDATE));
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- playingNotification = new PlayingNotificationImpl21();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ playingNotification = new PlayingNotificationImpl24();
} else {
playingNotification = new PlayingNotificationImpl();
}
@@ -209,16 +214,9 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
restoreState();
- sendBroadcast(new Intent("com.kabouzeid.gramophone.PHONOGRAPH_MUSIC_SERVICE_CREATED"));
- }
+ mediaSession.setActive(true);
- private void registerReceiversAndRemoteControlClient() {
- if (!receiversAndRemoteControlClientRegistered) {
- registerReceiver(becomingNoisyReceiver, new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
- getAudioManager().registerMediaButtonEventReceiver(new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class));
- initRemoteControlClient();
- receiversAndRemoteControlClientRegistered = true;
- }
+ sendBroadcast(new Intent("com.kabouzeid.gramophone.PHONOGRAPH_MUSIC_SERVICE_CREATED"));
}
private AudioManager getAudioManager() {
@@ -228,21 +226,62 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
return audioManager;
}
- @SuppressWarnings("deprecation")
- private void initRemoteControlClient() {
+ private void setupMediaSession() {
+ ComponentName mediaButtonReceiverComponentName = new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class);
+
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
- mediaButtonIntent.setComponent(new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class));
- remoteControlClient = new RemoteControlClient(PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0));
- 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);
+ mediaButtonIntent.setComponent(mediaButtonReceiverComponentName);
+
+ PendingIntent mediaButtonReceiverPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0);
+
+ mediaSession = new MediaSessionCompat(this, "Phonograph", mediaButtonReceiverComponentName, mediaButtonReceiverPendingIntent);
+ mediaSession.setCallback(new MediaSessionCompat.Callback() {
+ @Override
+ 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
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
+ MediaButtonReceiver.handleIntent(mediaSession, intent);
if (intent != null) {
if (intent.getAction() != null) {
restoreQueuesAndPositionIfNecessary();
@@ -268,8 +307,6 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
playNextSong(true);
break;
case ACTION_STOP:
- stop();
- break;
case ACTION_QUIT:
return quit();
}
@@ -282,6 +319,11 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
@Override
public void onDestroy() {
unregisterReceiver(widgetIntentReceiver);
+ if (becomingNoisyReceiverRegistered) {
+ unregisterReceiver(becomingNoisyReceiver);
+ becomingNoisyReceiverRegistered = false;
+ }
+ mediaSession.setActive(false);
quit();
releaseResources();
getContentResolver().unregisterContentObserver(mediaStoreObserver);
@@ -311,15 +353,6 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
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 {
@NonNull
private final WeakReference mService;
@@ -399,7 +432,6 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
}
private int quit() {
- unregisterReceiversAndRemoteControlClient();
pause();
playingNotification.stop();
@@ -407,6 +439,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
return START_STICKY;
} else {
closeAudioEffectSession();
+ getAudioManager().abandonAudioFocus(audioFocusListener);
stopSelf();
return START_NOT_STICKY;
}
@@ -427,14 +460,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
}
playback.release();
playback = null;
- }
-
- public void stop() {
- pausedByTransientLossOfFocus = false;
- savePositionInTrack();
- playback.stop();
- notifyChange(PLAY_STATE_CHANGED);
- getAudioManager().abandonAudioFocus(audioFocusListener);
+ mediaSession.release();
}
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);
}
- private void updateRemoteControlClient() {
- updateRemoteControlClient(PreferenceUtil.getInstance(this).albumArtOnLockscreen(), PreferenceUtil.getInstance(this).blurredAlbumArt());
- }
-
- private void updateRemoteControlClient(boolean showAlbumArt, final boolean blurAlbumArt) {
+ private void updateMediaSession() {
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)
+ 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);
- .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
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ metaData.putLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS, getPlayingQueue().size());
+ }
- .apply();
- if (showAlbumArt) {
+ if (PreferenceUtil.getInstance(this).albumArtOnLockscreen()) {
final Point screenSize = Util.getScreenSize(MusicService.this);
final BitmapRequestBuilder, Bitmap> request = SongGlideRequest.Builder.from(Glide.with(MusicService.this), song)
.checkIgnoreMediaStore(MusicService.this)
.asBitmap().build();
- if (blurAlbumArt) {
+ if (PreferenceUtil.getInstance(this).blurredAlbumArt()) {
request.transform(new BlurTransformation.Builder(MusicService.this).build());
}
runOnUiThread(new Runnable() {
@@ -533,28 +557,21 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
@Override
public void onLoadFailed(Exception e, Drawable errorDrawable) {
super.onLoadFailed(e, errorDrawable);
- updateRemoteControlClientBitmap(null);
+ mediaSession.setMetadata(metaData.build());
}
@Override
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 {
- 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) {
@@ -787,8 +804,11 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
if (!playback.isInitialized()) {
playSongAt(getPosition());
} else {
- registerReceiversAndRemoteControlClient();
playback.start();
+ if (!becomingNoisyReceiverRegistered) {
+ registerReceiver(becomingNoisyReceiver, becomingNoisyReceiverIntentFilter);
+ becomingNoisyReceiverRegistered = true;
+ }
if (notHandledMetaChangedForCurrentTrack) {
handleChangeInternal(META_CHANGED);
notHandledMetaChangedForCurrentTrack = false;
@@ -957,13 +977,25 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
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) {
switch (what) {
case PLAY_STATE_CHANGED:
final boolean isPlaying = isPlaying();
playingNotification.update();
- //noinspection deprecation
- remoteControlClient.setPlaybackState(isPlaying ? RemoteControlClient.PLAYSTATE_PLAYING : RemoteControlClient.PLAYSTATE_PAUSED);
+ mediaSession.setPlaybackState(
+ new PlaybackStateCompat.Builder()
+ .setActions(MEDIA_SESSION_ACTIONS)
+ .setState(isPlaying ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED,
+ getPosition(), 1)
+ .build());
if (!isPlaying && getSongProgressMillis() > 0) {
savePositionInTrack();
}
@@ -971,7 +1003,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
break;
case META_CHANGED:
playingNotification.update();
- updateRemoteControlClient();
+ updateMediaSession();
savePosition();
savePositionInTrack();
final Song currentSong = getCurrentSong();
@@ -982,6 +1014,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
songPlayCountHelper.notifySongChanged(currentSong);
break;
case QUEUE_CHANGED:
+ updateMediaSession();
saveState();
if (playingQueue.size() > 0) {
prepareNext();
@@ -996,6 +1029,10 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
return playback.getAudioSessionId();
}
+ public MediaSessionCompat getMediaSession() {
+ return mediaSession;
+ }
+
public void releaseWakeLock() {
if (wakeLock.isHeld()) {
wakeLock.release();
@@ -1018,7 +1055,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
break;
case PreferenceUtil.ALBUM_ART_ON_LOCKSCREEN:
case PreferenceUtil.BLURRED_ALBUM_ART:
- updateRemoteControlClient();
+ updateMediaSession();
break;
case PreferenceUtil.COLORED_NOTIFICATION:
playingNotification.update();
@@ -1128,7 +1165,6 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
case FOCUS_CHANGE:
switch (msg.arg1) {
case AudioManager.AUDIOFOCUS_GAIN:
- service.registerReceiversAndRemoteControlClient();
if (!service.isPlaying() && service.pausedByTransientLossOfFocus) {
service.play();
service.pausedByTransientLossOfFocus = false;
@@ -1140,7 +1176,6 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
case AudioManager.AUDIOFOCUS_LOSS:
// Lost focus for an unbounded amount of time: stop playback and release media playback
service.pause();
- service.unregisterReceiversAndRemoteControlClient();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
diff --git a/app/src/main/java/com/kabouzeid/gramophone/service/notification/PlayingNotificationImpl21.java b/app/src/main/java/com/kabouzeid/gramophone/service/notification/PlayingNotificationImpl24.java
similarity index 80%
rename from app/src/main/java/com/kabouzeid/gramophone/service/notification/PlayingNotificationImpl21.java
rename to app/src/main/java/com/kabouzeid/gramophone/service/notification/PlayingNotificationImpl24.java
index 435e1ade..056a2eae 100644
--- a/app/src/main/java/com/kabouzeid/gramophone/service/notification/PlayingNotificationImpl21.java
+++ b/app/src/main/java/com/kabouzeid/gramophone/service/notification/PlayingNotificationImpl24.java
@@ -9,9 +9,7 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
-import android.media.session.MediaSession;
import android.os.Build;
-import android.support.v4.media.session.MediaSessionCompat;
import android.support.v7.app.NotificationCompat;
import android.support.v7.graphics.Palette;
import android.text.TextUtils;
@@ -23,13 +21,10 @@ import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.glide.SongGlideRequest;
import com.kabouzeid.gramophone.glide.palette.BitmapPaletteWrapper;
import com.kabouzeid.gramophone.model.Song;
-import com.kabouzeid.gramophone.service.MediaButtonIntentReceiver;
import com.kabouzeid.gramophone.service.MusicService;
import com.kabouzeid.gramophone.ui.activities.MainActivity;
import com.kabouzeid.gramophone.util.PreferenceUtil;
-import hugo.weaving.DebugLog;
-
import static android.content.Context.NOTIFICATION_SERVICE;
import static com.kabouzeid.gramophone.service.MusicService.ACTION_REWIND;
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)
*/
-public class PlayingNotificationImpl21 implements PlayingNotification {
+public class PlayingNotificationImpl24 implements PlayingNotification {
private static final int NOTIFY_MODE_FOREGROUND = 1;
private static final int NOTIFY_MODE_BACKGROUND = 0;
private MusicService service;
- private MediaSessionCompat mediaSession;
private NotificationManager notificationManager;
private int notifyMode = NOTIFY_MODE_BACKGROUND;
@@ -56,53 +50,6 @@ public class PlayingNotificationImpl21 implements PlayingNotification {
public synchronized void init(MusicService service) {
this.service = 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
@@ -174,7 +121,7 @@ public class PlayingNotificationImpl21 implements PlayingNotification {
.addAction(nextAction);
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);
if (PreferenceUtil.getInstance(service).coloredNotification())
builder.setColor(color);
@@ -184,9 +131,7 @@ public class PlayingNotificationImpl21 implements PlayingNotification {
return; // notification has been stopped before loading was finished
updateNotifyModeAndPostNotification(builder.build());
}
-
});
-
}
});
}
@@ -224,6 +169,5 @@ public class PlayingNotificationImpl21 implements PlayingNotification {
public synchronized void stop() {
stopped = true;
service.stopForeground(true);
- mediaSession.release();
}
}