diff options
author | Domingos Lopes <domingos86lopes+github@gmail.com> | 2016-04-26 01:10:08 -0400 |
---|---|---|
committer | Domingos Lopes <domingos86lopes+github@gmail.com> | 2016-04-26 01:18:55 -0400 |
commit | b1f62b56cdf0e1f1011bf8b4eec6fe1bdd053220 (patch) | |
tree | e90ad3b7e47803a3be64fc915fc93812e4127c33 | |
parent | 86cc2233d3f6c7a7d5957049468865221762f2e8 (diff) | |
download | AntennaPod-b1f62b56cdf0e1f1011bf8b4eec6fe1bdd053220.zip |
add a general callback method for reporting media updates
5 files changed, 139 insertions, 91 deletions
diff --git a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java index 80a4458d1..b4e6710d2 100644 --- a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java +++ b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java @@ -176,7 +176,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { } @Override - public void updateMediaSessionMetadata(Playable p) { + public void reloadUI() { } @@ -255,7 +255,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { } @Override - public void updateMediaSessionMetadata(Playable p) { + public void reloadUI() { } @@ -337,7 +337,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { } @Override - public void updateMediaSessionMetadata(Playable p) { + public void reloadUI() { } @@ -420,7 +420,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { } @Override - public void updateMediaSessionMetadata(Playable p) { + public void reloadUI() { } @@ -497,7 +497,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { } @Override - public void updateMediaSessionMetadata(Playable p) { + public void reloadUI() { } @@ -575,7 +575,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { } @Override - public void updateMediaSessionMetadata(Playable p) { + public void reloadUI() { } @@ -655,7 +655,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { } @Override - public void updateMediaSessionMetadata(Playable p) { + public void reloadUI() { } @@ -738,7 +738,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { } @Override - public void updateMediaSessionMetadata(Playable p) { + public void reloadUI() { } @@ -796,7 +796,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { } @Override - public void updateMediaSessionMetadata(Playable p) { + public void reloadUI() { } @@ -874,7 +874,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { } @Override - public void updateMediaSessionMetadata(Playable p) { + public void reloadUI() { } @@ -989,7 +989,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { } @Override - public void updateMediaSessionMetadata(Playable p) { + public void reloadUI() { } @@ -1081,7 +1081,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { } @Override - public void updateMediaSessionMetadata(Playable p) { + public void reloadUI() { } @@ -1185,7 +1185,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase { } @Override - public void updateMediaSessionMetadata(Playable p) { + public void reloadUI() { } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index 28424306f..32bafd580 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -158,7 +158,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { setPlayerStatus(PlayerStatus.INITIALIZING, media); try { media.loadMetadata(); - executor.submit(() -> callback.updateMediaSessionMetadata(media)); + callback.reloadUI(); if (stream) { mediaPlayer.setDataSource(media.getStreamUrl()); } else { @@ -599,7 +599,6 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { public void shutdown() { executor.shutdown(); if (mediaPlayer != null) { - removeMediaPlayerListeners(mediaPlayer); mediaPlayer.release(); } releaseWifiLockIfNecessary(); @@ -822,26 +821,6 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { return mp; } - private void removeMediaPlayerListeners(IPlayer mp) { - if (mp == null) { - return; - } - if (mp instanceof AudioPlayer) { - ((AudioPlayer) mp).setOnCompletionListener(null); - ((AudioPlayer) mp).setOnSeekCompleteListener(null); - ((AudioPlayer) mp).setOnErrorListener(null); - ((AudioPlayer) mp).setOnBufferingUpdateListener(null); - ((AudioPlayer) mp).setOnInfoListener(null); - ((AudioPlayer) mp).setOnSpeedAdjustmentAvailableChangedListener(null); - } else { - ((VideoPlayer) mp).setOnCompletionListener(null); - ((VideoPlayer) mp).setOnSeekCompleteListener(null); - ((VideoPlayer) mp).setOnErrorListener(null); - ((VideoPlayer) mp).setOnBufferingUpdateListener(null); - ((VideoPlayer) mp).setOnInfoListener(null); - } - } - private final MediaPlayer.OnCompletionListener audioCompletionListener = mp -> genericOnCompletion(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index e477b9273..215acad17 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -22,10 +22,10 @@ import android.os.Build; import android.os.IBinder; import android.os.Vibrator; import android.preference.PreferenceManager; +import android.support.annotation.NonNull; import android.support.v4.media.MediaMetadataCompat; import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.PlaybackStateCompat; -import android.support.annotation.NonNull; import android.support.v7.app.NotificationCompat; import android.support.v7.media.MediaRouter; import android.text.TextUtils; @@ -39,6 +39,7 @@ import android.view.WindowManager; import android.widget.Toast; import com.bumptech.glide.Glide; +import com.bumptech.glide.request.target.Target; import com.google.android.gms.cast.ApplicationMetadata; import com.google.android.libraries.cast.companionlibrary.cast.BaseCastManager; @@ -633,8 +634,9 @@ public class PlaybackService extends Service { } @Override - public void updateMediaSessionMetadata(Playable p) { - PlaybackService.this.updateMediaSessionMetadata(p); + public void reloadUI() { + sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, 0); + PlaybackService.this.updateMediaSessionMetadata(getPlayable()); } @Override @@ -672,7 +674,7 @@ public class PlaybackService extends Service { }; private void endPlayback(final Playable playable, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) { - Log.d(TAG, "Playback ended"); + Log.d(TAG, "Playback ended" + (switchingPlayers ? " from switching players": "")); if (playable == null) { Log.e(TAG, "Cannot end playback: media was null"); @@ -707,12 +709,12 @@ public class PlaybackService extends Service { if (isInQueue) { DBWriter.removeQueueItem(PlaybackService.this, item, true); } - } - // Delete episode if enabled - if (item.getFeed().getPreferences().getCurrentAutoDelete() && !shouldKeep) { - DBWriter.deleteFeedMediaOfItem(PlaybackService.this, media.getId()); - Log.d(TAG, "Episode Deleted"); + // Delete episode if enabled + if (item.getFeed().getPreferences().getCurrentAutoDelete()) { + DBWriter.deleteFeedMediaOfItem(PlaybackService.this, media.getId()); + Log.d(TAG, "Episode Deleted"); + } } } @@ -904,11 +906,6 @@ public class PlaybackService extends Service { } /** - * Used by setupNotification to load notification data in another thread. - */ - private Thread notificationSetupThread; - - /** * Updates the Media Session for the corresponding status. * @param playerStatus the current {@link PlayerStatus} */ @@ -957,38 +954,69 @@ public class PlaybackService extends Service { mediaSession.setPlaybackState(sessionState.build()); } - private void updateMediaSessionMetadata(Playable p) { + /** + * Used by updateMediaSessionMetadata to load notification data in another thread. + */ + private Thread mediaSessionSetupThread; + + private void updateMediaSessionMetadata(final Playable p) { if (p == null || mediaSession == null) { return; } - MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder(); - builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, p.getFeedTitle()); - builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, p.getEpisodeTitle()); - builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, p.getDuration()); - builder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, p.getEpisodeTitle()); - builder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, p.getFeedTitle()); - - if (p.getImageUri() != null && UserPreferences.setLockscreenBackground()) { - builder.putString(MediaMetadataCompat.METADATA_KEY_ART_URI, p.getImageUri().toString()); - try { - WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); - Display display = wm.getDefaultDisplay(); - Bitmap art = Glide.with(this) - .load(p.getImageUri()) - .asBitmap() - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .centerCrop() - .into(display.getWidth(), display.getHeight()) - .get(); - builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, art); - } catch (Throwable tr) { - Log.e(TAG, Log.getStackTraceString(tr)); - } + if (mediaSessionSetupThread != null) { + mediaSessionSetupThread.interrupt(); } - mediaSession.setMetadata(builder.build()); + + Runnable mediaSessionSetupTask = () -> { + MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder(); + builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, p.getFeedTitle()); + builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, p.getEpisodeTitle()); + builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, p.getDuration()); + builder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, p.getEpisodeTitle()); + builder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, p.getFeedTitle()); + + if (p.getImageUri() != null && UserPreferences.setLockscreenBackground()) { + builder.putString(MediaMetadataCompat.METADATA_KEY_ART_URI, p.getImageUri().toString()); + try { + if (isCasting) { + Bitmap art = Glide.with(this) + .load(p.getImageUri()) + .asBitmap() + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) + .get(); + builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, art); + } else { + WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); + Display display = wm.getDefaultDisplay(); + Bitmap art = Glide.with(this) + .load(p.getImageUri()) + .asBitmap() + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .centerCrop() + .into(display.getWidth(), display.getHeight()) + .get(); + builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, art); + } + } catch (Throwable tr) { + Log.e(TAG, Log.getStackTraceString(tr)); + } + } + if (!Thread.currentThread().isInterrupted() && started) { + mediaSession.setMetadata(builder.build()); + } + }; + + mediaSessionSetupThread = new Thread(mediaSessionSetupTask); + mediaSessionSetupThread.start(); } /** + * Used by setupNotification to load notification data in another thread. + */ + private Thread notificationSetupThread; + + /** * Prepares notification and starts the service in the foreground. */ private void setupNotification(final PlaybackServiceMediaPlayer.PSMPInfo info) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index 43ec260c4..bd870a85d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -321,7 +321,7 @@ public abstract class PlaybackServiceMediaPlayer { void onBufferingUpdate(int percent); - void updateMediaSessionMetadata(Playable p); + void reloadUI(); boolean onMediaPlayerInfo(int code); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java index e3474f55a..203633b3c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java @@ -7,6 +7,7 @@ import android.util.Log; import android.util.Pair; import android.view.SurfaceHolder; +import com.google.android.gms.cast.Cast; import com.google.android.gms.cast.CastStatusCodes; import com.google.android.gms.cast.MediaInfo; import com.google.android.gms.cast.MediaStatus; @@ -14,9 +15,6 @@ import com.google.android.libraries.cast.companionlibrary.cast.exceptions.CastEx import com.google.android.libraries.cast.companionlibrary.cast.exceptions.NoConnectionException; import com.google.android.libraries.cast.companionlibrary.cast.exceptions.TransientNetworkDisconnectionException; -import java.util.concurrent.LinkedBlockingDeque; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import de.danoeh.antennapod.core.cast.CastConsumer; @@ -46,8 +44,6 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { private final AtomicBoolean startWhenPrepared; - private final ThreadPoolExecutor executor; - public RemotePSMP(@NonNull Context context, @NonNull PSMPCallback callback) { super(context, callback); @@ -57,9 +53,6 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { startWhenPrepared = new AtomicBoolean(false); isBuffering = new AtomicBoolean(false); - executor = new ThreadPoolExecutor(1, 1, 5, TimeUnit.MINUTES, new LinkedBlockingDeque<>(), - (r, executor) -> Log.d(TAG, "Rejected execution of runnable")); - try { if (castMgr.isConnected() && castMgr.isRemoteMediaLoaded()) { // updates the state, but does not start playing new media if it was going to @@ -107,6 +100,26 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { Log.d(TAG, "onMediaLoadResult called, but Player Status wasn't in preparing state, so we ignore the result"); } } + + @Override + public void onApplicationStatusChanged(String appStatus) { + if (playerStatus != PlayerStatus.PLAYING) { + Log.d(TAG, "onApplicationStatusChanged, but no media was playing"); + return; + } + boolean playbackEnded = false; + try { + int standbyState = castMgr.getApplicationStandbyState(); + Log.d(TAG, "standbyState: " + standbyState); + playbackEnded = standbyState == Cast.STANDBY_STATE_YES; + } catch (IllegalStateException e) { + Log.d(TAG, "unable to get standbyState on onApplicationStatusChanged()"); + } + if (playbackEnded) { + setPlayerStatus(PlayerStatus.INDETERMINATE, media); + callback.endPlayback(media, true, false, false); + } + } }; private void setBuffering(boolean buffering) { @@ -147,13 +160,14 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { MediaStatus status = castMgr.getMediaStatus(); if (status == null) { Log.d(TAG, "Received null MediaStatus"); - setBuffering(false); - setPlayerStatus(PlayerStatus.INDETERMINATE, null); + //setBuffering(false); + //setPlayerStatus(PlayerStatus.INDETERMINATE, null); return; } else { Log.d(TAG, "Received remote status/media update. New state=" + status.getPlayerState()); } Playable currentMedia = localVersion(status.getMediaInfo()); + boolean updateUI = currentMedia != media; if (currentMedia != null) { long position = status.getStreamPosition(); if (position > 0 && currentMedia.getPosition() == 0) { @@ -176,10 +190,20 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { int reason = status.getIdleReason(); switch (reason) { case MediaStatus.IDLE_REASON_CANCELED: - setPlayerStatus(PlayerStatus.STOPPED, currentMedia); + // check if we're already loading something else + if (!updateUI || media == null) { + setPlayerStatus(PlayerStatus.STOPPED, currentMedia); + } else { + updateUI = false; + } break; case MediaStatus.IDLE_REASON_INTERRUPTED: - setPlayerStatus(PlayerStatus.PREPARING, currentMedia); + // check if we're already loading something else + if (!updateUI || media == null) { + setPlayerStatus(PlayerStatus.PREPARING, currentMedia); + } else { + updateUI = false; + } break; case MediaStatus.IDLE_REASON_NONE: setPlayerStatus(PlayerStatus.INITIALIZED, currentMedia); @@ -188,11 +212,15 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { boolean playing = playerStatus == PlayerStatus.PLAYING; setPlayerStatus(PlayerStatus.INDETERMINATE, currentMedia); endPlaybackCall.endPlayback(currentMedia,playing, false, false); + // endPlayback already updates the UI, so no need to trigger it ourselves + updateUI = false; break; case MediaStatus.IDLE_REASON_ERROR: Log.w(TAG, "Got an error status from the Chromecast. Skipping, if possible, to the next episode..."); setPlayerStatus(PlayerStatus.INDETERMINATE, currentMedia); endPlaybackCall.endPlayback(currentMedia, startWhenPrepared.get(), true, false); + // endPlayback already updates the UI, so no need to trigger it ourselves + updateUI = false; } break; case MediaStatus.PLAYER_STATE_UNKNOWN: @@ -203,6 +231,9 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { Log.e(TAG, "Remote media state undetermined!"); setPlayerStatus(PlayerStatus.INDETERMINATE, currentMedia); } + if (updateUI) { + callback.reloadUI(); + } } @Override @@ -257,7 +288,7 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { setPlayerStatus(PlayerStatus.INITIALIZING, media); try { media.loadMetadata(); - executor.execute(() -> callback.updateMediaSessionMetadata(media)); + callback.reloadUI(); setPlayerStatus(PlayerStatus.INITIALIZED, media); if (prepareImmediately) { prepare(); @@ -471,13 +502,11 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { @Override public void shutdown() { castMgr.removeCastConsumer(castConsumer); - executor.shutdown(); } @Override public void shutdownQuietly() { - executor.execute(this::shutdown); - executor.shutdown(); + shutdown(); } @Override @@ -512,6 +541,18 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer { public void endPlayback(boolean wasSkipped, boolean switchingPlayers) { Log.d(TAG, "endPlayback() called"); boolean isPlaying = playerStatus == PlayerStatus.PLAYING; + try { + isPlaying = castMgr.isRemoteMediaPlaying(); + } catch (TransientNetworkDisconnectionException | NoConnectionException e) { + Log.e(TAG, "Could not determine if media is playing", e); + } + if (wasSkipped) { + try { + castMgr.stop(); + } catch (CastException | TransientNetworkDisconnectionException | NoConnectionException e) { + Log.e(TAG, "Could not stop remote playback when skipping", e); + } + } if (playerStatus != PlayerStatus.INDETERMINATE) { setPlayerStatus(PlayerStatus.INDETERMINATE, media); } |