mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 15:23:00 +00:00 
			
		
		
		
	PlayerHolder: use object class to implement singleton pattern
This commit is contained in:
		| @@ -849,7 +849,7 @@ public class MainActivity extends AppCompatActivity { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (PlayerHolder.Companion.getInstance().isPlayerOpen()) { | ||||
|         if (PlayerHolder.INSTANCE.isPlayerOpen()) { | ||||
|             // if the player is already open, no need for a broadcast receiver | ||||
|             openMiniPlayerIfMissing(); | ||||
|         } else { | ||||
| @@ -859,7 +859,7 @@ public class MainActivity extends AppCompatActivity { | ||||
|                 public void onReceive(final Context context, final Intent intent) { | ||||
|                     if (Objects.equals(intent.getAction(), | ||||
|                             VideoDetailFragment.ACTION_PLAYER_STARTED) | ||||
|                             && PlayerHolder.Companion.getInstance().isPlayerOpen()) { | ||||
|                             && PlayerHolder.INSTANCE.isPlayerOpen()) { | ||||
|                         openMiniPlayerIfMissing(); | ||||
|                         // At this point the player is added 100%, we can unregister. Other actions | ||||
|                         // are useless since the fragment will not be removed after that. | ||||
| @@ -874,7 +874,7 @@ public class MainActivity extends AppCompatActivity { | ||||
|  | ||||
|             // If the PlayerHolder is not bound yet, but the service is running, try to bind to it. | ||||
|             // Once the connection is established, the ACTION_PLAYER_STARTED will be sent. | ||||
|             PlayerHolder.Companion.getInstance().tryBindIfNeeded(this); | ||||
|             PlayerHolder.INSTANCE.tryBindIfNeeded(this); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -701,7 +701,7 @@ public class RouterActivity extends AppCompatActivity { | ||||
|         } | ||||
|  | ||||
|         // ...the player is not running or in normal Video-mode/type | ||||
|         final PlayerType playerType = PlayerHolder.Companion.getInstance().getType(); | ||||
|         final PlayerType playerType = PlayerHolder.INSTANCE.getType(); | ||||
|         return playerType == null || playerType == PlayerType.MAIN; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -100,7 +100,7 @@ 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.helper.PlayerHelper | ||||
| import org.schabi.newpipe.player.helper.PlayerHolder.Companion.getInstance | ||||
| import org.schabi.newpipe.player.helper.PlayerHolder | ||||
| import org.schabi.newpipe.player.playqueue.PlayQueue | ||||
| import org.schabi.newpipe.player.playqueue.SinglePlayQueue | ||||
| import org.schabi.newpipe.player.playqueue.events.PlayQueueEvent | ||||
| @@ -212,7 +212,6 @@ class VideoDetailFragment : | ||||
|     private var settingsContentObserver: ContentObserver? = null | ||||
|     private var playerService: PlayerService? = null | ||||
|     private var player: Player? = null | ||||
|     private val playerHolder = getInstance() | ||||
|  | ||||
|     /*////////////////////////////////////////////////////////////////////////// | ||||
|     // Service management | ||||
| @@ -367,9 +366,9 @@ class VideoDetailFragment : | ||||
|         // Stop the service when user leaves the app with double back press | ||||
|         // if video player is selected. Otherwise unbind | ||||
|         if (activity.isFinishing() && this.isPlayerAvailable && player!!.videoPlayerSelected()) { | ||||
|             playerHolder.stopService() | ||||
|             PlayerHolder.stopService() | ||||
|         } else { | ||||
|             playerHolder.setListener(null) | ||||
|             PlayerHolder.setListener(null) | ||||
|         } | ||||
|  | ||||
|         PreferenceManager.getDefaultSharedPreferences(activity) | ||||
| @@ -768,10 +767,10 @@ class VideoDetailFragment : | ||||
|         ) | ||||
|  | ||||
|         setupBottomPlayer() | ||||
|         if (!playerHolder.isBound) { | ||||
|         if (!PlayerHolder.isBound) { | ||||
|             setHeightThumbnail() | ||||
|         } else { | ||||
|             playerHolder.startService(false, this) | ||||
|             PlayerHolder.startService(false, this) | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -1175,7 +1174,7 @@ class VideoDetailFragment : | ||||
|  | ||||
|         // See UI changes while remote playQueue changes | ||||
|         if (!this.isPlayerAvailable) { | ||||
|             playerHolder.startService(false, this) | ||||
|             PlayerHolder.startService(false, this) | ||||
|         } else { | ||||
|             // FIXME Workaround #7427 | ||||
|             player!!.setRecovery() | ||||
| @@ -1245,7 +1244,7 @@ class VideoDetailFragment : | ||||
|     private fun openNormalBackgroundPlayer(append: Boolean) { | ||||
|         // See UI changes while remote playQueue changes | ||||
|         if (!this.isPlayerAvailable) { | ||||
|             playerHolder.startService(false, this) | ||||
|             PlayerHolder.startService(false, this) | ||||
|         } | ||||
|  | ||||
|         val queue = setupPlayQueueForIntent(append) | ||||
| @@ -1263,7 +1262,7 @@ class VideoDetailFragment : | ||||
|  | ||||
|     private fun openMainPlayer() { | ||||
|         if (noPlayerServiceAvailable()) { | ||||
|             playerHolder.startService(autoPlayEnabled, this) | ||||
|             PlayerHolder.startService(autoPlayEnabled, this) | ||||
|             return | ||||
|         } | ||||
|         if (currentInfo == null) { | ||||
| @@ -1298,7 +1297,7 @@ class VideoDetailFragment : | ||||
|             playerService!!.stopForImmediateReusing() | ||||
|             root.ifPresent(Consumer { view: View -> view.setVisibility(View.GONE) }) | ||||
|         } else { | ||||
|             playerHolder.stopService() | ||||
|             PlayerHolder.stopService() | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -1551,8 +1550,8 @@ class VideoDetailFragment : | ||||
|                             bottomSheetBehavior!!.setState(BottomSheetBehavior.STATE_COLLAPSED) | ||||
|                         } | ||||
|                         // Rebound to the service if it was closed via notification or mini player | ||||
|                         if (!playerHolder.isBound) { | ||||
|                             playerHolder.startService( | ||||
|                         if (!PlayerHolder.isBound) { | ||||
|                             PlayerHolder.startService( | ||||
|                                 false, this@VideoDetailFragment | ||||
|                             ) | ||||
|                         } | ||||
| @@ -2472,7 +2471,7 @@ class VideoDetailFragment : | ||||
|         if (currentWorker != null) { | ||||
|             currentWorker!!.dispose() | ||||
|         } | ||||
|         playerHolder.stopService() | ||||
|         PlayerHolder.stopService() | ||||
|         setInitialData(0, null, "", null) | ||||
|         currentInfo = null | ||||
|         updateOverlayData(null, null, mutableListOf<Image>()) | ||||
|   | ||||
| @@ -252,7 +252,7 @@ public final class InfoItemDialog { | ||||
|          * @return the current {@link Builder} instance | ||||
|          */ | ||||
|         public Builder addEnqueueEntriesIfNeeded() { | ||||
|             final PlayerHolder holder = PlayerHolder.Companion.getInstance(); | ||||
|             final PlayerHolder holder = PlayerHolder.INSTANCE; | ||||
|             if (holder.isPlayQueueReady()) { | ||||
|                 addEntry(StreamDialogDefaultEntry.ENQUEUE); | ||||
|  | ||||
|   | ||||
| @@ -22,12 +22,19 @@ import org.schabi.newpipe.player.playqueue.PlayQueue | ||||
| import org.schabi.newpipe.util.NavigationHelper | ||||
| import java.util.function.Consumer | ||||
|  | ||||
| class PlayerHolder private constructor() { | ||||
| private val DEBUG = MainActivity.DEBUG | ||||
| private val TAG: String = PlayerHolder::class.java.getSimpleName() | ||||
|  | ||||
| /** | ||||
|  * Singleton that manages a `PlayerService` | ||||
|  * and can be used to control the player instance through the service. | ||||
|  */ | ||||
| object PlayerHolder { | ||||
|     private var listener: PlayerServiceExtendedEventListener? = null | ||||
|  | ||||
|     private val serviceConnection = PlayerServiceConnection() | ||||
|     var isBound: Boolean = false | ||||
|         private set | ||||
|  | ||||
|     private var playerService: PlayerService? = null | ||||
|  | ||||
|     private val player: Player? | ||||
| @@ -110,7 +117,7 @@ class PlayerHolder private constructor() { | ||||
|         val intent = Intent(context, PlayerService::class.java) | ||||
|         intent.putExtra(PlayerService.SHOULD_START_FOREGROUND_EXTRA, true) | ||||
|         ContextCompat.startForegroundService(context, intent) | ||||
|         serviceConnection.doPlayAfterConnect(playAfterConnect) | ||||
|         PlayerServiceConnection.doPlayAfterConnect(playAfterConnect) | ||||
|         bind(context) | ||||
|     } | ||||
|  | ||||
| @@ -126,7 +133,7 @@ class PlayerHolder private constructor() { | ||||
|         context.stopService(Intent(context, PlayerService::class.java)) | ||||
|     } | ||||
|  | ||||
|     internal inner class PlayerServiceConnection : ServiceConnection { | ||||
|     internal object PlayerServiceConnection : ServiceConnection { | ||||
|         internal var playAfterConnect = false | ||||
|  | ||||
|         /** | ||||
| @@ -185,7 +192,7 @@ class PlayerHolder private constructor() { | ||||
|         // BIND_AUTO_CREATE starts the service if it's not already running | ||||
|         this.isBound = bind(context, Context.BIND_AUTO_CREATE) | ||||
|         if (!this.isBound) { | ||||
|             context.unbindService(serviceConnection) | ||||
|             context.unbindService(PlayerServiceConnection) | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -201,7 +208,7 @@ class PlayerHolder private constructor() { | ||||
|     private fun bind(context: Context, flags: Int): Boolean { | ||||
|         val serviceIntent = Intent(context, PlayerService::class.java) | ||||
|         serviceIntent.setAction(PlayerService.BIND_PLAYER_HOLDER_ACTION) | ||||
|         return context.bindService(serviceIntent, serviceConnection, flags) | ||||
|         return context.bindService(serviceIntent, PlayerServiceConnection, flags) | ||||
|     } | ||||
|  | ||||
|     private fun unbind(context: Context) { | ||||
| @@ -210,7 +217,7 @@ class PlayerHolder private constructor() { | ||||
|         } | ||||
|  | ||||
|         if (this.isBound) { | ||||
|             context.unbindService(serviceConnection) | ||||
|             context.unbindService(PlayerServiceConnection) | ||||
|             this.isBound = false | ||||
|             stopPlayerListener() | ||||
|             playerService = null | ||||
| @@ -223,18 +230,18 @@ class PlayerHolder private constructor() { | ||||
|         // setting the player listener will take care of calling relevant callbacks if the | ||||
|         // player in the service is (not) already active, also see playerStateListener below | ||||
|         playerService?.setPlayerListener(playerStateListener) | ||||
|         this.player?.setFragmentListener(internalListener) | ||||
|         this.player?.setFragmentListener(HolderPlayerServiceEventListener) | ||||
|     } | ||||
|  | ||||
|     private fun stopPlayerListener() { | ||||
|         playerService?.setPlayerListener(null) | ||||
|         this.player?.removeFragmentListener(internalListener) | ||||
|         this.player?.removeFragmentListener(HolderPlayerServiceEventListener) | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This listener will be held by the players created by [PlayerService]. | ||||
|      */ | ||||
|     private val internalListener: PlayerServiceEventListener = object : PlayerServiceEventListener { | ||||
|     private object HolderPlayerServiceEventListener : PlayerServiceEventListener { | ||||
|         override fun onViewCreated() { | ||||
|             listener?.onViewCreated() | ||||
|         } | ||||
| @@ -307,26 +314,11 @@ class PlayerHolder private constructor() { | ||||
|                 // before setting its player to null | ||||
|                 l.onPlayerDisconnected() | ||||
|             } else { | ||||
|                 l.onPlayerConnected(player, serviceConnection.playAfterConnect) | ||||
|                 l.onPlayerConnected(player, PlayerServiceConnection.playAfterConnect) | ||||
|                 // reset the value of playAfterConnect: if it was true before, it is now "consumed" | ||||
|                 serviceConnection.playAfterConnect = false; | ||||
|                 player.setFragmentListener(internalListener) | ||||
|                 PlayerServiceConnection.playAfterConnect = false | ||||
|                 player.setFragmentListener(HolderPlayerServiceEventListener) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     companion object { | ||||
|         private var instance: PlayerHolder? = null | ||||
|  | ||||
|         @Synchronized | ||||
|         fun getInstance(): PlayerHolder { | ||||
|             if (instance == null) { | ||||
|                 instance = PlayerHolder() | ||||
|             } | ||||
|             return instance!! | ||||
|         } | ||||
|  | ||||
|         private val DEBUG = MainActivity.DEBUG | ||||
|         private val TAG: String = PlayerHolder::class.java.getSimpleName() | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -28,10 +28,9 @@ fun StreamMenu( | ||||
| ) { | ||||
|     val context = LocalContext.current | ||||
|     val streamViewModel = viewModel<StreamViewModel>() | ||||
|     val playerHolder = PlayerHolder.Companion.getInstance() | ||||
|  | ||||
|     DropdownMenu(expanded = expanded, onDismissRequest = onDismissRequest) { | ||||
|         if (playerHolder.isPlayQueueReady) { | ||||
|         if (PlayerHolder.isPlayQueueReady) { | ||||
|             DropdownMenuItem( | ||||
|                 text = { Text(text = stringResource(R.string.enqueue_stream)) }, | ||||
|                 onClick = { | ||||
| @@ -42,7 +41,7 @@ fun StreamMenu( | ||||
|                 } | ||||
|             ) | ||||
|  | ||||
|             if (playerHolder.queuePosition < playerHolder.queueSize - 1) { | ||||
|             if (PlayerHolder.queuePosition < PlayerHolder.queueSize - 1) { | ||||
|                 DropdownMenuItem( | ||||
|                     text = { Text(text = stringResource(R.string.enqueue_next_stream)) }, | ||||
|                     onClick = { | ||||
|   | ||||
| @@ -200,7 +200,7 @@ public final class NavigationHelper { | ||||
|     } | ||||
|  | ||||
|     public static void enqueueOnPlayer(final Context context, final PlayQueue queue) { | ||||
|         PlayerType playerType = PlayerHolder.Companion.getInstance().getType(); | ||||
|         PlayerType playerType = PlayerHolder.INSTANCE.getType(); | ||||
|         if (playerType == null) { | ||||
|             Log.e(TAG, "Enqueueing but no player is open; defaulting to background player"); | ||||
|             playerType = PlayerType.AUDIO; | ||||
| @@ -211,7 +211,7 @@ public final class NavigationHelper { | ||||
|  | ||||
|     /* ENQUEUE NEXT */ | ||||
|     public static void enqueueNextOnPlayer(final Context context, final PlayQueue queue) { | ||||
|         PlayerType playerType = PlayerHolder.Companion.getInstance().getType(); | ||||
|         PlayerType playerType = PlayerHolder.INSTANCE.getType(); | ||||
|         if (playerType == null) { | ||||
|             Log.e(TAG, "Enqueueing next but no player is open; defaulting to background player"); | ||||
|             playerType = PlayerType.AUDIO; | ||||
| @@ -421,13 +421,13 @@ public final class NavigationHelper { | ||||
|                                                final boolean switchingPlayers) { | ||||
|  | ||||
|         final boolean autoPlay; | ||||
|         @Nullable final PlayerType playerType = PlayerHolder.Companion.getInstance().getType(); | ||||
|         @Nullable final PlayerType playerType = PlayerHolder.INSTANCE.getType(); | ||||
|         if (playerType == null) { | ||||
|             // no player open | ||||
|             autoPlay = PlayerHelper.isAutoplayAllowedByUser(context); | ||||
|         } else if (switchingPlayers) { | ||||
|             // switching player to main player | ||||
|             autoPlay = PlayerHolder.Companion.getInstance().isPlaying(); // keep play/pause state | ||||
|             autoPlay = PlayerHolder.INSTANCE.isPlaying(); // keep play/pause state | ||||
|         } else if (playerType == PlayerType.MAIN) { | ||||
|             // opening new stream while already playing in main player | ||||
|             autoPlay = PlayerHelper.isAutoplayAllowedByUser(context); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Profpatsch
					Profpatsch