summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/build.gradle14
-rw-r--r--core/src/androidTest/java/de/danoeh/antennapod/core/AntennaPodTestRunner.java (renamed from core/src/androidTest/java/de/danoeh/antennapod/core/tests/AntennaPodTestRunner.java)2
-rw-r--r--core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedImageMother.java9
-rw-r--r--core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/service/download/DownloadServiceTest.java35
-rw-r--r--core/src/androidTest/java/de/danoeh/antennapod/core/util/DateUtilsTest.java (renamed from core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java)24
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/UpdateManager.java24
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java35
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java92
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java48
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java29
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java10
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java84
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java292
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java37
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java420
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java16
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java18
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java22
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java7
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java13
-rw-r--r--core/src/main/res/drawable/progress_bar_horizontal_trueblack.xml15
-rw-r--r--core/src/main/res/values-v21/styles.xml13
-rw-r--r--core/src/main/res/values/arrays.xml2
-rw-r--r--core/src/main/res/values/attrs.xml1
-rw-r--r--core/src/main/res/values/colors.xml2
-rw-r--r--core/src/main/res/values/strings.xml1
-rw-r--r--core/src/main/res/values/styles.xml52
-rw-r--r--core/src/play/java/de/danoeh/antennapod/core/cast/CastUtils.java7
-rw-r--r--core/src/test/java/android/text/TextUtils.java32
-rw-r--r--core/src/test/java/android/util/Log.java245
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/feed/FeedItemMother.java (renamed from core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedItemMother.java)4
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/feed/FeedItemTest.java (renamed from core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedItemTest.java)47
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/feed/FeedMother.java (renamed from core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedMother.java)6
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/feed/FeedTest.java (renamed from core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedTest.java)42
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/util/LongLongMapTest.java (renamed from core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/LongLongMapTest.java)12
36 files changed, 849 insertions, 867 deletions
diff --git a/core/build.gradle b/core/build.gradle
index 691d8749a..4998b3853 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -10,7 +10,7 @@ android {
versionCode 1
versionName "1.0"
testApplicationId "de.danoeh.antennapod.core.tests"
- testInstrumentationRunner "de.danoeh.antennapod.core.tests.AntennaPodTestRunner"
+ testInstrumentationRunner "de.danoeh.antennapod.core.AntennaPodTestRunner"
}
buildTypes {
release {
@@ -80,6 +80,18 @@ dependencies {
} else {
System.out.println("core: free build hack, skipping some dependencies")
}
+
+ testImplementation 'junit:junit:4.12'
+
+}
+
+tasks.withType(Test) {
+ testLogging {
+ exceptionFormat "full"
+ events "skipped", "passed", "failed"
+ showStandardStreams true
+ displayGranularity 2
+ }
}
allprojects {
diff --git a/core/src/androidTest/java/de/danoeh/antennapod/core/tests/AntennaPodTestRunner.java b/core/src/androidTest/java/de/danoeh/antennapod/core/AntennaPodTestRunner.java
index 78e854b41..5d086c054 100644
--- a/core/src/androidTest/java/de/danoeh/antennapod/core/tests/AntennaPodTestRunner.java
+++ b/core/src/androidTest/java/de/danoeh/antennapod/core/AntennaPodTestRunner.java
@@ -1,4 +1,4 @@
-package de.danoeh.antennapod.core.tests;
+package de.danoeh.antennapod.core;
import android.test.InstrumentationTestRunner;
import android.test.suitebuilder.TestSuiteBuilder;
diff --git a/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedImageMother.java b/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedImageMother.java
deleted file mode 100644
index 0fb4992ba..000000000
--- a/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedImageMother.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package de.danoeh.antennapod.core.feed;
-
-class FeedImageMother {
-
- public static FeedImage anyFeedImage() {
- return new FeedImage(0, "image", null, "http://example.com/picture", false);
- }
-
-}
diff --git a/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/service/download/DownloadServiceTest.java b/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/service/download/DownloadServiceTest.java
deleted file mode 100644
index 94cfb3278..000000000
--- a/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/service/download/DownloadServiceTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package de.danoeh.antennapod.core.tests.util.service.download;
-
-import android.test.AndroidTestCase;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import de.danoeh.antennapod.core.feed.Feed;
-import de.danoeh.antennapod.core.feed.FeedImage;
-import de.danoeh.antennapod.core.feed.FeedItem;
-import de.danoeh.antennapod.core.service.download.DownloadService;
-
-public class DownloadServiceTest extends AndroidTestCase {
-
- public void testRemoveDuplicateImages() {
- List<FeedItem> items = new ArrayList<>();
- for (int i = 0; i < 50; i++) {
- FeedItem item = new FeedItem();
- String url = (i % 5 == 0) ? "dupe_url" : String.format("url_%d", i);
- item.setImage(new FeedImage(null, url, ""));
- items.add(item);
- }
- Feed feed = new Feed();
- feed.setItems(items);
-
- DownloadService.removeDuplicateImages(feed);
-
- assertEquals(50, items.size());
- for (int i = 0; i < items.size(); i++) {
- FeedItem item = items.get(i);
- String want = (i == 0) ? "dupe_url" : (i % 5 == 0) ? null : String.format("url_%d", i);
- assertEquals(want, item.getImageLocation());
- }
- }
-}
diff --git a/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java b/core/src/androidTest/java/de/danoeh/antennapod/core/util/DateUtilsTest.java
index ee90d9116..d5efdbc24 100644
--- a/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java
+++ b/core/src/androidTest/java/de/danoeh/antennapod/core/util/DateUtilsTest.java
@@ -1,4 +1,4 @@
-package de.danoeh.antennapod.core.tests.util;
+package de.danoeh.antennapod.core.util;
import android.test.AndroidTestCase;
@@ -7,8 +7,14 @@ import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
-import de.danoeh.antennapod.core.util.DateUtils;
-
+/**
+ * Unit test for {@link DateUtils}.
+ *
+ * Note: It NEEDS to be run in android devices, i.e., it cannot be run in standard JDK, because
+ * the test invokes some android platform-specific behavior in the underlying
+ * {@link java.text.SimpleDateFormat} used by {@link DateUtils}.
+ *
+ */
public class DateUtilsTest extends AndroidTestCase {
public void testParseDateWithMicroseconds() throws Exception {
@@ -101,6 +107,12 @@ public class DateUtilsTest extends AndroidTestCase {
assertEquals(expected, actual);
}
+ /**
+ * Requires Android platform.
+ *
+ * Reason: Standard JDK cannot parse timezone <code>-08:00</code> (ISO 8601 format). It only accepts
+ * <code>-0800</code> (RFC 822 format)
+ */
public void testParseDateWithNoTimezonePadding() throws Exception {
GregorianCalendar exp = new GregorianCalendar(2017, 1, 22, 22, 28, 0);
exp.setTimeZone(TimeZone.getTimeZone("UTC"));
@@ -109,6 +121,12 @@ public class DateUtilsTest extends AndroidTestCase {
assertEquals(expected, actual);
}
+ /**
+ * Requires Android platform. Root cause: {@link DateUtils} implementation makes
+ * use of ISO 8601 time zone, which does not work on standard JDK.
+ *
+ * @see #testParseDateWithNoTimezonePadding()
+ */
public void testParseDateWithForCest() throws Exception {
GregorianCalendar exp1 = new GregorianCalendar(2017, 0, 28, 22, 0, 0);
exp1.setTimeZone(TimeZone.getTimeZone("UTC"));
diff --git a/core/src/main/java/de/danoeh/antennapod/core/UpdateManager.java b/core/src/main/java/de/danoeh/antennapod/core/UpdateManager.java
index f7db11af6..ea07fc76e 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/UpdateManager.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/UpdateManager.java
@@ -14,7 +14,6 @@ import java.io.File;
import java.util.List;
import de.danoeh.antennapod.core.feed.Feed;
-import de.danoeh.antennapod.core.feed.FeedImage;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBReader;
@@ -64,29 +63,6 @@ class UpdateManager {
}
private static void onUpgrade(final int oldVersionCode, final int newVersionCode) {
- if(oldVersionCode < 1030099) {
- // delete the now obsolete image cache
- // from now on, Glide will handle caching images
- new Thread() {
- public void run() {
- List<Feed> feeds = DBReader.getFeedList();
- for (Feed podcast : feeds) {
- List<FeedItem> episodes = DBReader.getFeedItemList(podcast);
- for (FeedItem episode : episodes) {
- FeedImage image = episode.getImage();
- if (image != null && image.isDownloaded() && image.getFile_url() != null) {
- File imageFile = new File(image.getFile_url());
- if (imageFile.exists()) {
- imageFile.delete();
- }
- image.setFile_url(null); // calls setDownloaded(false)
- DBWriter.setFeedImage(image);
- }
- }
- }
- }
- }.start();
- }
if(oldVersionCode < 1050004) {
if(MediaPlayer.isPrestoLibraryInstalled(context) && Build.VERSION.SDK_INT >= 16) {
UserPreferences.enableSonic();
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java
index 78df74ee7..3395653f3 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java
@@ -44,7 +44,7 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource {
* Name of the author
*/
private String author;
- private FeedImage image;
+ private String imageUrl;
private List<FeedItem> items;
/**
@@ -96,7 +96,7 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource {
* This constructor is used for restoring a feed from the database.
*/
public Feed(long id, String lastUpdate, String title, String customTitle, String link, String description, String paymentLink,
- String author, String language, String type, String feedIdentifier, FeedImage image, String fileUrl,
+ String author, String language, String type, String feedIdentifier, String imageUrl, String fileUrl,
String downloadUrl, boolean downloaded, FlattrStatus status, boolean paged, String nextPageLink,
String filter, boolean lastUpdateFailed) {
super(fileUrl, downloadUrl, downloaded);
@@ -111,7 +111,7 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource {
this.language = language;
this.type = type;
this.feedIdentifier = feedIdentifier;
- this.image = image;
+ this.imageUrl = imageUrl;
this.flattrStatus = status;
this.paged = paged;
this.nextPageLink = nextPageLink;
@@ -128,9 +128,9 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource {
* This constructor is used for test purposes and uses a default flattr status object.
*/
public Feed(long id, String lastUpdate, String title, String link, String description, String paymentLink,
- String author, String language, String type, String feedIdentifier, FeedImage image, String fileUrl,
+ String author, String language, String type, String feedIdentifier, String imageUrl, String fileUrl,
String downloadUrl, boolean downloaded) {
- this(id, lastUpdate, title, null, link, description, paymentLink, author, language, type, feedIdentifier, image,
+ this(id, lastUpdate, title, null, link, description, paymentLink, author, language, type, feedIdentifier, imageUrl,
fileUrl, downloadUrl, downloaded, new FlattrStatus(), false, null, null, false);
}
@@ -191,6 +191,7 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource {
int indexNextPageLink = cursor.getColumnIndex(PodDBAdapter.KEY_NEXT_PAGE_LINK);
int indexHide = cursor.getColumnIndex(PodDBAdapter.KEY_HIDE);
int indexLastUpdateFailed = cursor.getColumnIndex(PodDBAdapter.KEY_LAST_UPDATE_FAILED);
+ int indexImageUrl = cursor.getColumnIndex(PodDBAdapter.KEY_IMAGE_URL);
Feed feed = new Feed(
cursor.getLong(indexId),
@@ -204,7 +205,7 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource {
cursor.getString(indexLanguage),
cursor.getString(indexType),
cursor.getString(indexFeedIdentifier),
- null,
+ cursor.getString(indexImageUrl),
cursor.getString(indexFileUrl),
cursor.getString(indexDownloadUrl),
cursor.getInt(indexDownloaded) > 0,
@@ -266,8 +267,8 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource {
public void updateFromOther(Feed other) {
// don't update feed's download_url, we do that manually if redirected
// see AntennapodHttpClient
- if (other.image != null) {
- this.image = other.image;
+ if (other.imageUrl != null) {
+ this.imageUrl = other.imageUrl;
}
if (other.feedTitle != null) {
feedTitle = other.feedTitle;
@@ -305,8 +306,8 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource {
if (super.compareWithOther(other)) {
return true;
}
- if (other.image != null) {
- if (image == null || !TextUtils.equals(image.download_url, other.image.download_url)) {
+ if (other.imageUrl != null) {
+ if (imageUrl == null || !TextUtils.equals(imageUrl, other.imageUrl)) {
return true;
}
}
@@ -411,12 +412,12 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource {
this.description = description;
}
- public FeedImage getImage() {
- return image;
+ public String getImageUrl() {
+ return imageUrl;
}
- public void setImage(FeedImage image) {
- this.image = image;
+ public void setImageUrl(String imageUrl) {
+ this.imageUrl = imageUrl;
}
public List<FeedItem> getItems() {
@@ -505,11 +506,7 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource {
@Override
public String getImageLocation() {
- if (image != null) {
- return image.getImageLocation();
- } else {
- return null;
- }
+ return imageUrl;
}
public int getPageNr() {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java
deleted file mode 100644
index 45bd2ad31..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package de.danoeh.antennapod.core.feed;
-
-import android.database.Cursor;
-
-import java.io.File;
-
-import de.danoeh.antennapod.core.asynctask.ImageResource;
-import de.danoeh.antennapod.core.storage.PodDBAdapter;
-
-
-public class FeedImage extends FeedFile implements ImageResource {
- public static final int FEEDFILETYPE_FEEDIMAGE = 1;
-
- private String title;
- private FeedComponent owner;
-
- public FeedImage(FeedComponent owner, String download_url, String title) {
- super(null, download_url, false);
- this.download_url = download_url;
- this.title = title;
- this.owner = owner;
- }
-
- public FeedImage(long id, String title, String file_url,
- String download_url, boolean downloaded) {
- super(file_url, download_url, downloaded);
- this.id = id;
- this.title = title;
- }
-
- public FeedImage() {
- super();
- }
-
- public static FeedImage fromCursor(Cursor cursor) {
- int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID);
- int indexTitle = cursor.getColumnIndex(PodDBAdapter.KEY_TITLE);
- int indexFileUrl = cursor.getColumnIndex(PodDBAdapter.KEY_FILE_URL);
- int indexDownloadUrl = cursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOAD_URL);
- int indexDownloaded = cursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOADED);
-
- return new FeedImage(
- cursor.getLong(indexId),
- cursor.getString(indexTitle),
- cursor.getString(indexFileUrl),
- cursor.getString(indexDownloadUrl),
- cursor.getInt(indexDownloaded) > 0
- );
- }
-
-
- @Override
- public String getHumanReadableIdentifier() {
- if (owner != null && owner.getHumanReadableIdentifier() != null) {
- return owner.getHumanReadableIdentifier();
- } else {
- return download_url;
- }
- }
-
- @Override
- public int getTypeAsInt() {
- return FEEDFILETYPE_FEEDIMAGE;
- }
-
- public String getTitle() {
- return title;
- }
-
- public void setTitle(String title) {
- this.title = title;
- }
-
- public FeedComponent getOwner() {
- return owner;
- }
-
- public void setOwner(FeedComponent owner) {
- this.owner = owner;
- }
-
- @Override
- public String getImageLocation() {
- if (file_url != null && downloaded) {
- return new File(file_url).getAbsolutePath();
- } else if(download_url != null) {
- return download_url;
- } else {
- return null;
- }
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java
index 87298d4c3..b0a87c885 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java
@@ -4,6 +4,7 @@ import android.database.Cursor;
import android.support.annotation.Nullable;
import android.text.TextUtils;
+import de.danoeh.antennapod.core.asynctask.ImageResource;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
@@ -14,7 +15,6 @@ import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
-import de.danoeh.antennapod.core.asynctask.ImageResource;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.danoeh.antennapod.core.util.ShownotesProvider;
@@ -75,7 +75,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
* in the database. The 'hasChapters' attribute should be used to check if this item has any chapters.
* */
private List<Chapter> chapters;
- private FeedImage image;
+ private String imageUrl;
/*
* 0: auto download disabled
@@ -100,7 +100,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
* This constructor is used by DBReader.
* */
public FeedItem(long id, String title, String link, Date pubDate, String paymentLink, long feedId,
- FlattrStatus flattrStatus, boolean hasChapters, FeedImage image, int state,
+ FlattrStatus flattrStatus, boolean hasChapters, String imageUrl, int state,
String itemIdentifier, long autoDownload) {
this.id = id;
this.title = title;
@@ -110,7 +110,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
this.feedId = feedId;
this.flattrStatus = flattrStatus;
this.hasChapters = hasChapters;
- this.image = image;
+ this.imageUrl = imageUrl;
this.state = state;
this.itemIdentifier = itemIdentifier;
this.autoDownload = autoDownload;
@@ -158,6 +158,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
int indexRead = cursor.getColumnIndex(PodDBAdapter.KEY_READ);
int indexItemIdentifier = cursor.getColumnIndex(PodDBAdapter.KEY_ITEM_IDENTIFIER);
int indexAutoDownload = cursor.getColumnIndex(PodDBAdapter.KEY_AUTO_DOWNLOAD);
+ int indexImageUrl = cursor.getColumnIndex(PodDBAdapter.KEY_IMAGE_URL);
long id = cursor.getInt(indexId);
String title = cursor.getString(indexTitle);
@@ -170,15 +171,16 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
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, flattrStatus,
- hasChapters, null, state, itemIdentifier, autoDownload);
+ hasChapters, imageUrl, state, itemIdentifier, autoDownload);
}
public void updateFromOther(FeedItem other) {
super.updateFromOther(other);
- if (other.image != null) {
- this.image = other.image;
+ if (other.imageUrl != null) {
+ this.imageUrl = other.imageUrl;
}
if (other.title != null) {
title = other.title;
@@ -212,9 +214,6 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
chapters = other.chapters;
}
}
- if (image == null) {
- image = other.image;
- }
}
/**
@@ -389,8 +388,8 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
public String getImageLocation() {
if(media != null && media.hasEmbeddedPicture()) {
return media.getImageLocation();
- } else if (image != null) {
- return image.getImageLocation();
+ } else if (imageUrl != null) {
+ return imageUrl;
} else if (feed != null) {
return feed.getImageLocation();
} else {
@@ -426,29 +425,12 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
* Returns the image of this item or the image of the feed if this item does
* not have its own image.
*/
- public FeedImage getImage() {
- return (hasItemImage()) ? image : feed.getImage();
- }
-
- public void setImage(FeedImage image) {
- this.image = image;
- if (image != null) {
- image.setOwner(this);
- }
- }
-
- /**
- * Returns true if this FeedItem has its own image, false otherwise.
- */
- public boolean hasItemImage() {
- return image != null;
+ public String getImageUrl() {
+ return (imageUrl != null) ? imageUrl : feed.getImageUrl();
}
- /**
- * Returns true if this FeedItem has its own image and the image has been downloaded.
- */
- public boolean hasItemImageDownloaded() {
- return image != null && image.isDownloaded();
+ public void setImageUrl(String imageUrl) {
+ this.imageUrl = imageUrl;
}
@Override
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 2bdefcb45..bb487c871 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
@@ -161,6 +161,8 @@ public class UserPreferences {
int theme = getTheme();
if (theme == R.style.Theme_AntennaPod_Dark) {
return R.style.Theme_AntennaPod_Dark_NoTitle;
+ } else if (theme == R.style.Theme_AntennaPod_TrueBlack) {
+ return R.style.Theme_AntennaPod_TrueBlack_NoTitle;
} else {
return R.style.Theme_AntennaPod_Light_NoTitle;
}
@@ -597,6 +599,8 @@ public class UserPreferences {
return R.style.Theme_AntennaPod_Light;
case 1:
return R.style.Theme_AntennaPod_Dark;
+ case 2:
+ return R.style.Theme_AntennaPod_TrueBlack;
default:
return R.style.Theme_AntennaPod_Light;
}
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 e3b8a505b..bfca04d60 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
@@ -55,7 +55,6 @@ import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.FeedItemEvent;
import de.danoeh.antennapod.core.feed.Feed;
-import de.danoeh.antennapod.core.feed.FeedImage;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.FeedPreferences;
@@ -489,9 +488,7 @@ public class DownloadService extends Service {
if (status.isSuccessful()) {
successfulDownloads++;
} else if (!status.isCancelled()) {
- if (status.getFeedfileType() != FeedImage.FEEDFILETYPE_FEEDIMAGE) {
- createReport = true;
- }
+ createReport = true;
failedDownloads++;
}
}
@@ -688,10 +685,6 @@ public class DownloadService extends Service {
Log.d(TAG, "Bundling " + results.size() + " feeds");
- for (Pair<DownloadRequest, FeedHandlerResult> result : results) {
- removeDuplicateImages(result.second.feed); // duplicate images have to removed because the DownloadRequester does not accept two downloads with the same download URL yet.
- }
-
// Save information of feed in DB
if (dbUpdateFuture != null) {
try {
@@ -1101,26 +1094,6 @@ public class DownloadService extends Service {
}
}
- /**
- * Checks if the FeedItems of this feed have images that point to the same URL. If two FeedItems
- * have an image that points to the same URL, the reference of the second item is removed, so
- * that every image reference is unique.
- */
- @VisibleForTesting
- public static void removeDuplicateImages(Feed feed) {
- Set<String> known = new HashSet<>();
- for (FeedItem item : feed.getItems()) {
- String url = item.hasItemImage() ? item.getImage().getDownload_url() : null;
- if (url != null) {
- if (known.contains(url)) {
- item.setImage(null);
- } else {
- known.add(url);
- }
- }
- }
- }
-
private static String compileNotificationString(List<Downloader> downloads) {
List<String> lines = new ArrayList<>(downloads.size());
for (Downloader downloader : downloads) {
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 7ab0931d6..8cce02155 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
@@ -20,7 +20,6 @@ import java.util.Date;
import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.R;
-import de.danoeh.antennapod.core.feed.FeedImage;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.util.DateUtils;
import de.danoeh.antennapod.core.util.DownloadError;
@@ -50,13 +49,8 @@ public class HttpDownloader extends Downloader {
if (request.isDeleteOnFailure() && fileExists) {
Log.w(TAG, "File already exists");
- if (request.getFeedfileType() != FeedImage.FEEDFILETYPE_FEEDIMAGE) {
- onFail(DownloadError.ERROR_FILE_EXISTS, null);
- return;
- } else {
- onSuccess();
- return;
- }
+ onSuccess();
+ return;
}
OkHttpClient.Builder httpClientBuilder = AntennapodHttpClient.newBuilder();
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 fa87cc216..5eb5145e8 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
@@ -13,7 +13,6 @@ import java.util.Map;
import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.Feed;
-import de.danoeh.antennapod.core.feed.FeedImage;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.FeedPreferences;
@@ -201,25 +200,15 @@ public final class DBReader {
private static List<FeedItem> extractItemlistFromCursor(PodDBAdapter adapter, Cursor cursor) {
List<FeedItem> result = new ArrayList<>(cursor.getCount());
- LongList imageIds = new LongList(cursor.getCount());
LongList itemIds = new LongList(cursor.getCount());
if (cursor.moveToFirst()) {
do {
- int indexImage = cursor.getColumnIndex(PodDBAdapter.KEY_IMAGE);
- long imageId = cursor.getLong(indexImage);
- imageIds.add(imageId);
-
FeedItem item = FeedItem.fromCursor(cursor);
result.add(item);
itemIds.add(item.getId());
} while (cursor.moveToNext());
- Map<Long, FeedImage> images = getFeedImages(adapter, imageIds.toArray());
Map<Long, FeedMedia> medias = getFeedMedia(adapter, itemIds);
- for (int i = 0; i < result.size(); i++) {
- FeedItem item = result.get(i);
- long imageId = imageIds.get(i);
- FeedImage image = images.get(imageId);
- item.setImage(image);
+ for (FeedItem item : result) {
FeedMedia media = medias.get(item.getId());
item.setMedia(media);
if (media != null) {
@@ -254,24 +243,9 @@ public final class DBReader {
}
private static Feed extractFeedFromCursorRow(PodDBAdapter adapter, Cursor cursor) {
- final FeedImage image;
- int indexImage = cursor.getColumnIndex(PodDBAdapter.KEY_IMAGE);
- long imageId = cursor.getLong(indexImage);
- if (imageId != 0) {
- image = getFeedImage(adapter, imageId);
- } else {
- image = null;
- }
-
Feed feed = Feed.fromCursor(cursor);
- if (image != null) {
- feed.setImage(image);
- image.setOwner(feed);
- }
-
FeedPreferences preferences = FeedPreferences.fromCursor(cursor);
feed.setPreferences(preferences);
-
return feed;
}
@@ -839,62 +813,6 @@ public final class DBReader {
}
/**
- * Searches the DB for a FeedImage of the given id.
- *
- * @param imageId The id of the object
- * @return The found object
- */
- public static FeedImage getFeedImage(final long imageId) {
- Log.d(TAG, "getFeedImage() called with: " + "imageId = [" + imageId + "]");
- PodDBAdapter adapter = PodDBAdapter.getInstance();
- adapter.open();
- try {
- return getFeedImage(adapter, imageId);
- } finally {
- adapter.close();
- }
- }
-
- /**
- * Searches the DB for a FeedImage of the given id.
- *
- * @param imageId The id of the object
- * @return The found object
- */
- private static FeedImage getFeedImage(PodDBAdapter adapter, final long imageId) {
- return getFeedImages(adapter, imageId).get(imageId);
- }
-
- /**
- * Searches the DB for a FeedImage of the given id.
- *
- * @param imageIds The ids of the images
- * @return Map that associates the id of an image with the image itself
- */
- private static Map<Long, FeedImage> getFeedImages(PodDBAdapter adapter, final long... imageIds) {
- String[] ids = new String[imageIds.length];
- for (int i = 0, len = imageIds.length; i < len; i++) {
- ids[i] = String.valueOf(imageIds[i]);
- }
- Cursor cursor = adapter.getImageCursor(ids);
- int imageCount = cursor.getCount();
- if (imageCount == 0) {
- cursor.close();
- return Collections.emptyMap();
- }
- Map<Long, FeedImage> result = new ArrayMap<>(imageCount);
- try {
- while (cursor.moveToNext()) {
- FeedImage image = FeedImage.fromCursor(cursor);
- result.put(image.getId(), image);
- }
- } finally {
- cursor.close();
- }
- return result;
- }
-
- /**
* Searches the DB for a FeedMedia of the given id.
*
* @param mediaId The id of the object
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
new file mode 100644
index 000000000..29ed5f7f9
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java
@@ -0,0 +1,292 @@
+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.core.feed.FeedItem;
+
+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
+ + " INTEGER DEFAULT 1");
+ }
+ if (oldVersion <= 10) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
+ + " ADD COLUMN " + PodDBAdapter.KEY_FLATTR_STATUS
+ + " INTEGER");
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ + " ADD COLUMN " + PodDBAdapter.KEY_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 " + PodDBAdapter.KEY_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 + " INTEGER");
+ db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
+ + " SET " + PodDBAdapter.KEY_AUTO_DOWNLOAD + " = "
+ + "(SELECT " + PodDBAdapter.KEY_AUTO_DOWNLOAD
+ + " 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 + "." + PodDBAdapter.KEY_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 + "." + PodDBAdapter.KEY_IMAGE + ")");
+
+ db.execSQL("DROP TABLE " + PodDBAdapter.TABLE_NAME_FEED_IMAGES);
+ }
+ }
+
+}
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 8cdf82e15..1f4fad4ba 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
@@ -32,7 +32,6 @@ import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedEvent;
-import de.danoeh.antennapod.core.feed.FeedImage;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.FeedPreferences;
@@ -166,17 +165,6 @@ public class DBWriter {
editor.commit();
}
- // delete image file
- if (feed.getImage() != null) {
- if (feed.getImage().isDownloaded()
- && feed.getImage().getFile_url() != null) {
- File imageFile = new File(feed.getImage()
- .getFile_url());
- imageFile.delete();
- } else if (requester.isDownloadingFile(feed.getImage())) {
- requester.cancelDownload(context, feed.getImage());
- }
- }
// delete stored media files and mark them as read
List<FeedItem> queue = DBReader.getQueue();
List<FeedItem> removed = new ArrayList<>();
@@ -200,16 +188,6 @@ public class DBWriter {
&& requester.isDownloadingFile(item.getMedia())) {
requester.cancelDownload(context, item.getMedia());
}
-
- if (item.hasItemImage()) {
- FeedImage image = item.getImage();
- if (image.isDownloaded() && image.getFile_url() != null) {
- File imgFile = new File(image.getFile_url());
- imgFile.delete();
- } else if (requester.isDownloadingFile(image)) {
- requester.cancelDownload(context, item.getImage());
- }
- }
}
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
@@ -786,21 +764,6 @@ public class DBWriter {
}
/**
- * Saves a FeedImage object in the database. This method will save all attributes of the FeedImage object. The
- * contents of FeedComponent-attributes (e.g. the FeedImages's 'feed'-attribute) will not be saved.
- *
- * @param image The FeedImage object.
- */
- public static Future<?> setFeedImage(final FeedImage image) {
- return dbExec.submit(() -> {
- PodDBAdapter adapter = PodDBAdapter.getInstance();
- adapter.open();
- adapter.setImage(image);
- adapter.close();
- });
- }
-
- /**
* Updates download URL of a feed
*/
public static Future<?> updateFeedDownloadURL(final String original, final String updated) {
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
index e82252310..591015dff 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
@@ -14,20 +14,10 @@ import android.database.sqlite.SQLiteOpenHelper;
import android.media.MediaMetadataRetriever;
import android.text.TextUtils;
import android.util.Log;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.event.ProgressEvent;
import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.Feed;
-import de.danoeh.antennapod.core.feed.FeedComponent;
-import de.danoeh.antennapod.core.feed.FeedImage;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.FeedPreferences;
@@ -38,6 +28,13 @@ import de.danoeh.antennapod.core.util.flattr.FlattrStatus;
import de.greenrobot.event.EventBus;
import org.apache.commons.io.FileUtils;
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
// TODO Remove media column from feeditem table
/**
@@ -74,8 +71,9 @@ public class PodDBAdapter {
public static final String KEY_SIZE = "filesize";
public static final String KEY_MIME_TYPE = "mime_type";
public static final String KEY_IMAGE = "image";
+ public static final String KEY_IMAGE_URL = "image_url";
public static final String KEY_FEED = "feed";
- private static final String KEY_MEDIA = "media";
+ 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";
@@ -114,14 +112,14 @@ public class PodDBAdapter {
public static final String KEY_EXCLUDE_FILTER = "exclude_filter";
// Table names
- private static final String TABLE_NAME_FEEDS = "Feeds";
- private static final String TABLE_NAME_FEED_ITEMS = "FeedItems";
- private static final String TABLE_NAME_FEED_IMAGES = "FeedImages";
- private static final String TABLE_NAME_FEED_MEDIA = "FeedMedia";
- private static final String TABLE_NAME_DOWNLOAD_LOG = "DownloadLog";
- private static final String TABLE_NAME_QUEUE = "Queue";
- private static final String TABLE_NAME_SIMPLECHAPTERS = "SimpleChapters";
- private static final String TABLE_NAME_FAVORITES = "Favorites";
+ static final String TABLE_NAME_FEEDS = "Feeds";
+ static final String TABLE_NAME_FEED_ITEMS = "FeedItems";
+ static final String TABLE_NAME_FEED_IMAGES = "FeedImages";
+ static final String TABLE_NAME_FEED_MEDIA = "FeedMedia";
+ static final String TABLE_NAME_DOWNLOAD_LOG = "DownloadLog";
+ static final String TABLE_NAME_QUEUE = "Queue";
+ static final String TABLE_NAME_SIMPLECHAPTERS = "SimpleChapters";
+ static final String TABLE_NAME_FAVORITES = "Favorites";
// SQL Statements for creating new tables
private static final String TABLE_PRIMARY_KEY = KEY_ID
@@ -133,7 +131,7 @@ public class PodDBAdapter {
+ KEY_DOWNLOADED + " INTEGER," + KEY_LINK + " TEXT,"
+ KEY_DESCRIPTION + " TEXT," + KEY_PAYMENT_LINK + " TEXT,"
+ KEY_LASTUPDATE + " TEXT," + KEY_LANGUAGE + " TEXT," + KEY_AUTHOR
- + " TEXT," + KEY_IMAGE + " INTEGER," + KEY_TYPE + " TEXT,"
+ + " TEXT," + KEY_IMAGE_URL + " TEXT," + KEY_TYPE + " TEXT,"
+ KEY_FEED_IDENTIFIER + " TEXT," + KEY_AUTO_DOWNLOAD + " INTEGER DEFAULT 1,"
+ KEY_FLATTR_STATUS + " INTEGER,"
+ KEY_USERNAME + " TEXT,"
@@ -155,14 +153,9 @@ public class PodDBAdapter {
+ KEY_MEDIA + " INTEGER," + KEY_FEED + " INTEGER,"
+ KEY_HAS_CHAPTERS + " INTEGER," + KEY_ITEM_IDENTIFIER + " TEXT,"
+ KEY_FLATTR_STATUS + " INTEGER,"
- + KEY_IMAGE + " INTEGER,"
+ + KEY_IMAGE_URL + " TEXT,"
+ KEY_AUTO_DOWNLOAD + " INTEGER)";
- private static final String CREATE_TABLE_FEED_IMAGES = "CREATE TABLE "
- + TABLE_NAME_FEED_IMAGES + " (" + TABLE_PRIMARY_KEY + KEY_TITLE
- + " TEXT," + KEY_FILE_URL + " TEXT," + KEY_DOWNLOAD_URL + " TEXT,"
- + KEY_DOWNLOADED + " 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
@@ -191,36 +184,31 @@ public class PodDBAdapter {
+ KEY_LINK + " TEXT," + KEY_CHAPTER_TYPE + " INTEGER)";
// SQL Statements for creating indexes
- private static final String CREATE_INDEX_FEEDITEMS_FEED = "CREATE INDEX "
+ static final String CREATE_INDEX_FEEDITEMS_FEED = "CREATE INDEX "
+ TABLE_NAME_FEED_ITEMS + "_" + KEY_FEED + " ON " + TABLE_NAME_FEED_ITEMS + " ("
+ KEY_FEED + ")";
- private static final String CREATE_INDEX_FEEDITEMS_IMAGE = "CREATE INDEX "
- + TABLE_NAME_FEED_ITEMS + "_" + KEY_IMAGE + " ON " + TABLE_NAME_FEED_ITEMS + " ("
- + KEY_IMAGE + ")";
-
- private static final String CREATE_INDEX_FEEDITEMS_PUBDATE = "CREATE INDEX IF NOT EXISTS "
+ static final String CREATE_INDEX_FEEDITEMS_PUBDATE = "CREATE INDEX IF NOT EXISTS "
+ TABLE_NAME_FEED_ITEMS + "_" + KEY_PUBDATE + " ON " + TABLE_NAME_FEED_ITEMS + " ("
+ KEY_PUBDATE + ")";
- private static final String CREATE_INDEX_FEEDITEMS_READ = "CREATE INDEX IF NOT EXISTS "
+ static final String CREATE_INDEX_FEEDITEMS_READ = "CREATE INDEX IF NOT EXISTS "
+ TABLE_NAME_FEED_ITEMS + "_" + KEY_READ + " ON " + TABLE_NAME_FEED_ITEMS + " ("
+ KEY_READ + ")";
-
- private static final String CREATE_INDEX_QUEUE_FEEDITEM = "CREATE INDEX "
+ static final String CREATE_INDEX_QUEUE_FEEDITEM = "CREATE INDEX "
+ TABLE_NAME_QUEUE + "_" + KEY_FEEDITEM + " ON " + TABLE_NAME_QUEUE + " ("
+ KEY_FEEDITEM + ")";
- private static final String CREATE_INDEX_FEEDMEDIA_FEEDITEM = "CREATE INDEX "
+ static final String CREATE_INDEX_FEEDMEDIA_FEEDITEM = "CREATE INDEX "
+ TABLE_NAME_FEED_MEDIA + "_" + KEY_FEEDITEM + " ON " + TABLE_NAME_FEED_MEDIA + " ("
+ KEY_FEEDITEM + ")";
- private static final String CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM = "CREATE INDEX "
+ static final String CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM = "CREATE INDEX "
+ TABLE_NAME_SIMPLECHAPTERS + "_" + KEY_FEEDITEM + " ON " + TABLE_NAME_SIMPLECHAPTERS + " ("
+ KEY_FEEDITEM + ")";
- private static final String CREATE_TABLE_FAVORITES = "CREATE TABLE "
+ static final String CREATE_TABLE_FAVORITES = "CREATE TABLE "
+ TABLE_NAME_FAVORITES + "(" + KEY_ID + " INTEGER PRIMARY KEY,"
+ KEY_FEEDITEM + " INTEGER," + KEY_FEED + " INTEGER)";
@@ -240,7 +228,7 @@ public class PodDBAdapter {
TABLE_NAME_FEEDS + "." + KEY_LASTUPDATE,
TABLE_NAME_FEEDS + "." + KEY_LANGUAGE,
TABLE_NAME_FEEDS + "." + KEY_AUTHOR,
- TABLE_NAME_FEEDS + "." + KEY_IMAGE,
+ TABLE_NAME_FEEDS + "." + KEY_IMAGE_URL,
TABLE_NAME_FEEDS + "." + KEY_TYPE,
TABLE_NAME_FEEDS + "." + KEY_FEED_IDENTIFIER,
TABLE_NAME_FEEDS + "." + KEY_AUTO_DOWNLOAD,
@@ -273,7 +261,7 @@ public class PodDBAdapter {
TABLE_NAME_FEED_ITEMS + "." + KEY_HAS_CHAPTERS,
TABLE_NAME_FEED_ITEMS + "." + KEY_ITEM_IDENTIFIER,
TABLE_NAME_FEED_ITEMS + "." + KEY_FLATTR_STATUS,
- TABLE_NAME_FEED_ITEMS + "." + KEY_IMAGE,
+ TABLE_NAME_FEED_ITEMS + "." + KEY_IMAGE_URL,
TABLE_NAME_FEED_ITEMS + "." + KEY_AUTO_DOWNLOAD
};
@@ -283,7 +271,6 @@ public class PodDBAdapter {
private static final String[] ALL_TABLES = {
TABLE_NAME_FEEDS,
TABLE_NAME_FEED_ITEMS,
- TABLE_NAME_FEED_IMAGES,
TABLE_NAME_FEED_MEDIA,
TABLE_NAME_DOWNLOAD_LOG,
TABLE_NAME_QUEUE,
@@ -388,12 +375,7 @@ public class PodDBAdapter {
values.put(KEY_PAYMENT_LINK, feed.getPaymentLink());
values.put(KEY_AUTHOR, feed.getAuthor());
values.put(KEY_LANGUAGE, feed.getLanguage());
- if (feed.getImage() != null) {
- if (feed.getImage().getId() == 0) {
- setImage(feed.getImage());
- }
- values.put(KEY_IMAGE, feed.getImage().getId());
- }
+ values.put(KEY_IMAGE_URL, feed.getImageUrl());
values.put(KEY_FILE_URL, feed.getFile_url());
values.put(KEY_DOWNLOAD_URL, feed.getDownload_url());
@@ -450,54 +432,7 @@ public class PodDBAdapter {
}
/**
- * Inserts or updates an image entry
- *
- * @return the id of the entry
- */
- public long setImage(FeedImage image) {
- boolean startedTransaction = false;
-
- try {
- if (!db.inTransaction()) {
- db.beginTransactionNonExclusive();
- startedTransaction = true;
- }
-
- ContentValues values = new ContentValues();
- values.put(KEY_TITLE, image.getTitle());
- values.put(KEY_DOWNLOAD_URL, image.getDownload_url());
- values.put(KEY_DOWNLOADED, image.isDownloaded());
- values.put(KEY_FILE_URL, image.getFile_url());
- if (image.getId() == 0) {
- image.setId(db.insert(TABLE_NAME_FEED_IMAGES, null, values));
- } else {
- db.update(TABLE_NAME_FEED_IMAGES, values, KEY_ID + "=?",
- new String[]{String.valueOf(image.getId())});
- }
-
- final FeedComponent owner = image.getOwner();
- if (owner != null && owner.getId() != 0) {
- values.clear();
- values.put(KEY_IMAGE, image.getId());
- if (owner instanceof Feed) {
- db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(image.getOwner().getId())});
- }
- }
- if (startedTransaction) {
- db.setTransactionSuccessful();
- }
- } catch (SQLException e) {
- Log.e(TAG, Log.getStackTraceString(e));
- } finally {
- if (startedTransaction) {
- db.endTransaction();
- }
- }
- return image.getId();
- }
-
- /**
- * Inserts or updates an image entry
+ * Inserts or updates a media entry
*
* @return the id of the entry
*/
@@ -759,12 +694,7 @@ public class PodDBAdapter {
values.put(KEY_ITEM_IDENTIFIER, item.getItemIdentifier());
values.put(KEY_FLATTR_STATUS, item.getFlattrStatus().toLong());
values.put(KEY_AUTO_DOWNLOAD, item.getAutoDownload());
- if (item.hasItemImage()) {
- if (item.getImage().getId() == 0) {
- setImage(item.getImage());
- }
- values.put(KEY_IMAGE, item.getImage().getId());
- }
+ values.put(KEY_IMAGE_URL, item.getImageUrl());
if (item.getId() == 0) {
item.setId(db.insert(TABLE_NAME_FEED_ITEMS, null, values));
@@ -993,11 +923,6 @@ public class PodDBAdapter {
new String[]{String.valueOf(item.getId())});
}
- private void removeFeedImage(FeedImage image) {
- db.delete(TABLE_NAME_FEED_IMAGES, KEY_ID + "=?",
- new String[]{String.valueOf(image.getId())});
- }
-
/**
* Remove a FeedItem and its FeedMedia entry.
*/
@@ -1008,9 +933,6 @@ public class PodDBAdapter {
if (item.hasChapters() || item.getChapters() != null) {
removeChaptersOfItem(item);
}
- if (item.hasItemImage()) {
- removeFeedImage(item.getImage());
- }
db.delete(TABLE_NAME_FEED_ITEMS, KEY_ID + "=?",
new String[]{String.valueOf(item.getId())});
}
@@ -1021,9 +943,6 @@ public class PodDBAdapter {
public void removeFeed(Feed feed) {
try {
db.beginTransactionNonExclusive();
- if (feed.getImage() != null) {
- removeFeedImage(feed.getImage());
- }
if (feed.getItems() != null) {
for (FeedItem item : feed.getItems()) {
removeFeedItem(item);
@@ -1363,17 +1282,12 @@ public class PodDBAdapter {
public Cursor getImageAuthenticationCursor(final String imageUrl) {
String downloadUrl = DatabaseUtils.sqlEscapeString(imageUrl);
final String query = ""
- + "SELECT " + KEY_USERNAME + "," + KEY_PASSWORD + " FROM " + TABLE_NAME_FEED_IMAGES
+ + "SELECT " + KEY_USERNAME + "," + KEY_PASSWORD + " FROM " + TABLE_NAME_FEED_ITEMS
+ " INNER JOIN " + TABLE_NAME_FEEDS
- + " ON " + TABLE_NAME_FEED_IMAGES + "." + KEY_ID + "=" + TABLE_NAME_FEEDS + "." + KEY_IMAGE
- + " WHERE " + TABLE_NAME_FEED_IMAGES + "." + KEY_DOWNLOAD_URL + "=" + downloadUrl
- + " UNION SELECT " + KEY_USERNAME + "," + KEY_PASSWORD
- + " FROM " + TABLE_NAME_FEED_IMAGES
- + " INNER JOIN " + TABLE_NAME_FEED_ITEMS
- + " ON " + TABLE_NAME_FEED_IMAGES + "." + KEY_ID + "=" + TABLE_NAME_FEED_ITEMS + "." + KEY_IMAGE
- + " INNER JOIN " + TABLE_NAME_FEEDS
- + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + "=" + TABLE_NAME_FEEDS + "." + KEY_ID
- + " WHERE " + TABLE_NAME_FEED_IMAGES + "." + KEY_DOWNLOAD_URL + "=" + downloadUrl;
+ + " 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);
}
@@ -1672,7 +1586,7 @@ public class PodDBAdapter {
*/
private static class PodDBHelper extends SQLiteOpenHelper {
- private static final int VERSION = 1060200;
+ private static final int VERSION = 1060596;
private final Context context;
@@ -1693,7 +1607,6 @@ public class PodDBAdapter {
public void onCreate(final SQLiteDatabase db) {
db.execSQL(CREATE_TABLE_FEEDS);
db.execSQL(CREATE_TABLE_FEED_ITEMS);
- db.execSQL(CREATE_TABLE_FEED_IMAGES);
db.execSQL(CREATE_TABLE_FEED_MEDIA);
db.execSQL(CREATE_TABLE_DOWNLOAD_LOG);
db.execSQL(CREATE_TABLE_QUEUE);
@@ -1701,7 +1614,6 @@ public class PodDBAdapter {
db.execSQL(CREATE_TABLE_FAVORITES);
db.execSQL(CREATE_INDEX_FEEDITEMS_FEED);
- db.execSQL(CREATE_INDEX_FEEDITEMS_IMAGE);
db.execSQL(CREATE_INDEX_FEEDITEMS_PUBDATE);
db.execSQL(CREATE_INDEX_FEEDITEMS_READ);
db.execSQL(CREATE_INDEX_FEEDMEDIA_FEEDITEM);
@@ -1716,263 +1628,7 @@ public class PodDBAdapter {
EventBus.getDefault().post(ProgressEvent.start(context.getString(R.string.progress_upgrading_database)));
Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to "
+ newVersion + ".");
- if (oldVersion <= 1) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN "
- + KEY_TYPE + " TEXT");
- }
- if (oldVersion <= 2) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS
- + " ADD COLUMN " + KEY_LINK + " TEXT");
- }
- if (oldVersion <= 3) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " ADD COLUMN " + KEY_ITEM_IDENTIFIER + " TEXT");
- }
- if (oldVersion <= 4) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN "
- + KEY_FEED_IDENTIFIER + " TEXT");
- }
- if (oldVersion <= 5) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_DOWNLOAD_LOG
- + " ADD COLUMN " + KEY_REASON_DETAILED + " TEXT");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_DOWNLOAD_LOG
- + " ADD COLUMN " + KEY_DOWNLOADSTATUS_TITLE + " TEXT");
- }
- if (oldVersion <= 6) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS
- + " ADD COLUMN " + KEY_CHAPTER_TYPE + " INTEGER");
- }
- if (oldVersion <= 7) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " ADD COLUMN " + 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 " + KEY_FEEDITEM
- + " INTEGER");
- Cursor feeditemCursor = db.query(PodDBAdapter.TABLE_NAME_FEED_ITEMS,
- new String[]{KEY_ID, KEY_MEDIA}, "? > 0",
- new String[]{KEY_MEDIA}, null, null, null);
- if (feeditemCursor.moveToFirst()) {
- db.beginTransaction();
- ContentValues contentValues = new ContentValues();
- do {
- long mediaId = feeditemCursor.getLong(KEY_MEDIA_POSITION);
- contentValues.put(KEY_FEEDITEM, feeditemCursor.getLong(KEY_ID_POSITION));
- db.update(PodDBAdapter.TABLE_NAME_FEED_MEDIA, contentValues, 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 " + KEY_AUTO_DOWNLOAD
- + " INTEGER DEFAULT 1");
- }
- if (oldVersion <= 10) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + KEY_FLATTR_STATUS
- + " INTEGER");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " ADD COLUMN " + KEY_FLATTR_STATUS
- + " INTEGER");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " ADD COLUMN " + KEY_PLAYED_DURATION
- + " INTEGER");
- }
- if (oldVersion <= 11) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + KEY_USERNAME
- + " TEXT");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + KEY_PASSWORD
- + " TEXT");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " ADD COLUMN " + KEY_IMAGE
- + " INTEGER");
- }
- if (oldVersion <= 12) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + KEY_IS_PAGED + " INTEGER DEFAULT 0");
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + 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,
- KEY_ID,
- KEY_ID,
- KEY_ID,
- PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS,
- KEY_TITLE,
- KEY_START,
- KEY_FEEDITEM,
- KEY_LINK,
- KEY_CHAPTER_TYPE));
- }
- if (oldVersion <= 14) {
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " ADD COLUMN " + KEY_AUTO_DOWNLOAD + " INTEGER");
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " SET " + KEY_AUTO_DOWNLOAD + " = "
- + "(SELECT " + KEY_AUTO_DOWNLOAD
- + " FROM " + PodDBAdapter.TABLE_NAME_FEEDS
- + " WHERE " + PodDBAdapter.TABLE_NAME_FEEDS + "." + KEY_ID
- + " = " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + ")");
-
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + KEY_HIDE + " TEXT");
-
- db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
- + " ADD COLUMN " + KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0");
-
- // create indexes
- db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_FEED);
- db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_IMAGE);
- 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 " + KEY_HAS_EMBEDDED_PICTURE + " INTEGER DEFAULT -1");
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " SET " + KEY_HAS_EMBEDDED_PICTURE + "=0"
- + " WHERE " + KEY_DOWNLOADED + "=0");
- Cursor c = db.rawQuery("SELECT " + KEY_FILE_URL
- + " FROM " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " WHERE " + KEY_DOWNLOADED + "=1 "
- + " AND " + 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 " + KEY_HAS_EMBEDDED_PICTURE + "=1"
- + " WHERE " + KEY_FILE_URL + "='" + fileUrl + "'");
- } else {
- db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA
- + " SET " + KEY_HAS_EMBEDDED_PICTURE + "=0"
- + " WHERE " + 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 + "." + KEY_ID
- + " FROM " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " INNER JOIN " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + " ON "
- + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
- + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM
- + " LEFT OUTER JOIN " + PodDBAdapter.TABLE_NAME_QUEUE + " ON "
- + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
- + PodDBAdapter.TABLE_NAME_QUEUE + "." + KEY_FEEDITEM
- + " WHERE "
- + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_READ + " = 0 AND " // unplayed
- + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " = 0 AND " // undownloaded
- + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " = 0 AND " // not partially played
- + PodDBAdapter.TABLE_NAME_QUEUE + "." + KEY_ID + " IS NULL"; // not in queue
- String sql = "UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS
- + " SET " + KEY_READ + "=" + FeedItem.NEW
- + " WHERE " + 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(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 " + TABLE_NAME_FEEDS + "\n" +
- "SET " + KEY_HIDE + " = replace(" + KEY_HIDE + ", 'unplayed', 'noplay')");
- db.execSQL("UPDATE " + TABLE_NAME_FEEDS + "\n" +
- "SET " + KEY_HIDE + " = replace(" + KEY_HIDE + ", 'not_queued', 'noqueue')");
- db.execSQL("UPDATE " + TABLE_NAME_FEEDS + "\n" +
- "SET " + KEY_HIDE + " = replace(" + KEY_HIDE + ", 'not_downloaded', 'nodl')");
-
- // Replace played, queued, and downloaded with their opposites
- db.execSQL("UPDATE " + TABLE_NAME_FEEDS + "\n" +
- "SET " + KEY_HIDE + " = replace(" + KEY_HIDE + ", 'played', 'unplayed')");
- db.execSQL("UPDATE " + TABLE_NAME_FEEDS + "\n" +
- "SET " + KEY_HIDE + " = replace(" + KEY_HIDE + ", 'queued', 'not_queued')");
- db.execSQL("UPDATE " + TABLE_NAME_FEEDS + "\n" +
- "SET " + KEY_HIDE + " = replace(" + KEY_HIDE + ", 'downloaded', 'not_downloaded')");
-
- // Now replace intermediates for unplayed, not queued, etc. with their opposites
- db.execSQL("UPDATE " + TABLE_NAME_FEEDS + "\n" +
- "SET " + KEY_HIDE + " = replace(" + KEY_HIDE + ", 'noplay', 'played')");
- db.execSQL("UPDATE " + TABLE_NAME_FEEDS + "\n" +
- "SET " + KEY_HIDE + " = replace(" + KEY_HIDE + ", 'noqueue', 'queued')");
- db.execSQL("UPDATE " + TABLE_NAME_FEEDS + "\n" +
- "SET " + KEY_HIDE + " = replace(" + KEY_HIDE + ", 'nodl', 'downloaded')");
-
- // Paused doesn't have an opposite, so unplayed is the next best option
- db.execSQL("UPDATE " + TABLE_NAME_FEEDS + "\n" +
- "SET " + KEY_HIDE + " = replace(" + 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");
- }
-
+ DBUpgrader.upgrade(db, oldVersion, newVersion);
EventBus.getDefault().post(ProgressEvent.end());
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java
index 670e99fce..18af0800f 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java
@@ -7,7 +7,6 @@ import org.xml.sax.Attributes;
import java.util.concurrent.TimeUnit;
-import de.danoeh.antennapod.core.feed.FeedImage;
import de.danoeh.antennapod.core.syndication.handler.HandlerState;
public class NSITunes extends Namespace {
@@ -16,7 +15,6 @@ public class NSITunes extends Namespace {
public static final String NSURI = "http://www.itunes.com/dtds/podcast-1.0.dtd";
private static final String IMAGE = "image";
- private static final String IMAGE_TITLE = "image";
private static final String IMAGE_HREF = "href";
private static final String AUTHOR = "author";
@@ -29,21 +27,15 @@ public class NSITunes extends Namespace {
public SyndElement handleElementStart(String localName, HandlerState state,
Attributes attributes) {
if (IMAGE.equals(localName)) {
- FeedImage image = new FeedImage();
- image.setTitle(IMAGE_TITLE);
- image.setDownload_url(attributes.getValue(IMAGE_HREF));
+ String url = attributes.getValue(IMAGE_HREF);
if (state.getCurrentItem() != null) {
- // this is an items image
- image.setTitle(state.getCurrentItem().getTitle() + IMAGE_TITLE);
- image.setOwner(state.getCurrentItem());
- state.getCurrentItem().setImage(image);
+ state.getCurrentItem().setImageUrl(url);
} else {
// this is the feed image
// prefer to all other images
- if (!TextUtils.isEmpty(image.getDownload_url())) {
- image.setOwner(state.getFeed());
- state.getFeed().setImage(image);
+ if (!TextUtils.isEmpty(url)) {
+ state.getFeed().setImageUrl(url);
}
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java
index f2cfc2e57..638383223 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java
@@ -7,7 +7,6 @@ import org.xml.sax.Attributes;
import java.util.concurrent.TimeUnit;
-import de.danoeh.antennapod.core.feed.FeedImage;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.syndication.handler.HandlerState;
import de.danoeh.antennapod.core.syndication.namespace.atom.AtomText;
@@ -94,25 +93,16 @@ public class NSMedia extends Namespace {
}
state.getCurrentItem().setMedia(media);
} else if (state.getCurrentItem() != null && url != null && validTypeImage) {
- FeedImage image = new FeedImage();
- image.setDownload_url(url);
- image.setOwner(state.getCurrentItem());
-
- state.getCurrentItem().setImage(image);
+ state.getCurrentItem().setImageUrl(url);
}
} else if (IMAGE.equals(localName)) {
String url = attributes.getValue(IMAGE_URL);
if (url != null) {
- FeedImage image = new FeedImage();
- image.setDownload_url(url);
-
if (state.getCurrentItem() != null) {
- image.setOwner(state.getCurrentItem());
- state.getCurrentItem().setImage(image);
+ state.getCurrentItem().setImageUrl(url);
} else {
- if (state.getFeed().getImage() == null) {
- image.setOwner(state.getFeed());
- state.getFeed().setImage(image);
+ if (state.getFeed().getImageUrl() == null) {
+ state.getFeed().setImageUrl(url);
}
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java
index 3d752df76..a1100a976 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java
@@ -6,7 +6,6 @@ import android.util.Log;
import org.xml.sax.Attributes;
import de.danoeh.antennapod.core.feed.Feed;
-import de.danoeh.antennapod.core.feed.FeedImage;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.syndication.handler.HandlerState;
@@ -77,17 +76,6 @@ public class NSRSS20 extends Namespace {
state.getCurrentItem().setMedia(media);
}
- } else if (IMAGE.equals(localName)) {
- if (state.getTagstack().size() >= 1) {
- String parent = state.getTagstack().peek().getName();
- if (CHANNEL.equals(parent)) {
- Feed feed = state.getFeed();
- if(feed != null && feed.getImage() == null) {
- feed.setImage(new FeedImage());
- feed.getImage().setOwner(state.getFeed());
- }
- }
- }
}
return new SyndElement(localName, this);
}
@@ -134,11 +122,6 @@ public class NSRSS20 extends Namespace {
state.getCurrentItem().setTitle(title);
} else if (CHANNEL.equals(second) && state.getFeed() != null) {
state.getFeed().setTitle(title);
- } else if (IMAGE.equals(second) && CHANNEL.equals(third)) {
- if(state.getFeed() != null && state.getFeed().getImage() != null &&
- state.getFeed().getImage().getTitle() == null) {
- state.getFeed().getImage().setTitle(title);
- }
}
} else if (LINK.equals(top)) {
if (CHANNEL.equals(second) && state.getFeed() != null) {
@@ -150,9 +133,8 @@ public class NSRSS20 extends Namespace {
state.getCurrentItem().setPubDate(DateUtils.parse(content));
} else if (URL.equals(top) && IMAGE.equals(second) && CHANNEL.equals(third)) {
// prefer itunes:image
- if(state.getFeed() != null && state.getFeed().getImage() != null &&
- state.getFeed().getImage().getDownload_url() == null) {
- state.getFeed().getImage().setDownload_url(content);
+ if (state.getFeed() != null) {
+ state.getFeed().setImageUrl(content);
}
} else if (DESCR.equals(localName)) {
if (CHANNEL.equals(second) && state.getFeed() != null) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java
index 1fe388d9d..aab1b1a5b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java
@@ -5,7 +5,6 @@ import android.util.Log;
import org.xml.sax.Attributes;
-import de.danoeh.antennapod.core.feed.FeedImage;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.syndication.handler.HandlerState;
@@ -210,10 +209,10 @@ public class NSAtom extends Namespace {
state.getCurrentItem().setPubDate(DateUtils.parse(content));
} else if (PUBLISHED.equals(top) && ENTRY.equals(second) && state.getCurrentItem() != null) {
state.getCurrentItem().setPubDate(DateUtils.parse(content));
- } else if (IMAGE_LOGO.equals(top) && state.getFeed() != null && state.getFeed().getImage() == null) {
- state.getFeed().setImage(new FeedImage(state.getFeed(), content, null));
+ } else if (IMAGE_LOGO.equals(top) && state.getFeed() != null && state.getFeed().getImageUrl() == null) {
+ state.getFeed().setImageUrl(content);
} else if (IMAGE_ICON.equals(top) && state.getFeed() != null) {
- state.getFeed().setImage(new FeedImage(state.getFeed(), content, null));
+ state.getFeed().setImageUrl(content);
} else if (AUTHOR_NAME.equals(top) && AUTHOR.equals(second) &&
state.getFeed() != null && state.getCurrentItem() == null) {
String currentName = state.getFeed().getAuthor();
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java
index f67367643..03d0f10ff 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/ThemeUtils.java
@@ -1,7 +1,12 @@
package de.danoeh.antennapod.core.util;
+import android.content.Context;
+import android.support.annotation.AttrRes;
+import android.support.annotation.ColorInt;
+import android.support.annotation.ColorRes;
import android.util.Log;
+import android.util.TypedValue;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.preferences.UserPreferences;
@@ -12,6 +17,8 @@ public class ThemeUtils {
int theme = UserPreferences.getTheme();
if (theme == R.style.Theme_AntennaPod_Dark) {
return R.color.selection_background_color_dark;
+ } else if (theme == R.style.Theme_AntennaPod_TrueBlack){
+ return R.color.selection_background_color_trueblack;
} else if (theme == R.style.Theme_AntennaPod_Light) {
return R.color.selection_background_color_light;
} else {
@@ -20,4 +27,10 @@ public class ThemeUtils {
return R.color.selection_background_color_light;
}
}
+
+ public static @ColorInt int getColorFromAttr(Context context, @AttrRes int attr) {
+ TypedValue typedValue = new TypedValue();
+ context.getTheme().resolveAttribute(attr, typedValue, true);
+ return typedValue.data;
+ }
}
diff --git a/core/src/main/res/drawable/progress_bar_horizontal_trueblack.xml b/core/src/main/res/drawable/progress_bar_horizontal_trueblack.xml
new file mode 100644
index 000000000..604bb2655
--- /dev/null
+++ b/core/src/main/res/drawable/progress_bar_horizontal_trueblack.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@android:id/background">
+ <shape>
+ <solid android:color="#000000"/>
+ </shape>
+ </item>
+ <item android:id="@android:id/progress">
+ <clip>
+ <shape>
+ <solid android:color="@color/holo_blue_dark"/>
+ </shape>
+ </clip>
+ </item>
+</layer-list>
diff --git a/core/src/main/res/values-v21/styles.xml b/core/src/main/res/values-v21/styles.xml
index 503337c95..c53000c4f 100644
--- a/core/src/main/res/values-v21/styles.xml
+++ b/core/src/main/res/values-v21/styles.xml
@@ -6,6 +6,19 @@
<style name="Theme.AntennaPod.Dark" parent="Theme.Base.AntennaPod.Dark">
<item name="android:windowContentTransitions">true</item>
</style>
+ <style name="Theme.AntennaPod.TrueBlack" parent="Theme.Base.AntennaPod.TrueBlack">
+ <item name="android:windowContentTransitions">true</item>
+ <item name="android:navigationBarColor">@color/black</item>
+ <item name="android:colorAccent">@color/white</item>
+ <item name="android:colorPrimary">@color/black</item>
+ <item name="android:colorPrimaryDark">@color/black</item>
+ </style>
+ <style name="Theme.AntennaPod.TrueBlack.NoTitle" parent="Theme.Base.AntennaPod.TrueBlack.NoTitle">
+ <item name="android:navigationBarColor">@color/black</item>
+ <item name="android:colorAccent">@color/white</item>
+ <item name="android:colorPrimary">@color/black</item>
+ <item name="android:colorPrimaryDark">@color/black</item>
+ </style>
<style name="Widget.AntennaPod.Button" parent="Widget.AppCompat.Button">
<item name="textAllCaps">true</item>
diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml
index 758abcea3..d9009d9d5 100644
--- a/core/src/main/res/values/arrays.xml
+++ b/core/src/main/res/values/arrays.xml
@@ -137,10 +137,12 @@
<string-array name="theme_options">
<item>@string/pref_theme_title_light</item>
<item>@string/pref_theme_title_dark</item>
+ <item>@string/pref_theme_title_trueblack</item>
</string-array>
<string-array name="theme_values">
<item>0</item>
<item>1</item>
+ <item>2</item>
</string-array>
<string-array name="nav_drawer_titles">
diff --git a/core/src/main/res/values/attrs.xml b/core/src/main/res/values/attrs.xml
index b005d4dc3..f3c2b9b7e 100644
--- a/core/src/main/res/values/attrs.xml
+++ b/core/src/main/res/values/attrs.xml
@@ -56,6 +56,7 @@
<attr name="ic_cast_disconnect" format="reference"/>
<attr name="ic_swap" format="reference"/>
<attr name="master_switch_background" format="color"/>
+ <attr name="currently_playing_background" format="color"/>
<!-- Used in itemdescription -->
<attr name="non_transparent_background" format="reference"/>
diff --git a/core/src/main/res/values/colors.xml b/core/src/main/res/values/colors.xml
index c9a5b3d6a..37ad81639 100644
--- a/core/src/main/res/values/colors.xml
+++ b/core/src/main/res/values/colors.xml
@@ -22,6 +22,7 @@
<color name="image_readability_tint">#80000000</color>
<color name="feed_image_bg">#50000000</color>
+ <color name="selection_background_color_trueblack">#286E8A</color>
<color name="selection_background_color_dark">#286E8A</color>
<color name="selection_background_color_light">#81CFEA</color>
@@ -30,6 +31,7 @@
<color name="highlight_light">#DDDDDD</color>
<color name="highlight_dark">#414141</color>
+ <color name="highlight_trueblack">#000000</color>
<color name="antennapod_blue">#147BAF</color>
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index f24c23b96..6312a5bbd 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -395,6 +395,7 @@
<string name="pref_episode_cache_title">Episode Cache</string>
<string name="pref_theme_title_light">Light</string>
<string name="pref_theme_title_dark">Dark</string>
+ <string name="pref_theme_title_trueblack">True Black</string>
<string name="pref_episode_cache_unlimited">Unlimited</string>
<string name="pref_update_interval_hours_plural">hours</string>
<string name="pref_update_interval_hours_singular">hour</string>
diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml
index 3a215588e..0314ca431 100644
--- a/core/src/main/res/values/styles.xml
+++ b/core/src/main/res/values/styles.xml
@@ -67,6 +67,7 @@
<item type="attr" name="ic_create_new_folder">@drawable/ic_create_new_folder_grey600_24dp</item>
<item type="attr" name="ic_cast_disconnect">@drawable/ic_cast_disconnect_grey600_36dp</item>
<item type="attr" name="master_switch_background">@color/master_switch_background_light</item>
+ <item type="attr" name="currently_playing_background">@color/highlight_light</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
</style>
@@ -136,9 +137,31 @@
<item type="attr" name="ic_create_new_folder">@drawable/ic_create_new_folder_white_24dp</item>
<item type="attr" name="ic_cast_disconnect">@drawable/ic_cast_disconnect_white_36dp</item>
<item type="attr" name="master_switch_background">@color/master_switch_background_dark</item>
+ <item type="attr" name="currently_playing_background">@color/highlight_dark</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
</style>
+ <style name="Theme.AntennaPod.TrueBlack" parent="Theme.Base.AntennaPod.TrueBlack">
+ <!-- Room for API dependent attributes -->
+ </style>
+
+ <style name="Theme.Base.AntennaPod.TrueBlack" parent="Theme.Base.AntennaPod.Dark">
+ <item name="progressBarTheme">@style/ProgressBarTrueBlack</item>
+ <item type="attr" name="non_transparent_background">@color/black</item>
+ <item type="attr" name="overlay_background">@color/overlay_dark</item>
+ <item type="attr" name="overlay_drawable">@drawable/overlay_drawable_dark</item>
+ <item type="attr" name="dragview_background">@drawable/ic_drag_vertical_white_48dp</item>
+ <item type="attr" name="dragview_float_background">@color/black</item>
+ <item type="attr" name="nav_drawer_background">@color/black</item>
+ <item name="android:textColorPrimary">@color/white</item>
+ <item name="android:color">@color/white</item>
+ <item name="android:windowBackground">@color/black</item>
+ <item name="android:actionBarStyle">@color/black</item>
+ <item name="colorPrimary">@color/black</item>
+ <item name="colorPrimaryDark">@color/black</item>
+ </style>
+
+
<style name="Theme.AntennaPod.Light.NoTitle" parent="Theme.Base.AntennaPod.Light.NoTitle">
<!-- Room for API dependent attributes -->
</style>
@@ -206,6 +229,7 @@
<item type="attr" name="ic_create_new_folder">@drawable/ic_create_new_folder_grey600_24dp</item>
<item type="attr" name="ic_cast_disconnect">@drawable/ic_cast_disconnect_grey600_36dp</item>
<item type="attr" name="master_switch_background">@color/master_switch_background_light</item>
+ <item type="attr" name="currently_playing_background">@color/highlight_light</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
</style>
@@ -276,9 +300,32 @@
<item type="attr" name="ic_create_new_folder">@drawable/ic_create_new_folder_white_24dp</item>
<item type="attr" name="ic_cast_disconnect">@drawable/ic_cast_disconnect_white_36dp</item>
<item type="attr" name="master_switch_background">@color/master_switch_background_dark</item>
+ <item type="attr" name="currently_playing_background">@color/highlight_dark</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
</style>
+ <style name="Theme.AntennaPod.TrueBlack.NoTitle" parent="Theme.Base.AntennaPod.TrueBlack.NoTitle">
+ <!-- Room for API dependent attributes -->
+ </style>
+
+ <style name="Theme.Base.AntennaPod.TrueBlack.NoTitle" parent="Theme.Base.AntennaPod.Dark.NoTitle">
+ <item name="progressBarTheme">@style/ProgressBarTrueBlack</item>
+ <item type="attr" name="non_transparent_background">@color/black</item>
+ <item type="attr" name="overlay_background">@color/black</item>
+ <item type="attr" name="overlay_drawable">@drawable/overlay_drawable_dark</item>
+ <item type="attr" name="dragview_background">@drawable/ic_drag_vertical_white_48dp</item>
+ <item type="attr" name="dragview_float_background">@color/black</item>
+ <item type="attr" name="nav_drawer_background">@color/black</item>
+ <item type="attr" name="currently_playing_background">@color/highlight_trueblack</item>
+ <item name="android:textColorPrimary">@color/white</item>
+ <item name="android:color">@color/white</item>
+ <item name="android:windowBackground">@color/black</item>
+ <item name="android:actionBarStyle">@color/black</item>
+ <item name="colorPrimary">@color/black</item>
+ <item name="colorPrimaryDark">@color/black</item>
+ </style>
+
+
<style name="Theme.AntennaPod.Dark.Splash" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowBackground">@drawable/bg_splash</item>
</style>
@@ -366,4 +413,9 @@
<item name="android:progressDrawable">@drawable/progress_bar_horizontal_dark</item>
</style>
+ <style name="ProgressBarTrueBlack">
+ <item name="android:indeterminateOnly">false</item>
+ <item name="android:progressDrawable">@drawable/progress_bar_horizontal_trueblack</item>
+ </style>
+
</resources>
diff --git a/core/src/play/java/de/danoeh/antennapod/core/cast/CastUtils.java b/core/src/play/java/de/danoeh/antennapod/core/cast/CastUtils.java
index f0a7214c9..aec559a5f 100644
--- a/core/src/play/java/de/danoeh/antennapod/core/cast/CastUtils.java
+++ b/core/src/play/java/de/danoeh/antennapod/core/cast/CastUtils.java
@@ -13,7 +13,6 @@ import java.util.Calendar;
import java.util.List;
import de.danoeh.antennapod.core.feed.Feed;
-import de.danoeh.antennapod.core.feed.FeedImage;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.storage.DBReader;
@@ -97,9 +96,9 @@ public class CastUtils {
if (subtitle != null) {
metadata.putString(MediaMetadata.KEY_SUBTITLE, subtitle);
}
- FeedImage image = feedItem.getImage();
- if (image != null && !TextUtils.isEmpty(image.getDownload_url())) {
- metadata.addImage(new WebImage(Uri.parse(image.getDownload_url())));
+
+ if (!TextUtils.isEmpty(feedItem.getImageUrl())) {
+ metadata.addImage(new WebImage(Uri.parse(feedItem.getImageUrl())));
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(media.getItem().getPubDate());
diff --git a/core/src/test/java/android/text/TextUtils.java b/core/src/test/java/android/text/TextUtils.java
new file mode 100644
index 000000000..c31234171
--- /dev/null
+++ b/core/src/test/java/android/text/TextUtils.java
@@ -0,0 +1,32 @@
+package android.text;
+
+/**
+ * A slim-down version of standard {@link android.text.TextUtils} to be used in unit tests.
+ */
+public class TextUtils {
+
+ /**
+ * Returns true if a and b are equal, including if they are both null.
+ * <p><i>Note: In platform versions 1.1 and earlier, this method only worked well if
+ * both the arguments were instances of String.</i></p>
+ * @param a first CharSequence to check
+ * @param b second CharSequence to check
+ * @return true if a and b are equal
+ */
+ public static boolean equals(CharSequence a, CharSequence b) {
+ if (a == b) return true;
+ int length;
+ if (a != null && b != null && (length = a.length()) == b.length()) {
+ if (a instanceof String && b instanceof String) {
+ return a.equals(b);
+ } else {
+ for (int i = 0; i < length; i++) {
+ if (a.charAt(i) != b.charAt(i)) return false;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/core/src/test/java/android/util/Log.java b/core/src/test/java/android/util/Log.java
new file mode 100644
index 000000000..881d10209
--- /dev/null
+++ b/core/src/test/java/android/util/Log.java
@@ -0,0 +1,245 @@
+package android.util;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * A stub for {@link android.util.Log} to be used in unit tests.
+ *
+ * It outputs the log statements to standard error.
+ */
+public final class Log {
+
+ /**
+ * Priority constant for the println method; use Log.v.
+ */
+ public static final int VERBOSE = 2;
+
+ /**
+ * Priority constant for the println method; use Log.d.
+ */
+ public static final int DEBUG = 3;
+
+ /**
+ * Priority constant for the println method; use Log.i.
+ */
+ public static final int INFO = 4;
+
+ /**
+ * Priority constant for the println method; use Log.w.
+ */
+ public static final int WARN = 5;
+
+ /**
+ * Priority constant for the println method; use Log.e.
+ */
+ public static final int ERROR = 6;
+
+ /**
+ * Priority constant for the println method.
+ */
+ public static final int ASSERT = 7;
+
+ private Log() {
+ }
+
+ /**
+ * Send a {@link #VERBOSE} log message.
+ * @param tag Used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg The message you would like logged.
+ */
+ public static int v(String tag, String msg) {
+ return println_native(LOG_ID_MAIN, VERBOSE, tag, msg);
+ }
+
+ /**
+ * Send a {@link #VERBOSE} log message and log the exception.
+ * @param tag Used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg The message you would like logged.
+ * @param tr An exception to log
+ */
+ public static int v(String tag, String msg, Throwable tr) {
+ return printlns(LOG_ID_MAIN, VERBOSE, tag, msg, tr);
+ }
+
+ /**
+ * Send a {@link #DEBUG} log message.
+ * @param tag Used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg The message you would like logged.
+ */
+ public static int d(String tag, String msg) {
+ return println_native(LOG_ID_MAIN, DEBUG, tag, msg);
+ }
+
+ /**
+ * Send a {@link #DEBUG} log message and log the exception.
+ * @param tag Used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg The message you would like logged.
+ * @param tr An exception to log
+ */
+ public static int d(String tag, String msg, Throwable tr) {
+ return printlns(LOG_ID_MAIN, DEBUG, tag, msg, tr);
+ }
+
+ /**
+ * Send an {@link #INFO} log message.
+ * @param tag Used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg The message you would like logged.
+ */
+ public static int i(String tag, String msg) {
+ return println_native(LOG_ID_MAIN, INFO, tag, msg);
+ }
+
+ /**
+ * Send a {@link #INFO} log message and log the exception.
+ * @param tag Used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg The message you would like logged.
+ * @param tr An exception to log
+ */
+ public static int i(String tag, String msg, Throwable tr) {
+ return printlns(LOG_ID_MAIN, INFO, tag, msg, tr);
+ }
+
+ /**
+ * Send a {@link #WARN} log message.
+ * @param tag Used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg The message you would like logged.
+ */
+ public static int w(String tag, String msg) {
+ return println_native(LOG_ID_MAIN, WARN, tag, msg);
+ }
+
+ /**
+ * Send a {@link #WARN} log message and log the exception.
+ * @param tag Used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg The message you would like logged.
+ * @param tr An exception to log
+ */
+ public static int w(String tag, String msg, Throwable tr) {
+ return printlns(LOG_ID_MAIN, WARN, tag, msg, tr);
+ }
+
+ /**
+ * Checks to see whether or not a log for the specified tag is loggable at the specified level.
+ *
+ * @return true in all cases (for unit test environment)
+ */
+ public static boolean isLoggable(String tag, int level) {
+ return true;
+ }
+
+ /*
+ * Send a {@link #WARN} log message and log the exception.
+ * @param tag Used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param tr An exception to log
+ */
+ public static int w(String tag, Throwable tr) {
+ return printlns(LOG_ID_MAIN, WARN, tag, "", tr);
+ }
+
+ /**
+ * Send an {@link #ERROR} log message.
+ * @param tag Used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg The message you would like logged.
+ */
+ public static int e(String tag, String msg) {
+ return println_native(LOG_ID_MAIN, ERROR, tag, msg);
+ }
+
+ /**
+ * Send a {@link #ERROR} log message and log the exception.
+ * @param tag Used to identify the source of a log message. It usually identifies
+ * the class or activity where the log call occurs.
+ * @param msg The message you would like logged.
+ * @param tr An exception to log
+ */
+ public static int e(String tag, String msg, Throwable tr) {
+ return printlns(LOG_ID_MAIN, ERROR, tag, msg, tr);
+ }
+
+ /**
+ * What a Terrible Failure: Report a condition that should never happen.
+ * The error will always be logged at level ASSERT with the call stack.
+ * Depending on system configuration, a report may be added to the
+ * {@link android.os.DropBoxManager} and/or the process may be terminated
+ * immediately with an error dialog.
+ * @param tag Used to identify the source of a log message.
+ * @param msg The message you would like logged.
+ */
+ public static int wtf(String tag, String msg) {
+ return wtf(LOG_ID_MAIN, tag, msg, null, false, false);
+ }
+
+ /**
+ * Like {@link #wtf(String, String)}, but also writes to the log the full
+ * call stack.
+ * @hide
+ */
+ public static int wtfStack(String tag, String msg) {
+ return wtf(LOG_ID_MAIN, tag, msg, null, true, false);
+ }
+
+ /**
+ * What a Terrible Failure: Report an exception that should never happen.
+ * Similar to {@link #wtf(String, String)}, with an exception to log.
+ * @param tag Used to identify the source of a log message.
+ * @param tr An exception to log.
+ */
+ public static int wtf(String tag, Throwable tr) {
+ return wtf(LOG_ID_MAIN, tag, tr.getMessage(), tr, false, false);
+ }
+
+ /**
+ * What a Terrible Failure: Report an exception that should never happen.
+ * Similar to {@link #wtf(String, Throwable)}, with a message as well.
+ * @param tag Used to identify the source of a log message.
+ * @param msg The message you would like logged.
+ * @param tr An exception to log. May be null.
+ */
+ public static int wtf(String tag, String msg, Throwable tr) {
+ return wtf(LOG_ID_MAIN, tag, msg, tr, false, false);
+ }
+
+ /**
+ * Priority Constant for wtf.
+ * Added for this custom Log implementation, not in android sources.
+ */
+ private static final int WTF = 8;
+ static int wtf(int logId, String tag, String msg, Throwable tr, boolean localStack,
+ boolean system) {
+ return printlns(LOG_ID_MAIN, WTF, tag, msg, tr);
+ }
+
+ private static final int LOG_ID_MAIN = 0;
+
+ private static final String[] PRIORITY_ABBREV = { "0", "1", "V", "D", "I", "W", "E", "A", "WTF" };
+
+ private static int println_native(int bufID, int priority, String tag, String msg) {
+ String res = PRIORITY_ABBREV[priority] + "/" + tag + " " + msg + System.lineSeparator();
+ System.err.print(res);
+ return res.length();
+ }
+
+ private static int printlns(int bufID, int priority, String tag, String msg,
+ Throwable tr) {
+ StringWriter trSW = new StringWriter();
+ if (tr != null) {
+ trSW.append(" , Exception: ");
+ PrintWriter trPW = new PrintWriter(trSW);
+ tr.printStackTrace(trPW);
+ trPW.flush();
+ }
+ return println_native(bufID, priority, tag, msg + trSW.toString());
+ }
+
+}
diff --git a/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedItemMother.java b/core/src/test/java/de/danoeh/antennapod/core/feed/FeedItemMother.java
index 3d7c4fe5f..b78cecc23 100644
--- a/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedItemMother.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/feed/FeedItemMother.java
@@ -2,14 +2,14 @@ package de.danoeh.antennapod.core.feed;
import java.util.Date;
-import static de.danoeh.antennapod.core.feed.FeedImageMother.anyFeedImage;
import static de.danoeh.antennapod.core.feed.FeedMother.anyFeed;
class FeedItemMother {
+ private static final String IMAGE_URL = "http://example.com/image";
static FeedItem anyFeedItemWithImage() {
FeedItem item = new FeedItem(0, "Item", "Item", "url", new Date(), FeedItem.PLAYED, anyFeed());
- item.setImage(anyFeedImage());
+ item.setImageUrl(IMAGE_URL);
return item;
}
diff --git a/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedItemTest.java b/core/src/test/java/de/danoeh/antennapod/core/feed/FeedItemTest.java
index 9e12e8ae0..e36a09f00 100644
--- a/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedItemTest.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/feed/FeedItemTest.java
@@ -1,65 +1,60 @@
package de.danoeh.antennapod.core.feed;
-import android.test.AndroidTestCase;
+import org.junit.Before;
+import org.junit.Test;
import static de.danoeh.antennapod.core.feed.FeedItemMother.anyFeedItemWithImage;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
-public class FeedItemTest extends AndroidTestCase {
+public class FeedItemTest {
private FeedItem original;
- private FeedImage originalImage;
private FeedItem changedFeedItem;
- @Override
- protected void setUp() {
+ @Before
+ public void setUp() {
original = anyFeedItemWithImage();
- originalImage = original.getImage();
changedFeedItem = anyFeedItemWithImage();
}
+ @Test
public void testUpdateFromOther_feedItemImageDownloadUrlChanged() throws Exception {
setNewFeedItemImageDownloadUrl();
-
original.updateFromOther(changedFeedItem);
-
- feedItemImageWasUpdated();
+ assertFeedItemImageWasUpdated();
}
+ @Test
public void testUpdateFromOther_feedItemImageRemoved() throws Exception {
feedItemImageRemoved();
-
original.updateFromOther(changedFeedItem);
-
- feedItemImageWasNotUpdated();
+ assertFeedItemImageWasNotUpdated();
}
+ @Test
public void testUpdateFromOther_feedItemImageAdded() throws Exception {
- feedItemHadNoImage();
+ original.setImageUrl(null);
setNewFeedItemImageDownloadUrl();
-
original.updateFromOther(changedFeedItem);
-
- feedItemImageWasUpdated();
- }
-
- private void feedItemHadNoImage() {
- original.setImage(null);
+ assertFeedItemImageWasUpdated();
}
private void setNewFeedItemImageDownloadUrl() {
- changedFeedItem.getImage().setDownload_url("http://example.com/new_picture");
+ changedFeedItem.setImageUrl("http://example.com/new_picture");
}
private void feedItemImageRemoved() {
- changedFeedItem.setImage(null);
+ changedFeedItem.setImageUrl(null);
}
- private void feedItemImageWasUpdated() {
- assertEquals(original.getImage().getDownload_url(), changedFeedItem.getImage().getDownload_url());
+ private void assertFeedItemImageWasUpdated() {
+ assertEquals(original.getImageUrl(), changedFeedItem.getImageUrl());
}
- private void feedItemImageWasNotUpdated() {
- assertTrue(originalImage == original.getImage());
+ private void assertFeedItemImageWasNotUpdated() {
+ assertEquals(anyFeedItemWithImage().getImageUrl(), original.getImageUrl());
}
} \ No newline at end of file
diff --git a/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedMother.java b/core/src/test/java/de/danoeh/antennapod/core/feed/FeedMother.java
index fecc8e377..f46797d28 100644
--- a/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedMother.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/feed/FeedMother.java
@@ -1,13 +1,11 @@
package de.danoeh.antennapod.core.feed;
-import static de.danoeh.antennapod.core.feed.FeedImageMother.anyFeedImage;
-
class FeedMother {
+ public static final String IMAGE_URL = "http://example.com/image";
public static Feed anyFeed() {
- FeedImage image = anyFeedImage();
return new Feed(0, null, "title", "http://example.com", "This is the description",
- "http://example.com/payment", "Daniel", "en", null, "http://example.com/feed", image,
+ "http://example.com/payment", "Daniel", "en", null, "http://example.com/feed", IMAGE_URL,
null, "http://example.com/feed", true);
}
diff --git a/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedTest.java b/core/src/test/java/de/danoeh/antennapod/core/feed/FeedTest.java
index 8067ec93f..4717041f4 100644
--- a/core/src/androidTest/java/de/danoeh/antennapod/core/feed/FeedTest.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/feed/FeedTest.java
@@ -1,63 +1,61 @@
package de.danoeh.antennapod.core.feed;
-import android.test.AndroidTestCase;
+import org.junit.Before;
+import org.junit.Test;
-import static de.danoeh.antennapod.core.feed.FeedImageMother.anyFeedImage;
import static de.danoeh.antennapod.core.feed.FeedMother.anyFeed;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
-public class FeedTest extends AndroidTestCase {
+public class FeedTest {
private Feed original;
- private FeedImage originalImage;
private Feed changedFeed;
- @Override
- protected void setUp() {
+ @Before
+ public void setUp() {
original = anyFeed();
- originalImage = original.getImage();
changedFeed = anyFeed();
}
+ @Test
public void testCompareWithOther_feedImageDownloadUrlChanged() throws Exception {
setNewFeedImageDownloadUrl();
-
feedHasChanged();
}
+ @Test
public void testCompareWithOther_sameFeedImage() throws Exception {
- changedFeed.setImage(anyFeedImage());
-
+ changedFeed.setImageUrl(FeedMother.IMAGE_URL);
feedHasNotChanged();
}
+ @Test
public void testCompareWithOther_feedImageRemoved() throws Exception {
feedImageRemoved();
-
feedHasNotChanged();
}
+ @Test
public void testUpdateFromOther_feedImageDownloadUrlChanged() throws Exception {
setNewFeedImageDownloadUrl();
-
original.updateFromOther(changedFeed);
-
feedImageWasUpdated();
}
+ @Test
public void testUpdateFromOther_feedImageRemoved() throws Exception {
feedImageRemoved();
-
original.updateFromOther(changedFeed);
-
feedImageWasNotUpdated();
}
+ @Test
public void testUpdateFromOther_feedImageAdded() throws Exception {
feedHadNoImage();
setNewFeedImageDownloadUrl();
-
original.updateFromOther(changedFeed);
-
feedImageWasUpdated();
}
@@ -66,11 +64,11 @@ public class FeedTest extends AndroidTestCase {
}
private void feedHadNoImage() {
- original.setImage(null);
+ original.setImageUrl(null);
}
private void setNewFeedImageDownloadUrl() {
- changedFeed.getImage().setDownload_url("http://example.com/new_picture");
+ changedFeed.setImageUrl("http://example.com/new_picture");
}
private void feedHasChanged() {
@@ -78,15 +76,15 @@ public class FeedTest extends AndroidTestCase {
}
private void feedImageRemoved() {
- changedFeed.setImage(null);
+ changedFeed.setImageUrl(null);
}
private void feedImageWasUpdated() {
- assertEquals(original.getImage().getDownload_url(), changedFeed.getImage().getDownload_url());
+ assertEquals(original.getImageUrl(), changedFeed.getImageUrl());
}
private void feedImageWasNotUpdated() {
- assertTrue(originalImage == original.getImage());
+ assertEquals(anyFeed().getImageUrl(), original.getImageUrl());
}
} \ No newline at end of file
diff --git a/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/LongLongMapTest.java b/core/src/test/java/de/danoeh/antennapod/core/util/LongLongMapTest.java
index 50c2a9c3c..0ed77eb9f 100644
--- a/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/LongLongMapTest.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/util/LongLongMapTest.java
@@ -1,11 +1,12 @@
-package de.danoeh.antennapod.core.tests.util;
+package de.danoeh.antennapod.core.util;
-import android.test.AndroidTestCase;
+import org.junit.Test;
-import de.danoeh.antennapod.core.util.LongIntMap;
+import static org.junit.Assert.assertEquals;
-public class LongLongMapTest extends AndroidTestCase {
+public class LongLongMapTest {
+ @Test
public void testEmptyMap() {
LongIntMap map = new LongIntMap();
assertEquals(0, map.size());
@@ -18,6 +19,7 @@ public class LongLongMapTest extends AndroidTestCase {
assertEquals(1, map.hashCode());
}
+ @Test
public void testSingleElement() {
LongIntMap map = new LongIntMap();
map.put(17, 42);
@@ -30,6 +32,7 @@ public class LongLongMapTest extends AndroidTestCase {
assertEquals(true, map.delete(17));
}
+ @Test
public void testAddAndDelete() {
LongIntMap map = new LongIntMap();
for(int i=0; i < 100; i++) {
@@ -46,6 +49,7 @@ public class LongLongMapTest extends AndroidTestCase {
}
}
+ @Test
public void testOverwrite() {
LongIntMap map = new LongIntMap();
map.put(17, 42);