851 lines
32 KiB
Java
851 lines
32 KiB
Java
package de.danoeh.antennapod.storage.preferences;
|
|
|
|
import android.content.Context;
|
|
import android.content.SharedPreferences;
|
|
import android.os.Build;
|
|
import android.text.TextUtils;
|
|
import android.util.Log;
|
|
import android.view.KeyEvent;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.annotation.VisibleForTesting;
|
|
import androidx.core.app.NotificationCompat;
|
|
import androidx.preference.PreferenceManager;
|
|
|
|
import de.danoeh.antennapod.model.feed.FeedOrder;
|
|
import org.json.JSONArray;
|
|
import org.json.JSONException;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.net.Proxy;
|
|
import java.text.DecimalFormat;
|
|
import java.text.DecimalFormatSymbols;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.Set;
|
|
|
|
import de.danoeh.antennapod.model.download.ProxyConfig;
|
|
import de.danoeh.antennapod.model.feed.FeedCounter;
|
|
import de.danoeh.antennapod.model.feed.FeedPreferences;
|
|
import de.danoeh.antennapod.model.feed.SortOrder;
|
|
import de.danoeh.antennapod.model.feed.SubscriptionsFilter;
|
|
|
|
/**
|
|
* Provides access to preferences set by the user in the settings screen. A
|
|
* private instance of this class must first be instantiated via
|
|
* init() or otherwise every public method will throw an Exception
|
|
* when called.
|
|
*/
|
|
public abstract class UserPreferences {
|
|
private static final String TAG = "UserPreferences";
|
|
|
|
// User Interface
|
|
public static final String PREF_THEME = "prefTheme";
|
|
public static final String PREF_THEME_BLACK = "prefThemeBlack";
|
|
public static final String PREF_TINTED_COLORS = "prefTintedColors";
|
|
public static final String PREF_HIDDEN_DRAWER_ITEMS = "prefHiddenDrawerItems";
|
|
public static final String PREF_DRAWER_FEED_ORDER = "prefDrawerFeedOrder";
|
|
public static final String PREF_DRAWER_FEED_COUNTER = "prefDrawerFeedIndicator";
|
|
public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify";
|
|
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_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";
|
|
public static final String PREF_SUBSCRIPTION_TITLE = "prefSubscriptionTitle";
|
|
public static final String PREF_BACK_OPENS_DRAWER = "prefBackButtonOpensDrawer";
|
|
|
|
public static final String PREF_QUEUE_KEEP_SORTED = "prefQueueKeepSorted";
|
|
public static final String PREF_QUEUE_KEEP_SORTED_ORDER = "prefQueueKeepSortedOrder";
|
|
public static final String PREF_NEW_EPISODES_ACTION = "prefNewEpisodesAction";
|
|
private static final String PREF_DOWNLOADS_SORTED_ORDER = "prefDownloadSortedOrder";
|
|
private static final String PREF_INBOX_SORTED_ORDER = "prefInboxSortedOrder";
|
|
|
|
// Episode
|
|
public static final String PREF_SORT_ALL_EPISODES = "prefEpisodesSort";
|
|
public static final String PREF_FILTER_ALL_EPISODES = "prefEpisodesFilter";
|
|
|
|
// Playback
|
|
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_BLUETOOTH_RECONNECT = "prefUnpauseOnBluetoothReconnect";
|
|
public static final String PREF_HARDWARE_FORWARD_BUTTON = "prefHardwareForwardButton";
|
|
public static final String PREF_HARDWARE_PREVIOUS_BUTTON = "prefHardwarePreviousButton";
|
|
public static final String PREF_FOLLOW_QUEUE = "prefFollowQueue";
|
|
public static final String PREF_SKIP_KEEPS_EPISODE = "prefSkipKeepsEpisode";
|
|
private static final String PREF_FAVORITE_KEEPS_EPISODE = "prefFavoriteKeepsEpisode";
|
|
private static final String PREF_AUTO_DELETE = "prefAutoDelete";
|
|
private static final String PREF_AUTO_DELETE_LOCAL = "prefAutoDeleteLocal";
|
|
public static final String PREF_SMART_MARK_AS_PLAYED_SECS = "prefSmartMarkAsPlayedSecs";
|
|
private static final String PREF_PLAYBACK_SPEED_ARRAY = "prefPlaybackSpeedArray";
|
|
public static final String PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS = "prefPauseForFocusLoss";
|
|
private static final String PREF_TIME_RESPECTS_SPEED = "prefPlaybackTimeRespectsSpeed";
|
|
public static final String PREF_STREAM_OVER_DOWNLOAD = "prefStreamOverDownload";
|
|
|
|
// Network
|
|
private static final String PREF_ENQUEUE_DOWNLOADED = "prefEnqueueDownloaded";
|
|
public static final String PREF_ENQUEUE_LOCATION = "prefEnqueueLocation";
|
|
public static final String PREF_UPDATE_INTERVAL = "prefAutoUpdateIntervall";
|
|
private static final String PREF_MOBILE_UPDATE = "prefMobileUpdateTypes";
|
|
public static final String PREF_EPISODE_CLEANUP = "prefEpisodeCleanup";
|
|
public static final String PREF_EPISODE_CACHE_SIZE = "prefEpisodeCacheSize";
|
|
public static final String PREF_ENABLE_AUTODL = "prefEnableAutoDl";
|
|
public static final String PREF_ENABLE_AUTODL_ON_BATTERY = "prefEnableAutoDownloadOnBattery";
|
|
public static final String PREF_ENABLE_AUTODL_WIFI_FILTER = "prefEnableAutoDownloadWifiFilter";
|
|
private static final String PREF_AUTODL_SELECTED_NETWORKS = "prefAutodownloadSelectedNetworks";
|
|
private static final String PREF_PROXY_TYPE = "prefProxyType";
|
|
private static final String PREF_PROXY_HOST = "prefProxyHost";
|
|
private static final String PREF_PROXY_PORT = "prefProxyPort";
|
|
private static final String PREF_PROXY_USER = "prefProxyUser";
|
|
private static final String PREF_PROXY_PASSWORD = "prefProxyPassword";
|
|
|
|
// Services
|
|
private static final String PREF_GPODNET_NOTIFICATIONS = "pref_gpodnet_notifications";
|
|
|
|
// Other
|
|
private static final String PREF_DATA_FOLDER = "prefDataFolder";
|
|
public static final String PREF_DELETE_REMOVES_FROM_QUEUE = "prefDeleteRemovesFromQueue";
|
|
private static final String PREF_AUTOMATIC_EXPORT_FOLDER = "prefAutomaticExportFolder";
|
|
|
|
// Mediaplayer
|
|
private static final String PREF_PLAYBACK_SPEED = "prefPlaybackSpeed";
|
|
public static final String PREF_PLAYBACK_SKIP_SILENCE = "prefSkipSilence";
|
|
private static final String PREF_FAST_FORWARD_SECS = "prefFastForwardSecs";
|
|
private static final String PREF_REWIND_SECS = "prefRewindSecs";
|
|
private static final String PREF_QUEUE_LOCKED = "prefQueueLocked";
|
|
|
|
// Experimental
|
|
public static final int EPISODE_CLEANUP_QUEUE = -1;
|
|
public static final int EPISODE_CLEANUP_NULL = -2;
|
|
public static final int EPISODE_CLEANUP_EXCEPT_FAVORITE = -3;
|
|
public static final int EPISODE_CLEANUP_DEFAULT = 0;
|
|
|
|
// Constants
|
|
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 NOTIFICATION_BUTTON_SLEEP_TIMER = 5;
|
|
public static final int EPISODE_CACHE_SIZE_UNLIMITED = -1;
|
|
public static final String DEFAULT_PAGE_REMEMBER = "remember";
|
|
|
|
private static Context context;
|
|
private static SharedPreferences prefs;
|
|
|
|
/**
|
|
* Sets up the UserPreferences class.
|
|
*
|
|
* @throws IllegalArgumentException if context is null
|
|
*/
|
|
public static void init(@NonNull Context context) {
|
|
Log.d(TAG, "Creating new instance of UserPreferences");
|
|
|
|
UserPreferences.context = context.getApplicationContext();
|
|
UserPreferences.prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
|
|
|
createNoMediaFile();
|
|
}
|
|
|
|
public enum ThemePreference {
|
|
LIGHT, DARK, BLACK, SYSTEM
|
|
}
|
|
|
|
public static void setTheme(ThemePreference theme) {
|
|
switch (theme) {
|
|
case LIGHT:
|
|
prefs.edit().putString(PREF_THEME, "0").apply();
|
|
break;
|
|
case DARK:
|
|
prefs.edit().putString(PREF_THEME, "1").apply();
|
|
break;
|
|
default:
|
|
prefs.edit().putString(PREF_THEME, "system").apply();
|
|
break;
|
|
}
|
|
}
|
|
|
|
public static ThemePreference getTheme() {
|
|
switch (prefs.getString(PREF_THEME, "system")) {
|
|
case "0":
|
|
return ThemePreference.LIGHT;
|
|
case "1":
|
|
return ThemePreference.DARK;
|
|
default:
|
|
return ThemePreference.SYSTEM;
|
|
}
|
|
}
|
|
|
|
public static boolean getIsBlackTheme() {
|
|
return prefs.getBoolean(PREF_THEME_BLACK, false);
|
|
}
|
|
|
|
public static boolean getIsThemeColorTinted() {
|
|
return Build.VERSION.SDK_INT >= 31 && prefs.getBoolean(PREF_TINTED_COLORS, false);
|
|
}
|
|
|
|
public static List<String> getHiddenDrawerItems() {
|
|
String hiddenItems = prefs.getString(PREF_HIDDEN_DRAWER_ITEMS, "");
|
|
return new ArrayList<>(Arrays.asList(TextUtils.split(hiddenItems, ",")));
|
|
}
|
|
|
|
public static List<Integer> getFullNotificationButtons() {
|
|
String[] buttons = TextUtils.split(
|
|
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));
|
|
}
|
|
return notificationButtons;
|
|
}
|
|
|
|
/**
|
|
* Helper function to return whether the specified button should be shown on full
|
|
* notifications.
|
|
*
|
|
* @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 showButtonOnFullNotification(int buttonId) {
|
|
return getFullNotificationButtons().contains(buttonId);
|
|
}
|
|
|
|
public static boolean showSkipOnFullNotification() {
|
|
return showButtonOnFullNotification(NOTIFICATION_BUTTON_SKIP);
|
|
}
|
|
|
|
public static boolean showNextChapterOnFullNotification() {
|
|
return showButtonOnFullNotification(NOTIFICATION_BUTTON_NEXT_CHAPTER);
|
|
}
|
|
|
|
public static boolean showPlaybackSpeedOnFullNotification() {
|
|
return showButtonOnFullNotification(NOTIFICATION_BUTTON_PLAYBACK_SPEED);
|
|
}
|
|
|
|
public static boolean showSleepTimerOnFullNotification() {
|
|
return showButtonOnFullNotification(NOTIFICATION_BUTTON_SLEEP_TIMER);
|
|
}
|
|
|
|
public static FeedOrder getFeedOrder() {
|
|
String value = prefs.getString(PREF_DRAWER_FEED_ORDER, "" + FeedOrder.COUNTER.id);
|
|
return FeedOrder.fromOrdinal(Integer.parseInt(value));
|
|
}
|
|
|
|
public static void setFeedOrder(FeedOrder feedOrder) {
|
|
prefs.edit().putString(PREF_DRAWER_FEED_ORDER, "" + feedOrder.id).apply();
|
|
}
|
|
|
|
public static FeedCounter getFeedCounterSetting() {
|
|
String value = prefs.getString(PREF_DRAWER_FEED_COUNTER, "" + FeedCounter.SHOW_NEW.id);
|
|
return FeedCounter.fromOrdinal(Integer.parseInt(value));
|
|
}
|
|
|
|
/**
|
|
* @return {@code true} if episodes should use their own cover, {@code false} otherwise
|
|
*/
|
|
public static boolean getUseEpisodeCoverSetting() {
|
|
return prefs.getBoolean(PREF_USE_EPISODE_COVER, true);
|
|
}
|
|
|
|
/**
|
|
* @return {@code true} if we should show remaining time or the duration
|
|
*/
|
|
public static boolean shouldShowRemainingTime() {
|
|
return prefs.getBoolean(PREF_SHOW_TIME_LEFT, false);
|
|
}
|
|
|
|
/**
|
|
* Sets the preference for whether we show the remain time, if not show the duration. This will
|
|
* send out events so the current playing screen, queue and the episode list would refresh
|
|
*
|
|
* @return {@code true} if we should show remaining time or the duration
|
|
*/
|
|
public static void setShowRemainTimeSetting(Boolean showRemain) {
|
|
prefs.edit().putBoolean(PREF_SHOW_TIME_LEFT, showRemain).apply();
|
|
}
|
|
|
|
@Nullable
|
|
public static String getAutomaticExportFolder() {
|
|
return prefs.getString(PREF_AUTOMATIC_EXPORT_FOLDER, null);
|
|
}
|
|
|
|
public static void setAutomaticExportFolder(@Nullable String folder) {
|
|
prefs.edit().putString(PREF_AUTOMATIC_EXPORT_FOLDER, folder).apply();
|
|
}
|
|
|
|
/**
|
|
* Returns notification priority.
|
|
*
|
|
* @return NotificationCompat.PRIORITY_MAX or NotificationCompat.PRIORITY_DEFAULT
|
|
*/
|
|
public static int getNotifyPriority() {
|
|
if (prefs.getBoolean(PREF_EXPANDED_NOTIFICATION, false)) {
|
|
return NotificationCompat.PRIORITY_MAX;
|
|
} else {
|
|
return NotificationCompat.PRIORITY_DEFAULT;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if notifications are persistent
|
|
*
|
|
* @return {@code true} if notifications are persistent, {@code false} otherwise
|
|
*/
|
|
public static boolean isPersistNotify() {
|
|
return prefs.getBoolean(PREF_PERSISTENT_NOTIFICATION, true);
|
|
}
|
|
|
|
/**
|
|
* Used for migration of the preference to system notification channels.
|
|
*/
|
|
public static boolean getShowDownloadReportRaw() {
|
|
return prefs.getBoolean(PREF_SHOW_DOWNLOAD_REPORT, true);
|
|
}
|
|
|
|
public static boolean enqueueDownloadedEpisodes() {
|
|
return prefs.getBoolean(PREF_ENQUEUE_DOWNLOADED, true);
|
|
}
|
|
|
|
public enum EnqueueLocation {
|
|
BACK, FRONT, AFTER_CURRENTLY_PLAYING, RANDOM
|
|
}
|
|
|
|
@NonNull
|
|
public static EnqueueLocation getEnqueueLocation() {
|
|
String valStr = prefs.getString(PREF_ENQUEUE_LOCATION, EnqueueLocation.BACK.name());
|
|
try {
|
|
return EnqueueLocation.valueOf(valStr);
|
|
} catch (Throwable t) {
|
|
// should never happen but just in case
|
|
Log.e(TAG, "getEnqueueLocation: invalid value '" + valStr + "' Use default.", t);
|
|
return EnqueueLocation.BACK;
|
|
}
|
|
}
|
|
|
|
public static void setEnqueueLocation(@NonNull EnqueueLocation location) {
|
|
prefs.edit()
|
|
.putString(PREF_ENQUEUE_LOCATION, location.name())
|
|
.apply();
|
|
}
|
|
|
|
public static boolean isPauseOnHeadsetDisconnect() {
|
|
return prefs.getBoolean(PREF_PAUSE_ON_HEADSET_DISCONNECT, true);
|
|
}
|
|
|
|
public static boolean isUnpauseOnHeadsetReconnect() {
|
|
return prefs.getBoolean(PREF_UNPAUSE_ON_HEADSET_RECONNECT, true);
|
|
}
|
|
|
|
public static boolean isUnpauseOnBluetoothReconnect() {
|
|
return prefs.getBoolean(PREF_UNPAUSE_ON_BLUETOOTH_RECONNECT, false);
|
|
}
|
|
|
|
public static int getHardwareForwardButton() {
|
|
return Integer.parseInt(prefs.getString(PREF_HARDWARE_FORWARD_BUTTON,
|
|
String.valueOf(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD)));
|
|
}
|
|
|
|
public static int getHardwarePreviousButton() {
|
|
return Integer.parseInt(prefs.getString(PREF_HARDWARE_PREVIOUS_BUTTON,
|
|
String.valueOf(KeyEvent.KEYCODE_MEDIA_REWIND)));
|
|
}
|
|
|
|
|
|
public static boolean isFollowQueue() {
|
|
return prefs.getBoolean(PREF_FOLLOW_QUEUE, true);
|
|
}
|
|
|
|
/**
|
|
* Set to true to enable Continuous Playback
|
|
*/
|
|
@VisibleForTesting
|
|
public static void setFollowQueue(boolean value) {
|
|
prefs.edit().putBoolean(UserPreferences.PREF_FOLLOW_QUEUE, value).apply();
|
|
}
|
|
|
|
public static boolean shouldSkipKeepEpisode() {
|
|
return prefs.getBoolean(PREF_SKIP_KEEPS_EPISODE, true);
|
|
}
|
|
|
|
public static boolean shouldFavoriteKeepEpisode() {
|
|
return prefs.getBoolean(PREF_FAVORITE_KEEPS_EPISODE, true);
|
|
}
|
|
|
|
public static boolean isAutoDelete() {
|
|
return prefs.getBoolean(PREF_AUTO_DELETE, false);
|
|
}
|
|
|
|
public static boolean isAutoDeleteLocal() {
|
|
return prefs.getBoolean(PREF_AUTO_DELETE_LOCAL, false);
|
|
}
|
|
|
|
public static int getSmartMarkAsPlayedSecs() {
|
|
return Integer.parseInt(prefs.getString(PREF_SMART_MARK_AS_PLAYED_SECS, "30"));
|
|
}
|
|
|
|
public static boolean shouldDeleteRemoveFromQueue() {
|
|
return prefs.getBoolean(PREF_DELETE_REMOVES_FROM_QUEUE, false);
|
|
}
|
|
|
|
public static float getPlaybackSpeed() {
|
|
try {
|
|
return Float.parseFloat(prefs.getString(PREF_PLAYBACK_SPEED, "1.00"));
|
|
} catch (NumberFormatException e) {
|
|
Log.e(TAG, Log.getStackTraceString(e));
|
|
UserPreferences.setPlaybackSpeed(1.0f);
|
|
return 1.0f;
|
|
}
|
|
}
|
|
|
|
public static boolean isSkipSilence() {
|
|
return prefs.getBoolean(PREF_PLAYBACK_SKIP_SILENCE, false);
|
|
}
|
|
|
|
public static List<Float> getPlaybackSpeedArray() {
|
|
return readPlaybackSpeedArray(prefs.getString(PREF_PLAYBACK_SPEED_ARRAY, null));
|
|
}
|
|
|
|
public static boolean shouldPauseForFocusLoss() {
|
|
return prefs.getBoolean(PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS, true);
|
|
}
|
|
|
|
public static long getUpdateInterval() {
|
|
return Integer.parseInt(prefs.getString(PREF_UPDATE_INTERVAL, "12"));
|
|
}
|
|
|
|
public static boolean isAutoUpdateDisabled() {
|
|
return getUpdateInterval() == 0;
|
|
}
|
|
|
|
private static boolean isAllowMobileFor(String type) {
|
|
HashSet<String> defaultValue = new HashSet<>();
|
|
defaultValue.add("images");
|
|
Set<String> allowed = prefs.getStringSet(PREF_MOBILE_UPDATE, defaultValue);
|
|
return allowed.contains(type);
|
|
}
|
|
|
|
public static boolean isAllowMobileFeedRefresh() {
|
|
return isAllowMobileFor("feed_refresh");
|
|
}
|
|
|
|
public static boolean isAllowMobileSync() {
|
|
return isAllowMobileFor("sync");
|
|
}
|
|
|
|
public static boolean isAllowMobileEpisodeDownload() {
|
|
return isAllowMobileFor("episode_download");
|
|
}
|
|
|
|
public static boolean isAllowMobileAutoDownload() {
|
|
return isAllowMobileFor("auto_download");
|
|
}
|
|
|
|
public static boolean isAllowMobileStreaming() {
|
|
return isAllowMobileFor("streaming");
|
|
}
|
|
|
|
public static boolean isAllowMobileImages() {
|
|
return isAllowMobileFor("images");
|
|
}
|
|
|
|
private static void setAllowMobileFor(String type, boolean allow) {
|
|
HashSet<String> defaultValue = new HashSet<>();
|
|
defaultValue.add("images");
|
|
final Set<String> getValueStringSet = prefs.getStringSet(PREF_MOBILE_UPDATE, defaultValue);
|
|
final Set<String> allowed = new HashSet<>(getValueStringSet);
|
|
if (allow) {
|
|
allowed.add(type);
|
|
} else {
|
|
allowed.remove(type);
|
|
}
|
|
prefs.edit().putStringSet(PREF_MOBILE_UPDATE, allowed).apply();
|
|
}
|
|
|
|
public static void setAllowMobileFeedRefresh(boolean allow) {
|
|
setAllowMobileFor("feed_refresh", allow);
|
|
}
|
|
|
|
public static void setAllowMobileEpisodeDownload(boolean allow) {
|
|
setAllowMobileFor("episode_download", allow);
|
|
}
|
|
|
|
public static void setAllowMobileAutoDownload(boolean allow) {
|
|
setAllowMobileFor("auto_download", allow);
|
|
}
|
|
|
|
public static void setAllowMobileStreaming(boolean allow) {
|
|
setAllowMobileFor("streaming", allow);
|
|
}
|
|
|
|
public static void setAllowMobileImages(boolean allow) {
|
|
setAllowMobileFor("images", allow);
|
|
}
|
|
|
|
public static void setAllowMobileSync(boolean allow) {
|
|
setAllowMobileFor("sync", allow);
|
|
}
|
|
|
|
/**
|
|
* Returns the capacity of the episode cache. This method will return the
|
|
* negative integer EPISODE_CACHE_SIZE_UNLIMITED if the cache size is set to
|
|
* 'unlimited'.
|
|
*/
|
|
public static int getEpisodeCacheSize() {
|
|
return Integer.parseInt(prefs.getString(PREF_EPISODE_CACHE_SIZE, "20"));
|
|
}
|
|
|
|
public static boolean isEnableAutodownload() {
|
|
return prefs.getBoolean(PREF_ENABLE_AUTODL, false);
|
|
}
|
|
|
|
@VisibleForTesting
|
|
public static void setEnableAutodownload(boolean enabled) {
|
|
prefs.edit().putBoolean(PREF_ENABLE_AUTODL, enabled).apply();
|
|
}
|
|
|
|
public static boolean isEnableAutodownloadOnBattery() {
|
|
return prefs.getBoolean(PREF_ENABLE_AUTODL_ON_BATTERY, true);
|
|
}
|
|
|
|
public static boolean isEnableAutodownloadWifiFilter() {
|
|
return Build.VERSION.SDK_INT < 29 && prefs.getBoolean(PREF_ENABLE_AUTODL_WIFI_FILTER, false);
|
|
}
|
|
|
|
public static int getFastForwardSecs() {
|
|
return prefs.getInt(PREF_FAST_FORWARD_SECS, 30);
|
|
}
|
|
|
|
public static int getRewindSecs() {
|
|
return prefs.getInt(PREF_REWIND_SECS, 10);
|
|
}
|
|
|
|
public static String[] getAutodownloadSelectedNetworks() {
|
|
String selectedNetWorks = prefs.getString(PREF_AUTODL_SELECTED_NETWORKS, "");
|
|
return TextUtils.split(selectedNetWorks, ",");
|
|
}
|
|
|
|
public static void setProxyConfig(ProxyConfig config) {
|
|
SharedPreferences.Editor editor = prefs.edit();
|
|
editor.putString(PREF_PROXY_TYPE, config.type.name());
|
|
if (TextUtils.isEmpty(config.host)) {
|
|
editor.remove(PREF_PROXY_HOST);
|
|
} else {
|
|
editor.putString(PREF_PROXY_HOST, config.host);
|
|
}
|
|
if (config.port <= 0 || config.port > 65535) {
|
|
editor.remove(PREF_PROXY_PORT);
|
|
} else {
|
|
editor.putInt(PREF_PROXY_PORT, config.port);
|
|
}
|
|
if (TextUtils.isEmpty(config.username)) {
|
|
editor.remove(PREF_PROXY_USER);
|
|
} else {
|
|
editor.putString(PREF_PROXY_USER, config.username);
|
|
}
|
|
if (TextUtils.isEmpty(config.password)) {
|
|
editor.remove(PREF_PROXY_PASSWORD);
|
|
} else {
|
|
editor.putString(PREF_PROXY_PASSWORD, config.password);
|
|
}
|
|
editor.apply();
|
|
}
|
|
|
|
public static ProxyConfig getProxyConfig() {
|
|
Proxy.Type type = Proxy.Type.valueOf(prefs.getString(PREF_PROXY_TYPE, Proxy.Type.DIRECT.name()));
|
|
String host = prefs.getString(PREF_PROXY_HOST, null);
|
|
int port = prefs.getInt(PREF_PROXY_PORT, 0);
|
|
String username = prefs.getString(PREF_PROXY_USER, null);
|
|
String password = prefs.getString(PREF_PROXY_PASSWORD, null);
|
|
return new ProxyConfig(type, host, port, username, password);
|
|
}
|
|
|
|
public static boolean isQueueLocked() {
|
|
return prefs.getBoolean(PREF_QUEUE_LOCKED, false);
|
|
}
|
|
|
|
public static void setFastForwardSecs(int secs) {
|
|
prefs.edit().putInt(PREF_FAST_FORWARD_SECS, secs).apply();
|
|
}
|
|
|
|
public static void setRewindSecs(int secs) {
|
|
prefs.edit().putInt(PREF_REWIND_SECS, secs).apply();
|
|
}
|
|
|
|
public static void setPlaybackSpeed(float speed) {
|
|
prefs.edit().putString(PREF_PLAYBACK_SPEED, String.valueOf(speed)).apply();
|
|
}
|
|
|
|
public static void setSkipSilence(boolean skipSilence) {
|
|
prefs.edit().putBoolean(PREF_PLAYBACK_SKIP_SILENCE, skipSilence).apply();
|
|
}
|
|
|
|
public static void setPlaybackSpeedArray(List<Float> speeds) {
|
|
DecimalFormatSymbols format = new DecimalFormatSymbols(Locale.US);
|
|
format.setDecimalSeparator('.');
|
|
DecimalFormat speedFormat = new DecimalFormat("0.00", format);
|
|
JSONArray jsonArray = new JSONArray();
|
|
for (float speed : speeds) {
|
|
jsonArray.put(speedFormat.format(speed));
|
|
}
|
|
prefs.edit().putString(PREF_PLAYBACK_SPEED_ARRAY, jsonArray.toString()).apply();
|
|
}
|
|
|
|
public static void setAutodownloadSelectedNetworks(String[] value) {
|
|
prefs.edit().putString(PREF_AUTODL_SELECTED_NETWORKS, TextUtils.join(",", value)).apply();
|
|
}
|
|
|
|
public static boolean gpodnetNotificationsEnabled() {
|
|
if (Build.VERSION.SDK_INT >= 26) {
|
|
return true; // System handles notification preferences
|
|
}
|
|
return prefs.getBoolean(PREF_GPODNET_NOTIFICATIONS, true);
|
|
}
|
|
|
|
/**
|
|
* Used for migration of the preference to system notification channels.
|
|
*/
|
|
public static boolean getGpodnetNotificationsEnabledRaw() {
|
|
return prefs.getBoolean(PREF_GPODNET_NOTIFICATIONS, true);
|
|
}
|
|
|
|
public static void setGpodnetNotificationsEnabled() {
|
|
prefs.edit().putBoolean(PREF_GPODNET_NOTIFICATIONS, true).apply();
|
|
}
|
|
|
|
public static void setHiddenDrawerItems(List<String> items) {
|
|
String str = TextUtils.join(",", items);
|
|
prefs.edit().putString(PREF_HIDDEN_DRAWER_ITEMS, str).apply();
|
|
}
|
|
|
|
public static void setFullNotificationButtons(List<Integer> items) {
|
|
String str = TextUtils.join(",", items);
|
|
prefs.edit().putString(PREF_FULL_NOTIFICATION_BUTTONS, str).apply();
|
|
}
|
|
|
|
public static void setQueueLocked(boolean locked) {
|
|
prefs.edit().putBoolean(PREF_QUEUE_LOCKED, locked).apply();
|
|
}
|
|
|
|
private static List<Float> readPlaybackSpeedArray(String valueFromPrefs) {
|
|
if (valueFromPrefs != null) {
|
|
try {
|
|
JSONArray jsonArray = new JSONArray(valueFromPrefs);
|
|
List<Float> selectedSpeeds = new ArrayList<>();
|
|
for (int i = 0; i < jsonArray.length(); i++) {
|
|
selectedSpeeds.add((float) jsonArray.getDouble(i));
|
|
}
|
|
return selectedSpeeds;
|
|
} catch (JSONException e) {
|
|
Log.e(TAG, "Got JSON error when trying to get speeds from JSONArray");
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
// If this preference hasn't been set yet, return the default options
|
|
return Arrays.asList(1.0f, 1.25f, 1.5f);
|
|
}
|
|
|
|
public static int getEpisodeCleanupValue() {
|
|
return Integer.parseInt(prefs.getString(PREF_EPISODE_CLEANUP, "" + EPISODE_CLEANUP_NULL));
|
|
}
|
|
|
|
public static void setEpisodeCleanupValue(int episodeCleanupValue) {
|
|
prefs.edit().putString(PREF_EPISODE_CLEANUP, Integer.toString(episodeCleanupValue)).apply();
|
|
}
|
|
|
|
/**
|
|
* Return the folder where the app stores all of its data. This method will
|
|
* return the standard data folder if none has been set by the user.
|
|
*
|
|
* @param type The name of the folder inside the data folder. May be null
|
|
* when accessing the root of the data folder.
|
|
* @return The data folder that has been requested or null if the folder could not be created.
|
|
*/
|
|
public static File getDataFolder(@Nullable String type) {
|
|
File dataFolder = getTypeDir(prefs.getString(PREF_DATA_FOLDER, null), type);
|
|
if (dataFolder == null || !dataFolder.canWrite()) {
|
|
Log.d(TAG, "User data folder not writable or not set. Trying default.");
|
|
dataFolder = context.getExternalFilesDir(type);
|
|
}
|
|
if (dataFolder == null || !dataFolder.canWrite()) {
|
|
Log.d(TAG, "Default data folder not available or not writable. Falling back to internal memory.");
|
|
dataFolder = getTypeDir(context.getFilesDir().getAbsolutePath(), type);
|
|
}
|
|
return dataFolder;
|
|
}
|
|
|
|
@Nullable
|
|
private static File getTypeDir(@Nullable String baseDirPath, @Nullable String type) {
|
|
if (baseDirPath == null) {
|
|
return null;
|
|
}
|
|
File baseDir = new File(baseDirPath);
|
|
File typeDir = type == null ? baseDir : new File(baseDir, type);
|
|
if (!typeDir.exists()) {
|
|
if (!baseDir.canWrite()) {
|
|
Log.e(TAG, "Base dir is not writable " + baseDir.getAbsolutePath());
|
|
return null;
|
|
}
|
|
if (!typeDir.mkdirs()) {
|
|
Log.e(TAG, "Could not create type dir " + typeDir.getAbsolutePath());
|
|
return null;
|
|
}
|
|
}
|
|
return typeDir;
|
|
}
|
|
|
|
public static void setDataFolder(String dir) {
|
|
Log.d(TAG, "setDataFolder(dir: " + dir + ")");
|
|
prefs.edit().putString(PREF_DATA_FOLDER, dir).apply();
|
|
}
|
|
|
|
/**
|
|
* Create a .nomedia file to prevent scanning by the media scanner.
|
|
*/
|
|
private static void createNoMediaFile() {
|
|
File f = new File(context.getExternalFilesDir(null), ".nomedia");
|
|
if (!f.exists()) {
|
|
try {
|
|
f.createNewFile();
|
|
} catch (IOException e) {
|
|
Log.e(TAG, "Could not create .nomedia file");
|
|
e.printStackTrace();
|
|
}
|
|
Log.d(TAG, ".nomedia file created");
|
|
}
|
|
}
|
|
|
|
public static String getDefaultPage() {
|
|
return prefs.getString(PREF_DEFAULT_PAGE, "HomeFragment");
|
|
}
|
|
|
|
public static void setDefaultPage(String defaultPage) {
|
|
prefs.edit().putString(PREF_DEFAULT_PAGE, defaultPage).apply();
|
|
}
|
|
|
|
public static boolean backButtonOpensDrawer() {
|
|
return prefs.getBoolean(PREF_BACK_OPENS_DRAWER, false);
|
|
}
|
|
|
|
public static boolean timeRespectsSpeed() {
|
|
return prefs.getBoolean(PREF_TIME_RESPECTS_SPEED, false);
|
|
}
|
|
|
|
public static boolean isStreamOverDownload() {
|
|
return prefs.getBoolean(PREF_STREAM_OVER_DOWNLOAD, false);
|
|
}
|
|
|
|
public static void setStreamOverDownload(boolean stream) {
|
|
prefs.edit().putBoolean(PREF_STREAM_OVER_DOWNLOAD, stream).apply();
|
|
}
|
|
|
|
/**
|
|
* Returns if the queue is in keep sorted mode.
|
|
*
|
|
* @see #getQueueKeepSortedOrder()
|
|
*/
|
|
public static boolean isQueueKeepSorted() {
|
|
return prefs.getBoolean(PREF_QUEUE_KEEP_SORTED, false);
|
|
}
|
|
|
|
/**
|
|
* Enables/disables the keep sorted mode of the queue.
|
|
*
|
|
* @see #setQueueKeepSortedOrder(SortOrder)
|
|
*/
|
|
public static void setQueueKeepSorted(boolean keepSorted) {
|
|
prefs.edit().putBoolean(PREF_QUEUE_KEEP_SORTED, keepSorted).apply();
|
|
}
|
|
|
|
/**
|
|
* Returns the sort order for the queue keep sorted mode.
|
|
* Note: This value is stored independently from the keep sorted state.
|
|
*
|
|
* @see #isQueueKeepSorted()
|
|
*/
|
|
public static SortOrder getQueueKeepSortedOrder() {
|
|
String sortOrderStr = prefs.getString(PREF_QUEUE_KEEP_SORTED_ORDER, "use-default");
|
|
return SortOrder.parseWithDefault(sortOrderStr, SortOrder.DATE_NEW_OLD);
|
|
}
|
|
|
|
/**
|
|
* Sets the sort order for the queue keep sorted mode.
|
|
*
|
|
* @see #setQueueKeepSorted(boolean)
|
|
*/
|
|
public static void setQueueKeepSortedOrder(SortOrder sortOrder) {
|
|
if (sortOrder == null) {
|
|
return;
|
|
}
|
|
prefs.edit().putString(PREF_QUEUE_KEEP_SORTED_ORDER, sortOrder.name()).apply();
|
|
}
|
|
|
|
public static FeedPreferences.NewEpisodesAction getNewEpisodesAction() {
|
|
String str = prefs.getString(PREF_NEW_EPISODES_ACTION,
|
|
"" + FeedPreferences.NewEpisodesAction.ADD_TO_INBOX.code);
|
|
return FeedPreferences.NewEpisodesAction.fromCode(Integer.parseInt(str));
|
|
}
|
|
|
|
/**
|
|
* Returns the sort order for the downloads.
|
|
*/
|
|
public static SortOrder getDownloadsSortedOrder() {
|
|
String sortOrderStr = prefs.getString(PREF_DOWNLOADS_SORTED_ORDER, "" + SortOrder.DATE_NEW_OLD.code);
|
|
return SortOrder.fromCodeString(sortOrderStr);
|
|
}
|
|
|
|
/**
|
|
* Sets the sort order for the downloads.
|
|
*/
|
|
public static void setDownloadsSortedOrder(SortOrder sortOrder) {
|
|
prefs.edit().putString(PREF_DOWNLOADS_SORTED_ORDER, "" + sortOrder.code).apply();
|
|
}
|
|
|
|
public static SortOrder getInboxSortedOrder() {
|
|
String sortOrderStr = prefs.getString(PREF_INBOX_SORTED_ORDER, "" + SortOrder.DATE_NEW_OLD.code);
|
|
return SortOrder.fromCodeString(sortOrderStr);
|
|
}
|
|
|
|
public static void setInboxSortedOrder(SortOrder sortOrder) {
|
|
prefs.edit().putString(PREF_INBOX_SORTED_ORDER, "" + sortOrder.code).apply();
|
|
}
|
|
|
|
public static SubscriptionsFilter getSubscriptionsFilter() {
|
|
String value = prefs.getString(PREF_FILTER_FEED, "");
|
|
return new SubscriptionsFilter(value);
|
|
}
|
|
|
|
public static void setSubscriptionsFilter(SubscriptionsFilter value) {
|
|
prefs.edit().putString(PREF_FILTER_FEED, value.serialize()).apply();
|
|
}
|
|
|
|
public static boolean shouldShowSubscriptionTitle() {
|
|
return prefs.getBoolean(PREF_SUBSCRIPTION_TITLE, false);
|
|
}
|
|
|
|
public static void setAllEpisodesSortOrder(SortOrder s) {
|
|
prefs.edit().putString(PREF_SORT_ALL_EPISODES, "" + s.code).apply();
|
|
}
|
|
|
|
public static SortOrder getAllEpisodesSortOrder() {
|
|
return SortOrder.fromCodeString(prefs.getString(PREF_SORT_ALL_EPISODES,
|
|
"" + SortOrder.DATE_NEW_OLD.code));
|
|
}
|
|
|
|
public static String getPrefFilterAllEpisodes() {
|
|
return prefs.getString(PREF_FILTER_ALL_EPISODES, "");
|
|
}
|
|
|
|
public static void setPrefFilterAllEpisodes(String filter) {
|
|
prefs.edit().putString(PREF_FILTER_ALL_EPISODES, filter).apply();
|
|
}
|
|
}
|