summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordaniel oeh <daniel.oeh@gmail.com>2014-03-19 20:27:12 +0100
committerdaniel oeh <daniel.oeh@gmail.com>2014-03-19 21:05:15 +0100
commite8b9e49ee9527f4e533c08cb7ac39d1dc8a19b6b (patch)
tree84387048022e9c9453f0ec53daec029219e529ff
parentb9ab10253ab04bacd7d27ab7a7aecd561f7efbc2 (diff)
downloadAntennaPod-e8b9e49ee9527f4e533c08cb7ac39d1dc8a19b6b.zip
Added support for images in itunes:image tags.
-rw-r--r--src/de/danoeh/antennapod/feed/Chapter.java4
-rw-r--r--src/de/danoeh/antennapod/feed/FeedComponent.java11
-rw-r--r--src/de/danoeh/antennapod/feed/FeedFile.java10
-rw-r--r--src/de/danoeh/antennapod/feed/FeedImage.java14
-rw-r--r--src/de/danoeh/antennapod/feed/FeedItem.java85
-rw-r--r--src/de/danoeh/antennapod/feed/FeedMedia.java26
-rw-r--r--src/de/danoeh/antennapod/service/download/DownloadService.java50
-rw-r--r--src/de/danoeh/antennapod/service/download/HttpDownloader.java20
-rw-r--r--src/de/danoeh/antennapod/storage/DBReader.java11
-rw-r--r--src/de/danoeh/antennapod/storage/DBWriter.java10
-rw-r--r--src/de/danoeh/antennapod/storage/DownloadRequester.java6
-rw-r--r--src/de/danoeh/antennapod/storage/PodDBAdapter.java30
-rw-r--r--src/de/danoeh/antennapod/syndication/namespace/NSITunes.java77
-rw-r--r--src/instrumentationTest/de/test/antennapod/AntennaPodTestRunner.java3
-rw-r--r--src/instrumentationTest/de/test/antennapod/storage/DBWriterTest.java78
15 files changed, 316 insertions, 119 deletions
diff --git a/src/de/danoeh/antennapod/feed/Chapter.java b/src/de/danoeh/antennapod/feed/Chapter.java
index ebf8ed44f..d6151ee9f 100644
--- a/src/de/danoeh/antennapod/feed/Chapter.java
+++ b/src/de/danoeh/antennapod/feed/Chapter.java
@@ -48,4 +48,8 @@ public abstract class Chapter extends FeedComponent {
this.link = link;
}
+ @Override
+ public String getHumanReadableIdentifier() {
+ return title;
+ }
}
diff --git a/src/de/danoeh/antennapod/feed/FeedComponent.java b/src/de/danoeh/antennapod/feed/FeedComponent.java
index d23c8d7c8..66a2f9cc5 100644
--- a/src/de/danoeh/antennapod/feed/FeedComponent.java
+++ b/src/de/danoeh/antennapod/feed/FeedComponent.java
@@ -5,7 +5,7 @@ package de.danoeh.antennapod.feed;
* @author daniel
*
*/
-public class FeedComponent {
+public abstract class FeedComponent {
protected long id;
@@ -39,7 +39,12 @@ public class FeedComponent {
public boolean compareWithOther(FeedComponent other) {
return false;
}
-
-
+
+
+ /**
+ * Should return a non-null, human-readable String so that the item can be
+ * identified by the user. Can be title, download-url, etc.
+ */
+ public abstract String getHumanReadableIdentifier();
} \ No newline at end of file
diff --git a/src/de/danoeh/antennapod/feed/FeedFile.java b/src/de/danoeh/antennapod/feed/FeedFile.java
index 1d7a135d4..28a9b1e10 100644
--- a/src/de/danoeh/antennapod/feed/FeedFile.java
+++ b/src/de/danoeh/antennapod/feed/FeedFile.java
@@ -17,14 +17,8 @@ public abstract class FeedFile extends FeedComponent {
}
public FeedFile() {
- this(null, null, false);
- }
-
- /**
- * Should return a non-null, human-readable String so that the item can be
- * identified by the user. Can be title, download-url, etc.
- */
- public abstract String getHumanReadableIdentifier();
+ this(null, null, false);
+ }
public abstract int getTypeAsInt();
diff --git a/src/de/danoeh/antennapod/feed/FeedImage.java b/src/de/danoeh/antennapod/feed/FeedImage.java
index 3cc99d1c2..c50ea8514 100644
--- a/src/de/danoeh/antennapod/feed/FeedImage.java
+++ b/src/de/danoeh/antennapod/feed/FeedImage.java
@@ -16,7 +16,7 @@ public class FeedImage extends FeedFile implements
public static final int FEEDFILETYPE_FEEDIMAGE = 1;
protected String title;
- protected Feed feed;
+ protected FeedComponent owner;
public FeedImage(String download_url, String title) {
super(null, download_url, false);
@@ -33,8 +33,8 @@ public class FeedImage extends FeedFile implements
@Override
public String getHumanReadableIdentifier() {
- if (feed != null && feed.getTitle() != null) {
- return feed.getTitle();
+ if (owner != null && owner.getHumanReadableIdentifier() != null) {
+ return owner.getHumanReadableIdentifier();
} else {
return download_url;
}
@@ -57,12 +57,12 @@ public class FeedImage extends FeedFile implements
this.title = title;
}
- public Feed getFeed() {
- return feed;
+ public FeedComponent getOwner() {
+ return owner;
}
- public void setFeed(Feed feed) {
- this.feed = feed;
+ public void setOwner(FeedComponent owner) {
+ this.owner = owner;
}
@Override
diff --git a/src/de/danoeh/antennapod/feed/FeedItem.java b/src/de/danoeh/antennapod/feed/FeedItem.java
index f63b5beb4..0d46cef48 100644
--- a/src/de/danoeh/antennapod/feed/FeedItem.java
+++ b/src/de/danoeh/antennapod/feed/FeedItem.java
@@ -1,17 +1,17 @@
package de.danoeh.antennapod.feed;
-import java.io.InputStream;
-import java.lang.ref.SoftReference;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.Callable;
-
import de.danoeh.antennapod.PodcastApp;
import de.danoeh.antennapod.asynctask.ImageLoader;
import de.danoeh.antennapod.storage.DBReader;
import de.danoeh.antennapod.util.ShownotesProvider;
import de.danoeh.antennapod.util.flattr.FlattrStatus;
import de.danoeh.antennapod.util.flattr.FlattrThing;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.InputStream;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.Callable;
/**
* Data Object for a XML message
@@ -44,17 +44,18 @@ public class FeedItem extends FeedComponent implements
private boolean read;
private String paymentLink;
- private FlattrStatus flattrStatus;
+ private FlattrStatus flattrStatus;
private List<Chapter> chapters;
+ private FeedImage image;
public FeedItem() {
this.read = true;
- this.flattrStatus = new FlattrStatus();
+ this.flattrStatus = new FlattrStatus();
}
/**
* This constructor should be used for creating test objects.
- * */
+ */
public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, boolean read, Feed feed) {
this.id = id;
this.title = title;
@@ -63,7 +64,7 @@ public class FeedItem extends FeedComponent implements
this.pubDate = (pubDate != null) ? (Date) pubDate.clone() : null;
this.read = read;
this.feed = feed;
- this.flattrStatus = new FlattrStatus();
+ this.flattrStatus = new FlattrStatus();
}
public void updateFromOther(FeedItem other) {
@@ -98,6 +99,9 @@ public class FeedItem extends FeedComponent implements
chapters = other.chapters;
}
}
+ if (image == null) {
+ image = other.image;
+ }
}
/**
@@ -164,7 +168,7 @@ public class FeedItem extends FeedComponent implements
* Sets the media object of this FeedItem. If the given
* FeedMedia object is not null, it's 'item'-attribute value
* will also be set to this item.
- * */
+ */
public void setMedia(FeedMedia media) {
this.media = media;
if (media != null && media.getItem() != this) {
@@ -200,15 +204,15 @@ public class FeedItem extends FeedComponent implements
this.contentEncoded = contentEncoded;
}
- public void setFlattrStatus(FlattrStatus status) {
- this.flattrStatus = status;
- }
+ public void setFlattrStatus(FlattrStatus status) {
+ this.flattrStatus = status;
+ }
- public FlattrStatus getFlattrStatus() {
- return flattrStatus;
- }
+ public FlattrStatus getFlattrStatus() {
+ return flattrStatus;
+ }
- public String getPaymentLink() {
+ public String getPaymentLink() {
return paymentLink;
}
@@ -277,10 +281,11 @@ public class FeedItem extends FeedComponent implements
@Override
public InputStream openImageInputStream() {
InputStream out = null;
- if (hasMedia()) {
+ if (hasItemImage()) {
+ out = image.openImageInputStream();
+ } else if (hasMedia()) {
out = media.openImageInputStream();
- }
- if (out == null && feed.getImage() != null) {
+ } else if (feed.getImage() != null) {
out = feed.getImage().openImageInputStream();
}
return out;
@@ -289,10 +294,11 @@ public class FeedItem extends FeedComponent implements
@Override
public InputStream reopenImageInputStream(InputStream input) {
InputStream out = null;
- if (hasMedia()) {
+ if (hasItemImage()) {
+ out = image.reopenImageInputStream(input);
+ } else if (hasMedia()) {
out = media.reopenImageInputStream(input);
- }
- if (out == null && feed.getImage() != null) {
+ } else if (feed.getImage() != null) {
out = feed.getImage().reopenImageInputStream(input);
}
return out;
@@ -301,10 +307,11 @@ public class FeedItem extends FeedComponent implements
@Override
public String getImageLoaderCacheKey() {
String out = null;
- if (hasMedia()) {
+ if (hasItemImage()) {
+ out = image.getImageLoaderCacheKey();
+ } else if (hasMedia()) {
out = media.getImageLoaderCacheKey();
- }
- if (out == null && feed.getImage() != null) {
+ } else if (feed.getImage() != null) {
out = feed.getImage().getImageLoaderCacheKey();
}
return out;
@@ -318,4 +325,28 @@ public class FeedItem extends FeedComponent implements
this.feedId = feedId;
}
+ /**
+ * 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;
+ image.setOwner(this);
+ }
+
+ /**
+ * Returns true if this FeedItem has its own image, false otherwise.
+ */
+ public boolean hasItemImage() {
+ return image != null;
+ }
+
+ @Override
+ public String getHumanReadableIdentifier() {
+ return title;
+ }
}
diff --git a/src/de/danoeh/antennapod/feed/FeedMedia.java b/src/de/danoeh/antennapod/feed/FeedMedia.java
index fe2c3d17e..f38e92398 100644
--- a/src/de/danoeh/antennapod/feed/FeedMedia.java
+++ b/src/de/danoeh/antennapod/feed/FeedMedia.java
@@ -4,8 +4,6 @@ import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.Log;
-import de.danoeh.antennapod.AppConfig;
import de.danoeh.antennapod.PodcastApp;
import de.danoeh.antennapod.preferences.PlaybackPreferences;
import de.danoeh.antennapod.storage.DBReader;
@@ -205,8 +203,8 @@ public class FeedMedia extends FeedFile implements Playable {
}
public FeedImage getImage() {
- if (item != null && item.getFeed() != null) {
- return item.getFeed().getImage();
+ if (item != null) {
+ return (item.hasItemImage()) ? item.getImage() : item.getFeed().getImage();
}
return null;
}
@@ -385,8 +383,13 @@ public class FeedMedia extends FeedFile implements Playable {
@Override
public InputStream openImageInputStream() {
- InputStream out = new Playable.DefaultPlayableImageLoader(this)
- .openImageInputStream();
+ InputStream out;
+ if (item.hasItemImage()) {
+ out = item.openImageInputStream();
+ } else {
+ out = new Playable.DefaultPlayableImageLoader(this)
+ .openImageInputStream();
+ }
if (out == null) {
if (item.getFeed().getImage() != null) {
return item.getFeed().getImage().openImageInputStream();
@@ -397,8 +400,13 @@ public class FeedMedia extends FeedFile implements Playable {
@Override
public String getImageLoaderCacheKey() {
- String out = new Playable.DefaultPlayableImageLoader(this)
- .getImageLoaderCacheKey();
+ String out;
+ if (item.hasItemImage()) {
+ out = item.getImageLoaderCacheKey();
+ } else {
+ out = new Playable.DefaultPlayableImageLoader(this)
+ .getImageLoaderCacheKey();
+ }
if (out == null) {
if (item.getFeed().getImage() != null) {
return item.getFeed().getImage().getImageLoaderCacheKey();
@@ -410,7 +418,7 @@ public class FeedMedia extends FeedFile implements Playable {
@Override
public InputStream reopenImageInputStream(InputStream input) {
if (input instanceof FileInputStream) {
- return item.getFeed().getImage().reopenImageInputStream(input);
+ return item.getImage().reopenImageInputStream(input);
} else {
return new Playable.DefaultPlayableImageLoader(this)
.reopenImageInputStream(input);
diff --git a/src/de/danoeh/antennapod/service/download/DownloadService.java b/src/de/danoeh/antennapod/service/download/DownloadService.java
index 5e1d29ecc..fbf7be071 100644
--- a/src/de/danoeh/antennapod/service/download/DownloadService.java
+++ b/src/de/danoeh/antennapod/service/download/DownloadService.java
@@ -23,7 +23,6 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.DownloadActivity;
import de.danoeh.antennapod.activity.DownloadAuthenticationActivity;
import de.danoeh.antennapod.activity.DownloadLogActivity;
-import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.feed.*;
import de.danoeh.antennapod.storage.*;
import de.danoeh.antennapod.syndication.handler.FeedHandler;
@@ -31,6 +30,7 @@ import de.danoeh.antennapod.syndication.handler.UnsupportedFeedtypeException;
import de.danoeh.antennapod.util.ChapterUtils;
import de.danoeh.antennapod.util.DownloadError;
import de.danoeh.antennapod.util.InvalidFeedException;
+import org.apache.commons.lang3.StringUtils;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
@@ -568,7 +568,7 @@ public class DownloadService extends Service {
.setContentTitle(getText(R.string.authentication_notification_title))
.setContentText(getText(R.string.authentication_notification_msg))
.setStyle(new NotificationCompat.BigTextStyle().bigText(getText(R.string.authentication_notification_msg)
- + ": " + resourceTitle))
+ + ": " + resourceTitle))
.setSmallIcon(R.drawable.ic_stat_authentication)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_stat_authentication))
.setAutoCancel(true)
@@ -655,7 +655,7 @@ public class DownloadService extends Service {
&& savedFeed.getImage().isDownloaded() == false) {
if (AppConfig.DEBUG)
Log.d(TAG, "Feed has image; Downloading....");
- savedFeed.getImage().setFeed(savedFeed);
+ savedFeed.getImage().setOwner(savedFeed);
final Feed savedFeedRef = savedFeed;
try {
requester.downloadImage(DownloadService.this,
@@ -675,6 +675,32 @@ public class DownloadService extends Service {
);
}
}
+ if (!hasDuplicateImages(savedFeed)) {
+ // download FeedItem images if provided and not downloaded
+ for (FeedItem item : savedFeed.getItems()) {
+ if (item.hasItemImage() && (!item.getImage().isDownloaded())) {
+ if (AppConfig.DEBUG)
+ Log.d(TAG, "Item has image; Downloading....");
+ try {
+ requester.downloadImage(DownloadService.this,
+ item.getImage());
+ } catch (DownloadRequestException e) {
+ e.printStackTrace();
+ DBWriter.addDownloadStatus(
+ DownloadService.this,
+ new DownloadStatus(
+ item.getImage(),
+ item
+ .getImage()
+ .getHumanReadableIdentifier(),
+ DownloadError.ERROR_REQUEST_ERROR,
+ false, e.getMessage()
+ )
+ );
+ }
+ }
+ }
+ }
} catch (SAXException e) {
successful = false;
@@ -731,7 +757,25 @@ public class DownloadService extends Service {
if (AppConfig.DEBUG)
Log.d(TAG, "Feed appears to be valid.");
return true;
+ }
+ /**
+ * Checks if the FeedItems of this feed have images that point
+ * to the same URL.
+ */
+ private boolean hasDuplicateImages(Feed feed) {
+ for (int x = 0; x < feed.getItems().size(); x++) {
+ for (int y = x + 1; y < feed.getItems().size(); y++) {
+ FeedItem item1 = feed.getItems().get(x);
+ FeedItem item2 = feed.getItems().get(y);
+ if (item1.hasItemImage() && item2.hasItemImage()) {
+ if (StringUtils.equals(item1.getImage().getDownload_url(), item2.getImage().getDownload_url())) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
}
private boolean hasValidFeedItems(Feed feed) {
diff --git a/src/de/danoeh/antennapod/service/download/HttpDownloader.java b/src/de/danoeh/antennapod/service/download/HttpDownloader.java
index 273c98b0d..6c685b2d5 100644
--- a/src/de/danoeh/antennapod/service/download/HttpDownloader.java
+++ b/src/de/danoeh/antennapod/service/download/HttpDownloader.java
@@ -5,6 +5,7 @@ import android.util.Log;
import de.danoeh.antennapod.AppConfig;
import de.danoeh.antennapod.PodcastApp;
import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.feed.FeedImage;
import de.danoeh.antennapod.util.DownloadError;
import de.danoeh.antennapod.util.StorageUtils;
import de.danoeh.antennapod.util.URIUtil;
@@ -32,6 +33,18 @@ public class HttpDownloader extends Downloader {
@Override
protected void download() {
+ File destination = new File(request.getDestination());
+ if (destination.exists()) {
+ Log.w(TAG, "File already exists");
+ if (request.getFeedfileType() != FeedImage.FEEDFILETYPE_FEEDIMAGE) {
+ onFail(DownloadError.ERROR_FILE_EXISTS, null);
+ return;
+ } else {
+ onSuccess();
+ return;
+ }
+ }
+
HttpClient httpClient = AntennapodHttpClient.getHttpClient();
BufferedOutputStream out = null;
InputStream connection = null;
@@ -79,13 +92,6 @@ public class HttpDownloader extends Downloader {
return;
}
- File destination = new File(request.getDestination());
- if (destination.exists()) {
- Log.w(TAG, "File already exists");
- onFail(DownloadError.ERROR_FILE_EXISTS, null);
- return;
- }
-
connection = new BufferedInputStream(AndroidHttpClient
.getUngzippedContent(httpEntity));
out = new BufferedOutputStream(new FileOutputStream(
diff --git a/src/de/danoeh/antennapod/storage/DBReader.java b/src/de/danoeh/antennapod/storage/DBReader.java
index c3e9ab9a2..2ebb8f719 100644
--- a/src/de/danoeh/antennapod/storage/DBReader.java
+++ b/src/de/danoeh/antennapod/storage/DBReader.java
@@ -216,7 +216,12 @@ public final class DBReader {
.getString(PodDBAdapter.IDX_FI_SMALL_ITEM_IDENTIFIER));
item.setFlattrStatus(new FlattrStatus(itemlistCursor
.getLong(PodDBAdapter.IDX_FI_SMALL_FLATTR_STATUS)));
-
+
+ long imageIndex = itemlistCursor.getLong(PodDBAdapter.IDX_FI_SMALL_IMAGE);
+ if (imageIndex != 0) {
+ item.setImage(getFeedImage(adapter, imageIndex));
+ }
+
// extract chapters
boolean hasSimpleChapters = itemlistCursor
.getInt(PodDBAdapter.IDX_FI_SMALL_HAS_CHAPTERS) > 0;
@@ -340,7 +345,7 @@ public final class DBReader {
new FlattrStatus(cursor.getLong(PodDBAdapter.IDX_FEED_SEL_STD_FLATTR_STATUS)));
if (image != null) {
- image.setFeed(feed);
+ image.setOwner(feed);
}
FeedPreferences preferences = new FeedPreferences(cursor.getLong(PodDBAdapter.IDX_FEED_SEL_STD_ID),
@@ -740,7 +745,7 @@ public final class DBReader {
* @return The found object
*/
static FeedImage getFeedImage(PodDBAdapter adapter, final long id) {
- Cursor cursor = adapter.getImageOfFeedCursor(id);
+ Cursor cursor = adapter.getImageCursor(id);
if ((cursor.getCount() == 0) || !cursor.moveToFirst()) {
throw new SQLException("No FeedImage found at index: " + id);
}
diff --git a/src/de/danoeh/antennapod/storage/DBWriter.java b/src/de/danoeh/antennapod/storage/DBWriter.java
index 444e9ea0c..9699230c7 100644
--- a/src/de/danoeh/antennapod/storage/DBWriter.java
+++ b/src/de/danoeh/antennapod/storage/DBWriter.java
@@ -176,6 +176,16 @@ 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 = new PodDBAdapter(context);
adapter.open();
diff --git a/src/de/danoeh/antennapod/storage/DownloadRequester.java b/src/de/danoeh/antennapod/storage/DownloadRequester.java
index ba112b662..357f44faa 100644
--- a/src/de/danoeh/antennapod/storage/DownloadRequester.java
+++ b/src/de/danoeh/antennapod/storage/DownloadRequester.java
@@ -157,7 +157,7 @@ public class DownloadRequester {
throws DownloadRequestException {
if (feedFileValid(image)) {
download(context, image, new File(getImagefilePath(context),
- getImagefileName(image)), true, null, null);
+ getImagefileName(image)), false, null, null);
}
}
@@ -291,8 +291,8 @@ public class DownloadRequester {
public String getImagefileName(FeedImage image) {
String filename = image.getDownload_url();
- if (image.getFeed() != null && image.getFeed().getTitle() != null) {
- filename = image.getFeed().getTitle();
+ if (image.getOwner() != null && image.getOwner().getHumanReadableIdentifier() != null) {
+ filename = image.getOwner().getHumanReadableIdentifier();
}
return "image-" + FileNameGenerator.generateFileName(filename);
}
diff --git a/src/de/danoeh/antennapod/storage/PodDBAdapter.java b/src/de/danoeh/antennapod/storage/PodDBAdapter.java
index 77768a801..7ccefde94 100644
--- a/src/de/danoeh/antennapod/storage/PodDBAdapter.java
+++ b/src/de/danoeh/antennapod/storage/PodDBAdapter.java
@@ -168,7 +168,8 @@ public class PodDBAdapter {
+ KEY_DESCRIPTION + " TEXT," + KEY_PAYMENT_LINK + " TEXT,"
+ KEY_MEDIA + " INTEGER," + KEY_FEED + " INTEGER,"
+ KEY_HAS_CHAPTERS + " INTEGER," + KEY_ITEM_IDENTIFIER + " TEXT,"
- + KEY_FLATTR_STATUS + " INTEGER)";
+ + KEY_FLATTR_STATUS + " INTEGER,"
+ + KEY_IMAGE + " INTEGER)";
private static final String CREATE_TABLE_FEED_IMAGES = "CREATE TABLE "
+ TABLE_NAME_FEED_IMAGES + " (" + TABLE_PRIMARY_KEY + KEY_TITLE
@@ -263,7 +264,8 @@ public class PodDBAdapter {
TABLE_NAME_FEED_ITEMS + "." + KEY_FEED,
TABLE_NAME_FEED_ITEMS + "." + KEY_HAS_CHAPTERS,
TABLE_NAME_FEED_ITEMS + "." + KEY_ITEM_IDENTIFIER,
- TABLE_NAME_FEED_ITEMS + "." + KEY_FLATTR_STATUS};
+ TABLE_NAME_FEED_ITEMS + "." + KEY_FLATTR_STATUS,
+ TABLE_NAME_FEED_ITEMS + "." + KEY_IMAGE};
/**
* Contains FEEDITEM_SEL_FI_SMALL as comma-separated list. Useful for raw queries.
@@ -288,6 +290,7 @@ public class PodDBAdapter {
public static final int IDX_FI_SMALL_HAS_CHAPTERS = 8;
public static final int IDX_FI_SMALL_ITEM_IDENTIFIER = 9;
public static final int IDX_FI_SMALL_FLATTR_STATUS = 10;
+ public static final int IDX_FI_SMALL_IMAGE = 11;
/**
* Select id, description and content-encoded column from feeditems.
@@ -416,10 +419,14 @@ public class PodDBAdapter {
db.update(TABLE_NAME_FEED_IMAGES, values, KEY_ID + "=?",
new String[]{String.valueOf(image.getId())});
}
- if (image.getFeed() != null && image.getFeed().getId() != 0) {
+
+ final FeedComponent owner = image.getOwner();
+ if (owner != null && owner.getId() != 0) {
values.clear();
values.put(KEY_IMAGE, image.getId());
- db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(image.getFeed().getId())});
+ if (owner instanceof Feed) {
+ db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(image.getOwner().getId())});
+ }
}
db.setTransactionSuccessful();
db.endTransaction();
@@ -662,6 +669,13 @@ public class PodDBAdapter {
values.put(KEY_HAS_CHAPTERS, item.getChapters() != null);
values.put(KEY_ITEM_IDENTIFIER, item.getItemIdentifier());
values.put(KEY_FLATTR_STATUS, item.getFlattrStatus().toLong());
+ if (item.hasItemImage()) {
+ if (item.getImage().getId() == 0) {
+ setImage(item.getImage());
+ }
+ values.put(KEY_IMAGE, item.getImage().getId());
+ }
+
if (item.getId() == 0) {
item.setId(db.insert(TABLE_NAME_FEED_ITEMS, null, values));
} else {
@@ -810,6 +824,9 @@ public class PodDBAdapter {
if (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())});
}
@@ -914,7 +931,7 @@ public class PodDBAdapter {
* @param id ID of the FeedImage
* @return The cursor of the query
*/
- public final Cursor getImageOfFeedCursor(final long id) {
+ public final Cursor getImageCursor(final long id) {
Cursor c = db.query(TABLE_NAME_FEED_IMAGES, null, KEY_ID + "=?",
new String[]{String.valueOf(id)}, null, null, null);
return c;
@@ -1337,6 +1354,9 @@ public class PodDBAdapter {
db.execSQL("ALTER TABLE " + TABLE_NAME_FEEDS
+ " ADD COLUMN " + KEY_PASSWORD
+ " TEXT");
+ db.execSQL("ALTER TABLE" + TABLE_NAME_FEED_ITEMS
+ + " ADD COLUMN " + KEY_IMAGE
+ + " INTEGER");
}
}
}
diff --git a/src/de/danoeh/antennapod/syndication/namespace/NSITunes.java b/src/de/danoeh/antennapod/syndication/namespace/NSITunes.java
index cd7fef509..d8cbe040b 100644
--- a/src/de/danoeh/antennapod/syndication/namespace/NSITunes.java
+++ b/src/de/danoeh/antennapod/syndication/namespace/NSITunes.java
@@ -1,40 +1,51 @@
package de.danoeh.antennapod.syndication.namespace;
-import org.xml.sax.Attributes;
-
import de.danoeh.antennapod.feed.FeedImage;
import de.danoeh.antennapod.syndication.handler.HandlerState;
+import org.xml.sax.Attributes;
+
+public class NSITunes extends Namespace {
+ public static final String NSTAG = "itunes";
+ 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";
+
+
+ @Override
+ public SyndElement handleElementStart(String localName, HandlerState state,
+ Attributes attributes) {
+ if (localName.equals(IMAGE)) {
+ FeedImage image = new FeedImage();
+ image.setTitle(IMAGE_TITLE);
+ image.setDownload_url(attributes.getValue(IMAGE_HREF));
+
+ if (state.getCurrentItem() != null) {
+ // this is an items image
+ image.setTitle(state.getCurrentItem().getTitle() + IMAGE_TITLE);
+ state.getCurrentItem().setImage(image);
+
+ } else {
+ // this is the feed image
+ if (state.getFeed().getImage() == null) {
+ state.getFeed().setImage(image);
+ }
+ }
+
+ }
+
+ return new SyndElement(localName, this);
+ }
+
+ @Override
+ public void handleElementEnd(String localName, HandlerState state) {
+ if (localName.equals(AUTHOR)) {
+ state.getFeed().setAuthor(state.getContentBuf().toString());
+ }
-public class NSITunes extends Namespace{
- public static final String NSTAG = "itunes";
- 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";
-
-
- @Override
- public SyndElement handleElementStart(String localName, HandlerState state,
- Attributes attributes) {
- if (localName.equals(IMAGE) && state.getFeed().getImage() == null) {
- FeedImage image = new FeedImage();
- image.setTitle(IMAGE_TITLE);
- image.setDownload_url(attributes.getValue(IMAGE_HREF));
- state.getFeed().setImage(image);
- }
-
- return new SyndElement(localName, this);
- }
-
- @Override
- public void handleElementEnd(String localName, HandlerState state) {
- if (localName.equals(AUTHOR)) {
- state.getFeed().setAuthor(state.getContentBuf().toString());
- }
-
- }
+ }
}
diff --git a/src/instrumentationTest/de/test/antennapod/AntennaPodTestRunner.java b/src/instrumentationTest/de/test/antennapod/AntennaPodTestRunner.java
index e1699139d..35ecf86dc 100644
--- a/src/instrumentationTest/de/test/antennapod/AntennaPodTestRunner.java
+++ b/src/instrumentationTest/de/test/antennapod/AntennaPodTestRunner.java
@@ -12,7 +12,8 @@ public class AntennaPodTestRunner extends InstrumentationTestRunner {
@Override
public TestSuite getAllTests() {
- return new TestSuiteBuilder(AntennaPodTestRunner.class).includeAllPackagesUnderHere()
+ return new TestSuiteBuilder(AntennaPodTestRunner.class).includePackages("instrumentationTest.de.test.antennapod.storage")
+ //.includeAllPackagesUnderHere()
// .excludePackages("instrumentationTest.de.test.antennapod.syndication.handler")
// .excludePackages("instrumentationTest.de.test.antennapod.gpodnet")
.build();
diff --git a/src/instrumentationTest/de/test/antennapod/storage/DBWriterTest.java b/src/instrumentationTest/de/test/antennapod/storage/DBWriterTest.java
index 679ae1ad3..67d99f9fc 100644
--- a/src/instrumentationTest/de/test/antennapod/storage/DBWriterTest.java
+++ b/src/instrumentationTest/de/test/antennapod/storage/DBWriterTest.java
@@ -95,7 +95,7 @@ public class DBWriterTest extends InstrumentationTestCase {
File imgFile = new File(destFolder, "image");
assertTrue(imgFile.createNewFile());
FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
- image.setFeed(feed);
+ image.setOwner(feed);
feed.setImage(image);
List<File> itemFiles = new ArrayList<File>();
@@ -137,7 +137,7 @@ public class DBWriterTest extends InstrumentationTestCase {
Cursor c = adapter.getFeedCursor(feed.getId());
assertTrue(c.getCount() == 0);
c.close();
- c = adapter.getImageOfFeedCursor(image.getId());
+ c = adapter.getImageCursor(image.getId());
assertTrue(c.getCount() == 0);
c.close();
for (FeedItem item : feed.getItems()) {
@@ -217,7 +217,7 @@ public class DBWriterTest extends InstrumentationTestCase {
File imgFile = new File(destFolder, "image");
assertTrue(imgFile.createNewFile());
FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
- image.setFeed(feed);
+ image.setOwner(feed);
feed.setImage(image);
PodDBAdapter adapter = new PodDBAdapter(getInstrumentation().getContext());
@@ -238,7 +238,7 @@ public class DBWriterTest extends InstrumentationTestCase {
Cursor c = adapter.getFeedCursor(feed.getId());
assertTrue(c.getCount() == 0);
c.close();
- c = adapter.getImageOfFeedCursor(image.getId());
+ c = adapter.getImageCursor(image.getId());
assertTrue(c.getCount() == 0);
c.close();
}
@@ -254,7 +254,7 @@ public class DBWriterTest extends InstrumentationTestCase {
File imgFile = new File(destFolder, "image");
assertTrue(imgFile.createNewFile());
FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
- image.setFeed(feed);
+ image.setOwner(feed);
feed.setImage(image);
// create items
@@ -285,7 +285,7 @@ public class DBWriterTest extends InstrumentationTestCase {
Cursor c = adapter.getFeedCursor(feed.getId());
assertTrue(c.getCount() == 0);
c.close();
- c = adapter.getImageOfFeedCursor(image.getId());
+ c = adapter.getImageCursor(image.getId());
assertTrue(c.getCount() == 0);
c.close();
for (FeedItem item : feed.getItems()) {
@@ -295,6 +295,64 @@ public class DBWriterTest extends InstrumentationTestCase {
}
}
+ public void testDeleteFeedWithItemImages() throws InterruptedException, ExecutionException, TimeoutException, IOException {
+ File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
+ assertNotNull(destFolder);
+
+ Feed feed = new Feed("url", new Date(), "title");
+ feed.setItems(new ArrayList<FeedItem>());
+
+ // create Feed image
+ File imgFile = new File(destFolder, "image");
+ assertTrue(imgFile.createNewFile());
+ FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
+ image.setOwner(feed);
+ feed.setImage(image);
+
+ // create items with images
+ for (int i = 0; i < 10; i++) {
+ FeedItem item = new FeedItem(0, "Item " + i, "Item" + i, "url", new Date(), true, feed);
+ feed.getItems().add(item);
+ File itemImageFile = new File(destFolder, "item-image-" + i);
+ FeedImage itemImage = new FeedImage(0, "item-image" + i, itemImageFile.getAbsolutePath(), "url", true);
+ item.setImage(itemImage);
+ }
+
+ PodDBAdapter adapter = new PodDBAdapter(getInstrumentation().getContext());
+ adapter.open();
+ adapter.setCompleteFeed(feed);
+ adapter.close();
+
+ assertTrue(feed.getId() != 0);
+ assertTrue(feed.getImage().getId() != 0);
+ for (FeedItem item : feed.getItems()) {
+ assertTrue(item.getId() != 0);
+ assertTrue(item.getImage().getId() != 0);
+ }
+
+ DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS);
+
+ // check if files still exist
+ assertFalse(imgFile.exists());
+
+ adapter = new PodDBAdapter(getInstrumentation().getContext());
+ adapter.open();
+ Cursor c = adapter.getFeedCursor(feed.getId());
+ assertTrue(c.getCount() == 0);
+ c.close();
+ c = adapter.getImageCursor(image.getId());
+ assertTrue(c.getCount() == 0);
+ c.close();
+ for (FeedItem item : feed.getItems()) {
+ c = adapter.getFeedItemCursor(String.valueOf(item.getId()));
+ assertTrue(c.getCount() == 0);
+ c.close();
+ c = adapter.getImageCursor(item.getImage().getId());
+ assertEquals(0, c.getCount());
+ c.close();
+ }
+ }
+
public void testDeleteFeedWithQueueItems() throws ExecutionException, InterruptedException, TimeoutException {
File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
assertNotNull(destFolder);
@@ -305,7 +363,7 @@ public class DBWriterTest extends InstrumentationTestCase {
// create Feed image
File imgFile = new File(destFolder, "image");
FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
- image.setFeed(feed);
+ image.setOwner(feed);
feed.setImage(image);
List<File> itemFiles = new ArrayList<File>();
@@ -350,7 +408,7 @@ public class DBWriterTest extends InstrumentationTestCase {
Cursor c = adapter.getFeedCursor(feed.getId());
assertTrue(c.getCount() == 0);
c.close();
- c = adapter.getImageOfFeedCursor(image.getId());
+ c = adapter.getImageCursor(image.getId());
assertTrue(c.getCount() == 0);
c.close();
for (FeedItem item : feed.getItems()) {
@@ -377,7 +435,7 @@ public class DBWriterTest extends InstrumentationTestCase {
// create Feed image
File imgFile = new File(destFolder, "image");
FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
- image.setFeed(feed);
+ image.setOwner(feed);
feed.setImage(image);
List<File> itemFiles = new ArrayList<File>();
@@ -412,7 +470,7 @@ public class DBWriterTest extends InstrumentationTestCase {
Cursor c = adapter.getFeedCursor(feed.getId());
assertTrue(c.getCount() == 0);
c.close();
- c = adapter.getImageOfFeedCursor(image.getId());
+ c = adapter.getImageCursor(image.getId());
assertTrue(c.getCount() == 0);
c.close();
for (FeedItem item : feed.getItems()) {