Merge pull request #5459 from Stypox/fullscreen-autoplay

Add option to directly open fullscreen when the main player starts
This commit is contained in:
Tobi 2021-09-01 23:01:09 +02:00 committed by GitHub
commit 81fa0c1558
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 130 additions and 49 deletions

View File

@ -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()

View File

@ -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

View File

@ -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) {

View File

@ -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);

View File

@ -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();
}
} }

View File

@ -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);
} }

View File

@ -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>

View File

@ -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>

View File

@ -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"