Allow remapping hardware buttons (#4881)

This commit is contained in:
Tim Schumacher 2021-02-03 12:50:01 +01:00 committed by GitHub
parent 4ff6ff4fb7
commit 1297a16850
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 85 additions and 44 deletions

View File

@ -2,6 +2,7 @@ package de.danoeh.antennapod.preferences;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.view.KeyEvent;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import de.danoeh.antennapod.BuildConfig; import de.danoeh.antennapod.BuildConfig;
@ -92,5 +93,16 @@ public class PreferenceUpgrader {
if (oldVersion < 1080100) { if (oldVersion < 1080100) {
prefs.edit().putString(UserPreferences.PREF_VIDEO_BEHAVIOR, "pip").apply(); prefs.edit().putString(UserPreferences.PREF_VIDEO_BEHAVIOR, "pip").apply();
} }
if (oldVersion < 2010300) {
// Migrate hardware button preferences
if (prefs.getBoolean("prefHardwareForwardButtonSkips", false)) {
prefs.edit().putString(UserPreferences.PREF_HARDWARE_FORWARD_BUTTON,
String.valueOf(KeyEvent.KEYCODE_MEDIA_NEXT)).apply();
}
if (prefs.getBoolean("prefHardwarePreviousButtonRestarts", false)) {
prefs.edit().putString(UserPreferences.PREF_HARDWARE_PREVIOUS_BUTTON,
String.valueOf(KeyEvent.KEYCODE_MEDIA_PREVIOUS)).apply();
}
}
} }
} }

View File

@ -44,18 +44,6 @@
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory android:title="@string/playback_control"> <PreferenceCategory android:title="@string/playback_control">
<SwitchPreferenceCompat
android:defaultValue="false"
android:enabled="true"
android:key="prefHardwareForwardButtonSkips"
android:summary="@string/pref_hardwareForwardButtonSkips_sum"
android:title="@string/pref_hardwareForwardButtonSkips_title"/>
<SwitchPreferenceCompat
android:defaultValue="false"
android:enabled="true"
android:key="prefHardwarePreviousButtonRestarts"
android:summary="@string/pref_hardwarePreviousButtonRestarts_sum"
android:title="@string/pref_hardwarePreviousButtonRestarts_title"/>
<Preference <Preference
android:key="prefPlaybackFastForwardDeltaLauncher" android:key="prefPlaybackFastForwardDeltaLauncher"
android:summary="@string/pref_fast_forward_sum" android:summary="@string/pref_fast_forward_sum"
@ -80,6 +68,23 @@
android:title="@string/pref_stream_over_download_title"/> android:title="@string/pref_stream_over_download_title"/>
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory android:title="@string/reassign_hardware_buttons">
<ListPreference
android:defaultValue="@string/keycode_media_fast_forward"
android:entries="@array/button_action_options"
android:entryValues="@array/button_action_values"
android:key="prefHardwareForwardButton"
android:title="@string/pref_hardware_forward_button_title"
android:summary="@string/pref_hardware_forward_button_summary"/>
<ListPreference
android:defaultValue="@string/keycode_media_rewind"
android:entries="@array/button_action_options"
android:entryValues="@array/button_action_values"
android:key="prefHardwarePreviousButton"
android:title="@string/pref_hardware_previous_button_title"
android:summary="@string/pref_hardware_previous_button_summary"/>
</PreferenceCategory>
<PreferenceCategory android:title="@string/queue_label"> <PreferenceCategory android:title="@string/queue_label">
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:defaultValue="true" android:defaultValue="true"

View File

@ -6,6 +6,7 @@ import android.content.res.Configuration;
import android.os.Build; import android.os.Build;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.KeyEvent;
import androidx.annotation.IntRange; import androidx.annotation.IntRange;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -76,8 +77,8 @@ public class UserPreferences {
public static final String PREF_PAUSE_ON_HEADSET_DISCONNECT = "prefPauseOnHeadsetDisconnect"; public static final String PREF_PAUSE_ON_HEADSET_DISCONNECT = "prefPauseOnHeadsetDisconnect";
public static final String PREF_UNPAUSE_ON_HEADSET_RECONNECT = "prefUnpauseOnHeadsetReconnect"; public static final String PREF_UNPAUSE_ON_HEADSET_RECONNECT = "prefUnpauseOnHeadsetReconnect";
private static final String PREF_UNPAUSE_ON_BLUETOOTH_RECONNECT = "prefUnpauseOnBluetoothReconnect"; private static final String PREF_UNPAUSE_ON_BLUETOOTH_RECONNECT = "prefUnpauseOnBluetoothReconnect";
private static final String PREF_HARDWARE_FOWARD_BUTTON_SKIPS = "prefHardwareForwardButtonSkips"; public static final String PREF_HARDWARE_FORWARD_BUTTON = "prefHardwareForwardButton";
private static final String PREF_HARDWARE_PREVIOUS_BUTTON_RESTARTS = "prefHardwarePreviousButtonRestarts"; public static final String PREF_HARDWARE_PREVIOUS_BUTTON = "prefHardwarePreviousButton";
public static final String PREF_FOLLOW_QUEUE = "prefFollowQueue"; public static final String PREF_FOLLOW_QUEUE = "prefFollowQueue";
public static final String PREF_SKIP_KEEPS_EPISODE = "prefSkipKeepsEpisode"; public static final String PREF_SKIP_KEEPS_EPISODE = "prefSkipKeepsEpisode";
private static final String PREF_FAVORITE_KEEPS_EPISODE = "prefFavoriteKeepsEpisode"; private static final String PREF_FAVORITE_KEEPS_EPISODE = "prefFavoriteKeepsEpisode";
@ -373,12 +374,14 @@ public class UserPreferences {
return prefs.getBoolean(PREF_UNPAUSE_ON_BLUETOOTH_RECONNECT, false); return prefs.getBoolean(PREF_UNPAUSE_ON_BLUETOOTH_RECONNECT, false);
} }
public static boolean shouldHardwareButtonSkip() { public static int getHardwareForwardButton() {
return prefs.getBoolean(PREF_HARDWARE_FOWARD_BUTTON_SKIPS, false); return Integer.parseInt(prefs.getString(PREF_HARDWARE_FORWARD_BUTTON,
String.valueOf(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD)));
} }
public static boolean shouldHardwarePreviousButtonRestart() { public static int getHardwarePreviousButton() {
return prefs.getBoolean(PREF_HARDWARE_PREVIOUS_BUTTON_RESTARTS, false); return Integer.parseInt(prefs.getString(PREF_HARDWARE_PREVIOUS_BUTTON,
String.valueOf(KeyEvent.KEYCODE_MEDIA_REWIND)));
} }

View File

@ -668,18 +668,14 @@ public class PlaybackService extends MediaBrowserServiceCompat {
} }
return false; return false;
case KeyEvent.KEYCODE_MEDIA_NEXT: case KeyEvent.KEYCODE_MEDIA_NEXT:
if (getStatus() != PlayerStatus.PLAYING && getStatus() != PlayerStatus.PAUSED) { if (!notificationButton) {
return false; // Handle remapped button as notification button which is not remapped again.
} else if (notificationButton || UserPreferences.shouldHardwareButtonSkip()) { return handleKeycode(UserPreferences.getHardwareForwardButton(), true);
// assume the skip command comes from a notification or the lockscreen } else if (getStatus() == PlayerStatus.PLAYING || getStatus() == PlayerStatus.PAUSED) {
// a >| skip button should actually skip
mediaPlayer.skip(); mediaPlayer.skip();
} else {
// assume skip command comes from a (bluetooth) media button
// user actually wants to fast-forward
seekDelta(UserPreferences.getFastForwardSecs() * 1000);
}
return true; return true;
}
return false;
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
if (getStatus() == PlayerStatus.PLAYING || getStatus() == PlayerStatus.PAUSED) { if (getStatus() == PlayerStatus.PLAYING || getStatus() == PlayerStatus.PAUSED) {
mediaPlayer.seekDelta(UserPreferences.getFastForwardSecs() * 1000); mediaPlayer.seekDelta(UserPreferences.getFastForwardSecs() * 1000);
@ -687,23 +683,20 @@ public class PlaybackService extends MediaBrowserServiceCompat {
} }
return false; return false;
case KeyEvent.KEYCODE_MEDIA_PREVIOUS: case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
if (getStatus() != PlayerStatus.PLAYING && getStatus() != PlayerStatus.PAUSED) { if (!notificationButton) {
return false; // Handle remapped button as notification button which is not remapped again.
} else if (UserPreferences.shouldHardwarePreviousButtonRestart()) { return handleKeycode(UserPreferences.getHardwarePreviousButton(), true);
// user wants to restart current episode } else if (getStatus() == PlayerStatus.PLAYING || getStatus() == PlayerStatus.PAUSED) {
mediaPlayer.seekTo(0); mediaPlayer.seekTo(0);
} else {
// user wants to rewind current episode
mediaPlayer.seekDelta(-UserPreferences.getRewindSecs() * 1000);
}
return true; return true;
}
return false;
case KeyEvent.KEYCODE_MEDIA_REWIND: case KeyEvent.KEYCODE_MEDIA_REWIND:
if (getStatus() == PlayerStatus.PLAYING || getStatus() == PlayerStatus.PAUSED) { if (getStatus() == PlayerStatus.PLAYING || getStatus() == PlayerStatus.PAUSED) {
mediaPlayer.seekDelta(-UserPreferences.getRewindSecs() * 1000); mediaPlayer.seekDelta(-UserPreferences.getRewindSecs() * 1000);
} else {
return false;
}
return true; return true;
}
return false;
case KeyEvent.KEYCODE_MEDIA_STOP: case KeyEvent.KEYCODE_MEDIA_STOP:
if (status == PlayerStatus.PLAYING) { if (status == PlayerStatus.PLAYING) {
mediaPlayer.pause(true, true); mediaPlayer.pause(true, true);
@ -1911,7 +1904,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
Log.d(TAG, "onSkipToNext()"); Log.d(TAG, "onSkipToNext()");
UiModeManager uiModeManager = (UiModeManager) getApplicationContext() UiModeManager uiModeManager = (UiModeManager) getApplicationContext()
.getSystemService(Context.UI_MODE_SERVICE); .getSystemService(Context.UI_MODE_SERVICE);
if (UserPreferences.shouldHardwareButtonSkip() if (UserPreferences.getHardwareForwardButton() == KeyEvent.KEYCODE_MEDIA_NEXT
|| uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR) { || uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR) {
mediaPlayer.skip(); mediaPlayer.skip();
} else { } else {

View File

@ -105,6 +105,20 @@
<item>@string/episode_cleanup_never</item> <item>@string/episode_cleanup_never</item>
</string-array> </string-array>
<string-array name="button_action_options">
<item>@string/button_action_fast_forward</item>
<item>@string/button_action_rewind</item>
<item>@string/button_action_skip_episode</item>
<item>@string/button_action_restart_episode</item>
</string-array>
<string-array name="button_action_values">
<item>@string/keycode_media_fast_forward</item>
<item>@string/keycode_media_rewind</item>
<item>@string/keycode_media_next</item>
<item>@string/keycode_media_previous</item>
</string-array>
<string-array name="enqueue_location_options"> <string-array name="enqueue_location_options">
<item>@string/enqueue_location_back</item> <item>@string/enqueue_location_back</item>
<item>@string/enqueue_location_front</item> <item>@string/enqueue_location_front</item>

View File

@ -0,0 +1,9 @@
<resources
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="MissingTranslation">
<string name="keycode_media_next">87</string>
<string name="keycode_media_previous">88</string>
<string name="keycode_media_rewind">89</string>
<string name="keycode_media_fast_forward">90</string>
</resources>

View File

@ -381,6 +381,7 @@
<string name="external_elements">External elements</string> <string name="external_elements">External elements</string>
<string name="interruptions">Interruptions</string> <string name="interruptions">Interruptions</string>
<string name="playback_control">Playback control</string> <string name="playback_control">Playback control</string>
<string name="reassign_hardware_buttons">Reassign hardware buttons</string>
<string name="preference_search_hint">Search…</string> <string name="preference_search_hint">Search…</string>
<string name="preference_search_no_results">No results</string> <string name="preference_search_no_results">No results</string>
<string name="preference_search_clear_history">Clear history</string> <string name="preference_search_clear_history">Clear history</string>
@ -390,10 +391,14 @@
<string name="pref_pauseOnDisconnect_sum">Pause playback when headphones or bluetooth are disconnected</string> <string name="pref_pauseOnDisconnect_sum">Pause playback when headphones or bluetooth are disconnected</string>
<string name="pref_unpauseOnHeadsetReconnect_sum">Resume playback when the headphones are reconnected</string> <string name="pref_unpauseOnHeadsetReconnect_sum">Resume playback when the headphones are reconnected</string>
<string name="pref_unpauseOnBluetoothReconnect_sum">Resume playback when bluetooth reconnects</string> <string name="pref_unpauseOnBluetoothReconnect_sum">Resume playback when bluetooth reconnects</string>
<string name="pref_hardwareForwardButtonSkips_title">Forward Button Skips</string> <string name="pref_hardware_forward_button_title">Forward Button</string>
<string name="pref_hardwareForwardButtonSkips_sum">When pressing a forward button on a bluetooth-connected device skip to the next episode instead of fast-forwarding</string> <string name="pref_hardware_forward_button_summary">Customize the forward button behavior</string>
<string name="pref_hardwarePreviousButtonRestarts_title">Previous button restarts</string> <string name="pref_hardware_previous_button_title">Previous Button</string>
<string name="pref_hardwarePreviousButtonRestarts_sum">When pressing a hardware previous button restart playing the current episode instead of rewinding</string> <string name="pref_hardware_previous_button_summary">Customize the previous button behavior</string>
<string name="button_action_fast_forward">Fast Forward</string>
<string name="button_action_rewind">Rewind</string>
<string name="button_action_skip_episode">Skip Episode</string>
<string name="button_action_restart_episode">Restart Episode</string>
<string name="pref_followQueue_sum">Jump to next queue item when playback completes</string> <string name="pref_followQueue_sum">Jump to next queue item when playback completes</string>
<string name="pref_auto_delete_sum">Delete episode when playback completes</string> <string name="pref_auto_delete_sum">Delete episode when playback completes</string>
<string name="pref_auto_delete_title">Auto Delete</string> <string name="pref_auto_delete_title">Auto Delete</string>