mirror of
https://github.com/MaintainTeam/LastPipeBender.git
synced 2025-03-01 05:48:22 +03:00
Merge pull request #5459 from Stypox/fullscreen-autoplay
Add option to directly open fullscreen when the main player starts
This commit is contained in:
commit
81fa0c1558
9 changed files with 130 additions and 49 deletions
|
@ -201,7 +201,7 @@ public final class VideoDetailFragment
|
||||||
@Nullable
|
@Nullable
|
||||||
private MainPlayer playerService;
|
private MainPlayer playerService;
|
||||||
private Player player;
|
private Player player;
|
||||||
private PlayerHolder playerHolder = PlayerHolder.getInstance();
|
private final PlayerHolder playerHolder = PlayerHolder.getInstance();
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Service management
|
// Service management
|
||||||
|
@ -220,7 +220,7 @@ public final class VideoDetailFragment
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLandscape()) {
|
if (DeviceUtils.isLandscape(requireContext())) {
|
||||||
// If the video is playing but orientation changed
|
// If the video is playing but orientation changed
|
||||||
// let's make the video in fullscreen again
|
// let's make the video in fullscreen again
|
||||||
checkLandscape();
|
checkLandscape();
|
||||||
|
@ -241,7 +241,7 @@ public final class VideoDetailFragment
|
||||||
&& isAutoplayEnabled()
|
&& isAutoplayEnabled()
|
||||||
&& player.getParentActivity() == null)) {
|
&& player.getParentActivity() == null)) {
|
||||||
autoPlayEnabled = true; // forcefully start playing
|
autoPlayEnabled = true; // forcefully start playing
|
||||||
openVideoPlayer();
|
openVideoPlayerAutoFullscreen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,7 +499,7 @@ public final class VideoDetailFragment
|
||||||
break;
|
break;
|
||||||
case R.id.detail_thumbnail_root_layout:
|
case R.id.detail_thumbnail_root_layout:
|
||||||
autoPlayEnabled = true; // forcefully start playing
|
autoPlayEnabled = true; // forcefully start playing
|
||||||
openVideoPlayer();
|
openVideoPlayerAutoFullscreen();
|
||||||
break;
|
break;
|
||||||
case R.id.detail_title_root_layout:
|
case R.id.detail_title_root_layout:
|
||||||
toggleTitleAndSecondaryControls();
|
toggleTitleAndSecondaryControls();
|
||||||
|
@ -516,7 +516,7 @@ public final class VideoDetailFragment
|
||||||
showSystemUi();
|
showSystemUi();
|
||||||
} else {
|
} else {
|
||||||
autoPlayEnabled = true; // forcefully start playing
|
autoPlayEnabled = true; // forcefully start playing
|
||||||
openVideoPlayer();
|
openVideoPlayer(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
setOverlayPlayPauseImage(isPlayerAvailable() && player.isPlaying());
|
setOverlayPlayPauseImage(isPlayerAvailable() && player.isPlaying());
|
||||||
|
@ -762,7 +762,7 @@ public final class VideoDetailFragment
|
||||||
|
|
||||||
private void setupFromHistoryItem(final StackItem item) {
|
private void setupFromHistoryItem(final StackItem item) {
|
||||||
setAutoPlay(false);
|
setAutoPlay(false);
|
||||||
hideMainPlayer();
|
hideMainPlayerOnLoadingNewStream();
|
||||||
|
|
||||||
setInitialData(item.getServiceId(), item.getUrl(),
|
setInitialData(item.getServiceId(), item.getUrl(),
|
||||||
item.getTitle() == null ? "" : item.getTitle(), item.getPlayQueue());
|
item.getTitle() == null ? "" : item.getTitle(), item.getPlayQueue());
|
||||||
|
@ -882,7 +882,7 @@ public final class VideoDetailFragment
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(result -> {
|
.subscribe(result -> {
|
||||||
isLoading.set(false);
|
isLoading.set(false);
|
||||||
hideMainPlayer();
|
hideMainPlayerOnLoadingNewStream();
|
||||||
if (result.getAgeLimit() != NO_AGE_LIMIT && !prefs.getBoolean(
|
if (result.getAgeLimit() != NO_AGE_LIMIT && !prefs.getBoolean(
|
||||||
getString(R.string.show_age_restricted_content), false)) {
|
getString(R.string.show_age_restricted_content), false)) {
|
||||||
hideAgeRestrictedContent();
|
hideAgeRestrictedContent();
|
||||||
|
@ -897,8 +897,9 @@ public final class VideoDetailFragment
|
||||||
stack.push(new StackItem(serviceId, url, title, playQueue));
|
stack.push(new StackItem(serviceId, url, title, playQueue));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAutoplayEnabled()) {
|
if (isAutoplayEnabled()) {
|
||||||
openVideoPlayer();
|
openVideoPlayerAutoFullscreen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, throwable -> showError(new ErrorInfo(throwable, UserAction.REQUESTED_STREAM,
|
}, throwable -> showError(new ErrorInfo(throwable, UserAction.REQUESTED_STREAM,
|
||||||
|
@ -1103,7 +1104,29 @@ public final class VideoDetailFragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void openVideoPlayer() {
|
/**
|
||||||
|
* Opens the video player, in fullscreen if needed. In order to open fullscreen, the activity
|
||||||
|
* is toggled to landscape orientation (which will then cause fullscreen mode).
|
||||||
|
*
|
||||||
|
* @param directlyFullscreenIfApplicable whether to open fullscreen if we are not already
|
||||||
|
* in landscape and screen orientation is locked
|
||||||
|
*/
|
||||||
|
public void openVideoPlayer(final boolean directlyFullscreenIfApplicable) {
|
||||||
|
if (directlyFullscreenIfApplicable
|
||||||
|
&& !DeviceUtils.isLandscape(requireContext())
|
||||||
|
&& PlayerHelper.globalScreenOrientationLocked(requireContext())) {
|
||||||
|
// Make sure the bottom sheet turns out expanded. When this code kicks in the bottom
|
||||||
|
// sheet could not have fully expanded yet, and thus be in the STATE_SETTLING state.
|
||||||
|
// When the activity is rotated, and its state is saved and then restored, the bottom
|
||||||
|
// sheet would forget what it was doing, since even if STATE_SETTLING is restored, it
|
||||||
|
// doesn't tell which state it was settling to, and thus the bottom sheet settles to
|
||||||
|
// STATE_COLLAPSED. This can be solved by manually setting the state that will be
|
||||||
|
// restored (i.e. bottomSheetState) to STATE_EXPANDED.
|
||||||
|
bottomSheetState = BottomSheetBehavior.STATE_EXPANDED;
|
||||||
|
// toggle landscape in order to open directly in fullscreen
|
||||||
|
onScreenRotationButtonClicked();
|
||||||
|
}
|
||||||
|
|
||||||
if (PreferenceManager.getDefaultSharedPreferences(activity)
|
if (PreferenceManager.getDefaultSharedPreferences(activity)
|
||||||
.getBoolean(this.getString(R.string.use_external_video_player_key), false)) {
|
.getBoolean(this.getString(R.string.use_external_video_player_key), false)) {
|
||||||
showExternalPlaybackDialog();
|
showExternalPlaybackDialog();
|
||||||
|
@ -1112,6 +1135,18 @@ public final class VideoDetailFragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the option to start directly fullscreen is enabled, calls
|
||||||
|
* {@link #openVideoPlayer(boolean)} with {@code directlyFullscreenIfApplicable = true}, so that
|
||||||
|
* if the user is not already in landscape and he has screen orientation locked the activity
|
||||||
|
* rotates and fullscreen starts. Otherwise, if the option to start directly fullscreen is
|
||||||
|
* disabled, calls {@link #openVideoPlayer(boolean)} with {@code directlyFullscreenIfApplicable
|
||||||
|
* = false}, hence preventing it from going directly fullscreen.
|
||||||
|
*/
|
||||||
|
public void openVideoPlayerAutoFullscreen() {
|
||||||
|
openVideoPlayer(PlayerHelper.isStartMainPlayerFullscreenEnabled(requireContext()));
|
||||||
|
}
|
||||||
|
|
||||||
private void openNormalBackgroundPlayer(final boolean append) {
|
private void openNormalBackgroundPlayer(final boolean append) {
|
||||||
// See UI changes while remote playQueue changes
|
// See UI changes while remote playQueue changes
|
||||||
if (!isPlayerAvailable()) {
|
if (!isPlayerAvailable()) {
|
||||||
|
@ -1145,12 +1180,19 @@ public final class VideoDetailFragment
|
||||||
}
|
}
|
||||||
addVideoPlayerView();
|
addVideoPlayerView();
|
||||||
|
|
||||||
final Intent playerIntent = NavigationHelper
|
final Intent playerIntent = NavigationHelper.getPlayerIntent(requireContext(),
|
||||||
.getPlayerIntent(requireContext(), MainPlayer.class, queue, true, autoPlayEnabled);
|
MainPlayer.class, queue, true, autoPlayEnabled);
|
||||||
ContextCompat.startForegroundService(activity, playerIntent);
|
ContextCompat.startForegroundService(activity, playerIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void hideMainPlayer() {
|
/**
|
||||||
|
* When the video detail fragment is already showing details for a video and the user opens a
|
||||||
|
* new one, the video detail fragment changes all of its old data to the new stream, so if there
|
||||||
|
* is a video player currently open it should be hidden. This method does exactly that. If
|
||||||
|
* autoplay is enabled, the underlying player is not stopped completely, since it is going to
|
||||||
|
* be reused in a few milliseconds and the flickering would be annoying.
|
||||||
|
*/
|
||||||
|
private void hideMainPlayerOnLoadingNewStream() {
|
||||||
if (!isPlayerServiceAvailable()
|
if (!isPlayerServiceAvailable()
|
||||||
|| playerService.getView() == null
|
|| playerService.getView() == null
|
||||||
|| !player.videoPlayerSelected()) {
|
|| !player.videoPlayerSelected()) {
|
||||||
|
@ -1158,8 +1200,12 @@ public final class VideoDetailFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
removeVideoPlayerView();
|
removeVideoPlayerView();
|
||||||
playerService.stop(isAutoplayEnabled());
|
if (isAutoplayEnabled()) {
|
||||||
playerService.getView().setVisibility(View.GONE);
|
playerService.stopForImmediateReusing();
|
||||||
|
playerService.getView().setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
playerHolder.stopService();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlayQueue setupPlayQueueForIntent(final boolean append) {
|
private PlayQueue setupPlayQueueForIntent(final boolean append) {
|
||||||
|
@ -1252,7 +1298,7 @@ public final class VideoDetailFragment
|
||||||
final DisplayMetrics metrics = getResources().getDisplayMetrics();
|
final DisplayMetrics metrics = getResources().getDisplayMetrics();
|
||||||
|
|
||||||
if (getView() != null) {
|
if (getView() != null) {
|
||||||
final int height = (isInMultiWindow()
|
final int height = (DeviceUtils.isInMultiWindow(activity)
|
||||||
? requireView()
|
? requireView()
|
||||||
: activity.getWindow().getDecorView()).getHeight();
|
: activity.getWindow().getDecorView()).getHeight();
|
||||||
setHeightThumbnail(height, metrics);
|
setHeightThumbnail(height, metrics);
|
||||||
|
@ -1275,7 +1321,7 @@ public final class VideoDetailFragment
|
||||||
requireView().getViewTreeObserver().removeOnPreDrawListener(preDrawListener);
|
requireView().getViewTreeObserver().removeOnPreDrawListener(preDrawListener);
|
||||||
|
|
||||||
if (isPlayerAvailable() && player.isFullscreen()) {
|
if (isPlayerAvailable() && player.isFullscreen()) {
|
||||||
final int height = (isInMultiWindow()
|
final int height = (DeviceUtils.isInMultiWindow(activity)
|
||||||
? requireView()
|
? requireView()
|
||||||
: activity.getWindow().getDecorView()).getHeight();
|
: activity.getWindow().getDecorView()).getHeight();
|
||||||
// Height is zero when the view is not yet displayed like after orientation change
|
// Height is zero when the view is not yet displayed like after orientation change
|
||||||
|
@ -1808,7 +1854,7 @@ public final class VideoDetailFragment
|
||||||
|| error.type == ExoPlaybackException.TYPE_UNEXPECTED) {
|
|| error.type == ExoPlaybackException.TYPE_UNEXPECTED) {
|
||||||
// Properly exit from fullscreen
|
// Properly exit from fullscreen
|
||||||
toggleFullscreenIfInFullscreenMode();
|
toggleFullscreenIfInFullscreenMode();
|
||||||
hideMainPlayer();
|
hideMainPlayerOnLoadingNewStream();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1864,13 +1910,14 @@ public final class VideoDetailFragment
|
||||||
// from landscape to portrait every time.
|
// from landscape to portrait every time.
|
||||||
// Just turn on fullscreen mode in landscape orientation
|
// Just turn on fullscreen mode in landscape orientation
|
||||||
// or portrait & unlocked global orientation
|
// or portrait & unlocked global orientation
|
||||||
|
final boolean isLandscape = DeviceUtils.isLandscape(requireContext());
|
||||||
if (DeviceUtils.isTablet(activity)
|
if (DeviceUtils.isTablet(activity)
|
||||||
&& (!globalScreenOrientationLocked(activity) || isLandscape())) {
|
&& (!globalScreenOrientationLocked(activity) || isLandscape)) {
|
||||||
player.toggleFullscreen();
|
player.toggleFullscreen();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int newOrientation = isLandscape()
|
final int newOrientation = isLandscape
|
||||||
? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||||
: ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
|
: ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
|
||||||
|
|
||||||
|
@ -1942,15 +1989,17 @@ public final class VideoDetailFragment
|
||||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||||
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||||
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
|
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
|
||||||
|
|
||||||
// In multiWindow mode status bar is not transparent for devices with cutout
|
// In multiWindow mode status bar is not transparent for devices with cutout
|
||||||
// if I include this flag. So without it is better in this case
|
// if I include this flag. So without it is better in this case
|
||||||
if (!isInMultiWindow()) {
|
final boolean isInMultiWindow = DeviceUtils.isInMultiWindow(activity);
|
||||||
|
if (!isInMultiWindow) {
|
||||||
visibility |= View.SYSTEM_UI_FLAG_FULLSCREEN;
|
visibility |= View.SYSTEM_UI_FLAG_FULLSCREEN;
|
||||||
}
|
}
|
||||||
activity.getWindow().getDecorView().setSystemUiVisibility(visibility);
|
activity.getWindow().getDecorView().setSystemUiVisibility(visibility);
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
|
||||||
&& (isInMultiWindow() || (isPlayerAvailable() && player.isFullscreen()))) {
|
&& (isInMultiWindow || (isPlayerAvailable() && player.isFullscreen()))) {
|
||||||
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
|
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
|
||||||
activity.getWindow().setNavigationBarColor(Color.TRANSPARENT);
|
activity.getWindow().setNavigationBarColor(Color.TRANSPARENT);
|
||||||
}
|
}
|
||||||
|
@ -2022,15 +2071,6 @@ public final class VideoDetailFragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLandscape() {
|
|
||||||
return getResources().getDisplayMetrics().heightPixels < getResources()
|
|
||||||
.getDisplayMetrics().widthPixels;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isInMultiWindow() {
|
|
||||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && activity.isInMultiWindowMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Means that the player fragment was swiped away via BottomSheetLayout
|
* Means that the player fragment was swiped away via BottomSheetLayout
|
||||||
* and is empty but ready for any new actions. See cleanUp()
|
* and is empty but ready for any new actions. See cleanUp()
|
||||||
|
@ -2213,7 +2253,7 @@ public final class VideoDetailFragment
|
||||||
setOverlayElementsClickable(false);
|
setOverlayElementsClickable(false);
|
||||||
hideSystemUiIfNeeded();
|
hideSystemUiIfNeeded();
|
||||||
// Conditions when the player should be expanded to fullscreen
|
// Conditions when the player should be expanded to fullscreen
|
||||||
if (isLandscape()
|
if (DeviceUtils.isLandscape(requireContext())
|
||||||
&& isPlayerAvailable()
|
&& isPlayerAvailable()
|
||||||
&& player.isPlaying()
|
&& player.isPlaying()
|
||||||
&& !player.isFullscreen()
|
&& !player.isFullscreen()
|
||||||
|
|
|
@ -24,7 +24,6 @@ import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.util.DisplayMetrics;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
@ -36,6 +35,7 @@ import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
import org.schabi.newpipe.App;
|
import org.schabi.newpipe.App;
|
||||||
import org.schabi.newpipe.databinding.PlayerBinding;
|
import org.schabi.newpipe.databinding.PlayerBinding;
|
||||||
|
import org.schabi.newpipe.util.DeviceUtils;
|
||||||
import org.schabi.newpipe.util.ThemeHelper;
|
import org.schabi.newpipe.util.ThemeHelper;
|
||||||
|
|
||||||
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
||||||
|
@ -133,32 +133,29 @@ public final class MainPlayer extends Service {
|
||||||
return START_NOT_STICKY;
|
return START_NOT_STICKY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop(final boolean autoplayEnabled) {
|
public void stopForImmediateReusing() {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "stop() called");
|
Log.d(TAG, "stopForImmediateReusing() called");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!player.exoPlayerIsNull()) {
|
if (!player.exoPlayerIsNull()) {
|
||||||
player.saveWasPlaying();
|
player.saveWasPlaying();
|
||||||
|
|
||||||
// Releases wifi & cpu, disables keepScreenOn, etc.
|
// Releases wifi & cpu, disables keepScreenOn, etc.
|
||||||
if (!autoplayEnabled) {
|
|
||||||
player.pause();
|
|
||||||
}
|
|
||||||
// We can't just pause the player here because it will make transition
|
// We can't just pause the player here because it will make transition
|
||||||
// from one stream to a new stream not smooth
|
// from one stream to a new stream not smooth
|
||||||
player.smoothStopPlayer();
|
player.smoothStopPlayer();
|
||||||
player.setRecovery();
|
player.setRecovery();
|
||||||
|
|
||||||
// Android TV will handle back button in case controls will be visible
|
// Android TV will handle back button in case controls will be visible
|
||||||
// (one more additional unneeded click while the player is hidden)
|
// (one more additional unneeded click while the player is hidden)
|
||||||
player.hideControls(0, 0);
|
player.hideControls(0, 0);
|
||||||
player.closeItemsList();
|
player.closeItemsList();
|
||||||
|
|
||||||
// Notification shows information about old stream but if a user selects
|
// Notification shows information about old stream but if a user selects
|
||||||
// a stream from backStack it's not actual anymore
|
// a stream from backStack it's not actual anymore
|
||||||
// So we should hide the notification at all.
|
// So we should hide the notification at all.
|
||||||
// When autoplay enabled such notification flashing is annoying so skip this case
|
// When autoplay enabled such notification flashing is annoying so skip this case
|
||||||
if (!autoplayEnabled) {
|
|
||||||
NotificationUtil.getInstance().cancelNotificationAndStopForeground(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,11 +219,8 @@ public final class MainPlayer extends Service {
|
||||||
boolean isLandscape() {
|
boolean isLandscape() {
|
||||||
// DisplayMetrics from activity context knows about MultiWindow feature
|
// DisplayMetrics from activity context knows about MultiWindow feature
|
||||||
// while DisplayMetrics from app context doesn't
|
// while DisplayMetrics from app context doesn't
|
||||||
final DisplayMetrics metrics = (player != null
|
return DeviceUtils.isLandscape(player != null && player.getParentActivity() != null
|
||||||
&& player.getParentActivity() != null
|
? player.getParentActivity() : this);
|
||||||
? player.getParentActivity().getResources()
|
|
||||||
: getResources()).getDisplayMetrics();
|
|
||||||
return metrics.heightPixels < metrics.widthPixels;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|
|
@ -621,6 +621,9 @@ public final class Player implements
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// needed for tablets, check the function for a better explanation
|
||||||
|
directlyOpenFullscreenIfNeeded();
|
||||||
|
|
||||||
final PlaybackParameters savedParameters = retrievePlaybackParametersFromPrefs(this);
|
final PlaybackParameters savedParameters = retrievePlaybackParametersFromPrefs(this);
|
||||||
final float playbackSpeed = savedParameters.speed;
|
final float playbackSpeed = savedParameters.speed;
|
||||||
final float playbackPitch = savedParameters.pitch;
|
final float playbackPitch = savedParameters.pitch;
|
||||||
|
@ -672,6 +675,7 @@ public final class Player implements
|
||||||
&& isPlaybackResumeEnabled(this)
|
&& isPlaybackResumeEnabled(this)
|
||||||
&& !samePlayQueue
|
&& !samePlayQueue
|
||||||
&& !newQueue.isEmpty()
|
&& !newQueue.isEmpty()
|
||||||
|
&& newQueue.getItem() != null
|
||||||
&& newQueue.getItem().getRecoveryPosition() == PlayQueueItem.RECOVERY_UNSET) {
|
&& newQueue.getItem().getRecoveryPosition() == PlayQueueItem.RECOVERY_UNSET) {
|
||||||
databaseUpdateDisposable.add(recordManager.loadStreamState(newQueue.getItem())
|
databaseUpdateDisposable.add(recordManager.loadStreamState(newQueue.getItem())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
@ -743,6 +747,22 @@ public final class Player implements
|
||||||
NavigationHelper.sendPlayerStartedEvent(context);
|
NavigationHelper.sendPlayerStartedEvent(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open fullscreen on tablets where the option to have the main player start automatically in
|
||||||
|
* fullscreen mode is on. Rotating the device to landscape is already done in {@link
|
||||||
|
* VideoDetailFragment#openVideoPlayer(boolean)} when the thumbnail is clicked, and that's
|
||||||
|
* enough for phones, but not for tablets since the mini player can be also shown in landscape.
|
||||||
|
*/
|
||||||
|
private void directlyOpenFullscreenIfNeeded() {
|
||||||
|
if (fragmentListener != null
|
||||||
|
&& PlayerHelper.isStartMainPlayerFullscreenEnabled(service)
|
||||||
|
&& DeviceUtils.isTablet(service)
|
||||||
|
&& videoPlayerSelected()
|
||||||
|
&& PlayerHelper.globalScreenOrientationLocked(service)) {
|
||||||
|
fragmentListener.onScreenRotationButtonClicked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void initPlayback(@NonNull final PlayQueue queue,
|
private void initPlayback(@NonNull final PlayQueue queue,
|
||||||
@RepeatMode final int repeatMode,
|
@RepeatMode final int repeatMode,
|
||||||
final float playbackSpeed,
|
final float playbackSpeed,
|
||||||
|
@ -3855,11 +3875,9 @@ public final class Player implements
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "toggleFullscreen() called");
|
Log.d(TAG, "toggleFullscreen() called");
|
||||||
}
|
}
|
||||||
if (popupPlayerSelected() || exoPlayerIsNull() || currentMetadata == null
|
if (popupPlayerSelected() || exoPlayerIsNull() || fragmentListener == null) {
|
||||||
|| fragmentListener == null) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//changeState(STATE_BLOCKED); TODO check what this does
|
|
||||||
|
|
||||||
isFullscreen = !isFullscreen;
|
isFullscreen = !isFullscreen;
|
||||||
if (!isFullscreen) {
|
if (!isFullscreen) {
|
||||||
|
|
|
@ -239,6 +239,11 @@ public final class PlayerHelper {
|
||||||
.getBoolean(context.getString(R.string.brightness_gesture_control_key), true);
|
.getBoolean(context.getString(R.string.brightness_gesture_control_key), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isStartMainPlayerFullscreenEnabled(@NonNull final Context context) {
|
||||||
|
return getPreferences(context)
|
||||||
|
.getBoolean(context.getString(R.string.start_main_player_fullscreen_key), false);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isAutoQueueEnabled(@NonNull final Context context) {
|
public static boolean isAutoQueueEnabled(@NonNull final Context context) {
|
||||||
return getPreferences(context)
|
return getPreferences(context)
|
||||||
.getBoolean(context.getString(R.string.auto_queue_key), false);
|
.getBoolean(context.getString(R.string.auto_queue_key), false);
|
||||||
|
|
|
@ -11,6 +11,7 @@ import android.view.KeyEvent;
|
||||||
|
|
||||||
import androidx.annotation.Dimension;
|
import androidx.annotation.Dimension;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
|
@ -130,4 +131,13 @@ public final class DeviceUtils {
|
||||||
&& !HI3798MV200
|
&& !HI3798MV200
|
||||||
&& !CVT_MT5886_EU_1G;
|
&& !CVT_MT5886_EU_1G;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isLandscape(final Context context) {
|
||||||
|
return context.getResources().getDisplayMetrics().heightPixels < context.getResources()
|
||||||
|
.getDisplayMetrics().widthPixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isInMultiWindow(final AppCompatActivity activity) {
|
||||||
|
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && activity.isInMultiWindowMode();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -366,7 +366,9 @@ public final class NavigationHelper {
|
||||||
if (switchingPlayers) {
|
if (switchingPlayers) {
|
||||||
// Situation when user switches from players to main player. All needed data is
|
// Situation when user switches from players to main player. All needed data is
|
||||||
// here, we can start watching (assuming newQueue equals playQueue).
|
// here, we can start watching (assuming newQueue equals playQueue).
|
||||||
detailFragment.openVideoPlayer();
|
// Starting directly in fullscreen if the previous player type was popup.
|
||||||
|
detailFragment.openVideoPlayer(playerType == MainPlayer.PlayerType.POPUP
|
||||||
|
|| PlayerHelper.isStartMainPlayerFullscreenEnabled(context));
|
||||||
} else {
|
} else {
|
||||||
detailFragment.selectAndLoadVideo(serviceId, url, title, playQueue);
|
detailFragment.selectAndLoadVideo(serviceId, url, title, playQueue);
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,8 @@
|
||||||
<item>@string/minimize_on_exit_popup_description</item>
|
<item>@string/minimize_on_exit_popup_description</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<string name="start_main_player_fullscreen_key" translatable="false">start_main_player_fullscreen_key</string>
|
||||||
|
|
||||||
<string name="autoplay_key" translatable="false">autoplay_key</string>
|
<string name="autoplay_key" translatable="false">autoplay_key</string>
|
||||||
<string name="autoplay_value" translatable="false">@string/autoplay_wifi_key</string>
|
<string name="autoplay_value" translatable="false">@string/autoplay_wifi_key</string>
|
||||||
<string name="autoplay_always_key" translatable="false">autoplay_always_key</string>
|
<string name="autoplay_always_key" translatable="false">autoplay_always_key</string>
|
||||||
|
|
|
@ -132,6 +132,8 @@
|
||||||
<string name="resume_on_audio_focus_gain_title">Resume playing</string>
|
<string name="resume_on_audio_focus_gain_title">Resume playing</string>
|
||||||
<string name="resume_on_audio_focus_gain_summary">Continue playing after interruptions (e.g. phonecalls)</string>
|
<string name="resume_on_audio_focus_gain_summary">Continue playing after interruptions (e.g. phonecalls)</string>
|
||||||
<string name="download_dialog_title">Download</string>
|
<string name="download_dialog_title">Download</string>
|
||||||
|
<string name="start_main_player_fullscreen_title">Start main player in fullscreen</string>
|
||||||
|
<string name="start_main_player_fullscreen_summary">Do not start videos in the mini player, but turn to fullscreen mode directly, if auto rotation is locked. You can still access the mini player by exiting fullscreen.</string>
|
||||||
<string name="autoplay_title">Autoplay</string>
|
<string name="autoplay_title">Autoplay</string>
|
||||||
<string name="show_hold_to_append_title">Show \"Hold to append\" tip</string>
|
<string name="show_hold_to_append_title">Show \"Hold to append\" tip</string>
|
||||||
<string name="show_hold_to_append_summary">Show tip when pressing the background or the popup button in video \"Details:\"</string>
|
<string name="show_hold_to_append_summary">Show tip when pressing the background or the popup button in video \"Details:\"</string>
|
||||||
|
|
|
@ -129,6 +129,14 @@
|
||||||
app:singleLineTitle="false"
|
app:singleLineTitle="false"
|
||||||
app:iconSpaceReserved="false" />
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="@string/start_main_player_fullscreen_key"
|
||||||
|
android:summary="@string/start_main_player_fullscreen_summary"
|
||||||
|
android:title="@string/start_main_player_fullscreen_title"
|
||||||
|
app:singleLineTitle="false"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="@string/autoplay_value"
|
android:defaultValue="@string/autoplay_value"
|
||||||
android:entries="@array/autoplay_type_description"
|
android:entries="@array/autoplay_type_description"
|
||||||
|
|
Loading…
Add table
Reference in a new issue