Completely switched to MediaSession
This commit is contained in:
parent
16a6218cc8
commit
826d874758
3 changed files with 120 additions and 147 deletions
|
|
@ -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" />
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue