-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.
This commit is contained in:
John Zhen M 2017-10-12 17:02:07 -07:00 committed by John Zhen Mo
parent 6a9e3ef639
commit 9685456ee4
10 changed files with 230 additions and 174 deletions

View File

@ -92,7 +92,7 @@ import io.reactivex.schedulers.Schedulers;
import static org.schabi.newpipe.util.AnimationUtils.animateView; import static org.schabi.newpipe.util.AnimationUtils.animateView;
public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implements BackPressable, SharedPreferences.OnSharedPreferenceChangeListener, View.OnClickListener { public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implements BackPressable, SharedPreferences.OnSharedPreferenceChangeListener, View.OnClickListener, View.OnLongClickListener {
public static final String AUTO_PLAY = "auto_play"; public static final String AUTO_PLAY = "auto_play";
// Amount of videos to show on start // Amount of videos to show on start
@ -320,10 +320,10 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
switch (v.getId()) { switch (v.getId()) {
case R.id.detail_controls_background: case R.id.detail_controls_background:
openBackgroundPlayer(); openBackgroundPlayer(false);
break; break;
case R.id.detail_controls_popup: case R.id.detail_controls_popup:
openPopupPlayer(); openPopupPlayer(false);
break; break;
case R.id.detail_uploader_root_layout: case R.id.detail_uploader_root_layout:
if (currentInfo.uploader_url == null || currentInfo.uploader_url.isEmpty()) { if (currentInfo.uploader_url == null || currentInfo.uploader_url.isEmpty()) {
@ -344,6 +344,22 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> 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() { private void toggleTitleAndDescription() {
if (videoDescriptionRootLayout.getVisibility() == View.VISIBLE) { if (videoDescriptionRootLayout.getVisibility() == View.VISIBLE) {
videoTitleTextView.setMaxLines(1); videoTitleTextView.setMaxLines(1);
@ -448,6 +464,11 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
detailControlsBackground.setOnClickListener(this); detailControlsBackground.setOnClickListener(this);
detailControlsPopup.setOnClickListener(this); detailControlsPopup.setOnClickListener(this);
relatedStreamExpandButton.setOnClickListener(this); relatedStreamExpandButton.setOnClickListener(this);
detailControlsBackground.setLongClickable(true);
detailControlsPopup.setLongClickable(true);
detailControlsBackground.setOnLongClickListener(this);
detailControlsPopup.setOnLongClickListener(this);
} }
private void initThumbnailViews(StreamInfo info) { private void initThumbnailViews(StreamInfo info) {
@ -716,7 +737,7 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
// Play Utils // Play Utils
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
private void openBackgroundPlayer() { private void openBackgroundPlayer(final boolean append) {
AudioStream audioStream = currentInfo.audio_streams.get(ListHelper.getDefaultAudioFormat(activity, currentInfo.audio_streams)); AudioStream audioStream = currentInfo.audio_streams.get(ListHelper.getDefaultAudioFormat(activity, currentInfo.audio_streams));
if (activity instanceof HistoryListener) { if (activity instanceof HistoryListener) {
@ -727,7 +748,7 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
.getBoolean(activity.getString(R.string.use_external_audio_player_key), false); .getBoolean(activity.getString(R.string.use_external_audio_player_key), false);
if (!useExternalAudioPlayer && android.os.Build.VERSION.SDK_INT >= 16) { if (!useExternalAudioPlayer && android.os.Build.VERSION.SDK_INT >= 16) {
openNormalBackgroundPlayer(); openNormalBackgroundPlayer(append);
} else { } else {
openExternalBackgroundPlayer(audioStream); openExternalBackgroundPlayer(audioStream);
} }
@ -742,7 +763,7 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
} }
} }
private void openPopupPlayer() { private void openPopupPlayer(final boolean append) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !PermissionHelper.checkSystemAlertWindowPermission(activity)) { 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); Toast toast = Toast.makeText(activity, R.string.msg_popup_permission, Toast.LENGTH_LONG);
TextView messageView = toast.getView().findViewById(android.R.id.message); TextView messageView = toast.getView().findViewById(android.R.id.message);
@ -759,7 +780,13 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
final PlayQueue playQueue = new SinglePlayQueue(currentInfo); final PlayQueue playQueue = new SinglePlayQueue(currentInfo);
final VideoStream candidate = sortedStreamVideosList.get(actionBarHandler.getSelectedVideoStream()); 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); activity.startService(intent);
} }
@ -778,9 +805,9 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
} }
private void openNormalBackgroundPlayer() { private void openNormalBackgroundPlayer(final boolean append) {
final PlayQueue playQueue = new SinglePlayQueue(currentInfo); 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(); Toast.makeText(activity, R.string.background_player_playing_toast, Toast.LENGTH_SHORT).show();
} }

View File

@ -44,14 +44,11 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource;
import org.schabi.newpipe.BuildConfig; import org.schabi.newpipe.BuildConfig;
import org.schabi.newpipe.MainActivity;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.MediaFormat; 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.AudioStream;
import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.playlist.PlayQueueItem; import org.schabi.newpipe.playlist.PlayQueueItem;
import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.ListHelper; import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.util.ThemeHelper;
@ -108,6 +105,7 @@ public final class BackgroundPlayer extends Service {
private RemoteViews notRemoteView; private RemoteViews notRemoteView;
private RemoteViews bigNotRemoteView; private RemoteViews bigNotRemoteView;
private final String setAlphaMethodName = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) ? "setImageAlpha" : "setAlpha"; private final String setAlphaMethodName = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) ? "setImageAlpha" : "setAlpha";
private final String setImageResourceMethodName = "setImageResource";
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// Service's LifeCycle // Service's LifeCycle
@ -137,12 +135,7 @@ public final class BackgroundPlayer extends Service {
@Override @Override
public void onDestroy() { public void onDestroy() {
if (DEBUG) Log.d(TAG, "destroy() called"); if (DEBUG) Log.d(TAG, "destroy() called");
releaseWifiAndCpu(); onClose();
stopForeground(true);
if (basePlayerImpl != null) basePlayerImpl.destroy();
basePlayerImpl = null;
mBinder = null;
} }
@Override @Override
@ -156,18 +149,22 @@ public final class BackgroundPlayer extends Service {
public void openControl(final Context context) { public void openControl(final Context context) {
final Intent intent = new Intent(context, BackgroundPlayerActivity.class); final Intent intent = new Intent(context, BackgroundPlayerActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent); context.startActivity(intent);
context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
} }
private void onClose() { private void onClose() {
if (basePlayerImpl != null) {
basePlayerImpl.stopActivityBinding();
basePlayerImpl.destroyPlayer();
}
stopForeground(true); stopForeground(true);
releaseWifiAndCpu(); releaseWifiAndCpu();
if (basePlayerImpl != null) {
basePlayerImpl.stopActivityBinding();
basePlayerImpl.destroy();
}
basePlayerImpl = null;
mBinder = null;
stopSelf(); stopSelf();
} }
@ -222,18 +219,7 @@ public final class BackgroundPlayer extends Service {
remoteViews.setOnClickPendingIntent(R.id.notificationFForward, remoteViews.setOnClickPendingIntent(R.id.notificationFForward,
PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_FAST_FORWARD), PendingIntent.FLAG_UPDATE_CURRENT)); PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_FAST_FORWARD), PendingIntent.FLAG_UPDATE_CURRENT));
switch (basePlayerImpl.simpleExoPlayer.getRepeatMode()) { setRepeatModeIcon(remoteViews, 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;
}
} }
/** /**
@ -285,6 +271,19 @@ public final class BackgroundPlayer extends Service {
wifiLock = null; 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 { protected class BasePlayerImpl extends BasePlayer {
@ -424,21 +423,8 @@ public final class BackgroundPlayer extends Service {
@Override @Override
public void onRepeatModeChanged(int i) { public void onRepeatModeChanged(int i) {
int opacity = 255; setRepeatModeIcon(notRemoteView, i);
switch (simpleExoPlayer.getRepeatMode()) { setRepeatModeIcon(bigNotRemoteView, i);
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);
updateNotification(-1); updateNotification(-1);
updatePlayback(); updatePlayback();
} }

View File

@ -18,6 +18,7 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.PopupMenu; import android.widget.PopupMenu;
import android.widget.ProgressBar;
import android.widget.SeekBar; import android.widget.SeekBar;
import android.widget.TextView; import android.widget.TextView;
@ -70,6 +71,7 @@ public class BackgroundPlayerActivity extends AppCompatActivity
private ImageButton playPauseButton; private ImageButton playPauseButton;
private ImageButton forwardButton; private ImageButton forwardButton;
private ImageButton shuffleButton; private ImageButton shuffleButton;
private ProgressBar progressBar;
private TextView playbackSpeedButton; private TextView playbackSpeedButton;
private PopupMenu playbackSpeedPopupMenu; private PopupMenu playbackSpeedPopupMenu;
@ -164,7 +166,7 @@ public class BackgroundPlayerActivity extends AppCompatActivity
Log.d(TAG, "Background player service is connected"); Log.d(TAG, "Background player service is connected");
final BackgroundPlayer.LocalBinder mLocalBinder = (BackgroundPlayer.LocalBinder) service; final BackgroundPlayer.LocalBinder mLocalBinder = (BackgroundPlayer.LocalBinder) service;
player = mLocalBinder.getBackgroundPlayerInstance(); player = mLocalBinder.getBackgroundPlayerInstance();
if (player == null) { if (player == null || player.playQueue == null || player.playQueueAdapter == null || player.simpleExoPlayer == null) {
unbind(); unbind();
} else { } else {
buildComponents(); buildComponents();
@ -219,6 +221,7 @@ public class BackgroundPlayerActivity extends AppCompatActivity
shuffleButton = rootView.findViewById(R.id.control_shuffle); shuffleButton = rootView.findViewById(R.id.control_shuffle);
playbackSpeedButton = rootView.findViewById(R.id.control_playback_speed); playbackSpeedButton = rootView.findViewById(R.id.control_playback_speed);
playbackPitchButton = rootView.findViewById(R.id.control_playback_pitch); playbackPitchButton = rootView.findViewById(R.id.control_playback_pitch);
progressBar = rootView.findViewById(R.id.control_progress_bar);
repeatButton.setOnClickListener(this); repeatButton.setOnClickListener(this);
backwardButton.setOnClickListener(this); backwardButton.setOnClickListener(this);
@ -431,52 +434,9 @@ public class BackgroundPlayerActivity extends AppCompatActivity
@Override @Override
public void onPlaybackUpdate(int state, int repeatMode, boolean shuffled, PlaybackParameters parameters) { public void onPlaybackUpdate(int state, int repeatMode, boolean shuffled, PlaybackParameters parameters) {
switch (state) { onStateChanged(state);
case BasePlayer.STATE_PAUSED: onPlayModeChanged(repeatMode, shuffled);
playPauseButton.setImageResource(R.drawable.ic_play_arrow_white); onPlaybackParameterChanged(parameters);
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));
}
scrollToSelected(); scrollToSelected();
} }
@ -509,4 +469,67 @@ public class BackgroundPlayerActivity extends AppCompatActivity
public void onServiceStopped() { public void onServiceStopped() {
unbind(); 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));
}
}
} }

View File

@ -137,6 +137,7 @@ public abstract class BasePlayer implements Player.EventListener,
public static final String PLAY_QUEUE = "play_queue"; public static final String PLAY_QUEUE = "play_queue";
public static final String RESTORE_QUEUE_INDEX = "restore_queue_index"; public static final String RESTORE_QUEUE_INDEX = "restore_queue_index";
public static final String RESTORE_WINDOW_POS = "restore_window_pos"; public static final String RESTORE_WINDOW_POS = "restore_window_pos";
public static final String APPEND_ONLY = "append_only";
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// Playback // Playback
@ -260,6 +261,12 @@ public abstract class BasePlayer implements Player.EventListener,
if (!(playQueueCandidate instanceof PlayQueue)) return; if (!(playQueueCandidate instanceof PlayQueue)) return;
final PlayQueue queue = (PlayQueue) playQueueCandidate; final PlayQueue queue = (PlayQueue) playQueueCandidate;
// Resolve append intents
if (intent.getBooleanExtra(APPEND_ONLY, false) && playQueue != null) {
playQueue.append(queue.getStreams());
return;
}
// Resolve playback details // Resolve playback details
if (intent.hasExtra(RESTORE_QUEUE_INDEX) && intent.hasExtra(START_POSITION)) { if (intent.hasExtra(RESTORE_QUEUE_INDEX) && intent.hasExtra(START_POSITION)) {
setRecovery( setRecovery(
@ -310,6 +317,7 @@ public abstract class BasePlayer implements Player.EventListener,
public void destroyPlayer() { public void destroyPlayer() {
if (DEBUG) Log.d(TAG, "destroyPlayer() called"); if (DEBUG) Log.d(TAG, "destroyPlayer() called");
if (simpleExoPlayer != null) { if (simpleExoPlayer != null) {
simpleExoPlayer.removeListener(this);
simpleExoPlayer.stop(); simpleExoPlayer.stop();
simpleExoPlayer.release(); simpleExoPlayer.release();
} }

View File

@ -189,6 +189,20 @@ public final class MainVideoPlayer extends Activity {
: ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT); : 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"}) @SuppressWarnings({"unused", "WeakerAccess"})
@ -218,12 +232,6 @@ public final class MainVideoPlayer extends Activity {
this.screenRotationButton = rootView.findViewById(R.id.screenRotationButton); this.screenRotationButton = rootView.findViewById(R.id.screenRotationButton);
this.playPauseButton = rootView.findViewById(R.id.playPauseButton); 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); getRootView().setKeepScreenOn(true);
} }
@ -241,6 +249,16 @@ public final class MainVideoPlayer extends Activity {
screenRotationButton.setOnClickListener(this); screenRotationButton.setOnClickListener(this);
} }
/*//////////////////////////////////////////////////////////////////////////
// ExoPlayer Video Listener
//////////////////////////////////////////////////////////////////////////*/
@Override
public void onRepeatModeChanged(int i) {
super.onRepeatModeChanged(i);
setRepeatModeButton(repeatButton, simpleExoPlayer.getRepeatMode());
}
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// Playback Listener // Playback Listener
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
@ -289,31 +307,6 @@ public final class MainVideoPlayer extends Activity {
finish(); 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 @Override
public void onClick(View v) { public void onClick(View v) {
super.onClick(v); super.onClick(v);
@ -509,7 +502,7 @@ public final class MainVideoPlayer extends Activity {
@Override @Override
public boolean onSingleTapConfirmed(MotionEvent e) { public boolean onSingleTapConfirmed(MotionEvent e) {
if (DEBUG) Log.d(TAG, "onSingleTapConfirmed() called with: e = [" + 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); if (playerImpl.isControlsVisible()) playerImpl.hideControls(150, 0);
else { else {

View File

@ -111,7 +111,8 @@ public final class PopupVideoPlayer extends Service {
private float minimumWidth, minimumHeight; private float minimumWidth, minimumHeight;
private float maximumWidth, maximumHeight; 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 NotificationManager notificationManager;
private NotificationCompat.Builder notBuilder; private NotificationCompat.Builder notBuilder;
private RemoteViews notRemoteView; private RemoteViews notRemoteView;
@ -255,18 +256,7 @@ public final class PopupVideoPlayer extends Service {
notRemoteView.setOnClickPendingIntent(R.id.notificationRepeat, notRemoteView.setOnClickPendingIntent(R.id.notificationRepeat,
PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_REPEAT), PendingIntent.FLAG_UPDATE_CURRENT)); PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_REPEAT), PendingIntent.FLAG_UPDATE_CURRENT));
switch (playerImpl.simpleExoPlayer.getRepeatMode()) { setRepeatModeRemote(notRemoteView, 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;
}
return new NotificationCompat.Builder(this, getString(R.string.notification_channel_id)) return new NotificationCompat.Builder(this, getString(R.string.notification_channel_id))
.setOngoing(true) .setOngoing(true)
@ -370,6 +360,20 @@ public final class PopupVideoPlayer extends Service {
windowManager.updateViewLayout(playerImpl.getRootView(), windowLayoutParams); 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 { private class VideoPlayerImpl extends VideoPlayer {
@ -435,27 +439,6 @@ public final class PopupVideoPlayer extends Service {
stopSelf(); 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 @Override
public void onDismiss(PopupMenu menu) { public void onDismiss(PopupMenu menu) {
super.onDismiss(menu); super.onDismiss(menu);
@ -482,6 +465,16 @@ public final class PopupVideoPlayer extends Service {
hideControls(100, 0); hideControls(100, 0);
} }
} }
/*//////////////////////////////////////////////////////////////////////////
// ExoPlayer Video Listener
//////////////////////////////////////////////////////////////////////////*/
@Override
public void onRepeatModeChanged(int i) {
super.onRepeatModeChanged(i);
setRepeatModeRemote(notRemoteView, i);
updateNotification(-1);
}
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// Playback Listener // Playback Listener

View File

@ -211,7 +211,9 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
simpleExoPlayer.setVideoSurfaceView(surfaceView); simpleExoPlayer.setVideoSurfaceView(surfaceView);
simpleExoPlayer.addVideoListener(this); simpleExoPlayer.addVideoListener(this);
trackSelector.setTunnelingAudioSessionId(C.generateAudioSessionIdV21(context)); if (Build.VERSION.SDK_INT >= 21) {
trackSelector.setTunnelingAudioSessionId(C.generateAudioSessionIdV21(context));
}
} }
@Override @Override
@ -286,6 +288,7 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
qualityPopupMenu.setOnMenuItemClickListener(this); qualityPopupMenu.setOnMenuItemClickListener(this);
qualityPopupMenu.setOnDismissListener(this); qualityPopupMenu.setOnDismissListener(this);
qualityTextView.setVisibility(View.VISIBLE);
} }
private void buildPlaybackSpeedMenu() { private void buildPlaybackSpeedMenu() {
@ -409,12 +412,8 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) { public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
super.onTracksChanged(trackGroups, trackSelections); super.onTracksChanged(trackGroups, trackSelections);
if (trackSelector.getCurrentMappedTrackInfo() == null) { if (trackSelector.getCurrentMappedTrackInfo() == null) return;
qualityTextView.setVisibility(View.GONE); qualityTextView.setVisibility(View.GONE);
return;
} else {
qualityTextView.setVisibility(View.VISIBLE);
}
for (int t = 0; t < simpleExoPlayer.getRendererCount(); t++) { for (int t = 0; t < simpleExoPlayer.getRendererCount(); t++) {
if (simpleExoPlayer.getRendererType(t) == C.TRACK_TYPE_VIDEO) { 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); videoTrackGroups = trackSelector.getCurrentMappedTrackInfo().getTrackGroups(videoRendererIndex);
selectedVideoTrackGroup = trackSelections.get(videoRendererIndex).getTrackGroup(); final TrackSelection trackSelection = trackSelections.get(videoRendererIndex);
if (trackSelection != null) {
buildQualityMenu(); selectedVideoTrackGroup = trackSelection.getTrackGroup();
buildQualityMenu();
}
} }
@Override @Override

View File

@ -57,6 +57,14 @@ public class NavigationHelper {
.putExtra(VideoPlayer.PLAY_QUEUE, playQueue); .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, public static Intent getPlayerIntent(final Context context,
final Class targetClazz, final Class targetClazz,
final PlayQueue playQueue, final PlayQueue playQueue,

View File

@ -183,6 +183,23 @@
android:src="@drawable/ic_pause_white" android:src="@drawable/ic_pause_white"
tools:ignore="ContentDescription"/> tools:ignore="ContentDescription"/>
<ProgressBar
android:id="@+id/control_progress_bar"
style="?android:attr/progressBarStyleLargeInverse"
android:layout_width="50dp"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:layout_centerInParent="true"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:background="#00000000"
android:padding="2dp"
android:clickable="false"
android:scaleType="fitCenter"
android:indeterminate="true"
android:visibility="invisible"/>
<ImageButton <ImageButton
android:id="@+id/control_forward" android:id="@+id/control_forward"
android:layout_width="40dp" android:layout_width="40dp"

View File

@ -155,7 +155,7 @@
android:clickable="true" android:clickable="true"
android:padding="5dp" android:padding="5dp"
android:scaleType="fitXY" android:scaleType="fitXY"
android:src="@drawable/ic_repeat_white" android:src="@drawable/exo_controls_repeat_off"
tools:ignore="ContentDescription,RtlHardcoded"/> tools:ignore="ContentDescription,RtlHardcoded"/>
<ImageButton <ImageButton