update dependency and refactor music service

This commit is contained in:
dkanada 2020-09-06 22:42:50 +09:00
commit 0f14bf037f
9 changed files with 34 additions and 112 deletions

View file

@ -48,7 +48,7 @@ dependencies {
implementation 'com.github.jellyfin.jellyfin-apiclient-java:android:0.7.3' implementation 'com.github.jellyfin.jellyfin-apiclient-java:android:0.7.3'
implementation 'com.google.android.exoplayer:exoplayer:2.11.4' implementation 'com.google.android.exoplayer:exoplayer:2.11.4'
implementation 'com.google.android.material:material:1.2.0' implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.core:core:1.3.1' implementation 'androidx.core:core:1.3.1'
implementation 'androidx.media:media:1.1.0' implementation 'androidx.media:media:1.1.0'

View file

@ -60,7 +60,6 @@ import java.util.Random;
public class MusicService extends Service implements SharedPreferences.OnSharedPreferenceChangeListener, Playback.PlaybackCallbacks { public class MusicService extends Service implements SharedPreferences.OnSharedPreferenceChangeListener, Playback.PlaybackCallbacks {
public static final String PHONOGRAPH_PACKAGE_NAME = "com.dkanada.gramophone"; public static final String PHONOGRAPH_PACKAGE_NAME = "com.dkanada.gramophone";
public static final String MUSIC_PACKAGE_NAME = "com.android.music";
public static final String ACTION_TOGGLE_PAUSE = PHONOGRAPH_PACKAGE_NAME + ".togglepause"; public static final String ACTION_TOGGLE_PAUSE = PHONOGRAPH_PACKAGE_NAME + ".togglepause";
public static final String ACTION_PLAY = PHONOGRAPH_PACKAGE_NAME + ".play"; public static final String ACTION_PLAY = PHONOGRAPH_PACKAGE_NAME + ".play";
@ -115,8 +114,8 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
public boolean pendingQuit = false; public boolean pendingQuit = false;
private AppWidgetAlbum appWidgetAlbum = AppWidgetAlbum.getInstance(); private AppWidgetAlbum appWidgetAlbum = AppWidgetAlbum.getInstance();
private AppWidgetClassic appWidgetClassic = AppWidgetClassic.getInstance();
private AppWidgetCard appWidgetCard = AppWidgetCard.getInstance(); private AppWidgetCard appWidgetCard = AppWidgetCard.getInstance();
private AppWidgetClassic appWidgetClassic = AppWidgetClassic.getInstance();
private Playback playback; private Playback playback;
private List<Song> playingQueue = new ArrayList<>(); private List<Song> playingQueue = new ArrayList<>();
@ -160,9 +159,13 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
private Handler uiThreadHandler; private Handler uiThreadHandler;
private static String getTrackUri(@NonNull Song song) { private static final long MEDIA_SESSION_ACTIONS = PlaybackStateCompat.ACTION_PLAY
return MusicUtil.getSongFileUri(song).toString(); | PlaybackStateCompat.ACTION_PAUSE
} | PlaybackStateCompat.ACTION_PLAY_PAUSE
| PlaybackStateCompat.ACTION_SKIP_TO_NEXT
| PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
| PlaybackStateCompat.ACTION_STOP
| PlaybackStateCompat.ACTION_SEEK_TO;
@Override @Override
public void onCreate() { public void onCreate() {
@ -199,8 +202,6 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
restoreState(); restoreState();
mediaSession.setActive(true); mediaSession.setActive(true);
sendBroadcast(new Intent("com.dkanada.gramophone.PHONOGRAPH_MUSIC_SERVICE_CREATED"));
} }
private AudioManager getAudioManager() { private AudioManager getAudioManager() {
@ -334,8 +335,6 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
releaseResources(); releaseResources();
PreferenceUtil.getInstance(this).unregisterOnSharedPreferenceChangedListener(this); PreferenceUtil.getInstance(this).unregisterOnSharedPreferenceChangedListener(this);
wakeLock.release(); wakeLock.release();
sendBroadcast(new Intent("com.dkanada.gramophone.PHONOGRAPH_MUSIC_SERVICE_DESTROYED"));
} }
@Override @Override
@ -371,14 +370,14 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
PreferenceManager.getDefaultSharedPreferences(this).edit().putInt(SAVED_POSITION, getPosition()).apply(); PreferenceManager.getDefaultSharedPreferences(this).edit().putInt(SAVED_POSITION, getPosition()).apply();
} }
private void savePositionInTrack() { private void saveProgress() {
PreferenceManager.getDefaultSharedPreferences(this).edit().putInt(SAVED_POSITION_IN_TRACK, getSongProgressMillis()).apply(); PreferenceManager.getDefaultSharedPreferences(this).edit().putInt(SAVED_POSITION_IN_TRACK, getSongProgressMillis()).apply();
} }
public void saveState() { public void saveState() {
saveQueues(); saveQueues();
savePosition(); savePosition();
savePositionInTrack(); saveProgress();
} }
private void saveQueues() { private void saveQueues() {
@ -390,8 +389,8 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
shuffleMode = PreferenceManager.getDefaultSharedPreferences(this).getInt(SAVED_SHUFFLE_MODE, 0); shuffleMode = PreferenceManager.getDefaultSharedPreferences(this).getInt(SAVED_SHUFFLE_MODE, 0);
repeatMode = PreferenceManager.getDefaultSharedPreferences(this).getInt(SAVED_REPEAT_MODE, 0); repeatMode = PreferenceManager.getDefaultSharedPreferences(this).getInt(SAVED_REPEAT_MODE, 0);
handleAndSendChangeInternal(SHUFFLE_MODE_CHANGED); notifyChange(SHUFFLE_MODE_CHANGED);
handleAndSendChangeInternal(REPEAT_MODE_CHANGED); notifyChange(REPEAT_MODE_CHANGED);
playerHandler.removeMessages(RESTORE_QUEUES); playerHandler.removeMessages(RESTORE_QUEUES);
playerHandler.sendEmptyMessage(RESTORE_QUEUES); playerHandler.sendEmptyMessage(RESTORE_QUEUES);
@ -473,10 +472,10 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
if (queue) { if (queue) {
// restore queue from database // restore queue from database
playback.queueDataSource(getTrackUri(getCurrentSong())); playback.queueDataSource(MusicUtil.getSongFileUri(getCurrentSong()));
} else { } else {
// set current song and start playback // set current song and start playback
playback.setDataSource(getTrackUri(getCurrentSong())); playback.setDataSource(MusicUtil.getSongFileUri(getCurrentSong()));
} }
} }
} }
@ -489,7 +488,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
private void prepareNextImpl() { private void prepareNextImpl() {
synchronized (this) { synchronized (this) {
nextPosition = getNextPosition(false); nextPosition = getNextPosition(false);
playback.queueDataSource(getTrackUri(getSongAt(nextPosition))); playback.queueDataSource(MusicUtil.getSongFileUri(getSongAt(nextPosition)));
} }
} }
@ -656,7 +655,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
.putInt(SAVED_REPEAT_MODE, repeatMode) .putInt(SAVED_REPEAT_MODE, repeatMode)
.apply(); .apply();
prepareNext(); prepareNext();
handleAndSendChangeInternal(REPEAT_MODE_CHANGED); notifyChange(REPEAT_MODE_CHANGED);
break; break;
} }
} }
@ -833,26 +832,6 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
} }
} }
public void playSongs(List<Song> songs, int shuffleMode) {
if (songs != null && !songs.isEmpty()) {
if (shuffleMode == SHUFFLE_MODE_SHUFFLE) {
int startPosition = 0;
if (!songs.isEmpty()) {
startPosition = new Random().nextInt(songs.size());
}
openQueue(songs, startPosition, false);
setShuffleMode(shuffleMode);
} else {
openQueue(songs, 0, false);
}
play();
} else {
Toast.makeText(getApplicationContext(), R.string.playlist_is_empty, Toast.LENGTH_LONG).show();
}
}
public void playPreviousSong(boolean force) { public void playPreviousSong(boolean force) {
playSongAt(getPreviousPosition(force)); playSongAt(getPreviousPosition(force));
} }
@ -974,57 +953,23 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
break; break;
} }
handleAndSendChangeInternal(SHUFFLE_MODE_CHANGED); notifyChange(SHUFFLE_MODE_CHANGED);
notifyChange(QUEUE_CHANGED); notifyChange(QUEUE_CHANGED);
} }
private void notifyChange(@NonNull final String what) { private void notifyChange(@NonNull final String what) {
handleAndSendChangeInternal(what);
sendPublicIntent(what);
}
private void handleAndSendChangeInternal(@NonNull final String what) {
handleChangeInternal(what); handleChangeInternal(what);
sendChangeInternal(what); sendChangeInternal(what);
} }
// to let other apps know whats playing like last.fm
private void sendPublicIntent(@NonNull final String what) {
final Intent intent = new Intent(what.replace(PHONOGRAPH_PACKAGE_NAME, MUSIC_PACKAGE_NAME));
final Song song = getCurrentSong();
intent.putExtra("id", song.id);
intent.putExtra("artist", song.artistName);
intent.putExtra("album", song.albumName);
intent.putExtra("track", song.title);
intent.putExtra("duration", song.duration);
intent.putExtra("position", (long) getSongProgressMillis());
intent.putExtra("playing", isPlaying());
intent.putExtra("scrobbling_source", PHONOGRAPH_PACKAGE_NAME);
sendStickyBroadcast(intent);
}
private void sendChangeInternal(final String what) { private void sendChangeInternal(final String what) {
sendBroadcast(new Intent(what)); sendBroadcast(new Intent(what));
appWidgetAlbum.notifyChange(this, what); appWidgetAlbum.notifyChange(this, what);
appWidgetClassic.notifyChange(this, what); appWidgetClassic.notifyChange(this, what);
appWidgetCard.notifyChange(this, what); appWidgetCard.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:
@ -1032,14 +977,14 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
updateMediaSessionPlaybackState(); updateMediaSessionPlaybackState();
final boolean isPlaying = isPlaying(); final boolean isPlaying = isPlaying();
if (!isPlaying && getSongProgressMillis() > 0) { if (!isPlaying && getSongProgressMillis() > 0) {
savePositionInTrack(); saveProgress();
} }
break; break;
case META_CHANGED: case META_CHANGED:
updateNotification(); updateNotification();
updateMediaSessionMetaData(); updateMediaSessionMetaData();
savePosition(); savePosition();
savePositionInTrack(); saveProgress();
break; break;
case QUEUE_CHANGED: case QUEUE_CHANGED:
// because playing queue size might have changed // because playing queue size might have changed
@ -1087,7 +1032,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
@Override @Override
public void onTrackStarted() { public void onTrackStarted() {
handleAndSendChangeInternal(PLAY_STATE_CHANGED); notifyChange(PLAY_STATE_CHANGED);
prepareNext(); prepareNext();
} }
@ -1279,8 +1224,8 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
@Override @Override
public void run() { public void run() {
savePositionInTrack(); saveProgress();
sendPublicIntent(PLAY_STATE_CHANGED); notifyChange(PLAY_STATE_CHANGED);
} }
} }
} }

View file

@ -88,6 +88,7 @@ public class PlayingNotificationImpl extends PlayingNotification {
if (target != null) { if (target != null) {
Glide.clear(target); Glide.clear(target);
} }
target = CustomGlideRequest.Builder.from(Glide.with(service), song.primary) target = CustomGlideRequest.Builder.from(Glide.with(service), song.primary)
.generatePalette(service).build() .generatePalette(service).build()
.into(new SimpleTarget<BitmapPaletteWrapper>(bigNotificationImageSize, bigNotificationImageSize) { .into(new SimpleTarget<BitmapPaletteWrapper>(bigNotificationImageSize, bigNotificationImageSize) {
@ -159,17 +160,17 @@ public class PlayingNotificationImpl extends PlayingNotification {
final ComponentName serviceName = new ComponentName(service, MusicService.class); final ComponentName serviceName = new ComponentName(service, MusicService.class);
// Previous track // previous track
pendingIntent = buildPendingIntent(service, MusicService.ACTION_REWIND, serviceName); pendingIntent = buildPendingIntent(service, MusicService.ACTION_REWIND, serviceName);
notificationLayout.setOnClickPendingIntent(R.id.action_prev, pendingIntent); notificationLayout.setOnClickPendingIntent(R.id.action_prev, pendingIntent);
notificationLayoutBig.setOnClickPendingIntent(R.id.action_prev, pendingIntent); notificationLayoutBig.setOnClickPendingIntent(R.id.action_prev, pendingIntent);
// Play and pause // toggle play and pause
pendingIntent = buildPendingIntent(service, MusicService.ACTION_TOGGLE_PAUSE, serviceName); pendingIntent = buildPendingIntent(service, MusicService.ACTION_TOGGLE_PAUSE, serviceName);
notificationLayout.setOnClickPendingIntent(R.id.action_play_pause, pendingIntent); notificationLayout.setOnClickPendingIntent(R.id.action_play_pause, pendingIntent);
notificationLayoutBig.setOnClickPendingIntent(R.id.action_play_pause, pendingIntent); notificationLayoutBig.setOnClickPendingIntent(R.id.action_play_pause, pendingIntent);
// Next track // next track
pendingIntent = buildPendingIntent(service, MusicService.ACTION_SKIP, serviceName); pendingIntent = buildPendingIntent(service, MusicService.ACTION_SKIP, serviceName);
notificationLayout.setOnClickPendingIntent(R.id.action_next, pendingIntent); notificationLayout.setOnClickPendingIntent(R.id.action_next, pendingIntent);
notificationLayoutBig.setOnClickPendingIntent(R.id.action_next, pendingIntent); notificationLayoutBig.setOnClickPendingIntent(R.id.action_next, pendingIntent);

View file

@ -100,7 +100,6 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements
setUpToolbar(); setUpToolbar();
setUpViews(); setUpViews();
if (Build.VERSION.SDK_INT > 21) postponeEnterTransition();
Album album = getIntent().getExtras().getParcelable(EXTRA_ALBUM); Album album = getIntent().getExtras().getParcelable(EXTRA_ALBUM);
loadAlbumCover(album.primary); loadAlbumCover(album.primary);
setAlbum(album); setAlbum(album);
@ -149,19 +148,6 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements
CustomGlideRequest.Builder CustomGlideRequest.Builder
.from(Glide.with(this), primary) .from(Glide.with(this), primary)
.generatePalette(this).build() .generatePalette(this).build()
.listener(new RequestListener<Object, BitmapPaletteWrapper>() {
@Override
public boolean onException(Exception e, Object model, Target<BitmapPaletteWrapper> target, boolean isFirstResource) {
if (Build.VERSION.SDK_INT > 21) startPostponedEnterTransition();
return false;
}
@Override
public boolean onResourceReady(BitmapPaletteWrapper resource, Object model, Target<BitmapPaletteWrapper> target, boolean dataSource, boolean isFirstResource) {
if (Build.VERSION.SDK_INT > 21) startPostponedEnterTransition();
return false;
}
})
.dontAnimate() .dontAnimate()
.into(new CustomPaletteTarget(albumArtImageView) { .into(new CustomPaletteTarget(albumArtImageView) {
@Override @Override

View file

@ -100,7 +100,6 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement
usePalette = PreferenceUtil.getInstance(this).getAlbumArtistColoredFooters(); usePalette = PreferenceUtil.getInstance(this).getAlbumArtistColoredFooters();
if (Build.VERSION.SDK_INT > 21) postponeEnterTransition();
Artist artist = getIntent().getExtras().getParcelable(EXTRA_ARTIST); Artist artist = getIntent().getExtras().getParcelable(EXTRA_ARTIST);
loadArtistImage(artist.primary); loadArtistImage(artist.primary);
setArtist(artist); setArtist(artist);
@ -181,19 +180,6 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement
CustomGlideRequest.Builder CustomGlideRequest.Builder
.from(Glide.with(this), primary) .from(Glide.with(this), primary)
.generatePalette(this).build() .generatePalette(this).build()
.listener(new RequestListener<Object, BitmapPaletteWrapper>() {
@Override
public boolean onException(Exception e, Object model, Target<BitmapPaletteWrapper> target, boolean isFirstResource) {
if (Build.VERSION.SDK_INT > 21) startPostponedEnterTransition();
return false;
}
@Override
public boolean onResourceReady(BitmapPaletteWrapper resource, Object model, Target<BitmapPaletteWrapper> target, boolean dataSource, boolean isFirstResource) {
if (Build.VERSION.SDK_INT > 21) startPostponedEnterTransition();
return false;
}
})
.dontAnimate() .dontAnimate()
.into(new CustomPaletteTarget(artistImage) { .into(new CustomPaletteTarget(artistImage) {
@Override @Override

View file

@ -151,6 +151,7 @@ public class PlaylistDetailActivity extends AbsSlidingMusicPanelActivity impleme
onBackPressed(); onBackPressed();
return true; return true;
} }
return PlaylistMenuHelper.handleMenuClick(this, playlist, item); return PlaylistMenuHelper.handleMenuClick(this, playlist, item);
} }

View file

@ -162,6 +162,7 @@ public abstract class AbsLibraryPagerRecyclerViewFragment<A extends RecyclerView
if (last > total - page / 2 && total < size) { if (last > total - page / 2 && total < size) {
query = createQuery(); query = createQuery();
loading = true; loading = true;
loadItems(getAdapter().getItemCount()); loadItems(getAdapter().getItemCount());
} }
} }

View file

@ -26,7 +26,7 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
public class MusicUtil { public class MusicUtil {
public static Uri getSongFileUri(Song song) { public static String getSongFileUri(Song song) {
PreferenceUtil preferenceUtil = PreferenceUtil.getInstance(App.getInstance()); PreferenceUtil preferenceUtil = PreferenceUtil.getInstance(App.getInstance());
StringBuilder builder = new StringBuilder(256); StringBuilder builder = new StringBuilder(256);
@ -67,7 +67,7 @@ public class MusicUtil {
builder.append("&api_key=").append(apiClient.getAccessToken()); builder.append("&api_key=").append(apiClient.getAccessToken());
Log.i(MusicUtil.class.getName(), "playing audio: " + builder); Log.i(MusicUtil.class.getName(), "playing audio: " + builder);
return Uri.parse(builder.toString()); return builder.toString();
} }
@NonNull @NonNull

View file

@ -95,6 +95,7 @@ public class AppWidgetAlbum extends BaseAppWidget {
if (target != null) { if (target != null) {
Glide.clear(target); Glide.clear(target);
} }
target = CustomGlideRequest.Builder.from(Glide.with(appContext), song.primary) target = CustomGlideRequest.Builder.from(Glide.with(appContext), song.primary)
.asBitmap().build() .asBitmap().build()
.into(new SimpleTarget<Bitmap>(widgetImageSize, widgetImageSize) { .into(new SimpleTarget<Bitmap>(widgetImageSize, widgetImageSize) {
@ -115,6 +116,7 @@ public class AppWidgetAlbum extends BaseAppWidget {
} else { } else {
appWidgetView.setImageViewBitmap(R.id.image, bitmap); appWidgetView.setImageViewBitmap(R.id.image, bitmap);
} }
pushUpdate(appContext, appWidgetIds, appWidgetView); pushUpdate(appContext, appWidgetIds, appWidgetView);
} }
}); });