mirror of
https://github.com/AntennaPod/AntennaPod.git
synced 2025-02-02 19:56:59 +01:00
Merge pull request #1241 from TomHennen/cleanup_algorithm
Cleanup algorithm updates
This commit is contained in:
commit
95cc133e0a
@ -0,0 +1,212 @@
|
||||
package de.test.antennapod.storage;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.test.FlakyTest;
|
||||
import android.test.InstrumentationTestCase;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.storage.DBTasks;
|
||||
import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
||||
|
||||
import static de.test.antennapod.storage.DBTestUtils.saveFeedlist;
|
||||
|
||||
/**
|
||||
* Test class for DBTasks
|
||||
*/
|
||||
public class DBCleanupTests extends InstrumentationTestCase {
|
||||
|
||||
private static final String TAG = "DBTasksTest";
|
||||
protected static final int EPISODE_CACHE_SIZE = 5;
|
||||
private final int cleanupAlgorithm;
|
||||
|
||||
protected Context context;
|
||||
|
||||
protected File destFolder;
|
||||
|
||||
public DBCleanupTests() {
|
||||
this.cleanupAlgorithm = UserPreferences.EPISODE_CLEANUP_DEFAULT;
|
||||
}
|
||||
|
||||
public DBCleanupTests(int cleanupAlgorithm) {
|
||||
this.cleanupAlgorithm = cleanupAlgorithm;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
|
||||
assertTrue(PodDBAdapter.deleteDatabase());
|
||||
|
||||
cleanupDestFolder(destFolder);
|
||||
assertTrue(destFolder.delete());
|
||||
}
|
||||
|
||||
private void cleanupDestFolder(File destFolder) {
|
||||
for (File f : destFolder.listFiles()) {
|
||||
assertTrue(f.delete());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
context = getInstrumentation().getTargetContext();
|
||||
destFolder = context.getExternalCacheDir();
|
||||
cleanupDestFolder(destFolder);
|
||||
assertNotNull(destFolder);
|
||||
assertTrue(destFolder.exists());
|
||||
assertTrue(destFolder.canWrite());
|
||||
|
||||
// create new database
|
||||
PodDBAdapter.deleteDatabase();
|
||||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
adapter.close();
|
||||
|
||||
SharedPreferences.Editor prefEdit = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()).edit();
|
||||
prefEdit.putString(UserPreferences.PREF_EPISODE_CACHE_SIZE, Integer.toString(EPISODE_CACHE_SIZE));
|
||||
prefEdit.putString(UserPreferences.PREF_EPISODE_CLEANUP, Integer.toString(cleanupAlgorithm));
|
||||
prefEdit.commit();
|
||||
|
||||
UserPreferences.init(context);
|
||||
}
|
||||
|
||||
@FlakyTest(tolerance = 3)
|
||||
public void testPerformAutoCleanupShouldDelete() throws IOException {
|
||||
final int NUM_ITEMS = EPISODE_CACHE_SIZE * 2;
|
||||
|
||||
Feed feed = new Feed("url", new Date(), "title");
|
||||
List<FeedItem> items = new ArrayList<>();
|
||||
feed.setItems(items);
|
||||
List<File> files = new ArrayList<>();
|
||||
populateItems(NUM_ITEMS, feed, items, files, FeedItem.PLAYED, false, false);
|
||||
|
||||
DBTasks.performAutoCleanup(context);
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
if (i < EPISODE_CACHE_SIZE) {
|
||||
assertTrue(files.get(i).exists());
|
||||
} else {
|
||||
assertFalse(files.get(i).exists());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void populateItems(final int numItems, Feed feed, List<FeedItem> items,
|
||||
List<File> files, int itemState, boolean addToQueue,
|
||||
boolean addToFavorites) throws IOException {
|
||||
for (int i = 0; i < numItems; i++) {
|
||||
Date itemDate = new Date(numItems - i);
|
||||
Date playbackCompletionDate = null;
|
||||
if (itemState == FeedItem.PLAYED) {
|
||||
playbackCompletionDate = itemDate;
|
||||
}
|
||||
FeedItem item = new FeedItem(0, "title", "id", "link", itemDate, itemState, feed);
|
||||
|
||||
File f = new File(destFolder, "file " + i);
|
||||
assertTrue(f.createNewFile());
|
||||
files.add(f);
|
||||
item.setMedia(new FeedMedia(0, item, 1, 0, 1L, "m", f.getAbsolutePath(), "url", true, playbackCompletionDate, 0));
|
||||
items.add(item);
|
||||
}
|
||||
|
||||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
adapter.setCompleteFeed(feed);
|
||||
if (addToQueue) {
|
||||
adapter.setQueue(items);
|
||||
}
|
||||
if (addToFavorites) {
|
||||
adapter.setFavorites(items);
|
||||
}
|
||||
adapter.close();
|
||||
|
||||
assertTrue(feed.getId() != 0);
|
||||
for (FeedItem item : items) {
|
||||
assertTrue(item.getId() != 0);
|
||||
assertTrue(item.getMedia().getId() != 0);
|
||||
}
|
||||
}
|
||||
|
||||
@FlakyTest(tolerance = 3)
|
||||
public void testPerformAutoCleanupHandleUnplayed() throws IOException {
|
||||
final int NUM_ITEMS = EPISODE_CACHE_SIZE * 2;
|
||||
|
||||
Feed feed = new Feed("url", new Date(), "title");
|
||||
List<FeedItem> items = new ArrayList<FeedItem>();
|
||||
feed.setItems(items);
|
||||
List<File> files = new ArrayList<File>();
|
||||
populateItems(NUM_ITEMS, feed, items, files, FeedItem.UNPLAYED, false, false);
|
||||
|
||||
DBTasks.performAutoCleanup(context);
|
||||
for (File file : files) {
|
||||
assertTrue(file.exists());
|
||||
}
|
||||
}
|
||||
|
||||
@FlakyTest(tolerance = 3)
|
||||
public void testPerformAutoCleanupShouldNotDeleteBecauseInQueue() throws IOException {
|
||||
final int NUM_ITEMS = EPISODE_CACHE_SIZE * 2;
|
||||
|
||||
Feed feed = new Feed("url", new Date(), "title");
|
||||
List<FeedItem> items = new ArrayList<>();
|
||||
feed.setItems(items);
|
||||
List<File> files = new ArrayList<>();
|
||||
populateItems(NUM_ITEMS, feed, items, files, FeedItem.PLAYED, true, false);
|
||||
|
||||
DBTasks.performAutoCleanup(context);
|
||||
for (File file : files) {
|
||||
assertTrue(file.exists());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reproduces a bug where DBTasks.performAutoCleanup(android.content.Context) would use the ID of the FeedItem in the
|
||||
* call to DBWriter.deleteFeedMediaOfItem instead of the ID of the FeedMedia. This would cause the wrong item to be deleted.
|
||||
* @throws IOException
|
||||
*/
|
||||
@FlakyTest(tolerance = 3)
|
||||
public void testPerformAutoCleanupShouldNotDeleteBecauseInQueue_withFeedsWithNoMedia() throws IOException {
|
||||
// add feed with no enclosures so that item ID != media ID
|
||||
saveFeedlist(1, 10, false);
|
||||
|
||||
// add candidate for performAutoCleanup
|
||||
List<Feed> feeds = saveFeedlist(1, 1, true);
|
||||
FeedMedia m = feeds.get(0).getItems().get(0).getMedia();
|
||||
m.setDownloaded(true);
|
||||
m.setFile_url("file");
|
||||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
adapter.setMedia(m);
|
||||
adapter.close();
|
||||
|
||||
testPerformAutoCleanupShouldNotDeleteBecauseInQueue();
|
||||
}
|
||||
|
||||
@FlakyTest(tolerance = 3)
|
||||
public void testPerformAutoCleanupShouldNotDeleteBecauseFavorite() throws IOException {
|
||||
final int NUM_ITEMS = EPISODE_CACHE_SIZE * 2;
|
||||
|
||||
Feed feed = new Feed("url", new Date(), "title");
|
||||
List<FeedItem> items = new ArrayList<>();
|
||||
feed.setItems(items);
|
||||
List<File> files = new ArrayList<>();
|
||||
populateItems(NUM_ITEMS, feed, items, files, FeedItem.PLAYED, false, true);
|
||||
|
||||
DBTasks.performAutoCleanup(context);
|
||||
for (File file : files) {
|
||||
assertTrue(file.exists());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
package de.test.antennapod.storage;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.test.FlakyTest;
|
||||
import android.test.InstrumentationTestCase;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.storage.DBTasks;
|
||||
import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
||||
|
||||
import static de.test.antennapod.storage.DBTestUtils.saveFeedlist;
|
||||
|
||||
/**
|
||||
* Tests that the APNullCleanupAlgorithm is working correctly.
|
||||
*/
|
||||
public class DBNullCleanupAlgorithmTest extends InstrumentationTestCase {
|
||||
|
||||
private static final String TAG = "DBNullCleanupAlgorithmTest";
|
||||
private static final int EPISODE_CACHE_SIZE = 5;
|
||||
|
||||
private Context context;
|
||||
|
||||
private File destFolder;
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
|
||||
assertTrue(PodDBAdapter.deleteDatabase());
|
||||
|
||||
cleanupDestFolder(destFolder);
|
||||
assertTrue(destFolder.delete());
|
||||
}
|
||||
|
||||
private void cleanupDestFolder(File destFolder) {
|
||||
for (File f : destFolder.listFiles()) {
|
||||
assertTrue(f.delete());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
context = getInstrumentation().getTargetContext();
|
||||
destFolder = context.getExternalCacheDir();
|
||||
cleanupDestFolder(destFolder);
|
||||
assertNotNull(destFolder);
|
||||
assertTrue(destFolder.exists());
|
||||
assertTrue(destFolder.canWrite());
|
||||
|
||||
// create new database
|
||||
PodDBAdapter.deleteDatabase();
|
||||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
adapter.close();
|
||||
|
||||
SharedPreferences.Editor prefEdit = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()).edit();
|
||||
prefEdit.putString(UserPreferences.PREF_EPISODE_CACHE_SIZE, Integer.toString(EPISODE_CACHE_SIZE));
|
||||
prefEdit.putString(UserPreferences.PREF_EPISODE_CLEANUP, Integer.toString(UserPreferences.EPISODE_CLEANUP_NULL));
|
||||
prefEdit.commit();
|
||||
|
||||
UserPreferences.init(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* A test with no items in the queue, but multiple items downloaded.
|
||||
* The null algorithm should never delete any items, even if they're played and not in the queue.
|
||||
* @throws IOException
|
||||
*/
|
||||
@FlakyTest(tolerance = 3)
|
||||
public void testPerformAutoCleanupShouldNotDelete() throws IOException {
|
||||
final int NUM_ITEMS = EPISODE_CACHE_SIZE * 2;
|
||||
|
||||
Feed feed = new Feed("url", new Date(), "title");
|
||||
List<FeedItem> items = new ArrayList<>();
|
||||
feed.setItems(items);
|
||||
List<File> files = new ArrayList<>();
|
||||
for (int i = 0; i < NUM_ITEMS; i++) {
|
||||
FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), FeedItem.PLAYED, feed);
|
||||
|
||||
File f = new File(destFolder, "file " + i);
|
||||
assertTrue(f.createNewFile());
|
||||
files.add(f);
|
||||
item.setMedia(new FeedMedia(0, item, 1, 0, 1L, "m", f.getAbsolutePath(), "url", true,
|
||||
new Date(NUM_ITEMS - i), 0));
|
||||
items.add(item);
|
||||
}
|
||||
|
||||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
adapter.setCompleteFeed(feed);
|
||||
adapter.close();
|
||||
|
||||
assertTrue(feed.getId() != 0);
|
||||
for (FeedItem item : items) {
|
||||
assertTrue(item.getId() != 0);
|
||||
assertTrue(item.getMedia().getId() != 0);
|
||||
}
|
||||
DBTasks.performAutoCleanup(context);
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
assertTrue(files.get(i).exists());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package de.test.antennapod.storage;
|
||||
|
||||
import android.test.FlakyTest;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.storage.DBTasks;
|
||||
|
||||
/**
|
||||
* Tests that the APQueueCleanupAlgorithm is working correctly.
|
||||
*/
|
||||
public class DBQueueCleanupAlgorithmTest extends DBCleanupTests {
|
||||
|
||||
private static final String TAG = "DBQueueCleanupAlgorithmTest";
|
||||
|
||||
public DBQueueCleanupAlgorithmTest() {
|
||||
super(UserPreferences.EPISODE_CLEANUP_QUEUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* For APQueueCleanupAlgorithm we expect even unplayed episodes to be deleted if needed
|
||||
* if they aren't in the queue
|
||||
*/
|
||||
@FlakyTest(tolerance = 3)
|
||||
public void testPerformAutoCleanupHandleUnplayed() throws IOException {
|
||||
final int NUM_ITEMS = EPISODE_CACHE_SIZE * 2;
|
||||
|
||||
Feed feed = new Feed("url", new Date(), "title");
|
||||
List<FeedItem> items = new ArrayList<>();
|
||||
feed.setItems(items);
|
||||
List<File> files = new ArrayList<>();
|
||||
populateItems(NUM_ITEMS, feed, items, files, FeedItem.UNPLAYED, false, false);
|
||||
|
||||
DBTasks.performAutoCleanup(context);
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
if (i < EPISODE_CACHE_SIZE) {
|
||||
assertTrue(files.get(i).exists());
|
||||
} else {
|
||||
assertFalse(files.get(i).exists());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -29,33 +29,20 @@ import static de.test.antennapod.storage.DBTestUtils.saveFeedlist;
|
||||
public class DBTasksTest extends InstrumentationTestCase {
|
||||
|
||||
private static final String TAG = "DBTasksTest";
|
||||
private static final int EPISODE_CACHE_SIZE = 5;
|
||||
|
||||
private Context context;
|
||||
|
||||
private File destFolder;
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
|
||||
assertTrue(PodDBAdapter.deleteDatabase());
|
||||
|
||||
for (File f : destFolder.listFiles()) {
|
||||
assertTrue(f.delete());
|
||||
}
|
||||
assertTrue(destFolder.delete());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
context = getInstrumentation().getTargetContext();
|
||||
destFolder = context.getExternalCacheDir();
|
||||
assertNotNull(destFolder);
|
||||
assertTrue(destFolder.exists());
|
||||
assertTrue(destFolder.canWrite());
|
||||
|
||||
// create new database
|
||||
PodDBAdapter.deleteDatabase();
|
||||
@ -63,145 +50,9 @@ public class DBTasksTest extends InstrumentationTestCase {
|
||||
adapter.open();
|
||||
adapter.close();
|
||||
|
||||
SharedPreferences.Editor prefEdit = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()).edit();
|
||||
prefEdit.putString(UserPreferences.PREF_EPISODE_CACHE_SIZE, Integer.toString(EPISODE_CACHE_SIZE));
|
||||
prefEdit.commit();
|
||||
|
||||
UserPreferences.init(context);
|
||||
}
|
||||
|
||||
@FlakyTest(tolerance = 3)
|
||||
public void testPerformAutoCleanupShouldDelete() throws IOException {
|
||||
final int NUM_ITEMS = EPISODE_CACHE_SIZE * 2;
|
||||
|
||||
Feed feed = new Feed("url", new Date(), "title");
|
||||
List<FeedItem> items = new ArrayList<>();
|
||||
feed.setItems(items);
|
||||
List<File> files = new ArrayList<>();
|
||||
for (int i = 0; i < NUM_ITEMS; i++) {
|
||||
FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), FeedItem.PLAYED, feed);
|
||||
|
||||
File f = new File(destFolder, "file " + i);
|
||||
assertTrue(f.createNewFile());
|
||||
files.add(f);
|
||||
item.setMedia(new FeedMedia(0, item, 1, 0, 1L, "m", f.getAbsolutePath(), "url", true, new Date(NUM_ITEMS - i), 0));
|
||||
items.add(item);
|
||||
}
|
||||
|
||||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
adapter.setCompleteFeed(feed);
|
||||
adapter.close();
|
||||
|
||||
assertTrue(feed.getId() != 0);
|
||||
for (FeedItem item : items) {
|
||||
assertTrue(item.getId() != 0);
|
||||
assertTrue(item.getMedia().getId() != 0);
|
||||
}
|
||||
DBTasks.performAutoCleanup(context);
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
if (i < EPISODE_CACHE_SIZE) {
|
||||
assertTrue(files.get(i).exists());
|
||||
} else {
|
||||
assertFalse(files.get(i).exists());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@FlakyTest(tolerance = 3)
|
||||
public void testPerformAutoCleanupShouldNotDeleteBecauseUnread() throws IOException {
|
||||
final int NUM_ITEMS = EPISODE_CACHE_SIZE * 2;
|
||||
|
||||
Feed feed = new Feed("url", new Date(), "title");
|
||||
List<FeedItem> items = new ArrayList<FeedItem>();
|
||||
feed.setItems(items);
|
||||
List<File> files = new ArrayList<File>();
|
||||
for (int i = 0; i < NUM_ITEMS; i++) {
|
||||
FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), FeedItem.UNPLAYED, feed);
|
||||
|
||||
File f = new File(destFolder, "file " + i);
|
||||
assertTrue(f.createNewFile());
|
||||
assertTrue(f.exists());
|
||||
files.add(f);
|
||||
item.setMedia(new FeedMedia(0, item, 1, 0, 1L, "m", f.getAbsolutePath(), "url", true, new Date(NUM_ITEMS - i), 0));
|
||||
items.add(item);
|
||||
}
|
||||
|
||||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
adapter.setCompleteFeed(feed);
|
||||
adapter.close();
|
||||
|
||||
assertTrue(feed.getId() != 0);
|
||||
for (FeedItem item : items) {
|
||||
assertTrue(item.getId() != 0);
|
||||
assertTrue(item.getMedia().getId() != 0);
|
||||
}
|
||||
DBTasks.performAutoCleanup(context);
|
||||
for (File file : files) {
|
||||
assertTrue(file.exists());
|
||||
}
|
||||
}
|
||||
|
||||
@FlakyTest(tolerance = 3)
|
||||
public void testPerformAutoCleanupShouldNotDeleteBecauseInQueue() throws IOException {
|
||||
final int NUM_ITEMS = EPISODE_CACHE_SIZE * 2;
|
||||
|
||||
Feed feed = new Feed("url", new Date(), "title");
|
||||
List<FeedItem> items = new ArrayList<>();
|
||||
feed.setItems(items);
|
||||
List<File> files = new ArrayList<>();
|
||||
for (int i = 0; i < NUM_ITEMS; i++) {
|
||||
FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), FeedItem.PLAYED, feed);
|
||||
|
||||
File f = new File(destFolder, "file " + i);
|
||||
assertTrue(f.createNewFile());
|
||||
assertTrue(f.exists());
|
||||
files.add(f);
|
||||
item.setMedia(new FeedMedia(0, item, 1, 0, 1L, "m", f.getAbsolutePath(), "url", true, new Date(NUM_ITEMS - i), 0));
|
||||
items.add(item);
|
||||
}
|
||||
|
||||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
adapter.setCompleteFeed(feed);
|
||||
adapter.setQueue(items);
|
||||
adapter.close();
|
||||
|
||||
assertTrue(feed.getId() != 0);
|
||||
for (FeedItem item : items) {
|
||||
assertTrue(item.getId() != 0);
|
||||
assertTrue(item.getMedia().getId() != 0);
|
||||
}
|
||||
DBTasks.performAutoCleanup(context);
|
||||
for (File file : files) {
|
||||
assertTrue(file.exists());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reproduces a bug where DBTasks.performAutoCleanup(android.content.Context) would use the ID of the FeedItem in the
|
||||
* call to DBWriter.deleteFeedMediaOfItem instead of the ID of the FeedMedia. This would cause the wrong item to be deleted.
|
||||
* @throws IOException
|
||||
*/
|
||||
@FlakyTest(tolerance = 3)
|
||||
public void testPerformAutoCleanupShouldNotDeleteBecauseInQueue_withFeedsWithNoMedia() throws IOException {
|
||||
// add feed with no enclosures so that item ID != media ID
|
||||
saveFeedlist(1, 10, false);
|
||||
|
||||
// add candidate for performAutoCleanup
|
||||
List<Feed> feeds = saveFeedlist(1, 1, true);
|
||||
FeedMedia m = feeds.get(0).getItems().get(0).getMedia();
|
||||
m.setDownloaded(true);
|
||||
m.setFile_url("file");
|
||||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
adapter.setMedia(m);
|
||||
adapter.close();
|
||||
|
||||
testPerformAutoCleanupShouldNotDeleteBecauseInQueue();
|
||||
}
|
||||
|
||||
@FlakyTest(tolerance = 3)
|
||||
public void testUpdateFeedNewFeed() {
|
||||
final int NUM_ITEMS = 10;
|
||||
|
@ -14,10 +14,15 @@ import org.apache.commons.io.IOUtils;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
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;
|
||||
|
||||
public class PreferencesTest extends ActivityInstrumentationTestCase2<PreferenceActivity> {
|
||||
|
||||
@ -59,12 +64,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
solo.clickOnText(solo.getString(R.string.pref_set_theme_title));
|
||||
solo.waitForDialogToOpen();
|
||||
solo.clickOnText(solo.getString(otherTheme));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return UserPreferences.getTheme() != theme;
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> UserPreferences.getTheme() != theme, Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
public void testSwitchThemeBack() {
|
||||
@ -78,140 +78,67 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
solo.clickOnText(solo.getString(R.string.pref_set_theme_title));
|
||||
solo.waitForDialogToOpen(1000);
|
||||
solo.clickOnText(solo.getString(otherTheme));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return UserPreferences.getTheme() != theme;
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> UserPreferences.getTheme() != theme, Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
public void testExpandNotification() {
|
||||
final int priority = UserPreferences.getNotifyPriority();
|
||||
solo.clickOnText(solo.getString(R.string.pref_expandNotify_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return priority != UserPreferences.getNotifyPriority();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> priority != UserPreferences.getNotifyPriority(), Timeout.getLargeTimeout()));
|
||||
solo.clickOnText(solo.getString(R.string.pref_expandNotify_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return priority == UserPreferences.getNotifyPriority();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> priority == UserPreferences.getNotifyPriority(), Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
public void testEnablePersistentPlaybackControls() {
|
||||
final boolean persistNotify = UserPreferences.isPersistNotify();
|
||||
solo.clickOnText(solo.getString(R.string.pref_persistNotify_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return persistNotify != UserPreferences.isPersistNotify();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> persistNotify != UserPreferences.isPersistNotify(), Timeout.getLargeTimeout()));
|
||||
solo.clickOnText(solo.getString(R.string.pref_persistNotify_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override public boolean isSatisfied() {
|
||||
return persistNotify == UserPreferences.isPersistNotify();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> persistNotify == UserPreferences.isPersistNotify(), Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
public void testEnqueueAtFront() {
|
||||
final boolean enqueueAtFront = UserPreferences.enqueueAtFront();
|
||||
solo.clickOnText(solo.getString(R.string.pref_queueAddToFront_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return enqueueAtFront != UserPreferences.enqueueAtFront();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> enqueueAtFront != UserPreferences.enqueueAtFront(), Timeout.getLargeTimeout()));
|
||||
solo.clickOnText(solo.getString(R.string.pref_queueAddToFront_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override public boolean isSatisfied() {
|
||||
return enqueueAtFront == UserPreferences.enqueueAtFront();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> enqueueAtFront == UserPreferences.enqueueAtFront(), Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
public void testHeadPhonesDisconnect() {
|
||||
final boolean pauseOnHeadsetDisconnect = UserPreferences.isPauseOnHeadsetDisconnect();
|
||||
solo.clickOnText(solo.getString(R.string.pref_pauseOnHeadsetDisconnect_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override public boolean isSatisfied() {
|
||||
return pauseOnHeadsetDisconnect != UserPreferences.isPauseOnHeadsetDisconnect();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> pauseOnHeadsetDisconnect != UserPreferences.isPauseOnHeadsetDisconnect(), Timeout.getLargeTimeout()));
|
||||
solo.clickOnText(solo.getString(R.string.pref_pauseOnHeadsetDisconnect_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override public boolean isSatisfied() {
|
||||
return pauseOnHeadsetDisconnect == UserPreferences.isPauseOnHeadsetDisconnect();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> pauseOnHeadsetDisconnect == UserPreferences.isPauseOnHeadsetDisconnect(), Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
public void testHeadPhonesReconnect() {
|
||||
if(UserPreferences.isPauseOnHeadsetDisconnect() == false) {
|
||||
solo.clickOnText(solo.getString(R.string.pref_pauseOnHeadsetDisconnect_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return UserPreferences.isPauseOnHeadsetDisconnect();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> UserPreferences.isPauseOnHeadsetDisconnect(), Timeout.getLargeTimeout()));
|
||||
}
|
||||
final boolean unpauseOnHeadsetReconnect = UserPreferences.isUnpauseOnHeadsetReconnect();
|
||||
solo.clickOnText(solo.getString(R.string.pref_unpauseOnHeadsetReconnect_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return unpauseOnHeadsetReconnect != UserPreferences.isUnpauseOnHeadsetReconnect();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> unpauseOnHeadsetReconnect != UserPreferences.isUnpauseOnHeadsetReconnect(), Timeout.getLargeTimeout()));
|
||||
solo.clickOnText(solo.getString(R.string.pref_unpauseOnHeadsetReconnect_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override public boolean isSatisfied() {
|
||||
return unpauseOnHeadsetReconnect == UserPreferences.isUnpauseOnHeadsetReconnect();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> unpauseOnHeadsetReconnect == UserPreferences.isUnpauseOnHeadsetReconnect(), Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
public void testContinuousPlayback() {
|
||||
final boolean continuousPlayback = UserPreferences.isFollowQueue();
|
||||
solo.clickOnText(solo.getString(R.string.pref_followQueue_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return continuousPlayback != UserPreferences.isFollowQueue();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> continuousPlayback != UserPreferences.isFollowQueue(), Timeout.getLargeTimeout()));
|
||||
solo.clickOnText(solo.getString(R.string.pref_followQueue_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override public boolean isSatisfied() {
|
||||
return continuousPlayback == UserPreferences.isFollowQueue();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> continuousPlayback == UserPreferences.isFollowQueue(), Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
public void testAutoDelete() {
|
||||
final boolean autoDelete = UserPreferences.isAutoDelete();
|
||||
solo.clickOnText(solo.getString(R.string.pref_auto_delete_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return autoDelete != UserPreferences.isAutoDelete();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> autoDelete != UserPreferences.isAutoDelete(), Timeout.getLargeTimeout()));
|
||||
solo.clickOnText(solo.getString(R.string.pref_auto_delete_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override public boolean isSatisfied() {
|
||||
return autoDelete == UserPreferences.isAutoDelete();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> autoDelete == UserPreferences.isAutoDelete(), Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
public void testPlaybackSpeeds() {
|
||||
@ -225,31 +152,16 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
public void testPauseForInterruptions() {
|
||||
final boolean pauseForFocusLoss = UserPreferences.shouldPauseForFocusLoss();
|
||||
solo.clickOnText(solo.getString(R.string.pref_pausePlaybackForFocusLoss_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return pauseForFocusLoss != UserPreferences.shouldPauseForFocusLoss();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> pauseForFocusLoss != UserPreferences.shouldPauseForFocusLoss(), Timeout.getLargeTimeout()));
|
||||
solo.clickOnText(solo.getString(R.string.pref_pausePlaybackForFocusLoss_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return pauseForFocusLoss == UserPreferences.shouldPauseForFocusLoss();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> pauseForFocusLoss == UserPreferences.shouldPauseForFocusLoss(), Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
public void testDisableUpdateInterval() {
|
||||
solo.clickOnText(solo.getString(R.string.pref_autoUpdateIntervallOrTime_sum));
|
||||
solo.waitForDialogToOpen();
|
||||
solo.clickOnText(solo.getString(R.string.pref_autoUpdateIntervallOrTime_Disable));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return UserPreferences.getUpdateInterval() == 0;
|
||||
}
|
||||
}, 1000);
|
||||
assertTrue(solo.waitForCondition(() -> UserPreferences.getUpdateInterval() == 0, 1000));
|
||||
}
|
||||
|
||||
public void testSetUpdateInterval() {
|
||||
@ -260,30 +172,16 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
String search = "12 " + solo.getString(R.string.pref_update_interval_hours_plural);
|
||||
solo.clickOnText(search);
|
||||
solo.waitForDialogToClose();
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return UserPreferences.getUpdateInterval() == 12;
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> UserPreferences.getUpdateInterval() ==
|
||||
TimeUnit.HOURS.toMillis(12), Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
public void testMobileUpdates() {
|
||||
final boolean mobileUpdates = UserPreferences.isAllowMobileUpdate();
|
||||
solo.clickOnText(solo.getString(R.string.pref_mobileUpdate_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return mobileUpdates != UserPreferences.isAllowMobileUpdate();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> mobileUpdates != UserPreferences.isAllowMobileUpdate(), Timeout.getLargeTimeout()));
|
||||
solo.clickOnText(solo.getString(R.string.pref_mobileUpdate_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return mobileUpdates == UserPreferences.isAllowMobileUpdate();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> mobileUpdates == UserPreferences.isAllowMobileUpdate(), Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
public void testSetSequentialDownload() {
|
||||
@ -292,12 +190,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
solo.clearEditText(0);
|
||||
solo.enterText(0, "1");
|
||||
solo.clickOnText(solo.getString(android.R.string.ok));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return UserPreferences.getParallelDownloads() == 1;
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> UserPreferences.getParallelDownloads() == 1, Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
public void testSetParallelDownloads() {
|
||||
@ -306,12 +199,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
solo.clearEditText(0);
|
||||
solo.enterText(0, "10");
|
||||
solo.clickOnText(solo.getString(android.R.string.ok));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return UserPreferences.getParallelDownloads() == 10;
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> UserPreferences.getParallelDownloads() == 10, Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
public void testSetParallelDownloadsInvalidInput() {
|
||||
@ -333,12 +221,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
solo.clickOnText(solo.getString(R.string.pref_episode_cache_title));
|
||||
solo.waitForDialogToOpen();
|
||||
solo.clickOnText(entry);
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return UserPreferences.getEpisodeCacheSize() == value;
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> UserPreferences.getEpisodeCacheSize() == value, Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
public void testSetEpisodeCacheMin() {
|
||||
@ -350,12 +233,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
solo.waitForDialogToOpen(1000);
|
||||
solo.scrollUp();
|
||||
solo.clickOnText(minEntry);
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return UserPreferences.getEpisodeCacheSize() == minValue;
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> UserPreferences.getEpisodeCacheSize() == minValue, Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
|
||||
@ -367,12 +245,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
solo.clickOnText(solo.getString(R.string.pref_episode_cache_title));
|
||||
solo.waitForDialogToOpen();
|
||||
solo.clickOnText(maxEntry);
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return UserPreferences.getEpisodeCacheSize() == maxValue;
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> UserPreferences.getEpisodeCacheSize() == maxValue, Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
public void testAutomaticDownload() {
|
||||
@ -380,50 +253,73 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
|
||||
solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
|
||||
solo.waitForText(solo.getString(R.string.pref_automatic_download_title));
|
||||
solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return automaticDownload != UserPreferences.isEnableAutodownload();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> automaticDownload != UserPreferences.isEnableAutodownload(), Timeout.getLargeTimeout()));
|
||||
if(UserPreferences.isEnableAutodownload() == false) {
|
||||
solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
|
||||
}
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return UserPreferences.isEnableAutodownload() == true;
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> UserPreferences.isEnableAutodownload() == true, Timeout.getLargeTimeout()));
|
||||
final boolean enableAutodownloadOnBattery = UserPreferences.isEnableAutodownloadOnBattery();
|
||||
solo.clickOnText(solo.getString(R.string.pref_automatic_download_on_battery_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return enableAutodownloadOnBattery != UserPreferences.isEnableAutodownloadOnBattery();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> enableAutodownloadOnBattery != UserPreferences.isEnableAutodownloadOnBattery(), Timeout.getLargeTimeout()));
|
||||
solo.clickOnText(solo.getString(R.string.pref_automatic_download_on_battery_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return enableAutodownloadOnBattery == UserPreferences.isEnableAutodownloadOnBattery();
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
assertTrue(solo.waitForCondition(() -> enableAutodownloadOnBattery == UserPreferences.isEnableAutodownloadOnBattery(), Timeout.getLargeTimeout()));
|
||||
final boolean enableWifiFilter = UserPreferences.isEnableAutodownloadWifiFilter();
|
||||
solo.clickOnText(solo.getString(R.string.pref_autodl_wifi_filter_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return enableWifiFilter != UserPreferences.isEnableAutodownloadWifiFilter();
|
||||
assertTrue(solo.waitForCondition(() -> enableWifiFilter != UserPreferences.isEnableAutodownloadWifiFilter(), Timeout.getLargeTimeout()));
|
||||
solo.clickOnText(solo.getString(R.string.pref_autodl_wifi_filter_title));
|
||||
assertTrue(solo.waitForCondition(() -> enableWifiFilter == UserPreferences.isEnableAutodownloadWifiFilter(), Timeout.getLargeTimeout()));
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
solo.clickOnText(solo.getString(R.string.pref_automatic_download_on_battery_title));
|
||||
solo.waitForCondition(new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return enableWifiFilter == UserPreferences.isEnableAutodownloadWifiFilter();
|
||||
|
||||
public void testEpisodeCleanupQueueOnly() {
|
||||
solo.clickOnText(solo.getString(R.string.pref_episode_cleanup_title));
|
||||
solo.waitForText(solo.getString(R.string.episode_cleanup_queue_removal));
|
||||
solo.clickOnText(solo.getString(R.string.episode_cleanup_queue_removal));
|
||||
assertTrue(solo.waitForCondition(() -> {
|
||||
EpisodeCleanupAlgorithm alg = UserPreferences.getEpisodeCleanupAlgorithm();
|
||||
return alg instanceof APQueueCleanupAlgorithm;
|
||||
},
|
||||
Timeout.getLargeTimeout()));
|
||||
}
|
||||
}, Timeout.getLargeTimeout());
|
||||
|
||||
public void testEpisodeCleanupNeverAlg() {
|
||||
solo.clickOnText(solo.getString(R.string.pref_episode_cleanup_title));
|
||||
solo.waitForText(solo.getString(R.string.episode_cleanup_never));
|
||||
solo.clickOnText(solo.getString(R.string.episode_cleanup_never));
|
||||
assertTrue(solo.waitForCondition(() -> {
|
||||
EpisodeCleanupAlgorithm alg = UserPreferences.getEpisodeCleanupAlgorithm();
|
||||
return alg instanceof APNullCleanupAlgorithm;
|
||||
},
|
||||
Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
public void testEpisodeCleanupClassic() {
|
||||
solo.clickOnText(solo.getString(R.string.pref_episode_cleanup_title));
|
||||
solo.waitForText(solo.getString(R.string.episode_cleanup_after_listening));
|
||||
solo.clickOnText(solo.getString(R.string.episode_cleanup_after_listening));
|
||||
assertTrue(solo.waitForCondition(() -> {
|
||||
EpisodeCleanupAlgorithm alg = UserPreferences.getEpisodeCleanupAlgorithm();
|
||||
if (alg instanceof APCleanupAlgorithm) {
|
||||
APCleanupAlgorithm cleanupAlg = (APCleanupAlgorithm)alg;
|
||||
return cleanupAlg.getNumberOfDaysAfterPlayback() == 0;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
public void testEpisodeCleanupNumDays() {
|
||||
solo.clickOnText(solo.getString(R.string.pref_episode_cleanup_title));
|
||||
solo.waitForText(solo.getString(R.string.episode_cleanup_after_listening));
|
||||
solo.clickOnText("5");
|
||||
assertTrue(solo.waitForCondition(() -> {
|
||||
EpisodeCleanupAlgorithm alg = UserPreferences.getEpisodeCleanupAlgorithm();
|
||||
if (alg instanceof APCleanupAlgorithm) {
|
||||
APCleanupAlgorithm cleanupAlg = (APCleanupAlgorithm)alg;
|
||||
return cleanupAlg.getNumberOfDaysAfterPlayback() == 5;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
Timeout.getLargeTimeout()));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package de.danoeh.antennapod.config;
|
||||
|
||||
import de.danoeh.antennapod.core.DBTasksCallbacks;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.storage.APCleanupAlgorithm;
|
||||
import de.danoeh.antennapod.core.storage.APDownloadAlgorithm;
|
||||
import de.danoeh.antennapod.core.storage.AutomaticDownloadAlgorithm;
|
||||
@ -15,6 +16,6 @@ public class DBTasksCallbacksImpl implements DBTasksCallbacks {
|
||||
|
||||
@Override
|
||||
public EpisodeCleanupAlgorithm getEpisodeCacheCleanupAlgorithm() {
|
||||
return new APCleanupAlgorithm();
|
||||
return UserPreferences.getEpisodeCleanupAlgorithm();
|
||||
}
|
||||
}
|
||||
|
@ -366,7 +366,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
|
||||
public boolean onPreferenceChange(Preference preference, Object o) {
|
||||
if (o instanceof String) {
|
||||
int newValue = Integer.valueOf((String) o) * 1024 * 1024;
|
||||
if(newValue != UserPreferences.getImageCacheSize()) {
|
||||
if (newValue != UserPreferences.getImageCacheSize()) {
|
||||
AlertDialog.Builder dialog = new AlertDialog.Builder(ui.getActivity());
|
||||
dialog.setTitle(android.R.string.dialog_alert_title);
|
||||
dialog.setMessage(R.string.pref_restart_required);
|
||||
@ -379,6 +379,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
|
||||
}
|
||||
}
|
||||
);
|
||||
buildEpisodeCleanupPreference();
|
||||
buildSmartMarkAsPlayedPreference();
|
||||
buildAutodownloadSelectedNetworsPreference();
|
||||
setSelectedNetworksEnabled(UserPreferences
|
||||
@ -432,6 +433,28 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
|
||||
return entries;
|
||||
}
|
||||
|
||||
private void buildEpisodeCleanupPreference() {
|
||||
final Resources res = ui.getActivity().getResources();
|
||||
|
||||
ListPreference pref = (ListPreference) ui.findPreference(UserPreferences.PREF_EPISODE_CLEANUP);
|
||||
String[] values = res.getStringArray(
|
||||
R.array.episode_cleanup_values);
|
||||
String[] entries = new String[values.length];
|
||||
for (int x = 0; x < values.length; x++) {
|
||||
int v = Integer.parseInt(values[x]);
|
||||
if (v == UserPreferences.EPISODE_CLEANUP_QUEUE) {
|
||||
entries[x] = res.getString(R.string.episode_cleanup_queue_removal);
|
||||
} else if (v == UserPreferences.EPISODE_CLEANUP_NULL){
|
||||
entries[x] = res.getString(R.string.episode_cleanup_never);
|
||||
} else if (v == 0) {
|
||||
entries[x] = res.getString(R.string.episode_cleanup_after_listening);
|
||||
} else {
|
||||
entries[x] = res.getQuantityString(R.plurals.episode_cleanup_days_after_listening, v, v);
|
||||
}
|
||||
}
|
||||
pref.setEntries(entries);
|
||||
}
|
||||
|
||||
private void buildSmartMarkAsPlayedPreference() {
|
||||
final Resources res = ui.getActivity().getResources();
|
||||
|
||||
|
@ -137,6 +137,15 @@
|
||||
android:key="prefMobileUpdate"
|
||||
android:summary="@string/pref_mobileUpdate_sum"
|
||||
android:title="@string/pref_mobileUpdate_title"/>
|
||||
|
||||
<ListPreference
|
||||
android:defaultValue="-1"
|
||||
android:entries="@array/episode_cleanup_entries"
|
||||
android:key="prefEpisodeCleanup"
|
||||
android:title="@string/pref_episode_cleanup_title"
|
||||
android:summary="@string/pref_episode_cleanup_summary"
|
||||
android:entryValues="@array/episode_cleanup_values"/>
|
||||
|
||||
<de.danoeh.antennapod.preferences.CustomEditTextPreference
|
||||
android:defaultValue="6"
|
||||
android:inputType="number"
|
||||
|
@ -27,6 +27,10 @@ import java.util.concurrent.TimeUnit;
|
||||
import de.danoeh.antennapod.core.ClientConfig;
|
||||
import de.danoeh.antennapod.core.R;
|
||||
import de.danoeh.antennapod.core.receiver.FeedUpdateReceiver;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Provides access to preferences set by the user in the settings screen. A
|
||||
@ -67,6 +71,7 @@ public class UserPreferences {
|
||||
// Network
|
||||
public static final String PREF_UPDATE_INTERVAL = "prefAutoUpdateIntervall";
|
||||
public static final String PREF_MOBILE_UPDATE = "prefMobileUpdate";
|
||||
public static final String PREF_EPISODE_CLEANUP = "prefEpisodeCleanup";
|
||||
public static final String PREF_PARALLEL_DOWNLOADS = "prefParallelDownloads";
|
||||
public static final String PREF_EPISODE_CACHE_SIZE = "prefEpisodeCacheSize";
|
||||
public static final String PREF_ENABLE_AUTODL = "prefEnableAutoDl";
|
||||
@ -93,6 +98,9 @@ public class UserPreferences {
|
||||
// Experimental
|
||||
public static final String PREF_SONIC = "prefSonic";
|
||||
public static final String PREF_NORMALIZER = "prefNormalizer";
|
||||
public static final int EPISODE_CLEANUP_QUEUE = -1;
|
||||
public static final int EPISODE_CLEANUP_NULL = -2;
|
||||
public static final int EPISODE_CLEANUP_DEFAULT = 0;
|
||||
|
||||
// Constants
|
||||
private static int EPISODE_CACHE_SIZE_UNLIMITED = -1;
|
||||
@ -487,6 +495,18 @@ public class UserPreferences {
|
||||
.apply();
|
||||
}
|
||||
|
||||
|
||||
public static EpisodeCleanupAlgorithm getEpisodeCleanupAlgorithm() {
|
||||
int cleanupValue = Integer.valueOf(prefs.getString(PREF_EPISODE_CLEANUP, "-1"));
|
||||
if (cleanupValue == EPISODE_CLEANUP_QUEUE) {
|
||||
return new APQueueCleanupAlgorithm();
|
||||
} else if (cleanupValue == EPISODE_CLEANUP_NULL) {
|
||||
return new APNullCleanupAlgorithm();
|
||||
} else {
|
||||
return new APCleanupAlgorithm(cleanupValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@ -646,5 +666,4 @@ public class UserPreferences {
|
||||
public static int readEpisodeCacheSize(String valueFromPrefs) {
|
||||
return readEpisodeCacheSizeInternal(valueFromPrefs);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,34 +4,53 @@ import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.util.LongList;
|
||||
|
||||
/**
|
||||
* Implementation of the EpisodeCleanupAlgorithm interface used by AntennaPod.
|
||||
*/
|
||||
public class APCleanupAlgorithm implements EpisodeCleanupAlgorithm<Integer> {
|
||||
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;
|
||||
|
||||
@Override
|
||||
public int performCleanup(Context context, Integer episodeNumber) {
|
||||
List<FeedItem> candidates = new ArrayList<>();
|
||||
List<FeedItem> downloadedItems = DBReader.getDownloadedItems();
|
||||
LongList queue = DBReader.getQueueIDList();
|
||||
List<FeedItem> delete;
|
||||
for (FeedItem item : downloadedItems) {
|
||||
if (item.hasMedia() && item.getMedia().isDownloaded()
|
||||
&& !queue.contains(item.getId()) && item.isPlayed()) {
|
||||
candidates.add(item);
|
||||
public APCleanupAlgorithm(int numberOfDaysAfterPlayback) {
|
||||
this.numberOfDaysAfterPlayback = numberOfDaysAfterPlayback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int performCleanup(Context context, int numberOfEpisodesToDelete) {
|
||||
List<FeedItem> candidates = new ArrayList<>();
|
||||
List<FeedItem> downloadedItems = DBReader.getDownloadedItems();
|
||||
List<FeedItem> delete;
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.add(Calendar.DAY_OF_MONTH, -1 * numberOfDaysAfterPlayback);
|
||||
Date mostRecentDateForDeletion = cal.getTime();
|
||||
for (FeedItem item : downloadedItems) {
|
||||
if (item.hasMedia()
|
||||
&& item.getMedia().isDownloaded()
|
||||
&& !item.isTagged(FeedItem.TAG_QUEUE)
|
||||
&& item.isPlayed()
|
||||
&& !item.isTagged(FeedItem.TAG_FAVORITE)) {
|
||||
FeedMedia media = item.getMedia();
|
||||
// make sure this candidate was played at least the proper amount of days prior
|
||||
// to now
|
||||
if (media != null
|
||||
&& media.getPlaybackCompletionDate() != null
|
||||
&& media.getPlaybackCompletionDate().before(mostRecentDateForDeletion)) {
|
||||
candidates.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Collections.sort(candidates, (lhs, rhs) -> {
|
||||
@ -47,8 +66,8 @@ public class APCleanupAlgorithm implements EpisodeCleanupAlgorithm<Integer> {
|
||||
return l.compareTo(r);
|
||||
});
|
||||
|
||||
if (candidates.size() > episodeNumber) {
|
||||
delete = candidates.subList(0, episodeNumber);
|
||||
if (candidates.size() > numberOfEpisodesToDelete) {
|
||||
delete = candidates.subList(0, numberOfEpisodesToDelete);
|
||||
} else {
|
||||
delete = candidates;
|
||||
}
|
||||
@ -66,34 +85,15 @@ public class APCleanupAlgorithm implements EpisodeCleanupAlgorithm<Integer> {
|
||||
|
||||
Log.i(TAG, String.format(
|
||||
"Auto-delete deleted %d episodes (%d requested)", counter,
|
||||
episodeNumber));
|
||||
numberOfEpisodesToDelete));
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getDefaultCleanupParameter() {
|
||||
return getPerformAutoCleanupArgs(0);
|
||||
public int getDefaultCleanupParameter() {
|
||||
return getNumEpisodesToCleanup(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPerformCleanupParameter(List<FeedItem> items) {
|
||||
return getPerformAutoCleanupArgs(items.size());
|
||||
}
|
||||
|
||||
static int getPerformAutoCleanupArgs(final int episodeNumber) {
|
||||
if (episodeNumber >= 0
|
||||
&& UserPreferences.getEpisodeCacheSize() != UserPreferences
|
||||
.getEpisodeCacheSizeUnlimited()) {
|
||||
int downloadedEpisodes = DBReader
|
||||
.getNumberOfDownloadedEpisodes();
|
||||
if (downloadedEpisodes + episodeNumber >= UserPreferences
|
||||
.getEpisodeCacheSize()) {
|
||||
|
||||
return downloadedEpisodes + episodeNumber
|
||||
- UserPreferences.getEpisodeCacheSize();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
public int getNumberOfDaysAfterPlayback() { return numberOfDaysAfterPlayback; }
|
||||
}
|
||||
|
@ -19,8 +19,6 @@ import de.danoeh.antennapod.core.util.PowerUtils;
|
||||
public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm {
|
||||
private static final String TAG = "APDownloadAlgorithm";
|
||||
|
||||
private final APCleanupAlgorithm cleanupAlgorithm = new APCleanupAlgorithm();
|
||||
|
||||
/**
|
||||
* Looks for undownloaded episodes in the queue or list of new items and request a download if
|
||||
* 1. Network is available
|
||||
@ -72,8 +70,8 @@ public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm {
|
||||
|
||||
int autoDownloadableEpisodes = candidates.size();
|
||||
int downloadedEpisodes = DBReader.getNumberOfDownloadedEpisodes();
|
||||
int deletedEpisodes = cleanupAlgorithm.performCleanup(context,
|
||||
APCleanupAlgorithm.getPerformAutoCleanupArgs(autoDownloadableEpisodes));
|
||||
int deletedEpisodes = UserPreferences.getEpisodeCleanupAlgorithm()
|
||||
.makeRoomForEpisodes(context, autoDownloadableEpisodes);
|
||||
boolean cacheIsUnlimited = UserPreferences.getEpisodeCacheSize() == UserPreferences
|
||||
.getEpisodeCacheSizeUnlimited();
|
||||
int episodeCacheSize = UserPreferences.getEpisodeCacheSize();
|
||||
@ -101,5 +99,4 @@ public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,24 @@
|
||||
package de.danoeh.antennapod.core.storage;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* A cleanup algorithm that never removes anything
|
||||
*/
|
||||
public class APNullCleanupAlgorithm extends EpisodeCleanupAlgorithm {
|
||||
|
||||
private static final String TAG = "APNullCleanupAlgorithm";
|
||||
|
||||
@Override
|
||||
public int performCleanup(Context context, int parameter) {
|
||||
// never clean anything up
|
||||
Log.i(TAG, "performCleanup: Not removing anything");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultCleanupParameter() {
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package de.danoeh.antennapod.core.storage;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.util.LongList;
|
||||
|
||||
/**
|
||||
* A cleanup algorithm that removes any item that isn't in the queue and isn't a favorite
|
||||
* but only if space is needed.
|
||||
*/
|
||||
public class APQueueCleanupAlgorithm extends EpisodeCleanupAlgorithm {
|
||||
|
||||
private static final String TAG = "APQueueCleanupAlgorithm";
|
||||
|
||||
@Override
|
||||
public int performCleanup(Context context, int numberOfEpisodesToDelete) {
|
||||
List<FeedItem> candidates = new ArrayList<>();
|
||||
List<FeedItem> downloadedItems = DBReader.getDownloadedItems();
|
||||
List<FeedItem> delete;
|
||||
for (FeedItem item : downloadedItems) {
|
||||
if (item.hasMedia()
|
||||
&& item.getMedia().isDownloaded()
|
||||
&& !item.isTagged(FeedItem.TAG_QUEUE)
|
||||
&& !item.isTagged(FeedItem.TAG_FAVORITE)) {
|
||||
candidates.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
// in the absence of better data, we'll sort by item publication date
|
||||
Collections.sort(candidates, (lhs, rhs) -> {
|
||||
Date l = lhs.getPubDate();
|
||||
Date r = rhs.getPubDate();
|
||||
|
||||
if (l == null) {
|
||||
l = new Date();
|
||||
}
|
||||
if (r == null) {
|
||||
r = new Date();
|
||||
}
|
||||
return l.compareTo(r);
|
||||
});
|
||||
|
||||
if (candidates.size() > numberOfEpisodesToDelete) {
|
||||
delete = candidates.subList(0, numberOfEpisodesToDelete);
|
||||
} else {
|
||||
delete = candidates;
|
||||
}
|
||||
|
||||
for (FeedItem item : delete) {
|
||||
try {
|
||||
DBWriter.deleteFeedMediaOfItem(context, item.getMedia().getId()).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
int counter = delete.size();
|
||||
|
||||
|
||||
Log.i(TAG, String.format(
|
||||
"Auto-delete deleted %d episodes (%d requested)", counter,
|
||||
numberOfEpisodesToDelete));
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultCleanupParameter() {
|
||||
return getNumEpisodesToCleanup(0);
|
||||
}
|
||||
}
|
@ -332,9 +332,7 @@ public final class DBTasks {
|
||||
@Override
|
||||
public void run() {
|
||||
ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm()
|
||||
.performCleanup(context,
|
||||
ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm()
|
||||
.getPerformCleanupParameter(Arrays.asList(items)));
|
||||
.makeRoomForEpisodes(context, items.length);
|
||||
}
|
||||
|
||||
}.start();
|
||||
@ -390,8 +388,7 @@ public final class DBTasks {
|
||||
* @param context Used for accessing the DB.
|
||||
*/
|
||||
public static void performAutoCleanup(final Context context) {
|
||||
ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm().performCleanup(context,
|
||||
ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm().getDefaultCleanupParameter());
|
||||
ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm().performCleanup(context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,35 +2,60 @@ package de.danoeh.antennapod.core.storage;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.List;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
|
||||
public interface EpisodeCleanupAlgorithm<T> {
|
||||
public abstract class EpisodeCleanupAlgorithm {
|
||||
|
||||
/**
|
||||
* Deletes downloaded episodes that are no longer needed. What episodes are deleted and how many
|
||||
* of them depends on the implementation.
|
||||
*
|
||||
* @param context Can be used for accessing the database
|
||||
* @param parameter An additional parameter. This parameter is either returned by getDefaultCleanupParameter
|
||||
* @param numToRemove An additional parameter. This parameter is either returned by getDefaultCleanupParameter
|
||||
* or getPerformCleanupParameter.
|
||||
* @return The number of episodes that were deleted.
|
||||
*/
|
||||
public int performCleanup(Context context, T parameter);
|
||||
public abstract int performCleanup(Context context, int numToRemove);
|
||||
|
||||
public int performCleanup(Context context) {
|
||||
return performCleanup(context, getDefaultCleanupParameter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a parameter for performCleanup. The implementation of this interface should decide how much
|
||||
* space to free to satisfy the episode cache conditions. If the conditions are already satisfied, this
|
||||
* method should not have any effects.
|
||||
*/
|
||||
public T getDefaultCleanupParameter();
|
||||
public abstract int getDefaultCleanupParameter();
|
||||
|
||||
/**
|
||||
* Returns a parameter for performCleanup.
|
||||
* Cleans up just enough episodes to make room for the requested number
|
||||
*
|
||||
* @param items A list of FeedItems that are about to be downloaded. The implementation of this interface
|
||||
* should decide how much space to free to satisfy the episode cache conditions.
|
||||
* @param context Can be used for accessing the database
|
||||
* @param amountOfRoomNeeded the number of episodes we need space for
|
||||
* @return The number of epiosdes that were deleted
|
||||
*/
|
||||
public T getPerformCleanupParameter(List<FeedItem> items);
|
||||
public int makeRoomForEpisodes(Context context, int amountOfRoomNeeded) {
|
||||
return performCleanup(context, getNumEpisodesToCleanup(amountOfRoomNeeded));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param amountOfRoomNeeded the number of episodes we want to download
|
||||
* @return the number of episodes to delete in order to make room
|
||||
*/
|
||||
protected int getNumEpisodesToCleanup(final int amountOfRoomNeeded) {
|
||||
if (amountOfRoomNeeded >= 0
|
||||
&& UserPreferences.getEpisodeCacheSize() != UserPreferences
|
||||
.getEpisodeCacheSizeUnlimited()) {
|
||||
int downloadedEpisodes = DBReader
|
||||
.getNumberOfDownloadedEpisodes();
|
||||
if (downloadedEpisodes + amountOfRoomNeeded >= UserPreferences
|
||||
.getEpisodeCacheSize()) {
|
||||
|
||||
return downloadedEpisodes + amountOfRoomNeeded
|
||||
- UserPreferences.getEpisodeCacheSize();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -790,6 +790,21 @@ public class PodDBAdapter {
|
||||
db.execSQL(sql);
|
||||
}
|
||||
|
||||
public void setFavorites(List<FeedItem> favorites) {
|
||||
ContentValues values = new ContentValues();
|
||||
db.beginTransaction();
|
||||
db.delete(TABLE_NAME_FAVORITES, null, null);
|
||||
for (int i = 0; i < favorites.size(); i++) {
|
||||
FeedItem item = favorites.get(i);
|
||||
values.put(KEY_ID, i);
|
||||
values.put(KEY_FEEDITEM, item.getId());
|
||||
values.put(KEY_FEED, item.getFeed().getId());
|
||||
db.insertWithOnConflict(TABLE_NAME_FAVORITES, null, values, SQLiteDatabase.CONFLICT_REPLACE);
|
||||
}
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the item to favorites
|
||||
*/
|
||||
|
@ -44,6 +44,7 @@
|
||||
<item>100</item>
|
||||
<item>@string/pref_episode_cache_unlimited</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="episode_cache_size_values">
|
||||
<item>5</item>
|
||||
<item>10</item>
|
||||
@ -53,6 +54,26 @@
|
||||
<item>-1</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="episode_cleanup_entries">
|
||||
<item>@string/episode_cleanup_queue_removal</item>
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>3</item>
|
||||
<item>5</item>
|
||||
<item>7</item>
|
||||
<item>@string/episode_cleanup_never</item>
|
||||
</string-array>
|
||||
|
||||
<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>-2</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="playback_speed_values">
|
||||
<item>0.5</item>
|
||||
<item>0.6</item>
|
||||
|
@ -87,6 +87,13 @@
|
||||
<string name="feed_auto_download_always">Always</string>
|
||||
<string name="feed_auto_download_never">Never</string>
|
||||
<string name="send_label">Send...</string>
|
||||
<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 listening</string>
|
||||
<plurals name="episode_cleanup_days_after_listening">
|
||||
<item quantity="one">1 day after listening</item>
|
||||
<item quantity="other">%d days after listening</item>
|
||||
</plurals>
|
||||
|
||||
<!-- 'Add Feed' Activity labels -->
|
||||
<string name="feedurl_label">Feed URL</string>
|
||||
@ -267,6 +274,8 @@
|
||||
<string name="queue_label">Queue</string>
|
||||
<string name="services_label">Services</string>
|
||||
<string name="flattr_label">Flattr</string>
|
||||
<string name="pref_episode_cleanup_title">Episode Cleanup</string>
|
||||
<string name="pref_episode_cleanup_summary">Episodes that aren\'t in the queue and aren\'t favorites should be eligible for removal if space is needed</string>
|
||||
<string name="pref_pauseOnHeadsetDisconnect_sum">Pause playback when the headphones are disconnected</string>
|
||||
<string name="pref_unpauseOnHeadsetReconnect_sum">Resume playback when the headphones are reconnected</string>
|
||||
<string name="pref_followQueue_sum">Jump to next queue item when playback completes</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user