From 1d42e45d785b955f7f2dfc38c4da168cd7601e27 Mon Sep 17 00:00:00 2001 From: Stypox Date: Sun, 18 Oct 2020 20:19:50 +0200 Subject: [PATCH 1/7] Unify all ways of opening VideoDetailFragment --- .../java/org/schabi/newpipe/MainActivity.java | 40 ++-- .../org/schabi/newpipe/RouterActivity.java | 87 +------ .../fragments/detail/VideoDetailFragment.java | 99 ++++---- .../fragments/list/BaseListFragment.java | 5 +- .../list/channel/ChannelFragment.java | 2 +- .../list/playlist/PlaylistFragment.java | 2 +- .../history/StatisticsPlaylistFragment.java | 12 +- .../local/playlist/LocalPlaylistFragment.java | 11 +- .../newpipe/player/ServicePlayerActivity.java | 9 +- .../newpipe/player/VideoPlayerImpl.java | 2 +- .../newpipe/player/playqueue/PlayQueue.java | 44 ---- .../schabi/newpipe/util/NavigationHelper.java | 215 ++++++++---------- app/src/main/res/values/settings_keys.xml | 1 - 13 files changed, 201 insertions(+), 328 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index e72d4609e..1d911c944 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -30,9 +30,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Looper; -import androidx.preference.PreferenceManager; import android.util.Log; - import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; @@ -46,6 +44,7 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.Spinner; import android.widget.TextView; + import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBarDrawerToggle; @@ -55,6 +54,7 @@ import androidx.core.view.GravityCompat; import androidx.drawerlayout.widget.DrawerLayout; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; +import androidx.preference.PreferenceManager; import com.google.android.material.bottomsheet.BottomSheetBehavior; import com.google.android.material.navigation.NavigationView; @@ -71,8 +71,8 @@ import org.schabi.newpipe.player.VideoPlayer; import org.schabi.newpipe.player.event.OnKeyDownListener; import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.report.ErrorActivity; -import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.Constants; +import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.KioskTranslator; import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.NavigationHelper; @@ -758,32 +758,36 @@ public class MainActivity extends AppCompatActivity { if (intent.hasExtra(Constants.KEY_LINK_TYPE)) { final String url = intent.getStringExtra(Constants.KEY_URL); final int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0); - final String title = intent.getStringExtra(Constants.KEY_TITLE); - switch (((StreamingService.LinkType) intent - .getSerializableExtra(Constants.KEY_LINK_TYPE))) { + String title = intent.getStringExtra(Constants.KEY_TITLE); + if (title == null) { + title = ""; + } + + final StreamingService.LinkType linkType = ((StreamingService.LinkType) intent + .getSerializableExtra(Constants.KEY_LINK_TYPE)); + assert linkType != null; + switch (linkType) { case STREAM: - final boolean autoPlay = intent - .getBooleanExtra(VideoDetailFragment.AUTO_PLAY, false); - final String intentCacheKey = intent - .getStringExtra(VideoPlayer.PLAY_QUEUE_KEY); + final String intentCacheKey = intent.getStringExtra( + VideoPlayer.PLAY_QUEUE_KEY); final PlayQueue playQueue = intentCacheKey != null ? SerializedCache.getInstance() .take(intentCacheKey, PlayQueue.class) : null; - NavigationHelper.openVideoDetailFragment(getSupportFragmentManager(), - serviceId, url, title, autoPlay, playQueue); + + final boolean switchingPlayers = intent.getBooleanExtra( + VideoDetailFragment.KEY_SWITCHING_PLAYERS, false); + NavigationHelper.openVideoDetailFragment( + getApplicationContext(), getSupportFragmentManager(), + serviceId, url, title, playQueue, switchingPlayers); break; case CHANNEL: NavigationHelper.openChannelFragment(getSupportFragmentManager(), - serviceId, - url, - title); + serviceId, url, title); break; case PLAYLIST: NavigationHelper.openPlaylistFragment(getSupportFragmentManager(), - serviceId, - url, - title); + serviceId, url, title); break; } } else if (intent.hasExtra(Constants.KEY_OPEN_SEARCH)) { diff --git a/app/src/main/java/org/schabi/newpipe/RouterActivity.java b/app/src/main/java/org/schabi/newpipe/RouterActivity.java index 388d7683a..ca145bb9a 100644 --- a/app/src/main/java/org/schabi/newpipe/RouterActivity.java +++ b/app/src/main/java/org/schabi/newpipe/RouterActivity.java @@ -60,8 +60,6 @@ import org.schabi.newpipe.views.FocusOverlayView; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; import java.util.List; import icepick.Icepick; @@ -116,8 +114,6 @@ public class RouterActivity extends AppCompatActivity { } } - internalRoute = getIntent().getBooleanExtra(INTERNAL_ROUTE_KEY, false); - setTheme(ThemeHelper.isLightThemeSelected(this) ? R.style.RouterActivityThemeLight : R.style.RouterActivityThemeDark); } @@ -492,10 +488,6 @@ public class RouterActivity extends AppCompatActivity { .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(intent -> { - if (!internalRoute) { - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); - } startActivity(intent); finish(); @@ -515,7 +507,7 @@ public class RouterActivity extends AppCompatActivity { @SuppressLint("CheckResult") private void openDownloadDialog() { - ExtractorHelper.getStreamInfo(currentServiceId, currentUrl, true) + disposables.add(ExtractorHelper.getStreamInfo(currentServiceId, currentUrl, true) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe((@NonNull StreamInfo result) -> { @@ -532,10 +524,10 @@ public class RouterActivity extends AppCompatActivity { downloadDialog.setSelectedVideoStream(selectedVideoStreamIndex); downloadDialog.show(fm, "downloadDialog"); fm.executePendingTransactions(); - downloadDialog.getDialog().setOnDismissListener(dialog -> finish()); + downloadDialog.requireDialog().setOnDismissListener(dialog -> finish()); }, (@NonNull Throwable throwable) -> { showUnsupportedUrlDialog(currentUrl); - }); + })); } @Override @@ -553,66 +545,6 @@ public class RouterActivity extends AppCompatActivity { } } - /*////////////////////////////////////////////////////////////////////////// - // Service Fetcher - //////////////////////////////////////////////////////////////////////////*/ - - private String removeHeadingGibberish(final String input) { - int start = 0; - for (int i = input.indexOf("://") - 1; i >= 0; i--) { - if (!input.substring(i, i + 1).matches("\\p{L}")) { - start = i + 1; - break; - } - } - return input.substring(start); - } - - /*////////////////////////////////////////////////////////////////////////// - // Utils - //////////////////////////////////////////////////////////////////////////*/ - - private String trim(final String input) { - if (input == null || input.length() < 1) { - return input; - } else { - String output = input; - while (output.length() > 0 && output.substring(0, 1).matches(REGEX_REMOVE_FROM_URL)) { - output = output.substring(1); - } - while (output.length() > 0 - && output.substring(output.length() - 1).matches(REGEX_REMOVE_FROM_URL)) { - output = output.substring(0, output.length() - 1); - } - return output; - } - } - - /** - * Retrieves all Strings which look remotely like URLs from a text. - * Used if NewPipe was called through share menu. - * - * @param sharedText text to scan for URLs. - * @return potential URLs - */ - protected String[] getUris(final String sharedText) { - final Collection result = new HashSet<>(); - if (sharedText != null) { - final String[] array = sharedText.split("\\p{Space}"); - for (String s : array) { - s = trim(s); - if (s.length() != 0) { - if (s.matches(".+://.+")) { - result.add(removeHeadingGibberish(s)); - } else if (s.matches(".+\\..+")) { - result.add("http://" + s); - } - } - } - } - return result.toArray(new String[0]); - } - private static class AdapterChoiceItem { final String description; final String key; @@ -739,11 +671,11 @@ public class RouterActivity extends AppCompatActivity { playQueue = new SinglePlayQueue((StreamInfo) info); if (playerChoice.equals(videoPlayerKey)) { - openMainPlayer(playQueue, choice); + NavigationHelper.playOnMainPlayer(this, playQueue); } else if (playerChoice.equals(backgroundPlayerKey)) { - NavigationHelper.enqueueOnBackgroundPlayer(this, playQueue, true); + NavigationHelper.playOnBackgroundPlayer(this, playQueue, true); } else if (playerChoice.equals(popupPlayerKey)) { - NavigationHelper.enqueueOnPopupPlayer(this, playQueue, true); + NavigationHelper.playOnPopupPlayer(this, playQueue, true); } } } @@ -754,7 +686,7 @@ public class RouterActivity extends AppCompatActivity { : new PlaylistPlayQueue((PlaylistInfo) info); if (playerChoice.equals(videoPlayerKey)) { - openMainPlayer(playQueue, choice); + NavigationHelper.playOnMainPlayer(this, playQueue); } else if (playerChoice.equals(backgroundPlayerKey)) { NavigationHelper.playOnBackgroundPlayer(this, playQueue, true); } else if (playerChoice.equals(popupPlayerKey)) { @@ -764,11 +696,6 @@ public class RouterActivity extends AppCompatActivity { }; } - private void openMainPlayer(final PlayQueue playQueue, final Choice choice) { - NavigationHelper.playOnMainPlayer(this, playQueue, choice.linkType, - choice.url, "", true, true); - } - @Override public void onDestroy() { super.onDestroy(); diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index d5da006f7..ffba7f521 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -110,6 +110,7 @@ import org.schabi.newpipe.views.LargeTextMovementMethod; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.Objects; import java.util.concurrent.TimeUnit; import icepick.State; @@ -128,7 +129,7 @@ import static org.schabi.newpipe.player.helper.PlayerHelper.isClearingQueueConfi import static org.schabi.newpipe.player.playqueue.PlayQueueItem.RECOVERY_UNSET; import static org.schabi.newpipe.util.AnimationUtils.animateView; -public class VideoDetailFragment +public final class VideoDetailFragment extends BaseStateFragment implements BackPressable, SharedPreferences.OnSharedPreferenceChangeListener, @@ -136,7 +137,7 @@ public class VideoDetailFragment View.OnLongClickListener, PlayerServiceExtendedEventListener, OnKeyDownListener { - public static final String AUTO_PLAY = "auto_play"; + public static final String KEY_SWITCHING_PLAYERS = "switching_players"; private static final int RELATED_STREAMS_UPDATE_FLAG = 0x1; private static final int COMMENTS_UPDATE_FLAG = 0x2; @@ -167,19 +168,23 @@ public class VideoDetailFragment @State protected int serviceId = Constants.NO_SERVICE_ID; @State - protected String name; + @NonNull + protected String title = ""; @State - protected String url; - protected static PlayQueue playQueue; + @Nullable + protected String url = null; + @Nullable + protected PlayQueue playQueue = null; @State int bottomSheetState = BottomSheetBehavior.STATE_EXPANDED; @State protected boolean autoPlayEnabled = true; - private static StreamInfo currentInfo; + @Nullable + private StreamInfo currentInfo = null; private Disposable currentWorker; @NonNull - private CompositeDisposable disposables = new CompositeDisposable(); + private final CompositeDisposable disposables = new CompositeDisposable(); @Nullable private Disposable positionSubscriber = null; @@ -298,8 +303,10 @@ public class VideoDetailFragment /*////////////////////////////////////////////////////////////////////////*/ - public static VideoDetailFragment getInstance(final int serviceId, final String videoUrl, - final String name, final PlayQueue queue) { + public static VideoDetailFragment getInstance(final int serviceId, + @Nullable final String videoUrl, + @NonNull final String name, + @Nullable final PlayQueue queue) { final VideoDetailFragment instance = new VideoDetailFragment(); instance.setInitialData(serviceId, videoUrl, name, queue); return instance; @@ -444,8 +451,8 @@ public class VideoDetailFragment switch (requestCode) { case ReCaptchaActivity.RECAPTCHA_REQUEST: if (resultCode == Activity.RESULT_OK) { - NavigationHelper - .openVideoDetailFragment(getFM(), serviceId, url, name); + NavigationHelper.openVideoDetailFragment(requireContext(), getFM(), + serviceId, url, title, null, false); } else { Log.e(TAG, "ReCaptcha failed"); } @@ -791,7 +798,7 @@ public class VideoDetailFragment player.onPause(); } restoreDefaultOrientation(); - setAutoplay(false); + setAutoPlay(false); return true; } @@ -819,14 +826,11 @@ public class VideoDetailFragment } private void setupFromHistoryItem(final StackItem item) { - setAutoplay(false); + setAutoPlay(false); hideMainPlayer(); - setInitialData( - item.getServiceId(), - item.getUrl(), - !TextUtils.isEmpty(item.getTitle()) ? item.getTitle() : "", - item.getPlayQueue()); + setInitialData(item.getServiceId(), item.getUrl(), + item.getTitle() == null ? "" : item.getTitle(), item.getPlayQueue()); startLoading(false); // Maybe an item was deleted in background activity @@ -860,18 +864,17 @@ public class VideoDetailFragment } } - public void selectAndLoadVideo(final int sid, final String videoUrl, final String title, - final PlayQueue queue) { - // Situation when user switches from players to main player. - // All needed data is here, we can start watching - if (this.playQueue != null && this.playQueue.equals(queue)) { - openVideoPlayer(); - return; - } - setInitialData(sid, videoUrl, title, queue); - if (player != null) { + public void selectAndLoadVideo(final int newServiceId, + @Nullable final String newUrl, + @NonNull final String newTitle, + @Nullable final PlayQueue newQueue) { + if (player != null && newQueue != null && playQueue != null + && !Objects.equals(newQueue.getItem(), playQueue.getItem())) { + // Preloading can be disabled since playback is surely being replaced. player.disablePreloadingOfCurrentTrack(); } + + setInitialData(newServiceId, newUrl, newTitle, newQueue); startLoading(false, true); } @@ -956,7 +959,7 @@ public class VideoDetailFragment playQueue = new SinglePlayQueue(result); } if (stack.isEmpty() || !stack.peek().getPlayQueue().equals(playQueue)) { - stack.push(new StackItem(serviceId, url, name, playQueue)); + stack.push(new StackItem(serviceId, url, title, playQueue)); } } if (isAutoplayEnabled()) { @@ -977,7 +980,7 @@ public class VideoDetailFragment if (shouldShowComments()) { pageAdapter.addFragment( - CommentsFragment.getInstance(serviceId, url, name), COMMENTS_TAB_TAG); + CommentsFragment.getInstance(serviceId, url, title), COMMENTS_TAB_TAG); } if (showRelatedStreams && null == relatedStreamsLayout) { @@ -1068,7 +1071,7 @@ public class VideoDetailFragment } } - private void openVideoPlayer() { + public void openVideoPlayer() { if (PreferenceManager.getDefaultSharedPreferences(activity) .getBoolean(this.getString(R.string.use_external_video_player_key), false)) { showExternalPlaybackDialog(); @@ -1143,8 +1146,8 @@ public class VideoDetailFragment // Utils //////////////////////////////////////////////////////////////////////////*/ - public void setAutoplay(final boolean autoplay) { - this.autoPlayEnabled = autoplay; + public void setAutoPlay(final boolean autoPlay) { + this.autoPlayEnabled = autoPlay; } private void startOnExternalPlayer(@NonNull final Context context, @@ -1166,7 +1169,7 @@ public class VideoDetailFragment .getBoolean(getString(R.string.use_external_video_player_key), false); } - // This method overrides default behaviour when setAutoplay() is called. + // This method overrides default behaviour when setAutoPlay() is called. // Don't auto play if the user selected an external player or disabled it in settings private boolean isAutoplayEnabled() { return autoPlayEnabled @@ -1302,12 +1305,14 @@ public class VideoDetailFragment contentRootLayoutHiding.setVisibility(View.VISIBLE); } - protected void setInitialData(final int sid, final String u, final String title, - final PlayQueue queue) { - this.serviceId = sid; - this.url = u; - this.name = !TextUtils.isEmpty(title) ? title : ""; - this.playQueue = queue; + protected void setInitialData(final int newServiceId, + @Nullable final String newUrl, + @NonNull final String newTitle, + @Nullable final PlayQueue newPlayQueue) { + this.serviceId = newServiceId; + this.url = newUrl; + this.title = newTitle; + this.playQueue = newPlayQueue; } private void setErrorImage(final int imageResource) { @@ -1400,7 +1405,7 @@ public class VideoDetailFragment animateView(detailPositionView, false, 100); animateView(positionView, false, 50); - videoTitleTextView.setText(name != null ? name : ""); + videoTitleTextView.setText(title); videoTitleTextView.setMaxLines(1); animateView(videoTitleTextView, true, 0); @@ -1445,7 +1450,7 @@ public class VideoDetailFragment } } animateView(thumbnailPlayButton, true, 200); - videoTitleTextView.setText(name); + videoTitleTextView.setText(title); if (!TextUtils.isEmpty(info.getSubChannelName())) { displayBothUploaderAndSubChannel(info); @@ -1738,7 +1743,7 @@ public class VideoDetailFragment if (DEBUG) { Log.d(TAG, "onQueueUpdate() called with: serviceId = [" + serviceId + "], videoUrl = [" + url + "], name = [" - + name + "], playQueue = [" + playQueue + "]"); + + title + "], playQueue = [" + playQueue + "]"); } // This should be the only place where we push data to stack. @@ -1823,7 +1828,7 @@ public class VideoDetailFragment currentInfo = info; setInitialData(info.getServiceId(), info.getUrl(), info.getName(), queue); - setAutoplay(false); + setAutoPlay(false); // Delay execution just because it freezes the main thread, and while playing // next/previous video you see visual glitches // (when non-vertical video goes after vertical video) @@ -2037,7 +2042,7 @@ public class VideoDetailFragment private void checkLandscape() { if ((!player.isPlaying() && player.getPlayQueue() != playQueue) || player.getPlayQueue() == null) { - setAutoplay(true); + setAutoPlay(true); } player.checkLandscape(); @@ -2287,10 +2292,10 @@ public class VideoDetailFragment }); } - private void updateOverlayData(@Nullable final String title, + private void updateOverlayData(@Nullable final String overlayTitle, @Nullable final String uploader, @Nullable final String thumbnailUrl) { - overlayTitleTextView.setText(TextUtils.isEmpty(title) ? "" : title); + overlayTitleTextView.setText(TextUtils.isEmpty(overlayTitle) ? "" : overlayTitle); overlayChannelTextView.setText(TextUtils.isEmpty(uploader) ? "" : uploader); overlayThumbnailImageView.setImageResource(R.drawable.dummy_thumbnail_dark); if (!TextUtils.isEmpty(thumbnailUrl)) { diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java index 79e1854e9..41263bc34 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java @@ -321,8 +321,9 @@ public abstract class BaseListFragment extends BaseStateFragment private void onStreamSelected(final StreamInfoItem selectedItem) { onItemSelected(selectedItem); - NavigationHelper.openVideoDetailFragment(getFM(), - selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName()); + NavigationHelper.openVideoDetailFragment(requireContext(), getFM(), + selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName(), + null, false); } protected void onScrollToBottom() { 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 58e28df49..6ec818909 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 @@ -517,7 +517,7 @@ public class ChannelFragment extends BaseListInfoFragment monitorSubscription(result); headerPlayAllButton.setOnClickListener(view -> NavigationHelper - .playOnMainPlayer(activity, getPlayQueue(), true)); + .playOnMainPlayer(activity, getPlayQueue())); headerPopupButton.setOnClickListener(view -> NavigationHelper .playOnPopupPlayer(activity, getPlayQueue(), false)); headerBackgroundButton.setOnClickListener(view -> NavigationHelper diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java index 67f1a007a..71b51f9a1 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java @@ -319,7 +319,7 @@ public class PlaylistFragment extends BaseListInfoFragment { .subscribe(getPlaylistBookmarkSubscriber()); headerPlayAllButton.setOnClickListener(view -> - NavigationHelper.playOnMainPlayer(activity, getPlayQueue(), true)); + NavigationHelper.playOnMainPlayer(activity, getPlayQueue())); headerPopupButton.setOnClickListener(view -> NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(), false)); headerBackgroundButton.setOnClickListener(view -> diff --git a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java index b4398d873..8cd4e4c7e 100644 --- a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java @@ -25,6 +25,7 @@ import org.reactivestreams.Subscription; import org.schabi.newpipe.R; import org.schabi.newpipe.database.LocalItem; import org.schabi.newpipe.database.stream.StreamStatisticsEntry; +import org.schabi.newpipe.database.stream.model.StreamEntity; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.info_list.InfoItemDialog; @@ -149,11 +150,10 @@ public class StatisticsPlaylistFragment @Override public void selected(final LocalItem selectedItem) { if (selectedItem instanceof StreamStatisticsEntry) { - final StreamStatisticsEntry item = (StreamStatisticsEntry) selectedItem; - NavigationHelper.openVideoDetailFragment(getFM(), - item.getStreamEntity().getServiceId(), - item.getStreamEntity().getUrl(), - item.getStreamEntity().getTitle()); + final StreamEntity item = + ((StreamStatisticsEntry) selectedItem).getStreamEntity(); + NavigationHelper.openVideoDetailFragment(requireContext(), getFM(), + item.getServiceId(), item.getUrl(), item.getTitle(), null, false); } } @@ -325,7 +325,7 @@ public class StatisticsPlaylistFragment } headerPlayAllButton.setOnClickListener(view -> - NavigationHelper.playOnMainPlayer(activity, getPlayQueue(), true)); + NavigationHelper.playOnMainPlayer(activity, getPlayQueue())); headerPopupButton.setOnClickListener(view -> NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(), false)); headerBackgroundButton.setOnClickListener(view -> diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java index 32fac9de0..71df07a4b 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java @@ -30,6 +30,7 @@ import org.schabi.newpipe.R; import org.schabi.newpipe.database.LocalItem; import org.schabi.newpipe.database.history.model.StreamHistoryEntry; import org.schabi.newpipe.database.playlist.PlaylistStreamEntry; +import org.schabi.newpipe.database.stream.model.StreamEntity; import org.schabi.newpipe.database.stream.model.StreamStateEntity; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.extractor.stream.StreamType; @@ -178,10 +179,10 @@ public class LocalPlaylistFragment extends BaseLocalListFragment - NavigationHelper.playOnMainPlayer(activity, getPlayQueue(), true)); + NavigationHelper.playOnMainPlayer(activity, getPlayQueue())); headerPopupButton.setOnClickListener(view -> NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(), false)); headerBackgroundButton.setOnClickListener(view -> diff --git a/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java b/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java index 8b606260a..fee189295 100644 --- a/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java +++ b/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java @@ -367,7 +367,9 @@ public abstract class ServicePlayerActivity extends AppCompatActivity final MenuItem detail = popupMenu.getMenu().add(RECYCLER_ITEM_POPUP_MENU_GROUP_ID, 1, Menu.NONE, R.string.play_queue_stream_detail); detail.setOnMenuItemClickListener(menuItem -> { - onOpenDetail(item.getServiceId(), item.getUrl(), item.getTitle()); + // playQueue is null since we don't want any queue change + NavigationHelper.openVideoDetail( + this, item.getServiceId(), item.getUrl(), item.getTitle(), null); return true; }); @@ -454,11 +456,6 @@ public abstract class ServicePlayerActivity extends AppCompatActivity }; } - private void onOpenDetail(final int serviceId, final String videoUrl, - final String videoTitle) { - NavigationHelper.openVideoDetail(this, serviceId, videoUrl, videoTitle); - } - private void scrollToSelected() { if (player == null) { return; diff --git a/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java b/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java index 97007f0f6..765eb148b 100644 --- a/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java +++ b/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java @@ -785,7 +785,7 @@ public class VideoPlayerImpl extends VideoPlayer intent.putExtra(Constants.KEY_LINK_TYPE, StreamingService.LinkType.STREAM); intent.putExtra(Constants.KEY_URL, getVideoUrl()); intent.putExtra(Constants.KEY_TITLE, getVideoTitle()); - intent.putExtra(VideoDetailFragment.AUTO_PLAY, true); + intent.putExtra(VideoDetailFragment.KEY_SWITCHING_PLAYERS, true); service.onDestroy(); context.startActivity(intent); } diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueue.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueue.java index 4f35f98f5..b8bb677e0 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueue.java +++ b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueue.java @@ -1,12 +1,8 @@ package org.schabi.newpipe.player.playqueue; -import android.util.Log; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.player.playqueue.events.AppendEvent; import org.schabi.newpipe.player.playqueue.events.ErrorEvent; @@ -43,7 +39,6 @@ import io.reactivex.subjects.BehaviorSubject; *

*/ public abstract class PlayQueue implements Serializable { - private final String TAG = "PlayQueue@" + Integer.toHexString(hashCode()); public static final boolean DEBUG = MainActivity.DEBUG; private ArrayList backup; @@ -55,7 +50,6 @@ public abstract class PlayQueue implements Serializable { private transient BehaviorSubject eventBroadcast; private transient Flowable broadcastReceiver; - private transient Subscription reportingReactor; private transient boolean disposed; @@ -87,10 +81,6 @@ public abstract class PlayQueue implements Serializable { broadcastReceiver = eventBroadcast.toFlowable(BackpressureStrategy.BUFFER) .observeOn(AndroidSchedulers.mainThread()) .startWith(new InitEvent()); - - if (DEBUG) { - broadcastReceiver.subscribe(getSelfReporter()); - } } /** @@ -100,13 +90,9 @@ public abstract class PlayQueue implements Serializable { if (eventBroadcast != null) { eventBroadcast.onComplete(); } - if (reportingReactor != null) { - reportingReactor.cancel(); - } eventBroadcast = null; broadcastReceiver = null; - reportingReactor = null; disposed = true; } @@ -544,35 +530,5 @@ public abstract class PlayQueue implements Serializable { eventBroadcast.onNext(event); } } - - private Subscriber getSelfReporter() { - return new Subscriber() { - @Override - public void onSubscribe(final Subscription s) { - if (reportingReactor != null) { - reportingReactor.cancel(); - } - reportingReactor = s; - reportingReactor.request(1); - } - - @Override - public void onNext(final PlayQueueEvent event) { - Log.d(TAG, "Received broadcast: " + event.type().name() + ". " - + "Current index: " + getIndex() + ", play queue length: " + size() + "."); - reportingReactor.request(1); - } - - @Override - public void onError(final Throwable t) { - Log.e(TAG, "Received broadcast error", t); - } - - @Override - public void onComplete() { - Log.d(TAG, "Broadcast is shutting down."); - } - }; - } } diff --git a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java index 6761fce59..a96730552 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java @@ -18,7 +18,6 @@ import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; -import androidx.preference.PreferenceManager; import com.nostra13.universalimageloader.core.ImageLoader; @@ -52,13 +51,14 @@ import org.schabi.newpipe.player.BackgroundPlayerActivity; import org.schabi.newpipe.player.BasePlayer; import org.schabi.newpipe.player.MainPlayer; import org.schabi.newpipe.player.VideoPlayer; +import org.schabi.newpipe.player.helper.PlayerHelper; +import org.schabi.newpipe.player.helper.PlayerHolder; import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.player.playqueue.PlayQueueItem; import org.schabi.newpipe.settings.SettingsActivity; import java.util.ArrayList; -@SuppressWarnings({"unused"}) public final class NavigationHelper { public static final String MAIN_FRAGMENT_TAG = "main_fragment_tag"; public static final String SEARCH_FRAGMENT_TAG = "search_fragment_tag"; @@ -130,42 +130,22 @@ public final class NavigationHelper { } public static void playOnMainPlayer(final AppCompatActivity activity, - final PlayQueue queue, - final boolean autoPlay) { - playOnMainPlayer(activity.getSupportFragmentManager(), queue, autoPlay); + @NonNull final PlayQueue playQueue) { + final PlayQueueItem item = playQueue.getItem(); + assert item != null; + openVideoDetailFragment(activity, activity.getSupportFragmentManager(), + item.getServiceId(), item.getUrl(), item.getTitle(), playQueue, false); } - public static void playOnMainPlayer(final FragmentManager fragmentManager, - final PlayQueue queue, - final boolean autoPlay) { - final PlayQueueItem currentStream = queue.getItem(); - openVideoDetailFragment( - fragmentManager, - currentStream.getServiceId(), - currentStream.getUrl(), - currentStream.getTitle(), - autoPlay, - queue); + public static void playOnMainPlayer(final Context context, + @NonNull final PlayQueue playQueue) { + final PlayQueueItem item = playQueue.getItem(); + assert item != null; + openVideoDetail(context, item.getServiceId(), item.getUrl(), item.getTitle(), playQueue); } - public static void playOnMainPlayer(@NonNull final Context context, - @Nullable final PlayQueue queue, - @NonNull final StreamingService.LinkType linkType, - @NonNull final String url, - @NonNull final String title, - final boolean autoPlay, - final boolean resumePlayback) { - - final Intent intent = getPlayerIntent(context, MainActivity.class, queue, resumePlayback); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(Constants.KEY_LINK_TYPE, linkType); - intent.putExtra(Constants.KEY_URL, url); - intent.putExtra(Constants.KEY_TITLE, title); - intent.putExtra(VideoDetailFragment.AUTO_PLAY, autoPlay); - context.startActivity(intent); - } - - public static void playOnPopupPlayer(final Context context, final PlayQueue queue, + public static void playOnPopupPlayer(final Context context, + final PlayQueue queue, final boolean resumePlayback) { if (!PermissionHelper.isPopupEnabled(context)) { PermissionHelper.showPopupEnablementToast(context); @@ -300,9 +280,6 @@ public final class NavigationHelper { .setNegativeButton(R.string.cancel, (dialog, which) -> Log.i("NavigationHelper", "You unlocked a secret unicorn.")) .show(); -// Log.e("NavigationHelper", -// "Either no Streaming player for audio was installed, " -// + "or something important crashed:"); } else { Toast.makeText(context, R.string.no_player_found_toast, Toast.LENGTH_LONG).show(); } @@ -358,41 +335,6 @@ public final class NavigationHelper { .commit(); } - public static void openVideoDetailFragment(final FragmentManager fragmentManager, - final int serviceId, final String url, - final String title) { - openVideoDetailFragment(fragmentManager, serviceId, url, title, true, null); - } - - public static void openVideoDetailFragment( - final FragmentManager fragmentManager, - final int serviceId, - final String url, - final String title, - final boolean autoPlay, - final PlayQueue playQueue) { - final Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_player_holder); - - if (fragment instanceof VideoDetailFragment && fragment.isVisible()) { - expandMainPlayer(fragment.requireActivity()); - final VideoDetailFragment detailFragment = (VideoDetailFragment) fragment; - detailFragment.setAutoplay(autoPlay); - detailFragment - .selectAndLoadVideo(serviceId, url, title == null ? "" : title, playQueue); - detailFragment.scrollToTop(); - return; - } - - final VideoDetailFragment instance = VideoDetailFragment - .getInstance(serviceId, url, title == null ? "" : title, playQueue); - instance.setAutoplay(autoPlay); - - defaultTransaction(fragmentManager) - .replace(R.id.fragment_player_holder, instance) - .runOnCommit(() -> expandMainPlayer(instance.requireActivity())) - .commit(); - } - public static void expandMainPlayer(final Context context) { context.sendBroadcast(new Intent(VideoDetailFragment.ACTION_SHOW_MAIN_PLAYER)); } @@ -409,33 +351,86 @@ public final class NavigationHelper { .commitAllowingStateLoss(); } + private interface RunnableWithVideoDetailFragment { + void run(VideoDetailFragment detailFragment); + } + + public static void openVideoDetailFragment(@NonNull final Context context, + @NonNull final FragmentManager fragmentManager, + final int serviceId, + @Nullable final String url, + @NonNull final String title, + @Nullable final PlayQueue playQueue, + final boolean switchingPlayers) { + + final boolean autoPlay; + @Nullable final MainPlayer.PlayerType playerType = PlayerHolder.getType(); + if (playerType == null) { + // no player open + autoPlay = PlayerHelper.isAutoplayAllowedByUser(context); + } else if (switchingPlayers) { + // switching player to main player + autoPlay = true; + } else if (playerType == MainPlayer.PlayerType.VIDEO) { + // opening new stream while already playing in main player + autoPlay = PlayerHelper.isAutoplayAllowedByUser(context); + } else { + // opening new stream while already playing in another player + autoPlay = false; + } + + final RunnableWithVideoDetailFragment onVideoDetailFragmentReady = (detailFragment) -> { + expandMainPlayer(detailFragment.requireActivity()); + detailFragment.setAutoPlay(autoPlay); + if (switchingPlayers) { + // Situation when user switches from players to main player. All needed data is + // here, we can start watching (assuming newQueue equals playQueue). + detailFragment.openVideoPlayer(); + } else { + detailFragment.selectAndLoadVideo(serviceId, url, title, playQueue); + } + detailFragment.scrollToTop(); + }; + + final Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_player_holder); + if (fragment instanceof VideoDetailFragment && fragment.isVisible()) { + onVideoDetailFragmentReady.run((VideoDetailFragment) fragment); + } else { + final VideoDetailFragment instance = VideoDetailFragment + .getInstance(serviceId, url, title, playQueue); + instance.setAutoPlay(autoPlay); + + defaultTransaction(fragmentManager) + .replace(R.id.fragment_player_holder, instance) + .runOnCommit(() -> onVideoDetailFragmentReady.run(instance)) + .commit(); + } + } + public static void openChannelFragment(final FragmentManager fragmentManager, final int serviceId, final String url, - final String name) { + @NonNull final String name) { defaultTransaction(fragmentManager) - .replace(R.id.fragment_holder, ChannelFragment.getInstance(serviceId, url, - name == null ? "" : name)) + .replace(R.id.fragment_holder, ChannelFragment.getInstance(serviceId, url, name)) .addToBackStack(null) .commit(); } public static void openCommentsFragment(final FragmentManager fragmentManager, final int serviceId, final String url, - final String name) { + @NonNull final String name) { fragmentManager.beginTransaction() .setCustomAnimations(R.anim.switch_service_in, R.anim.switch_service_out) - .replace(R.id.fragment_holder, CommentsFragment.getInstance(serviceId, url, - name == null ? "" : name)) + .replace(R.id.fragment_holder, CommentsFragment.getInstance(serviceId, url, name)) .addToBackStack(null) .commit(); } public static void openPlaylistFragment(final FragmentManager fragmentManager, final int serviceId, final String url, - final String name) { + @NonNull final String name) { defaultTransaction(fragmentManager) - .replace(R.id.fragment_holder, PlaylistFragment.getInstance(serviceId, url, - name == null ? "" : name)) + .replace(R.id.fragment_holder, PlaylistFragment.getInstance(serviceId, url, name)) .addToBackStack(null) .commit(); } @@ -511,33 +506,31 @@ public final class NavigationHelper { context.startActivity(mIntent); } - public static void openChannel(final Context context, final int serviceId, final String url) { - openChannel(context, serviceId, url, null); - } - public static void openChannel(final Context context, final int serviceId, - final String url, final String name) { + final String url, @NonNull final String name) { final Intent openIntent = getOpenIntent(context, url, serviceId, StreamingService.LinkType.CHANNEL); - if (name != null && !name.isEmpty()) { - openIntent.putExtra(Constants.KEY_TITLE, name); - } + openIntent.putExtra(Constants.KEY_TITLE, name); context.startActivity(openIntent); } - public static void openVideoDetail(final Context context, final int serviceId, - final String url) { - openVideoDetail(context, serviceId, url, null); - } + public static void openVideoDetail(final Context context, + final int serviceId, + final String url, + @NonNull final String title, + @Nullable final PlayQueue playQueue) { - public static void openVideoDetail(final Context context, final int serviceId, - final String url, final String title) { - final Intent openIntent = getOpenIntent(context, url, serviceId, + final Intent intent = getOpenIntent(context, url, serviceId, StreamingService.LinkType.STREAM); - if (title != null && !title.isEmpty()) { - openIntent.putExtra(Constants.KEY_TITLE, title); + intent.putExtra(Constants.KEY_TITLE, title); + + if (playQueue != null) { + final String cacheKey = SerializedCache.getInstance().put(playQueue, PlayQueue.class); + if (cacheKey != null) { + intent.putExtra(VideoPlayer.PLAY_QUEUE_KEY, cacheKey); + } } - context.startActivity(openIntent); + context.startActivity(intent); } public static void openMainActivity(final Context context) { @@ -550,7 +543,6 @@ public final class NavigationHelper { public static void openRouterActivity(final Context context, final String url) { final Intent mIntent = new Intent(context, RouterActivity.class); mIntent.setData(Uri.parse(url)); - mIntent.putExtra(RouterActivity.INTERNAL_ROUTE_KEY, true); context.startActivity(mIntent); } @@ -564,14 +556,12 @@ public final class NavigationHelper { context.startActivity(intent); } - public static boolean openDownloads(final Activity activity) { - if (!PermissionHelper.checkStoragePermissions( + public static void openDownloads(final Activity activity) { + if (PermissionHelper.checkStoragePermissions( activity, PermissionHelper.DOWNLOADS_REQUEST_CODE)) { - return false; + final Intent intent = new Intent(activity, DownloadActivity.class); + activity.startActivity(intent); } - final Intent intent = new Intent(activity, DownloadActivity.class); - activity.startActivity(intent); - return true; } public static Intent getPlayQueueActivityIntent(final Context context) { @@ -600,7 +590,8 @@ public final class NavigationHelper { return getIntentByLink(context, NewPipe.getServiceByUrl(url), url); } - public static Intent getIntentByLink(final Context context, final StreamingService service, + public static Intent getIntentByLink(final Context context, + final StreamingService service, final String url) throws ExtractionException { final StreamingService.LinkType linkType = service.getLinkTypeByUrl(url); @@ -609,15 +600,7 @@ public final class NavigationHelper { + " url=" + url); } - final Intent rIntent = getOpenIntent(context, url, service.getServiceId(), linkType); - - if (linkType == StreamingService.LinkType.STREAM) { - rIntent.putExtra(VideoDetailFragment.AUTO_PLAY, - PreferenceManager.getDefaultSharedPreferences(context).getBoolean( - context.getString(R.string.autoplay_through_intent_key), false)); - } - - return rIntent; + return getOpenIntent(context, url, service.getServiceId(), linkType); } private static Uri openMarketUrl(final String packageName) { diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index 1aa781fe2..9c9fa4853 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -21,7 +21,6 @@ use_external_video_player use_external_audio_player - autoplay_through_intent use_oldplayer volume_gesture_control From bb882ada2c4460c9c3705a6fdf461be205f6a2fc Mon Sep 17 00:00:00 2001 From: Stypox Date: Sun, 18 Oct 2020 20:33:08 +0200 Subject: [PATCH 2/7] Show "Show info" instead of "Video player" if a stream is playing not on the main player when sharing something to NewPipe --- .../org/schabi/newpipe/RouterActivity.java | 72 +++++++++---------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/RouterActivity.java b/app/src/main/java/org/schabi/newpipe/RouterActivity.java index ca145bb9a..4f563a1d1 100644 --- a/app/src/main/java/org/schabi/newpipe/RouterActivity.java +++ b/app/src/main/java/org/schabi/newpipe/RouterActivity.java @@ -40,7 +40,9 @@ import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.playlist.PlaylistInfo; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.VideoStream; +import org.schabi.newpipe.player.MainPlayer; import org.schabi.newpipe.player.helper.PlayerHelper; +import org.schabi.newpipe.player.helper.PlayerHolder; import org.schabi.newpipe.player.playqueue.ChannelPlayQueue; import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.player.playqueue.PlaylistPlayQueue; @@ -394,14 +396,22 @@ public class RouterActivity extends AppCompatActivity { // show both "show info" and "video player", they are two different activities returnList.add(showInfo); returnList.add(videoPlayer); - } else if (capabilities.contains(VIDEO) - && PlayerHelper.isAutoplayAllowedByUser(context)) { - // show only "video player" since the details activity will be opened and the video - // will be autoplayed there and "show info" would do the exact same thing - returnList.add(videoPlayer); } else { - // show only "show info" if video player is not applicable or autoplay is disabled - returnList.add(showInfo); + final MainPlayer.PlayerType playerType = PlayerHolder.getType(); + if (capabilities.contains(VIDEO) + && PlayerHelper.isAutoplayAllowedByUser(context) + && playerType == null || playerType == MainPlayer.PlayerType.VIDEO) { + // show only "video player" since the details activity will be opened and the + // video will be auto played there. Since "show info" would do the exact same + // thing, use that as a key to let VideoDetailFragment load the stream instead + // of using FetcherService (see comment in handleChoice()) + returnList.add(new AdapterChoiceItem( + showInfo.key, videoPlayer.description, videoPlayer.icon)); + } else { + // show only "show info" if video player is not applicable, auto play is + // disabled or a video is playing in a player different than the main one + returnList.add(showInfo); + } } if (capabilities.contains(VIDEO)) { @@ -489,7 +499,6 @@ public class RouterActivity extends AppCompatActivity { .observeOn(AndroidSchedulers.mainThread()) .subscribe(intent -> { startActivity(intent); - finish(); }, throwable -> handleError(throwable, currentUrl)) ); @@ -657,41 +666,30 @@ public class RouterActivity extends AppCompatActivity { final boolean isExtAudioEnabled = preferences.getBoolean( getString(R.string.use_external_audio_player_key), false); - PlayQueue playQueue; - final String playerChoice = choice.playerChoice; - + final PlayQueue playQueue; if (info instanceof StreamInfo) { - if (playerChoice.equals(backgroundPlayerKey) && isExtAudioEnabled) { + if (choice.playerChoice.equals(backgroundPlayerKey) && isExtAudioEnabled) { NavigationHelper.playOnExternalAudioPlayer(this, (StreamInfo) info); - - } else if (playerChoice.equals(videoPlayerKey) && isExtVideoEnabled) { + return; + } else if (choice.playerChoice.equals(videoPlayerKey) && isExtVideoEnabled) { NavigationHelper.playOnExternalVideoPlayer(this, (StreamInfo) info); - - } else { - playQueue = new SinglePlayQueue((StreamInfo) info); - - if (playerChoice.equals(videoPlayerKey)) { - NavigationHelper.playOnMainPlayer(this, playQueue); - } else if (playerChoice.equals(backgroundPlayerKey)) { - NavigationHelper.playOnBackgroundPlayer(this, playQueue, true); - } else if (playerChoice.equals(popupPlayerKey)) { - NavigationHelper.playOnPopupPlayer(this, playQueue, true); - } + return; } + playQueue = new SinglePlayQueue((StreamInfo) info); + } else if (info instanceof ChannelInfo) { + playQueue = new ChannelPlayQueue((ChannelInfo) info); + } else if (info instanceof PlaylistInfo) { + playQueue = new PlaylistPlayQueue((PlaylistInfo) info); + } else { + return; } - if (info instanceof ChannelInfo || info instanceof PlaylistInfo) { - playQueue = info instanceof ChannelInfo - ? new ChannelPlayQueue((ChannelInfo) info) - : new PlaylistPlayQueue((PlaylistInfo) info); - - if (playerChoice.equals(videoPlayerKey)) { - NavigationHelper.playOnMainPlayer(this, playQueue); - } else if (playerChoice.equals(backgroundPlayerKey)) { - NavigationHelper.playOnBackgroundPlayer(this, playQueue, true); - } else if (playerChoice.equals(popupPlayerKey)) { - NavigationHelper.playOnPopupPlayer(this, playQueue, true); - } + if (choice.playerChoice.equals(videoPlayerKey)) { + NavigationHelper.playOnMainPlayer(this, playQueue); + } else if (choice.playerChoice.equals(backgroundPlayerKey)) { + NavigationHelper.playOnBackgroundPlayer(this, playQueue, true); + } else if (choice.playerChoice.equals(popupPlayerKey)) { + NavigationHelper.playOnPopupPlayer(this, playQueue, true); } }; } From 2a2c82e73bb2380c07ab848b185952ab183a5502 Mon Sep 17 00:00:00 2001 From: Stypox Date: Sat, 31 Oct 2020 20:26:09 +0100 Subject: [PATCH 3/7] More fixes with opening VideoDetailFragment --- .../org/schabi/newpipe/RouterActivity.java | 2 +- .../fragments/detail/VideoDetailFragment.java | 4 +- .../player/BackgroundPlayerActivity.java | 28 --------- .../org/schabi/newpipe/player/BasePlayer.java | 33 ++++++----- .../org/schabi/newpipe/player/MainPlayer.java | 2 +- .../newpipe/player/ServicePlayerActivity.java | 47 ++++++--------- .../newpipe/player/VideoPlayerImpl.java | 48 +++------------ .../player/event/BasePlayerGestureListener.kt | 5 +- .../newpipe/player/helper/AudioReactor.java | 2 +- .../newpipe/player/helper/PlayerHelper.java | 6 +- .../newpipe/player/helper/PlayerHolder.java | 7 +++ .../player/playqueue/PlayQueueItem.java | 14 +++++ .../schabi/newpipe/util/NavigationHelper.java | 59 ++++--------------- 13 files changed, 87 insertions(+), 170 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/RouterActivity.java b/app/src/main/java/org/schabi/newpipe/RouterActivity.java index 4f563a1d1..537d71901 100644 --- a/app/src/main/java/org/schabi/newpipe/RouterActivity.java +++ b/app/src/main/java/org/schabi/newpipe/RouterActivity.java @@ -685,7 +685,7 @@ public class RouterActivity extends AppCompatActivity { } if (choice.playerChoice.equals(videoPlayerKey)) { - NavigationHelper.playOnMainPlayer(this, playQueue); + NavigationHelper.playOnMainPlayer(this, playQueue, false); } else if (choice.playerChoice.equals(backgroundPlayerKey)) { NavigationHelper.playOnBackgroundPlayer(this, playQueue, true); } else if (choice.playerChoice.equals(popupPlayerKey)) { diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index ffba7f521..1324d6832 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -1097,7 +1097,7 @@ public final class VideoDetailFragment private void openMainPlayer() { if (playerService == null) { - PlayerHolder.startService(App.getApp(), true, this); + PlayerHolder.startService(App.getApp(), autoPlayEnabled, this); return; } if (currentInfo == null) { @@ -1112,7 +1112,7 @@ public final class VideoDetailFragment addVideoPlayerView(); final Intent playerIntent = NavigationHelper - .getPlayerIntent(requireContext(), MainPlayer.class, queue, null, true); + .getPlayerIntent(requireContext(), MainPlayer.class, queue, true, autoPlayEnabled); activity.startService(playerIntent); } diff --git a/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayerActivity.java b/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayerActivity.java index 0e5222f5e..2fc710fb0 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayerActivity.java +++ b/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayerActivity.java @@ -2,11 +2,8 @@ package org.schabi.newpipe.player; import android.content.Intent; import android.view.Menu; -import android.view.MenuItem; import org.schabi.newpipe.R; -import org.schabi.newpipe.util.NavigationHelper; -import org.schabi.newpipe.util.PermissionHelper; public final class BackgroundPlayerActivity extends ServicePlayerActivity { @@ -46,31 +43,6 @@ public final class BackgroundPlayerActivity extends ServicePlayerActivity { return R.menu.menu_play_queue_bg; } - @Override - public boolean onPlayerOptionSelected(final MenuItem item) { - if (item.getItemId() == R.id.action_switch_popup) { - - if (!PermissionHelper.isPopupEnabled(this)) { - PermissionHelper.showPopupEnablementToast(this); - return true; - } - - this.player.setRecovery(); - NavigationHelper.playOnPopupPlayer( - getApplicationContext(), player.playQueue, this.player.isPlaying()); - return true; - } - - if (item.getItemId() == R.id.action_switch_background) { - this.player.setRecovery(); - NavigationHelper.playOnBackgroundPlayer( - getApplicationContext(), player.playQueue, this.player.isPlaying()); - return true; - } - - return false; - } - @Override public void setupMenu(final Menu menu) { if (player == null) { 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 70f2e158b..1355f4285 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java @@ -125,7 +125,7 @@ public abstract class BasePlayer implements @NonNull public static final String RESUME_PLAYBACK = "resume_playback"; @NonNull - public static final String START_PAUSED = "start_paused"; + public static final String PLAY_WHEN_READY = "play_when_ready"; @NonNull public static final String SELECT_ON_APPEND = "select_on_append"; @NonNull @@ -224,7 +224,7 @@ public abstract class BasePlayer implements this.dataSource = new PlayerDataSource(context, userAgent, bandwidthMeter); final TrackSelection.Factory trackSelectionFactory = PlayerHelper - .getQualitySelector(context); + .getQualitySelector(); this.trackSelector = new CustomTrackSelector(context, trackSelectionFactory); this.loadControl = new LoadController(); @@ -302,6 +302,7 @@ public abstract class BasePlayer implements final boolean samePlayQueue = playQueue != null && playQueue.equals(queue); final int repeatMode = intent.getIntExtra(REPEAT_MODE, getRepeatMode()); + final boolean playWhenReady = intent.getBooleanExtra(PLAY_WHEN_READY, true); final boolean isMuted = intent .getBooleanExtra(IS_MUTED, simpleExoPlayer != null && isMuted()); @@ -327,16 +328,20 @@ public abstract class BasePlayer implements simpleExoPlayer.retry(); } simpleExoPlayer.seekTo(playQueue.getIndex(), queue.getItem().getRecoveryPosition()); - return; + simpleExoPlayer.setPlayWhenReady(playWhenReady); - } else if (samePlayQueue && !playQueue.isDisposed() && simpleExoPlayer != null) { + } else if (simpleExoPlayer != null + && samePlayQueue + && playQueue != null + && !playQueue.isDisposed()) { // Do not re-init the same PlayQueue. Save time // Player can have state = IDLE when playback is stopped or failed // and we should retry() in this case if (simpleExoPlayer.getPlaybackState() == Player.STATE_IDLE) { simpleExoPlayer.retry(); } - return; + simpleExoPlayer.setPlayWhenReady(playWhenReady); + } else if (intent.getBooleanExtra(RESUME_PLAYBACK, false) && isPlaybackResumeEnabled() && !samePlayQueue) { @@ -351,7 +356,7 @@ public abstract class BasePlayer implements state -> { queue.setRecovery(queue.getIndex(), state.getProgressTime()); initPlayback(queue, repeatMode, playbackSpeed, playbackPitch, - playbackSkipSilence, true, isMuted); + playbackSkipSilence, playWhenReady, isMuted); }, error -> { if (DEBUG) { @@ -359,24 +364,22 @@ public abstract class BasePlayer implements } // In case any error we can start playback without history initPlayback(queue, repeatMode, playbackSpeed, playbackPitch, - playbackSkipSilence, true, isMuted); + playbackSkipSilence, playWhenReady, isMuted); }, () -> { // Completed but not found in history initPlayback(queue, repeatMode, playbackSpeed, playbackPitch, - playbackSkipSilence, true, isMuted); + playbackSkipSilence, playWhenReady, isMuted); } ); databaseUpdateReactor.add(stateLoader); - return; } + } else { + // Good to go... + // In a case of equal PlayQueues we can re-init old one but only when it is disposed + initPlayback(samePlayQueue ? playQueue : queue, repeatMode, playbackSpeed, + playbackPitch, playbackSkipSilence, playWhenReady, isMuted); } - // Good to go... - // In a case of equal PlayQueues we can re-init old one but only when it is disposed - initPlayback(samePlayQueue ? playQueue : queue, repeatMode, - playbackSpeed, playbackPitch, playbackSkipSilence, - !intent.getBooleanExtra(START_PAUSED, false), - isMuted); } private PlaybackParameters retrievePlaybackParametersFromPreferences() { diff --git a/app/src/main/java/org/schabi/newpipe/player/MainPlayer.java b/app/src/main/java/org/schabi/newpipe/player/MainPlayer.java index ea205bbdf..07ca7b339 100644 --- a/app/src/main/java/org/schabi/newpipe/player/MainPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/MainPlayer.java @@ -240,7 +240,7 @@ public final class MainPlayer extends Service { } public void removeViewFromParent() { - if (getView().getParent() != null) { + if (getView() != null && getView().getParent() != null) { if (playerImpl.getParentActivity() != null) { // This means view was added to fragment final ViewGroup parent = (ViewGroup) getView().getParent(); diff --git a/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java b/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java index fee189295..ad4c603cd 100644 --- a/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java +++ b/app/src/main/java/org/schabi/newpipe/player/ServicePlayerActivity.java @@ -27,9 +27,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; -import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; -import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.fragments.OnScrollBelowItemsListener; import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; @@ -42,9 +40,9 @@ import org.schabi.newpipe.player.playqueue.PlayQueueItem; import org.schabi.newpipe.player.playqueue.PlayQueueItemBuilder; import org.schabi.newpipe.player.playqueue.PlayQueueItemHolder; import org.schabi.newpipe.player.playqueue.PlayQueueItemTouchCallback; -import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.NavigationHelper; +import org.schabi.newpipe.util.PermissionHelper; import org.schabi.newpipe.util.ThemeHelper; import java.util.Collections; @@ -113,9 +111,8 @@ public abstract class ServicePlayerActivity extends AppCompatActivity public abstract int getPlayerOptionMenuResource(); - public abstract boolean onPlayerOptionSelected(MenuItem item); - public abstract void setupMenu(Menu m); + //////////////////////////////////////////////////////////////////////////// // Activity Lifecycle //////////////////////////////////////////////////////////////////////////// @@ -187,12 +184,22 @@ public abstract class ServicePlayerActivity extends AppCompatActivity return true; case R.id.action_switch_main: this.player.setRecovery(); - getApplicationContext().startActivity( - getSwitchIntent(MainActivity.class, MainPlayer.PlayerType.VIDEO) - .putExtra(BasePlayer.START_PAUSED, !this.player.isPlaying())); + NavigationHelper.playOnMainPlayer(this, player.getPlayQueue(), true); + return true; + case R.id.action_switch_popup: + if (PermissionHelper.isPopupEnabled(this)) { + this.player.setRecovery(); + NavigationHelper.playOnPopupPlayer(this, player.playQueue, true); + } else { + PermissionHelper.showPopupEnablementToast(this); + } + return true; + case R.id.action_switch_background: + this.player.setRecovery(); + NavigationHelper.playOnBackgroundPlayer(this, player.playQueue, true); return true; } - return onPlayerOptionSelected(item) || super.onOptionsItemSelected(item); + return super.onOptionsItemSelected(item); } @Override @@ -201,24 +208,6 @@ public abstract class ServicePlayerActivity extends AppCompatActivity unbind(); } - protected Intent getSwitchIntent(final Class clazz, final MainPlayer.PlayerType playerType) { - return NavigationHelper.getPlayerIntent(getApplicationContext(), clazz, - this.player.getPlayQueue(), this.player.getRepeatMode(), - this.player.getPlaybackSpeed(), this.player.getPlaybackPitch(), - this.player.getPlaybackSkipSilence(), - null, - true, - !this.player.isPlaying(), - this.player.isMuted()) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - .putExtra(Constants.KEY_LINK_TYPE, StreamingService.LinkType.STREAM) - .putExtra(Constants.KEY_URL, this.player.getVideoUrl()) - .putExtra(Constants.KEY_TITLE, this.player.getVideoTitle()) - .putExtra(Constants.KEY_SERVICE_ID, - this.player.getCurrentMetadata().getMetadata().getServiceId()) - .putExtra(VideoPlayer.PLAYER_TYPE, playerType); - } - //////////////////////////////////////////////////////////////////////////// // Service Connection //////////////////////////////////////////////////////////////////////////// @@ -368,8 +357,8 @@ public abstract class ServicePlayerActivity extends AppCompatActivity Menu.NONE, R.string.play_queue_stream_detail); detail.setOnMenuItemClickListener(menuItem -> { // playQueue is null since we don't want any queue change - NavigationHelper.openVideoDetail( - this, item.getServiceId(), item.getUrl(), item.getTitle(), null); + NavigationHelper.openVideoDetail(this, item.getServiceId(), item.getUrl(), + item.getTitle(), null, false); return true; }); diff --git a/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java b/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java index 765eb148b..fa016e158 100644 --- a/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java +++ b/app/src/main/java/org/schabi/newpipe/player/VideoPlayerImpl.java @@ -76,9 +76,7 @@ import com.google.android.exoplayer2.ui.SubtitleView; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.nostra13.universalimageloader.core.assist.FailReason; -import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; -import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.VideoStream; import org.schabi.newpipe.fragments.OnScrollBelowItemsListener; @@ -97,7 +95,6 @@ import org.schabi.newpipe.player.resolver.AudioPlaybackResolver; import org.schabi.newpipe.player.resolver.MediaSourceTag; import org.schabi.newpipe.player.resolver.VideoPlaybackResolver; import org.schabi.newpipe.util.AnimationUtils; -import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.KoreUtil; import org.schabi.newpipe.util.ListHelper; @@ -260,7 +257,12 @@ public class VideoPlayerImpl extends VideoPlayer onQueueClosed(); // Android TV: without it focus will frame the whole player playPauseButton.requestFocus(); - onPlay(); + + if (simpleExoPlayer.getPlayWhenReady()) { + onPlay(); + } else { + onPause(); + } } NavigationHelper.sendPlayerStartedEvent(service); } @@ -756,40 +758,6 @@ public class VideoPlayerImpl extends VideoPlayer setupScreenRotationButton(); } - public void switchFromPopupToMain() { - if (DEBUG) { - Log.d(TAG, "switchFromPopupToMain() called"); - } - if (!popupPlayerSelected() || simpleExoPlayer == null || getCurrentMetadata() == null) { - return; - } - - setRecovery(); - service.removeViewFromParent(); - final Intent intent = NavigationHelper.getPlayerIntent( - service, - MainActivity.class, - this.getPlayQueue(), - this.getRepeatMode(), - this.getPlaybackSpeed(), - this.getPlaybackPitch(), - this.getPlaybackSkipSilence(), - null, - true, - !isPlaying(), - isMuted() - ); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(Constants.KEY_SERVICE_ID, - getCurrentMetadata().getMetadata().getServiceId()); - intent.putExtra(Constants.KEY_LINK_TYPE, StreamingService.LinkType.STREAM); - intent.putExtra(Constants.KEY_URL, getVideoUrl()); - intent.putExtra(Constants.KEY_TITLE, getVideoTitle()); - intent.putExtra(VideoDetailFragment.KEY_SWITCHING_PLAYERS, true); - service.onDestroy(); - context.startActivity(intent); - } - @Override public void onClick(final View v) { super.onClick(v); @@ -817,7 +785,9 @@ public class VideoPlayerImpl extends VideoPlayer } else if (v.getId() == openInBrowser.getId()) { onOpenInBrowserClicked(); } else if (v.getId() == fullscreenButton.getId()) { - switchFromPopupToMain(); + setRecovery(); + NavigationHelper.playOnMainPlayer(context, getPlayQueue(), true); + return; } else if (v.getId() == screenRotationButton.getId()) { // Only if it's not a vertical video or vertical video but in landscape with locked // orientation a screen orientation can be changed automatically diff --git a/app/src/main/java/org/schabi/newpipe/player/event/BasePlayerGestureListener.kt b/app/src/main/java/org/schabi/newpipe/player/event/BasePlayerGestureListener.kt index dcc1bb128..681c1b9af 100644 --- a/app/src/main/java/org/schabi/newpipe/player/event/BasePlayerGestureListener.kt +++ b/app/src/main/java/org/schabi/newpipe/player/event/BasePlayerGestureListener.kt @@ -63,7 +63,7 @@ abstract class BasePlayerGestureListener( private var isMovingInPopup = false private var isResizing = false - private val tossFlingVelocity = PlayerHelper.getTossFlingVelocity(service) + private val tossFlingVelocity = PlayerHelper.getTossFlingVelocity() // [popup] initial coordinates and distance between fingers private var initPointerDistance = -1.0 @@ -104,9 +104,6 @@ abstract class BasePlayerGestureListener( } private fun onTouchInPopup(v: View, event: MotionEvent): Boolean { - if (playerImpl == null) { - return false - } playerImpl.gestureDetector.onTouchEvent(event) if (event.pointerCount == 2 && !isMovingInPopup && !isResizing) { if (DEBUG) { diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.java b/app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.java index a931c46bd..ffe19599d 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.java @@ -164,7 +164,7 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, An @Override public void onAudioSessionId(final EventTime eventTime, final int audioSessionId) { - if (!PlayerHelper.isUsingDSP(context)) { + if (!PlayerHelper.isUsingDSP()) { return; } diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java index 4b52aa27d..cdd07ba1c 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java @@ -295,7 +295,7 @@ public final class PlayerHelper { return 60000; } - public static TrackSelection.Factory getQualitySelector(@NonNull final Context context) { + public static TrackSelection.Factory getQualitySelector() { return new AdaptiveTrackSelection.Factory( 1000, AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS, @@ -303,11 +303,11 @@ public final class PlayerHelper { AdaptiveTrackSelection.DEFAULT_BANDWIDTH_FRACTION); } - public static boolean isUsingDSP(@NonNull final Context context) { + public static boolean isUsingDSP() { return true; } - public static int getTossFlingVelocity(@NonNull final Context context) { + public static int getTossFlingVelocity() { return 2500; } diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java index 6d0f5fff7..5764b2b94 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java @@ -49,6 +49,13 @@ public final class PlayerHolder { return player.getPlayerType(); } + public static boolean isPlaying() { + if (player == null) { + return false; + } + return player.isPlaying(); + } + public static void setListener(final PlayerServiceExtendedEventListener newListener) { listener = newListener; // Force reload data from service diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItem.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItem.java index 74aef07fa..79efc03ae 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItem.java +++ b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItem.java @@ -64,6 +64,20 @@ public class PlayQueueItem implements Serializable { this.recoveryPosition = RECOVERY_UNSET; } + @Override + public boolean equals(final Object o) { + if (o instanceof PlayQueueItem) { + return url.equals(((PlayQueueItem) o).url); + } else { + return false; + } + } + + @Override + public int hashCode() { + return url.hashCode(); + } + @NonNull public String getTitle() { return title; diff --git a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java index a96730552..3c791d44d 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java @@ -37,7 +37,6 @@ import org.schabi.newpipe.extractor.stream.VideoStream; import org.schabi.newpipe.fragments.MainFragment; import org.schabi.newpipe.fragments.detail.VideoDetailFragment; import org.schabi.newpipe.fragments.list.channel.ChannelFragment; -import org.schabi.newpipe.fragments.list.comments.CommentsFragment; import org.schabi.newpipe.fragments.list.kiosk.KioskFragment; import org.schabi.newpipe.fragments.list.playlist.PlaylistFragment; import org.schabi.newpipe.fragments.list.search.SearchFragment; @@ -73,7 +72,6 @@ public final class NavigationHelper { public static Intent getPlayerIntent(@NonNull final Context context, @NonNull final Class targetClazz, @Nullable final PlayQueue playQueue, - @Nullable final String quality, final boolean resumePlayback) { final Intent intent = new Intent(context, targetClazz); @@ -83,9 +81,6 @@ public final class NavigationHelper { intent.putExtra(VideoPlayer.PLAY_QUEUE_KEY, cacheKey); } } - if (quality != null) { - intent.putExtra(VideoPlayer.PLAYBACK_QUALITY, quality); - } intent.putExtra(VideoPlayer.RESUME_PLAYBACK, resumePlayback); intent.putExtra(VideoPlayer.PLAYER_TYPE, VideoPlayer.PLAYER_TYPE_VIDEO); @@ -96,8 +91,10 @@ public final class NavigationHelper { public static Intent getPlayerIntent(@NonNull final Context context, @NonNull final Class targetClazz, @Nullable final PlayQueue playQueue, - final boolean resumePlayback) { - return getPlayerIntent(context, targetClazz, playQueue, null, resumePlayback); + final boolean resumePlayback, + final boolean playWhenReady) { + return getPlayerIntent(context, targetClazz, playQueue, resumePlayback) + .putExtra(BasePlayer.PLAY_WHEN_READY, playWhenReady); } @NonNull @@ -111,24 +108,6 @@ public final class NavigationHelper { .putExtra(BasePlayer.SELECT_ON_APPEND, selectOnAppend); } - @NonNull - public static Intent getPlayerIntent(@NonNull final Context context, - @NonNull final Class targetClazz, - @Nullable final PlayQueue playQueue, - final int repeatMode, - final float playbackSpeed, - final float playbackPitch, - final boolean playbackSkipSilence, - @Nullable final String playbackQuality, - final boolean resumePlayback, - final boolean startPaused, - final boolean isMuted) { - return getPlayerIntent(context, targetClazz, playQueue, playbackQuality, resumePlayback) - .putExtra(BasePlayer.REPEAT_MODE, repeatMode) - .putExtra(BasePlayer.START_PAUSED, startPaused) - .putExtra(BasePlayer.IS_MUTED, isMuted); - } - public static void playOnMainPlayer(final AppCompatActivity activity, @NonNull final PlayQueue playQueue) { final PlayQueueItem item = playQueue.getItem(); @@ -138,10 +117,12 @@ public final class NavigationHelper { } public static void playOnMainPlayer(final Context context, - @NonNull final PlayQueue playQueue) { + @NonNull final PlayQueue playQueue, + final boolean switchingPlayers) { final PlayQueueItem item = playQueue.getItem(); assert item != null; - openVideoDetail(context, item.getServiceId(), item.getUrl(), item.getTitle(), playQueue); + openVideoDetail(context, + item.getServiceId(), item.getUrl(), item.getTitle(), playQueue, switchingPlayers); } public static void playOnPopupPlayer(final Context context, @@ -370,7 +351,7 @@ public final class NavigationHelper { autoPlay = PlayerHelper.isAutoplayAllowedByUser(context); } else if (switchingPlayers) { // switching player to main player - autoPlay = true; + autoPlay = PlayerHolder.isPlaying(); // keep play/pause state } else if (playerType == MainPlayer.PlayerType.VIDEO) { // opening new stream while already playing in main player autoPlay = PlayerHelper.isAutoplayAllowedByUser(context); @@ -416,16 +397,6 @@ public final class NavigationHelper { .commit(); } - public static void openCommentsFragment(final FragmentManager fragmentManager, - final int serviceId, final String url, - @NonNull final String name) { - fragmentManager.beginTransaction() - .setCustomAnimations(R.anim.switch_service_in, R.anim.switch_service_out) - .replace(R.id.fragment_holder, CommentsFragment.getInstance(serviceId, url, name)) - .addToBackStack(null) - .commit(); - } - public static void openPlaylistFragment(final FragmentManager fragmentManager, final int serviceId, final String url, @NonNull final String name) { @@ -506,23 +477,17 @@ public final class NavigationHelper { context.startActivity(mIntent); } - public static void openChannel(final Context context, final int serviceId, - final String url, @NonNull final String name) { - final Intent openIntent = getOpenIntent(context, url, serviceId, - StreamingService.LinkType.CHANNEL); - openIntent.putExtra(Constants.KEY_TITLE, name); - context.startActivity(openIntent); - } - public static void openVideoDetail(final Context context, final int serviceId, final String url, @NonNull final String title, - @Nullable final PlayQueue playQueue) { + @Nullable final PlayQueue playQueue, + final boolean switchingPlayers) { final Intent intent = getOpenIntent(context, url, serviceId, StreamingService.LinkType.STREAM); intent.putExtra(Constants.KEY_TITLE, title); + intent.putExtra(VideoDetailFragment.KEY_SWITCHING_PLAYERS, switchingPlayers); if (playQueue != null) { final String cacheKey = SerializedCache.getInstance().put(playQueue, PlayQueue.class); From 00a178f7d3b34d57e23dc4047c150c22d2e84fa3 Mon Sep 17 00:00:00 2001 From: Stypox Date: Sun, 1 Nov 2020 21:25:31 +0100 Subject: [PATCH 4/7] Fix tapping on video thumbnail does nothing --- .../schabi/newpipe/fragments/detail/VideoDetailFragment.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index 1324d6832..92032986d 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -289,6 +289,7 @@ public final class VideoDetailFragment || (currentInfo != null && isAutoplayEnabled() && player.getParentActivity() == null)) { + autoPlayEnabled = true; // forcefully start playing openVideoPlayer(); } } @@ -521,6 +522,7 @@ public final class VideoDetailFragment } break; case R.id.detail_thumbnail_root_layout: + autoPlayEnabled = true; // forcefully start playing openVideoPlayer(); break; case R.id.detail_title_root_layout: @@ -537,6 +539,7 @@ public final class VideoDetailFragment player.hideControls(0, 0); showSystemUi(); } else { + autoPlayEnabled = true; // forcefully start playing openVideoPlayer(); } From 5a87cfc25df880a579d943299a20d00e6fbdc7e3 Mon Sep 17 00:00:00 2001 From: Stypox Date: Sun, 1 Nov 2020 21:45:39 +0100 Subject: [PATCH 5/7] Open mini player if player running on app open --- .../java/org/schabi/newpipe/MainActivity.java | 60 ++++++++++--------- .../newpipe/player/helper/PlayerHolder.java | 4 ++ 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index 1d911c944..84235d4fb 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -69,6 +69,7 @@ import org.schabi.newpipe.fragments.detail.VideoDetailFragment; import org.schabi.newpipe.fragments.list.search.SearchFragment; import org.schabi.newpipe.player.VideoPlayer; import org.schabi.newpipe.player.event.OnKeyDownListener; +import org.schabi.newpipe.player.helper.PlayerHolder; import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.report.ErrorActivity; import org.schabi.newpipe.util.Constants; @@ -152,7 +153,7 @@ public class MainActivity extends AppCompatActivity { if (DeviceUtils.isTv(this)) { FocusOverlayView.setupFocusObserver(this); } - setupBroadcastReceiver(); + openMiniPlayerUponPlayerStarted(); } private void setupDrawer() throws Exception { @@ -809,34 +810,39 @@ public class MainActivity extends AppCompatActivity { } } - private void setupBroadcastReceiver() { - broadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(final Context context, final Intent intent) { - if (intent.getAction().equals(VideoDetailFragment.ACTION_PLAYER_STARTED)) { - final Fragment fragmentPlayer = getSupportFragmentManager() - .findFragmentById(R.id.fragment_player_holder); - if (fragmentPlayer == null) { - /* - * We still don't have a fragment attached to the activity. - * It can happen when a user started popup or background players - * without opening a stream inside the fragment. - * Adding it in a collapsed state (only mini player will be visible) - * */ - NavigationHelper.showMiniPlayer(getSupportFragmentManager()); + private void openMiniPlayerIfMissing() { + final Fragment fragmentPlayer = getSupportFragmentManager() + .findFragmentById(R.id.fragment_player_holder); + if (fragmentPlayer == null) { + // We still don't have a fragment attached to the activity. It can happen when a user + // started popup or background players without opening a stream inside the fragment. + // Adding it in a collapsed state (only mini player will be visible). + NavigationHelper.showMiniPlayer(getSupportFragmentManager()); + } + } + + private void openMiniPlayerUponPlayerStarted() { + if (PlayerHolder.isPlayerOpen()) { + // no need for a broadcast receiver if the player is already open + openMiniPlayerIfMissing(); + } else { + // listen for player intents being sent around + broadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(final Context context, final Intent intent) { + if (intent.getAction().equals(VideoDetailFragment.ACTION_PLAYER_STARTED)) { + 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. + unregisterReceiver(broadcastReceiver); + broadcastReceiver = null; } - /* - * At this point the player is added 100%, we can unregister. - * Other actions are useless since the fragment will not be removed after that - * */ - unregisterReceiver(broadcastReceiver); - broadcastReceiver = null; } - } - }; - final IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(VideoDetailFragment.ACTION_PLAYER_STARTED); - registerReceiver(broadcastReceiver, intentFilter); + }; + final IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(VideoDetailFragment.ACTION_PLAYER_STARTED); + registerReceiver(broadcastReceiver, intentFilter); + } } private boolean bottomSheetHiddenOrCollapsed() { diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java index 5764b2b94..854e3eb2b 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java @@ -56,6 +56,10 @@ public final class PlayerHolder { return player.isPlaying(); } + public static boolean isPlayerOpen() { + return player != null; + } + public static void setListener(final PlayerServiceExtendedEventListener newListener) { listener = newListener; // Force reload data from service From 1b47a1a994e009a298f12ad6570d2565cb49b7dd Mon Sep 17 00:00:00 2001 From: Stypox Date: Mon, 2 Nov 2020 18:06:14 +0100 Subject: [PATCH 6/7] Fix switching to main player when MainActivity is closed --- .../java/org/schabi/newpipe/MainActivity.java | 15 ++++++++++++--- .../fragments/detail/VideoDetailFragment.java | 4 +++- .../org/schabi/newpipe/player/MainPlayer.java | 2 ++ .../org/schabi/newpipe/util/NavigationHelper.java | 1 + 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index 84235d4fb..9bcbe4ff1 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -88,6 +88,7 @@ import org.schabi.newpipe.views.FocusOverlayView; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; @@ -822,15 +823,23 @@ public class MainActivity extends AppCompatActivity { } private void openMiniPlayerUponPlayerStarted() { + if (getIntent().getSerializableExtra(Constants.KEY_LINK_TYPE) + == StreamingService.LinkType.STREAM) { + // handleIntent() already takes care of opening video detail fragment + // due to an intent containing a STREAM link + return; + } + if (PlayerHolder.isPlayerOpen()) { - // no need for a broadcast receiver if the player is already open + // if the player is already open, no need for a broadcast receiver openMiniPlayerIfMissing(); } else { - // listen for player intents being sent around + // listen for player start intent being sent around broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(final Context context, final Intent intent) { - if (intent.getAction().equals(VideoDetailFragment.ACTION_PLAYER_STARTED)) { + if (Objects.equals(intent.getAction(), + VideoDetailFragment.ACTION_PLAYER_STARTED)) { 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. diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index 92032986d..3296f5bf8 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -1111,7 +1111,9 @@ public final class VideoDetailFragment // Video view can have elements visible from popup, // We hide it here but once it ready the view will be shown in handleIntent() - playerService.getView().setVisibility(View.GONE); + if (playerService.getView() != null) { + playerService.getView().setVisibility(View.GONE); + } addVideoPlayerView(); final Intent playerIntent = NavigationHelper diff --git a/app/src/main/java/org/schabi/newpipe/player/MainPlayer.java b/app/src/main/java/org/schabi/newpipe/player/MainPlayer.java index 07ca7b339..63f6a400e 100644 --- a/app/src/main/java/org/schabi/newpipe/player/MainPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/MainPlayer.java @@ -30,6 +30,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; +import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import org.schabi.newpipe.R; @@ -231,6 +232,7 @@ public final class MainPlayer extends Service { return metrics.heightPixels < metrics.widthPixels; } + @Nullable public View getView() { if (playerImpl == null) { return null; diff --git a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java index 3c791d44d..b45a1e7b9 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java @@ -486,6 +486,7 @@ public final class NavigationHelper { final Intent intent = getOpenIntent(context, url, serviceId, StreamingService.LinkType.STREAM); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra(Constants.KEY_TITLE, title); intent.putExtra(VideoDetailFragment.KEY_SWITCHING_PLAYERS, switchingPlayers); From 617ee0afc0093bc0f075bd4a11b5762c7df19b79 Mon Sep 17 00:00:00 2001 From: Stypox Date: Wed, 4 Nov 2020 16:10:25 +0100 Subject: [PATCH 7/7] Fix brightness and volume scroll swapped --- .../schabi/newpipe/player/event/PlayerGestureListener.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java b/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java index a23d5d3ff..fdea20775 100644 --- a/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java +++ b/app/src/main/java/org/schabi/newpipe/player/event/PlayerGestureListener.java @@ -111,10 +111,10 @@ public class PlayerGestureListener } if (playerType == MainPlayer.PlayerType.VIDEO) { if (portion == DisplayPortion.LEFT_HALF) { - onScrollMainVolume(distanceX, distanceY); + onScrollMainBrightness(distanceX, distanceY); } else /* DisplayPortion.RIGHT_HALF */ { - onScrollMainBrightness(distanceX, distanceY); + onScrollMainVolume(distanceX, distanceY); } } else /* MainPlayer.PlayerType.POPUP */ {