diff options
5 files changed, 87 insertions, 48 deletions
diff --git a/core/src/free/java/de/danoeh/antennapod/core/service/playback/WearMediaSession.java b/core/src/free/java/de/danoeh/antennapod/core/service/playback/WearMediaSession.java index 373b24bc8..5998a1e2f 100644 --- a/core/src/free/java/de/danoeh/antennapod/core/service/playback/WearMediaSession.java +++ b/core/src/free/java/de/danoeh/antennapod/core/service/playback/WearMediaSession.java @@ -4,8 +4,10 @@ import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.PlaybackStateCompat; class WearMediaSession { - static void sessionStateAddActionForWear(PlaybackStateCompat.Builder sessionState, String actionName, - CharSequence name, int icon) { + /** + * Take a custom action builder and add no extras, because this is not the Play version of the app. + */ + static void addWearExtrasToAction(PlaybackStateCompat.CustomAction.Builder actionBuilder) { // no-op } 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 344421cd8..50517c303 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 @@ -57,6 +57,7 @@ import de.danoeh.antennapod.playback.base.PlaybackServiceMediaPlayer; import de.danoeh.antennapod.playback.base.PlayerStatus; import de.danoeh.antennapod.playback.cast.CastPsmp; import de.danoeh.antennapod.playback.cast.CastStateListener; +import de.danoeh.antennapod.storage.preferences.UserPreferences; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; @@ -74,7 +75,6 @@ import de.danoeh.antennapod.event.settings.SpeedPresetChangedEvent; import de.danoeh.antennapod.event.settings.VolumeAdaptionChangedEvent; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; -import de.danoeh.antennapod.storage.preferences.UserPreferences; import de.danoeh.antennapod.core.receiver.MediaButtonReceiver; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; @@ -115,10 +115,13 @@ public class PlaybackService extends MediaBrowserServiceCompat { private static final String AVRCP_ACTION_META_CHANGED = "com.android.music.metachanged"; /** - * Custom action used by Android Wear, Android Auto + * Custom actions used by Android Wear, Android Auto, and Android (API 33+ only) */ + private static final String CUSTOM_ACTION_SKIP_TO_NEXT = "action.de.danoeh.antennapod.core.service.skipToNext"; private static final String CUSTOM_ACTION_FAST_FORWARD = "action.de.danoeh.antennapod.core.service.fastForward"; private static final String CUSTOM_ACTION_REWIND = "action.de.danoeh.antennapod.core.service.rewind"; + private static final String CUSTOM_ACTION_CHANGE_PLAYBACK_SPEED = + "action.de.danoeh.antennapod.core.service.changePlaybackSpeed"; /** * Set a max number of episodes to load for Android Auto, otherwise there could be performance issues @@ -1173,45 +1176,52 @@ public class PlaybackService extends MediaBrowserServiceCompat { } else { state = PlaybackStateCompat.STATE_NONE; } + sessionState.setState(state, getCurrentPosition(), getCurrentPlaybackSpeed()); - long capabilities = PlaybackStateCompat.ACTION_PLAY_PAUSE + long capabilities = PlaybackStateCompat.ACTION_PLAY + | PlaybackStateCompat.ACTION_PLAY_PAUSE | PlaybackStateCompat.ACTION_REWIND | PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_FAST_FORWARD - | PlaybackStateCompat.ACTION_SKIP_TO_NEXT | PlaybackStateCompat.ACTION_SEEK_TO | PlaybackStateCompat.ACTION_SET_PLAYBACK_SPEED; - UiModeManager uiModeManager = (UiModeManager) getApplicationContext() - .getSystemService(Context.UI_MODE_SERVICE); - if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR) { - sessionState.addCustomAction( + sessionState.setActions(capabilities); + + // On Android Auto, custom actions are added in the following order around the play button, if no default + // actions are present: Near left, near right, far left, far right, additional actions panel + PlaybackStateCompat.CustomAction.Builder rewindBuilder = new PlaybackStateCompat.CustomAction.Builder( + CUSTOM_ACTION_REWIND, + getString(R.string.rewind_label), + R.drawable.ic_notification_fast_rewind + ); + WearMediaSession.addWearExtrasToAction(rewindBuilder); + sessionState.addCustomAction(rewindBuilder.build()); + + PlaybackStateCompat.CustomAction.Builder fastForwardBuilder = new PlaybackStateCompat.CustomAction.Builder( + CUSTOM_ACTION_FAST_FORWARD, + getString(R.string.fast_forward_label), + R.drawable.ic_notification_fast_forward + ); + WearMediaSession.addWearExtrasToAction(fastForwardBuilder); + sessionState.addCustomAction(fastForwardBuilder.build()); + + sessionState.addCustomAction( new PlaybackStateCompat.CustomAction.Builder( - CUSTOM_ACTION_REWIND, - getString(R.string.rewind_label), R.drawable.ic_notification_fast_rewind) - .build()); - sessionState.addCustomAction( + CUSTOM_ACTION_CHANGE_PLAYBACK_SPEED, + getString(R.string.playback_speed), + R.drawable.ic_notification_playback_speed + ).build() + ); + sessionState.addCustomAction( new PlaybackStateCompat.CustomAction.Builder( - CUSTOM_ACTION_FAST_FORWARD, - getString(R.string.fast_forward_label), R.drawable.ic_notification_fast_forward) - .build()); - } else { - // This would give the PIP of videos a play button - capabilities = capabilities | PlaybackStateCompat.ACTION_PLAY; - if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_WATCH) { - WearMediaSession.sessionStateAddActionForWear(sessionState, - CUSTOM_ACTION_REWIND, - getString(R.string.rewind_label), - android.R.drawable.ic_media_rew); - WearMediaSession.sessionStateAddActionForWear(sessionState, - CUSTOM_ACTION_FAST_FORWARD, - getString(R.string.fast_forward_label), - android.R.drawable.ic_media_ff); - WearMediaSession.mediaSessionSetExtraForWear(mediaSession); - } - } + CUSTOM_ACTION_SKIP_TO_NEXT, + getString(R.string.skip_episode_label), + R.drawable.ic_notification_skip + ).build() + ); - sessionState.setActions(capabilities); + WearMediaSession.mediaSessionSetExtraForWear(mediaSession); mediaSession.setPlaybackState(sessionState.build()); } @@ -1548,6 +1558,13 @@ public class PlaybackService extends MediaBrowserServiceCompat { } public void setSpeed(float speed) { + PlaybackPreferences.setCurrentlyPlayingTemporaryPlaybackSpeed(speed); + if (currentMediaType == MediaType.VIDEO) { + UserPreferences.setVideoPlaybackSpeed(speed); + } else { + UserPreferences.setPlaybackSpeed(speed); + } + mediaPlayer.setPlaybackParams(speed, UserPreferences.isSkipSilence()); } @@ -1787,6 +1804,26 @@ public class PlaybackService extends MediaBrowserServiceCompat { onFastForward(); } else if (CUSTOM_ACTION_REWIND.equals(action)) { onRewind(); + } else if (CUSTOM_ACTION_SKIP_TO_NEXT.equals(action)) { + mediaPlayer.skip(); + } else if (CUSTOM_ACTION_CHANGE_PLAYBACK_SPEED.equals(action)) { + List<Float> selectedSpeeds = UserPreferences.getPlaybackSpeedArray(); + + // If the list has zero or one element, there's nothing we can do to change the playback speed. + if (selectedSpeeds.size() > 1) { + int speedPosition = selectedSpeeds.indexOf(mediaPlayer.getPlaybackSpeed()); + float newSpeed; + + if (speedPosition == selectedSpeeds.size() - 1) { + // This is the last element. Wrap instead of going over the size of the list. + newSpeed = selectedSpeeds.get(0); + } else { + // If speedPosition is still -1 (the user isn't using a preset), use the first preset in the + // list. + newSpeed = selectedSpeeds.get(speedPosition + 1); + } + onSetPlaybackSpeed(newSpeed); + } } } }; diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java index 7a0fcdc4c..c3b103501 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java @@ -399,13 +399,6 @@ public abstract class PlaybackController { } public void setPlaybackSpeed(float speed) { - PlaybackPreferences.setCurrentlyPlayingTemporaryPlaybackSpeed(speed); - if (getMedia() != null && getMedia().getMediaType() == MediaType.VIDEO) { - UserPreferences.setVideoPlaybackSpeed(speed); - } else { - UserPreferences.setPlaybackSpeed(speed); - } - if (playbackService != null) { playbackService.setSpeed(speed); } else { diff --git a/core/src/play/java/de/danoeh/antennapod/core/service/playback/WearMediaSession.java b/core/src/play/java/de/danoeh/antennapod/core/service/playback/WearMediaSession.java index 8df05d10d..47881da0b 100644 --- a/core/src/play/java/de/danoeh/antennapod/core/service/playback/WearMediaSession.java +++ b/core/src/play/java/de/danoeh/antennapod/core/service/playback/WearMediaSession.java @@ -6,21 +6,20 @@ import android.support.v4.media.session.PlaybackStateCompat; import android.support.wearable.media.MediaControlConstants; public class WearMediaSession { - static void sessionStateAddActionForWear(PlaybackStateCompat.Builder sessionState, String actionName, - CharSequence name, int icon) { - PlaybackStateCompat.CustomAction.Builder actionBuilder = - new PlaybackStateCompat.CustomAction.Builder(actionName, name, icon); + /** + * Take a custom action builder and make sure the custom action shows on Wear OS because this is the Play version + * of the app. + */ + static void addWearExtrasToAction(PlaybackStateCompat.CustomAction.Builder actionBuilder) { Bundle actionExtras = new Bundle(); actionExtras.putBoolean(MediaControlConstants.EXTRA_CUSTOM_ACTION_SHOW_ON_WEAR, true); actionBuilder.setExtras(actionExtras); - - sessionState.addCustomAction(actionBuilder.build()); } static void mediaSessionSetExtraForWear(MediaSessionCompat mediaSession) { Bundle sessionExtras = new Bundle(); - sessionExtras.putBoolean(MediaControlConstants.EXTRA_RESERVE_SLOT_SKIP_TO_PREVIOUS, true); - sessionExtras.putBoolean(MediaControlConstants.EXTRA_RESERVE_SLOT_SKIP_TO_NEXT, true); + sessionExtras.putBoolean(MediaControlConstants.EXTRA_RESERVE_SLOT_SKIP_TO_PREVIOUS, false); + sessionExtras.putBoolean(MediaControlConstants.EXTRA_RESERVE_SLOT_SKIP_TO_NEXT, false); mediaSession.setExtras(sessionExtras); } } diff --git a/ui/png-icons/src/main/res/drawable/ic_notification_playback_speed.xml b/ui/png-icons/src/main/res/drawable/ic_notification_playback_speed.xml new file mode 100644 index 000000000..5aad5031a --- /dev/null +++ b/ui/png-icons/src/main/res/drawable/ic_notification_playback_speed.xml @@ -0,0 +1,8 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:height="30dp" + android:viewportHeight="24.0" + android:viewportWidth="24.0" + android:width="30dp"> + + <path android:fillColor="#ffffff" android:pathData="M 12 15.98 A 2.98 2.98 0 0 1 9.02 12.99 c 0 -1.11 0.61 -2.09 1.49 -2.6 L 20.17 4.81 L 14.67 14.34 C 14.17 15.31 13.16 15.98 12 15.98 M 12 3.05 c 1.8 0 3.48 0.5 4.94 1.31 l -2.09 1.2 C 13.99 5.22 12.99 5.04 12 5.04 a 7.96 7.96 0 0 0 -7.96 7.96 c 0 2.2 0.89 4.19 2.33 5.62 h 0.01 c 0.39 0.39 0.39 1.01 0 1.4 c -0.39 0.39 -1.02 0.39 -1.41 0.01 v 0 C 3.17 18.22 2.05 15.74 2.05 12.99 A 9.95 9.95 0 0 1 12 3.05 m 9.95 9.95 c 0 2.75 -1.11 5.23 -2.91 7.03 v 0 c -0.39 0.38 -1.01 0.38 -1.4 -0.01 c -0.39 -0.39 -0.39 -1.01 0 -1.4 v 0 c 1.44 -1.44 2.33 -3.42 2.33 -5.62 c 0 -0.99 -0.19 -1.99 -0.54 -2.88 L 20.62 8.02 c 0.83 1.49 1.32 3.16 1.32 4.97 z" /> +</vector> |