From ef3c76645f439917967b3aaaa641314482a171c8 Mon Sep 17 00:00:00 2001 From: Profpatsch Date: Wed, 25 Dec 2024 22:14:22 +0100 Subject: [PATCH 1/6] PlayerHolder/PlayerService: inline & remove duplicate player passing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The player in playerHolder is exactly the player inside the `PlayerService`, which in turn is exactly passed through the IBinder interface. Thus we don’t have to pass both. Instead add `PlayerService.getPlayer()`. Also inline a few methods of `PlayerHolder` and simplify. --- .../fragments/detail/VideoDetailFragment.java | 5 +- .../newpipe/player/PlayQueueActivity.java | 11 +++-- .../schabi/newpipe/player/PlayerService.java | 21 ++++++--- .../PlayerServiceExtendedEventListener.java | 4 +- .../newpipe/player/helper/PlayerHolder.java | 47 +++++++++---------- 5 files changed, 48 insertions(+), 40 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index 63077e92d44..2dd24fabf99 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -234,10 +234,9 @@ public final class VideoDetailFragment // Service management //////////////////////////////////////////////////////////////////////////*/ @Override - public void onServiceConnected(final Player connectedPlayer, - final PlayerService connectedPlayerService, + public void onServiceConnected(final PlayerService connectedPlayerService, final boolean playAfterConnect) { - player = connectedPlayer; + player = connectedPlayerService.getPlayer(); playerService = connectedPlayerService; // It will do nothing if the player is not in fullscreen mode diff --git a/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java b/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java index 195baecbda8..e936b9f4556 100644 --- a/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java +++ b/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java @@ -217,11 +217,16 @@ public void onServiceDisconnected(final ComponentName name) { } @Override - public void onServiceConnected(final ComponentName name, final IBinder service) { + public void onServiceConnected(final ComponentName name, final IBinder binder) { Log.d(TAG, "Player service is connected"); - if (service instanceof PlayerService.LocalBinder) { - player = ((PlayerService.LocalBinder) service).getPlayer(); + if (binder instanceof PlayerService.LocalBinder localBinder) { + final @Nullable PlayerService s = localBinder.getService(); + if (s == null) { + player = null; + } else { + player = s.getPlayer(); + } } if (player == null || player.getPlayQueue() == null || player.exoPlayerIsNull()) { diff --git a/app/src/main/java/org/schabi/newpipe/player/PlayerService.java b/app/src/main/java/org/schabi/newpipe/player/PlayerService.java index e7abf4320d5..924a0e25151 100644 --- a/app/src/main/java/org/schabi/newpipe/player/PlayerService.java +++ b/app/src/main/java/org/schabi/newpipe/player/PlayerService.java @@ -28,6 +28,8 @@ import android.os.IBinder; import android.util.Log; +import androidx.annotation.Nullable; + import org.schabi.newpipe.player.mediasession.MediaSessionPlayerUi; import org.schabi.newpipe.player.notification.NotificationPlayerUi; import org.schabi.newpipe.util.ThemeHelper; @@ -36,7 +38,9 @@ /** - * One service for all players. + * One background service for our player. Even though the player has multiple UIs + * (e.g. the audio-only UI, the main UI, the pulldown-menu UI), + * this allows us to keep playing even when switching between the different UIs. */ public final class PlayerService extends Service { private static final String TAG = PlayerService.class.getSimpleName(); @@ -46,6 +50,9 @@ public final class PlayerService extends Service { private final IBinder mBinder = new PlayerService.LocalBinder(this); + public Player getPlayer() { + return player; + } /*////////////////////////////////////////////////////////////////////////// // Service's LifeCycle @@ -167,6 +174,9 @@ public IBinder onBind(final Intent intent) { return mBinder; } + /** Allows us this {@link org.schabi.newpipe.player.PlayerService} over the Service boundary + * back to our {@link org.schabi.newpipe.player.helper.PlayerHolder}. + */ public static class LocalBinder extends Binder { private final WeakReference playerService; @@ -174,12 +184,11 @@ public static class LocalBinder extends Binder { this.playerService = new WeakReference<>(playerService); } - public PlayerService getService() { + /** Get the PlayerService object itself. + * @return this + * */ + public @Nullable PlayerService getService() { return playerService.get(); } - - public Player getPlayer() { - return playerService.get().player; - } } } diff --git a/app/src/main/java/org/schabi/newpipe/player/event/PlayerServiceExtendedEventListener.java b/app/src/main/java/org/schabi/newpipe/player/event/PlayerServiceExtendedEventListener.java index 8effe2f0e93..9e8c7cf764c 100644 --- a/app/src/main/java/org/schabi/newpipe/player/event/PlayerServiceExtendedEventListener.java +++ b/app/src/main/java/org/schabi/newpipe/player/event/PlayerServiceExtendedEventListener.java @@ -1,11 +1,9 @@ package org.schabi.newpipe.player.event; import org.schabi.newpipe.player.PlayerService; -import org.schabi.newpipe.player.Player; public interface PlayerServiceExtendedEventListener extends PlayerServiceEventListener { - void onServiceConnected(Player player, - PlayerService playerService, + void onServiceConnected(PlayerService playerService, boolean playAfterConnect); void onServiceDisconnected(); } diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java index 24939c1d8ad..70a1da6a7b5 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java @@ -43,6 +43,7 @@ public static synchronized PlayerHolder getInstance() { private final PlayerServiceConnection serviceConnection = new PlayerServiceConnection(); private boolean bound; + @Nullable private PlayerService playerService; @Nullable private Player player; @@ -108,13 +109,16 @@ public void setListener(@Nullable final PlayerServiceExtendedEventListener newLi // Force reload data from service if (player != null) { - listener.onServiceConnected(player, playerService, false); - startPlayerListener(); + listener.onServiceConnected(playerService, false); + player.setFragmentListener(internalListener); } } - // helper to handle context in common place as using the same - // context to bind/unbind a service is crucial + /** Helper to handle context in common place as using the same + * context to bind/unbind a service is crucial. + * + * @return the common context + * */ private Context getCommonContext() { return App.getInstance(); } @@ -131,7 +135,7 @@ public void startService(final boolean playAfterConnect, // bound twice. Prevent it with unbinding first unbind(context); ContextCompat.startForegroundService(context, new Intent(context, PlayerService.class)); - serviceConnection.doPlayAfterConnect(playAfterConnect); + serviceConnection.playAfterConnect = playAfterConnect; bind(context); } @@ -145,10 +149,6 @@ class PlayerServiceConnection implements ServiceConnection { private boolean playAfterConnect = false; - public void doPlayAfterConnect(final boolean playAfterConnection) { - this.playAfterConnect = playAfterConnection; - } - @Override public void onServiceDisconnected(final ComponentName compName) { if (DEBUG) { @@ -167,14 +167,21 @@ public void onServiceConnected(final ComponentName compName, final IBinder servi final PlayerService.LocalBinder localBinder = (PlayerService.LocalBinder) service; playerService = localBinder.getService(); - player = localBinder.getPlayer(); + player = playerService != null ? playerService.getPlayer() : null; + if (listener != null) { - listener.onServiceConnected(player, playerService, playAfterConnect); + listener.onServiceConnected(playerService, playAfterConnect); + } + if (player != null) { + player.setFragmentListener(internalListener); } - startPlayerListener(); } } + /** Connect to (and if needed start) the {@link PlayerService} + * and bind {@link PlayerServiceConnection} to it. + * @param context common holder context + * */ private void bind(final Context context) { if (DEBUG) { Log.d(TAG, "bind() called"); @@ -196,7 +203,9 @@ private void unbind(final Context context) { if (bound) { context.unbindService(serviceConnection); bound = false; - stopPlayerListener(); + if (player != null) { + player.removeFragmentListener(internalListener); + } playerService = null; player = null; if (listener != null) { @@ -205,18 +214,6 @@ private void unbind(final Context context) { } } - private void startPlayerListener() { - if (player != null) { - player.setFragmentListener(internalListener); - } - } - - private void stopPlayerListener() { - if (player != null) { - player.removeFragmentListener(internalListener); - } - } - private final PlayerServiceEventListener internalListener = new PlayerServiceEventListener() { @Override From a78bed700aba3a52e732e8e6bc1e7477209b3a29 Mon Sep 17 00:00:00 2001 From: Profpatsch Date: Thu, 26 Dec 2024 00:26:22 +0100 Subject: [PATCH 2/6] PlayerHolder: inline `bind` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only used once. Now the code looks weird … why is the service started twice?? --- .../newpipe/player/helper/PlayerHolder.java | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java index 70a1da6a7b5..74b1251786f 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java @@ -123,6 +123,13 @@ private Context getCommonContext() { return App.getInstance(); } + + /** Connect to (and if needed start) the {@link PlayerService} + * and bind {@link PlayerServiceConnection} to it. + * If the service is already started, only set the listener. + * @param playAfterConnect If the service is started, start playing immediately + * @param newListener set this listener + * */ public void startService(final boolean playAfterConnect, final PlayerServiceExtendedEventListener newListener) { final Context context = getCommonContext(); @@ -136,7 +143,17 @@ public void startService(final boolean playAfterConnect, unbind(context); ContextCompat.startForegroundService(context, new Intent(context, PlayerService.class)); serviceConnection.playAfterConnect = playAfterConnect; - bind(context); + + if (DEBUG) { + Log.d(TAG, "bind() called"); + } + + final Intent serviceIntent = new Intent(context, PlayerService.class); + bound = context.bindService(serviceIntent, serviceConnection, + Context.BIND_AUTO_CREATE); + if (!bound) { + context.unbindService(serviceConnection); + } } public void stopService() { @@ -178,23 +195,6 @@ public void onServiceConnected(final ComponentName compName, final IBinder servi } } - /** Connect to (and if needed start) the {@link PlayerService} - * and bind {@link PlayerServiceConnection} to it. - * @param context common holder context - * */ - private void bind(final Context context) { - if (DEBUG) { - Log.d(TAG, "bind() called"); - } - - final Intent serviceIntent = new Intent(context, PlayerService.class); - bound = context.bindService(serviceIntent, serviceConnection, - Context.BIND_AUTO_CREATE); - if (!bound) { - context.unbindService(serviceConnection); - } - } - private void unbind(final Context context) { if (DEBUG) { Log.d(TAG, "unbind() called"); From 8d15a141b19ff0548985eb688ff7c957cfeb0526 Mon Sep 17 00:00:00 2001 From: Profpatsch Date: Thu, 26 Dec 2024 00:26:59 +0100 Subject: [PATCH 3/6] PlayerHolder: invert isBound --- .../schabi/newpipe/fragments/detail/VideoDetailFragment.java | 4 ++-- .../java/org/schabi/newpipe/player/helper/PlayerHolder.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index 2dd24fabf99..eb497cd79f9 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -657,7 +657,7 @@ protected void initListeners() { }); setupBottomPlayer(); - if (!playerHolder.isBound()) { + if (playerHolder.isNotBoundYet()) { setHeightThumbnail(); } else { playerHolder.startService(false, this); @@ -1383,7 +1383,7 @@ public void onReceive(final Context context, final Intent intent) { bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); } // Rebound to the service if it was closed via notification or mini player - if (!playerHolder.isBound()) { + if (playerHolder.isNotBoundYet()) { playerHolder.startService( false, VideoDetailFragment.this); } diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java index 74b1251786f..18821ab09b5 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java @@ -81,8 +81,8 @@ public boolean isPlayQueueReady() { return player != null && player.getPlayQueue() != null; } - public boolean isBound() { - return bound; + public boolean isNotBoundYet() { + return !bound; } public int getQueueSize() { From 83d93e16e7ae5aade1f888278234199de82fcd84 Mon Sep 17 00:00:00 2001 From: Profpatsch Date: Thu, 26 Dec 2024 00:36:49 +0100 Subject: [PATCH 4/6] PlayerHolder: move unbind right next to stopService --- .../newpipe/player/helper/PlayerHolder.java | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java index 18821ab09b5..d4da8ea45ed 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java @@ -162,6 +162,26 @@ public void stopService() { context.stopService(new Intent(context, PlayerService.class)); } + + private void unbind(final Context context) { + if (DEBUG) { + Log.d(TAG, "unbind() called"); + } + + if (bound) { + context.unbindService(serviceConnection); + bound = false; + if (player != null) { + player.removeFragmentListener(internalListener); + } + playerService = null; + player = null; + if (listener != null) { + listener.onServiceDisconnected(); + } + } + } + class PlayerServiceConnection implements ServiceConnection { private boolean playAfterConnect = false; @@ -195,25 +215,6 @@ public void onServiceConnected(final ComponentName compName, final IBinder servi } } - private void unbind(final Context context) { - if (DEBUG) { - Log.d(TAG, "unbind() called"); - } - - if (bound) { - context.unbindService(serviceConnection); - bound = false; - if (player != null) { - player.removeFragmentListener(internalListener); - } - playerService = null; - player = null; - if (listener != null) { - listener.onServiceDisconnected(); - } - } - } - private final PlayerServiceEventListener internalListener = new PlayerServiceEventListener() { @Override From 6a4aaba4310c8fd72c9491b7c972efc2077852d4 Mon Sep 17 00:00:00 2001 From: Profpatsch Date: Thu, 26 Dec 2024 01:02:59 +0100 Subject: [PATCH 5/6] PlayerHolder: add some more docstrings --- .../schabi/newpipe/player/helper/PlayerHolder.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java index d4da8ea45ed..92ef16d0c74 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java @@ -23,6 +23,8 @@ import org.schabi.newpipe.player.event.PlayerServiceExtendedEventListener; import org.schabi.newpipe.player.playqueue.PlayQueue; +/** Singleton that manages a `PlayerService` + * and can be used to control the player instance through the service. */ public final class PlayerHolder { private PlayerHolder() { @@ -162,7 +164,11 @@ public void stopService() { context.stopService(new Intent(context, PlayerService.class)); } - + /** Call {@link Context#unbindService(ServiceConnection)} on our service + * (does not necesarily stop the service right away). + * Remove all our listeners and deinitialize them. + * @param context shared context + * */ private void unbind(final Context context) { if (DEBUG) { Log.d(TAG, "unbind() called"); @@ -215,6 +221,10 @@ public void onServiceConnected(final ComponentName compName, final IBinder servi } } + /** Delegate all {@link PlayerServiceEventListener} events to our current `listener` object. + * Only difference is that if {@link PlayerServiceEventListener#onServiceStopped()} is called, + * it also calls {@link PlayerHolder#unbind(Context)}. + * */ private final PlayerServiceEventListener internalListener = new PlayerServiceEventListener() { @Override From ce919215fbca18c8d99d0d91e4403dea48f5bcf2 Mon Sep 17 00:00:00 2001 From: Profpatsch Date: Thu, 26 Dec 2024 01:31:17 +0100 Subject: [PATCH 6/6] PlayerHolder: Separate holder and service event interface Should make it easier to seperate the two further later, both of them are only implemented by VideoDetailFragment anyway, which is kind of a code smell! --- .../fragments/detail/VideoDetailFragment.java | 20 ++++++----- .../player/event/PlayerEventListener.java | 1 + ...> PlayerHolderLifecycleEventListener.java} | 3 +- .../event/PlayerServiceEventListener.java | 3 ++ .../newpipe/player/helper/PlayerHolder.java | 36 +++++++++++-------- 5 files changed, 40 insertions(+), 23 deletions(-) rename app/src/main/java/org/schabi/newpipe/player/event/{PlayerServiceExtendedEventListener.java => PlayerHolderLifecycleEventListener.java} (64%) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index eb497cd79f9..976d5bdbeb9 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -95,7 +95,8 @@ import org.schabi.newpipe.player.PlayerService; import org.schabi.newpipe.player.PlayerType; import org.schabi.newpipe.player.event.OnKeyDownListener; -import org.schabi.newpipe.player.event.PlayerServiceExtendedEventListener; +import org.schabi.newpipe.player.event.PlayerHolderLifecycleEventListener; +import org.schabi.newpipe.player.event.PlayerServiceEventListener; import org.schabi.newpipe.player.helper.PlayerHelper; import org.schabi.newpipe.player.helper.PlayerHolder; import org.schabi.newpipe.player.playqueue.PlayQueue; @@ -136,7 +137,8 @@ public final class VideoDetailFragment extends BaseStateFragment implements BackPressable, - PlayerServiceExtendedEventListener, + PlayerServiceEventListener, + PlayerHolderLifecycleEventListener, OnKeyDownListener { public static final String KEY_SWITCHING_PLAYERS = "switching_players"; @@ -392,7 +394,7 @@ public void onDestroy() { if (activity.isFinishing() && isPlayerAvailable() && player.videoPlayerSelected()) { playerHolder.stopService(); } else { - playerHolder.setListener(null); + playerHolder.unsetListeners(); } PreferenceManager.getDefaultSharedPreferences(activity) @@ -660,7 +662,7 @@ protected void initListeners() { if (playerHolder.isNotBoundYet()) { setHeightThumbnail(); } else { - playerHolder.startService(false, this); + playerHolder.startService(false, this, this); } } @@ -1051,7 +1053,7 @@ private void openPopupPlayer(final boolean append) { // See UI changes while remote playQueue changes if (!isPlayerAvailable()) { - playerHolder.startService(false, this); + playerHolder.startService(false, this, this); } else { // FIXME Workaround #7427 player.setRecovery(); @@ -1114,7 +1116,7 @@ public void openVideoPlayerAutoFullscreen() { private void openNormalBackgroundPlayer(final boolean append) { // See UI changes while remote playQueue changes if (!isPlayerAvailable()) { - playerHolder.startService(false, this); + playerHolder.startService(false, this, this); } final PlayQueue queue = setupPlayQueueForIntent(append); @@ -1128,7 +1130,7 @@ private void openNormalBackgroundPlayer(final boolean append) { private void openMainPlayer() { if (!isPlayerServiceAvailable()) { - playerHolder.startService(autoPlayEnabled, this); + playerHolder.startService(autoPlayEnabled, this, this); return; } if (currentInfo == null) { @@ -1385,7 +1387,9 @@ public void onReceive(final Context context, final Intent intent) { // Rebound to the service if it was closed via notification or mini player if (playerHolder.isNotBoundYet()) { playerHolder.startService( - false, VideoDetailFragment.this); + false, + VideoDetailFragment.this, + VideoDetailFragment.this); } break; } diff --git a/app/src/main/java/org/schabi/newpipe/player/event/PlayerEventListener.java b/app/src/main/java/org/schabi/newpipe/player/event/PlayerEventListener.java index 2cca259c2f3..80c795e8c9a 100644 --- a/app/src/main/java/org/schabi/newpipe/player/event/PlayerEventListener.java +++ b/app/src/main/java/org/schabi/newpipe/player/event/PlayerEventListener.java @@ -5,6 +5,7 @@ import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.player.playqueue.PlayQueue; +/** Player-specific events like queue or progress updates. */ public interface PlayerEventListener { void onQueueUpdate(PlayQueue queue); void onPlaybackUpdate(int state, int repeatMode, boolean shuffled, diff --git a/app/src/main/java/org/schabi/newpipe/player/event/PlayerServiceExtendedEventListener.java b/app/src/main/java/org/schabi/newpipe/player/event/PlayerHolderLifecycleEventListener.java similarity index 64% rename from app/src/main/java/org/schabi/newpipe/player/event/PlayerServiceExtendedEventListener.java rename to app/src/main/java/org/schabi/newpipe/player/event/PlayerHolderLifecycleEventListener.java index 9e8c7cf764c..e5eaa09c734 100644 --- a/app/src/main/java/org/schabi/newpipe/player/event/PlayerServiceExtendedEventListener.java +++ b/app/src/main/java/org/schabi/newpipe/player/event/PlayerHolderLifecycleEventListener.java @@ -2,7 +2,8 @@ import org.schabi.newpipe.player.PlayerService; -public interface PlayerServiceExtendedEventListener extends PlayerServiceEventListener { +/** Gets signalled if our PlayerHolder (dis)connects from the PlayerService. */ +public interface PlayerHolderLifecycleEventListener { void onServiceConnected(PlayerService playerService, boolean playAfterConnect); void onServiceDisconnected(); diff --git a/app/src/main/java/org/schabi/newpipe/player/event/PlayerServiceEventListener.java b/app/src/main/java/org/schabi/newpipe/player/event/PlayerServiceEventListener.java index 8c18fd2ad1c..5feaebc0073 100644 --- a/app/src/main/java/org/schabi/newpipe/player/event/PlayerServiceEventListener.java +++ b/app/src/main/java/org/schabi/newpipe/player/event/PlayerServiceEventListener.java @@ -2,6 +2,9 @@ import com.google.android.exoplayer2.PlaybackException; +/** {@link org.schabi.newpipe.player.event.PlayerEventListener} that also gets called for + * application-specific events like screen rotation or UI changes. + */ public interface PlayerServiceEventListener extends PlayerEventListener { void onViewCreated(); diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java index 92ef16d0c74..478436d93e0 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java @@ -7,6 +7,7 @@ import android.os.IBinder; import android.util.Log; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; @@ -20,7 +21,7 @@ import org.schabi.newpipe.player.PlayerService; import org.schabi.newpipe.player.PlayerType; import org.schabi.newpipe.player.event.PlayerServiceEventListener; -import org.schabi.newpipe.player.event.PlayerServiceExtendedEventListener; +import org.schabi.newpipe.player.event.PlayerHolderLifecycleEventListener; import org.schabi.newpipe.player.playqueue.PlayQueue; /** Singleton that manages a `PlayerService` @@ -41,7 +42,8 @@ public static synchronized PlayerHolder getInstance() { private static final boolean DEBUG = MainActivity.DEBUG; private static final String TAG = PlayerHolder.class.getSimpleName(); - @Nullable private PlayerServiceExtendedEventListener listener; + @Nullable private PlayerServiceEventListener listener; + @Nullable private PlayerHolderLifecycleEventListener holderListener; private final PlayerServiceConnection serviceConnection = new PlayerServiceConnection(); private boolean bound; @@ -102,16 +104,19 @@ public int getQueuePosition() { return player.getPlayQueue().getIndex(); } - public void setListener(@Nullable final PlayerServiceExtendedEventListener newListener) { - listener = newListener; + public void unsetListeners() { + listener = null; + holderListener = null; + } - if (listener == null) { - return; - } + public void setListener(@NonNull final PlayerServiceEventListener newListener, + @NonNull final PlayerHolderLifecycleEventListener newHolderListener) { + listener = newListener; + holderListener = newHolderListener; // Force reload data from service if (player != null) { - listener.onServiceConnected(playerService, false); + holderListener.onServiceConnected(playerService, false); player.setFragmentListener(internalListener); } } @@ -131,11 +136,14 @@ private Context getCommonContext() { * If the service is already started, only set the listener. * @param playAfterConnect If the service is started, start playing immediately * @param newListener set this listener + * @param newHolderListener set this listener * */ public void startService(final boolean playAfterConnect, - final PlayerServiceExtendedEventListener newListener) { + final PlayerServiceEventListener newListener, + final PlayerHolderLifecycleEventListener newHolderListener + ) { final Context context = getCommonContext(); - setListener(newListener); + setListener(newListener, newHolderListener); if (bound) { return; } @@ -182,8 +190,8 @@ private void unbind(final Context context) { } playerService = null; player = null; - if (listener != null) { - listener.onServiceDisconnected(); + if (holderListener != null) { + holderListener.onServiceDisconnected(); } } } @@ -212,8 +220,8 @@ public void onServiceConnected(final ComponentName compName, final IBinder servi playerService = localBinder.getService(); player = playerService != null ? playerService.getPlayer() : null; - if (listener != null) { - listener.onServiceConnected(playerService, playAfterConnect); + if (holderListener != null) { + holderListener.onServiceConnected(playerService, playAfterConnect); } if (player != null) { player.setFragmentListener(internalListener);