summaryrefslogtreecommitdiff
path: root/storage/preferences
diff options
context:
space:
mode:
authorByteHamster <ByteHamster@users.noreply.github.com>2024-03-24 21:08:06 +0100
committerGitHub <noreply@github.com>2024-03-24 21:08:06 +0100
commit4078b3475e5140e6f5f9ef924bc8ff8d9e345113 (patch)
tree46c619e1f35649f504af8789ff61d98d2a29e6d0 /storage/preferences
parent7b390f1c9299d644ad0339e83724e1457c150410 (diff)
downloadAntennaPod-4078b3475e5140e6f5f9ef924bc8ff8d9e345113.zip
Simplify playback preferences and move to :storage:preferences (#7024)
Diffstat (limited to 'storage/preferences')
-rw-r--r--storage/preferences/src/main/java/de/danoeh/antennapod/storage/preferences/PlaybackPreferences.java170
-rw-r--r--storage/preferences/src/main/java/de/danoeh/antennapod/storage/preferences/SleepTimerPreferences.java106
-rw-r--r--storage/preferences/src/main/java/de/danoeh/antennapod/storage/preferences/UsageStatistics.java70
3 files changed, 346 insertions, 0 deletions
diff --git a/storage/preferences/src/main/java/de/danoeh/antennapod/storage/preferences/PlaybackPreferences.java b/storage/preferences/src/main/java/de/danoeh/antennapod/storage/preferences/PlaybackPreferences.java
new file mode 100644
index 000000000..d6d260446
--- /dev/null
+++ b/storage/preferences/src/main/java/de/danoeh/antennapod/storage/preferences/PlaybackPreferences.java
@@ -0,0 +1,170 @@
+package de.danoeh.antennapod.storage.preferences;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import androidx.preference.PreferenceManager;
+
+import android.util.Log;
+import de.danoeh.antennapod.model.feed.FeedMedia;
+import de.danoeh.antennapod.model.feed.FeedPreferences;
+import de.danoeh.antennapod.model.playback.MediaType;
+import de.danoeh.antennapod.model.playback.Playable;
+
+/**
+ * Provides access to preferences set by the playback service. A private
+ * instance of this class must first be instantiated via createInstance() or
+ * otherwise every public method will throw an Exception when called.
+ */
+public abstract class PlaybackPreferences {
+
+ private static final String TAG = "PlaybackPreferences";
+
+ /**
+ * Contains the feed id of the currently playing item if it is a FeedMedia
+ * object.
+ */
+ private static final String PREF_CURRENTLY_PLAYING_FEED_ID = "de.danoeh.antennapod.preferences.lastPlayedFeedId";
+
+ /**
+ * Contains the id of the currently playing FeedMedia object or
+ * NO_MEDIA_PLAYING if the currently playing media is no FeedMedia object.
+ */
+ private static final String PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID
+ = "de.danoeh.antennapod.preferences.lastPlayedFeedMediaId";
+
+ /**
+ * Type of the media object that is currently being played. This preference
+ * is set to NO_MEDIA_PLAYING after playback has been completed and is set
+ * as soon as the 'play' button is pressed.
+ */
+ private static final String PREF_CURRENTLY_PLAYING_MEDIA_TYPE
+ = "de.danoeh.antennapod.preferences.currentlyPlayingMedia";
+
+ /**
+ * True if last played media was a video.
+ */
+ private static final String PREF_CURRENT_EPISODE_IS_VIDEO = "de.danoeh.antennapod.preferences.lastIsVideo";
+
+ /**
+ * The current player status as int.
+ */
+ private static final String PREF_CURRENT_PLAYER_STATUS = "de.danoeh.antennapod.preferences.currentPlayerStatus";
+
+ /**
+ * A temporary playback speed which overrides the per-feed playback speed for the currently playing
+ * media. Considered unset if set to SPEED_USE_GLOBAL;
+ */
+ private static final String PREF_CURRENTLY_PLAYING_TEMPORARY_PLAYBACK_SPEED
+ = "de.danoeh.antennapod.preferences.temporaryPlaybackSpeed";
+
+ /**
+ * A temporary skip silence preference which overrides the per-feed skip silence for the currently playing
+ * media. Considered unset if set to null;
+ */
+ private static final String PREF_CURRENTLY_PLAYING_TEMPORARY_SKIP_SILENCE
+ = "de.danoeh.antennapod.preferences.temporarySkipSilence";
+
+ /**
+ * Value of PREF_CURRENTLY_PLAYING_MEDIA if no media is playing.
+ */
+ public static final long NO_MEDIA_PLAYING = -1;
+
+ /**
+ * Value of PREF_CURRENT_PLAYER_STATUS if media player status is playing.
+ */
+ public static final int PLAYER_STATUS_PLAYING = 1;
+
+ /**
+ * Value of PREF_CURRENT_PLAYER_STATUS if media player status is paused.
+ */
+ public static final int PLAYER_STATUS_PAUSED = 2;
+
+ /**
+ * Value of PREF_CURRENT_PLAYER_STATUS if media player status is neither playing nor paused.
+ */
+ public static final int PLAYER_STATUS_OTHER = 3;
+
+ private static SharedPreferences prefs;
+
+ public static void init(Context context) {
+ prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ }
+
+ public static long getCurrentlyPlayingMediaType() {
+ return prefs.getLong(PREF_CURRENTLY_PLAYING_MEDIA_TYPE, NO_MEDIA_PLAYING);
+ }
+
+ public static long getCurrentlyPlayingFeedMediaId() {
+ if (PlaybackPreferences.getCurrentlyPlayingMediaType() == NO_MEDIA_PLAYING) {
+ return NO_MEDIA_PLAYING;
+ }
+ return prefs.getLong(PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID, NO_MEDIA_PLAYING);
+ }
+
+ public static boolean getCurrentEpisodeIsVideo() {
+ return prefs.getBoolean(PREF_CURRENT_EPISODE_IS_VIDEO, false);
+ }
+
+ public static int getCurrentPlayerStatus() {
+ return prefs.getInt(PREF_CURRENT_PLAYER_STATUS, PLAYER_STATUS_OTHER);
+ }
+
+ public static float getCurrentlyPlayingTemporaryPlaybackSpeed() {
+ return prefs.getFloat(PREF_CURRENTLY_PLAYING_TEMPORARY_PLAYBACK_SPEED, FeedPreferences.SPEED_USE_GLOBAL);
+ }
+
+ public static FeedPreferences.SkipSilence getCurrentlyPlayingTemporarySkipSilence() {
+ return FeedPreferences.SkipSilence.fromCode(prefs.getInt(
+ PREF_CURRENTLY_PLAYING_TEMPORARY_SKIP_SILENCE, FeedPreferences.SkipSilence.GLOBAL.code));
+ }
+
+ public static void writeNoMediaPlaying() {
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putLong(PREF_CURRENTLY_PLAYING_MEDIA_TYPE, NO_MEDIA_PLAYING);
+ editor.putLong(PREF_CURRENTLY_PLAYING_FEED_ID, NO_MEDIA_PLAYING);
+ editor.putLong(PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID, NO_MEDIA_PLAYING);
+ editor.putInt(PREF_CURRENT_PLAYER_STATUS, PLAYER_STATUS_OTHER);
+ editor.apply();
+ }
+
+ public static void writeMediaPlaying(Playable playable) {
+ Log.d(TAG, "Writing playback preferences");
+ SharedPreferences.Editor editor = prefs.edit();
+
+ if (playable == null) {
+ writeNoMediaPlaying();
+ } else {
+ editor.putLong(PREF_CURRENTLY_PLAYING_MEDIA_TYPE, playable.getPlayableType());
+ editor.putBoolean(PREF_CURRENT_EPISODE_IS_VIDEO, playable.getMediaType() == MediaType.VIDEO);
+ if (playable instanceof FeedMedia) {
+ FeedMedia feedMedia = (FeedMedia) playable;
+ editor.putLong(PREF_CURRENTLY_PLAYING_FEED_ID, feedMedia.getItem().getFeed().getId());
+ editor.putLong(PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID, feedMedia.getId());
+ } else {
+ editor.putLong(PREF_CURRENTLY_PLAYING_FEED_ID, NO_MEDIA_PLAYING);
+ editor.putLong(PREF_CURRENTLY_PLAYING_FEEDMEDIA_ID, NO_MEDIA_PLAYING);
+ }
+ }
+ editor.apply();
+ }
+
+ public static void setCurrentlyPlayingTemporaryPlaybackSpeed(float speed) {
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putFloat(PREF_CURRENTLY_PLAYING_TEMPORARY_PLAYBACK_SPEED, speed);
+ editor.apply();
+ }
+
+ public static void setCurrentlyPlayingTemporarySkipSilence(boolean skipSilence) {
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putInt(PREF_CURRENTLY_PLAYING_TEMPORARY_SKIP_SILENCE, skipSilence
+ ? FeedPreferences.SkipSilence.AGGRESSIVE.code : FeedPreferences.SkipSilence.OFF.code);
+ editor.apply();
+ }
+
+ public static void clearCurrentlyPlayingTemporaryPlaybackSettings() {
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.remove(PREF_CURRENTLY_PLAYING_TEMPORARY_PLAYBACK_SPEED);
+ editor.remove(PREF_CURRENTLY_PLAYING_TEMPORARY_SKIP_SILENCE);
+ editor.apply();
+ }
+}
diff --git a/storage/preferences/src/main/java/de/danoeh/antennapod/storage/preferences/SleepTimerPreferences.java b/storage/preferences/src/main/java/de/danoeh/antennapod/storage/preferences/SleepTimerPreferences.java
new file mode 100644
index 000000000..5c2643c51
--- /dev/null
+++ b/storage/preferences/src/main/java/de/danoeh/antennapod/storage/preferences/SleepTimerPreferences.java
@@ -0,0 +1,106 @@
+package de.danoeh.antennapod.storage.preferences;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.util.concurrent.TimeUnit;
+
+public class SleepTimerPreferences {
+
+ private static final String TAG = "SleepTimerPreferences";
+
+ public static final String PREF_NAME = "SleepTimerDialog";
+ private static final String PREF_VALUE = "LastValue";
+
+ private static final String PREF_VIBRATE = "Vibrate";
+ private static final String PREF_SHAKE_TO_RESET = "ShakeToReset";
+ private static final String PREF_AUTO_ENABLE = "AutoEnable";
+ private static final String PREF_AUTO_ENABLE_FROM = "AutoEnableFrom";
+ private static final String PREF_AUTO_ENABLE_TO = "AutoEnableTo";
+
+ private static final String DEFAULT_LAST_TIMER = "15";
+ private static final int DEFAULT_AUTO_ENABLE_FROM = 22;
+ private static final int DEFAULT_AUTO_ENABLE_TO = 6;
+
+ 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 SleepTimerPreferences");
+ SleepTimerPreferences.prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
+ }
+
+ public static void setLastTimer(String value) {
+ prefs.edit().putString(PREF_VALUE, value).apply();
+ }
+
+ public static String lastTimerValue() {
+ return prefs.getString(PREF_VALUE, DEFAULT_LAST_TIMER);
+ }
+
+ public static long timerMillis() {
+ long value = Long.parseLong(lastTimerValue());
+ return TimeUnit.MINUTES.toMillis(value);
+ }
+
+ public static void setVibrate(boolean vibrate) {
+ prefs.edit().putBoolean(PREF_VIBRATE, vibrate).apply();
+ }
+
+ public static boolean vibrate() {
+ return prefs.getBoolean(PREF_VIBRATE, false);
+ }
+
+ public static void setShakeToReset(boolean shakeToReset) {
+ prefs.edit().putBoolean(PREF_SHAKE_TO_RESET, shakeToReset).apply();
+ }
+
+ public static boolean shakeToReset() {
+ return prefs.getBoolean(PREF_SHAKE_TO_RESET, true);
+ }
+
+ public static void setAutoEnable(boolean autoEnable) {
+ prefs.edit().putBoolean(PREF_AUTO_ENABLE, autoEnable).apply();
+ }
+
+ public static boolean autoEnable() {
+ return prefs.getBoolean(PREF_AUTO_ENABLE, false);
+ }
+
+ public static void setAutoEnableFrom(int hourOfDay) {
+ prefs.edit().putInt(PREF_AUTO_ENABLE_FROM, hourOfDay).apply();
+ }
+
+ public static int autoEnableFrom() {
+ return prefs.getInt(PREF_AUTO_ENABLE_FROM, DEFAULT_AUTO_ENABLE_FROM);
+ }
+
+ public static void setAutoEnableTo(int hourOfDay) {
+ prefs.edit().putInt(PREF_AUTO_ENABLE_TO, hourOfDay).apply();
+ }
+
+ public static int autoEnableTo() {
+ return prefs.getInt(PREF_AUTO_ENABLE_TO, DEFAULT_AUTO_ENABLE_TO);
+ }
+
+ public static boolean isInTimeRange(int from, int to, int current) {
+ // Range covers one day
+ if (from < to) {
+ return from <= current && current < to;
+ }
+
+ // Range covers two days
+ if (from <= current) {
+ return true;
+ }
+
+ return current < to;
+ }
+}
diff --git a/storage/preferences/src/main/java/de/danoeh/antennapod/storage/preferences/UsageStatistics.java b/storage/preferences/src/main/java/de/danoeh/antennapod/storage/preferences/UsageStatistics.java
new file mode 100644
index 000000000..e8da0d194
--- /dev/null
+++ b/storage/preferences/src/main/java/de/danoeh/antennapod/storage/preferences/UsageStatistics.java
@@ -0,0 +1,70 @@
+package de.danoeh.antennapod.storage.preferences;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import androidx.annotation.NonNull;
+
+/**
+ * Collects statistics about the app usage. The statistics are used to allow on-demand configuration:
+ * "Looks like you stream a lot. Do you want to toggle the 'Prefer streaming' setting?".
+ * The data is only stored locally on the device. It is NOT used for analytics/tracking.
+ * A private instance of this class must first be instantiated via
+ * init() or otherwise every public method will throw an Exception
+ * when called.
+ */
+public class UsageStatistics {
+ private UsageStatistics() {
+
+ }
+
+ private static final String PREF_DB_NAME = "UsageStatistics";
+ private static final float MOVING_AVERAGE_WEIGHT = 0.8f;
+ private static final float MOVING_AVERAGE_BIAS_THRESHOLD = 0.1f;
+ private static final String SUFFIX_HIDDEN = "_hidden";
+ private static SharedPreferences prefs;
+
+ public static final StatsAction ACTION_STREAM = new StatsAction("downloadVsStream", 0);
+ public static final StatsAction ACTION_DOWNLOAD = new StatsAction("downloadVsStream", 1);
+
+ /**
+ * Sets up the UsageStatistics class.
+ *
+ * @throws IllegalArgumentException if context is null
+ */
+ public static void init(@NonNull Context context) {
+ prefs = context.getSharedPreferences(PREF_DB_NAME, Context.MODE_PRIVATE);
+ }
+
+ public static void logAction(StatsAction action) {
+ int numExecutions = prefs.getInt(action.type + action.value, 0);
+ float movingAverage = prefs.getFloat(action.type, 0.5f);
+ prefs.edit()
+ .putInt(action.type + action.value, numExecutions + 1)
+ .putFloat(action.type, MOVING_AVERAGE_WEIGHT * movingAverage
+ + (1 - MOVING_AVERAGE_WEIGHT) * action.value)
+ .apply();
+ }
+
+ public static boolean hasSignificantBiasTo(StatsAction action) {
+ if (prefs.getBoolean(action.type + SUFFIX_HIDDEN, false)) {
+ return false;
+ } else {
+ final float movingAverage = prefs.getFloat(action.type, 0.5f);
+ return Math.abs(action.value - movingAverage) < MOVING_AVERAGE_BIAS_THRESHOLD;
+ }
+ }
+
+ public static void doNotAskAgain(StatsAction action) {
+ prefs.edit().putBoolean(action.type + SUFFIX_HIDDEN, true).apply();
+ }
+
+ public static final class StatsAction {
+ public final String type;
+ public final int value;
+
+ public StatsAction(String type, int value) {
+ this.type = type;
+ this.value = value;
+ }
+ }
+}