summaryrefslogtreecommitdiff
path: root/src/de
diff options
context:
space:
mode:
Diffstat (limited to 'src/de')
-rw-r--r--src/de/danoeh/antennapod/activity/MainActivity.java2
-rw-r--r--src/de/danoeh/antennapod/asynctask/DownloadStatus.java12
-rw-r--r--src/de/danoeh/antennapod/feed/Feed.java75
-rw-r--r--src/de/danoeh/antennapod/feed/FeedCategory.java20
-rw-r--r--src/de/danoeh/antennapod/feed/FeedComponent.java19
-rw-r--r--src/de/danoeh/antennapod/feed/FeedFile.java27
-rw-r--r--src/de/danoeh/antennapod/feed/FeedItem.java42
-rw-r--r--src/de/danoeh/antennapod/feed/FeedManager.java53
-rw-r--r--src/de/danoeh/antennapod/feed/FeedMedia.java25
-rw-r--r--src/de/danoeh/antennapod/feed/SimpleChapter.java10
-rw-r--r--src/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java2
-rw-r--r--src/de/danoeh/antennapod/opml/OpmlReader.java8
-rw-r--r--src/de/danoeh/antennapod/service/download/DownloadService.java108
-rw-r--r--src/de/danoeh/antennapod/service/download/Downloader.java22
-rw-r--r--src/de/danoeh/antennapod/service/download/DownloaderCallback.java10
-rw-r--r--src/de/danoeh/antennapod/service/download/HttpDownloader.java78
-rw-r--r--src/de/danoeh/antennapod/storage/DownloadRequester.java26
-rw-r--r--src/de/danoeh/antennapod/storage/PodDBAdapter.java3
-rw-r--r--src/de/danoeh/antennapod/syndication/handler/SyndHandler.java2
-rw-r--r--src/de/danoeh/antennapod/syndication/namespace/simplechapters/NSSimpleChapters.java2
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";