Update compact notification buttons dialog

The preference dialog to select which buttons are shown in compact
notifications now provides feedback via a snackbar. The internal
preference storage handling has been cleaned up. A testcase for
the dialog has been added.
This commit is contained in:
saqura 2016-04-03 20:22:03 +02:00
parent e215e162ad
commit e3408565dc
7 changed files with 109 additions and 84 deletions

View File

@ -90,6 +90,30 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
assertTrue(solo.waitForCondition(() -> persistNotify == UserPreferences.isPersistNotify(), Timeout.getLargeTimeout())); assertTrue(solo.waitForCondition(() -> persistNotify == UserPreferences.isPersistNotify(), Timeout.getLargeTimeout()));
} }
public void testSetLockscreenButtons() {
String[] buttons = res.getStringArray(R.array.compact_notification_buttons_options);
solo.clickOnText(solo.getString(R.string.pref_compact_notification_buttons_title));
solo.waitForDialogToOpen(1000);
// First uncheck every checkbox
for (int i=0; i<buttons.length; i++) {
assertTrue(solo.searchText(buttons[i]));
if (solo.isTextChecked(buttons[i])) {
solo.clickOnText(buttons[i]);
}
}
// Now try to check all checkboxes
solo.clickOnText(buttons[0]);
solo.clickOnText(buttons[1]);
solo.clickOnText(buttons[2]);
// Make sure that the third checkbox is unchecked
assertTrue(!solo.isTextChecked(buttons[2]));
solo.clickOnText(solo.getString(R.string.confirm_label));
solo.waitForDialogToClose(1000);
assertTrue(solo.waitForCondition(() -> UserPreferences.showRewindOnCompactNotification(), Timeout.getLargeTimeout()));
assertTrue(solo.waitForCondition(() -> UserPreferences.showFastForwardOnCompactNotification(), Timeout.getLargeTimeout()));
assertTrue(solo.waitForCondition(() -> !UserPreferences.showSkipOnCompactNotification(), Timeout.getLargeTimeout()));
}
public void testEnqueueAtFront() { public void testEnqueueAtFront() {
final boolean enqueueAtFront = UserPreferences.enqueueAtFront(); final boolean enqueueAtFront = UserPreferences.enqueueAtFront();
solo.clickOnText(solo.getString(R.string.pref_queueAddToFront_title)); solo.clickOnText(solo.getString(R.string.pref_queueAddToFront_title));

View File

@ -6,7 +6,6 @@ import android.app.Activity;
import android.app.TimePickerDialog; import android.app.TimePickerDialog;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
@ -21,6 +20,7 @@ import android.preference.ListPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.preference.PreferenceScreen; import android.preference.PreferenceScreen;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat; import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
@ -31,6 +31,7 @@ import android.text.format.DateFormat;
import android.util.Log; import android.util.Log;
import android.widget.EditText; import android.widget.EditText;
import android.widget.Toast; import android.widget.Toast;
import android.widget.ListView;
import com.afollestad.materialdialogs.MaterialDialog; import com.afollestad.materialdialogs.MaterialDialog;
@ -222,7 +223,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
return true; return true;
}); });
ui.findPreference(UserPreferences.PREF_NOTIFICATION_BUTTONS) ui.findPreference(UserPreferences.PREF_COMPACT_NOTIFICATION_BUTTONS)
.setOnPreferenceClickListener(preference -> { .setOnPreferenceClickListener(preference -> {
showNotificationButtonsDialog(); showNotificationButtonsDialog();
return true; return true;
@ -744,52 +745,45 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
private void showNotificationButtonsDialog() { private void showNotificationButtonsDialog() {
final Context context = ui.getActivity(); final Context context = ui.getActivity();
final List<String> preferredButtons = UserPreferences.getNotificationButtons(); final List<Integer> preferredButtons = UserPreferences.getCompactNotificationButtons();
final String[] allButtonNames = context.getResources().getStringArray( final String[] allButtonNames = context.getResources().getStringArray(
R.array.notification_buttons_options); R.array.compact_notification_buttons_options);
final String[] allButtonIDs = context.getResources().getStringArray( boolean[] checked = new boolean[allButtonNames.length]; // booleans default to false in java
R.array.notification_buttons_values);
boolean[] checked = new boolean[allButtonIDs.length]; // booleans default to false in java
for(int i=0; i < allButtonIDs.length; i++) { for(int i=0; i < checked.length; i++) {
String id = allButtonIDs[i]; if(preferredButtons.contains(i)) {
if(preferredButtons.contains(id)) {
checked[i] = true; checked[i] = true;
} }
} }
AlertDialog.Builder builder = new AlertDialog.Builder(context); AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(String.format(context.getResources().getString( builder.setTitle(String.format(context.getResources().getString(
R.string.pref_notification_buttons_dialog_title), 2)); R.string.pref_compact_notification_buttons_dialog_title), 2));
builder.setMultiChoiceItems(allButtonNames, checked,new DialogInterface.OnMultiChoiceClickListener() { builder.setMultiChoiceItems(allButtonNames, checked, (dialog, which, isChecked) -> {
int count = preferredButtons.size(); checked[which] = isChecked;
public void onClick(DialogInterface dialog, int which, boolean isChecked) { if (isChecked) {
checked[which] = isChecked; if (preferredButtons.size() < 2) {
if (isChecked) { preferredButtons.add(which);
if (count < 2) {
preferredButtons.add(allButtonIDs[which]);
count++;
} 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;
((AlertDialog) dialog).getListView().setItemChecked(which, false);
Toast.makeText(
context,
String.format(context.getResources().getString(
R.string.pref_notification_buttons_dialog_error), 2),
Toast.LENGTH_SHORT).show();
}
} else { } else {
preferredButtons.remove(allButtonIDs[which]); // Only allow a maximum of two selections. This is because the notification
count--; // 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();
} }
} else {
preferredButtons.remove((Integer) which);
} }
}); });
builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> { builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
UserPreferences.setNotificationButtons(preferredButtons); UserPreferences.setCompactNotificationButtons(preferredButtons);
}); });
builder.setNegativeButton(R.string.cancel_label, null); builder.setNegativeButton(R.string.cancel_label, null);
builder.create().show(); builder.create().show();

View File

@ -56,9 +56,9 @@
android:summary="@string/pref_persistNotify_sum" android:summary="@string/pref_persistNotify_sum"
android:title="@string/pref_persistNotify_title"/> android:title="@string/pref_persistNotify_title"/>
<Preference <Preference
android:key="prefNotificationButtons" android:key="prefCompactNotificationButtons"
android:summary="@string/pref_notification_buttons_sum" android:summary="@string/pref_compact_notification_buttons_sum"
android:title="@string/pref_notification_buttons_title"/> android:title="@string/pref_compact_notification_buttons_title"/>
<de.danoeh.antennapod.preferences.SwitchCompatPreference <de.danoeh.antennapod.preferences.SwitchCompatPreference
android:defaultValue="true" android:defaultValue="true"
android:enabled="true" android:enabled="true"

View File

@ -52,7 +52,7 @@ public class UserPreferences {
public static final String PREF_DRAWER_FEED_COUNTER = "prefDrawerFeedIndicator"; public static final String PREF_DRAWER_FEED_COUNTER = "prefDrawerFeedIndicator";
public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify"; public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify";
public static final String PREF_PERSISTENT_NOTIFICATION = "prefPersistNotify"; public static final String PREF_PERSISTENT_NOTIFICATION = "prefPersistNotify";
public static final String PREF_NOTIFICATION_BUTTONS = "prefNotificationButtons"; public static final String PREF_COMPACT_NOTIFICATION_BUTTONS = "prefCompactNotificationButtons";
public static final String PREF_LOCKSCREEN_BACKGROUND = "prefLockscreenBackground"; public static final String PREF_LOCKSCREEN_BACKGROUND = "prefLockscreenBackground";
public static final String PREF_SHOW_DOWNLOAD_REPORT = "prefShowDownloadReport"; public static final String PREF_SHOW_DOWNLOAD_REPORT = "prefShowDownloadReport";
public static final String PREF_SHOW_SUBSCRIPTIONS_IN_DRAWER = "prefShowSubscriptionsInDrawer"; public static final String PREF_SHOW_SUBSCRIPTIONS_IN_DRAWER = "prefShowSubscriptionsInDrawer";
@ -117,6 +117,9 @@ public class UserPreferences {
public static final int EPISODE_CLEANUP_DEFAULT = 0; public static final int EPISODE_CLEANUP_DEFAULT = 0;
// Constants // 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;
private static int EPISODE_CACHE_SIZE_UNLIMITED = -1; private static int EPISODE_CACHE_SIZE_UNLIMITED = -1;
public static int FEED_ORDER_COUNTER = 0; public static int FEED_ORDER_COUNTER = 0;
public static int FEED_ORDER_ALPHABETICAL = 1; public static int FEED_ORDER_ALPHABETICAL = 1;
@ -167,9 +170,40 @@ public class UserPreferences {
return new ArrayList<>(Arrays.asList(TextUtils.split(hiddenItems, ","))); return new ArrayList<>(Arrays.asList(TextUtils.split(hiddenItems, ",")));
} }
public static List<String> getNotificationButtons() { public static List<Integer> getCompactNotificationButtons() {
String hiddenItems = prefs.getString(PREF_NOTIFICATION_BUTTONS, "skip"); String[] buttons = TextUtils.split(
return new ArrayList<>(Arrays.asList(TextUtils.split(hiddenItems, ","))); prefs.getString(PREF_COMPACT_NOTIFICATION_BUTTONS,
String.valueOf(NOTIFICATION_BUTTON_SKIP)),
",");
List<Integer> notificationButtons = new ArrayList<>();
for (int i=0; i<buttons.length; i++) {
notificationButtons.add(Integer.parseInt(buttons[i]));
}
return notificationButtons;
}
/**
* Helper function to return whether the specified button should be shown on compact
* notifications.
*
* @param buttonId Either NOTIFICATION_BUTTON_REWIND, NOTIFICATION_BUTTON_FAST_FORWARD or
* NOTIFICATION_BUTTON_SKIP.
* @return {@code true} if button should be shown, {@code false} otherwise
*/
private static boolean showButtonOnCompactNotification(int buttonId) {
return getCompactNotificationButtons().contains(buttonId);
}
public static boolean showRewindOnCompactNotification() {
return showButtonOnCompactNotification(NOTIFICATION_BUTTON_REWIND);
}
public static boolean showFastForwardOnCompactNotification() {
return showButtonOnCompactNotification(NOTIFICATION_BUTTON_FAST_FORWARD);
}
public static boolean showSkipOnCompactNotification() {
return showButtonOnCompactNotification(NOTIFICATION_BUTTON_SKIP);
} }
public static int getFeedOrder() { public static int getFeedOrder() {
@ -199,16 +233,6 @@ public class UserPreferences {
} }
} }
/**
* Returns true if additional playback buttons should be shown in the notification even when
* on the lockscreen
*
* @return {@code true} if additional playback buttons should be shown, {@code false} otherwise
*/
public static boolean showAdditionalNotificationButtons() {
return prefs.getBoolean(PREF_EXPANDED_NOTIFICATION, false);
}
/** /**
* Returns true if notifications are persistent * Returns true if notifications are persistent
* *
@ -533,10 +557,10 @@ public class UserPreferences {
.apply(); .apply();
} }
public static void setNotificationButtons(List<String> items) { public static void setCompactNotificationButtons(List<Integer> items) {
String str = TextUtils.join(",", items); String str = TextUtils.join(",", items);
prefs.edit() prefs.edit()
.putString(PREF_NOTIFICATION_BUTTONS, str) .putString(PREF_COMPACT_NOTIFICATION_BUTTONS, str)
.apply(); .apply();
} }

View File

@ -858,7 +858,6 @@ public class PlaybackService extends Service {
.setPriority(UserPreferences.getNotifyPriority()); // set notification priority .setPriority(UserPreferences.getNotifyPriority()); // set notification priority
IntList compactActionList = new IntList(); IntList compactActionList = new IntList();
final List<String> notificationButtons = UserPreferences.getNotificationButtons();
int numActions = 0; // we start and 0 and then increment by 1 for each call to addAction int numActions = 0; // we start and 0 and then increment by 1 for each call to addAction
// always let them rewind // always let them rewind
@ -867,13 +866,10 @@ public class PlaybackService extends Service {
notificationBuilder.addAction(android.R.drawable.ic_media_rew, notificationBuilder.addAction(android.R.drawable.ic_media_rew,
getString(R.string.rewind_label), getString(R.string.rewind_label),
rewindButtonPendingIntent); rewindButtonPendingIntent);
if(notificationButtons.contains("rewind")) { if(UserPreferences.showRewindOnCompactNotification()) {
// show the rewind button even on the lock screen compactActionList.add(numActions);
compactActionList.add(numActions++);
} else {
numActions++;
} }
numActions++;
if (playerStatus == PlayerStatus.PLAYING) { if (playerStatus == PlayerStatus.PLAYING) {
PendingIntent pauseButtonPendingIntent = getPendingIntentForMediaAction( PendingIntent pauseButtonPendingIntent = getPendingIntentForMediaAction(
@ -897,12 +893,10 @@ public class PlaybackService extends Service {
notificationBuilder.addAction(android.R.drawable.ic_media_ff, notificationBuilder.addAction(android.R.drawable.ic_media_ff,
getString(R.string.fast_forward_label), getString(R.string.fast_forward_label),
ffButtonPendingIntent); ffButtonPendingIntent);
if(notificationButtons.contains("fastforward")) { if(UserPreferences.showFastForwardOnCompactNotification()) {
// show the fast forward button even on the lock screen compactActionList.add(numActions);
compactActionList.add(numActions++);
} else {
numActions++;
} }
numActions++;
if (UserPreferences.isFollowQueue()) { if (UserPreferences.isFollowQueue()) {
PendingIntent skipButtonPendingIntent = getPendingIntentForMediaAction( PendingIntent skipButtonPendingIntent = getPendingIntentForMediaAction(
@ -910,12 +904,10 @@ public class PlaybackService extends Service {
notificationBuilder.addAction(android.R.drawable.ic_media_next, notificationBuilder.addAction(android.R.drawable.ic_media_next,
getString(R.string.skip_episode_label), getString(R.string.skip_episode_label),
skipButtonPendingIntent); skipButtonPendingIntent);
if(notificationButtons.contains("skip")) { if(UserPreferences.showSkipOnCompactNotification()) {
// show the skip button even on the lock screen compactActionList.add(numActions);
compactActionList.add(numActions++);
} else {
numActions++;
} }
numActions++;
} }
PendingIntent stopButtonPendingIntent = getPendingIntentForMediaAction( PendingIntent stopButtonPendingIntent = getPendingIntentForMediaAction(

View File

@ -212,18 +212,9 @@
<item>500</item> <item>500</item>
</string-array> </string-array>
<string-array name="notification_buttons_options"> <string-array name="compact_notification_buttons_options">
<item>@string/rewind_label</item> <item>@string/rewind_label</item>
<item>@string/fast_forward_label</item> <item>@string/fast_forward_label</item>
<item>@string/skip_episode_label</item> <item>@string/skip_episode_label</item>
</string-array> </string-array>
<string-array name="notification_buttons_values">
<item>rewind</item>
<item>fastforward</item>
<item>skip</item>
</string-array>
<string-array name="notification_buttons_default_values">
<item>skip</item>
</string-array>
</resources> </resources>

View File

@ -384,10 +384,10 @@
<string name="pref_expandNotify_sum">Always expand the notification to show playback buttons.</string> <string name="pref_expandNotify_sum">Always expand the notification to show playback buttons.</string>
<string name="pref_persistNotify_title">Persistent Playback Controls</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_persistNotify_sum">Keep notification and lockscreen controls when playback is paused.</string>
<string name="pref_notification_buttons_title">Select Notification Buttons</string> <string name="pref_compact_notification_buttons_title">Set Lockscreen Buttons</string>
<string name="pref_notification_buttons_sum">Change the playback buttons on the lock screen notification. The play/pause button is always included.</string> <string name="pref_compact_notification_buttons_sum">Change the playback buttons on the lockscreen. The play/pause button is always included.</string>
<string name="pref_notification_buttons_dialog_title">Select a maximum of %1$d items</string> <string name="pref_compact_notification_buttons_dialog_title">Select a maximum of %1$d items</string>
<string name="pref_notification_buttons_dialog_error">You can only 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_show_subscriptions_in_drawer_title">Show Subscriptions</string> <string name="pref_show_subscriptions_in_drawer_title">Show Subscriptions</string>
<string name="pref_show_subscriptions_in_drawer_sum">Show subscription list directly in navigation drawer</string> <string name="pref_show_subscriptions_in_drawer_sum">Show subscription list directly in navigation drawer</string>
<string name="pref_lockscreen_background_title">Set Lockscreen Background</string> <string name="pref_lockscreen_background_title">Set Lockscreen Background</string>