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 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) && 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); - } +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"; - @Override - public void handleElementEnd(String localName, HandlerState state) { - if (localName.equals(AUTHOR)) { - state.getFeed().setAuthor(state.getContentBuf().toString()); - } - - } + 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()); + } + + } } 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 itemFiles = new ArrayList(); @@ -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()); + + // 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 itemFiles = new ArrayList(); @@ -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 itemFiles = new ArrayList(); @@ -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()) {