mirror of
https://github.com/clangen/musikcube.git
synced 2025-01-31 00:32:42 +00:00
* Added a distinction between SystemService sleeping (no wakelock, but appears
active) and shutdown (no notification or lockscreen controls). * Fixed bug where recovering from an HTTP error would cause the track to reset playback at the beginning
This commit is contained in:
parent
ab11376356
commit
45a81cb138
@ -22,7 +22,6 @@ import com.google.android.exoplayer2.trackselection.TrackSelector;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
|
||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||
import com.google.android.exoplayer2.upstream.HttpDataSource;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
|
||||
import io.casey.musikcube.remote.Application;
|
||||
@ -35,6 +34,7 @@ public class ExoPlayerWrapper extends PlayerWrapper {
|
||||
private SimpleExoPlayer player;
|
||||
private boolean prefetch;
|
||||
private Context context;
|
||||
private long lastPosition = -1;
|
||||
|
||||
public ExoPlayerWrapper() {
|
||||
this.context = Application.getInstance();
|
||||
@ -100,7 +100,7 @@ public class ExoPlayerWrapper extends PlayerWrapper {
|
||||
break;
|
||||
|
||||
case Error:
|
||||
this.player.setPlayWhenReady(true);
|
||||
this.player.setPlayWhenReady(this.lastPosition == -1);
|
||||
this.player.prepare(this.source);
|
||||
setState(State.Preparing);
|
||||
break;
|
||||
@ -113,6 +113,7 @@ public class ExoPlayerWrapper extends PlayerWrapper {
|
||||
public void setPosition(int millis) {
|
||||
Preconditions.throwIfNotOnMainThread();
|
||||
|
||||
this.lastPosition = -1;
|
||||
if (this.player.getPlaybackState() != ExoPlayer.STATE_IDLE) {
|
||||
if (this.player.isCurrentWindowSeekable()) {
|
||||
this.player.seekTo(millis);
|
||||
@ -201,6 +202,11 @@ public class ExoPlayerWrapper extends PlayerWrapper {
|
||||
|
||||
player.setVolume(getGlobalVolume());
|
||||
|
||||
if (lastPosition != -1) {
|
||||
player.seekTo(lastPosition);
|
||||
lastPosition = -1;
|
||||
}
|
||||
|
||||
if (!prefetch) {
|
||||
player.setPlayWhenReady(true);
|
||||
setState(State.Playing);
|
||||
@ -220,6 +226,8 @@ public class ExoPlayerWrapper extends PlayerWrapper {
|
||||
public void onPlayerError(ExoPlaybackException error) {
|
||||
Preconditions.throwIfNotOnMainThread();
|
||||
|
||||
lastPosition = player.getCurrentPosition();
|
||||
|
||||
switch (getState()) {
|
||||
case Preparing:
|
||||
case Prepared:
|
||||
|
@ -40,7 +40,7 @@ public class StreamingPlaybackService implements PlaybackService {
|
||||
private static final int PREV_TRACK_GRACE_PERIOD_MILLIS = 3500;
|
||||
private static final int MAX_TRACK_METADATA_CACHE_SIZE = 50;
|
||||
private static final int PRECACHE_METADATA_SIZE = 10;
|
||||
private static final int PAUSED_SERVICE_SHUTDOWN_DELAY_MS = 1000 * 60; /* 1 minute */
|
||||
private static final int PAUSED_SERVICE_SLEEP_DELAY_MS = 1000 * 60 * 5; /* 5 minutes */
|
||||
|
||||
private WebSocketService wss;
|
||||
private Set<EventListener> listeners = new HashSet<>();
|
||||
@ -72,7 +72,8 @@ public class StreamingPlaybackService implements PlaybackService {
|
||||
public void stopPlaybackAndReset() {
|
||||
reset(currentPlayer);
|
||||
reset(nextPlayer);
|
||||
nextPlayerScheduled = false; this.currentPlayer = this.nextPlayer = null;
|
||||
nextPlayerScheduled = false;
|
||||
this.currentPlayer = this.nextPlayer = null;
|
||||
this.currentMetadata = this.nextMetadata = null;
|
||||
this.currentIndex = this.nextIndex = -1;
|
||||
}
|
||||
@ -226,7 +227,7 @@ public class StreamingPlaybackService implements PlaybackService {
|
||||
@Override
|
||||
public void pause() {
|
||||
if (state != PlaybackState.Paused) {
|
||||
schedulePausedShutdown();
|
||||
schedulePausedSleep();
|
||||
killAudioFocus();
|
||||
|
||||
if (context.currentPlayer != null) {
|
||||
@ -240,7 +241,7 @@ public class StreamingPlaybackService implements PlaybackService {
|
||||
@Override
|
||||
public void resume() {
|
||||
if (requestAudioFocus()) {
|
||||
cancelScheduledPausedShutdown();
|
||||
cancelScheduledPausedSleep();
|
||||
context.currentPlayer.resume();
|
||||
setState(PlaybackState.Playing);
|
||||
pausedByTransientLoss = false;
|
||||
@ -259,7 +260,7 @@ public class StreamingPlaybackService implements PlaybackService {
|
||||
@Override
|
||||
public void prev() {
|
||||
if (requestAudioFocus()) {
|
||||
cancelScheduledPausedShutdown();
|
||||
cancelScheduledPausedSleep();
|
||||
|
||||
if (context.currentPlayer != null) {
|
||||
if (context.currentPlayer.getPosition() > PREV_TRACK_GRACE_PERIOD_MILLIS) {
|
||||
@ -274,7 +275,7 @@ public class StreamingPlaybackService implements PlaybackService {
|
||||
@Override
|
||||
public void next() {
|
||||
if (requestAudioFocus()) {
|
||||
cancelScheduledPausedShutdown();
|
||||
cancelScheduledPausedSleep();
|
||||
moveToNextTrack(true);
|
||||
}
|
||||
}
|
||||
@ -503,7 +504,7 @@ public class StreamingPlaybackService implements PlaybackService {
|
||||
case Playing:
|
||||
setState(PlaybackState.Playing);
|
||||
prefetchNextTrackAudio();
|
||||
cancelScheduledPausedShutdown();
|
||||
cancelScheduledPausedSleep();
|
||||
precacheTrackMetadata(context.currentIndex, PRECACHE_METADATA_SIZE);
|
||||
break;
|
||||
|
||||
@ -737,7 +738,7 @@ public class StreamingPlaybackService implements PlaybackService {
|
||||
private void loadQueueAndPlay(final QueueParams params, int startIndex) {
|
||||
setState(PlaybackState.Buffering);
|
||||
|
||||
cancelScheduledPausedShutdown();
|
||||
cancelScheduledPausedSleep();
|
||||
SystemService.wakeup();
|
||||
|
||||
this.pausedByTransientLoss = false;
|
||||
@ -782,13 +783,13 @@ public class StreamingPlaybackService implements PlaybackService {
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
private void cancelScheduledPausedShutdown() {
|
||||
private void cancelScheduledPausedSleep() {
|
||||
SystemService.wakeup();
|
||||
handler.removeCallbacks(pauseServiceShutdownRunnable);
|
||||
handler.removeCallbacks(pauseServiceSleepRunnable);
|
||||
}
|
||||
|
||||
private void schedulePausedShutdown() {
|
||||
handler.postDelayed(pauseServiceShutdownRunnable, PAUSED_SERVICE_SHUTDOWN_DELAY_MS);
|
||||
private void schedulePausedSleep() {
|
||||
handler.postDelayed(pauseServiceSleepRunnable, PAUSED_SERVICE_SLEEP_DELAY_MS);
|
||||
}
|
||||
|
||||
private void precacheTrackMetadata(final int start, final int count) {
|
||||
@ -881,7 +882,7 @@ public class StreamingPlaybackService implements PlaybackService {
|
||||
}
|
||||
};
|
||||
|
||||
private Runnable pauseServiceShutdownRunnable = () -> SystemService.shutdown();
|
||||
private Runnable pauseServiceSleepRunnable = () -> SystemService.sleep();
|
||||
|
||||
private AudioManager.OnAudioFocusChangeListener audioFocusChangeListener = (flag) -> {
|
||||
switch (flag) {
|
||||
|
@ -49,6 +49,7 @@ public class SystemService extends Service {
|
||||
public static final String ACTION_NOTIFICATION_STOP = "io.casey.musikcube.remote.PAUSE_SHUT_DOWN";
|
||||
public static String ACTION_WAKE_UP = "io.casey.musikcube.remote.WAKE_UP";
|
||||
public static String ACTION_SHUT_DOWN = "io.casey.musikcube.remote.SHUT_DOWN";
|
||||
public static String ACTION_SLEEP = "io.casey.musikcube.remote.SLEEP";
|
||||
|
||||
private final static long MEDIA_SESSION_ACTIONS =
|
||||
PlaybackStateCompat.ACTION_PLAY_PAUSE |
|
||||
@ -79,6 +80,11 @@ public class SystemService extends Service {
|
||||
c.startService(new Intent(c, SystemService.class).setAction(ACTION_SHUT_DOWN));
|
||||
}
|
||||
|
||||
public static void sleep() {
|
||||
final Context c = Application.getInstance();
|
||||
c.startService(new Intent(c, SystemService.class).setAction(ACTION_SLEEP));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
@ -99,42 +105,16 @@ public class SystemService extends Service {
|
||||
if (intent != null) {
|
||||
final String action = intent.getAction();
|
||||
if (ACTION_WAKE_UP.equals(action)) {
|
||||
Log.d(TAG, "SystemService WAKE_UP");
|
||||
|
||||
if (playback == null) {
|
||||
playback = PlaybackServiceFactory.streaming(this);
|
||||
playback.connect(listener);
|
||||
initMediaSession();
|
||||
}
|
||||
|
||||
if (wakeLock == null) {
|
||||
wakeLock = powerManager.newWakeLock(
|
||||
PowerManager.PARTIAL_WAKE_LOCK, "StreamingPlaybackService");
|
||||
|
||||
wakeLock.setReferenceCounted(false);
|
||||
wakeLock.acquire();
|
||||
}
|
||||
wakeupNow();
|
||||
}
|
||||
else if (ACTION_SHUT_DOWN.equals(action)) {
|
||||
Log.d(TAG, "SystemService SHUT_DOWN");
|
||||
|
||||
if (mediaSession != null) {
|
||||
mediaSession.release();
|
||||
}
|
||||
|
||||
if (playback != null) {
|
||||
playback.disconnect(listener);
|
||||
playback = null;
|
||||
}
|
||||
|
||||
if (wakeLock != null) {
|
||||
wakeLock.release();
|
||||
wakeLock = null;
|
||||
}
|
||||
|
||||
stopSelf();
|
||||
shutdownNow();
|
||||
}
|
||||
else if (ACTION_SLEEP.equals(action)) {
|
||||
sleepNow();
|
||||
}
|
||||
else if (handlePlaybackAction(action)) {
|
||||
wakeupNow();
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
}
|
||||
}
|
||||
@ -148,6 +128,62 @@ public class SystemService extends Service {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void wakeupNow() {
|
||||
Log.d(TAG, "SystemService WAKE_UP");
|
||||
|
||||
final boolean sleeping = (playback == null || wakeLock == null);
|
||||
|
||||
if (playback == null) {
|
||||
playback = PlaybackServiceFactory.streaming(this);
|
||||
}
|
||||
|
||||
if (wakeLock == null) {
|
||||
wakeLock = powerManager.newWakeLock(
|
||||
PowerManager.PARTIAL_WAKE_LOCK, "StreamingPlaybackService");
|
||||
|
||||
wakeLock.setReferenceCounted(false);
|
||||
wakeLock.acquire();
|
||||
}
|
||||
|
||||
if (sleeping) {
|
||||
playback.connect(listener);
|
||||
initMediaSession();
|
||||
}
|
||||
}
|
||||
|
||||
private void shutdownNow() {
|
||||
Log.d(TAG, "SystemService SHUT_DOWN");
|
||||
|
||||
if (mediaSession != null) {
|
||||
mediaSession.release();
|
||||
}
|
||||
|
||||
if (playback != null) {
|
||||
playback.disconnect(listener);
|
||||
playback = null;
|
||||
}
|
||||
|
||||
if (wakeLock != null) {
|
||||
wakeLock.release();
|
||||
wakeLock = null;
|
||||
}
|
||||
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
private void sleepNow() {
|
||||
Log.d(TAG, "SystemService SLEEP");
|
||||
|
||||
if (wakeLock != null) {
|
||||
wakeLock.release();
|
||||
wakeLock = null;
|
||||
}
|
||||
|
||||
if (playback != null) {
|
||||
playback.disconnect(listener);
|
||||
}
|
||||
}
|
||||
|
||||
private void initMediaSession() {
|
||||
ComponentName receiver = new ComponentName(getPackageName(), MediaButtonReceiver.class.getName());
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user