Merge pull request #2688 from orionlee/auto_download_12_hour_option_2685

Episode Cleanup (for automatic download) - support 12 hours after finishing
This commit is contained in:
H. Lehmann 2019-02-01 16:31:45 +01:00 committed by GitHub
commit 91987460db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 94 additions and 28 deletions

View File

@ -32,7 +32,7 @@ android {
// Version code schema:
// "1.2.3-SNAPSHOT" -> 1020300
// "1.2.3-RC4" -> 1020304
versionCode 1070195
versionCode 1070196
versionName "1.7.1"
testApplicationId "de.test.antennapod"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

View File

@ -7,18 +7,9 @@ import android.support.test.espresso.contrib.RecyclerViewActions;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.view.View;
import com.robotium.solo.Solo;
import com.robotium.solo.Timeout;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.PreferenceActivity;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.APCleanupAlgorithm;
import de.danoeh.antennapod.core.storage.APNullCleanupAlgorithm;
import de.danoeh.antennapod.core.storage.APQueueCleanupAlgorithm;
import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithm;
import de.danoeh.antennapod.fragment.EpisodesFragment;
import de.danoeh.antennapod.fragment.QueueFragment;
import de.danoeh.antennapod.fragment.SubscriptionFragment;
import org.hamcrest.Matcher;
import org.junit.After;
@ -30,6 +21,17 @@ import org.junit.runner.RunWith;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.PreferenceActivity;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.APCleanupAlgorithm;
import de.danoeh.antennapod.core.storage.APNullCleanupAlgorithm;
import de.danoeh.antennapod.core.storage.APQueueCleanupAlgorithm;
import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithm;
import de.danoeh.antennapod.fragment.EpisodesFragment;
import de.danoeh.antennapod.fragment.QueueFragment;
import de.danoeh.antennapod.fragment.SubscriptionFragment;
import static android.support.test.InstrumentationRegistry.getInstrumentation;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
@ -397,7 +399,7 @@ public class PreferencesTest {
EpisodeCleanupAlgorithm alg = UserPreferences.getEpisodeCleanupAlgorithm();
if (alg instanceof APCleanupAlgorithm) {
APCleanupAlgorithm cleanupAlg = (APCleanupAlgorithm)alg;
return cleanupAlg.getNumberOfDaysAfterPlayback() == 0;
return cleanupAlg.getNumberOfHoursAfterPlayback() == 0;
}
return false;
},
@ -416,7 +418,7 @@ public class PreferencesTest {
EpisodeCleanupAlgorithm alg = UserPreferences.getEpisodeCleanupAlgorithm();
if (alg instanceof APCleanupAlgorithm) {
APCleanupAlgorithm cleanupAlg = (APCleanupAlgorithm)alg;
return cleanupAlg.getNumberOfDaysAfterPlayback() == 5;
return cleanupAlg.getNumberOfHoursAfterPlayback() == 120; // 5 days
}
return false;
},

View File

@ -846,8 +846,11 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
entries[x] = res.getString(R.string.episode_cleanup_never);
} else if (v == 0) {
entries[x] = res.getString(R.string.episode_cleanup_after_listening);
} else if (v > 0 && v < 24) {
entries[x] = res.getQuantityString(R.plurals.episode_cleanup_hours_after_listening, v, v);
} else {
entries[x] = res.getQuantityString(R.plurals.episode_cleanup_days_after_listening, v, v);
int numDays = (int)(v / 24); // assume underlying value will be NOT fraction of days, e.g., 36 (hours)
entries[x] = res.getQuantityString(R.plurals.episode_cleanup_days_after_listening, numDays, numDays);
}
}
pref.setEntries(entries);

View File

@ -58,11 +58,19 @@ class UpdateManager {
}
private static void onUpgrade(final int oldVersionCode, final int newVersionCode) {
if(oldVersionCode < 1050004) {
if (oldVersionCode < 1050004) {
if(MediaPlayer.isPrestoLibraryInstalled(context) && Build.VERSION.SDK_INT >= 16) {
UserPreferences.enableSonic();
}
}
if (oldVersionCode < 1070196) {
// migrate episode cleanup value (unit changed from days to hours)
int oldValueInDays = UserPreferences.getEpisodeCleanupValue();
if (oldValueInDays > 0) {
UserPreferences.setEpisodeCleanupValue(oldValueInDays * 24);
} // else 0 or special negative values, no change needed
}
}
}

View File

@ -691,7 +691,7 @@ public class UserPreferences {
}
public static EpisodeCleanupAlgorithm getEpisodeCleanupAlgorithm() {
int cleanupValue = Integer.parseInt(prefs.getString(PREF_EPISODE_CLEANUP, "-1"));
int cleanupValue = getEpisodeCleanupValue();
if (cleanupValue == EPISODE_CLEANUP_QUEUE) {
return new APQueueCleanupAlgorithm();
} else if (cleanupValue == EPISODE_CLEANUP_NULL) {
@ -701,6 +701,16 @@ public class UserPreferences {
}
}
public static int getEpisodeCleanupValue() {
return Integer.parseInt(prefs.getString(PREF_EPISODE_CLEANUP, "-1"));
}
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.

View File

@ -2,6 +2,7 @@ package de.danoeh.antennapod.core.storage;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
import java.util.ArrayList;
@ -20,11 +21,12 @@ import de.danoeh.antennapod.core.feed.FeedMedia;
public class APCleanupAlgorithm extends EpisodeCleanupAlgorithm {
private static final String TAG = "APCleanupAlgorithm";
/** the number of days after playback to wait before an item is eligible to be cleaned up */
private final int numberOfDaysAfterPlayback;
/** the number of days after playback to wait before an item is eligible to be cleaned up.
Fractional for number of hours, e.g., 0.5 = 12 hours, 0.0416 = 1 hour. */
private final int numberOfHoursAfterPlayback;
public APCleanupAlgorithm(int numberOfDaysAfterPlayback) {
this.numberOfDaysAfterPlayback = numberOfDaysAfterPlayback;
public APCleanupAlgorithm(int numberOfHoursAfterPlayback) {
this.numberOfHoursAfterPlayback = numberOfHoursAfterPlayback;
}
/**
@ -77,13 +79,17 @@ public class APCleanupAlgorithm extends EpisodeCleanupAlgorithm {
return counter;
}
@VisibleForTesting
Date calcMostRecentDateForDeletion(@NonNull Date currentDate) {
return minusHours(currentDate, numberOfHoursAfterPlayback);
}
@NonNull
private List<FeedItem> getCandidates() {
List<FeedItem> candidates = new ArrayList<>();
List<FeedItem> downloadedItems = DBReader.getDownloadedItems();
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_MONTH, -1 * numberOfDaysAfterPlayback);
Date mostRecentDateForDeletion = cal.getTime();
Date mostRecentDateForDeletion = calcMostRecentDateForDeletion(new Date());
for (FeedItem item : downloadedItems) {
if (item.hasMedia()
&& item.getMedia().isDownloaded()
@ -108,5 +114,16 @@ public class APCleanupAlgorithm extends EpisodeCleanupAlgorithm {
return getNumEpisodesToCleanup(0);
}
public int getNumberOfDaysAfterPlayback() { return numberOfDaysAfterPlayback; }
@VisibleForTesting
public int getNumberOfHoursAfterPlayback() { return numberOfHoursAfterPlayback; }
private static Date minusHours(Date baseDate, int numberOfHours) {
Calendar cal = Calendar.getInstance();
cal.setTime(baseDate);
cal.add(Calendar.HOUR_OF_DAY, -1 * numberOfHours);
return cal.getTime();
}
}

View File

@ -130,6 +130,7 @@ public final class Converter {
return String.format(Locale.getDefault(), "%.1f ", hours) + context.getString(R.string.time_hours);
}
/**
* Converts the volume as read as the progress from a SeekBar scaled to 100 and as saved in
* UserPreferences to the format taken by setVolume methods.

View File

@ -68,10 +68,11 @@
<string-array name="episode_cleanup_values">
<item>-1</item>
<item>0</item>
<item>1</item>
<item>3</item>
<item>5</item>
<item>7</item>
<item>12</item>
<item>24</item>
<item>72</item>
<item>120</item>
<item>168</item>
<item>-2</item>
</string-array>

View File

@ -105,6 +105,10 @@
<string name="episode_cleanup_never">Never</string>
<string name="episode_cleanup_queue_removal">When not in queue</string>
<string name="episode_cleanup_after_listening">After finishing</string>
<plurals name="episode_cleanup_hours_after_listening">
<item quantity="one">1 hour after finishing</item>
<item quantity="other">%d hours after finishing</item>
</plurals>
<plurals name="episode_cleanup_days_after_listening">
<item quantity="one">1 day after finishing</item>
<item quantity="other">%d days after finishing</item>

View File

@ -0,0 +1,20 @@
package de.danoeh.antennapod.core.storage;
import org.junit.Test;
import java.text.SimpleDateFormat;
import java.util.Date;
import static org.junit.Assert.assertEquals;
public class APCleanupAlgorithmTest {
@Test
public void testCalcMostRecentDateForDeletion() throws Exception {
APCleanupAlgorithm algo = new APCleanupAlgorithm(24);
Date curDateForTest = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse("2018-11-13T14:08:56-0800");
Date resExpected = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse("2018-11-12T14:08:56-0800");
Date resActual = algo.calcMostRecentDateForDeletion(curDateForTest);
assertEquals("cutoff for retaining most recent 1 day", resExpected, resActual);
}
}