diff --git a/app/build.gradle b/app/build.gradle
index e20535ee4..47a424250 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -8,8 +8,8 @@ android {
applicationId "org.schabi.newpipe"
minSdkVersion 15
targetSdkVersion 27
- versionCode 60
- versionName "0.13.1"
+ versionCode 61
+ versionName "0.13.2"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
@@ -42,7 +42,7 @@ android {
ext {
supportLibVersion = '27.1.0'
- exoPlayerLibVersion = '2.7.1'
+ exoPlayerLibVersion = '2.7.3'
roomDbLibVersion = '1.0.0'
leakCanaryLibVersion = '1.5.4'
okHttpLibVersion = '1.5.0'
@@ -73,6 +73,7 @@ dependencies {
implementation 'de.hdodenhof:circleimageview:2.2.0'
implementation 'com.github.nirhart:ParallaxScroll:dd53d1f9d1'
implementation 'com.nononsenseapps:filepicker:4.2.1'
+
implementation "com.google.android.exoplayer:exoplayer:$exoPlayerLibVersion"
implementation "com.google.android.exoplayer:extension-mediasession:$exoPlayerLibVersion"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7447c81ed..1e55270be 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -42,7 +42,11 @@
+ android:exported="false">
+
+
+
+
{
@@ -549,6 +551,12 @@ public class VideoDetailFragment
case 1:
NavigationHelper.enqueueOnPopupPlayer(getActivity(), new SinglePlayQueue(item));
break;
+ case 2:
+ if (getFragmentManager() != null) {
+ PlaylistAppendDialog.fromStreamInfoItems(Collections.singletonList(item))
+ .show(getFragmentManager(), TAG);
+ }
+ break;
default:
break;
}
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java
index dbc61961e..683286764 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java
@@ -36,6 +36,7 @@ import org.schabi.newpipe.extractor.stream.Stream;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
+import org.schabi.newpipe.fragments.local.dialog.PlaylistAppendDialog;
import org.schabi.newpipe.info_list.InfoItemDialog;
import org.schabi.newpipe.playlist.ChannelPlayQueue;
import org.schabi.newpipe.playlist.PlayQueue;
@@ -49,6 +50,7 @@ import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -161,6 +163,7 @@ public class ChannelFragment extends BaseListInfoFragment {
context.getResources().getString(R.string.start_here_on_main),
context.getResources().getString(R.string.start_here_on_background),
context.getResources().getString(R.string.start_here_on_popup),
+ context.getResources().getString(R.string.append_playlist)
};
final DialogInterface.OnClickListener actions = new DialogInterface.OnClickListener() {
@@ -183,6 +186,12 @@ public class ChannelFragment extends BaseListInfoFragment {
case 4:
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(index));
break;
+ case 5:
+ if (getFragmentManager() != null) {
+ PlaylistAppendDialog.fromStreamInfoItems(Collections.singletonList(item))
+ .show(getFragmentManager(), TAG);
+ }
+ break;
default:
break;
}
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/local/bookmark/BookmarkFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/local/bookmark/BookmarkFragment.java
index b740cb15e..e1f724b6e 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/local/bookmark/BookmarkFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/local/bookmark/BookmarkFragment.java
@@ -56,7 +56,8 @@ public final class BookmarkFragment
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- final AppDatabase database = NewPipeDatabase.getInstance(getContext());
+ if (activity == null) return;
+ final AppDatabase database = NewPipeDatabase.getInstance(activity);
localPlaylistManager = new LocalPlaylistManager(database);
remotePlaylistManager = new RemotePlaylistManager(database);
disposables = new CompositeDisposable();
diff --git a/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java b/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java
index ac070fb44..2d990e43e 100644
--- a/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java
+++ b/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java
@@ -118,8 +118,12 @@ public final class BackgroundPlayer extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
- if (DEBUG) Log.d(TAG, "onStartCommand() called with: intent = [" + intent + "], flags = [" + flags + "], startId = [" + startId + "]");
+ if (DEBUG) Log.d(TAG, "onStartCommand() called with: intent = [" + intent +
+ "], flags = [" + flags + "], startId = [" + startId + "]");
basePlayerImpl.handleIntent(intent);
+ if (basePlayerImpl.mediaSessionManager != null) {
+ basePlayerImpl.mediaSessionManager.handleMediaButtonIntent(intent);
+ }
return START_NOT_STICKY;
}
@@ -160,6 +164,11 @@ public final class BackgroundPlayer extends Service {
if (DEBUG) Log.d(TAG, "onScreenOnOff() called with: on = [" + on + "]");
shouldUpdateOnProgress = on;
basePlayerImpl.triggerProgressUpdate();
+ if (on) {
+ basePlayerImpl.startProgressLoop();
+ } else {
+ basePlayerImpl.stopProgressLoop();
+ }
}
/*//////////////////////////////////////////////////////////////////////////
@@ -545,7 +554,6 @@ public final class BackgroundPlayer extends Service {
super.onPaused();
updateNotification(R.drawable.ic_play_arrow_white);
- if (isProgressLoopRunning()) stopProgressLoop();
lockManager.releaseWifiAndCpu();
}
diff --git a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java
index cd1451d37..5e5518ee9 100644
--- a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java
+++ b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java
@@ -46,7 +46,7 @@ import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.BehindLiveWindowException;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.TrackGroupArray;
-import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
+import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.util.Util;
@@ -64,6 +64,7 @@ import org.schabi.newpipe.player.helper.LoadController;
import org.schabi.newpipe.player.helper.MediaSessionManager;
import org.schabi.newpipe.player.helper.PlayerDataSource;
import org.schabi.newpipe.player.helper.PlayerHelper;
+import org.schabi.newpipe.player.mediasource.FailedMediaSource;
import org.schabi.newpipe.player.playback.BasePlayerMediaSession;
import org.schabi.newpipe.player.playback.CustomTrackSelector;
import org.schabi.newpipe.player.playback.MediaSourceManager;
@@ -124,7 +125,6 @@ public abstract class BasePlayer implements
//////////////////////////////////////////////////////////////////////////*/
protected static final float[] PLAYBACK_SPEEDS = {0.5f, 0.75f, 1f, 1.25f, 1.5f, 1.75f, 2f};
- protected static final float[] PLAYBACK_PITCHES = {0.8f, 0.9f, 0.95f, 1f, 1.05f, 1.1f, 1.2f};
protected PlayQueue playQueue;
protected PlayQueueAdapter playQueueAdapter;
@@ -140,10 +140,10 @@ public abstract class BasePlayer implements
// Player
//////////////////////////////////////////////////////////////////////////*/
- protected final static int FAST_FORWARD_REWIND_AMOUNT = 10000; // 10 Seconds
- protected final static int PLAY_PREV_ACTIVATION_LIMIT = 5000; // 5 seconds
- protected final static int PROGRESS_LOOP_INTERVAL = 500;
- protected final static int RECOVERY_SKIP_THRESHOLD = 3000; // 3 seconds
+ protected final static int FAST_FORWARD_REWIND_AMOUNT_MILLIS = 10000; // 10 Seconds
+ protected final static int PLAY_PREV_ACTIVATION_LIMIT_MILLIS = 5000; // 5 seconds
+ protected final static int PROGRESS_LOOP_INTERVAL_MILLIS = 500;
+ protected final static int RECOVERY_SKIP_THRESHOLD_MILLIS = 3000; // 3 seconds
protected CustomTrackSelector trackSelector;
protected PlayerDataSource dataSource;
@@ -177,11 +177,11 @@ public abstract class BasePlayer implements
}
public void setup() {
- if (simpleExoPlayer == null) initPlayer();
+ if (simpleExoPlayer == null) initPlayer(/*playOnInit=*/true);
initListeners();
}
- public void initPlayer() {
+ public void initPlayer(final boolean playOnReady) {
if (DEBUG) Log.d(TAG, "initPlayer() called with: context = [" + context + "]");
if (databaseUpdateReactor != null) databaseUpdateReactor.dispose();
@@ -191,15 +191,15 @@ public abstract class BasePlayer implements
final DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
dataSource = new PlayerDataSource(context, userAgent, bandwidthMeter);
- final AdaptiveTrackSelection.Factory trackSelectionFactory =
- new AdaptiveTrackSelection.Factory(bandwidthMeter);
+ final TrackSelection.Factory trackSelectionFactory =
+ PlayerHelper.getQualitySelector(context, bandwidthMeter);
trackSelector = new CustomTrackSelector(trackSelectionFactory);
final LoadControl loadControl = new LoadController(context);
final RenderersFactory renderFactory = new DefaultRenderersFactory(context);
simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(renderFactory, trackSelector, loadControl);
simpleExoPlayer.addListener(this);
- simpleExoPlayer.setPlayWhenReady(true);
+ simpleExoPlayer.setPlayWhenReady(playOnReady);
simpleExoPlayer.setSeekParameters(PlayerHelper.getSeekParameters(context));
audioReactor = new AudioReactor(context, simpleExoPlayer);
@@ -237,15 +237,16 @@ public abstract class BasePlayer implements
final float playbackPitch = intent.getFloatExtra(PLAYBACK_PITCH, getPlaybackPitch());
// Good to go...
- initPlayback(queue, repeatMode, playbackSpeed, playbackPitch);
+ initPlayback(queue, repeatMode, playbackSpeed, playbackPitch, /*playOnInit=*/true);
}
protected void initPlayback(@NonNull final PlayQueue queue,
@Player.RepeatMode final int repeatMode,
final float playbackSpeed,
- final float playbackPitch) {
+ final float playbackPitch,
+ final boolean playOnReady) {
destroyPlayer();
- initPlayer();
+ initPlayer(playOnReady);
setRepeatMode(repeatMode);
setPlaybackParameters(playbackSpeed, playbackPitch);
@@ -518,15 +519,16 @@ public abstract class BasePlayer implements
}
public void triggerProgressUpdate() {
+ if (simpleExoPlayer == null) return;
onUpdateProgress(
- (int) simpleExoPlayer.getCurrentPosition(),
+ Math.max((int) simpleExoPlayer.getCurrentPosition(), 0),
(int) simpleExoPlayer.getDuration(),
simpleExoPlayer.getBufferedPercentage()
);
}
private Disposable getProgressReactor() {
- return Observable.interval(PROGRESS_LOOP_INTERVAL, TimeUnit.MILLISECONDS)
+ return Observable.interval(PROGRESS_LOOP_INTERVAL_MILLIS, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(ignored -> triggerProgressUpdate());
}
@@ -553,8 +555,8 @@ public abstract class BasePlayer implements
// Ensure dynamic/livestream timeline changes does not cause negative position
if (isPlaylistStable && !isCurrentWindowValid() && !isSynchronizing) {
if (DEBUG) Log.d(TAG, "Playback - negative time position reached, " +
- "clamping position to 0ms.");
- seekTo(/*clampToTime=*/0);
+ "clamping to default position.");
+ seekToDefault();
}
break;
}
@@ -640,12 +642,12 @@ public abstract class BasePlayer implements
seekTo(recoveryPositionMillis);
playQueue.unsetRecovery(currentSourceIndex);
- } else if (isSynchronizing && simpleExoPlayer.isCurrentWindowDynamic()) {
+ } else if (isSynchronizing && isLive()) {
if (DEBUG) Log.d(TAG, "Playback - Synchronizing livestream to default time");
// Is still synchronizing?
seekToDefault();
- } else if (isSynchronizing && presetStartPositionMillis != 0L) {
+ } else if (isSynchronizing && presetStartPositionMillis > 0L) {
if (DEBUG) Log.d(TAG, "Playback - Seeking to preset start " +
"position=[" + presetStartPositionMillis + "]");
// Has another start position?
@@ -700,41 +702,23 @@ public abstract class BasePlayer implements
}
}
- /**
- * Processes {@link ExoPlaybackException} tagged with {@link ExoPlaybackException#TYPE_SOURCE}.
- *
- * If the current {@link com.google.android.exoplayer2.Timeline.Window window} is valid,
- * then we know the error is produced by transitioning into a bad window, therefore we report
- * an error to the play queue based on if the current error can be skipped.
- *
- * This is done because ExoPlayer reports the source exceptions before window is
- * transitioned on seamless playback. Because player error causes ExoPlayer to go
- * back to {@link Player#STATE_IDLE STATE_IDLE}, we reset and prepare the media source
- * again to resume playback.
- *
- * In the event that this error is produced during a valid stream playback, we save the
- * current position so the playback may be recovered and resumed manually by the user. This
- * happens only if the playback is {@link #RECOVERY_SKIP_THRESHOLD} milliseconds until complete.
- *
- * In the event of livestreaming being lagged behind for any reason, most notably pausing for
- * too long, a {@link BehindLiveWindowException} will be produced. This will trigger a reload
- * instead of skipping or removal.
- * */
private void processSourceError(final IOException error) {
if (simpleExoPlayer == null || playQueue == null) return;
-
- if (simpleExoPlayer.getCurrentPosition() <
- simpleExoPlayer.getDuration() - RECOVERY_SKIP_THRESHOLD) {
- setRecovery();
- }
+ setRecovery();
final Throwable cause = error.getCause();
if (cause instanceof BehindLiveWindowException) {
reload();
} else if (cause instanceof UnknownHostException) {
playQueue.error(/*isNetworkProblem=*/true);
+ } else if (isCurrentWindowValid()) {
+ playQueue.error(/*isTransitioningToBadStream=*/true);
+ } else if (cause instanceof FailedMediaSource.MediaSourceResolutionException) {
+ playQueue.error(/*recoverableWithNoAvailableStream=*/false);
+ } else if (cause instanceof FailedMediaSource.StreamInfoLoadException) {
+ playQueue.error(/*recoverableIfLoadFailsWhenNetworkIsFine=*/false);
} else {
- playQueue.error(isCurrentWindowValid());
+ playQueue.error(/*noIdeaWhatHappenedAndLetUserChooseWhatToDo=*/true);
}
}
@@ -787,9 +771,10 @@ public abstract class BasePlayer implements
//////////////////////////////////////////////////////////////////////////*/
@Override
- public boolean isNearPlaybackEdge(final long timeToEndMillis) {
+ public boolean isApproachingPlaybackEdge(final long timeToEndMillis) {
// If live, then not near playback edge
- if (simpleExoPlayer == null || simpleExoPlayer.isCurrentWindowDynamic()) return false;
+ // If not playing, then not approaching playback edge
+ if (simpleExoPlayer == null || isLive() || !isPlaying()) return false;
final long currentPositionMillis = simpleExoPlayer.getCurrentPosition();
final long currentDurationMillis = simpleExoPlayer.getDuration();
@@ -985,22 +970,22 @@ public abstract class BasePlayer implements
public void onFastRewind() {
if (DEBUG) Log.d(TAG, "onFastRewind() called");
- seekBy(-FAST_FORWARD_REWIND_AMOUNT);
+ seekBy(-FAST_FORWARD_REWIND_AMOUNT_MILLIS);
}
public void onFastForward() {
if (DEBUG) Log.d(TAG, "onFastForward() called");
- seekBy(FAST_FORWARD_REWIND_AMOUNT);
+ seekBy(FAST_FORWARD_REWIND_AMOUNT_MILLIS);
}
public void onPlayPrevious() {
if (simpleExoPlayer == null || playQueue == null) return;
if (DEBUG) Log.d(TAG, "onPlayPrevious() called");
- /* If current playback has run for PLAY_PREV_ACTIVATION_LIMIT milliseconds,
+ /* If current playback has run for PLAY_PREV_ACTIVATION_LIMIT_MILLIS milliseconds,
* restart current track. Also restart the track if the current track
* is the first in a queue.*/
- if (simpleExoPlayer.getCurrentPosition() > PLAY_PREV_ACTIVATION_LIMIT ||
+ if (simpleExoPlayer.getCurrentPosition() > PLAY_PREV_ACTIVATION_LIMIT_MILLIS ||
playQueue.getIndex() == 0) {
seekToDefault();
playQueue.offsetIndex(0);
@@ -1050,7 +1035,9 @@ public abstract class BasePlayer implements
}
public void seekToDefault() {
- if (simpleExoPlayer != null) simpleExoPlayer.seekToDefaultPosition();
+ if (simpleExoPlayer != null) {
+ simpleExoPlayer.seekToDefaultPosition();
+ }
}
/*//////////////////////////////////////////////////////////////////////////
@@ -1091,9 +1078,9 @@ public abstract class BasePlayer implements
private void savePlaybackState() {
if (simpleExoPlayer == null || currentInfo == null) return;
- if (simpleExoPlayer.getCurrentPosition() > RECOVERY_SKIP_THRESHOLD &&
+ if (simpleExoPlayer.getCurrentPosition() > RECOVERY_SKIP_THRESHOLD_MILLIS &&
simpleExoPlayer.getCurrentPosition() <
- simpleExoPlayer.getDuration() - RECOVERY_SKIP_THRESHOLD) {
+ simpleExoPlayer.getDuration() - RECOVERY_SKIP_THRESHOLD_MILLIS) {
savePlaybackState(currentInfo, simpleExoPlayer.getCurrentPosition());
}
}
@@ -1127,9 +1114,7 @@ public abstract class BasePlayer implements
/** Checks if the current playback is a livestream AND is playing at or beyond the live edge */
public boolean isLiveEdge() {
- if (simpleExoPlayer == null) return false;
- final boolean isLive = simpleExoPlayer.isCurrentWindowDynamic();
- if (!isLive) return false;
+ if (simpleExoPlayer == null || !isLive()) return false;
final Timeline currentTimeline = simpleExoPlayer.getCurrentTimeline();
final int currentWindowIndex = simpleExoPlayer.getCurrentWindowIndex();
@@ -1143,6 +1128,16 @@ public abstract class BasePlayer implements
return timelineWindow.getDefaultPositionMs() <= simpleExoPlayer.getCurrentPosition();
}
+ public boolean isLive() {
+ if (simpleExoPlayer == null) return false;
+ try {
+ return simpleExoPlayer.isCurrentWindowDynamic();
+ } catch (@NonNull IndexOutOfBoundsException ignored) {
+ // Why would this even happen =(
+ return false;
+ }
+ }
+
public boolean isPlaying() {
final int state = simpleExoPlayer.getPlaybackState();
return (state == Player.STATE_READY || state == Player.STATE_BUFFERING)
@@ -1170,10 +1165,6 @@ public abstract class BasePlayer implements
setPlaybackParameters(speed, getPlaybackPitch());
}
- public void setPlaybackPitch(float pitch) {
- setPlaybackParameters(getPlaybackSpeed(), pitch);
- }
-
public PlaybackParameters getPlaybackParameters() {
final PlaybackParameters defaultParameters = new PlaybackParameters(1f, 1f);
if (simpleExoPlayer == null) return defaultParameters;
diff --git a/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java
index dbc34b11a..aedcdb791 100644
--- a/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java
+++ b/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java
@@ -30,8 +30,10 @@ import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.Settings;
+import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
@@ -50,6 +52,7 @@ import android.widget.TextView;
import android.widget.Toast;
import com.google.android.exoplayer2.Player;
+import com.google.android.exoplayer2.text.CaptionStyleCompat;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import com.google.android.exoplayer2.ui.SubtitleView;
@@ -59,7 +62,6 @@ import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.fragments.OnScrollBelowItemsListener;
import org.schabi.newpipe.player.helper.PlaybackParameterDialog;
import org.schabi.newpipe.player.helper.PlayerHelper;
-import org.schabi.newpipe.playlist.PlayQueue;
import org.schabi.newpipe.playlist.PlayQueueItem;
import org.schabi.newpipe.playlist.PlayQueueItemBuilder;
import org.schabi.newpipe.playlist.PlayQueueItemHolder;
@@ -95,12 +97,12 @@ public final class MainVideoPlayer extends AppCompatActivity
private GestureDetector gestureDetector;
- private boolean activityPaused;
private VideoPlayerImpl playerImpl;
private SharedPreferences defaultPreferences;
- @Nullable private StateSaver.SavedState savedState;
+ @Nullable private PlayerState playerState;
+ private boolean isInMultiWindow;
/*//////////////////////////////////////////////////////////////////////////
// Activity LifeCycle
@@ -135,8 +137,9 @@ public final class MainVideoPlayer extends AppCompatActivity
@Override
protected void onRestoreInstanceState(@NonNull Bundle bundle) {
+ if (DEBUG) Log.d(TAG, "onRestoreInstanceState() called");
super.onRestoreInstanceState(bundle);
- savedState = StateSaver.tryToRestore(bundle, this);
+ StateSaver.tryToRestore(bundle, this);
}
@Override
@@ -148,26 +151,28 @@ public final class MainVideoPlayer extends AppCompatActivity
@Override
protected void onResume() {
- super.onResume();
if (DEBUG) Log.d(TAG, "onResume() called");
- if (playerImpl.getPlayer() != null && activityPaused && playerImpl.wasPlaying()
- && !playerImpl.isPlaying()) {
- playerImpl.onPlay();
- }
- activityPaused = false;
+ super.onResume();
- if(globalScreenOrientationLocked()) {
- boolean lastOrientationWasLandscape
- = defaultPreferences.getBoolean(getString(R.string.last_orientation_landscape_key), false);
+ if (globalScreenOrientationLocked()) {
+ boolean lastOrientationWasLandscape = defaultPreferences.getBoolean(
+ getString(R.string.last_orientation_landscape_key), false);
setLandscape(lastOrientationWasLandscape);
}
- }
- @Override
- public void onBackPressed() {
- if (DEBUG) Log.d(TAG, "onBackPressed() called");
- super.onBackPressed();
- if (playerImpl.isPlaying()) playerImpl.getPlayer().setPlayWhenReady(false);
+ // Upon going in or out of multiwindow mode, isInMultiWindow will always be false,
+ // since the first onResume needs to restore the player.
+ // Subsequent onResume calls while multiwindow mode remains the same and the player is
+ // prepared should be ignored.
+ if (isInMultiWindow) return;
+ isInMultiWindow = isInMultiWindow();
+
+ if (playerState != null) {
+ playerImpl.setPlaybackQuality(playerState.getPlaybackQuality());
+ playerImpl.initPlayback(playerState.getPlayQueue(), playerState.getRepeatMode(),
+ playerState.getPlaybackSpeed(), playerState.getPlaybackPitch(),
+ playerState.wasPlaying());
+ }
}
@Override
@@ -180,33 +185,24 @@ public final class MainVideoPlayer extends AppCompatActivity
}
}
- @Override
- protected void onPause() {
- super.onPause();
- if (DEBUG) Log.d(TAG, "onPause() called");
-
- if (playerImpl != null && playerImpl.getPlayer() != null && !activityPaused) {
- playerImpl.wasPlaying = playerImpl.isPlaying();
- playerImpl.onPause();
- }
- activityPaused = true;
- }
-
@Override
protected void onSaveInstanceState(Bundle outState) {
+ if (DEBUG) Log.d(TAG, "onSaveInstanceState() called");
super.onSaveInstanceState(outState);
if (playerImpl == null) return;
playerImpl.setRecovery();
- savedState = StateSaver.tryToSave(isChangingConfigurations(), savedState,
- outState, this);
+ playerState = new PlayerState(playerImpl.getPlayQueue(), playerImpl.getRepeatMode(),
+ playerImpl.getPlaybackSpeed(), playerImpl.getPlaybackPitch(),
+ playerImpl.getPlaybackQuality(), playerImpl.isPlaying());
+ StateSaver.tryToSave(isChangingConfigurations(), null, outState, this);
}
@Override
- protected void onDestroy() {
- super.onDestroy();
- if (DEBUG) Log.d(TAG, "onDestroy() called");
- if (playerImpl != null) playerImpl.destroy();
+ protected void onStop() {
+ if (DEBUG) Log.d(TAG, "onStop() called");
+ super.onStop();
+ playerImpl.destroy();
}
/*//////////////////////////////////////////////////////////////////////////
@@ -221,48 +217,19 @@ public final class MainVideoPlayer extends AppCompatActivity
@Override
public void writeTo(Queue