-Fixed audio-only streams thumbnail not displaying on video players.
-Fixed potential play queue desynchronization due to fast forwarding on silence. -Added current thumbnail storing in base player to allow immediate retrieval for notification building. -Removed video player buffer spinner during interim buffering but not initial buffering. -Reverted foreground notification stopping on pause and on complete.
This commit is contained in:
parent
157b064214
commit
2d6317bd24
5 changed files with 64 additions and 112 deletions
|
@ -188,7 +188,9 @@ public final class BackgroundPlayer extends Service {
|
|||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
.setCustomContentView(notRemoteView)
|
||||
.setCustomBigContentView(bigNotRemoteView);
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) builder.setPriority(NotificationCompat.PRIORITY_MAX);
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
|
||||
builder.setPriority(NotificationCompat.PRIORITY_MAX);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
@ -197,6 +199,7 @@ public final class BackgroundPlayer extends Service {
|
|||
|
||||
remoteViews.setTextViewText(R.id.notificationSongName, basePlayerImpl.getVideoTitle());
|
||||
remoteViews.setTextViewText(R.id.notificationArtist, basePlayerImpl.getUploaderName());
|
||||
remoteViews.setImageViewBitmap(R.id.notificationCover, basePlayerImpl.getThumbnail());
|
||||
|
||||
remoteViews.setOnClickPendingIntent(R.id.notificationPlayPause,
|
||||
PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_PLAY_PAUSE), PendingIntent.FLAG_UPDATE_CURRENT));
|
||||
|
@ -244,6 +247,7 @@ public final class BackgroundPlayer extends Service {
|
|||
}
|
||||
notificationManager.notify(NOTIFICATION_ID, notBuilder.build());
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
@ -291,57 +295,26 @@ public final class BackgroundPlayer extends Service {
|
|||
// Thumbnail Loading
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private void setDummyRemoteViewThumbnail() {
|
||||
resetNotification();
|
||||
if (notRemoteView != null) {
|
||||
notRemoteView.setImageViewResource(R.id.notificationCover,
|
||||
R.drawable.dummy_thumbnail);
|
||||
}
|
||||
if (bigNotRemoteView != null) {
|
||||
bigNotRemoteView.setImageViewResource(R.id.notificationCover,
|
||||
R.drawable.dummy_thumbnail);
|
||||
}
|
||||
updateNotification(-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadingStarted(String imageUri, View view) {
|
||||
super.onLoadingStarted(imageUri, view);
|
||||
setDummyRemoteViewThumbnail();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
|
||||
super.onLoadingComplete(imageUri, view, loadedImage);
|
||||
if (loadedImage == null) {
|
||||
setDummyRemoteViewThumbnail();
|
||||
return;
|
||||
}
|
||||
|
||||
// rebuild notification here since remote view does not release bitmaps,
|
||||
// causing memory leaks
|
||||
resetNotification();
|
||||
if (notRemoteView != null) {
|
||||
notRemoteView.setImageViewBitmap(R.id.notificationCover, loadedImage);
|
||||
}
|
||||
if (bigNotRemoteView != null) {
|
||||
bigNotRemoteView.setImageViewBitmap(R.id.notificationCover, loadedImage);
|
||||
}
|
||||
updateNotification(-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
|
||||
super.onLoadingFailed(imageUri, view, failReason);
|
||||
setDummyRemoteViewThumbnail();
|
||||
resetNotification();
|
||||
updateNotification(-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadingCancelled(String imageUri, View view) {
|
||||
super.onLoadingCancelled(imageUri, view);
|
||||
setDummyRemoteViewThumbnail();
|
||||
resetNotification();
|
||||
updateNotification(-1);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// States Implementation
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
@ -544,60 +517,38 @@ public final class BackgroundPlayer extends Service {
|
|||
|
||||
@Override
|
||||
public void changeState(int state) {
|
||||
resetNotification();
|
||||
super.changeState(state);
|
||||
updatePlayback();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlocked() {
|
||||
super.onBlocked();
|
||||
updateNotification(-1);
|
||||
startForeground(NOTIFICATION_ID, notBuilder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBuffering() {
|
||||
super.onBuffering();
|
||||
updateNotification(-1);
|
||||
startForeground(NOTIFICATION_ID, notBuilder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPausedSeek() {
|
||||
super.onPausedSeek();
|
||||
updateNotification(-1);
|
||||
startForeground(NOTIFICATION_ID, notBuilder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaying() {
|
||||
super.onPlaying();
|
||||
resetNotification();
|
||||
updateNotification(R.drawable.ic_pause_white);
|
||||
|
||||
lockManager.acquireWifiAndCpu();
|
||||
startForeground(NOTIFICATION_ID, notBuilder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPaused() {
|
||||
super.onPaused();
|
||||
resetNotification();
|
||||
updateNotification(R.drawable.ic_play_arrow_white);
|
||||
|
||||
lockManager.releaseWifiAndCpu();
|
||||
stopForeground(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
super.onCompleted();
|
||||
|
||||
if (bigNotRemoteView != null) bigNotRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 100, false);
|
||||
if (notRemoteView != null) notRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 100, false);
|
||||
resetNotification();
|
||||
if (bigNotRemoteView != null) {
|
||||
bigNotRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 100, false);
|
||||
}
|
||||
if (notRemoteView != null) {
|
||||
notRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 100, false);
|
||||
}
|
||||
updateNotification(R.drawable.ic_replay_white);
|
||||
|
||||
lockManager.releaseWifiAndCpu();
|
||||
stopForeground(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.media.AudioManager;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
@ -139,6 +140,7 @@ public abstract class BasePlayer implements
|
|||
|
||||
@Nullable private PlayQueueItem currentItem;
|
||||
@Nullable private MediaSourceTag currentMetadata;
|
||||
@Nullable private Bitmap currentThumbnail;
|
||||
|
||||
@Nullable protected Toast errorToast;
|
||||
|
||||
|
@ -317,6 +319,7 @@ public abstract class BasePlayer implements
|
|||
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
|
||||
Log.e(TAG, "Thumbnail - onLoadingFailed() called on imageUri = [" + imageUri + "]",
|
||||
failReason.getCause());
|
||||
currentThumbnail = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -324,12 +327,14 @@ public abstract class BasePlayer implements
|
|||
if (DEBUG) Log.d(TAG, "Thumbnail - onLoadingComplete() called with: " +
|
||||
"imageUri = [" + imageUri + "], view = [" + view + "], " +
|
||||
"loadedImage = [" + loadedImage + "]");
|
||||
currentThumbnail = loadedImage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadingCancelled(String imageUri, View view) {
|
||||
if (DEBUG) Log.d(TAG, "Thumbnail - onLoadingCancelled() called with: " +
|
||||
"imageUri = [" + imageUri + "], view = [" + view + "]");
|
||||
currentThumbnail = null;
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -653,19 +658,25 @@ public abstract class BasePlayer implements
|
|||
public void onPositionDiscontinuity(@Player.DiscontinuityReason final int reason) {
|
||||
if (DEBUG) Log.d(TAG, "ExoPlayer - onPositionDiscontinuity() called with " +
|
||||
"reason = [" + reason + "]");
|
||||
if (playQueue == null) return;
|
||||
|
||||
// Refresh the playback if there is a transition to the next video
|
||||
final int newPeriodIndex = simpleExoPlayer.getCurrentPeriodIndex();
|
||||
final int newWindowIndex = simpleExoPlayer.getCurrentWindowIndex();
|
||||
switch (reason) {
|
||||
case DISCONTINUITY_REASON_PERIOD_TRANSITION:
|
||||
if (newPeriodIndex == playQueue.getIndex()) {
|
||||
// When player is in single repeat mode and a period transition occurs,
|
||||
// we need to register a view count here since no metadata has changed
|
||||
if (getRepeatMode() == Player.REPEAT_MODE_ONE &&
|
||||
newWindowIndex == playQueue.getIndex()) {
|
||||
registerView();
|
||||
} else {
|
||||
playQueue.setIndex(newPeriodIndex);
|
||||
break;
|
||||
}
|
||||
case DISCONTINUITY_REASON_SEEK:
|
||||
case DISCONTINUITY_REASON_SEEK_ADJUSTMENT:
|
||||
case DISCONTINUITY_REASON_INTERNAL:
|
||||
if (playQueue.getIndex() != newWindowIndex) {
|
||||
playQueue.setIndex(newWindowIndex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -777,9 +788,10 @@ public abstract class BasePlayer implements
|
|||
}
|
||||
|
||||
protected void onMetadataChanged(@NonNull final MediaSourceTag tag) {
|
||||
Log.d(TAG, "Playback - onMetadataChanged() called, " +
|
||||
"playing: " + tag.getMetadata().getName());
|
||||
final StreamInfo info = tag.getMetadata();
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Playback - onMetadataChanged() called, playing: " + info.getName());
|
||||
}
|
||||
|
||||
initThumbnail(info.getThumbnailUrl());
|
||||
registerView();
|
||||
|
@ -1045,6 +1057,13 @@ public abstract class BasePlayer implements
|
|||
return currentItem == null ? context.getString(R.string.unknown_content) : currentItem.getUploader();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Bitmap getThumbnail() {
|
||||
return currentThumbnail == null ?
|
||||
BitmapFactory.decodeResource(context.getResources(), R.drawable.dummy_thumbnail) :
|
||||
currentThumbnail;
|
||||
}
|
||||
|
||||
/** Checks if the current playback is a livestream AND is playing at or beyond the live edge */
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
public boolean isLiveEdge() {
|
||||
|
|
|
@ -720,7 +720,6 @@ public final class MainVideoPlayer extends AppCompatActivity
|
|||
@Override
|
||||
public void onBuffering() {
|
||||
super.onBuffering();
|
||||
animatePlayButtons(false, 100);
|
||||
getRootView().setKeepScreenOn(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ import android.os.Build;
|
|||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
|
@ -229,6 +228,7 @@ public final class PopupVideoPlayer extends Service {
|
|||
|
||||
notRemoteView.setTextViewText(R.id.notificationSongName, playerImpl.getVideoTitle());
|
||||
notRemoteView.setTextViewText(R.id.notificationArtist, playerImpl.getUploaderName());
|
||||
notRemoteView.setImageViewBitmap(R.id.notificationCover, playerImpl.getThumbnail());
|
||||
|
||||
notRemoteView.setOnClickPendingIntent(R.id.notificationPlayPause,
|
||||
PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_PLAY_PAUSE), PendingIntent.FLAG_UPDATE_CURRENT));
|
||||
|
@ -517,48 +517,27 @@ public final class PopupVideoPlayer extends Service {
|
|||
// Thumbnail Loading
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private void setDummyRemoteViewThumbnail() {
|
||||
resetNotification();
|
||||
if (notRemoteView != null) {
|
||||
notRemoteView.setImageViewResource(R.id.notificationCover,
|
||||
R.drawable.dummy_thumbnail);
|
||||
}
|
||||
updateNotification(-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadingStarted(String imageUri, View view) {
|
||||
super.onLoadingStarted(imageUri, view);
|
||||
setDummyRemoteViewThumbnail();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
|
||||
super.onLoadingComplete(imageUri, view, loadedImage);
|
||||
if (loadedImage == null) {
|
||||
setDummyRemoteViewThumbnail();
|
||||
return;
|
||||
}
|
||||
|
||||
// rebuild notification here since remote view does not release bitmaps,
|
||||
// causing memory leaks
|
||||
resetNotification();
|
||||
if (notRemoteView != null) {
|
||||
notRemoteView.setImageViewBitmap(R.id.notificationCover, loadedImage);
|
||||
}
|
||||
updateNotification(-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
|
||||
super.onLoadingFailed(imageUri, view, failReason);
|
||||
setDummyRemoteViewThumbnail();
|
||||
resetNotification();
|
||||
updateNotification(-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadingCancelled(String imageUri, View view) {
|
||||
super.onLoadingCancelled(imageUri, view);
|
||||
setDummyRemoteViewThumbnail();
|
||||
resetNotification();
|
||||
updateNotification(-1);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -613,6 +592,7 @@ public final class PopupVideoPlayer extends Service {
|
|||
super.onRepeatModeChanged(i);
|
||||
setRepeatModeRemote(notRemoteView, i);
|
||||
updatePlayback();
|
||||
resetNotification();
|
||||
updateNotification(-1);
|
||||
}
|
||||
|
||||
|
@ -683,7 +663,6 @@ public final class PopupVideoPlayer extends Service {
|
|||
|
||||
@Override
|
||||
public void changeState(int state) {
|
||||
resetNotification();
|
||||
super.changeState(state);
|
||||
updatePlayback();
|
||||
}
|
||||
|
@ -691,14 +670,16 @@ public final class PopupVideoPlayer extends Service {
|
|||
@Override
|
||||
public void onBlocked() {
|
||||
super.onBlocked();
|
||||
resetNotification();
|
||||
updateNotification(R.drawable.ic_play_arrow_white);
|
||||
startForeground(NOTIFICATION_ID, notBuilder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlaying() {
|
||||
super.onPlaying();
|
||||
resetNotification();
|
||||
updateNotification(R.drawable.ic_pause_white);
|
||||
|
||||
videoPlayPause.setBackgroundResource(R.drawable.ic_pause_white);
|
||||
hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME);
|
||||
|
||||
|
@ -713,16 +694,17 @@ public final class PopupVideoPlayer extends Service {
|
|||
@Override
|
||||
public void onBuffering() {
|
||||
super.onBuffering();
|
||||
resetNotification();
|
||||
updateNotification(R.drawable.ic_play_arrow_white);
|
||||
startForeground(NOTIFICATION_ID, notBuilder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPaused() {
|
||||
super.onPaused();
|
||||
resetNotification();
|
||||
updateNotification(R.drawable.ic_play_arrow_white);
|
||||
videoPlayPause.setBackgroundResource(R.drawable.ic_play_arrow_white);
|
||||
|
||||
videoPlayPause.setBackgroundResource(R.drawable.ic_play_arrow_white);
|
||||
lockManager.releaseWifiAndCpu();
|
||||
|
||||
windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
|
@ -734,17 +716,19 @@ public final class PopupVideoPlayer extends Service {
|
|||
@Override
|
||||
public void onPausedSeek() {
|
||||
super.onPausedSeek();
|
||||
videoPlayPause.setBackgroundResource(R.drawable.ic_pause_white);
|
||||
resetNotification();
|
||||
updateNotification(R.drawable.ic_play_arrow_white);
|
||||
startForeground(NOTIFICATION_ID, notBuilder.build());
|
||||
|
||||
videoPlayPause.setBackgroundResource(R.drawable.ic_pause_white);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
super.onCompleted();
|
||||
resetNotification();
|
||||
updateNotification(R.drawable.ic_replay_white);
|
||||
videoPlayPause.setBackgroundResource(R.drawable.ic_replay_white);
|
||||
|
||||
videoPlayPause.setBackgroundResource(R.drawable.ic_replay_white);
|
||||
lockManager.releaseWifiAndCpu();
|
||||
|
||||
windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
|
@ -768,8 +752,6 @@ public final class PopupVideoPlayer extends Service {
|
|||
super.hideControlsAndButton(duration, delay, videoPlayPause);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
|
|
@ -333,16 +333,19 @@ public abstract class VideoPlayer extends BasePlayer
|
|||
switch (tag.getMetadata().getStreamType()) {
|
||||
case AUDIO_STREAM:
|
||||
surfaceView.setVisibility(View.GONE);
|
||||
endScreen.setVisibility(View.VISIBLE);
|
||||
playbackEndTime.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
|
||||
case AUDIO_LIVE_STREAM:
|
||||
surfaceView.setVisibility(View.GONE);
|
||||
endScreen.setVisibility(View.VISIBLE);
|
||||
playbackLiveSync.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
|
||||
case LIVE_STREAM:
|
||||
surfaceView.setVisibility(View.VISIBLE);
|
||||
endScreen.setVisibility(View.GONE);
|
||||
playbackLiveSync.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
|
||||
|
@ -357,6 +360,7 @@ public abstract class VideoPlayer extends BasePlayer
|
|||
qualityTextView.setVisibility(View.VISIBLE);
|
||||
surfaceView.setVisibility(View.VISIBLE);
|
||||
default:
|
||||
endScreen.setVisibility(View.GONE);
|
||||
playbackEndTime.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
}
|
||||
|
@ -387,7 +391,6 @@ public abstract class VideoPlayer extends BasePlayer
|
|||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
|
||||
playbackSeekBar.getThumb().setColorFilter(Color.RED, PorterDuff.Mode.SRC_IN);
|
||||
|
||||
animateView(endScreen, false, 0);
|
||||
loadingPanel.setBackgroundColor(Color.BLACK);
|
||||
animateView(loadingPanel, true, 0);
|
||||
animateView(surfaceForeground, true, 100);
|
||||
|
@ -407,14 +410,12 @@ public abstract class VideoPlayer extends BasePlayer
|
|||
loadingPanel.setVisibility(View.GONE);
|
||||
|
||||
animateView(currentDisplaySeek, AnimationUtils.Type.SCALE_AND_ALPHA, false, 200);
|
||||
animateView(endScreen, false, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBuffering() {
|
||||
if (DEBUG) Log.d(TAG, "onBuffering() called");
|
||||
loadingPanel.setBackgroundColor(Color.TRANSPARENT);
|
||||
animateView(loadingPanel, true, 500);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in a new issue