Add back skip buttons and more custom actions on Android Auto (#6050)

This commit is contained in:
Andrew Booze 2023-02-24 10:10:44 -06:00 committed by GitHub
parent 7753c500db
commit 59253db2e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 89 additions and 50 deletions

View File

@ -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
}

View File

@ -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,46 +1176,53 @@ 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(
new PlaybackStateCompat.CustomAction.Builder(
CUSTOM_ACTION_REWIND,
getString(R.string.rewind_label), R.drawable.ic_notification_fast_rewind)
.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);
}
}
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_CHANGE_PLAYBACK_SPEED,
getString(R.string.playback_speed),
R.drawable.ic_notification_playback_speed
).build()
);
sessionState.addCustomAction(
new PlaybackStateCompat.CustomAction.Builder(
CUSTOM_ACTION_SKIP_TO_NEXT,
getString(R.string.skip_episode_label),
R.drawable.ic_notification_skip
).build()
);
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);
}
}
}
};

View File

@ -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 {

View File

@ -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);
}
}

View File

@ -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>