summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorByteHamster <info@bytehamster.com>2022-02-27 12:12:24 +0100
committerByteHamster <info@bytehamster.com>2022-02-27 19:47:41 +0100
commitff3258c34a1797e75538b83baa1e867d0ea07ceb (patch)
tree82530a8ce01909638b143ae0d72f3862811c5321 /core/src
parent42e36328e3bb6d4bda632da7586fdace912a34e0 (diff)
downloadAntennaPod-ff3258c34a1797e75538b83baa1e867d0ea07ceb.zip
Move database to its own module
Diffstat (limited to 'core/src')
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/SubscriptionsFilter.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java12
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceNotification.java1
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java154
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/Downloader.java1
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java10
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedSyncTask.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java19
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java7
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java331
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java1
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/NavDrawerData.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java1439
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/mapper/ChapterCursorMapper.java51
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/mapper/DownloadStatusCursorMapper.java35
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedCursorMapper.java70
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedItemCursorMapper.java46
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedItemFilterQuery.java76
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedMediaCursorMapper.java67
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedPreferencesCursorMapper.java74
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/DownloadError.java49
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/DownloadErrorLabel.java1
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/LongIntMap.java263
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/comparator/DownloadStatusComparator.java2
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/feed/LocalFeedUpdaterTest.java2
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/storage/DbCleanupTests.java1
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/storage/DbNullCleanupAlgorithmTest.java1
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/storage/DbReaderTest.java1
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/storage/DbTasksTest.java1
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/storage/DbTestUtils.java4
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/storage/DbWriterTest.java1
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/storage/mapper/FeedCursorMapperTest.java3
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/util/LongLongMapTest.java1
40 files changed, 55 insertions, 2698 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java b/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java
index ac67fb042..e03c8118d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java
@@ -9,9 +9,9 @@ import de.danoeh.antennapod.core.preferences.SleepTimerPreferences;
import de.danoeh.antennapod.core.preferences.UsageStatistics;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
-import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.danoeh.antennapod.core.util.NetworkUtils;
import de.danoeh.antennapod.core.util.gui.NotificationUtils;
+import de.danoeh.antennapod.storage.database.PodDBAdapter;
import java.io.File;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java b/core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java
index e0e1bbaa5..4cf2703d6 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java
@@ -22,12 +22,12 @@ import java.util.Set;
import java.util.UUID;
import de.danoeh.antennapod.core.R;
-import de.danoeh.antennapod.core.service.download.DownloadStatus;
+import de.danoeh.antennapod.model.download.DownloadStatus;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.parser.feed.util.DateUtils;
-import de.danoeh.antennapod.core.util.DownloadError;
+import de.danoeh.antennapod.model.download.DownloadError;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/SubscriptionsFilter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/SubscriptionsFilter.java
index a083a7220..7e80fb231 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/SubscriptionsFilter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/SubscriptionsFilter.java
@@ -5,7 +5,7 @@ import android.text.TextUtils;
import java.util.ArrayList;
import java.util.List;
-import de.danoeh.antennapod.core.util.LongIntMap;
+import de.danoeh.antennapod.storage.database.LongIntMap;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedPreferences;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java
index 82e1fb55a..f6caa9016 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java
@@ -13,6 +13,7 @@ import androidx.annotation.VisibleForTesting;
import androidx.core.app.NotificationCompat;
import androidx.preference.PreferenceManager;
+import de.danoeh.antennapod.model.feed.FeedCounter;
import org.json.JSONArray;
import org.json.JSONException;
@@ -141,11 +142,6 @@ public class UserPreferences {
public static final int FEED_ORDER_COUNTER = 0;
public static final int FEED_ORDER_ALPHABETICAL = 1;
public static final int FEED_ORDER_MOST_PLAYED = 3;
- public static final int FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM = 0;
- public static final int FEED_COUNTER_SHOW_NEW = 1;
- public static final int FEED_COUNTER_SHOW_UNPLAYED = 2;
- public static final int FEED_COUNTER_SHOW_NONE = 3;
- public static final int FEED_COUNTER_SHOW_DOWNLOADED = 4;
private static Context context;
private static SharedPreferences prefs;
@@ -247,9 +243,9 @@ public class UserPreferences {
.apply();
}
- public static int getFeedCounterSetting() {
- String value = prefs.getString(PREF_DRAWER_FEED_COUNTER, "" + FEED_COUNTER_SHOW_NEW);
- return Integer.parseInt(value);
+ public static FeedCounter getFeedCounterSetting() {
+ String value = prefs.getString(PREF_DRAWER_FEED_COUNTER, "" + FeedCounter.SHOW_NEW.id);
+ return FeedCounter.fromOrdinal(Integer.parseInt(value));
}
/**
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
index 1973c626b..1522f42e2 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
@@ -20,6 +20,7 @@ import androidx.core.app.ServiceCompat;
import androidx.core.content.ContextCompat;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.feed.LocalFeedUpdater;
+import de.danoeh.antennapod.model.download.DownloadStatus;
import org.apache.commons.io.FileUtils;
import org.greenrobot.eventbus.EventBus;
@@ -50,7 +51,7 @@ import de.danoeh.antennapod.core.service.download.handler.PostDownloaderTask;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DBWriter;
-import de.danoeh.antennapod.core.util.DownloadError;
+import de.danoeh.antennapod.model.download.DownloadError;
/**
* Manages the download of feedfiles in the app. Downloads can be enqueued via the startService intent.
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceNotification.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceNotification.java
index 48a9e8017..5c5d665d8 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceNotification.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceNotification.java
@@ -10,6 +10,7 @@ import androidx.core.app.NotificationCompat;
import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.util.DownloadErrorLabel;
+import de.danoeh.antennapod.model.download.DownloadStatus;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.core.util.gui.NotificationUtils;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java
deleted file mode 100644
index 9d4f1ab43..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java
+++ /dev/null
@@ -1,154 +0,0 @@
-package de.danoeh.antennapod.core.service.download;
-
-import androidx.annotation.NonNull;
-
-import java.util.Date;
-
-import de.danoeh.antennapod.model.feed.FeedFile;
-import de.danoeh.antennapod.core.util.DownloadError;
-
-/**
- * Contains status attributes for one download
- */
-public class DownloadStatus {
- /**
- * Downloaders should use this constant for the size attribute if necessary
- * so that the listadapters etc. can react properly.
- */
- public static final int SIZE_UNKNOWN = -1;
-
- // ----------------------------------- ATTRIBUTES STORED IN DB
- /**
- * A human-readable string which is shown to the user so that he can
- * identify the download. Should be the title of the item/feed/media or the
- * URL if the download has no other title.
- */
- private final String title;
- private final long feedfileId;
- /**
- * Is used to determine the type of the feedfile even if the feedfile does
- * not exist anymore. The value should be FEEDFILETYPE_FEED,
- * FEEDFILETYPE_FEEDIMAGE or FEEDFILETYPE_FEEDMEDIA
- */
- private final int feedfileType;
- private final boolean initiatedByUser;
- /**
- * Unique id for storing the object in database.
- */
- private long id;
- private DownloadError reason;
- /**
- * A message which can be presented to the user to give more information.
- * Should be null if Download was successful.
- */
- private String reasonDetailed;
- private boolean successful;
- private final Date completionDate;
- // ------------------------------------ NOT STORED IN DB
- private boolean done;
- private boolean cancelled;
-
- /**
- * Constructor for creating new completed downloads.
- */
- public DownloadStatus(@NonNull FeedFile feedfile, String title, DownloadError reason, boolean successful,
- String reasonDetailed, boolean initiatedByUser) {
- this(0, title, feedfile.getId(), feedfile.getTypeAsInt(), successful, false, true, reason, new Date(),
- reasonDetailed, initiatedByUser);
- }
-
- public DownloadStatus(long id, String title, long feedfileId, int feedfileType, boolean successful,
- boolean cancelled, boolean done, DownloadError reason, Date completionDate,
- String reasonDetailed, boolean initiatedByUser) {
- this.id = id;
- this.title = title;
- this.feedfileId = feedfileId;
- this.reason = reason;
- this.successful = successful;
- this.cancelled = cancelled;
- this.done = done;
- this.completionDate = (Date) completionDate.clone();
- this.reasonDetailed = reasonDetailed;
- this.feedfileType = feedfileType;
- this.initiatedByUser = initiatedByUser;
- }
-
- @Override
- @NonNull
- public String toString() {
- return "DownloadStatus [id=" + id + ", title=" + title + ", reason="
- + reason + ", reasonDetailed=" + reasonDetailed
- + ", successful=" + successful + ", completionDate="
- + completionDate + ", feedfileId=" + feedfileId
- + ", feedfileType=" + feedfileType + ", done=" + done
- + ", cancelled=" + cancelled + "]";
- }
-
- public long getId() {
- return id;
- }
-
- public void setId(long id) {
- this.id = id;
- }
-
- public String getTitle() {
- return title;
- }
-
- public DownloadError getReason() {
- return reason;
- }
-
- public String getReasonDetailed() {
- return reasonDetailed;
- }
-
- public boolean isSuccessful() {
- return successful;
- }
-
- public Date getCompletionDate() {
- return (Date) completionDate.clone();
- }
-
- public long getFeedfileId() {
- return feedfileId;
- }
-
- public int getFeedfileType() {
- return feedfileType;
- }
-
- public boolean isInitiatedByUser() {
- return initiatedByUser;
- }
-
- public boolean isDone() {
- return done;
- }
-
- public boolean isCancelled() {
- return cancelled;
- }
-
- public void setSuccessful() {
- this.successful = true;
- this.reason = DownloadError.SUCCESS;
- this.done = true;
- }
-
- public void setFailed(DownloadError reason, String reasonDetailed) {
- this.successful = false;
- this.reason = reason;
- this.reasonDetailed = reasonDetailed;
- this.done = true;
- }
-
- public void setCancelled() {
- this.successful = false;
- this.reason = DownloadError.ERROR_DOWNLOAD_CANCELLED;
- this.done = true;
- this.cancelled = true;
- }
-} \ No newline at end of file
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/Downloader.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/Downloader.java
index 3cc16d12a..fe44faac9 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/Downloader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/Downloader.java
@@ -9,6 +9,7 @@ import java.util.concurrent.Callable;
import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.R;
+import de.danoeh.antennapod.model.download.DownloadStatus;
/**
* Downloads files
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java
index 698278af9..894428f44 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java
@@ -5,6 +5,7 @@ import android.text.TextUtils;
import android.util.Log;
import de.danoeh.antennapod.core.util.NetworkUtils;
+import de.danoeh.antennapod.model.download.DownloadStatus;
import okhttp3.CacheControl;
import org.apache.commons.io.IOUtils;
@@ -24,7 +25,7 @@ import java.util.Date;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.parser.feed.util.DateUtils;
-import de.danoeh.antennapod.core.util.DownloadError;
+import de.danoeh.antennapod.model.download.DownloadError;
import de.danoeh.antennapod.core.util.StorageUtils;
import de.danoeh.antennapod.core.util.URIUtil;
import okhttp3.OkHttpClient;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java
index f7ed049cd..0e046978e 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java
@@ -17,12 +17,12 @@ import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.model.feed.Feed;
+import de.danoeh.antennapod.model.feed.FeedCounter;
import de.danoeh.antennapod.model.feed.FeedPreferences;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
-import de.danoeh.antennapod.core.storage.PodDBAdapter;
-import de.danoeh.antennapod.core.util.LongIntMap;
+import de.danoeh.antennapod.storage.database.LongIntMap;
import de.danoeh.antennapod.core.util.gui.NotificationUtils;
+import de.danoeh.antennapod.storage.database.PodDBAdapter;
public class NewEpisodesNotification {
private static final String TAG = "NewEpisodesNotification";
@@ -36,7 +36,7 @@ public class NewEpisodesNotification {
public void loadCountersBeforeRefresh() {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- countersBefore = adapter.getFeedCounters(UserPreferences.FEED_COUNTER_SHOW_NEW);
+ countersBefore = adapter.getFeedCounters(FeedCounter.SHOW_NEW);
adapter.close();
}
@@ -130,7 +130,7 @@ public class NewEpisodesNotification {
private static int getNewEpisodeCount(long feedId) {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- int episodeCount = adapter.getFeedCounters(UserPreferences.FEED_COUNTER_SHOW_NEW, feedId).get(feedId);
+ int episodeCount = adapter.getFeedCounters(FeedCounter.SHOW_NEW, feedId).get(feedId);
adapter.close();
return episodeCount;
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java
index 7e3b07880..76c464a6d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedParserTask.java
@@ -7,11 +7,11 @@ import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedPreferences;
import de.danoeh.antennapod.model.feed.VolumeAdaptionSetting;
import de.danoeh.antennapod.core.service.download.DownloadRequest;
-import de.danoeh.antennapod.core.service.download.DownloadStatus;
+import de.danoeh.antennapod.model.download.DownloadStatus;
import de.danoeh.antennapod.parser.feed.FeedHandler;
import de.danoeh.antennapod.parser.feed.FeedHandlerResult;
import de.danoeh.antennapod.parser.feed.UnsupportedFeedtypeException;
-import de.danoeh.antennapod.core.util.DownloadError;
+import de.danoeh.antennapod.model.download.DownloadError;
import de.danoeh.antennapod.core.util.InvalidFeedException;
import org.xml.sax.SAXException;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedSyncTask.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedSyncTask.java
index 8f559a889..042a903d3 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedSyncTask.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/FeedSyncTask.java
@@ -4,7 +4,7 @@ import android.content.Context;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.core.service.download.DownloadRequest;
-import de.danoeh.antennapod.core.service.download.DownloadStatus;
+import de.danoeh.antennapod.model.download.DownloadStatus;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.parser.feed.FeedHandlerResult;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java
index 541e17cf6..90254c1f3 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java
@@ -13,12 +13,12 @@ import java.util.concurrent.ExecutionException;
import de.danoeh.antennapod.event.UnreadItemsUpdateEvent;
import de.danoeh.antennapod.core.service.download.DownloadRequest;
-import de.danoeh.antennapod.core.service.download.DownloadStatus;
+import de.danoeh.antennapod.model.download.DownloadStatus;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.sync.queue.SynchronizationQueueSink;
import de.danoeh.antennapod.core.util.ChapterUtils;
-import de.danoeh.antennapod.core.util.DownloadError;
+import de.danoeh.antennapod.model.download.DownloadError;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.net.sync.model.EpisodeAction;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java
index c7b72c332..64cf446aa 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java
@@ -15,7 +15,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import de.danoeh.antennapod.core.storage.mapper.DownloadStatusCursorMapper;
import de.danoeh.antennapod.model.feed.Chapter;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedItem;
@@ -24,13 +23,15 @@ import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.model.feed.FeedPreferences;
import de.danoeh.antennapod.core.feed.SubscriptionsFilter;
import de.danoeh.antennapod.core.preferences.UserPreferences;
-import de.danoeh.antennapod.core.service.download.DownloadStatus;
-import de.danoeh.antennapod.core.storage.mapper.ChapterCursorMapper;
-import de.danoeh.antennapod.core.storage.mapper.FeedCursorMapper;
-import de.danoeh.antennapod.core.storage.mapper.FeedItemCursorMapper;
-import de.danoeh.antennapod.core.storage.mapper.FeedMediaCursorMapper;
-import de.danoeh.antennapod.core.storage.mapper.FeedPreferencesCursorMapper;
-import de.danoeh.antennapod.core.util.LongIntMap;
+import de.danoeh.antennapod.model.download.DownloadStatus;
+import de.danoeh.antennapod.storage.database.PodDBAdapter;
+import de.danoeh.antennapod.storage.database.mapper.DownloadStatusCursorMapper;
+import de.danoeh.antennapod.storage.database.mapper.ChapterCursorMapper;
+import de.danoeh.antennapod.storage.database.mapper.FeedCursorMapper;
+import de.danoeh.antennapod.storage.database.mapper.FeedItemCursorMapper;
+import de.danoeh.antennapod.storage.database.mapper.FeedMediaCursorMapper;
+import de.danoeh.antennapod.storage.database.mapper.FeedPreferencesCursorMapper;
+import de.danoeh.antennapod.storage.database.LongIntMap;
import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.comparator.DownloadStatusComparator;
import de.danoeh.antennapod.core.util.comparator.FeedItemPubdateComparator;
@@ -877,7 +878,7 @@ public final class DBReader {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
- final LongIntMap feedCounters = adapter.getFeedCounters();
+ final LongIntMap feedCounters = adapter.getFeedCounters(UserPreferences.getFeedCounterSetting());
SubscriptionsFilter subscriptionsFilter = UserPreferences.getSubscriptionsFilter();
List<Feed> feeds = subscriptionsFilter.filter(getFeedList(adapter), feedCounters);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java
index f447090a8..e5310c4ff 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java
@@ -13,6 +13,8 @@ import androidx.annotation.VisibleForTesting;
import de.danoeh.antennapod.core.service.download.DownloadRequest;
import de.danoeh.antennapod.core.service.download.DownloadRequestCreator;
import de.danoeh.antennapod.core.service.download.DownloadService;
+import de.danoeh.antennapod.storage.database.PodDBAdapter;
+import de.danoeh.antennapod.storage.database.mapper.FeedCursorMapper;
import org.greenrobot.eventbus.EventBus;
import java.util.ArrayList;
@@ -32,11 +34,10 @@ import de.danoeh.antennapod.event.FeedItemEvent;
import de.danoeh.antennapod.event.FeedListUpdateEvent;
import de.danoeh.antennapod.event.MessageEvent;
import de.danoeh.antennapod.core.preferences.UserPreferences;
-import de.danoeh.antennapod.core.service.download.DownloadStatus;
-import de.danoeh.antennapod.core.storage.mapper.FeedCursorMapper;
+import de.danoeh.antennapod.model.download.DownloadStatus;
import de.danoeh.antennapod.core.sync.SyncService;
import de.danoeh.antennapod.core.sync.queue.SynchronizationQueueSink;
-import de.danoeh.antennapod.core.util.DownloadError;
+import de.danoeh.antennapod.model.download.DownloadError;
import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.comparator.FeedItemPubdateComparator;
import de.danoeh.antennapod.model.feed.Feed;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java
deleted file mode 100644
index 4e0a6aeda..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java
+++ /dev/null
@@ -1,331 +0,0 @@
-package de.danoeh.antennapod.core.storage;
-
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.media.MediaMetadataRetriever;
-import android.util.Log;
-
-import de.danoeh.antennapod.model.feed.FeedItem;
-
-import static de.danoeh.antennapod.model.feed.FeedPreferences.SPEED_USE_GLOBAL;
-
-class DBUpgrader {
- /**
- * Upgrades the given database to a new schema version
- */
- static void upgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
- if (oldVersion <= 1) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN "
- + PodDBAdapter.KEY_TYPE + " TEXT");
- }
- if (oldVersion <= 2) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS
- + " ADD COLUMN " + PodDBAdapter.KEY_LINK + " TEXT");
- }
- if (oldVersion <= 3) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " ADD COLUMN " + PodDBAdapter.KEY_ITEM_IDENTIFIER + " TEXT");
- }
- if (oldVersion <= 4) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN "
- + PodDBAdapter.KEY_FEED_IDENTIFIER + " TEXT");
- }
- if (oldVersion <= 5) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_DOWNLOAD_LOG
- + " ADD COLUMN " + PodDBAdapter.KEY_REASON_DETAILED + " TEXT");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_DOWNLOAD_LOG
- + " ADD COLUMN " + PodDBAdapter.KEY_DOWNLOADSTATUS_TITLE + " TEXT");
- }
- if (oldVersion <= 6) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS
- + " ADD COLUMN " + PodDBAdapter.KEY_CHAPTER_TYPE + " INTEGER");
- }
- if (oldVersion <= 7) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " ADD COLUMN " + PodDBAdapter.KEY_PLAYBACK_COMPLETION_DATE
- + " INTEGER");
- }
- if (oldVersion <= 8) {
- final int KEY_ID_POSITION = 0;
- final int KEY_MEDIA_POSITION = 1;
-
- // Add feeditem column to feedmedia table
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " ADD COLUMN " + PodDBAdapter.KEY_FEEDITEM
- + " INTEGER");
- Cursor feeditemCursor = db.query(PodDBAdapter.TABLE_NAME_FEED_ITEMS,
- new String[]{PodDBAdapter.KEY_ID, PodDBAdapter.KEY_MEDIA}, "? > 0",
- new String[]{PodDBAdapter.KEY_MEDIA}, null, null, null);
- if (feeditemCursor.moveToFirst()) {
- db.beginTransaction();
- ContentValues contentValues = new ContentValues();
- do {
- long mediaId = feeditemCursor.getLong(KEY_MEDIA_POSITION);
- contentValues.put(PodDBAdapter.KEY_FEEDITEM, feeditemCursor.getLong(KEY_ID_POSITION));
- db.update(PodDBAdapter.TABLE_NAME_FEED_MEDIA, contentValues, PodDBAdapter.KEY_ID + "=?", new String[]{String.valueOf(mediaId)});
- contentValues.clear();
- } while (feeditemCursor.moveToNext());
- db.setTransactionSuccessful();
- db.endTransaction();
- }
- feeditemCursor.close();
- }
- if (oldVersion <= 9) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_AUTO_DOWNLOAD_ENABLED
- + " INTEGER DEFAULT 1");
- }
- if (oldVersion <= 10) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN flattr_status"
- + " INTEGER");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " ADD COLUMN flattr_status"
- + " INTEGER");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " ADD COLUMN " + PodDBAdapter.KEY_PLAYED_DURATION
- + " INTEGER");
- }
- if (oldVersion <= 11) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_USERNAME
- + " TEXT");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_PASSWORD
- + " TEXT");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " ADD COLUMN image"
- + " INTEGER");
- }
- if (oldVersion <= 12) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_IS_PAGED + " INTEGER DEFAULT 0");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_NEXT_PAGE_LINK + " TEXT");
- }
- if (oldVersion <= 13) {
- // remove duplicate rows in "Chapters" table that were created because of a bug.
- db.execSQL(String.format("DELETE FROM %s WHERE %s NOT IN " +
- "(SELECT MIN(%s) as %s FROM %s GROUP BY %s,%s,%s,%s,%s)",
- PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS,
- PodDBAdapter.KEY_ID,
- PodDBAdapter.KEY_ID,
- PodDBAdapter.KEY_ID,
- PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS,
- PodDBAdapter.KEY_TITLE,
- PodDBAdapter.KEY_START,
- PodDBAdapter.KEY_FEEDITEM,
- PodDBAdapter.KEY_LINK,
- PodDBAdapter.KEY_CHAPTER_TYPE));
- }
- if (oldVersion <= 14) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " ADD COLUMN " + PodDBAdapter.KEY_AUTO_DOWNLOAD_ATTEMPTS + " INTEGER");
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " SET " + PodDBAdapter.KEY_AUTO_DOWNLOAD_ATTEMPTS + " = "
- + "(SELECT " + PodDBAdapter.KEY_AUTO_DOWNLOAD_ENABLED
- + " FROM " + PodDBAdapter.TABLE_NAME_FEEDS
- + " WHERE " + PodDBAdapter.TABLE_NAME_FEEDS + "." + PodDBAdapter.KEY_ID
- + " = " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_FEED + ")");
-
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_HIDE + " TEXT");
-
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0");
-
- // create indexes
- db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_FEED);
- db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDMEDIA_FEEDITEM);
- db.execSQL(PodDBAdapter.CREATE_INDEX_QUEUE_FEEDITEM);
- db.execSQL(PodDBAdapter.CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM);
- }
- if (oldVersion <= 15) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " ADD COLUMN " + PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE + " INTEGER DEFAULT -1");
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " SET " + PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE + "=0"
- + " WHERE " + PodDBAdapter.KEY_DOWNLOADED + "=0");
- Cursor c = db.rawQuery("SELECT " + PodDBAdapter.KEY_FILE_URL
- + " FROM " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " WHERE " + PodDBAdapter.KEY_DOWNLOADED + "=1 "
- + " AND " + PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE + "=-1", null);
- if (c.moveToFirst()) {
- MediaMetadataRetriever mmr = new MediaMetadataRetriever();
- do {
- String fileUrl = c.getString(0);
- try {
- mmr.setDataSource(fileUrl);
- byte[] image = mmr.getEmbeddedPicture();
- if (image != null) {
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " SET " + PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE + "=1"
- + " WHERE " + PodDBAdapter.KEY_FILE_URL + "='" + fileUrl + "'");
- } else {
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " SET " + PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE + "=0"
- + " WHERE " + PodDBAdapter.KEY_FILE_URL + "='" + fileUrl + "'");
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- } while (c.moveToNext());
- }
- c.close();
- }
- if (oldVersion <= 16) {
- String selectNew = "SELECT " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_ID
- + " FROM " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " INNER JOIN " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + " ON "
- + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_ID + "="
- + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_FEEDITEM
- + " LEFT OUTER JOIN " + PodDBAdapter.TABLE_NAME_QUEUE + " ON "
- + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_ID + "="
- + PodDBAdapter.TABLE_NAME_QUEUE + "." + PodDBAdapter.KEY_FEEDITEM
- + " WHERE "
- + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_READ + " = 0 AND " // unplayed
- + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_DOWNLOADED + " = 0 AND " // undownloaded
- + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_POSITION + " = 0 AND " // not partially played
- + PodDBAdapter.TABLE_NAME_QUEUE + "." + PodDBAdapter.KEY_ID + " IS NULL"; // not in queue
- String sql = "UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " SET " + PodDBAdapter.KEY_READ + "=" + FeedItem.NEW
- + " WHERE " + PodDBAdapter.KEY_ID + " IN (" + selectNew + ")";
- Log.d("Migration", "SQL: " + sql);
- db.execSQL(sql);
- }
- if (oldVersion <= 17) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0");
- }
- if (oldVersion < 1030005) {
- db.execSQL("UPDATE FeedItems SET auto_download=0 WHERE " +
- "(read=1 OR id IN (SELECT feeditem FROM FeedMedia WHERE position>0 OR downloaded=1)) " +
- "AND id NOT IN (SELECT feeditem FROM Queue)");
- }
- if (oldVersion < 1040001) {
- db.execSQL(PodDBAdapter.CREATE_TABLE_FAVORITES);
- }
- if (oldVersion < 1040002) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " ADD COLUMN " + PodDBAdapter.KEY_LAST_PLAYED_TIME + " INTEGER DEFAULT 0");
- }
- if (oldVersion < 1040013) {
- db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_PUBDATE);
- db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_READ);
- }
- if (oldVersion < 1050003) {
- // Migrates feed list filter data
-
- db.beginTransaction();
-
- // Change to intermediate values to avoid overwriting in the following find/replace
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + "\n" +
- "SET " + PodDBAdapter.KEY_HIDE + " = replace(" + PodDBAdapter.KEY_HIDE + ", 'unplayed', 'noplay')");
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + "\n" +
- "SET " + PodDBAdapter.KEY_HIDE + " = replace(" + PodDBAdapter.KEY_HIDE + ", 'not_queued', 'noqueue')");
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + "\n" +
- "SET " + PodDBAdapter.KEY_HIDE + " = replace(" + PodDBAdapter.KEY_HIDE + ", 'not_downloaded', 'nodl')");
-
- // Replace played, queued, and downloaded with their opposites
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + "\n" +
- "SET " + PodDBAdapter.KEY_HIDE + " = replace(" + PodDBAdapter.KEY_HIDE + ", 'played', 'unplayed')");
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + "\n" +
- "SET " + PodDBAdapter.KEY_HIDE + " = replace(" + PodDBAdapter.KEY_HIDE + ", 'queued', 'not_queued')");
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + "\n" +
- "SET " + PodDBAdapter.KEY_HIDE + " = replace(" + PodDBAdapter.KEY_HIDE + ", 'downloaded', 'not_downloaded')");
-
- // Now replace intermediates for unplayed, not queued, etc. with their opposites
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + "\n" +
- "SET " + PodDBAdapter.KEY_HIDE + " = replace(" + PodDBAdapter.KEY_HIDE + ", 'noplay', 'played')");
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + "\n" +
- "SET " + PodDBAdapter.KEY_HIDE + " = replace(" + PodDBAdapter.KEY_HIDE + ", 'noqueue', 'queued')");
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + "\n" +
- "SET " + PodDBAdapter.KEY_HIDE + " = replace(" + PodDBAdapter.KEY_HIDE + ", 'nodl', 'downloaded')");
-
- // Paused doesn't have an opposite, so unplayed is the next best option
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + "\n" +
- "SET " + PodDBAdapter.KEY_HIDE + " = replace(" + PodDBAdapter.KEY_HIDE + ", 'paused', 'unplayed')");
-
- db.setTransactionSuccessful();
- db.endTransaction();
-
- // and now get ready for autodownload filters
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_INCLUDE_FILTER + " TEXT DEFAULT ''");
-
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_EXCLUDE_FILTER + " TEXT DEFAULT ''");
-
- // and now auto refresh
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_KEEP_UPDATED + " INTEGER DEFAULT 1");
- }
- if (oldVersion < 1050004) {
- // prevent old timestamps to be misinterpreted as ETags
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " SET " + PodDBAdapter.KEY_LASTUPDATE + "=NULL");
- }
- if (oldVersion < 1060200) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_CUSTOM_TITLE + " TEXT");
- }
- if (oldVersion < 1060596) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_IMAGE_URL + " TEXT");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " ADD COLUMN " + PodDBAdapter.KEY_IMAGE_URL + " TEXT");
-
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + " SET " + PodDBAdapter.KEY_IMAGE_URL + " = ("
- + " SELECT " + PodDBAdapter.KEY_DOWNLOAD_URL
- + " FROM " + PodDBAdapter.TABLE_NAME_FEED_IMAGES
- + " WHERE " + PodDBAdapter.TABLE_NAME_FEED_IMAGES + "." + PodDBAdapter.KEY_ID
- + " = " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + ".image)");
-
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEEDS + " SET " + PodDBAdapter.KEY_IMAGE_URL + " = ("
- + " SELECT " + PodDBAdapter.KEY_DOWNLOAD_URL
- + " FROM " + PodDBAdapter.TABLE_NAME_FEED_IMAGES
- + " WHERE " + PodDBAdapter.TABLE_NAME_FEED_IMAGES + "." + PodDBAdapter.KEY_ID
- + " = " + PodDBAdapter.TABLE_NAME_FEEDS + ".image)");
-
- db.execSQL("DROP TABLE " + PodDBAdapter.TABLE_NAME_FEED_IMAGES);
- }
- if (oldVersion < 1070400) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_FEED_PLAYBACK_SPEED + " REAL DEFAULT " + SPEED_USE_GLOBAL);
- }
- if (oldVersion < 1070401) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_SORT_ORDER + " TEXT");
- }
- if (oldVersion < 1090000) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_FEED_VOLUME_ADAPTION + " INTEGER DEFAULT 0");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS
- + " ADD COLUMN " + PodDBAdapter.KEY_IMAGE_URL + " TEXT DEFAULT NULL");
- }
- if (oldVersion < 1090001) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_FEED_SKIP_INTRO + " INTEGER DEFAULT 0;");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_FEED_SKIP_ENDING + " INTEGER DEFAULT 0;");
- }
- if (oldVersion < 2020000) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_EPISODE_NOTIFICATION + " INTEGER DEFAULT 0;");
- }
- if (oldVersion < 2030000) {
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " SET " + PodDBAdapter.KEY_DESCRIPTION + " = content_encoded, content_encoded = NULL "
- + "WHERE length(" + PodDBAdapter.KEY_DESCRIPTION + ") < length(content_encoded)");
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + " SET content_encoded = NULL");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_FEED_TAGS + " TEXT;");
- }
- if (oldVersion < 2050000) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + PodDBAdapter.KEY_MINIMAL_DURATION_FILTER + " INTEGER DEFAULT -1");
- }
- }
-
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
index e572b4d8c..df4094590 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
@@ -9,6 +9,7 @@ import androidx.annotation.Nullable;
import androidx.core.app.NotificationManagerCompat;
import de.danoeh.antennapod.core.service.download.DownloadService;
+import de.danoeh.antennapod.storage.database.PodDBAdapter;
import org.greenrobot.eventbus.EventBus;
import java.io.File;
@@ -34,7 +35,7 @@ import de.danoeh.antennapod.event.UnreadItemsUpdateEvent;
import de.danoeh.antennapod.core.feed.FeedEvent;
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
-import de.danoeh.antennapod.core.service.download.DownloadStatus;
+import de.danoeh.antennapod.model.download.DownloadStatus;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.sync.queue.SynchronizationQueueSink;
import de.danoeh.antennapod.core.util.FeedItemPermutors;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java
index a0fac0c74..812080368 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java
@@ -8,6 +8,7 @@ import android.os.ParcelFileDescriptor;
import android.text.format.Formatter;
import android.util.Log;
import de.danoeh.antennapod.core.R;
+import de.danoeh.antennapod.storage.database.PodDBAdapter;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/NavDrawerData.java b/core/src/main/java/de/danoeh/antennapod/core/storage/NavDrawerData.java
index 1ec58216a..24b55f9f4 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/NavDrawerData.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/NavDrawerData.java
@@ -1,7 +1,7 @@
package de.danoeh.antennapod.core.storage;
import de.danoeh.antennapod.model.feed.Feed;
-import de.danoeh.antennapod.core.util.LongIntMap;
+import de.danoeh.antennapod.storage.database.LongIntMap;
import java.util.ArrayList;
import java.util.List;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
deleted file mode 100644
index ea4617f16..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
+++ /dev/null
@@ -1,1439 +0,0 @@
-package de.danoeh.antennapod.core.storage;
-
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.DatabaseErrorHandler;
-import android.database.DatabaseUtils;
-import android.database.DefaultDatabaseErrorHandler;
-import android.database.SQLException;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteDatabase.CursorFactory;
-import android.database.sqlite.SQLiteOpenHelper;
-import android.text.TextUtils;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import de.danoeh.antennapod.model.feed.FeedFunding;
-import de.danoeh.antennapod.core.storage.mapper.FeedItemFilterQuery;
-import org.apache.commons.io.FileUtils;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
-import de.danoeh.antennapod.model.feed.Chapter;
-import de.danoeh.antennapod.model.feed.Feed;
-import de.danoeh.antennapod.model.feed.FeedItem;
-import de.danoeh.antennapod.model.feed.FeedItemFilter;
-import de.danoeh.antennapod.model.feed.FeedMedia;
-import de.danoeh.antennapod.model.feed.FeedPreferences;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
-import de.danoeh.antennapod.core.service.download.DownloadStatus;
-import de.danoeh.antennapod.core.util.LongIntMap;
-import de.danoeh.antennapod.model.feed.SortOrder;
-
-import static de.danoeh.antennapod.model.feed.FeedPreferences.SPEED_USE_GLOBAL;
-import static de.danoeh.antennapod.model.feed.SortOrder.toCodeString;
-
-/**
- * Implements methods for accessing the database
- */
-public class PodDBAdapter {
-
- private static final String TAG = "PodDBAdapter";
- public static final String DATABASE_NAME = "Antennapod.db";
- public static final int VERSION = 2050000;
-
- /**
- * Maximum number of arguments for IN-operator.
- */
- private static final int IN_OPERATOR_MAXIMUM = 800;
-
- // Key-constants
- public static final String KEY_ID = "id";
- public static final String KEY_TITLE = "title";
- public static final String KEY_CUSTOM_TITLE = "custom_title";
- public static final String KEY_LINK = "link";
- public static final String KEY_DESCRIPTION = "description";
- public static final String KEY_FILE_URL = "file_url";
- public static final String KEY_DOWNLOAD_URL = "download_url";
- public static final String KEY_PUBDATE = "pubDate";
- public static final String KEY_READ = "read";
- public static final String KEY_DURATION = "duration";
- public static final String KEY_POSITION = "position";
- public static final String KEY_SIZE = "filesize";
- public static final String KEY_MIME_TYPE = "mime_type";
- public static final String KEY_IMAGE_URL = "image_url";
- public static final String KEY_FEED = "feed";
- public static final String KEY_MEDIA = "media";
- public static final String KEY_DOWNLOADED = "downloaded";
- public static final String KEY_LASTUPDATE = "last_update";
- public static final String KEY_FEEDFILE = "feedfile";
- public static final String KEY_REASON = "reason";
- public static final String KEY_SUCCESSFUL = "successful";
- public static final String KEY_FEEDFILETYPE = "feedfile_type";
- public static final String KEY_COMPLETION_DATE = "completion_date";
- public static final String KEY_FEEDITEM = "feeditem";
- public static final String KEY_PAYMENT_LINK = "payment_link";
- public static final String KEY_START = "start";
- public static final String KEY_LANGUAGE = "language";
- public static final String KEY_AUTHOR = "author";
- public static final String KEY_HAS_CHAPTERS = "has_simple_chapters";
- public static final String KEY_TYPE = "type";
- public static final String KEY_ITEM_IDENTIFIER = "item_identifier";
- public static final String KEY_FEED_IDENTIFIER = "feed_identifier";
- public static final String KEY_REASON_DETAILED = "reason_detailed";
- public static final String KEY_DOWNLOADSTATUS_TITLE = "title";
- public static final String KEY_CHAPTER_TYPE = "type";
- public static final String KEY_PLAYBACK_COMPLETION_DATE = "playback_completion_date";
- public static final String KEY_AUTO_DOWNLOAD_ATTEMPTS = "auto_download";
- public static final String KEY_AUTO_DOWNLOAD_ENABLED = "auto_download"; // Both tables use the same key
- public static final String KEY_KEEP_UPDATED = "keep_updated";
- public static final String KEY_AUTO_DELETE_ACTION = "auto_delete_action";
- public static final String KEY_FEED_VOLUME_ADAPTION = "feed_volume_adaption";
- public static final String KEY_PLAYED_DURATION = "played_duration";
- public static final String KEY_USERNAME = "username";
- public static final String KEY_PASSWORD = "password";
- public static final String KEY_IS_PAGED = "is_paged";
- public static final String KEY_NEXT_PAGE_LINK = "next_page_link";
- public static final String KEY_HIDE = "hide";
- public static final String KEY_SORT_ORDER = "sort_order";
- public static final String KEY_LAST_UPDATE_FAILED = "last_update_failed";
- public static final String KEY_HAS_EMBEDDED_PICTURE = "has_embedded_picture";
- public static final String KEY_LAST_PLAYED_TIME = "last_played_time";
- public static final String KEY_INCLUDE_FILTER = "include_filter";
- public static final String KEY_EXCLUDE_FILTER = "exclude_filter";
- public static final String KEY_MINIMAL_DURATION_FILTER = "minimal_duration_filter";
- public static final String KEY_FEED_PLAYBACK_SPEED = "feed_playback_speed";
- public static final String KEY_FEED_SKIP_INTRO = "feed_skip_intro";
- public static final String KEY_FEED_SKIP_ENDING = "feed_skip_ending";
- public static final String KEY_FEED_TAGS = "tags";
- public static final String KEY_EPISODE_NOTIFICATION = "episode_notification";
-
- // Table names
- public static final String TABLE_NAME_FEEDS = "Feeds";
- public static final String TABLE_NAME_FEED_ITEMS = "FeedItems";
- public static final String TABLE_NAME_FEED_IMAGES = "FeedImages";
- public static final String TABLE_NAME_FEED_MEDIA = "FeedMedia";
- public static final String TABLE_NAME_DOWNLOAD_LOG = "DownloadLog";
- public static final String TABLE_NAME_QUEUE = "Queue";
- public static final String TABLE_NAME_SIMPLECHAPTERS = "SimpleChapters";
- public static final String TABLE_NAME_FAVORITES = "Favorites";
-
- // SQL Statements for creating new tables
- private static final String TABLE_PRIMARY_KEY = KEY_ID
- + " INTEGER PRIMARY KEY AUTOINCREMENT ,";
-
- private static final String CREATE_TABLE_FEEDS = "CREATE TABLE "
- + TABLE_NAME_FEEDS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE
- + " TEXT," + KEY_CUSTOM_TITLE + " TEXT," + KEY_FILE_URL + " TEXT," + KEY_DOWNLOAD_URL + " TEXT,"
- + KEY_DOWNLOADED + " INTEGER," + KEY_LINK + " TEXT,"
- + KEY_DESCRIPTION + " TEXT," + KEY_PAYMENT_LINK + " TEXT,"
- + KEY_LASTUPDATE + " TEXT," + KEY_LANGUAGE + " TEXT," + KEY_AUTHOR
- + " TEXT," + KEY_IMAGE_URL + " TEXT," + KEY_TYPE + " TEXT,"
- + KEY_FEED_IDENTIFIER + " TEXT," + KEY_AUTO_DOWNLOAD_ENABLED + " INTEGER DEFAULT 1,"
- + KEY_USERNAME + " TEXT,"
- + KEY_PASSWORD + " TEXT,"
- + KEY_INCLUDE_FILTER + " TEXT DEFAULT '',"
- + KEY_EXCLUDE_FILTER + " TEXT DEFAULT '',"
- + KEY_MINIMAL_DURATION_FILTER + " INTEGER DEFAULT -1,"
- + KEY_KEEP_UPDATED + " INTEGER DEFAULT 1,"
- + KEY_IS_PAGED + " INTEGER DEFAULT 0,"
- + KEY_NEXT_PAGE_LINK + " TEXT,"
- + KEY_HIDE + " TEXT,"
- + KEY_SORT_ORDER + " TEXT,"
- + KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0,"
- + KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0,"
- + KEY_FEED_PLAYBACK_SPEED + " REAL DEFAULT " + SPEED_USE_GLOBAL + ","
- + KEY_FEED_VOLUME_ADAPTION + " INTEGER DEFAULT 0,"
- + KEY_FEED_TAGS + " TEXT,"
- + KEY_FEED_SKIP_INTRO + " INTEGER DEFAULT 0,"
- + KEY_FEED_SKIP_ENDING + " INTEGER DEFAULT 0,"
- + KEY_EPISODE_NOTIFICATION + " INTEGER DEFAULT 0)";
-
- private static final String CREATE_TABLE_FEED_ITEMS = "CREATE TABLE "
- + TABLE_NAME_FEED_ITEMS + " (" + TABLE_PRIMARY_KEY
- + KEY_TITLE + " TEXT," + KEY_PUBDATE + " INTEGER,"
- + KEY_READ + " INTEGER," + KEY_LINK + " TEXT,"
- + KEY_DESCRIPTION + " TEXT," + KEY_PAYMENT_LINK + " TEXT,"
- + KEY_MEDIA + " INTEGER," + KEY_FEED + " INTEGER,"
- + KEY_HAS_CHAPTERS + " INTEGER," + KEY_ITEM_IDENTIFIER + " TEXT,"
- + KEY_IMAGE_URL + " TEXT,"
- + KEY_AUTO_DOWNLOAD_ATTEMPTS + " INTEGER)";
-
- private static final String CREATE_TABLE_FEED_MEDIA = "CREATE TABLE "
- + TABLE_NAME_FEED_MEDIA + " (" + TABLE_PRIMARY_KEY + KEY_DURATION
- + " INTEGER," + KEY_FILE_URL + " TEXT," + KEY_DOWNLOAD_URL
- + " TEXT," + KEY_DOWNLOADED + " INTEGER," + KEY_POSITION
- + " INTEGER," + KEY_SIZE + " INTEGER," + KEY_MIME_TYPE + " TEXT,"
- + KEY_PLAYBACK_COMPLETION_DATE + " INTEGER,"
- + KEY_FEEDITEM + " INTEGER,"
- + KEY_PLAYED_DURATION + " INTEGER,"
- + KEY_HAS_EMBEDDED_PICTURE + " INTEGER,"
- + KEY_LAST_PLAYED_TIME + " INTEGER" + ")";
-
- private static final String CREATE_TABLE_DOWNLOAD_LOG = "CREATE TABLE "
- + TABLE_NAME_DOWNLOAD_LOG + " (" + TABLE_PRIMARY_KEY + KEY_FEEDFILE
- + " INTEGER," + KEY_FEEDFILETYPE + " INTEGER," + KEY_REASON
- + " INTEGER," + KEY_SUCCESSFUL + " INTEGER," + KEY_COMPLETION_DATE
- + " INTEGER," + KEY_REASON_DETAILED + " TEXT,"
- + KEY_DOWNLOADSTATUS_TITLE + " TEXT)";
-
- private static final String CREATE_TABLE_QUEUE = "CREATE TABLE "
- + TABLE_NAME_QUEUE + "(" + KEY_ID + " INTEGER PRIMARY KEY,"
- + KEY_FEEDITEM + " INTEGER," + KEY_FEED + " INTEGER)";
-
- private static final String CREATE_TABLE_SIMPLECHAPTERS = "CREATE TABLE "
- + TABLE_NAME_SIMPLECHAPTERS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE
- + " TEXT," + KEY_START + " INTEGER," + KEY_FEEDITEM + " INTEGER,"
- + KEY_LINK + " TEXT," + KEY_IMAGE_URL + " TEXT," + KEY_CHAPTER_TYPE + " INTEGER)";
-
- // SQL Statements for creating indexes
- static final String CREATE_INDEX_FEEDITEMS_FEED = "CREATE INDEX "
- + TABLE_NAME_FEED_ITEMS + "_" + KEY_FEED + " ON " + TABLE_NAME_FEED_ITEMS + " ("
- + KEY_FEED + ")";
-
- static final String CREATE_INDEX_FEEDITEMS_PUBDATE = "CREATE INDEX "
- + TABLE_NAME_FEED_ITEMS + "_" + KEY_PUBDATE + " ON " + TABLE_NAME_FEED_ITEMS + " ("
- + KEY_PUBDATE + ")";
-
- static final String CREATE_INDEX_FEEDITEMS_READ = "CREATE INDEX "
- + TABLE_NAME_FEED_ITEMS + "_" + KEY_READ + " ON " + TABLE_NAME_FEED_ITEMS + " ("
- + KEY_READ + ")";
-
- static final String CREATE_INDEX_QUEUE_FEEDITEM = "CREATE INDEX "
- + TABLE_NAME_QUEUE + "_" + KEY_FEEDITEM + " ON " + TABLE_NAME_QUEUE + " ("
- + KEY_FEEDITEM + ")";
-
- static final String CREATE_INDEX_FEEDMEDIA_FEEDITEM = "CREATE INDEX "
- + TABLE_NAME_FEED_MEDIA + "_" + KEY_FEEDITEM + " ON " + TABLE_NAME_FEED_MEDIA + " ("
- + KEY_FEEDITEM + ")";
-
- static final String CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM = "CREATE INDEX "
- + TABLE_NAME_SIMPLECHAPTERS + "_" + KEY_FEEDITEM + " ON " + TABLE_NAME_SIMPLECHAPTERS + " ("
- + KEY_FEEDITEM + ")";
-
- static final String CREATE_TABLE_FAVORITES = "CREATE TABLE "
- + TABLE_NAME_FAVORITES + "(" + KEY_ID + " INTEGER PRIMARY KEY,"
- + KEY_FEEDITEM + " INTEGER," + KEY_FEED + " INTEGER)";
-
- /**
- * Select all columns from the feed-table
- */
- private static final String[] FEED_SEL_STD = {
- TABLE_NAME_FEEDS + "." + KEY_ID,
- TABLE_NAME_FEEDS + "." + KEY_TITLE,
- TABLE_NAME_FEEDS + "." + KEY_CUSTOM_TITLE,
- TABLE_NAME_FEEDS + "." + KEY_FILE_URL,
- TABLE_NAME_FEEDS + "." + KEY_DOWNLOAD_URL,
- TABLE_NAME_FEEDS + "." + KEY_DOWNLOADED,
- TABLE_NAME_FEEDS + "." + KEY_LINK,
- TABLE_NAME_FEEDS + "." + KEY_DESCRIPTION,
- TABLE_NAME_FEEDS + "." + KEY_PAYMENT_LINK,
- TABLE_NAME_FEEDS + "." + KEY_LASTUPDATE,
- TABLE_NAME_FEEDS + "." + KEY_LANGUAGE,
- TABLE_NAME_FEEDS + "." + KEY_AUTHOR,
- TABLE_NAME_FEEDS + "." + KEY_IMAGE_URL,
- TABLE_NAME_FEEDS + "." + KEY_TYPE,
- TABLE_NAME_FEEDS + "." + KEY_FEED_IDENTIFIER,
- TABLE_NAME_FEEDS + "." + KEY_AUTO_DOWNLOAD_ENABLED,
- TABLE_NAME_FEEDS + "." + KEY_KEEP_UPDATED,
- TABLE_NAME_FEEDS + "." + KEY_IS_PAGED,
- TABLE_NAME_FEEDS + "." + KEY_NEXT_PAGE_LINK,
- TABLE_NAME_FEEDS + "." + KEY_USERNAME,
- TABLE_NAME_FEEDS + "." + KEY_PASSWORD,
- TABLE_NAME_FEEDS + "." + KEY_HIDE,
- TABLE_NAME_FEEDS + "." + KEY_SORT_ORDER,
- TABLE_NAME_FEEDS + "." + KEY_LAST_UPDATE_FAILED,
- TABLE_NAME_FEEDS + "." + KEY_AUTO_DELETE_ACTION,
- TABLE_NAME_FEEDS + "." + KEY_FEED_VOLUME_ADAPTION,
- TABLE_NAME_FEEDS + "." + KEY_INCLUDE_FILTER,
- TABLE_NAME_FEEDS + "." + KEY_EXCLUDE_FILTER,
- TABLE_NAME_FEEDS + "." + KEY_MINIMAL_DURATION_FILTER,
- TABLE_NAME_FEEDS + "." + KEY_FEED_PLAYBACK_SPEED,
- TABLE_NAME_FEEDS + "." + KEY_FEED_TAGS,
- TABLE_NAME_FEEDS + "." + KEY_FEED_SKIP_INTRO,
- TABLE_NAME_FEEDS + "." + KEY_FEED_SKIP_ENDING,
- TABLE_NAME_FEEDS + "." + KEY_EPISODE_NOTIFICATION
- };
-
- /**
- * All the tables in the database
- */
- private static final String[] ALL_TABLES = {
- TABLE_NAME_FEEDS,
- TABLE_NAME_FEED_ITEMS,
- TABLE_NAME_FEED_MEDIA,
- TABLE_NAME_DOWNLOAD_LOG,
- TABLE_NAME_QUEUE,
- TABLE_NAME_SIMPLECHAPTERS,
- TABLE_NAME_FAVORITES
- };
-
- public static final String SELECT_KEY_ITEM_ID = "item_id";
- public static final String SELECT_KEY_MEDIA_ID = "media_id";
-
- private static final String KEYS_FEED_ITEM_WITHOUT_DESCRIPTION =
- TABLE_NAME_FEED_ITEMS + "." + KEY_ID + " AS " + SELECT_KEY_ITEM_ID + ", "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_TITLE + ", "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + ", "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_READ + ", "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_LINK + ", "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_PAYMENT_LINK + ", "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_MEDIA + ", "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + ", "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_HAS_CHAPTERS + ", "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_ITEM_IDENTIFIER + ", "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_IMAGE_URL + ", "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_AUTO_DOWNLOAD_ATTEMPTS;
-
- private static final String KEYS_FEED_MEDIA =
- TABLE_NAME_FEED_MEDIA + "." + KEY_ID + " AS " + SELECT_KEY_MEDIA_ID + ", "
- + TABLE_NAME_FEED_MEDIA + "." + KEY_DURATION + ", "
- + TABLE_NAME_FEED_MEDIA + "." + KEY_FILE_URL + ", "
- + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOAD_URL + ", "
- + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + ", "
- + TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + ", "
- + TABLE_NAME_FEED_MEDIA + "." + KEY_SIZE + ", "
- + TABLE_NAME_FEED_MEDIA + "." + KEY_MIME_TYPE + ", "
- + TABLE_NAME_FEED_MEDIA + "." + KEY_PLAYBACK_COMPLETION_DATE + ", "
- + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM + ", "
- + TABLE_NAME_FEED_MEDIA + "." + KEY_PLAYED_DURATION + ", "
- + TABLE_NAME_FEED_MEDIA + "." + KEY_HAS_EMBEDDED_PICTURE + ", "
- + TABLE_NAME_FEED_MEDIA + "." + KEY_LAST_PLAYED_TIME;
-
- private static final String JOIN_FEED_ITEM_AND_MEDIA = " LEFT JOIN " + TABLE_NAME_FEED_MEDIA
- + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM + " ";
-
- private static final String SELECT_FEED_ITEMS_AND_MEDIA_WITH_DESCRIPTION =
- "SELECT " + KEYS_FEED_ITEM_WITHOUT_DESCRIPTION + ", " + KEYS_FEED_MEDIA + ", "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_DESCRIPTION
- + " FROM " + TABLE_NAME_FEED_ITEMS
- + JOIN_FEED_ITEM_AND_MEDIA;
- private static final String SELECT_FEED_ITEMS_AND_MEDIA =
- "SELECT " + KEYS_FEED_ITEM_WITHOUT_DESCRIPTION + ", " + KEYS_FEED_MEDIA
- + " FROM " + TABLE_NAME_FEED_ITEMS
- + JOIN_FEED_ITEM_AND_MEDIA;
-
- private static Context context;
- private static PodDBAdapter instance;
-
- private final SQLiteDatabase db;
- private final PodDBHelper dbHelper;
-
- public static void init(Context context) {
- PodDBAdapter.context = context.getApplicationContext();
- }
-
- public static synchronized PodDBAdapter getInstance() {
- if (instance == null) {
- instance = new PodDBAdapter();
- }
- return instance;
- }
-
- private PodDBAdapter() {
- dbHelper = new PodDBHelper(PodDBAdapter.context, DATABASE_NAME, null);
- db = openDb();
- }
-
- private SQLiteDatabase openDb() {
- SQLiteDatabase newDb;
- try {
- newDb = dbHelper.getWritableDatabase();
- newDb.disableWriteAheadLogging();
- } catch (SQLException ex) {
- Log.e(TAG, Log.getStackTraceString(ex));
- newDb = dbHelper.getReadableDatabase();
- }
- return newDb;
- }
-
- public synchronized PodDBAdapter open() {
- // do nothing
- return this;
- }
-
- public synchronized void close() {
- // do nothing
- }
-
- /**
- * <p>Resets all database connections to ensure new database connections for
- * the next test case. Call method only for unit tests.</p>
- *
- * <p>That's a workaround for a Robolectric issue in ShadowSQLiteConnection
- * that leads to an error <tt>IllegalStateException: Illegal connection
- * pointer</tt> if several threads try to use the same database connection.
- * For more information see
- * <a href="https://github.com/robolectric/robolectric/issues/1890">robolectric/robolectric#1890</a>.</p>
- */
- @VisibleForTesting(otherwise = VisibleForTesting.NONE)
- public static void tearDownTests() {
- getInstance().dbHelper.close();
- instance = null;
- }
-
- public static boolean deleteDatabase() {
- PodDBAdapter adapter = getInstance();
- adapter.open();
- try {
- for (String tableName : ALL_TABLES) {
- adapter.db.delete(tableName, "1", null);
- }
- return true;
- } finally {
- adapter.close();
- }
- }
-
- /**
- * Inserts or updates a feed entry
- *
- * @return the id of the entry
- */
- private long setFeed(Feed feed) {
- ContentValues values = new ContentValues();
- values.put(KEY_TITLE, feed.getFeedTitle());
- values.put(KEY_LINK, feed.getLink());
- values.put(KEY_DESCRIPTION, feed.getDescription());
- values.put(KEY_PAYMENT_LINK, FeedFunding.getPaymentLinksAsString(feed.getPaymentLinks()));
- values.put(KEY_AUTHOR, feed.getAuthor());
- values.put(KEY_LANGUAGE, feed.getLanguage());
- values.put(KEY_IMAGE_URL, feed.getImageUrl());
-
- values.put(KEY_FILE_URL, feed.getFile_url());
- values.put(KEY_DOWNLOAD_URL, feed.getDownload_url());
- values.put(KEY_DOWNLOADED, feed.isDownloaded());
- values.put(KEY_LASTUPDATE, feed.getLastUpdate());
- values.put(KEY_TYPE, feed.getType());
- values.put(KEY_FEED_IDENTIFIER, feed.getFeedIdentifier());
-
- values.put(KEY_IS_PAGED, feed.isPaged());
- values.put(KEY_NEXT_PAGE_LINK, feed.getNextPageLink());
- if (feed.getItemFilter() != null && feed.getItemFilter().getValues().length > 0) {
- values.put(KEY_HIDE, TextUtils.join(",", feed.getItemFilter().getValues()));
- } else {
- values.put(KEY_HIDE, "");
- }
- values.put(KEY_SORT_ORDER, toCodeString(feed.getSortOrder()));
- values.put(KEY_LAST_UPDATE_FAILED, feed.hasLastUpdateFailed());
- if (feed.getId() == 0) {
- // Create new entry
- Log.d(this.toString(), "Inserting new Feed into db");
- feed.setId(db.insert(TABLE_NAME_FEEDS, null, values));
- } else {
- Log.d(this.toString(), "Updating existing Feed in db");
- db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?",
- new String[]{String.valueOf(feed.getId())});
- }
- return feed.getId();
- }
-
- public void setFeedPreferences(FeedPreferences prefs) {
- if (prefs.getFeedID() == 0) {
- throw new IllegalArgumentException("Feed ID of preference must not be null");
- }
- ContentValues values = new ContentValues();
- values.put(KEY_AUTO_DOWNLOAD_ENABLED, prefs.getAutoDownload());
- values.put(KEY_KEEP_UPDATED, prefs.getKeepUpdated());
- values.put(KEY_AUTO_DELETE_ACTION, prefs.getAutoDeleteAction().ordinal());
- values.put(KEY_FEED_VOLUME_ADAPTION, prefs.getVolumeAdaptionSetting().toInteger());
- values.put(KEY_USERNAME, prefs.getUsername());
- values.put(KEY_PASSWORD, prefs.getPassword());
- values.put(KEY_INCLUDE_FILTER, prefs.getFilter().getIncludeFilter());
- values.put(KEY_EXCLUDE_FILTER, prefs.getFilter().getExcludeFilter());
- values.put(KEY_MINIMAL_DURATION_FILTER, prefs.getFilter().getMinimalDurationFilter());
- values.put(KEY_FEED_PLAYBACK_SPEED, prefs.getFeedPlaybackSpeed());
- values.put(KEY_FEED_TAGS, prefs.getTagsAsString());
- values.put(KEY_FEED_SKIP_INTRO, prefs.getFeedSkipIntro());
- values.put(KEY_FEED_SKIP_ENDING, prefs.getFeedSkipEnding());
- values.put(KEY_EPISODE_NOTIFICATION, prefs.getShowEpisodeNotification());
- db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(prefs.getFeedID())});
- }
-
- public void setFeedItemFilter(long feedId, Set<String> filterValues) {
- String valuesList = TextUtils.join(",", filterValues);
- Log.d(TAG, String.format(Locale.US,
- "setFeedItemFilter() called with: feedId = [%d], filterValues = [%s]", feedId, valuesList));
- ContentValues values = new ContentValues();
- values.put(KEY_HIDE, valuesList);
- db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(feedId)});
- }
-
- public void setFeedItemSortOrder(long feedId, @Nullable SortOrder sortOrder) {
- ContentValues values = new ContentValues();
- values.put(KEY_SORT_ORDER, toCodeString(sortOrder));
- db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(feedId)});
- }
-
- /**
- * Inserts or updates a media entry
- *
- * @return the id of the entry
- */
- public long setMedia(FeedMedia media) {
- ContentValues values = new ContentValues();
- values.put(KEY_DURATION, media.getDuration());
- values.put(KEY_POSITION, media.getPosition());
- values.put(KEY_SIZE, media.getSize());
- values.put(KEY_MIME_TYPE, media.getMime_type());
- values.put(KEY_DOWNLOAD_URL, media.getDownload_url());
- values.put(KEY_DOWNLOADED, media.isDownloaded());
- values.put(KEY_FILE_URL, media.getFile_url());
- values.put(KEY_HAS_EMBEDDED_PICTURE, media.hasEmbeddedPicture());
- values.put(KEY_LAST_PLAYED_TIME, media.getLastPlayedTime());
-
- if (media.getPlaybackCompletionDate() != null) {
- values.put(KEY_PLAYBACK_COMPLETION_DATE, media.getPlaybackCompletionDate().getTime());
- } else {
- values.put(KEY_PLAYBACK_COMPLETION_DATE, 0);
- }
- if (media.getItem() != null) {
- values.put(KEY_FEEDITEM, media.getItem().getId());
- }
- if (media.getId() == 0) {
- media.setId(db.insert(TABLE_NAME_FEED_MEDIA, null, values));
- } else {
- db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?",
- new String[]{String.valueOf(media.getId())});
- }
- return media.getId();
- }
-
- public void setFeedMediaPlaybackInformation(FeedMedia media) {
- if (media.getId() != 0) {
- ContentValues values = new ContentValues();
- values.put(KEY_POSITION, media.getPosition());
- values.put(KEY_DURATION, media.getDuration());
- values.put(KEY_PLAYED_DURATION, media.getPlayedDuration());
- values.put(KEY_LAST_PLAYED_TIME, media.getLastPlayedTime());
- db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?",
- new String[]{String.valueOf(media.getId())});
- } else {
- Log.e(TAG, "setFeedMediaPlaybackInformation: ID of media was 0");
- }
- }
-
- public void setFeedMediaPlaybackCompletionDate(FeedMedia media) {
- if (media.getId() != 0) {
- ContentValues values = new ContentValues();
- values.put(KEY_PLAYBACK_COMPLETION_DATE, media.getPlaybackCompletionDate().getTime());
- values.put(KEY_PLAYED_DURATION, media.getPlayedDuration());
- db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?",
- new String[]{String.valueOf(media.getId())});
- } else {
- Log.e(TAG, "setFeedMediaPlaybackCompletionDate: ID of media was 0");
- }
- }
-
- public void resetAllMediaPlayedDuration() {
- try {
- db.beginTransactionNonExclusive();
- ContentValues values = new ContentValues();
- values.put(KEY_PLAYED_DURATION, 0);
- db.update(TABLE_NAME_FEED_MEDIA, values, null, new String[0]);
- db.setTransactionSuccessful();
- } catch (SQLException e) {
- Log.e(TAG, Log.getStackTraceString(e));
- } finally {
- db.endTransaction();
- }
- }
-
- /**
- * Insert all FeedItems of a feed and the feed object itself in a single
- * transaction
- */
- public void setCompleteFeed(Feed... feeds) {
- try {
- db.beginTransactionNonExclusive();
- for (Feed feed : feeds) {
- setFeed(feed);
- if (feed.getItems() != null) {
- for (FeedItem item : feed.getItems()) {
- updateOrInsertFeedItem(item, false);
- }
- }
- if (feed.getPreferences() != null) {
- setFeedPreferences(feed.getPreferences());
- }
- }
- db.setTransactionSuccessful();
- } catch (SQLException e) {
- Log.e(TAG, Log.getStackTraceString(e));
- } finally {
- db.endTransaction();
- }
- }
-
- /**
- * Updates the download URL of a Feed.
- */
- public void setFeedDownloadUrl(String original, String updated) {
- ContentValues values = new ContentValues();
- values.put(KEY_DOWNLOAD_URL, updated);
- db.update(TABLE_NAME_FEEDS, values, KEY_DOWNLOAD_URL + "=?", new String[]{original});
- }
-
- public void storeFeedItemlist(List<FeedItem> items) {
- try {
- db.beginTransactionNonExclusive();
- for (FeedItem item : items) {
- updateOrInsertFeedItem(item, true);
- }
- db.setTransactionSuccessful();
- } catch (SQLException e) {
- Log.e(TAG, Log.getStackTraceString(e));
- } finally {
- db.endTransaction();
- }
- }
-
- public long setSingleFeedItem(FeedItem item) {
- long result = 0;
- try {
- db.beginTransactionNonExclusive();
- result = updateOrInsertFeedItem(item, true);
- db.setTransactionSuccessful();
- } catch (SQLException e) {
- Log.e(TAG, Log.getStackTraceString(e));
- } finally {
- db.endTransaction();
- }
- return result;
- }
-
- /**
- * Inserts or updates a feeditem entry
- *
- * @param item The FeedItem
- * @param saveFeed true if the Feed of the item should also be saved. This should be set to
- * false if the method is executed on a list of FeedItems of the same Feed.
- * @return the id of the entry
- */
- private long updateOrInsertFeedItem(FeedItem item, boolean saveFeed) {
- if (item.getId() == 0 && item.getPubDate() == null) {
- Log.e(TAG, "Newly saved item has no pubDate. Using current date as pubDate");
- item.setPubDate(new Date());
- }
-
- ContentValues values = new ContentValues();
- values.put(KEY_TITLE, item.getTitle());
- values.put(KEY_LINK, item.getLink());
- if (item.getDescription() != null) {
- values.put(KEY_DESCRIPTION, item.getDescription());
- }
- values.put(KEY_PUBDATE, item.getPubDate().getTime());
- values.put(KEY_PAYMENT_LINK, item.getPaymentLink());
- if (saveFeed && item.getFeed() != null) {
- setFeed(item.getFeed());
- }
- values.put(KEY_FEED, item.getFeed().getId());
- if (item.isNew()) {
- values.put(KEY_READ, FeedItem.NEW);
- } else if (item.isPlayed()) {
- values.put(KEY_READ, FeedItem.PLAYED);
- } else {
- values.put(KEY_READ, FeedItem.UNPLAYED);
- }
- values.put(KEY_HAS_CHAPTERS, item.getChapters() != null || item.hasChapters());
- values.put(KEY_ITEM_IDENTIFIER, item.getItemIdentifier());
- values.put(KEY_AUTO_DOWNLOAD_ATTEMPTS, item.getAutoDownloadAttemptsAndTime());
- values.put(KEY_IMAGE_URL, item.getImageUrl());
-
- if (item.getId() == 0) {
- item.setId(db.insert(TABLE_NAME_FEED_ITEMS, null, values));
- } else {
- db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?",
- new String[]{String.valueOf(item.getId())});
- }
- if (item.getMedia() != null) {
- setMedia(item.getMedia());
- }
- if (item.getChapters() != null) {
- setChapters(item);
- }
- return item.getId();
- }
-
- public void setFeedItemRead(int played, long itemId, long mediaId,
- boolean resetMediaPosition) {
- try {
- db.beginTransactionNonExclusive();
- ContentValues values = new ContentValues();
-
- values.put(KEY_READ, played);
- db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?", new String[]{String.valueOf(itemId)});
-
- if (resetMediaPosition) {
- values.clear();
- values.put(KEY_POSITION, 0);
- db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?", new String[]{String.valueOf(mediaId)});
- }
-
- db.setTransactionSuccessful();
- } catch (SQLException e) {
- Log.e(TAG, Log.getStackTraceString(e));
- } finally {
- db.endTransaction();
- }
- }
-
- /**
- * Sets the 'read' attribute of the item.
- *
- * @param read must be one of FeedItem.PLAYED, FeedItem.NEW, FeedItem.UNPLAYED
- * @param itemIds items to change the value of
- */
- public void setFeedItemRead(int read, long... itemIds) {
- try {
- db.beginTransactionNonExclusive();
- ContentValues values = new ContentValues();
- for (long id : itemIds) {
- values.clear();
- values.put(KEY_READ, read);
- db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?", new String[]{String.valueOf(id)});
- }
- db.setTransactionSuccessful();
- } catch (SQLException e) {
- Log.e(TAG, Log.getStackTraceString(e));
- } finally {
- db.endTransaction();
- }
- }
-
- private void setChapters(FeedItem item) {
- ContentValues values = new ContentValues();
- for (Chapter chapter : item.getChapters()) {
- values.put(KEY_TITLE, chapter.getTitle());
- values.put(KEY_START, chapter.getStart());
- values.put(KEY_FEEDITEM, item.getId());
- values.put(KEY_LINK, chapter.getLink());
- values.put(KEY_IMAGE_URL, chapter.getImageUrl());
- values.put(KEY_CHAPTER_TYPE, chapter.getChapterType());
- if (chapter.getId() == 0) {
- chapter.setId(db.insert(TABLE_NAME_SIMPLECHAPTERS, null, values));
- } else {
- db.update(TABLE_NAME_SIMPLECHAPTERS, values, KEY_ID + "=?",
- new String[]{String.valueOf(chapter.getId())});
- }
- }
- }
-
- public void setFeedLastUpdateFailed(long feedId, boolean failed) {
- final String sql = "UPDATE " + TABLE_NAME_FEEDS
- + " SET " + KEY_LAST_UPDATE_FAILED + "=" + (failed ? "1" : "0")
- + " WHERE " + KEY_ID + "=" + feedId;
- db.execSQL(sql);
- }
-
- void setFeedCustomTitle(long feedId, String customTitle) {
- ContentValues values = new ContentValues();
- values.put(KEY_CUSTOM_TITLE, customTitle);
- db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(feedId)});
- }
-
- /**
- * Inserts or updates a download status.
- */
- public long setDownloadStatus(DownloadStatus status) {
- ContentValues values = new ContentValues();
- values.put(KEY_FEEDFILE, status.getFeedfileId());
- values.put(KEY_FEEDFILETYPE, status.getFeedfileType());
- values.put(KEY_REASON, status.getReason().getCode());
- values.put(KEY_SUCCESSFUL, status.isSuccessful());
- values.put(KEY_COMPLETION_DATE, status.getCompletionDate().getTime());
- values.put(KEY_REASON_DETAILED, status.getReasonDetailed());
- values.put(KEY_DOWNLOADSTATUS_TITLE, status.getTitle());
- if (status.getId() == 0) {
- status.setId(db.insert(TABLE_NAME_DOWNLOAD_LOG, null, values));
- } else {
- db.update(TABLE_NAME_DOWNLOAD_LOG, values, KEY_ID + "=?",
- new String[]{String.valueOf(status.getId())});
- }
- return status.getId();
- }
-
- public void setFavorites(List<FeedItem> favorites) {
- ContentValues values = new ContentValues();
- try {
- db.beginTransactionNonExclusive();
- 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();
- } catch (SQLException e) {
- Log.e(TAG, Log.getStackTraceString(e));
- } finally {
- db.endTransaction();
- }
- }
-
- /**
- * Adds the item to favorites
- */
- public void addFavoriteItem(FeedItem item) {
- // don't add an item that's already there...
- if (isItemInFavorites(item)) {
- Log.d(TAG, "item already in favorites");
- return;
- }
- ContentValues values = new ContentValues();
- values.put(KEY_FEEDITEM, item.getId());
- values.put(KEY_FEED, item.getFeedId());
- db.insert(TABLE_NAME_FAVORITES, null, values);
- }
-
- public void removeFavoriteItem(FeedItem item) {
- String deleteClause = String.format("DELETE FROM %s WHERE %s=%s AND %s=%s",
- TABLE_NAME_FAVORITES,
- KEY_FEEDITEM, item.getId(),
- KEY_FEED, item.getFeedId());
- db.execSQL(deleteClause);
- }
-
- private boolean isItemInFavorites(FeedItem item) {
- String query = String.format(Locale.US, "SELECT %s from %s WHERE %s=%d",
- KEY_ID, TABLE_NAME_FAVORITES, KEY_FEEDITEM, item.getId());
- Cursor c = db.rawQuery(query, null);
- int count = c.getCount();
- c.close();
- return count > 0;
- }
-
- public void setQueue(List<FeedItem> queue) {
- ContentValues values = new ContentValues();
- try {
- db.beginTransactionNonExclusive();
- db.delete(TABLE_NAME_QUEUE, null, null);
- for (int i = 0; i < queue.size(); i++) {
- FeedItem item = queue.get(i);
- values.put(KEY_ID, i);
- values.put(KEY_FEEDITEM, item.getId());
- values.put(KEY_FEED, item.getFeed().getId());
- db.insertWithOnConflict(TABLE_NAME_QUEUE, null, values, SQLiteDatabase.CONFLICT_REPLACE);
- }
- db.setTransactionSuccessful();
- } catch (SQLException e) {
- Log.e(TAG, Log.getStackTraceString(e));
- } finally {
- db.endTransaction();
- }
- }
-
- public void clearQueue() {
- db.delete(TABLE_NAME_QUEUE, null, null);
- }
-
- /**
- * Remove the listed items and their FeedMedia entries.
- */
- public void removeFeedItems(@NonNull List<FeedItem> items) {
- try {
- StringBuilder mediaIds = new StringBuilder();
- StringBuilder itemIds = new StringBuilder();
- for (FeedItem item : items) {
- if (item.getMedia() != null) {
- if (mediaIds.length() != 0) {
- mediaIds.append(",");
- }
- mediaIds.append(item.getMedia().getId());
- }
- if (itemIds.length() != 0) {
- itemIds.append(",");
- }
- itemIds.append(item.getId());
- }
-
- db.beginTransactionNonExclusive();
- db.delete(TABLE_NAME_SIMPLECHAPTERS, KEY_FEEDITEM + " IN (" + itemIds + ")", null);
- db.delete(TABLE_NAME_DOWNLOAD_LOG, KEY_FEEDFILETYPE + "=" + FeedMedia.FEEDFILETYPE_FEEDMEDIA
- + " AND " + KEY_FEEDFILE + " IN (" + mediaIds + ")", null);
- db.delete(TABLE_NAME_FEED_MEDIA, KEY_ID + " IN (" + mediaIds + ")", null);
- db.delete(TABLE_NAME_FEED_ITEMS, KEY_ID + " IN (" + itemIds + ")", null);
- db.setTransactionSuccessful();
- } catch (SQLException e) {
- Log.e(TAG, Log.getStackTraceString(e));
- } finally {
- db.endTransaction();
- }
- }
-
- /**
- * Remove a feed with all its FeedItems and Media entries.
- */
- public void removeFeed(Feed feed) {
- try {
- db.beginTransactionNonExclusive();
- if (feed.getItems() != null) {
- removeFeedItems(feed.getItems());
- }
- // delete download log entries for feed
- db.delete(TABLE_NAME_DOWNLOAD_LOG, KEY_FEEDFILE + "=? AND " + KEY_FEEDFILETYPE + "=?",
- new String[]{String.valueOf(feed.getId()), String.valueOf(Feed.FEEDFILETYPE_FEED)});
-
- db.delete(TABLE_NAME_FEEDS, KEY_ID + "=?",
- new String[]{String.valueOf(feed.getId())});
- db.setTransactionSuccessful();
- } catch (SQLException e) {
- Log.e(TAG, Log.getStackTraceString(e));
- } finally {
- db.endTransaction();
- }
- }
-
- public void clearPlaybackHistory() {
- ContentValues values = new ContentValues();
- values.put(KEY_PLAYBACK_COMPLETION_DATE, 0);
- db.update(TABLE_NAME_FEED_MEDIA, values, null, null);
- }
-
- public void clearDownloadLog() {
- db.delete(TABLE_NAME_DOWNLOAD_LOG, null, null);
- }
-
- /**
- * Get all Feeds from the Feed Table.
- *
- * @return The cursor of the query
- */
- public final Cursor getAllFeedsCursor() {
- return db.query(TABLE_NAME_FEEDS, FEED_SEL_STD, null, null, null, null,
- KEY_TITLE + " COLLATE NOCASE ASC");
- }
-
- public final Cursor getFeedCursorDownloadUrls() {
- return db.query(TABLE_NAME_FEEDS, new String[]{KEY_ID, KEY_DOWNLOAD_URL}, null, null, null, null, null);
- }
-
- /**
- * Returns a cursor with all FeedItems of a Feed. Uses FEEDITEM_SEL_FI_SMALL
- *
- * @param feed The feed you want to get the FeedItems from.
- * @return The cursor of the query
- */
- public final Cursor getItemsOfFeedCursor(final Feed feed, FeedItemFilter filter) {
- String filterQuery = FeedItemFilterQuery.generateFrom(filter);
- String whereClauseAnd = "".equals(filterQuery) ? "" : " AND " + filterQuery;
- final String query = SELECT_FEED_ITEMS_AND_MEDIA
- + " WHERE " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + "=" + feed.getId()
- + whereClauseAnd;
- return db.rawQuery(query, null);
- }
-
- /**
- * Return the description and content_encoded of item
- */
- public final Cursor getDescriptionOfItem(final FeedItem item) {
- final String query = "SELECT " + KEY_DESCRIPTION
- + " FROM " + TABLE_NAME_FEED_ITEMS
- + " WHERE " + KEY_ID + "=" + item.getId();
- return db.rawQuery(query, null);
- }
-
- public final Cursor getSimpleChaptersOfFeedItemCursor(final FeedItem item) {
- return db.query(TABLE_NAME_SIMPLECHAPTERS, null, KEY_FEEDITEM
- + "=?", new String[]{String.valueOf(item.getId())}, null,
- null, null
- );
- }
-
- public final Cursor getDownloadLog(final int feedFileType, final long feedFileId) {
- final String query = "SELECT * FROM " + TABLE_NAME_DOWNLOAD_LOG +
- " WHERE " + KEY_FEEDFILE + "=" + feedFileId + " AND " + KEY_FEEDFILETYPE + "=" + feedFileType
- + " ORDER BY " + KEY_ID + " DESC";
- return db.rawQuery(query, null);
- }
-
- public final Cursor getDownloadLogCursor(final int limit) {
- return db.query(TABLE_NAME_DOWNLOAD_LOG, null, null, null, null,
- null, KEY_COMPLETION_DATE + " DESC LIMIT " + limit);
- }
-
- /**
- * Returns a cursor which contains all feed items in the queue. The returned
- * cursor uses the FEEDITEM_SEL_FI_SMALL selection.
- * cursor uses the FEEDITEM_SEL_FI_SMALL selection.
- */
- public final Cursor getQueueCursor() {
- final String query = SELECT_FEED_ITEMS_AND_MEDIA
- + " INNER JOIN " + TABLE_NAME_QUEUE
- + " ON " + SELECT_KEY_ITEM_ID + " = " + TABLE_NAME_QUEUE + "." + KEY_FEEDITEM
- + " ORDER BY " + TABLE_NAME_QUEUE + "." + KEY_ID;
- return db.rawQuery(query, null);
- }
-
- public Cursor getQueueIDCursor() {
- return db.query(TABLE_NAME_QUEUE, new String[]{KEY_FEEDITEM}, null, null, null, null, KEY_ID + " ASC", null);
- }
-
- public Cursor getNextInQueue(final FeedItem item) {
- final String query = SELECT_FEED_ITEMS_AND_MEDIA
- + "INNER JOIN " + TABLE_NAME_QUEUE
- + " ON " + SELECT_KEY_ITEM_ID + " = " + TABLE_NAME_QUEUE + "." + KEY_FEEDITEM
- + " WHERE Queue.ID > (SELECT Queue.ID FROM Queue WHERE Queue.FeedItem = "
- + item.getId()
- + ")"
- + " ORDER BY Queue.ID"
- + " LIMIT 1";
- return db.rawQuery(query, null);
- }
-
- public final Cursor getFavoritesCursor(int offset, int limit) {
- final String query = SELECT_FEED_ITEMS_AND_MEDIA
- + " INNER JOIN " + TABLE_NAME_FAVORITES
- + " ON " + SELECT_KEY_ITEM_ID + " = " + TABLE_NAME_FAVORITES + "." + KEY_FEEDITEM
- + " ORDER BY " + TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + " DESC"
- + " LIMIT " + offset + ", " + limit;
- return db.rawQuery(query, null);
- }
-
- public void setFeedItems(int state) {
- setFeedItems(Integer.MIN_VALUE, state, 0);
- }
-
- public void setFeedItems(int oldState, int newState) {
- setFeedItems(oldState, newState, 0);
- }
-
- public void setFeedItems(int state, long feedId) {
- setFeedItems(Integer.MIN_VALUE, state, feedId);
- }
-
- public void setFeedItems(int oldState, int newState, long feedId) {
- String sql = "UPDATE " + TABLE_NAME_FEED_ITEMS + " SET " + KEY_READ + "=" + newState;
- if (feedId > 0) {
- sql += " WHERE " + KEY_FEED + "=" + feedId;
- }
- if (FeedItem.NEW <= oldState && oldState <= FeedItem.PLAYED) {
- sql += feedId > 0 ? " AND " : " WHERE ";
- sql += KEY_READ + "=" + oldState;
- }
- db.execSQL(sql);
- }
-
- /**
- * Returns a cursor which contains all feed items that are considered new.
- * Excludes those feeds that do not have 'Keep Updated' enabled.
- * The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection.
- */
- public final Cursor getNewItemsCursor(int offset, int limit) {
- final String query = SELECT_FEED_ITEMS_AND_MEDIA
- + " INNER JOIN " + TABLE_NAME_FEEDS
- + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + "=" + TABLE_NAME_FEEDS + "." + KEY_ID
- + " WHERE " + TABLE_NAME_FEED_ITEMS + "." + KEY_READ + "=" + FeedItem.NEW
- + " AND " + TABLE_NAME_FEEDS + "." + KEY_KEEP_UPDATED + " > 0"
- + " ORDER BY " + TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + " DESC"
- + " LIMIT " + offset + ", " + limit;
- return db.rawQuery(query, null);
- }
-
- public final Cursor getRecentlyPublishedItemsCursor(int offset, int limit, FeedItemFilter filter) {
- String filterQuery = FeedItemFilterQuery.generateFrom(filter);
- String whereClause = "".equals(filterQuery) ? "" : " WHERE " + filterQuery;
- final String query = SELECT_FEED_ITEMS_AND_MEDIA + whereClause
- + " ORDER BY " + KEY_PUBDATE + " DESC LIMIT " + offset + ", " + limit;
- return db.rawQuery(query, null);
- }
-
- public Cursor getDownloadedItemsCursor() {
- final String query = SELECT_FEED_ITEMS_AND_MEDIA
- + "WHERE " + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " > 0";
- return db.rawQuery(query, null);
- }
-
- public Cursor getPlayedItemsCursor() {
- final String query = SELECT_FEED_ITEMS_AND_MEDIA
- + "WHERE " + TABLE_NAME_FEED_ITEMS + "." + KEY_READ + "=" + FeedItem.PLAYED;
- return db.rawQuery(query, null);
- }
-
- /**
- * Returns a cursor which contains feed media objects with a playback
- * completion date in ascending order.
- *
- * @param limit The maximum row count of the returned cursor. Must be an
- * integer >= 0.
- * @throws IllegalArgumentException if limit < 0
- */
- public final Cursor getCompletedMediaCursor(int limit) {
- if (limit < 0) {
- throw new IllegalArgumentException("Limit must be >= 0");
- }
-
- return db.query(TABLE_NAME_FEED_MEDIA, null,
- KEY_PLAYBACK_COMPLETION_DATE + " > 0", null, null,
- null, String.format(Locale.US, "%s DESC LIMIT %d", KEY_PLAYBACK_COMPLETION_DATE, limit));
- }
-
- public final Cursor getSingleFeedMediaCursor(long id) {
- final String query = "SELECT " + KEYS_FEED_MEDIA + " FROM " + TABLE_NAME_FEED_MEDIA
- + " WHERE " + KEY_ID + "=" + id;
- return db.rawQuery(query, null);
- }
-
- public final Cursor getFeedCursor(final long id) {
- return db.query(TABLE_NAME_FEEDS, FEED_SEL_STD, KEY_ID + "=" + id, null,
- null, null, null);
- }
-
- public final Cursor getFeedItemCursor(final String id) {
- return getFeedItemCursor(new String[]{id});
- }
-
- public final Cursor getFeedItemCursor(final String[] ids) {
- if (ids.length > IN_OPERATOR_MAXIMUM) {
- throw new IllegalArgumentException("number of IDs must not be larger than " + IN_OPERATOR_MAXIMUM);
- }
- final String query = SELECT_FEED_ITEMS_AND_MEDIA
- + " WHERE " + SELECT_KEY_ITEM_ID + " IN (" + TextUtils.join(",", ids) + ")";
- return db.rawQuery(query, null);
- }
-
- public final Cursor getFeedItemCursor(final String guid, final String episodeUrl) {
- String escapedEpisodeUrl = DatabaseUtils.sqlEscapeString(episodeUrl);
- String whereClauseCondition = TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOAD_URL + "=" + escapedEpisodeUrl;
-
- if (guid != null) {
- String escapedGuid = DatabaseUtils.sqlEscapeString(guid);
- whereClauseCondition = TABLE_NAME_FEED_ITEMS + "." + KEY_ITEM_IDENTIFIER + "=" + escapedGuid;
- }
-
- final String query = SELECT_FEED_ITEMS_AND_MEDIA
- + " INNER JOIN " + TABLE_NAME_FEEDS
- + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + "=" + TABLE_NAME_FEEDS + "." + KEY_ID
- + " WHERE " + whereClauseCondition;
- return db.rawQuery(query, null);
- }
-
- public Cursor getImageAuthenticationCursor(final String imageUrl) {
- String downloadUrl = DatabaseUtils.sqlEscapeString(imageUrl);
- final String query = ""
- + "SELECT " + KEY_USERNAME + "," + KEY_PASSWORD + " FROM " + TABLE_NAME_FEED_ITEMS
- + " INNER JOIN " + TABLE_NAME_FEEDS
- + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + " = " + TABLE_NAME_FEEDS + "." + KEY_ID
- + " WHERE " + TABLE_NAME_FEED_ITEMS + "." + KEY_IMAGE_URL + "=" + downloadUrl
- + " UNION SELECT " + KEY_USERNAME + "," + KEY_PASSWORD + " FROM " + TABLE_NAME_FEEDS
- + " WHERE " + TABLE_NAME_FEEDS + "." + KEY_IMAGE_URL + "=" + downloadUrl;
- return db.rawQuery(query, null);
- }
-
- public final Cursor getMonthlyStatisticsCursor() {
- final String query = "SELECT SUM(" + KEY_PLAYED_DURATION + ") AS total_duration"
- + ", strftime('%m', datetime(" + KEY_LAST_PLAYED_TIME + "/1000, 'unixepoch')) AS month"
- + ", strftime('%Y', datetime(" + KEY_LAST_PLAYED_TIME + "/1000, 'unixepoch')) AS year"
- + " FROM " + TABLE_NAME_FEED_MEDIA
- + " WHERE " + KEY_LAST_PLAYED_TIME + " > 0 AND " + KEY_PLAYED_DURATION + " > 0"
- + " GROUP BY year, month"
- + " ORDER BY year, month";
- return db.rawQuery(query, null);
- }
-
- public int getQueueSize() {
- final String query = String.format("SELECT COUNT(%s) FROM %s", KEY_ID, TABLE_NAME_QUEUE);
- Cursor c = db.rawQuery(query, null);
- int result = 0;
- if (c.moveToFirst()) {
- result = c.getInt(0);
- }
- c.close();
- return result;
- }
-
- public final int getNumberOfNewItems() {
- Object[] args = new String[]{
- TABLE_NAME_FEED_ITEMS + "." + KEY_ID,
- TABLE_NAME_FEED_ITEMS,
- TABLE_NAME_FEEDS,
- TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + "=" + TABLE_NAME_FEEDS + "." + KEY_ID,
- TABLE_NAME_FEED_ITEMS + "." + KEY_READ + "=" + FeedItem.NEW
- + " AND " + TABLE_NAME_FEEDS + "." + KEY_KEEP_UPDATED + " > 0"
- };
- final String query = String.format("SELECT COUNT(%s) FROM %s INNER JOIN %s ON %s WHERE %s", args);
- Cursor c = db.rawQuery(query, null);
- int result = 0;
- if (c.moveToFirst()) {
- result = c.getInt(0);
- }
- c.close();
- return result;
- }
-
- public final LongIntMap getFeedCounters(long... feedIds) {
- int setting = UserPreferences.getFeedCounterSetting();
-
- return getFeedCounters(setting, feedIds);
- }
-
- public final LongIntMap getFeedCounters(int setting, long... feedIds) {
- String whereRead;
- switch (setting) {
- case UserPreferences.FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM:
- whereRead = "(" + KEY_READ + "=" + FeedItem.NEW +
- " OR " + KEY_READ + "=" + FeedItem.UNPLAYED + ")";
- break;
- case UserPreferences.FEED_COUNTER_SHOW_NEW:
- whereRead = KEY_READ + "=" + FeedItem.NEW;
- break;
- case UserPreferences.FEED_COUNTER_SHOW_UNPLAYED:
- whereRead = KEY_READ + "=" + FeedItem.UNPLAYED;
- break;
- case UserPreferences.FEED_COUNTER_SHOW_DOWNLOADED:
- whereRead = KEY_DOWNLOADED + "=1";
- break;
- case UserPreferences.FEED_COUNTER_SHOW_NONE:
- // deliberate fall-through
- default: // NONE
- return new LongIntMap(0);
- }
- return conditionalFeedCounterRead(whereRead, feedIds);
- }
-
- private LongIntMap conditionalFeedCounterRead(String whereRead, long... feedIds) {
- String limitFeeds = "";
- if (feedIds.length > 0) {
- // work around TextUtils.join wanting only boxed items
- // and StringUtils.join() causing NoSuchMethodErrors on MIUI
- StringBuilder builder = new StringBuilder();
- for (long id : feedIds) {
- builder.append(id);
- builder.append(',');
- }
- // there's an extra ',', get rid of it
- builder.deleteCharAt(builder.length() - 1);
- limitFeeds = KEY_FEED + " IN (" + builder.toString() + ") AND ";
- }
-
- final String query = "SELECT " + KEY_FEED + ", COUNT(" + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + ") AS count "
- + " FROM " + TABLE_NAME_FEED_ITEMS
- + " LEFT JOIN " + TABLE_NAME_FEED_MEDIA + " ON "
- + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM
- + " WHERE " + limitFeeds + " "
- + whereRead + " GROUP BY " + KEY_FEED;
-
- Cursor c = db.rawQuery(query, null);
- LongIntMap result = new LongIntMap(c.getCount());
- if (c.moveToFirst()) {
- do {
- long feedId = c.getLong(0);
- int count = c.getInt(1);
- result.put(feedId, count);
- } while (c.moveToNext());
- }
- c.close();
- return result;
- }
-
- public final LongIntMap getPlayedEpisodesCounters(long... feedIds) {
- String whereRead = KEY_READ + "=" + FeedItem.PLAYED;
- return conditionalFeedCounterRead(whereRead, feedIds);
- }
-
- public final Map<Long, Long> getMostRecentItemDates() {
- final String query = "SELECT " + KEY_FEED + ","
- + " MAX(" + TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + ") AS most_recent_pubdate"
- + " FROM " + TABLE_NAME_FEED_ITEMS
- + " GROUP BY " + KEY_FEED;
-
- Cursor c = db.rawQuery(query, null);
- Map<Long, Long> result = new HashMap<>();
- if (c.moveToFirst()) {
- do {
- long feedId = c.getLong(0);
- long date = c.getLong(1);
- result.put(feedId, date);
- } while (c.moveToNext());
- }
- c.close();
- return result;
- }
-
- public final int getNumberOfDownloadedEpisodes() {
- final String query = "SELECT COUNT(DISTINCT " + KEY_ID + ") AS count FROM " + TABLE_NAME_FEED_MEDIA +
- " WHERE " + KEY_DOWNLOADED + " > 0";
-
- Cursor c = db.rawQuery(query, null);
- int result = 0;
- if (c.moveToFirst()) {
- result = c.getInt(0);
- }
- c.close();
- return result;
- }
-
- /**
- * Uses DatabaseUtils to escape a search query and removes ' at the
- * beginning and the end of the string returned by the escape method.
- */
- private String[] prepareSearchQuery(String query) {
- String[] queryWords = query.split("\\s+");
- for (int i = 0; i < queryWords.length; ++i) {
- StringBuilder builder = new StringBuilder();
- DatabaseUtils.appendEscapedSQLString(builder, queryWords[i]);
- builder.deleteCharAt(0);
- builder.deleteCharAt(builder.length() - 1);
- queryWords[i] = builder.toString();
- }
-
- return queryWords;
- }
-
- /**
- * Searches for the given query in various values of all items or the items
- * of a specified feed.
- *
- * @return A cursor with all search results in SEL_FI_EXTRA selection.
- */
- public Cursor searchItems(long feedID, String searchQuery) {
- String[] queryWords = prepareSearchQuery(searchQuery);
-
- String queryFeedId;
- if (feedID != 0) {
- // search items in specific feed
- queryFeedId = KEY_FEED + " = " + feedID;
- } else {
- // search through all items
- queryFeedId = "1 = 1";
- }
-
- String queryStart = SELECT_FEED_ITEMS_AND_MEDIA_WITH_DESCRIPTION
- + " WHERE " + queryFeedId + " AND (";
- StringBuilder sb = new StringBuilder(queryStart);
-
- for (int i = 0; i < queryWords.length; i++) {
- sb
- .append("(")
- .append(KEY_DESCRIPTION + " LIKE '%").append(queryWords[i])
- .append("%' OR ")
- .append(KEY_TITLE).append(" LIKE '%").append(queryWords[i])
- .append("%') ");
-
- if (i != queryWords.length - 1) {
- sb.append("AND ");
- }
- }
-
- sb.append(") ORDER BY " + KEY_PUBDATE + " DESC LIMIT 300");
-
- return db.rawQuery(sb.toString(), null);
- }
-
- /**
- * Searches for the given query in various values of all feeds.
- *
- * @return A cursor with all search results in SEL_FI_EXTRA selection.
- */
- public Cursor searchFeeds(String searchQuery) {
- String[] queryWords = prepareSearchQuery(searchQuery);
-
- String queryStart = "SELECT * FROM " + TABLE_NAME_FEEDS + " WHERE ";
- StringBuilder sb = new StringBuilder(queryStart);
-
- for (int i = 0; i < queryWords.length; i++) {
- sb
- .append("(")
- .append(KEY_TITLE).append(" LIKE '%").append(queryWords[i])
- .append("%' OR ")
- .append(KEY_CUSTOM_TITLE).append(" LIKE '%").append(queryWords[i])
- .append("%' OR ")
- .append(KEY_AUTHOR).append(" LIKE '%").append(queryWords[i])
- .append("%' OR ")
- .append(KEY_DESCRIPTION).append(" LIKE '%").append(queryWords[i])
- .append("%') ");
-
- if (i != queryWords.length - 1) {
- sb.append("AND ");
- }
- }
-
- sb.append("ORDER BY " + KEY_TITLE + " ASC LIMIT 300");
-
- return db.rawQuery(sb.toString(), null);
- }
-
- /**
- * Insert raw data to the database.
- * Call method only for unit tests.
- */
- @VisibleForTesting(otherwise = VisibleForTesting.NONE)
- public void insertTestData(@NonNull String table, @NonNull ContentValues values) {
- db.insert(table, null, values);
- }
-
- /**
- * Called when a database corruption happens.
- */
- public static class PodDbErrorHandler implements DatabaseErrorHandler {
- @Override
- public void onCorruption(SQLiteDatabase db) {
- Log.e(TAG, "Database corrupted: " + db.getPath());
-
- File dbPath = new File(db.getPath());
- File backupFolder = PodDBAdapter.context.getExternalFilesDir(null);
- File backupFile = new File(backupFolder, "CorruptedDatabaseBackup.db");
- try {
- FileUtils.copyFile(dbPath, backupFile);
- Log.d(TAG, "Dumped database to " + backupFile.getPath());
- } catch (IOException e) {
- Log.d(TAG, Log.getStackTraceString(e));
- }
-
- new DefaultDatabaseErrorHandler().onCorruption(db); // This deletes the database
- }
- }
-
- /**
- * Helper class for opening the Antennapod database.
- */
- private static class PodDBHelper extends SQLiteOpenHelper {
- /**
- * Constructor.
- *
- * @param context Context to use
- * @param name Name of the database
- * @param factory to use for creating cursor objects
- */
- public PodDBHelper(final Context context, final String name, final CursorFactory factory) {
- super(context, name, factory, VERSION, new PodDbErrorHandler());
- }
-
- @Override
- public void onCreate(final SQLiteDatabase db) {
- db.execSQL(CREATE_TABLE_FEEDS);
- db.execSQL(CREATE_TABLE_FEED_ITEMS);
- db.execSQL(CREATE_TABLE_FEED_MEDIA);
- db.execSQL(CREATE_TABLE_DOWNLOAD_LOG);
- db.execSQL(CREATE_TABLE_QUEUE);
- db.execSQL(CREATE_TABLE_SIMPLECHAPTERS);
- db.execSQL(CREATE_TABLE_FAVORITES);
-
- db.execSQL(CREATE_INDEX_FEEDITEMS_FEED);
- db.execSQL(CREATE_INDEX_FEEDITEMS_PUBDATE);
- db.execSQL(CREATE_INDEX_FEEDITEMS_READ);
- db.execSQL(CREATE_INDEX_FEEDMEDIA_FEEDITEM);
- db.execSQL(CREATE_INDEX_QUEUE_FEEDITEM);
- db.execSQL(CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM);
- }
-
- @Override
- public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
- Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to " + newVersion + ".");
- DBUpgrader.upgrade(db, oldVersion, newVersion);
- }
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/ChapterCursorMapper.java b/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/ChapterCursorMapper.java
deleted file mode 100644
index 5fa376129..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/ChapterCursorMapper.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package de.danoeh.antennapod.core.storage.mapper;
-
-import android.database.Cursor;
-import androidx.annotation.NonNull;
-import de.danoeh.antennapod.model.feed.Chapter;
-import de.danoeh.antennapod.parser.feed.element.SimpleChapter;
-import de.danoeh.antennapod.core.storage.PodDBAdapter;
-import de.danoeh.antennapod.parser.media.id3.ID3Chapter;
-import de.danoeh.antennapod.parser.media.vorbis.VorbisCommentChapter;
-
-/**
- * Converts a {@link Cursor} to a {@link Chapter} object.
- */
-public abstract class ChapterCursorMapper {
- /**
- * Create a {@link Chapter} instance from a database row (cursor).
- */
- @NonNull
- public static Chapter convert(@NonNull Cursor cursor) {
- int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID);
- int indexTitle = cursor.getColumnIndex(PodDBAdapter.KEY_TITLE);
- int indexStart = cursor.getColumnIndex(PodDBAdapter.KEY_START);
- int indexLink = cursor.getColumnIndex(PodDBAdapter.KEY_LINK);
- int indexImage = cursor.getColumnIndex(PodDBAdapter.KEY_IMAGE_URL);
- int indexChapterType = cursor.getColumnIndex(PodDBAdapter.KEY_CHAPTER_TYPE);
-
- long id = cursor.getLong(indexId);
- String title = cursor.getString(indexTitle);
- long start = cursor.getLong(indexStart);
- String link = cursor.getString(indexLink);
- String imageUrl = cursor.getString(indexImage);
- int chapterType = cursor.getInt(indexChapterType);
-
- Chapter chapter;
- switch (chapterType) {
- case SimpleChapter.CHAPTERTYPE_SIMPLECHAPTER:
- chapter = new SimpleChapter(start, title, link, imageUrl);
- break;
- case ID3Chapter.CHAPTERTYPE_ID3CHAPTER:
- chapter = new ID3Chapter(start, title, link, imageUrl);
- break;
- case VorbisCommentChapter.CHAPTERTYPE_VORBISCOMMENT_CHAPTER:
- chapter = new VorbisCommentChapter(start, title, link, imageUrl);
- break;
- default:
- throw new IllegalArgumentException("Unknown chapter type");
- }
- chapter.setId(id);
- return chapter;
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/DownloadStatusCursorMapper.java b/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/DownloadStatusCursorMapper.java
deleted file mode 100644
index f8b57b819..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/DownloadStatusCursorMapper.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package de.danoeh.antennapod.core.storage.mapper;
-
-import android.database.Cursor;
-import androidx.annotation.NonNull;
-import de.danoeh.antennapod.core.service.download.DownloadStatus;
-import de.danoeh.antennapod.core.storage.PodDBAdapter;
-import de.danoeh.antennapod.core.util.DownloadError;
-
-import java.util.Date;
-
-/**
- * Converts a {@link Cursor} to a {@link DownloadStatus} object.
- */
-public abstract class DownloadStatusCursorMapper {
- /**
- * Create a {@link DownloadStatus} instance from a database row (cursor).
- */
- @NonNull
- public static DownloadStatus convert(@NonNull Cursor cursor) {
- int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID);
- int indexTitle = cursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOADSTATUS_TITLE);
- int indexFeedFile = cursor.getColumnIndex(PodDBAdapter.KEY_FEEDFILE);
- int indexFileFileType = cursor.getColumnIndex(PodDBAdapter.KEY_FEEDFILETYPE);
- int indexSuccessful = cursor.getColumnIndex(PodDBAdapter.KEY_SUCCESSFUL);
- int indexReason = cursor.getColumnIndex(PodDBAdapter.KEY_REASON);
- int indexCompletionDate = cursor.getColumnIndex(PodDBAdapter.KEY_COMPLETION_DATE);
- int indexReasonDetailed = cursor.getColumnIndex(PodDBAdapter.KEY_REASON_DETAILED);
-
- return new DownloadStatus(cursor.getLong(indexId), cursor.getString(indexTitle), cursor.getLong(indexFeedFile),
- cursor.getInt(indexFileFileType), cursor.getInt(indexSuccessful) > 0, false, true,
- DownloadError.fromCode(cursor.getInt(indexReason)),
- new Date(cursor.getLong(indexCompletionDate)),
- cursor.getString(indexReasonDetailed), false);
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedCursorMapper.java b/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedCursorMapper.java
deleted file mode 100644
index a2a180735..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedCursorMapper.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package de.danoeh.antennapod.core.storage.mapper;
-
-import android.database.Cursor;
-
-import androidx.annotation.NonNull;
-
-import de.danoeh.antennapod.model.feed.Feed;
-import de.danoeh.antennapod.model.feed.FeedPreferences;
-import de.danoeh.antennapod.core.storage.PodDBAdapter;
-import de.danoeh.antennapod.model.feed.SortOrder;
-
-/**
- * Converts a {@link Cursor} to a {@link Feed} object.
- */
-public abstract class FeedCursorMapper {
-
- /**
- * Create a {@link Feed} instance from a database row (cursor).
- */
- @NonNull
- public static Feed convert(@NonNull Cursor cursor) {
- int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID);
- int indexLastUpdate = cursor.getColumnIndex(PodDBAdapter.KEY_LASTUPDATE);
- int indexTitle = cursor.getColumnIndex(PodDBAdapter.KEY_TITLE);
- int indexCustomTitle = cursor.getColumnIndex(PodDBAdapter.KEY_CUSTOM_TITLE);
- int indexLink = cursor.getColumnIndex(PodDBAdapter.KEY_LINK);
- int indexDescription = cursor.getColumnIndex(PodDBAdapter.KEY_DESCRIPTION);
- int indexPaymentLink = cursor.getColumnIndex(PodDBAdapter.KEY_PAYMENT_LINK);
- int indexAuthor = cursor.getColumnIndex(PodDBAdapter.KEY_AUTHOR);
- int indexLanguage = cursor.getColumnIndex(PodDBAdapter.KEY_LANGUAGE);
- int indexType = cursor.getColumnIndex(PodDBAdapter.KEY_TYPE);
- int indexFeedIdentifier = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_IDENTIFIER);
- int indexFileUrl = cursor.getColumnIndex(PodDBAdapter.KEY_FILE_URL);
- int indexDownloadUrl = cursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOAD_URL);
- int indexDownloaded = cursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOADED);
- int indexIsPaged = cursor.getColumnIndex(PodDBAdapter.KEY_IS_PAGED);
- int indexNextPageLink = cursor.getColumnIndex(PodDBAdapter.KEY_NEXT_PAGE_LINK);
- int indexHide = cursor.getColumnIndex(PodDBAdapter.KEY_HIDE);
- int indexSortOrder = cursor.getColumnIndex(PodDBAdapter.KEY_SORT_ORDER);
- int indexLastUpdateFailed = cursor.getColumnIndex(PodDBAdapter.KEY_LAST_UPDATE_FAILED);
- int indexImageUrl = cursor.getColumnIndex(PodDBAdapter.KEY_IMAGE_URL);
-
- Feed feed = new Feed(
- cursor.getLong(indexId),
- cursor.getString(indexLastUpdate),
- cursor.getString(indexTitle),
- cursor.getString(indexCustomTitle),
- cursor.getString(indexLink),
- cursor.getString(indexDescription),
- cursor.getString(indexPaymentLink),
- cursor.getString(indexAuthor),
- cursor.getString(indexLanguage),
- cursor.getString(indexType),
- cursor.getString(indexFeedIdentifier),
- cursor.getString(indexImageUrl),
- cursor.getString(indexFileUrl),
- cursor.getString(indexDownloadUrl),
- cursor.getInt(indexDownloaded) > 0,
- cursor.getInt(indexIsPaged) > 0,
- cursor.getString(indexNextPageLink),
- cursor.getString(indexHide),
- SortOrder.fromCodeString(cursor.getString(indexSortOrder)),
- cursor.getInt(indexLastUpdateFailed) > 0
- );
-
- FeedPreferences preferences = FeedPreferencesCursorMapper.convert(cursor);
- feed.setPreferences(preferences);
- return feed;
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedItemCursorMapper.java b/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedItemCursorMapper.java
deleted file mode 100644
index ca0834339..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedItemCursorMapper.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package de.danoeh.antennapod.core.storage.mapper;
-
-import android.database.Cursor;
-import androidx.annotation.NonNull;
-import de.danoeh.antennapod.model.feed.FeedItem;
-import de.danoeh.antennapod.core.storage.PodDBAdapter;
-
-import java.util.Date;
-
-/**
- * Converts a {@link Cursor} to a {@link FeedItem} object.
- */
-public abstract class FeedItemCursorMapper {
- /**
- * Create a {@link FeedItem} instance from a database row (cursor).
- */
- @NonNull
- public static FeedItem convert(@NonNull Cursor cursor) {
- int indexId = cursor.getColumnIndexOrThrow(PodDBAdapter.SELECT_KEY_ITEM_ID);
- int indexTitle = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_TITLE);
- int indexLink = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_LINK);
- int indexPubDate = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_PUBDATE);
- int indexPaymentLink = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_PAYMENT_LINK);
- int indexFeedId = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_FEED);
- int indexHasChapters = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_HAS_CHAPTERS);
- int indexRead = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_READ);
- int indexItemIdentifier = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_ITEM_IDENTIFIER);
- int indexAutoDownload = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_AUTO_DOWNLOAD_ATTEMPTS);
- int indexImageUrl = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_IMAGE_URL);
-
- long id = cursor.getInt(indexId);
- String title = cursor.getString(indexTitle);
- String link = cursor.getString(indexLink);
- Date pubDate = new Date(cursor.getLong(indexPubDate));
- String paymentLink = cursor.getString(indexPaymentLink);
- long feedId = cursor.getLong(indexFeedId);
- boolean hasChapters = cursor.getInt(indexHasChapters) > 0;
- int state = cursor.getInt(indexRead);
- String itemIdentifier = cursor.getString(indexItemIdentifier);
- long autoDownload = cursor.getLong(indexAutoDownload);
- String imageUrl = cursor.getString(indexImageUrl);
-
- return new FeedItem(id, title, link, pubDate, paymentLink, feedId,
- hasChapters, imageUrl, state, itemIdentifier, autoDownload);
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedItemFilterQuery.java b/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedItemFilterQuery.java
deleted file mode 100644
index 1d9c8a9e6..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedItemFilterQuery.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package de.danoeh.antennapod.core.storage.mapper;
-
-import de.danoeh.antennapod.model.feed.FeedItemFilter;
-import de.danoeh.antennapod.core.storage.PodDBAdapter;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class FeedItemFilterQuery {
- private FeedItemFilterQuery() {
- // Must not be instantiated
- }
-
- /**
- * Express the filter using an SQL boolean statement that can be inserted into an SQL WHERE clause
- * to yield output filtered according to the rules of this filter.
- *
- * @return An SQL boolean statement that matches the desired items,
- * empty string if there is nothing to filter
- */
- public static String generateFrom(FeedItemFilter filter) {
- // The keys used within this method, but explicitly combined with their table
- String keyRead = PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_READ;
- String keyPosition = PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_POSITION;
- String keyDownloaded = PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_DOWNLOADED;
- String keyMediaId = PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + PodDBAdapter.KEY_ID;
- String keyItemId = PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + PodDBAdapter.KEY_ID;
- String keyFeedItem = PodDBAdapter.KEY_FEEDITEM;
- String tableQueue = PodDBAdapter.TABLE_NAME_QUEUE;
- String tableFavorites = PodDBAdapter.TABLE_NAME_FAVORITES;
-
- List<String> statements = new ArrayList<>();
- if (filter.showPlayed) {
- statements.add(keyRead + " = 1 ");
- } else if (filter.showUnplayed) {
- statements.add(" NOT " + keyRead + " = 1 "); // Match "New" items (read = -1) as well
- }
- if (filter.showPaused) {
- statements.add(" (" + keyPosition + " NOT NULL AND " + keyPosition + " > 0 " + ") ");
- } else if (filter.showNotPaused) {
- statements.add(" (" + keyPosition + " IS NULL OR " + keyPosition + " = 0 " + ") ");
- }
- if (filter.showQueued) {
- statements.add(keyItemId + " IN (SELECT " + keyFeedItem + " FROM " + tableQueue + ") ");
- } else if (filter.showNotQueued) {
- statements.add(keyItemId + " NOT IN (SELECT " + keyFeedItem + " FROM " + tableQueue + ") ");
- }
- if (filter.showDownloaded) {
- statements.add(keyDownloaded + " = 1 ");
- } else if (filter.showNotDownloaded) {
- statements.add(keyDownloaded + " = 0 ");
- }
- if (filter.showHasMedia) {
- statements.add(keyMediaId + " NOT NULL ");
- } else if (filter.showNoMedia) {
- statements.add(keyMediaId + " IS NULL ");
- }
- if (filter.showIsFavorite) {
- statements.add(keyItemId + " IN (SELECT " + keyFeedItem + " FROM " + tableFavorites + ") ");
- } else if (filter.showNotFavorite) {
- statements.add(keyItemId + " NOT IN (SELECT " + keyFeedItem + " FROM " + tableFavorites + ") ");
- }
-
- if (statements.isEmpty()) {
- return "";
- }
-
- StringBuilder query = new StringBuilder(" (" + statements.get(0));
- for (String r : statements.subList(1, statements.size())) {
- query.append(" AND ");
- query.append(r);
- }
- query.append(") ");
- return query.toString();
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedMediaCursorMapper.java b/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedMediaCursorMapper.java
deleted file mode 100644
index 0dc3dc231..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedMediaCursorMapper.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package de.danoeh.antennapod.core.storage.mapper;
-
-import android.database.Cursor;
-import androidx.annotation.NonNull;
-import de.danoeh.antennapod.model.feed.FeedMedia;
-import de.danoeh.antennapod.core.storage.PodDBAdapter;
-
-import java.util.Date;
-
-/**
- * Converts a {@link Cursor} to a {@link FeedMedia} object.
- */
-public abstract class FeedMediaCursorMapper {
- /**
- * Create a {@link FeedMedia} instance from a database row (cursor).
- */
- @NonNull
- public static FeedMedia convert(@NonNull Cursor cursor) {
- int indexId = cursor.getColumnIndexOrThrow(PodDBAdapter.SELECT_KEY_MEDIA_ID);
- int indexPlaybackCompletionDate = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_PLAYBACK_COMPLETION_DATE);
- int indexDuration = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_DURATION);
- int indexPosition = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_POSITION);
- int indexSize = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_SIZE);
- int indexMimeType = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_MIME_TYPE);
- int indexFileUrl = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_FILE_URL);
- int indexDownloadUrl = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_DOWNLOAD_URL);
- int indexDownloaded = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_DOWNLOADED);
- int indexPlayedDuration = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_PLAYED_DURATION);
- int indexLastPlayedTime = cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_LAST_PLAYED_TIME);
-
- long mediaId = cursor.getLong(indexId);
- Date playbackCompletionDate = null;
- long playbackCompletionTime = cursor.getLong(indexPlaybackCompletionDate);
- if (playbackCompletionTime > 0) {
- playbackCompletionDate = new Date(playbackCompletionTime);
- }
-
- Boolean hasEmbeddedPicture;
- switch (cursor.getInt(cursor.getColumnIndexOrThrow(PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE))) {
- case 1:
- hasEmbeddedPicture = Boolean.TRUE;
- break;
- case 0:
- hasEmbeddedPicture = Boolean.FALSE;
- break;
- default:
- hasEmbeddedPicture = null;
- break;
- }
-
- return new FeedMedia(
- mediaId,
- null,
- cursor.getInt(indexDuration),
- cursor.getInt(indexPosition),
- cursor.getLong(indexSize),
- cursor.getString(indexMimeType),
- cursor.getString(indexFileUrl),
- cursor.getString(indexDownloadUrl),
- cursor.getInt(indexDownloaded) > 0,
- playbackCompletionDate,
- cursor.getInt(indexPlayedDuration),
- hasEmbeddedPicture,
- cursor.getLong(indexLastPlayedTime)
- );
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedPreferencesCursorMapper.java b/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedPreferencesCursorMapper.java
deleted file mode 100644
index f062609b6..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/mapper/FeedPreferencesCursorMapper.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package de.danoeh.antennapod.core.storage.mapper;
-
-import android.database.Cursor;
-import android.text.TextUtils;
-import androidx.annotation.NonNull;
-import de.danoeh.antennapod.model.feed.FeedFilter;
-import de.danoeh.antennapod.model.feed.FeedPreferences;
-import de.danoeh.antennapod.model.feed.VolumeAdaptionSetting;
-import de.danoeh.antennapod.core.storage.PodDBAdapter;
-
-import java.util.Arrays;
-import java.util.HashSet;
-
-/**
- * Converts a {@link Cursor} to a {@link FeedPreferences} object.
- */
-public abstract class FeedPreferencesCursorMapper {
- /**
- * Create a {@link FeedPreferences} instance from a database row (cursor).
- */
- @NonNull
- public static FeedPreferences convert(@NonNull Cursor cursor) {
- int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID);
- int indexAutoDownload = cursor.getColumnIndex(PodDBAdapter.KEY_AUTO_DOWNLOAD_ENABLED);
- int indexAutoRefresh = cursor.getColumnIndex(PodDBAdapter.KEY_KEEP_UPDATED);
- int indexAutoDeleteAction = cursor.getColumnIndex(PodDBAdapter.KEY_AUTO_DELETE_ACTION);
- int indexVolumeAdaption = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_VOLUME_ADAPTION);
- int indexUsername = cursor.getColumnIndex(PodDBAdapter.KEY_USERNAME);
- int indexPassword = cursor.getColumnIndex(PodDBAdapter.KEY_PASSWORD);
- int indexIncludeFilter = cursor.getColumnIndex(PodDBAdapter.KEY_INCLUDE_FILTER);
- int indexExcludeFilter = cursor.getColumnIndex(PodDBAdapter.KEY_EXCLUDE_FILTER);
- int indexMinimalDurationFilter = cursor.getColumnIndex(PodDBAdapter.KEY_MINIMAL_DURATION_FILTER);
- int indexFeedPlaybackSpeed = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_PLAYBACK_SPEED);
- int indexAutoSkipIntro = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_SKIP_INTRO);
- int indexAutoSkipEnding = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_SKIP_ENDING);
- int indexEpisodeNotification = cursor.getColumnIndex(PodDBAdapter.KEY_EPISODE_NOTIFICATION);
- int indexTags = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_TAGS);
-
- long feedId = cursor.getLong(indexId);
- boolean autoDownload = cursor.getInt(indexAutoDownload) > 0;
- boolean autoRefresh = cursor.getInt(indexAutoRefresh) > 0;
- int autoDeleteActionIndex = cursor.getInt(indexAutoDeleteAction);
- FeedPreferences.AutoDeleteAction autoDeleteAction =
- FeedPreferences.AutoDeleteAction.values()[autoDeleteActionIndex];
- int volumeAdaptionValue = cursor.getInt(indexVolumeAdaption);
- VolumeAdaptionSetting volumeAdaptionSetting = VolumeAdaptionSetting.fromInteger(volumeAdaptionValue);
- String username = cursor.getString(indexUsername);
- String password = cursor.getString(indexPassword);
- String includeFilter = cursor.getString(indexIncludeFilter);
- String excludeFilter = cursor.getString(indexExcludeFilter);
- int minimalDurationFilter = cursor.getInt(indexMinimalDurationFilter);
- float feedPlaybackSpeed = cursor.getFloat(indexFeedPlaybackSpeed);
- int feedAutoSkipIntro = cursor.getInt(indexAutoSkipIntro);
- int feedAutoSkipEnding = cursor.getInt(indexAutoSkipEnding);
- boolean showNotification = cursor.getInt(indexEpisodeNotification) > 0;
- String tagsString = cursor.getString(indexTags);
- if (TextUtils.isEmpty(tagsString)) {
- tagsString = FeedPreferences.TAG_ROOT;
- }
- return new FeedPreferences(feedId,
- autoDownload,
- autoRefresh,
- autoDeleteAction,
- volumeAdaptionSetting,
- username,
- password,
- new FeedFilter(includeFilter, excludeFilter, minimalDurationFilter),
- feedPlaybackSpeed,
- feedAutoSkipIntro,
- feedAutoSkipEnding,
- showNotification,
- new HashSet<>(Arrays.asList(tagsString.split(FeedPreferences.TAG_SEPARATOR))));
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DownloadError.java b/core/src/main/java/de/danoeh/antennapod/core/util/DownloadError.java
deleted file mode 100644
index 06ec8396f..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/util/DownloadError.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package de.danoeh.antennapod.core.util;
-
-/** Utility class for Download Errors. */
-public enum DownloadError {
- SUCCESS(0),
- ERROR_PARSER_EXCEPTION(1),
- ERROR_UNSUPPORTED_TYPE(2),
- ERROR_CONNECTION_ERROR(3),
- ERROR_MALFORMED_URL(4),
- ERROR_IO_ERROR(5),
- ERROR_FILE_EXISTS(6),
- ERROR_DOWNLOAD_CANCELLED(7),
- ERROR_DEVICE_NOT_FOUND(8),
- ERROR_HTTP_DATA_ERROR(9),
- ERROR_NOT_ENOUGH_SPACE(10),
- ERROR_UNKNOWN_HOST(11),
- ERROR_REQUEST_ERROR(12),
- ERROR_DB_ACCESS_ERROR(13),
- ERROR_UNAUTHORIZED(14),
- ERROR_FILE_TYPE(15),
- ERROR_FORBIDDEN(16),
- ERROR_IO_WRONG_SIZE(17),
- ERROR_IO_BLOCKED(18),
- ERROR_UNSUPPORTED_TYPE_HTML(19),
- ERROR_NOT_FOUND(20),
- ERROR_CERTIFICATE(21),
- ERROR_PARSER_EXCEPTION_DUPLICATE(22);
-
- private final int code;
-
- DownloadError(int code) {
- this.code = code;
- }
-
- /** Return DownloadError from its associated code. */
- public static DownloadError fromCode(int code) {
- for (DownloadError reason : values()) {
- if (reason.getCode() == code) {
- return reason;
- }
- }
- throw new IllegalArgumentException("unknown code: " + code);
- }
-
- /** Get machine-readable code. */
- public int getCode() {
- return code;
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DownloadErrorLabel.java b/core/src/main/java/de/danoeh/antennapod/core/util/DownloadErrorLabel.java
index 8834350d1..3d2558a9f 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/DownloadErrorLabel.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/DownloadErrorLabel.java
@@ -3,6 +3,7 @@ package de.danoeh.antennapod.core.util;
import androidx.annotation.StringRes;
import de.danoeh.antennapod.core.BuildConfig;
import de.danoeh.antennapod.core.R;
+import de.danoeh.antennapod.model.download.DownloadError;
/**
* Provides user-visible labels for download errors.
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/LongIntMap.java b/core/src/main/java/de/danoeh/antennapod/core/util/LongIntMap.java
deleted file mode 100644
index 78ed002ac..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/util/LongIntMap.java
+++ /dev/null
@@ -1,263 +0,0 @@
-package de.danoeh.antennapod.core.util;
-
-
-import java.util.Arrays;
-
-/**
- * Fast and memory efficient long to long map
- */
-public class LongIntMap {
-
- private long[] keys;
- private int[] values;
- private int size;
-
- /**
- * Creates a new LongLongMap containing no mappings.
- */
- public LongIntMap() {
- this(10);
- }
-
- /**
- * Creates a new SparseLongArray containing no mappings that will not
- * require any additional memory allocation to store the specified
- * number of mappings. If you supply an initial capacity of 0, the
- * sparse array will be initialized with a light-weight representation
- * not requiring any additional array allocations.
- */
- public LongIntMap(int initialCapacity) {
- if(initialCapacity < 0) {
- throw new IllegalArgumentException("initial capacity must be 0 or higher");
- }
- keys = new long[initialCapacity];
- values = new int[initialCapacity];
- size = 0;
- }
-
- /**
- * Increases size of array if needed
- */
- private void growIfNeeded() {
- if (size == keys.length) {
- // Resize.
- long[] newKeysArray = new long[size * 3 / 2 + 10];
- int[] newValuesArray = new int[size * 3 / 2 + 10];
- System.arraycopy(keys, 0, newKeysArray, 0, size);
- System.arraycopy(values, 0, newValuesArray, 0, size);
- keys = newKeysArray;
- values = newValuesArray;
- }
- }
-
- /**
- * Gets the long mapped from the specified key, or <code>0</code>
- * if no such mapping has been made.
- */
- public int get(long key) {
- return get(key, 0);
- }
-
- /**
- * Gets the long mapped from the specified key, or the specified value
- * if no such mapping has been made.
- */
- public int get(long key, int valueIfKeyNotFound) {
- int index = indexOfKey(key);
- if(index >= 0) {
- return values[index];
- } else {
- return valueIfKeyNotFound;
- }
- }
-
- /**
- * Removes the mapping from the specified key, if there was any.
- */
- public boolean delete(long key) {
- int index = indexOfKey(key);
-
- if (index >= 0) {
- removeAt(index);
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Removes the mapping at the given index.
- */
- private void removeAt(int index) {
- System.arraycopy(keys, index + 1, keys, index, size - (index + 1));
- System.arraycopy(values, index + 1, values, index, size - (index + 1));
- size--;
- }
-
- /**
- * Adds a mapping from the specified key to the specified value,
- * replacing the previous mapping from the specified key if there
- * was one.
- */
- public void put(long key, int value) {
- int index = indexOfKey(key);
-
- if (index >= 0) {
- values[index] = value;
- } else {
- growIfNeeded();
- keys[size] = key;
- values[size] = value;
- size++;
- }
- }
-
- /**
- * Returns the number of key-value mappings that this SparseIntArray
- * currently stores.
- */
- public int size() {
- return size;
- }
-
- /**
- * Given an index in the range <code>0...size()-1</code>, returns
- * the key from the <code>index</code>th key-value mapping that this
- * SparseLongArray stores.
- *
- * <p>The keys corresponding to indices in ascending order are guaranteed to
- * be in ascending order, e.g., <code>keyAt(0)</code> will return the
- * smallest key and <code>keyAt(size()-1)</code> will return the largest
- * key.</p>
- */
- private long keyAt(int index) {
- if (index >= size) {
- throw new IndexOutOfBoundsException("n >= size()");
- } else if(index < 0) {
- throw new IndexOutOfBoundsException("n < 0");
- }
- return keys[index];
- }
-
- /**
- * Given an index in the range <code>0...size()-1</code>, returns
- * the value from the <code>index</code>th key-value mapping that this
- * SparseLongArray stores.
- *
- * <p>The values corresponding to indices in ascending order are guaranteed
- * to be associated with keys in ascending order, e.g.,
- * <code>valueAt(0)</code> will return the value associated with the
- * smallest key and <code>valueAt(size()-1)</code> will return the value
- * associated with the largest key.</p>
- */
- private int valueAt(int index) {
- if (index >= size) {
- throw new IndexOutOfBoundsException("n >= size()");
- } else if(index < 0) {
- throw new IndexOutOfBoundsException("n < 0");
- }
- return values[index];
- }
-
- /**
- * Returns the index for which {@link #keyAt} would return the
- * specified key, or a negative number if the specified
- * key is not mapped.
- */
- public int indexOfKey(long key) {
- for(int i=0; i < size; i++) {
- if(keys[i] == key) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Returns an index for which {@link #valueAt} would return the
- * specified key, or a negative number if no keys map to the
- * specified value.
- * Beware that this is a linear search, unlike lookups by key,
- * and that multiple keys can map to the same value and this will
- * find only one of them.
- */
- public int indexOfValue(long value) {
- for (int i = 0; i < size; i++) {
- if (values[i] == value) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Removes all key-value mappings from this SparseIntArray.
- */
- public void clear() {
- keys = new long[10];
- values = new int[10];
- size = 0;
- }
-
- /**
- * Returns a copy of the values contained in this map.
- *
- * @return a copy of the values contained in this map
- */
- public int[] values() {
- return Arrays.copyOf(values, size);
- }
-
- @Override
- public boolean equals(Object other) {
- if (other == this) {
- return true;
- }
- if (! (other instanceof LongIntMap)) {
- return false;
- }
- LongIntMap otherMap = (LongIntMap) other;
- if (size != otherMap.size) {
- return false;
- }
- for (int i = 0; i < size; i++) {
- if (keys[i] != otherMap.keys[i] ||
- values[i] != otherMap.values[i]) {
- return false;
- }
- }
- return true;
- }
-
- @Override
- public int hashCode() {
- int hashCode = 1;
- for (int i = 0; i < size; i++) {
- long value = values[i];
- hashCode = 31 * hashCode + (int)(value ^ (value >>> 32));
- }
- return hashCode;
- }
-
- @Override
- public String toString() {
- if (size() <= 0) {
- return "LongLongMap{}";
- }
-
- StringBuilder buffer = new StringBuilder(size * 28);
- buffer.append("LongLongMap{");
- for (int i=0; i < size; i++) {
- if (i > 0) {
- buffer.append(", ");
- }
- long key = keyAt(i);
- buffer.append(key);
- buffer.append('=');
- long value = valueAt(i);
- buffer.append(value);
- }
- buffer.append('}');
- return buffer.toString();
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/DownloadStatusComparator.java b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/DownloadStatusComparator.java
index 868f3b835..68b38ec7f 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/DownloadStatusComparator.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/DownloadStatusComparator.java
@@ -2,7 +2,7 @@ package de.danoeh.antennapod.core.util.comparator;
import java.util.Comparator;
-import de.danoeh.antennapod.core.service.download.DownloadStatus;
+import de.danoeh.antennapod.model.download.DownloadStatus;
/** Compares the completion date of two Downloadstatus objects. */
public class DownloadStatusComparator implements Comparator<DownloadStatus> {
diff --git a/core/src/test/java/de/danoeh/antennapod/core/feed/LocalFeedUpdaterTest.java b/core/src/test/java/de/danoeh/antennapod/core/feed/LocalFeedUpdaterTest.java
index 37d525670..bafee7293 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/feed/LocalFeedUpdaterTest.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/feed/LocalFeedUpdaterTest.java
@@ -14,6 +14,7 @@ import androidx.test.platform.app.InstrumentationRegistry;
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedItem;
+import de.danoeh.antennapod.storage.database.PodDBAdapter;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -34,7 +35,6 @@ import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
-import de.danoeh.antennapod.core.storage.PodDBAdapter;
import static org.hamcrest.CoreMatchers.endsWith;
import static org.hamcrest.CoreMatchers.is;
diff --git a/core/src/test/java/de/danoeh/antennapod/core/storage/DbCleanupTests.java b/core/src/test/java/de/danoeh/antennapod/core/storage/DbCleanupTests.java
index b5c2e5c73..5aa670736 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/storage/DbCleanupTests.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/storage/DbCleanupTests.java
@@ -21,6 +21,7 @@ import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.storage.database.PodDBAdapter;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/core/src/test/java/de/danoeh/antennapod/core/storage/DbNullCleanupAlgorithmTest.java b/core/src/test/java/de/danoeh/antennapod/core/storage/DbNullCleanupAlgorithmTest.java
index 6485c9515..09a2580b1 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/storage/DbNullCleanupAlgorithmTest.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/storage/DbNullCleanupAlgorithmTest.java
@@ -15,6 +15,7 @@ import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.storage.database.PodDBAdapter;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/core/src/test/java/de/danoeh/antennapod/core/storage/DbReaderTest.java b/core/src/test/java/de/danoeh/antennapod/core/storage/DbReaderTest.java
index c9be06afd..834442fdd 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/storage/DbReaderTest.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/storage/DbReaderTest.java
@@ -13,6 +13,7 @@ import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.util.LongList;
+import de.danoeh.antennapod.storage.database.PodDBAdapter;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/core/src/test/java/de/danoeh/antennapod/core/storage/DbTasksTest.java b/core/src/test/java/de/danoeh/antennapod/core/storage/DbTasksTest.java
index 0d98ba294..0779c6ae3 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/storage/DbTasksTest.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/storage/DbTasksTest.java
@@ -5,6 +5,7 @@ import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
+import de.danoeh.antennapod.storage.database.PodDBAdapter;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/core/src/test/java/de/danoeh/antennapod/core/storage/DbTestUtils.java b/core/src/test/java/de/danoeh/antennapod/core/storage/DbTestUtils.java
index 413243d1d..3a3213a37 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/storage/DbTestUtils.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/storage/DbTestUtils.java
@@ -9,8 +9,8 @@ import de.danoeh.antennapod.model.feed.Chapter;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
-import de.danoeh.antennapod.parser.feed.element.SimpleChapter;
import de.danoeh.antennapod.core.util.comparator.FeedItemPubdateComparator;
+import de.danoeh.antennapod.storage.database.PodDBAdapter;
import static org.junit.Assert.assertTrue;
@@ -56,7 +56,7 @@ abstract class DbTestUtils {
List<Chapter> chapters = new ArrayList<>();
item.setChapters(chapters);
for (int k = 0; k < numChapters; k++) {
- chapters.add(new SimpleChapter(k, "item " + j + " chapter " + k,
+ chapters.add(new Chapter(k, "item " + j + " chapter " + k,
"http://example.com", "http://example.com/image.png"));
}
}
diff --git a/core/src/test/java/de/danoeh/antennapod/core/storage/DbWriterTest.java b/core/src/test/java/de/danoeh/antennapod/core/storage/DbWriterTest.java
index 5e73773db..de1e78408 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/storage/DbWriterTest.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/storage/DbWriterTest.java
@@ -10,6 +10,7 @@ import androidx.core.util.Consumer;
import androidx.preference.PreferenceManager;
import androidx.test.platform.app.InstrumentationRegistry;
+import de.danoeh.antennapod.storage.database.PodDBAdapter;
import org.awaitility.Awaitility;
import org.junit.After;
import org.junit.Before;
diff --git a/core/src/test/java/de/danoeh/antennapod/core/storage/mapper/FeedCursorMapperTest.java b/core/src/test/java/de/danoeh/antennapod/core/storage/mapper/FeedCursorMapperTest.java
index 8695f98b1..486aa82a8 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/storage/mapper/FeedCursorMapperTest.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/storage/mapper/FeedCursorMapperTest.java
@@ -6,6 +6,8 @@ import android.database.Cursor;
import androidx.test.platform.app.InstrumentationRegistry;
+import de.danoeh.antennapod.storage.database.PodDBAdapter;
+import de.danoeh.antennapod.storage.database.mapper.FeedCursorMapper;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -13,7 +15,6 @@ import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import de.danoeh.antennapod.model.feed.Feed;
-import de.danoeh.antennapod.core.storage.PodDBAdapter;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
diff --git a/core/src/test/java/de/danoeh/antennapod/core/util/LongLongMapTest.java b/core/src/test/java/de/danoeh/antennapod/core/util/LongLongMapTest.java
index 21df71bec..03326d3b1 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/util/LongLongMapTest.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/util/LongLongMapTest.java
@@ -1,5 +1,6 @@
package de.danoeh.antennapod.core.util;
+import de.danoeh.antennapod.storage.database.LongIntMap;
import org.junit.Test;
import static org.junit.Assert.assertEquals;