diff --git a/app/build.gradle b/app/build.gradle index ae0e7b3f..7a3ab366 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -48,7 +48,7 @@ dependencies { implementation 'com.github.jellyfin.jellyfin-apiclient-java:android:0.7.3' 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.media:media:1.1.0' diff --git a/app/src/main/java/com/dkanada/gramophone/service/MusicService.java b/app/src/main/java/com/dkanada/gramophone/service/MusicService.java index df9d4395..bb56fe29 100644 --- a/app/src/main/java/com/dkanada/gramophone/service/MusicService.java +++ b/app/src/main/java/com/dkanada/gramophone/service/MusicService.java @@ -60,7 +60,6 @@ import java.util.Random; public class MusicService extends Service implements SharedPreferences.OnSharedPreferenceChangeListener, Playback.PlaybackCallbacks { 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_PLAY = PHONOGRAPH_PACKAGE_NAME + ".play"; @@ -115,8 +114,8 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP public boolean pendingQuit = false; private AppWidgetAlbum appWidgetAlbum = AppWidgetAlbum.getInstance(); - private AppWidgetClassic appWidgetClassic = AppWidgetClassic.getInstance(); private AppWidgetCard appWidgetCard = AppWidgetCard.getInstance(); + private AppWidgetClassic appWidgetClassic = AppWidgetClassic.getInstance(); private Playback playback; private List playingQueue = new ArrayList<>(); @@ -160,9 +159,13 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP private Handler uiThreadHandler; - private static String getTrackUri(@NonNull Song song) { - return MusicUtil.getSongFileUri(song).toString(); - } + 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; @Override public void onCreate() { @@ -199,8 +202,6 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP restoreState(); mediaSession.setActive(true); - - sendBroadcast(new Intent("com.dkanada.gramophone.PHONOGRAPH_MUSIC_SERVICE_CREATED")); } private AudioManager getAudioManager() { @@ -334,8 +335,6 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP releaseResources(); PreferenceUtil.getInstance(this).unregisterOnSharedPreferenceChangedListener(this); wakeLock.release(); - - sendBroadcast(new Intent("com.dkanada.gramophone.PHONOGRAPH_MUSIC_SERVICE_DESTROYED")); } @Override @@ -371,14 +370,14 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP 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(); } public void saveState() { saveQueues(); savePosition(); - savePositionInTrack(); + saveProgress(); } private void saveQueues() { @@ -390,8 +389,8 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP shuffleMode = PreferenceManager.getDefaultSharedPreferences(this).getInt(SAVED_SHUFFLE_MODE, 0); repeatMode = PreferenceManager.getDefaultSharedPreferences(this).getInt(SAVED_REPEAT_MODE, 0); - handleAndSendChangeInternal(SHUFFLE_MODE_CHANGED); - handleAndSendChangeInternal(REPEAT_MODE_CHANGED); + notifyChange(SHUFFLE_MODE_CHANGED); + notifyChange(REPEAT_MODE_CHANGED); playerHandler.removeMessages(RESTORE_QUEUES); playerHandler.sendEmptyMessage(RESTORE_QUEUES); @@ -473,10 +472,10 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP if (queue) { // restore queue from database - playback.queueDataSource(getTrackUri(getCurrentSong())); + playback.queueDataSource(MusicUtil.getSongFileUri(getCurrentSong())); } else { // 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() { synchronized (this) { 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) .apply(); prepareNext(); - handleAndSendChangeInternal(REPEAT_MODE_CHANGED); + notifyChange(REPEAT_MODE_CHANGED); break; } } @@ -833,26 +832,6 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP } } - public void playSongs(List 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) { playSongAt(getPreviousPosition(force)); } @@ -974,57 +953,23 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP break; } - handleAndSendChangeInternal(SHUFFLE_MODE_CHANGED); + notifyChange(SHUFFLE_MODE_CHANGED); notifyChange(QUEUE_CHANGED); } private void notifyChange(@NonNull final String what) { - handleAndSendChangeInternal(what); - sendPublicIntent(what); - } - - private void handleAndSendChangeInternal(@NonNull final String what) { handleChangeInternal(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) { sendBroadcast(new Intent(what)); + appWidgetAlbum.notifyChange(this, what); appWidgetClassic.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) { switch (what) { case PLAY_STATE_CHANGED: @@ -1032,14 +977,14 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP updateMediaSessionPlaybackState(); final boolean isPlaying = isPlaying(); if (!isPlaying && getSongProgressMillis() > 0) { - savePositionInTrack(); + saveProgress(); } break; case META_CHANGED: updateNotification(); updateMediaSessionMetaData(); savePosition(); - savePositionInTrack(); + saveProgress(); break; case QUEUE_CHANGED: // because playing queue size might have changed @@ -1087,7 +1032,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP @Override public void onTrackStarted() { - handleAndSendChangeInternal(PLAY_STATE_CHANGED); + notifyChange(PLAY_STATE_CHANGED); prepareNext(); } @@ -1279,8 +1224,8 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP @Override public void run() { - savePositionInTrack(); - sendPublicIntent(PLAY_STATE_CHANGED); + saveProgress(); + notifyChange(PLAY_STATE_CHANGED); } } } diff --git a/app/src/main/java/com/dkanada/gramophone/service/notification/PlayingNotificationImpl.java b/app/src/main/java/com/dkanada/gramophone/service/notification/PlayingNotificationImpl.java index b653a733..c8f386b6 100644 --- a/app/src/main/java/com/dkanada/gramophone/service/notification/PlayingNotificationImpl.java +++ b/app/src/main/java/com/dkanada/gramophone/service/notification/PlayingNotificationImpl.java @@ -88,6 +88,7 @@ public class PlayingNotificationImpl extends PlayingNotification { if (target != null) { Glide.clear(target); } + target = CustomGlideRequest.Builder.from(Glide.with(service), song.primary) .generatePalette(service).build() .into(new SimpleTarget(bigNotificationImageSize, bigNotificationImageSize) { @@ -159,17 +160,17 @@ public class PlayingNotificationImpl extends PlayingNotification { final ComponentName serviceName = new ComponentName(service, MusicService.class); - // Previous track + // previous track pendingIntent = buildPendingIntent(service, MusicService.ACTION_REWIND, serviceName); notificationLayout.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); notificationLayout.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); notificationLayout.setOnClickPendingIntent(R.id.action_next, pendingIntent); notificationLayoutBig.setOnClickPendingIntent(R.id.action_next, pendingIntent); diff --git a/app/src/main/java/com/dkanada/gramophone/ui/activities/AlbumDetailActivity.java b/app/src/main/java/com/dkanada/gramophone/ui/activities/AlbumDetailActivity.java index 669cfa5a..0f9d18f8 100644 --- a/app/src/main/java/com/dkanada/gramophone/ui/activities/AlbumDetailActivity.java +++ b/app/src/main/java/com/dkanada/gramophone/ui/activities/AlbumDetailActivity.java @@ -100,7 +100,6 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements setUpToolbar(); setUpViews(); - if (Build.VERSION.SDK_INT > 21) postponeEnterTransition(); Album album = getIntent().getExtras().getParcelable(EXTRA_ALBUM); loadAlbumCover(album.primary); setAlbum(album); @@ -149,19 +148,6 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements CustomGlideRequest.Builder .from(Glide.with(this), primary) .generatePalette(this).build() - .listener(new RequestListener() { - @Override - public boolean onException(Exception e, Object model, Target target, boolean isFirstResource) { - if (Build.VERSION.SDK_INT > 21) startPostponedEnterTransition(); - return false; - } - - @Override - public boolean onResourceReady(BitmapPaletteWrapper resource, Object model, Target target, boolean dataSource, boolean isFirstResource) { - if (Build.VERSION.SDK_INT > 21) startPostponedEnterTransition(); - return false; - } - }) .dontAnimate() .into(new CustomPaletteTarget(albumArtImageView) { @Override diff --git a/app/src/main/java/com/dkanada/gramophone/ui/activities/ArtistDetailActivity.java b/app/src/main/java/com/dkanada/gramophone/ui/activities/ArtistDetailActivity.java index 87854cda..386ffbdb 100644 --- a/app/src/main/java/com/dkanada/gramophone/ui/activities/ArtistDetailActivity.java +++ b/app/src/main/java/com/dkanada/gramophone/ui/activities/ArtistDetailActivity.java @@ -100,7 +100,6 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement usePalette = PreferenceUtil.getInstance(this).getAlbumArtistColoredFooters(); - if (Build.VERSION.SDK_INT > 21) postponeEnterTransition(); Artist artist = getIntent().getExtras().getParcelable(EXTRA_ARTIST); loadArtistImage(artist.primary); setArtist(artist); @@ -181,19 +180,6 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement CustomGlideRequest.Builder .from(Glide.with(this), primary) .generatePalette(this).build() - .listener(new RequestListener() { - @Override - public boolean onException(Exception e, Object model, Target target, boolean isFirstResource) { - if (Build.VERSION.SDK_INT > 21) startPostponedEnterTransition(); - return false; - } - - @Override - public boolean onResourceReady(BitmapPaletteWrapper resource, Object model, Target target, boolean dataSource, boolean isFirstResource) { - if (Build.VERSION.SDK_INT > 21) startPostponedEnterTransition(); - return false; - } - }) .dontAnimate() .into(new CustomPaletteTarget(artistImage) { @Override diff --git a/app/src/main/java/com/dkanada/gramophone/ui/activities/PlaylistDetailActivity.java b/app/src/main/java/com/dkanada/gramophone/ui/activities/PlaylistDetailActivity.java index 1902a30a..691228ea 100644 --- a/app/src/main/java/com/dkanada/gramophone/ui/activities/PlaylistDetailActivity.java +++ b/app/src/main/java/com/dkanada/gramophone/ui/activities/PlaylistDetailActivity.java @@ -151,6 +151,7 @@ public class PlaylistDetailActivity extends AbsSlidingMusicPanelActivity impleme onBackPressed(); return true; } + return PlaylistMenuHelper.handleMenuClick(this, playlist, item); } diff --git a/app/src/main/java/com/dkanada/gramophone/ui/fragments/mainactivity/library/pager/AbsLibraryPagerRecyclerViewFragment.java b/app/src/main/java/com/dkanada/gramophone/ui/fragments/mainactivity/library/pager/AbsLibraryPagerRecyclerViewFragment.java index 82d04ce1..2f5e9662 100644 --- a/app/src/main/java/com/dkanada/gramophone/ui/fragments/mainactivity/library/pager/AbsLibraryPagerRecyclerViewFragment.java +++ b/app/src/main/java/com/dkanada/gramophone/ui/fragments/mainactivity/library/pager/AbsLibraryPagerRecyclerViewFragment.java @@ -162,6 +162,7 @@ public abstract class AbsLibraryPagerRecyclerViewFragment total - page / 2 && total < size) { query = createQuery(); loading = true; + loadItems(getAdapter().getItemCount()); } } diff --git a/app/src/main/java/com/dkanada/gramophone/util/MusicUtil.java b/app/src/main/java/com/dkanada/gramophone/util/MusicUtil.java index 593886c9..dfaaf464 100644 --- a/app/src/main/java/com/dkanada/gramophone/util/MusicUtil.java +++ b/app/src/main/java/com/dkanada/gramophone/util/MusicUtil.java @@ -26,7 +26,7 @@ import java.util.List; import java.util.Locale; public class MusicUtil { - public static Uri getSongFileUri(Song song) { + public static String getSongFileUri(Song song) { PreferenceUtil preferenceUtil = PreferenceUtil.getInstance(App.getInstance()); StringBuilder builder = new StringBuilder(256); @@ -67,7 +67,7 @@ public class MusicUtil { builder.append("&api_key=").append(apiClient.getAccessToken()); Log.i(MusicUtil.class.getName(), "playing audio: " + builder); - return Uri.parse(builder.toString()); + return builder.toString(); } @NonNull diff --git a/app/src/main/java/com/dkanada/gramophone/widgets/AppWidgetAlbum.java b/app/src/main/java/com/dkanada/gramophone/widgets/AppWidgetAlbum.java index 5a67a776..9390a373 100644 --- a/app/src/main/java/com/dkanada/gramophone/widgets/AppWidgetAlbum.java +++ b/app/src/main/java/com/dkanada/gramophone/widgets/AppWidgetAlbum.java @@ -95,6 +95,7 @@ public class AppWidgetAlbum extends BaseAppWidget { if (target != null) { Glide.clear(target); } + target = CustomGlideRequest.Builder.from(Glide.with(appContext), song.primary) .asBitmap().build() .into(new SimpleTarget(widgetImageSize, widgetImageSize) { @@ -115,6 +116,7 @@ public class AppWidgetAlbum extends BaseAppWidget { } else { appWidgetView.setImageViewBitmap(R.id.image, bitmap); } + pushUpdate(appContext, appWidgetIds, appWidgetView); } });