Add next chapter button to notification (#6276)
This commit is contained in:
parent
f0e96a2692
commit
0f5600932d
@ -3,6 +3,7 @@ package de.test.antennapod.ui;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.test.filters.LargeTest;
|
||||
@ -30,9 +31,7 @@ import static androidx.test.espresso.action.ViewActions.click;
|
||||
import static androidx.test.espresso.action.ViewActions.scrollTo;
|
||||
import static androidx.test.espresso.action.ViewActions.swipeDown;
|
||||
import static androidx.test.espresso.action.ViewActions.swipeUp;
|
||||
import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
|
||||
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.isChecked;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
||||
@ -40,7 +39,6 @@ import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||
import static de.test.antennapod.EspressoTestUtils.clickPreference;
|
||||
import static de.test.antennapod.EspressoTestUtils.waitForView;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@ -80,38 +78,22 @@ public class PreferencesTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetLockscreenButtons() {
|
||||
public void testSetNotificationButtons() {
|
||||
clickPreference(R.string.user_interface_label);
|
||||
String[] buttons = res.getStringArray(R.array.compact_notification_buttons_options);
|
||||
clickPreference(R.string.pref_compact_notification_buttons_title);
|
||||
String[] buttons = res.getStringArray(R.array.full_notification_buttons_options);
|
||||
clickPreference(R.string.pref_full_notification_buttons_title);
|
||||
// First uncheck checkboxes
|
||||
onView(withText(buttons[0])).perform(click());
|
||||
onView(withText(buttons[1])).perform(click());
|
||||
|
||||
// Now try to check all checkboxes
|
||||
onView(withText(buttons[0])).perform(click());
|
||||
onView(withText(buttons[1])).perform(click());
|
||||
onView(withText(buttons[2])).perform(click());
|
||||
|
||||
// Make sure that the third checkbox is unchecked
|
||||
onView(withText(buttons[2])).check(matches(not(isChecked())));
|
||||
|
||||
String snackBarText = String.format(res.getString(
|
||||
R.string.pref_compact_notification_buttons_dialog_error), 2);
|
||||
Awaitility.await().ignoreExceptions().atMost(4000, MILLISECONDS)
|
||||
.until(() -> {
|
||||
onView(withText(snackBarText)).check(doesNotExist());
|
||||
return true;
|
||||
});
|
||||
|
||||
onView(withText(R.string.confirm_label)).perform(click());
|
||||
|
||||
Awaitility.await().atMost(1000, MILLISECONDS)
|
||||
.until(UserPreferences::showRewindOnCompactNotification);
|
||||
.until(() -> UserPreferences.showSkipOnFullNotification());
|
||||
Awaitility.await().atMost(1000, MILLISECONDS)
|
||||
.until(UserPreferences::showFastForwardOnCompactNotification);
|
||||
.until(() -> UserPreferences.showNextChapterOnFullNotification());
|
||||
Awaitility.await().atMost(1000, MILLISECONDS)
|
||||
.until(() -> !UserPreferences.showSkipOnCompactNotification());
|
||||
.until(() -> !UserPreferences.showPlaybackSpeedOnFullNotification());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1,8 +1,10 @@
|
||||
package de.danoeh.antennapod.fragment.preferences;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Button;
|
||||
import android.widget.ListView;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
@ -64,9 +66,9 @@ public class UserInterfacePreferencesFragment extends PreferenceFragmentCompat {
|
||||
return true;
|
||||
});
|
||||
|
||||
findPreference(UserPreferences.PREF_COMPACT_NOTIFICATION_BUTTONS)
|
||||
findPreference(UserPreferences.PREF_FULL_NOTIFICATION_BUTTONS)
|
||||
.setOnPreferenceClickListener(preference -> {
|
||||
showNotificationButtonsDialog();
|
||||
showFullNotificationButtonsDialog();
|
||||
return true;
|
||||
});
|
||||
findPreference(UserPreferences.PREF_FILTER_FEED)
|
||||
@ -91,48 +93,85 @@ public class UserInterfacePreferencesFragment extends PreferenceFragmentCompat {
|
||||
}
|
||||
}
|
||||
|
||||
private void showNotificationButtonsDialog() {
|
||||
|
||||
private void showFullNotificationButtonsDialog() {
|
||||
final Context context = getActivity();
|
||||
final List<Integer> preferredButtons = UserPreferences.getCompactNotificationButtons();
|
||||
|
||||
final List<Integer> preferredButtons = UserPreferences.getFullNotificationButtons();
|
||||
final String[] allButtonNames = context.getResources().getStringArray(
|
||||
R.array.compact_notification_buttons_options);
|
||||
R.array.full_notification_buttons_options);
|
||||
final int[] buttonIDs = {2, 3, 4};
|
||||
final int exactItems = 2;
|
||||
final DialogInterface.OnClickListener completeListener = (dialog, which) ->
|
||||
UserPreferences.setFullNotificationButtons(preferredButtons);
|
||||
final String title = context.getResources().getString(
|
||||
R.string.pref_full_notification_buttons_title);
|
||||
|
||||
showNotificationButtonsDialog(preferredButtons, allButtonNames, buttonIDs, title,
|
||||
exactItems, completeListener
|
||||
);
|
||||
}
|
||||
|
||||
private void showNotificationButtonsDialog(List<Integer> preferredButtons,
|
||||
String[] allButtonNames, int[] buttonIds, String title,
|
||||
int exactItems, DialogInterface.OnClickListener completeListener) {
|
||||
boolean[] checked = new boolean[allButtonNames.length]; // booleans default to false in java
|
||||
|
||||
final Context context = getActivity();
|
||||
|
||||
// Clear buttons that are not part of the setting anymore
|
||||
for (int i = preferredButtons.size() - 1; i >= 0; i--) {
|
||||
boolean isValid = false;
|
||||
for (int j = 0; j < checked.length; j++) {
|
||||
if (buttonIds[j] == preferredButtons.get(i)) {
|
||||
isValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isValid) {
|
||||
preferredButtons.remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i < checked.length; i++) {
|
||||
if(preferredButtons.contains(i)) {
|
||||
if (preferredButtons.contains(buttonIds[i])) {
|
||||
checked[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(context);
|
||||
builder.setTitle(String.format(context.getResources().getString(
|
||||
R.string.pref_compact_notification_buttons_dialog_title), 2));
|
||||
builder.setTitle(title);
|
||||
builder.setMultiChoiceItems(allButtonNames, checked, (dialog, which, isChecked) -> {
|
||||
checked[which] = isChecked;
|
||||
|
||||
if (isChecked) {
|
||||
if (preferredButtons.size() < 2) {
|
||||
preferredButtons.add(which);
|
||||
} else {
|
||||
// Only allow a maximum of two selections. This is because the notification
|
||||
// on the lock screen can only display 3 buttons, and the play/pause button
|
||||
// is always included.
|
||||
checked[which] = false;
|
||||
ListView selectionView = ((AlertDialog) dialog).getListView();
|
||||
selectionView.setItemChecked(which, false);
|
||||
Snackbar.make(
|
||||
selectionView,
|
||||
String.format(context.getResources().getString(
|
||||
R.string.pref_compact_notification_buttons_dialog_error), 2),
|
||||
Snackbar.LENGTH_SHORT).show();
|
||||
}
|
||||
preferredButtons.add(buttonIds[which]);
|
||||
} else {
|
||||
preferredButtons.remove((Integer) which);
|
||||
preferredButtons.remove((Integer) buttonIds[which]);
|
||||
}
|
||||
});
|
||||
builder.setPositiveButton(R.string.confirm_label, (dialog, which) ->
|
||||
UserPreferences.setCompactNotificationButtons(preferredButtons));
|
||||
builder.setPositiveButton(R.string.confirm_label, null);
|
||||
builder.setNegativeButton(R.string.cancel_label, null);
|
||||
builder.create().show();
|
||||
final AlertDialog dialog = builder.create();
|
||||
|
||||
dialog.show();
|
||||
|
||||
Button positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
||||
|
||||
positiveButton.setOnClickListener(v -> {
|
||||
if (preferredButtons.size() != exactItems) {
|
||||
ListView selectionView = dialog.getListView();
|
||||
Snackbar.make(
|
||||
selectionView,
|
||||
String.format(context.getResources().getString(
|
||||
R.string.pref_compact_notification_buttons_dialog_error_exact), exactItems),
|
||||
Snackbar.LENGTH_SHORT).show();
|
||||
|
||||
} else {
|
||||
completeListener.onClick(dialog, AlertDialog.BUTTON_POSITIVE);
|
||||
dialog.cancel();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -70,9 +70,9 @@
|
||||
android:summary="@string/pref_persistNotify_sum"
|
||||
android:title="@string/pref_persistNotify_title"/>
|
||||
<Preference
|
||||
android:key="prefCompactNotificationButtons"
|
||||
android:summary="@string/pref_compact_notification_buttons_sum"
|
||||
android:title="@string/pref_compact_notification_buttons_title"/>
|
||||
android:key="prefFullNotificationButtons"
|
||||
android:summary="@string/pref_full_notification_buttons_sum"
|
||||
android:title="@string/pref_full_notification_buttons_title"/>
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="@string/behavior">
|
||||
<de.danoeh.antennapod.preferences.MaterialListPreference
|
||||
|
@ -17,6 +17,8 @@ import de.danoeh.antennapod.core.ClientConfigurator;
|
||||
public class MediaButtonReceiver extends BroadcastReceiver {
|
||||
private static final String TAG = "MediaButtonReceiver";
|
||||
public static final String EXTRA_KEYCODE = "de.danoeh.antennapod.core.service.extra.MediaButtonReceiver.KEYCODE";
|
||||
public static final String EXTRA_CUSTOM_ACTION =
|
||||
"de.danoeh.antennapod.core.service.extra.MediaButtonReceiver.CUSTOM_ACTION";
|
||||
public static final String EXTRA_SOURCE = "de.danoeh.antennapod.core.service.extra.MediaButtonReceiver.SOURCE";
|
||||
public static final String EXTRA_HARDWAREBUTTON
|
||||
= "de.danoeh.antennapod.core.service.extra.MediaButtonReceiver.HARDWAREBUTTON";
|
||||
|
@ -47,6 +47,20 @@ import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.media.MediaBrowserServiceCompat;
|
||||
|
||||
import de.danoeh.antennapod.core.service.QuickSettingsTileService;
|
||||
import de.danoeh.antennapod.core.util.ChapterUtils;
|
||||
import de.danoeh.antennapod.core.util.playback.PlayableUtils;
|
||||
import de.danoeh.antennapod.event.playback.BufferUpdateEvent;
|
||||
import de.danoeh.antennapod.event.playback.PlaybackServiceEvent;
|
||||
import de.danoeh.antennapod.event.PlayerErrorEvent;
|
||||
import de.danoeh.antennapod.event.playback.SleepTimerUpdatedEvent;
|
||||
import de.danoeh.antennapod.model.feed.Chapter;
|
||||
import de.danoeh.antennapod.model.feed.FeedItemFilter;
|
||||
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 org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
@ -126,6 +140,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
|
||||
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";
|
||||
public static final String CUSTOM_ACTION_NEXT_CHAPTER = "action.de.danoeh.antennapod.core.service.next_chapter";
|
||||
|
||||
/**
|
||||
* Set a max number of episodes to load for Android Auto, otherwise there could be performance issues
|
||||
@ -482,9 +497,10 @@ public class PlaybackService extends MediaBrowserServiceCompat {
|
||||
notificationManager.cancel(R.id.notification_streaming_confirmation);
|
||||
|
||||
final int keycode = intent.getIntExtra(MediaButtonReceiver.EXTRA_KEYCODE, -1);
|
||||
final String customAction = intent.getStringExtra(MediaButtonReceiver.EXTRA_CUSTOM_ACTION);
|
||||
final boolean hardwareButton = intent.getBooleanExtra(MediaButtonReceiver.EXTRA_HARDWAREBUTTON, false);
|
||||
Playable playable = intent.getParcelableExtra(PlaybackServiceInterface.EXTRA_PLAYABLE);
|
||||
if (keycode == -1 && playable == null) {
|
||||
if (keycode == -1 && playable == null && customAction == null) {
|
||||
Log.e(TAG, "PlaybackService was started with no arguments");
|
||||
stateManager.stopService();
|
||||
return Service.START_NOT_STICKY;
|
||||
@ -508,7 +524,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
|
||||
stateManager.stopService();
|
||||
return Service.START_NOT_STICKY;
|
||||
}
|
||||
} else {
|
||||
} else if (playable != null) {
|
||||
stateManager.validStartCommandWasReceived();
|
||||
boolean allowStreamThisTime = intent.getBooleanExtra(
|
||||
PlaybackServiceInterface.EXTRA_ALLOW_STREAM_THIS_TIME, false);
|
||||
@ -536,6 +552,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
|
||||
stateManager.stopService();
|
||||
});
|
||||
return Service.START_NOT_STICKY;
|
||||
} else {
|
||||
mediaSession.getController().getTransportControls().sendCustomAction(customAction, null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -783,6 +801,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
|
||||
@Override
|
||||
public void onChapterLoaded(Playable media) {
|
||||
sendNotificationBroadcast(PlaybackServiceInterface.NOTIFICATION_TYPE_RELOAD, 0);
|
||||
updateMediaSession(mediaPlayer.getPlayerStatus());
|
||||
}
|
||||
};
|
||||
|
||||
@ -1250,20 +1269,35 @@ public class PlaybackService extends MediaBrowserServiceCompat {
|
||||
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
|
||||
if (UserPreferences.showPlaybackSpeedOnFullNotification()) {
|
||||
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(
|
||||
);
|
||||
}
|
||||
|
||||
if (UserPreferences.showNextChapterOnFullNotification()) {
|
||||
if (getPlayable() != null && getPlayable().getChapters() != null) {
|
||||
sessionState.addCustomAction(
|
||||
new PlaybackStateCompat.CustomAction.Builder(
|
||||
CUSTOM_ACTION_NEXT_CHAPTER,
|
||||
getString(R.string.next_chapter), R.drawable.ic_notification_next_chapter)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
if (UserPreferences.showSkipOnFullNotification()) {
|
||||
sessionState.addCustomAction(
|
||||
new PlaybackStateCompat.CustomAction.Builder(
|
||||
CUSTOM_ACTION_SKIP_TO_NEXT,
|
||||
getString(R.string.skip_episode_label),
|
||||
R.drawable.ic_notification_skip
|
||||
CUSTOM_ACTION_SKIP_TO_NEXT,
|
||||
getString(R.string.skip_episode_label),
|
||||
R.drawable.ic_notification_skip
|
||||
).build()
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
WearMediaSession.mediaSessionSetExtraForWear(mediaSession);
|
||||
|
||||
@ -1812,6 +1846,26 @@ public class PlaybackService extends MediaBrowserServiceCompat {
|
||||
seekDelta(-UserPreferences.getRewindSecs() * 1000);
|
||||
}
|
||||
|
||||
public void onNextChapter() {
|
||||
List<Chapter> chapters = mediaPlayer.getPlayable().getChapters();
|
||||
if (chapters == null) {
|
||||
// No chapters, just fallback to next episode
|
||||
mediaPlayer.skip();
|
||||
return;
|
||||
}
|
||||
|
||||
int nextChapter = ChapterUtils.getCurrentChapterIndex(
|
||||
mediaPlayer.getPlayable(), mediaPlayer.getPosition()) + 1;
|
||||
|
||||
if (chapters.size() < nextChapter + 1) {
|
||||
// We are on the last chapter, just fallback to the next episode
|
||||
mediaPlayer.skip();
|
||||
return;
|
||||
}
|
||||
|
||||
mediaPlayer.seekTo((int) chapters.get(nextChapter).getStart());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFastForward() {
|
||||
Log.d(TAG, "onFastForward()");
|
||||
@ -1884,6 +1938,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
|
||||
onRewind();
|
||||
} else if (CUSTOM_ACTION_SKIP_TO_NEXT.equals(action)) {
|
||||
mediaPlayer.skip();
|
||||
} else if (CUSTOM_ACTION_NEXT_CHAPTER.equals(action)) {
|
||||
onNextChapter();
|
||||
} else if (CUSTOM_ACTION_CHANGE_PLAYBACK_SPEED.equals(action)) {
|
||||
List<Float> selectedSpeeds = UserPreferences.getPlaybackSpeedArray();
|
||||
|
||||
|
@ -175,14 +175,12 @@ public class PlaybackServiceNotificationBuilder {
|
||||
ArrayList<Integer> compactActionList = new ArrayList<>();
|
||||
|
||||
int numActions = 0; // we start and 0 and then increment by 1 for each call to addAction
|
||||
// always let them rewind
|
||||
|
||||
PendingIntent rewindButtonPendingIntent = getPendingIntentForMediaAction(
|
||||
KeyEvent.KEYCODE_MEDIA_REWIND, numActions);
|
||||
notification.addAction(R.drawable.ic_notification_fast_rewind, context.getString(R.string.rewind_label),
|
||||
rewindButtonPendingIntent);
|
||||
if (UserPreferences.showRewindOnCompactNotification()) {
|
||||
compactActionList.add(numActions);
|
||||
}
|
||||
compactActionList.add(numActions);
|
||||
numActions++;
|
||||
|
||||
if (playerStatus == PlayerStatus.PLAYING) {
|
||||
@ -205,19 +203,24 @@ public class PlaybackServiceNotificationBuilder {
|
||||
KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, numActions);
|
||||
notification.addAction(R.drawable.ic_notification_fast_forward, context.getString(R.string.fast_forward_label),
|
||||
ffButtonPendingIntent);
|
||||
if (UserPreferences.showFastForwardOnCompactNotification()) {
|
||||
compactActionList.add(numActions);
|
||||
}
|
||||
compactActionList.add(numActions);
|
||||
numActions++;
|
||||
|
||||
PendingIntent skipButtonPendingIntent = getPendingIntentForMediaAction(
|
||||
KeyEvent.KEYCODE_MEDIA_NEXT, numActions);
|
||||
notification.addAction(R.drawable.ic_notification_skip, context.getString(R.string.skip_episode_label),
|
||||
skipButtonPendingIntent);
|
||||
if (UserPreferences.showSkipOnCompactNotification()) {
|
||||
compactActionList.add(numActions);
|
||||
if (UserPreferences.showNextChapterOnFullNotification() && playable.getChapters() != null) {
|
||||
PendingIntent nextChapterPendingIntent = getPendingIntentForCustomMediaAction(
|
||||
PlaybackService.CUSTOM_ACTION_NEXT_CHAPTER, numActions);
|
||||
notification.addAction(R.drawable.ic_notification_next_chapter, context.getString(R.string.next_chapter),
|
||||
nextChapterPendingIntent);
|
||||
numActions++;
|
||||
}
|
||||
|
||||
if (UserPreferences.showSkipOnFullNotification()) {
|
||||
PendingIntent skipButtonPendingIntent = getPendingIntentForMediaAction(
|
||||
KeyEvent.KEYCODE_MEDIA_NEXT, numActions);
|
||||
notification.addAction(R.drawable.ic_notification_skip, context.getString(R.string.skip_episode_label),
|
||||
skipButtonPendingIntent);
|
||||
numActions++;
|
||||
}
|
||||
numActions++;
|
||||
|
||||
PendingIntent stopButtonPendingIntent = getPendingIntentForMediaAction(
|
||||
KeyEvent.KEYCODE_MEDIA_STOP, numActions);
|
||||
@ -242,6 +245,20 @@ public class PlaybackServiceNotificationBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
private PendingIntent getPendingIntentForCustomMediaAction(String action, int requestCode) {
|
||||
Intent intent = new Intent(context, PlaybackService.class);
|
||||
intent.setAction("MediaAction" + action);
|
||||
intent.putExtra(MediaButtonReceiver.EXTRA_CUSTOM_ACTION, action);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
return PendingIntent.getForegroundService(context, requestCode, intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||
} else {
|
||||
return PendingIntent.getService(context, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT
|
||||
| (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0));
|
||||
}
|
||||
}
|
||||
|
||||
public void setMediaSessionToken(MediaSessionCompat.Token mediaSessionToken) {
|
||||
this.mediaSessionToken = mediaSessionToken;
|
||||
}
|
||||
@ -253,4 +270,4 @@ public class PlaybackServiceNotificationBuilder {
|
||||
public PlayerStatus getPlayerStatus() {
|
||||
return playerStatus;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -246,10 +246,10 @@
|
||||
<item>DownloadsSection</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="compact_notification_buttons_options">
|
||||
<item>@string/rewind_label</item>
|
||||
<item>@string/fast_forward_label</item>
|
||||
<string-array name="full_notification_buttons_options">
|
||||
<item>@string/skip_episode_label</item>
|
||||
<item>@string/next_chapter</item>
|
||||
<item>@string/playback_speed</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="default_page_values">
|
||||
|
@ -54,7 +54,7 @@ public class UserPreferences {
|
||||
public static final String PREF_USE_EPISODE_COVER = "prefEpisodeCover";
|
||||
public static final String PREF_SHOW_TIME_LEFT = "showTimeLeft";
|
||||
private static final String PREF_PERSISTENT_NOTIFICATION = "prefPersistNotify";
|
||||
public static final String PREF_COMPACT_NOTIFICATION_BUTTONS = "prefCompactNotificationButtons";
|
||||
public static final String PREF_FULL_NOTIFICATION_BUTTONS = "prefFullNotificationButtons";
|
||||
private static final String PREF_SHOW_DOWNLOAD_REPORT = "prefShowDownloadReport";
|
||||
public static final String PREF_DEFAULT_PAGE = "prefDefaultPage";
|
||||
public static final String PREF_FILTER_FEED = "prefSubscriptionsFilter";
|
||||
@ -127,9 +127,12 @@ public class UserPreferences {
|
||||
public static final int EPISODE_CLEANUP_DEFAULT = 0;
|
||||
|
||||
// Constants
|
||||
private static final int NOTIFICATION_BUTTON_REWIND = 0;
|
||||
private static final int NOTIFICATION_BUTTON_FAST_FORWARD = 1;
|
||||
private static final int NOTIFICATION_BUTTON_SKIP = 2;
|
||||
public static final int NOTIFICATION_BUTTON_REWIND = 0;
|
||||
public static final int NOTIFICATION_BUTTON_FAST_FORWARD = 1;
|
||||
public static final int NOTIFICATION_BUTTON_SKIP = 2;
|
||||
|
||||
public static final int NOTIFICATION_BUTTON_NEXT_CHAPTER = 3;
|
||||
public static final int NOTIFICATION_BUTTON_PLAYBACK_SPEED = 4;
|
||||
public static final int EPISODE_CACHE_SIZE_UNLIMITED = -1;
|
||||
public static final int FEED_ORDER_COUNTER = 0;
|
||||
public static final int FEED_ORDER_ALPHABETICAL = 1;
|
||||
@ -195,11 +198,11 @@ public class UserPreferences {
|
||||
return new ArrayList<>(Arrays.asList(TextUtils.split(hiddenItems, ",")));
|
||||
}
|
||||
|
||||
public static List<Integer> getCompactNotificationButtons() {
|
||||
public static List<Integer> getFullNotificationButtons() {
|
||||
String[] buttons = TextUtils.split(
|
||||
prefs.getString(PREF_COMPACT_NOTIFICATION_BUTTONS,
|
||||
NOTIFICATION_BUTTON_REWIND + "," + NOTIFICATION_BUTTON_FAST_FORWARD),
|
||||
",");
|
||||
prefs.getString(PREF_FULL_NOTIFICATION_BUTTONS,
|
||||
NOTIFICATION_BUTTON_SKIP + "," + NOTIFICATION_BUTTON_PLAYBACK_SPEED), ",");
|
||||
|
||||
List<Integer> notificationButtons = new ArrayList<>();
|
||||
for (String button : buttons) {
|
||||
notificationButtons.add(Integer.parseInt(button));
|
||||
@ -208,27 +211,28 @@ public class UserPreferences {
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to return whether the specified button should be shown on compact
|
||||
* Helper function to return whether the specified button should be shown on full
|
||||
* notifications.
|
||||
*
|
||||
* @param buttonId Either NOTIFICATION_BUTTON_REWIND, NOTIFICATION_BUTTON_FAST_FORWARD or
|
||||
* NOTIFICATION_BUTTON_SKIP.
|
||||
* @param buttonId Either NOTIFICATION_BUTTON_REWIND, NOTIFICATION_BUTTON_FAST_FORWARD,
|
||||
* NOTIFICATION_BUTTON_SKIP, NOTIFICATION_BUTTON_PLAYBACK_SPEED
|
||||
* or NOTIFICATION_BUTTON_NEXT_CHAPTER.
|
||||
* @return {@code true} if button should be shown, {@code false} otherwise
|
||||
*/
|
||||
private static boolean showButtonOnCompactNotification(int buttonId) {
|
||||
return getCompactNotificationButtons().contains(buttonId);
|
||||
private static boolean showButtonOnFullNotification(int buttonId) {
|
||||
return getFullNotificationButtons().contains(buttonId);
|
||||
}
|
||||
|
||||
public static boolean showRewindOnCompactNotification() {
|
||||
return showButtonOnCompactNotification(NOTIFICATION_BUTTON_REWIND);
|
||||
public static boolean showSkipOnFullNotification() {
|
||||
return showButtonOnFullNotification(NOTIFICATION_BUTTON_SKIP);
|
||||
}
|
||||
|
||||
public static boolean showFastForwardOnCompactNotification() {
|
||||
return showButtonOnCompactNotification(NOTIFICATION_BUTTON_FAST_FORWARD);
|
||||
public static boolean showNextChapterOnFullNotification() {
|
||||
return showButtonOnFullNotification(NOTIFICATION_BUTTON_NEXT_CHAPTER);
|
||||
}
|
||||
|
||||
public static boolean showSkipOnCompactNotification() {
|
||||
return showButtonOnCompactNotification(NOTIFICATION_BUTTON_SKIP);
|
||||
public static boolean showPlaybackSpeedOnFullNotification() {
|
||||
return showButtonOnFullNotification(NOTIFICATION_BUTTON_PLAYBACK_SPEED);
|
||||
}
|
||||
|
||||
public static int getFeedOrder() {
|
||||
@ -653,10 +657,10 @@ public class UserPreferences {
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static void setCompactNotificationButtons(List<Integer> items) {
|
||||
public static void setFullNotificationButtons(List<Integer> items) {
|
||||
String str = TextUtils.join(",", items);
|
||||
prefs.edit()
|
||||
.putString(PREF_COMPACT_NOTIFICATION_BUTTONS, str)
|
||||
.putString(PREF_FULL_NOTIFICATION_BUTTONS, str)
|
||||
.apply();
|
||||
}
|
||||
|
||||
|
@ -489,10 +489,9 @@
|
||||
<string name="pref_expandNotify_sum">This usually expands the notification to show playback buttons.</string>
|
||||
<string name="pref_persistNotify_title">Persistent playback controls</string>
|
||||
<string name="pref_persistNotify_sum">Keep notification and lockscreen controls when playback is paused</string>
|
||||
<string name="pref_compact_notification_buttons_title">Set compact notification buttons</string>
|
||||
<string name="pref_compact_notification_buttons_sum">Change the playback buttons when the notification is collapsed. The play/pause button is always included.</string>
|
||||
<string name="pref_compact_notification_buttons_dialog_title">Select a maximum of %1$d items</string>
|
||||
<string name="pref_compact_notification_buttons_dialog_error">You can only select a maximum of %1$d items.</string>
|
||||
<string name="pref_compact_notification_buttons_dialog_error_exact">You must select exactly %1$d items.</string>
|
||||
<string name="pref_full_notification_buttons_title">Set notification buttons</string>
|
||||
<string name="pref_full_notification_buttons_sum">Change the playback buttons on the playback notification.</string>
|
||||
<string name="pref_enqueue_location_title">Enqueue location</string>
|
||||
<string name="pref_enqueue_location_sum">Add episodes to: %1$s</string>
|
||||
<string name="enqueue_location_back">Back</string>
|
||||
|
@ -0,0 +1,7 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="#fff" android:pathData="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4M8,8V16L13,12M14,8V16H16V8" />
|
||||
</vector>
|
Loading…
x
Reference in New Issue
Block a user