From 9685456ee441d4e5b461d6a20be860a056a18326 Mon Sep 17 00:00:00 2001 From: John Zhen M Date: Thu, 12 Oct 2017 17:02:07 -0700 Subject: [PATCH] -Added new intents to append streams to current player. -Added long clicks for popup and background player buttons on details fragment for append intents. -Removed restrictions for preventing UI to show up when player is buffering. -Fixed icons for all repeat modes. -Added Progress bar to background activity when player is in not ready state. -Fixed Track Selection when switching between video and audio only on video players. -Fixed video player to enable tunnelling only after sdk > 21. -Fixed activity exception from restarting after service is shutdown on earlier sdk versions. --- .../fragments/detail/VideoDetailFragment.java | 45 +++++-- .../newpipe/player/BackgroundPlayer.java | 68 ++++------ .../player/BackgroundPlayerActivity.java | 117 +++++++++++------- .../org/schabi/newpipe/player/BasePlayer.java | 8 ++ .../newpipe/player/MainVideoPlayer.java | 57 ++++----- .../newpipe/player/PopupVideoPlayer.java | 61 ++++----- .../schabi/newpipe/player/VideoPlayer.java | 21 ++-- .../schabi/newpipe/util/NavigationHelper.java | 8 ++ .../res/layout/activity_background_player.xml | 17 +++ .../main/res/layout/activity_main_player.xml | 2 +- 10 files changed, 230 insertions(+), 174 deletions(-) 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 939933afc..1872383e7 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 @@ -92,7 +92,7 @@ import io.reactivex.schedulers.Schedulers; import static org.schabi.newpipe.util.AnimationUtils.animateView; -public class VideoDetailFragment extends BaseStateFragment implements BackPressable, SharedPreferences.OnSharedPreferenceChangeListener, View.OnClickListener { +public class VideoDetailFragment extends BaseStateFragment implements BackPressable, SharedPreferences.OnSharedPreferenceChangeListener, View.OnClickListener, View.OnLongClickListener { public static final String AUTO_PLAY = "auto_play"; // Amount of videos to show on start @@ -320,10 +320,10 @@ public class VideoDetailFragment extends BaseStateFragment implement switch (v.getId()) { case R.id.detail_controls_background: - openBackgroundPlayer(); + openBackgroundPlayer(false); break; case R.id.detail_controls_popup: - openPopupPlayer(); + openPopupPlayer(false); break; case R.id.detail_uploader_root_layout: if (currentInfo.uploader_url == null || currentInfo.uploader_url.isEmpty()) { @@ -344,6 +344,22 @@ public class VideoDetailFragment extends BaseStateFragment implement } } + @Override + public boolean onLongClick(View v) { + if (isLoading.get() || currentInfo == null) return false; + + switch (v.getId()) { + case R.id.detail_controls_background: + openBackgroundPlayer(true); + break; + case R.id.detail_controls_popup: + openPopupPlayer(true); + break; + } + + return true; + } + private void toggleTitleAndDescription() { if (videoDescriptionRootLayout.getVisibility() == View.VISIBLE) { videoTitleTextView.setMaxLines(1); @@ -448,6 +464,11 @@ public class VideoDetailFragment extends BaseStateFragment implement detailControlsBackground.setOnClickListener(this); detailControlsPopup.setOnClickListener(this); relatedStreamExpandButton.setOnClickListener(this); + + detailControlsBackground.setLongClickable(true); + detailControlsPopup.setLongClickable(true); + detailControlsBackground.setOnLongClickListener(this); + detailControlsPopup.setOnLongClickListener(this); } private void initThumbnailViews(StreamInfo info) { @@ -716,7 +737,7 @@ public class VideoDetailFragment extends BaseStateFragment implement // Play Utils //////////////////////////////////////////////////////////////////////////*/ - private void openBackgroundPlayer() { + private void openBackgroundPlayer(final boolean append) { AudioStream audioStream = currentInfo.audio_streams.get(ListHelper.getDefaultAudioFormat(activity, currentInfo.audio_streams)); if (activity instanceof HistoryListener) { @@ -727,7 +748,7 @@ public class VideoDetailFragment extends BaseStateFragment implement .getBoolean(activity.getString(R.string.use_external_audio_player_key), false); if (!useExternalAudioPlayer && android.os.Build.VERSION.SDK_INT >= 16) { - openNormalBackgroundPlayer(); + openNormalBackgroundPlayer(append); } else { openExternalBackgroundPlayer(audioStream); } @@ -742,7 +763,7 @@ public class VideoDetailFragment extends BaseStateFragment implement } } - private void openPopupPlayer() { + private void openPopupPlayer(final boolean append) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !PermissionHelper.checkSystemAlertWindowPermission(activity)) { Toast toast = Toast.makeText(activity, R.string.msg_popup_permission, Toast.LENGTH_LONG); TextView messageView = toast.getView().findViewById(android.R.id.message); @@ -759,7 +780,13 @@ public class VideoDetailFragment extends BaseStateFragment implement final PlayQueue playQueue = new SinglePlayQueue(currentInfo); final VideoStream candidate = sortedStreamVideosList.get(actionBarHandler.getSelectedVideoStream()); - final Intent intent = NavigationHelper.getPlayerIntent(activity, PopupVideoPlayer.class, playQueue, resolutionOf(candidate.resolution)); + + final Intent intent; + if (append) { + intent = NavigationHelper.getPlayerIntent(activity, PopupVideoPlayer.class, playQueue, true); + } else { + intent = NavigationHelper.getPlayerIntent(activity, PopupVideoPlayer.class, playQueue, resolutionOf(candidate.resolution)); + } activity.startService(intent); } @@ -778,9 +805,9 @@ public class VideoDetailFragment extends BaseStateFragment implement } - private void openNormalBackgroundPlayer() { + private void openNormalBackgroundPlayer(final boolean append) { final PlayQueue playQueue = new SinglePlayQueue(currentInfo); - activity.startService(NavigationHelper.getPlayerIntent(activity, BackgroundPlayer.class, playQueue)); + activity.startService(NavigationHelper.getPlayerIntent(activity, BackgroundPlayer.class, playQueue, append)); Toast.makeText(activity, R.string.background_player_playing_toast, Toast.LENGTH_SHORT).show(); } 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 e39035013..5eacb5d05 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayer.java @@ -44,14 +44,11 @@ import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.source.MediaSource; import org.schabi.newpipe.BuildConfig; -import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; import org.schabi.newpipe.extractor.MediaFormat; -import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.stream.AudioStream; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.playlist.PlayQueueItem; -import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.ListHelper; import org.schabi.newpipe.util.ThemeHelper; @@ -108,6 +105,7 @@ public final class BackgroundPlayer extends Service { private RemoteViews notRemoteView; private RemoteViews bigNotRemoteView; private final String setAlphaMethodName = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) ? "setImageAlpha" : "setAlpha"; + private final String setImageResourceMethodName = "setImageResource"; /*////////////////////////////////////////////////////////////////////////// // Service's LifeCycle @@ -137,12 +135,7 @@ public final class BackgroundPlayer extends Service { @Override public void onDestroy() { if (DEBUG) Log.d(TAG, "destroy() called"); - releaseWifiAndCpu(); - stopForeground(true); - - if (basePlayerImpl != null) basePlayerImpl.destroy(); - basePlayerImpl = null; - mBinder = null; + onClose(); } @Override @@ -156,18 +149,22 @@ public final class BackgroundPlayer extends Service { public void openControl(final Context context) { final Intent intent = new Intent(context, BackgroundPlayerActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); } private void onClose() { - if (basePlayerImpl != null) { - basePlayerImpl.stopActivityBinding(); - basePlayerImpl.destroyPlayer(); - } - stopForeground(true); releaseWifiAndCpu(); + + if (basePlayerImpl != null) { + basePlayerImpl.stopActivityBinding(); + basePlayerImpl.destroy(); + } + + basePlayerImpl = null; + mBinder = null; stopSelf(); } @@ -222,18 +219,7 @@ public final class BackgroundPlayer extends Service { remoteViews.setOnClickPendingIntent(R.id.notificationFForward, PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_FAST_FORWARD), PendingIntent.FLAG_UPDATE_CURRENT)); - switch (basePlayerImpl.simpleExoPlayer.getRepeatMode()) { - case Player.REPEAT_MODE_OFF: - remoteViews.setInt(R.id.notificationRepeat, setAlphaMethodName, 77); - break; - case Player.REPEAT_MODE_ONE: - // todo change image - remoteViews.setInt(R.id.notificationRepeat, setAlphaMethodName, 168); - break; - case Player.REPEAT_MODE_ALL: - remoteViews.setInt(R.id.notificationRepeat, setAlphaMethodName, 255); - break; - } + setRepeatModeIcon(remoteViews, basePlayerImpl.simpleExoPlayer.getRepeatMode()); } /** @@ -285,6 +271,19 @@ public final class BackgroundPlayer extends Service { wifiLock = null; } + private void setRepeatModeIcon(final RemoteViews remoteViews, final int repeatMode) { + switch (repeatMode) { + case Player.REPEAT_MODE_OFF: + remoteViews.setInt(R.id.notificationRepeat, setImageResourceMethodName, R.drawable.exo_controls_repeat_off); + break; + case Player.REPEAT_MODE_ONE: + remoteViews.setInt(R.id.notificationRepeat, setImageResourceMethodName, R.drawable.exo_controls_repeat_one); + break; + case Player.REPEAT_MODE_ALL: + remoteViews.setInt(R.id.notificationRepeat, setImageResourceMethodName, R.drawable.exo_controls_repeat_all); + break; + } + } ////////////////////////////////////////////////////////////////////////// protected class BasePlayerImpl extends BasePlayer { @@ -424,21 +423,8 @@ public final class BackgroundPlayer extends Service { @Override public void onRepeatModeChanged(int i) { - int opacity = 255; - switch (simpleExoPlayer.getRepeatMode()) { - case Player.REPEAT_MODE_OFF: - opacity = 77; - break; - case Player.REPEAT_MODE_ONE: - // todo change image - opacity = 168; - break; - case Player.REPEAT_MODE_ALL: - opacity = 255; - break; - } - if (notRemoteView != null) notRemoteView.setInt(R.id.notificationRepeat, setAlphaMethodName, opacity); - if (bigNotRemoteView != null) bigNotRemoteView.setInt(R.id.notificationRepeat, setAlphaMethodName, opacity); + setRepeatModeIcon(notRemoteView, i); + setRepeatModeIcon(bigNotRemoteView, i); updateNotification(-1); updatePlayback(); } 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 ffa1e68bd..62abe81b5 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayerActivity.java +++ b/app/src/main/java/org/schabi/newpipe/player/BackgroundPlayerActivity.java @@ -18,6 +18,7 @@ import android.view.MenuItem; import android.view.View; import android.widget.ImageButton; import android.widget.PopupMenu; +import android.widget.ProgressBar; import android.widget.SeekBar; import android.widget.TextView; @@ -70,6 +71,7 @@ public class BackgroundPlayerActivity extends AppCompatActivity private ImageButton playPauseButton; private ImageButton forwardButton; private ImageButton shuffleButton; + private ProgressBar progressBar; private TextView playbackSpeedButton; private PopupMenu playbackSpeedPopupMenu; @@ -164,7 +166,7 @@ public class BackgroundPlayerActivity extends AppCompatActivity Log.d(TAG, "Background player service is connected"); final BackgroundPlayer.LocalBinder mLocalBinder = (BackgroundPlayer.LocalBinder) service; player = mLocalBinder.getBackgroundPlayerInstance(); - if (player == null) { + if (player == null || player.playQueue == null || player.playQueueAdapter == null || player.simpleExoPlayer == null) { unbind(); } else { buildComponents(); @@ -219,6 +221,7 @@ public class BackgroundPlayerActivity extends AppCompatActivity shuffleButton = rootView.findViewById(R.id.control_shuffle); playbackSpeedButton = rootView.findViewById(R.id.control_playback_speed); playbackPitchButton = rootView.findViewById(R.id.control_playback_pitch); + progressBar = rootView.findViewById(R.id.control_progress_bar); repeatButton.setOnClickListener(this); backwardButton.setOnClickListener(this); @@ -431,52 +434,9 @@ public class BackgroundPlayerActivity extends AppCompatActivity @Override public void onPlaybackUpdate(int state, int repeatMode, boolean shuffled, PlaybackParameters parameters) { - switch (state) { - case BasePlayer.STATE_PAUSED: - playPauseButton.setImageResource(R.drawable.ic_play_arrow_white); - break; - case BasePlayer.STATE_PLAYING: - playPauseButton.setImageResource(R.drawable.ic_pause_white); - break; - case BasePlayer.STATE_COMPLETED: - playPauseButton.setImageResource(R.drawable.ic_replay_white); - break; - default: - break; - } - - int repeatAlpha = 255; - switch (repeatMode) { - case Player.REPEAT_MODE_OFF: - repeatAlpha = 77; - break; - case Player.REPEAT_MODE_ONE: - // todo change image - repeatAlpha = 168; - break; - case Player.REPEAT_MODE_ALL: - repeatAlpha = 255; - break; - } - - int shuffleAlpha = 255; - if (!shuffled) { - shuffleAlpha = 77; - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - repeatButton.setImageAlpha(repeatAlpha); - shuffleButton.setImageAlpha(shuffleAlpha); - } else { - repeatButton.setAlpha(repeatAlpha); - shuffleButton.setAlpha(shuffleAlpha); - } - - if (parameters != null) { - playbackSpeedButton.setText(player.formatSpeed(parameters.speed)); - playbackPitchButton.setText(player.formatPitch(parameters.pitch)); - } - + onStateChanged(state); + onPlayModeChanged(repeatMode, shuffled); + onPlaybackParameterChanged(parameters); scrollToSelected(); } @@ -509,4 +469,67 @@ public class BackgroundPlayerActivity extends AppCompatActivity public void onServiceStopped() { unbind(); } + + //////////////////////////////////////////////////////////////////////////// + // Binding Service Helper + //////////////////////////////////////////////////////////////////////////// + + private void onStateChanged(final int state) { + switch (state) { + case BasePlayer.STATE_PAUSED: + playPauseButton.setImageResource(R.drawable.ic_play_arrow_white); + break; + case BasePlayer.STATE_PLAYING: + playPauseButton.setImageResource(R.drawable.ic_pause_white); + break; + case BasePlayer.STATE_COMPLETED: + playPauseButton.setImageResource(R.drawable.ic_replay_white); + break; + default: + break; + } + + switch (state) { + case BasePlayer.STATE_PAUSED: + case BasePlayer.STATE_PLAYING: + case BasePlayer.STATE_COMPLETED: + playPauseButton.setClickable(true); + playPauseButton.setVisibility(View.VISIBLE); + progressBar.setVisibility(View.GONE); + break; + default: + playPauseButton.setClickable(false); + playPauseButton.setVisibility(View.INVISIBLE); + progressBar.setVisibility(View.VISIBLE); + break; + } + } + + private void onPlayModeChanged(final int repeatMode, final boolean shuffled) { + switch (repeatMode) { + case Player.REPEAT_MODE_OFF: + repeatButton.setImageResource(R.drawable.exo_controls_repeat_off); + break; + case Player.REPEAT_MODE_ONE: + repeatButton.setImageResource(R.drawable.exo_controls_repeat_one); + break; + case Player.REPEAT_MODE_ALL: + repeatButton.setImageResource(R.drawable.exo_controls_repeat_all); + break; + } + + final int shuffleAlpha = shuffled ? 255 : 77; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + shuffleButton.setImageAlpha(shuffleAlpha); + } else { + shuffleButton.setAlpha(shuffleAlpha); + } + } + + private void onPlaybackParameterChanged(final PlaybackParameters parameters) { + if (parameters != null) { + playbackSpeedButton.setText(player.formatSpeed(parameters.speed)); + playbackPitchButton.setText(player.formatPitch(parameters.pitch)); + } + } } 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 3f1d86818..3bab31293 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java @@ -137,6 +137,7 @@ public abstract class BasePlayer implements Player.EventListener, public static final String PLAY_QUEUE = "play_queue"; public static final String RESTORE_QUEUE_INDEX = "restore_queue_index"; public static final String RESTORE_WINDOW_POS = "restore_window_pos"; + public static final String APPEND_ONLY = "append_only"; /*////////////////////////////////////////////////////////////////////////// // Playback @@ -260,6 +261,12 @@ public abstract class BasePlayer implements Player.EventListener, if (!(playQueueCandidate instanceof PlayQueue)) return; final PlayQueue queue = (PlayQueue) playQueueCandidate; + // Resolve append intents + if (intent.getBooleanExtra(APPEND_ONLY, false) && playQueue != null) { + playQueue.append(queue.getStreams()); + return; + } + // Resolve playback details if (intent.hasExtra(RESTORE_QUEUE_INDEX) && intent.hasExtra(START_POSITION)) { setRecovery( @@ -310,6 +317,7 @@ public abstract class BasePlayer implements Player.EventListener, public void destroyPlayer() { if (DEBUG) Log.d(TAG, "destroyPlayer() called"); if (simpleExoPlayer != null) { + simpleExoPlayer.removeListener(this); simpleExoPlayer.stop(); simpleExoPlayer.release(); } 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 2f30f4ec2..454eeed28 100644 --- a/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java @@ -189,6 +189,20 @@ public final class MainVideoPlayer extends Activity { : ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT); } + protected void setRepeatModeButton(final ImageButton imageButton, final int repeatMode) { + switch (repeatMode) { + case Player.REPEAT_MODE_OFF: + imageButton.setImageResource(R.drawable.exo_controls_repeat_off); + break; + case Player.REPEAT_MODE_ONE: + imageButton.setImageResource(R.drawable.exo_controls_repeat_one); + break; + case Player.REPEAT_MODE_ALL: + imageButton.setImageResource(R.drawable.exo_controls_repeat_all); + break; + } + } + /////////////////////////////////////////////////////////////////////////// @SuppressWarnings({"unused", "WeakerAccess"}) @@ -218,12 +232,6 @@ public final class MainVideoPlayer extends Activity { this.screenRotationButton = rootView.findViewById(R.id.screenRotationButton); this.playPauseButton = rootView.findViewById(R.id.playPauseButton); - // Due to a bug on lower API, lets set the alpha instead of using a drawable - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) repeatButton.setImageAlpha(77); - else { //noinspection deprecation - repeatButton.setAlpha(77); - } - getRootView().setKeepScreenOn(true); } @@ -241,6 +249,16 @@ public final class MainVideoPlayer extends Activity { screenRotationButton.setOnClickListener(this); } + /*////////////////////////////////////////////////////////////////////////// + // ExoPlayer Video Listener + //////////////////////////////////////////////////////////////////////////*/ + + @Override + public void onRepeatModeChanged(int i) { + super.onRepeatModeChanged(i); + setRepeatModeButton(repeatButton, simpleExoPlayer.getRepeatMode()); + } + /*////////////////////////////////////////////////////////////////////////// // Playback Listener //////////////////////////////////////////////////////////////////////////*/ @@ -289,31 +307,6 @@ public final class MainVideoPlayer extends Activity { finish(); } - @Override - @SuppressWarnings("deprecation") - public void onRepeatClicked() { - super.onRepeatClicked(); - if (DEBUG) Log.d(TAG, "onRepeatClicked() called"); - switch (simpleExoPlayer.getRepeatMode()) { - case Player.REPEAT_MODE_OFF: - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) repeatButton.setImageAlpha(77); - else repeatButton.setAlpha(77); - - break; - case Player.REPEAT_MODE_ONE: - // todo change image - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) repeatButton.setImageAlpha(168); - else repeatButton.setAlpha(168); - - break; - case Player.REPEAT_MODE_ALL: - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) repeatButton.setImageAlpha(255); - else repeatButton.setAlpha(255); - - break; - } - } - @Override public void onClick(View v) { super.onClick(v); @@ -509,7 +502,7 @@ public final class MainVideoPlayer extends Activity { @Override public boolean onSingleTapConfirmed(MotionEvent e) { if (DEBUG) Log.d(TAG, "onSingleTapConfirmed() called with: e = [" + e + "]"); - if (playerImpl.getCurrentState() != BasePlayer.STATE_PLAYING) return true; + if (playerImpl.getCurrentState() == BasePlayer.STATE_BLOCKED) return true; if (playerImpl.isControlsVisible()) playerImpl.hideControls(150, 0); else { diff --git a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java index 1437986e2..270b7e5b8 100644 --- a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java @@ -111,7 +111,8 @@ public final class PopupVideoPlayer extends Service { private float minimumWidth, minimumHeight; private float maximumWidth, maximumHeight; - private final String setAlphaMethodName = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) ? "setImageAlpha" : "setAlpha"; + private final String setImageResourceMethodName = "setImageResource"; + private NotificationManager notificationManager; private NotificationCompat.Builder notBuilder; private RemoteViews notRemoteView; @@ -255,18 +256,7 @@ public final class PopupVideoPlayer extends Service { notRemoteView.setOnClickPendingIntent(R.id.notificationRepeat, PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_REPEAT), PendingIntent.FLAG_UPDATE_CURRENT)); - switch (playerImpl.simpleExoPlayer.getRepeatMode()) { - case Player.REPEAT_MODE_OFF: - notRemoteView.setInt(R.id.notificationRepeat, setAlphaMethodName, 77); - break; - case Player.REPEAT_MODE_ONE: - //todo change image - notRemoteView.setInt(R.id.notificationRepeat, setAlphaMethodName, 168); - break; - case Player.REPEAT_MODE_ALL: - notRemoteView.setInt(R.id.notificationRepeat, setAlphaMethodName, 255); - break; - } + setRepeatModeRemote(notRemoteView, playerImpl.simpleExoPlayer.getRepeatMode()); return new NotificationCompat.Builder(this, getString(R.string.notification_channel_id)) .setOngoing(true) @@ -370,6 +360,20 @@ public final class PopupVideoPlayer extends Service { windowManager.updateViewLayout(playerImpl.getRootView(), windowLayoutParams); } + protected void setRepeatModeRemote(final RemoteViews remoteViews, final int repeatMode) { + switch (repeatMode) { + case Player.REPEAT_MODE_OFF: + remoteViews.setInt(R.id.notificationRepeat, setImageResourceMethodName, R.drawable.exo_controls_repeat_off); + break; + case Player.REPEAT_MODE_ONE: + remoteViews.setInt(R.id.notificationRepeat, setImageResourceMethodName, R.drawable.exo_controls_repeat_one); + break; + case Player.REPEAT_MODE_ALL: + remoteViews.setInt(R.id.notificationRepeat, setImageResourceMethodName, R.drawable.exo_controls_repeat_all); + break; + } + } + /////////////////////////////////////////////////////////////////////////// private class VideoPlayerImpl extends VideoPlayer { @@ -435,27 +439,6 @@ public final class PopupVideoPlayer extends Service { stopSelf(); } - @Override - public void onRepeatClicked() { - super.onRepeatClicked(); - switch (simpleExoPlayer.getRepeatMode()) { - case Player.REPEAT_MODE_OFF: - // Drawable didn't work on low API :/ - //notRemoteView.setImageViewResource(R.id.notificationRepeat, R.drawable.ic_repeat_disabled_white); - // Set the icon to 30% opacity - 255 (max) * .3 - notRemoteView.setInt(R.id.notificationRepeat, setAlphaMethodName, 77); - break; - case Player.REPEAT_MODE_ONE: - // todo change image - notRemoteView.setInt(R.id.notificationRepeat, setAlphaMethodName, 168); - break; - case Player.REPEAT_MODE_ALL: - notRemoteView.setInt(R.id.notificationRepeat, setAlphaMethodName, 255); - break; - } - updateNotification(-1); - } - @Override public void onDismiss(PopupMenu menu) { super.onDismiss(menu); @@ -482,6 +465,16 @@ public final class PopupVideoPlayer extends Service { hideControls(100, 0); } } + /*////////////////////////////////////////////////////////////////////////// + // ExoPlayer Video Listener + //////////////////////////////////////////////////////////////////////////*/ + + @Override + public void onRepeatModeChanged(int i) { + super.onRepeatModeChanged(i); + setRepeatModeRemote(notRemoteView, i); + updateNotification(-1); + } /*////////////////////////////////////////////////////////////////////////// // Playback Listener diff --git a/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java index 5d2ef1967..422567d00 100644 --- a/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java @@ -211,7 +211,9 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer. simpleExoPlayer.setVideoSurfaceView(surfaceView); simpleExoPlayer.addVideoListener(this); - trackSelector.setTunnelingAudioSessionId(C.generateAudioSessionIdV21(context)); + if (Build.VERSION.SDK_INT >= 21) { + trackSelector.setTunnelingAudioSessionId(C.generateAudioSessionIdV21(context)); + } } @Override @@ -286,6 +288,7 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer. qualityPopupMenu.setOnMenuItemClickListener(this); qualityPopupMenu.setOnDismissListener(this); + qualityTextView.setVisibility(View.VISIBLE); } private void buildPlaybackSpeedMenu() { @@ -409,12 +412,8 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer. public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) { super.onTracksChanged(trackGroups, trackSelections); - if (trackSelector.getCurrentMappedTrackInfo() == null) { - qualityTextView.setVisibility(View.GONE); - return; - } else { - qualityTextView.setVisibility(View.VISIBLE); - } + if (trackSelector.getCurrentMappedTrackInfo() == null) return; + qualityTextView.setVisibility(View.GONE); for (int t = 0; t < simpleExoPlayer.getRendererCount(); t++) { if (simpleExoPlayer.getRendererType(t) == C.TRACK_TYPE_VIDEO) { @@ -422,9 +421,11 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer. } } videoTrackGroups = trackSelector.getCurrentMappedTrackInfo().getTrackGroups(videoRendererIndex); - selectedVideoTrackGroup = trackSelections.get(videoRendererIndex).getTrackGroup(); - - buildQualityMenu(); + final TrackSelection trackSelection = trackSelections.get(videoRendererIndex); + if (trackSelection != null) { + selectedVideoTrackGroup = trackSelection.getTrackGroup(); + buildQualityMenu(); + } } @Override 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 03e18c98a..9e92c128e 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java @@ -57,6 +57,14 @@ public class NavigationHelper { .putExtra(VideoPlayer.PLAY_QUEUE, playQueue); } + public static Intent getPlayerIntent(final Context context, + final Class targetClazz, + final PlayQueue playQueue, + final boolean isAppending) { + return getPlayerIntent(context, targetClazz, playQueue) + .putExtra(BasePlayer.APPEND_ONLY, isAppending); + } + public static Intent getPlayerIntent(final Context context, final Class targetClazz, final PlayQueue playQueue, diff --git a/app/src/main/res/layout/activity_background_player.xml b/app/src/main/res/layout/activity_background_player.xml index f2efd7411..0a0f3bb96 100644 --- a/app/src/main/res/layout/activity_background_player.xml +++ b/app/src/main/res/layout/activity_background_player.xml @@ -183,6 +183,23 @@ android:src="@drawable/ic_pause_white" tools:ignore="ContentDescription"/> + +