diff options
author | ByteHamster <info@bytehamster.com> | 2018-06-08 20:14:57 +0200 |
---|---|---|
committer | ByteHamster <info@bytehamster.com> | 2018-06-08 20:14:57 +0200 |
commit | 83a9df26579394697c5f930d37db117cde620c9c (patch) | |
tree | a3d66dc5a4b63d9e3d1f6f7549005636d6cf31dc /core | |
parent | 920f0613857f468804114fcd85da8733b71db9bd (diff) | |
parent | f0151501a5195bf3c2dbd50336c51005e629196f (diff) | |
download | AntennaPod-83a9df26579394697c5f930d37db117cde620c9c.zip |
Merge branch 'develop' into exo-player
Diffstat (limited to 'core')
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); |