diff options
Diffstat (limited to 'src/de')
20 files changed, 429 insertions, 117 deletions
diff --git a/src/de/danoeh/antennapod/activity/MainActivity.java b/src/de/danoeh/antennapod/activity/MainActivity.java index 902869a80..bfd99016f 100644 --- a/src/de/danoeh/antennapod/activity/MainActivity.java +++ b/src/de/danoeh/antennapod/activity/MainActivity.java @@ -160,7 +160,7 @@ public class MainActivity extends SherlockFragmentActivity { @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = new MenuInflater(this); - inflater.inflate(R.menu.podfetcher, menu); + inflater.inflate(R.menu.main, menu); return true; } diff --git a/src/de/danoeh/antennapod/asynctask/DownloadStatus.java b/src/de/danoeh/antennapod/asynctask/DownloadStatus.java index cede8c71f..e9225d33b 100644 --- a/src/de/danoeh/antennapod/asynctask/DownloadStatus.java +++ b/src/de/danoeh/antennapod/asynctask/DownloadStatus.java @@ -83,6 +83,18 @@ public class DownloadStatus { new Date(), reasonDetailed); } + @Override + public String toString() { + return "DownloadStatus [id=" + id + ", title=" + title + ", reason=" + + reason + ", reasonDetailed=" + reasonDetailed + + ", successful=" + successful + ", completionDate=" + + completionDate + ", feedfile=" + feedfile + ", feedfileType=" + + feedfileType + ", progressPercent=" + progressPercent + + ", soFar=" + soFar + ", size=" + size + ", statusMsg=" + + statusMsg + ", done=" + done + ", cancelled=" + cancelled + + "]"; + } + public FeedFile getFeedFile() { return feedfile; } diff --git a/src/de/danoeh/antennapod/feed/Feed.java b/src/de/danoeh/antennapod/feed/Feed.java index 7640ef7d1..4df9fc43f 100644 --- a/src/de/danoeh/antennapod/feed/Feed.java +++ b/src/de/danoeh/antennapod/feed/Feed.java @@ -30,7 +30,6 @@ public class Feed extends FeedFile { /** Name of the author */ private String author; private FeedImage image; - private FeedCategory category; private List<FeedItem> items; /** Date of last refresh. */ private Date lastUpdate; @@ -171,6 +170,72 @@ public class Feed extends FeedFile { } } + public void updateFromOther(Feed other) { + super.updateFromOther(other); + if (other.title != null) { + title = other.title; + } + if (other.feedIdentifier != null) { + feedIdentifier = other.feedIdentifier; + } + if (other.link != null) { + link = other.link; + } + if (other.description != null) { + description = other.description; + } + if (other.language != null) { + language = other.language; + } + if (other.author != null) { + author = other.author; + } + if (other.paymentLink != null) { + paymentLink = other.paymentLink; + } + } + + public boolean compareWithOther(Feed other) { + if (super.compareWithOther(other)) { + return true; + } + if (!title.equals(other.title)) { + return true; + } + if (other.feedIdentifier != null) { + if (feedIdentifier == null + || !feedIdentifier.equals(other.feedIdentifier)) { + return true; + } + } + if (other.link != null) { + if (link == null || !link.equals(other.link)) { + return true; + } + } + if (other.description != null) { + if (description == null || !description.equals(other.description)) { + return true; + } + } + if (other.language != null) { + if (language == null || !language.equals(other.language)) { + return true; + } + } + if (other.author != null) { + if (author == null || !author.equals(other.author)) { + return true; + } + } + if (other.paymentLink != null) { + if (paymentLink == null || !paymentLink.equals(other.paymentLink)) { + return true; + } + } + return false; + } + @Override public int getTypeAsInt() { return FEEDFILETYPE_FEED; @@ -208,14 +273,6 @@ public class Feed extends FeedFile { this.image = image; } - public FeedCategory getCategory() { - return category; - } - - public void setCategory(FeedCategory category) { - this.category = category; - } - public List<FeedItem> getItems() { return items; } diff --git a/src/de/danoeh/antennapod/feed/FeedCategory.java b/src/de/danoeh/antennapod/feed/FeedCategory.java deleted file mode 100644 index fc3d8d79b..000000000 --- a/src/de/danoeh/antennapod/feed/FeedCategory.java +++ /dev/null @@ -1,20 +0,0 @@ -package de.danoeh.antennapod.feed; - -public class FeedCategory extends FeedComponent{ - protected String name; - - public FeedCategory(String name) { - super(); - this.name = name; - } - - public String getName() { - return name; - } - - - - - - -} diff --git a/src/de/danoeh/antennapod/feed/FeedComponent.java b/src/de/danoeh/antennapod/feed/FeedComponent.java index a192f4bc8..d23c8d7c8 100644 --- a/src/de/danoeh/antennapod/feed/FeedComponent.java +++ b/src/de/danoeh/antennapod/feed/FeedComponent.java @@ -21,6 +21,25 @@ public class FeedComponent { this.id = id; } + /** + * Update this FeedComponent's attributes with the attributes from another + * FeedComponent. This method should only update attributes which where read from + * the feed. + */ + public void updateFromOther(FeedComponent other) { + } + + /** + * Compare's this FeedComponent's attribute values with another FeedComponent's + * attribute values. This method will only compare attributes which were + * read from the feed. + * + * @return true if attribute values are different, false otherwise + */ + public boolean compareWithOther(FeedComponent other) { + return false; + } + }
\ 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 63ce956f1..305d58c1b 100644 --- a/src/de/danoeh/antennapod/feed/FeedFile.java +++ b/src/de/danoeh/antennapod/feed/FeedFile.java @@ -26,6 +26,33 @@ public abstract class FeedFile extends FeedComponent { public abstract int getTypeAsInt(); + /** + * Update this FeedFile's attributes with the attributes from another + * FeedFile. This method should only update attributes which where read from + * the feed. + */ + public void updateFromOther(FeedFile other) { + super.updateFromOther(other); + this.download_url = other.download_url; + } + + /** + * Compare's this FeedFile's attribute values with another FeedFile's + * attribute values. This method will only compare attributes which were + * read from the feed. + * + * @return true if attribute values are different, false otherwise + */ + public boolean compareWithOther(FeedFile other) { + if (super.compareWithOther(other)) { + return true; + } + if (!download_url.equals(other.download_url)) { + return true; + } + return false; + } + public String getFile_url() { return file_url; } diff --git a/src/de/danoeh/antennapod/feed/FeedItem.java b/src/de/danoeh/antennapod/feed/FeedItem.java index e886c73b3..06fdc4292 100644 --- a/src/de/danoeh/antennapod/feed/FeedItem.java +++ b/src/de/danoeh/antennapod/feed/FeedItem.java @@ -43,6 +43,40 @@ public class FeedItem extends FeedComponent { this.read = true; } + public void updateFromOther(FeedItem other) { + super.updateFromOther(other); + if (other.title != null) { + title = other.title; + } + if (other.getDescription() != null) { + description = other.getDescription(); + } + if (other.getContentEncoded() != null) { + contentEncoded = other.contentEncoded; + } + if (other.link != null) { + link = other.link; + } + if (other.pubDate != null && other.pubDate != pubDate) { + pubDate = other.pubDate; + } + if (other.media != null) { + if (media == null) { + media = other.media; + } else if (media.compareWithOther(other)) { + media.updateFromOther(other); + } + } + if (other.paymentLink != null) { + paymentLink = other.paymentLink; + } + if (other.chapters != null) { + if (chapters == null) { + chapters = other.chapters; + } + } + } + /** * Moves the 'description' and 'contentEncoded' field of feeditem to their * SoftReference fields. @@ -214,9 +248,11 @@ public class FeedItem extends FeedComponent { public void setCachedContentEncoded(String c) { cachedContentEncoded = new SoftReference<String>(c); } - - public enum State {NEW, IN_PROGRESS, READ, PLAYING} - + + public enum State { + NEW, IN_PROGRESS, READ, PLAYING + } + public State getState() { if (hasMedia()) { if (isPlaying()) { diff --git a/src/de/danoeh/antennapod/feed/FeedManager.java b/src/de/danoeh/antennapod/feed/FeedManager.java index 9888febc9..855316d81 100644 --- a/src/de/danoeh/antennapod/feed/FeedManager.java +++ b/src/de/danoeh/antennapod/feed/FeedManager.java @@ -53,7 +53,6 @@ public class FeedManager { private static FeedManager singleton; private List<Feed> feeds; - private ArrayList<FeedCategory> categories; /** Contains all items where 'read' is false */ private List<FeedItem> unreadItems; @@ -82,7 +81,6 @@ public class FeedManager { private FeedManager() { feeds = Collections.synchronizedList(new ArrayList<Feed>()); - categories = new ArrayList<FeedCategory>(); unreadItems = Collections.synchronizedList(new ArrayList<FeedItem>()); requester = DownloadRequester.getInstance(); downloadLog = new ArrayList<DownloadStatus>(); @@ -776,18 +774,7 @@ public class FeedManager { sendFeedUpdateBroadcast(context); } }); - dbExec.execute(new Runnable() { - - @Override - public void run() { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.setCompleteFeed(feed); - feed.cacheDescriptionsOfItems(); - adapter.close(); - } - }); - + setCompleteFeed(context, feed); } /** @@ -811,6 +798,12 @@ public class FeedManager { if (AppConfig.DEBUG) Log.d(TAG, "Feed with title " + newFeed.getTitle() + " already exists. Syncing new with existing one."); + if (savedFeed.compareWithOther(newFeed)) { + if (AppConfig.DEBUG) + Log.d(TAG, + "Feed has updated attribute values. Updating old feed's attributes"); + savedFeed.updateFromOther(newFeed); + } // Look for new or updated Items for (int idx = 0; idx < newFeed.getItems().size(); idx++) { final FeedItem item = newFeed.getItems().get(idx); @@ -828,12 +821,14 @@ public class FeedManager { } }); markItemRead(context, item, false, false); + } else { + oldItem.updateFromOther(item); } } // update attributes savedFeed.setLastUpdate(newFeed.getLastUpdate()); savedFeed.setType(newFeed.getType()); - setFeed(context, savedFeed); + setCompleteFeed(context, savedFeed); return savedFeed; } @@ -931,6 +926,25 @@ public class FeedManager { }); } + + /** + * Updates Information of an existing Feed and its FeedItems. Creates and opens its own + * adapter. + */ + public void setCompleteFeed(final Context context, final Feed feed) { + dbExec.execute(new Runnable() { + + @Override + public void run() { + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + adapter.setCompleteFeed(feed); + feed.cacheDescriptionsOfItems(); + adapter.close(); + } + }); + + } /** * Updates information of an existing FeedItem. Creates and opens its own @@ -1078,7 +1092,6 @@ public class FeedManager { public void updateArrays(Context context) { feeds.clear(); - categories.clear(); PodDBAdapter adapter = new PodDBAdapter(context); adapter.open(); extractFeedlistFromCursor(context, adapter); @@ -1348,9 +1361,9 @@ public class FeedManager { } /** - * Loads description and contentEncoded values from the database and caches it in the feeditem. The task - * callback will contain a String-array with the description at index 0 and - * the value of contentEncoded at index 1. + * Loads description and contentEncoded values from the database and caches + * it in the feeditem. The task callback will contain a String-array with + * the description at index 0 and the value of contentEncoded at index 1. */ public void loadExtraInformationOfItem(final Context context, final FeedItem item, FeedManager.TaskCallback<String[]> callback) { @@ -1375,7 +1388,7 @@ public class FeedManager { .getString(PodDBAdapter.IDX_FI_EXTRA_CONTENT_ENCODED); item.setCachedDescription(description); item.setCachedContentEncoded(contentEncoded); - setResult(new String[] {description, contentEncoded}); + setResult(new String[] { description, contentEncoded }); } adapter.close(); } diff --git a/src/de/danoeh/antennapod/feed/FeedMedia.java b/src/de/danoeh/antennapod/feed/FeedMedia.java index 357a642a6..b0a6fe5d4 100644 --- a/src/de/danoeh/antennapod/feed/FeedMedia.java +++ b/src/de/danoeh/antennapod/feed/FeedMedia.java @@ -65,6 +65,31 @@ public class FeedMedia extends FeedFile { return MediaType.UNKNOWN; } + public void updateFromOther(FeedMedia other) { + super.updateFromOther(other); + if (other.size > 0) { + size = other.size; + } + if (other.mime_type != null) { + mime_type = other.mime_type; + } + } + + public boolean compareWithOther(FeedMedia other) { + if (super.compareWithOther(other)) { + return true; + } + if (other.mime_type != null) { + if (mime_type == null || !mime_type.equals(other.mime_type)) { + return true; + } + } + if (other.size > 0 && other.size != size) { + return true; + } + return false; + } + @Override public int getTypeAsInt() { return FEEDFILETYPE_FEEDMEDIA; diff --git a/src/de/danoeh/antennapod/feed/SimpleChapter.java b/src/de/danoeh/antennapod/feed/SimpleChapter.java index 7b74f28f6..3dab1b74d 100644 --- a/src/de/danoeh/antennapod/feed/SimpleChapter.java +++ b/src/de/danoeh/antennapod/feed/SimpleChapter.java @@ -12,4 +12,14 @@ public class SimpleChapter extends Chapter { return CHAPTERTYPE_SIMPLECHAPTER; } + public void updateFromOther(SimpleChapter other) { + super.updateFromOther(other); + start = other.start; + if (other.title != null) { + title = other.title; + } + if (other.link != null) { + link = other.link; + } + } } diff --git a/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java b/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java index 64cce214b..c46bb6c90 100644 --- a/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java +++ b/src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java @@ -14,6 +14,7 @@ import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.webkit.WebSettings.LayoutAlgorithm; import android.webkit.WebView; import com.actionbarsherlock.app.SherlockFragment; @@ -65,6 +66,7 @@ public class ItemDescriptionFragment extends SherlockFragment { webvDescription.setBackgroundColor(0); } webvDescription.getSettings().setUseWideViewPort(false); + webvDescription.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN); return webvDescription; } diff --git a/src/de/danoeh/antennapod/opml/OpmlReader.java b/src/de/danoeh/antennapod/opml/OpmlReader.java index c05ce61e2..61a00742c 100644 --- a/src/de/danoeh/antennapod/opml/OpmlReader.java +++ b/src/de/danoeh/antennapod/opml/OpmlReader.java @@ -17,7 +17,6 @@ public class OpmlReader { // ATTRIBUTES private boolean isInOpml = false; - private boolean isInBody = false; private ArrayList<OpmlElement> elementList; /** @@ -47,12 +46,7 @@ public class OpmlReader { isInOpml = true; if (AppConfig.DEBUG) Log.d(TAG, "Reached beginning of OPML tree."); - } else if (isInOpml && xpp.getName().equals(OpmlSymbols.BODY)) { - isInBody = true; - if (AppConfig.DEBUG) - Log.d(TAG, "Reached beginning of body tree."); - - } else if (isInBody && xpp.getName().equals(OpmlSymbols.OUTLINE)) { + } else if (isInOpml && xpp.getName().equals(OpmlSymbols.OUTLINE)) { if (AppConfig.DEBUG) Log.d(TAG, "Found new Opml element"); OpmlElement element = new OpmlElement(); diff --git a/src/de/danoeh/antennapod/service/download/DownloadService.java b/src/de/danoeh/antennapod/service/download/DownloadService.java index 6da651838..1e6480cce 100644 --- a/src/de/danoeh/antennapod/service/download/DownloadService.java +++ b/src/de/danoeh/antennapod/service/download/DownloadService.java @@ -308,7 +308,20 @@ public class DownloadService extends Service { private Downloader getDownloader(DownloadStatus status) { if (URLUtil.isHttpUrl(status.getFeedFile().getDownload_url())) { - return new HttpDownloader(this, status); + return new HttpDownloader(new DownloaderCallback() { + + @Override + public void onDownloadCompleted(final Downloader downloader) { + handler.post(new Runnable() { + + @Override + public void run() { + DownloadService.this + .onDownloadCompleted(downloader); + } + }); + } + }, status); } Log.e(TAG, "Could not find appropriate downloader for " + status.getFeedFile().getDownload_url()); @@ -318,6 +331,21 @@ public class DownloadService extends Service { @SuppressLint("NewApi") public void onDownloadCompleted(final Downloader downloader) { final AsyncTask<Void, Void, Void> handlerTask = new AsyncTask<Void, Void, Void>() { + boolean successful; + + @Override + protected void onPostExecute(Void result) { + super.onPostExecute(result); + if (!successful) { + queryDownloads(); + } + } + + @Override + protected void onPreExecute() { + super.onPreExecute(); + removeDownload(downloader); + } @Override protected Void doInBackground(Void... params) { @@ -326,7 +354,7 @@ public class DownloadService extends Service { downloadsBeingHandled += 1; DownloadStatus status = downloader.getStatus(); status.setCompletionDate(new Date()); - boolean successful = status.isSuccessful(); + successful = status.isSuccessful(); FeedFile download = status.getFeedFile(); if (download != null) { @@ -349,10 +377,6 @@ public class DownloadService extends Service { downloadsBeingHandled -= 1; } } - removeDownload(downloader); - if (!successful) { - queryDownloads(); - } return null; } }; @@ -368,7 +392,9 @@ public class DownloadService extends Service { * DownloadService list. */ private void removeDownload(final Downloader d) { - downloads.remove(d); + if (AppConfig.DEBUG) Log.d(TAG, "Removing downloader: " + d.getStatus().getFeedFile().getDownload_url()); + boolean rc = downloads.remove(d); + if (AppConfig.DEBUG) Log.d(TAG, "Result of downloads.remove: " + rc); DownloadRequester.getInstance().removeDownload( d.getStatus().getFeedFile()); sendBroadcast(new Intent(ACTION_DOWNLOADS_CONTENT_CHANGED)); @@ -536,12 +562,12 @@ public class DownloadService extends Service { reason = 0; String reasonDetailed = null; successful = true; - FeedManager manager = FeedManager.getInstance(); - FeedHandler handler = new FeedHandler(); + final FeedManager manager = FeedManager.getInstance(); + FeedHandler feedHandler = new FeedHandler(); feed.setDownloaded(true); try { - feed = handler.parseFeed(feed); + feed = feedHandler.parseFeed(feed); if (AppConfig.DEBUG) Log.d(TAG, feed.getTitle() + " parsed"); if (checkFeedData(feed) == false) { @@ -555,18 +581,29 @@ public class DownloadService extends Service { if (AppConfig.DEBUG) Log.d(TAG, "Feed has image; Downloading...."); savedFeed.getImage().setFeed(savedFeed); - try { - requester.downloadImage(DownloadService.this, - savedFeed.getImage()); - } catch (DownloadRequestException e) { - e.printStackTrace(); - manager.addDownloadStatus(DownloadService.this, - new DownloadStatus(savedFeed.getImage(), - savedFeed.getImage() - .getHumanReadableIdentifier(), - DownloadError.ERROR_REQUEST_ERROR, - false, e.getMessage())); - } + final Feed savedFeedRef = savedFeed; + handler.post(new Runnable() { + + @Override + public void run() { + try { + requester.downloadImage(DownloadService.this, + savedFeedRef.getImage()); + } catch (DownloadRequestException e) { + e.printStackTrace(); + manager.addDownloadStatus( + DownloadService.this, + new DownloadStatus( + savedFeedRef.getImage(), + savedFeedRef + .getImage() + .getHumanReadableIdentifier(), + DownloadError.ERROR_REQUEST_ERROR, + false, e.getMessage())); + } + } + }); + } } catch (SAXException e) { @@ -606,7 +643,14 @@ public class DownloadService extends Service { reasonDetailed)); sendDownloadHandledIntent(DOWNLOAD_TYPE_FEED); downloadsBeingHandled -= 1; - queryDownloads(); + handler.post(new Runnable() { + + @Override + public void run() { + queryDownloads(); + + } + }); } /** Checks if the feed was parsed correctly. */ @@ -683,7 +727,14 @@ public class DownloadService extends Service { "Image has no feed, image might not be saved correctly!"); } downloadsBeingHandled -= 1; - queryDownloads(); + handler.post(new Runnable() { + + @Override + public void run() { + queryDownloads(); + + } + }); } } @@ -739,7 +790,14 @@ public class DownloadService extends Service { } downloadsBeingHandled -= 1; - queryDownloads(); + handler.post(new Runnable() { + + @Override + public void run() { + queryDownloads(); + + } + }); } } diff --git a/src/de/danoeh/antennapod/service/download/Downloader.java b/src/de/danoeh/antennapod/service/download/Downloader.java index d4e7009bf..70727879a 100644 --- a/src/de/danoeh/antennapod/service/download/Downloader.java +++ b/src/de/danoeh/antennapod/service/download/Downloader.java @@ -7,22 +7,21 @@ import de.danoeh.antennapod.asynctask.DownloadStatus; /** Downloads files */ public abstract class Downloader extends Thread { private static final String TAG = "Downloader"; - private Handler handler; - private DownloadService downloadService; + private DownloaderCallback downloaderCallback; protected boolean finished; - + protected volatile boolean cancelled; protected volatile DownloadStatus status; - public Downloader(DownloadService downloadService, DownloadStatus status) { + public Downloader(DownloaderCallback downloaderCallback, + DownloadStatus status) { super(); - this.downloadService = downloadService; + this.downloaderCallback = downloaderCallback; this.status = status; this.status.setStatusMsg(R.string.download_pending); this.cancelled = false; - handler = new Handler(); } /** @@ -32,14 +31,7 @@ public abstract class Downloader extends Thread { protected void finish() { if (!finished) { finished = true; - handler.post(new Runnable() { - - @Override - public void run() { - downloadService.onDownloadCompleted(Downloader.this); - } - - }); + downloaderCallback.onDownloadCompleted(this); } } @@ -54,7 +46,7 @@ public abstract class Downloader extends Thread { public DownloadStatus getStatus() { return status; } - + public void cancel() { cancelled = true; } diff --git a/src/de/danoeh/antennapod/service/download/DownloaderCallback.java b/src/de/danoeh/antennapod/service/download/DownloaderCallback.java new file mode 100644 index 000000000..08420e83a --- /dev/null +++ b/src/de/danoeh/antennapod/service/download/DownloaderCallback.java @@ -0,0 +1,10 @@ +package de.danoeh.antennapod.service.download; + +/** + * Callback used by the Downloader-classes to notify the requester that the + * download has completed. + */ +public interface DownloaderCallback { + + public void onDownloadCompleted(Downloader downloader); +} diff --git a/src/de/danoeh/antennapod/service/download/HttpDownloader.java b/src/de/danoeh/antennapod/service/download/HttpDownloader.java index a4fdefbe3..fb51be032 100644 --- a/src/de/danoeh/antennapod/service/download/HttpDownloader.java +++ b/src/de/danoeh/antennapod/service/download/HttpDownloader.java @@ -14,6 +14,8 @@ import java.net.URL; import java.net.UnknownHostException; import org.apache.commons.io.IOUtils; +import org.apache.http.HttpConnection; +import org.apache.http.HttpStatus; import android.util.Log; import de.danoeh.antennapod.AppConfig; @@ -25,11 +27,70 @@ import de.danoeh.antennapod.util.StorageUtils; public class HttpDownloader extends Downloader { private static final String TAG = "HttpDownloader"; + private static final int MAX_REDIRECTS = 5; + private static final int BUFFER_SIZE = 8 * 1024; private static final int CONNECTION_TIMEOUT = 5000; - public HttpDownloader(DownloadService downloadService, DownloadStatus status) { - super(downloadService, status); + public HttpDownloader(DownloaderCallback downloaderCallback, DownloadStatus status) { + super(downloaderCallback, status); + } + + /** + * This method is called by establishConnection(String). Don't call it + * directly. + * */ + private HttpURLConnection establishConnection(String location, + int redirectCount) throws MalformedURLException, IOException { + URL url = new URL(location); + HttpURLConnection connection = null; + int responseCode = -1; + connection = (HttpURLConnection) url.openConnection(); + connection.setConnectTimeout(CONNECTION_TIMEOUT); + // try with 'follow redirect' + connection.setInstanceFollowRedirects(true); + try { + responseCode = connection.getResponseCode(); + } catch (IOException e) { + e.printStackTrace(); + if (AppConfig.DEBUG) + Log.d(TAG, + "Failed to establish connection with 'follow redirects. Disabling 'follow redirects'"); + connection.disconnect(); + connection.setInstanceFollowRedirects(false); + responseCode = connection.getResponseCode(); + } + if (AppConfig.DEBUG) + Log.d(TAG, "Response Code: " + responseCode); + switch (responseCode) { + case HttpStatus.SC_TEMPORARY_REDIRECT: + if (redirectCount < MAX_REDIRECTS) { + final String redirect = connection.getHeaderField("Location"); + if (redirect != null) { + return establishConnection(redirect, redirectCount + 1); + } + } + case HttpStatus.SC_OK: + return connection; + default: + onFail(DownloadError.ERROR_HTTP_DATA_ERROR, + String.valueOf(responseCode)); + return null; + } + } + + /** + * Establish connection to resource. This method will also try to handle + * different response codes / redirect issues. + * + * @return the HttpURLConnection object if the connection could be opened, + * null otherwise. + * @throws MalformedURLException + * , IOException + * */ + private HttpURLConnection establishConnection(String location) + throws MalformedURLException, IOException { + return establishConnection(location, 0); } @Override @@ -37,12 +98,9 @@ public class HttpDownloader extends Downloader { HttpURLConnection connection = null; OutputStream out = null; try { - URL url = new URL(status.getFeedFile().getDownload_url()); - connection = (HttpURLConnection) url.openConnection(); - connection.setConnectTimeout(CONNECTION_TIMEOUT); - connection.setInstanceFollowRedirects(true); - int responseCode = connection.getResponseCode(); - if (responseCode == HttpURLConnection.HTTP_OK) { + connection = establishConnection(status.getFeedFile() + .getDownload_url()); + if (connection != null) { if (AppConfig.DEBUG) { Log.d(TAG, "Connected to resource"); } @@ -89,14 +147,12 @@ public class HttpDownloader extends Downloader { onFail(DownloadError.ERROR_NOT_ENOUGH_SPACE, null); } } else { + Log.w(TAG, "File already exists"); onFail(DownloadError.ERROR_FILE_EXISTS, null); } } else { onFail(DownloadError.ERROR_DEVICE_NOT_FOUND, null); } - } else { - onFail(DownloadError.ERROR_HTTP_DATA_ERROR, - String.valueOf(responseCode)); } } catch (MalformedURLException e) { e.printStackTrace(); diff --git a/src/de/danoeh/antennapod/storage/DownloadRequester.java b/src/de/danoeh/antennapod/storage/DownloadRequester.java index 0201cc542..26bc91555 100644 --- a/src/de/danoeh/antennapod/storage/DownloadRequester.java +++ b/src/de/danoeh/antennapod/storage/DownloadRequester.java @@ -49,10 +49,10 @@ public class DownloadRequester { private void download(Context context, FeedFile item, File dest, boolean overwriteIfExists) { if (!isDownloadingFile(item)) { - if (dest.exists()) { + if (!isFilenameAvailable(dest.toString()) || dest.exists()) { if (AppConfig.DEBUG) - Log.d(TAG, "File already exists."); - if (overwriteIfExists) { + Log.d(TAG, "Filename already used."); + if (isFilenameAvailable(dest.toString()) && overwriteIfExists) { boolean result = dest.delete(); if (AppConfig.DEBUG) Log.d(TAG, "Deleting file. Result: " + result); @@ -69,7 +69,7 @@ public class DownloadRequester { if (AppConfig.DEBUG) Log.d(TAG, "Testing filename " + newName); newDest = new File(dest.getParent(), newName); - if (!newDest.exists()) { + if (!newDest.exists() && isFilenameAvailable(newDest.toString())) { if (AppConfig.DEBUG) Log.d(TAG, "File doesn't exist yet. Using " + newName); @@ -108,6 +108,24 @@ public class DownloadRequester { } } + /** + * Returns true if a filename is available and false if it has already been + * taken by another requested download. + */ + private boolean isFilenameAvailable(String path) { + for (String key : downloads.keySet()) { + FeedFile f = downloads.get(key); + if (f.getFile_url().equals(path)) { + if (AppConfig.DEBUG) + Log.d(TAG, path + + " is already used by another requested download"); + return false; + } + } + if (AppConfig.DEBUG) Log.d(TAG, path + " is available as a download destination"); + return true; + } + public void downloadFeed(Context context, Feed feed) throws DownloadRequestException { if (feedFileValid(feed)) { diff --git a/src/de/danoeh/antennapod/storage/PodDBAdapter.java b/src/de/danoeh/antennapod/storage/PodDBAdapter.java index 9b60521cf..4045f8664 100644 --- a/src/de/danoeh/antennapod/storage/PodDBAdapter.java +++ b/src/de/danoeh/antennapod/storage/PodDBAdapter.java @@ -481,6 +481,7 @@ public class PodDBAdapter { /** Remove a feed with all its FeedItems and Media entries. */ public void removeFeed(Feed feed) { + db.beginTransaction(); if (feed.getImage() != null) { removeFeedImage(feed.getImage()); } @@ -489,6 +490,8 @@ public class PodDBAdapter { } db.delete(TABLE_NAME_FEEDS, KEY_ID + "=?", new String[] { String.valueOf(feed.getId()) }); + db.setTransactionSuccessful(); + db.endTransaction(); } public void removeDownloadStatus(DownloadStatus remove) { diff --git a/src/de/danoeh/antennapod/syndication/handler/SyndHandler.java b/src/de/danoeh/antennapod/syndication/handler/SyndHandler.java index 55757ce18..b52d4f6d2 100644 --- a/src/de/danoeh/antennapod/syndication/handler/SyndHandler.java +++ b/src/de/danoeh/antennapod/syndication/handler/SyndHandler.java @@ -97,7 +97,7 @@ public class SyndHandler extends DefaultHandler { if (AppConfig.DEBUG) Log.d(TAG, "Recognized ITunes namespace"); } else if (uri.equals(NSSimpleChapters.NSURI) - && prefix.equals(NSSimpleChapters.NSTAG)) { + && prefix.matches(NSSimpleChapters.NSTAG)) { state.namespaces.put(uri, new NSSimpleChapters()); if (AppConfig.DEBUG) Log.d(TAG, "Recognized SimpleChapters namespace"); diff --git a/src/de/danoeh/antennapod/syndication/namespace/simplechapters/NSSimpleChapters.java b/src/de/danoeh/antennapod/syndication/namespace/simplechapters/NSSimpleChapters.java index f6918231c..3a5d2a833 100644 --- a/src/de/danoeh/antennapod/syndication/namespace/simplechapters/NSSimpleChapters.java +++ b/src/de/danoeh/antennapod/syndication/namespace/simplechapters/NSSimpleChapters.java @@ -12,7 +12,7 @@ import de.danoeh.antennapod.syndication.namespace.SyndElement; import de.danoeh.antennapod.syndication.util.SyndDateUtils; public class NSSimpleChapters extends Namespace { - public static final String NSTAG = "sc"; + public static final String NSTAG = "psc|sc"; public static final String NSURI = "http://podlove.org/simple-chapters"; public static final String CHAPTERS = "chapters"; |