diff options
Diffstat (limited to 'core')
22 files changed, 162 insertions, 59 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java index 75d6570b2..41bbd5ba6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadRequest.java @@ -6,6 +6,9 @@ import android.os.Parcelable; import org.apache.commons.lang3.Validate; +import de.danoeh.antennapod.core.feed.FeedFile; +import de.danoeh.antennapod.core.util.URLChecker; + public class DownloadRequest implements Parcelable { private final String destination; @@ -13,6 +16,7 @@ public class DownloadRequest implements Parcelable { private final String title; private String username; private String password; + private long ifModifiedSince; private boolean deleteOnFailure; private final long feedfileId; private final int feedfileType; @@ -45,12 +49,26 @@ public class DownloadRequest implements Parcelable { this(destination, source, title, feedfileId, feedfileType, null, null, true, null); } + public DownloadRequest(Builder builder) { + this.destination = builder.destination; + this.source = builder.source; + this.title = builder.title; + this.feedfileId = builder.feedfileId; + this.feedfileType = builder.feedfileType; + this.username = builder.username; + this.password = builder.password; + this.ifModifiedSince = builder.ifModifiedSince; + this.deleteOnFailure = builder.deleteOnFailure; + this.arguments = (builder.arguments != null) ? builder.arguments : new Bundle(); + } + private DownloadRequest(Parcel in) { destination = in.readString(); source = in.readString(); title = in.readString(); feedfileId = in.readLong(); feedfileType = in.readInt(); + ifModifiedSince = in.readLong(); deleteOnFailure = (in.readByte() > 0); arguments = in.readBundle(); if (in.dataAvail() > 0) { @@ -77,6 +95,7 @@ public class DownloadRequest implements Parcelable { dest.writeString(title); dest.writeLong(feedfileId); dest.writeInt(feedfileType); + dest.writeLong(ifModifiedSince); dest.writeByte((deleteOnFailure) ? (byte) 1 : 0); dest.writeBundle(arguments); if (username != null) { @@ -105,6 +124,7 @@ public class DownloadRequest implements Parcelable { DownloadRequest that = (DownloadRequest) o; + if (ifModifiedSince != that.ifModifiedSince) return false; if (deleteOnFailure != that.deleteOnFailure) return false; if (feedfileId != that.feedfileId) return false; if (feedfileType != that.feedfileType) return false; @@ -131,6 +151,7 @@ public class DownloadRequest implements Parcelable { result = 31 * result + (title != null ? title.hashCode() : 0); result = 31 * result + (username != null ? username.hashCode() : 0); result = 31 * result + (password != null ? password.hashCode() : 0); + result = 31 * result + (int)ifModifiedSince; result = 31 * result + (deleteOnFailure ? 1 : 0); result = 31 * result + (int) (feedfileId ^ (feedfileId >>> 32)); result = 31 * result + feedfileType; @@ -210,6 +231,15 @@ public class DownloadRequest implements Parcelable { this.password = password; } + public DownloadRequest setIfModifiedSince(long time) { + this.ifModifiedSince = time; + return this; + } + + public long getIfModifiedSince() { + return this.ifModifiedSince; + } + public boolean isDeleteOnFailure() { return deleteOnFailure; } @@ -217,4 +247,54 @@ public class DownloadRequest implements Parcelable { public Bundle getArguments() { return arguments; } + + public static class Builder { + private String destination; + private String source; + private String title; + private String username; + private String password; + private long ifModifiedSince; + private boolean deleteOnFailure = false; + private long feedfileId; + private int feedfileType; + private Bundle arguments; + + public Builder(String destination, FeedFile item) { + this.destination = destination; + this.source = URLChecker.prepareURL(item.getDownload_url()); + this.title = item.getHumanReadableIdentifier(); + this.feedfileId = item.getId(); + this.feedfileType = item.getTypeAsInt(); + } + + public Builder deleteOnFailure(boolean deleteOnFailure) { + this.deleteOnFailure = deleteOnFailure; + return this; + } + + public Builder ifModifiedSince(long time) { + this.ifModifiedSince = time; + return this; + } + + public Builder withAuthentication(String username, String password) { + this.username = username; + this.password = password; + return this; + } + + public DownloadRequest build() { + Validate.notNull(destination); + Validate.notNull(source); + Validate.notNull(title); + return new DownloadRequest(this); + } + + public Builder withArguments(Bundle args) { + this.arguments = args; + return this; + } + + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java index 6bfd9b4a0..7abb6df5e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java @@ -7,6 +7,7 @@ import com.squareup.okhttp.OkHttpClient; import com.squareup.okhttp.Request; import com.squareup.okhttp.Response; import com.squareup.okhttp.ResponseBody; +import com.squareup.okhttp.internal.http.HttpDate; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; @@ -21,6 +22,7 @@ import java.net.HttpURLConnection; import java.net.SocketTimeoutException; import java.net.URI; import java.net.UnknownHostException; +import java.util.Date; import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.ClientConfig; @@ -64,6 +66,15 @@ public class HttpDownloader extends Downloader { final URI uri = URIUtil.getURIFromRequestUrl(request.getSource()); Request.Builder httpReq = new Request.Builder().url(uri.toURL()) .header("User-Agent", ClientConfig.USER_AGENT); + if(request.getIfModifiedSince() > 0) { + long threeDaysAgo = System.currentTimeMillis() - 1000*60*60*24*3; + if(request.getIfModifiedSince() > threeDaysAgo) { + Date date = new Date(request.getIfModifiedSince()); + String httpDate = HttpDate.format(date); + Log.d(TAG, "addHeader(\"If-Modified-Since\", \"" + httpDate + "\")"); + httpReq.addHeader("If-Modified-Since", httpDate); + } + } // add authentication information String userInfo = uri.getUserInfo(); @@ -83,7 +94,7 @@ public class HttpDownloader extends Downloader { request.setSoFar(destination.length()); httpReq.addHeader("Range", "bytes=" + request.getSoFar() + "-"); - if (BuildConfig.DEBUG) Log.d(TAG, "Adding range header: " + request.getSoFar()); + Log.d(TAG, "Adding range header: " + request.getSoFar()); } Response response = httpClient.newCall(httpReq.build()).execute(); @@ -96,6 +107,12 @@ public class HttpDownloader extends Downloader { if (BuildConfig.DEBUG) Log.d(TAG, "Response code is " + response.code()); + if(!response.isSuccessful() && response.code() == HttpURLConnection.HTTP_NOT_MODIFIED) { + Log.d(TAG, "Feed '" + request.getSource() + "' not modified since last update, Download canceled"); + onCancelled(); + return; + } + if (!response.isSuccessful() || response.body() == null) { final DownloadError error; final String details; diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index e73f9599d..e0e370b0d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -298,7 +298,8 @@ public final class DBTasks { } /** - * Updates a specific Feed. + * Refresh a specific Feed. The refresh may get canceled if the feed does not seem to be modified + * and the last update was only few days ago. * * @param context Used for requesting the download. * @param feed The Feed object. @@ -311,9 +312,9 @@ public final class DBTasks { private static void refreshFeed(Context context, Feed feed, boolean loadAllPages) throws DownloadRequestException { Feed f; if (feed.getPreferences() == null) { - f = new Feed(feed.getDownload_url(), new Date(), feed.getTitle()); + f = new Feed(feed.getDownload_url(), feed.getLastUpdate(), feed.getTitle()); } else { - f = new Feed(feed.getDownload_url(), new Date(), feed.getTitle(), + f = new Feed(feed.getDownload_url(), feed.getLastUpdate(), feed.getTitle(), feed.getPreferences().getUsername(), feed.getPreferences().getPassword()); } f.setId(feed.getId()); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java index d0cdad649..ca6aa0178 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java @@ -91,57 +91,53 @@ public class DownloadRequester { } private void download(Context context, FeedFile item, FeedFile container, File dest, - boolean overwriteIfExists, String username, String password, boolean deleteOnFailure, Bundle arguments) { + boolean overwriteIfExists, String username, String password, + long ifModifiedSince, boolean deleteOnFailure, Bundle arguments) { final boolean partiallyDownloadedFileExists = item.getFile_url() != null; - if (!isDownloadingFile(item)) { - if (!isFilenameAvailable(dest.toString()) || (!partiallyDownloadedFileExists && dest.exists())) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Filename already used."); - if (isFilenameAvailable(dest.toString()) && overwriteIfExists) { - boolean result = dest.delete(); - if (BuildConfig.DEBUG) - Log.d(TAG, "Deleting file. Result: " + result); - } else { - // find different name - File newDest = null; - for (int i = 1; i < Integer.MAX_VALUE; i++) { - String newName = FilenameUtils.getBaseName(dest - .getName()) - + "-" - + i - + FilenameUtils.EXTENSION_SEPARATOR - + FilenameUtils.getExtension(dest.getName()); - if (BuildConfig.DEBUG) - Log.d(TAG, "Testing filename " + newName); - newDest = new File(dest.getParent(), newName); - if (!newDest.exists() - && isFilenameAvailable(newDest.toString())) { - if (BuildConfig.DEBUG) - Log.d(TAG, "File doesn't exist yet. Using " - + newName); - break; - } - } - if (newDest != null) { - dest = newDest; + if (isDownloadingFile(item)) { + Log.e(TAG, "URL " + item.getDownload_url() + + " is already being downloaded"); + return; + } + if (!isFilenameAvailable(dest.toString()) || (!partiallyDownloadedFileExists && dest.exists())) { + Log.d(TAG, "Filename already used."); + if (isFilenameAvailable(dest.toString()) && overwriteIfExists) { + boolean result = dest.delete(); + Log.d(TAG, "Deleting file. Result: " + result); + } else { + // find different name + File newDest = null; + for (int i = 1; i < Integer.MAX_VALUE; i++) { + String newName = FilenameUtils.getBaseName(dest + .getName()) + + "-" + + i + + FilenameUtils.EXTENSION_SEPARATOR + + FilenameUtils.getExtension(dest.getName()); + Log.d(TAG, "Testing filename " + newName); + newDest = new File(dest.getParent(), newName); + if (!newDest.exists() + && isFilenameAvailable(newDest.toString())) { + Log.d(TAG, "File doesn't exist yet. Using " + newName); + break; } } + if (newDest != null) { + dest = newDest; + } } - if (BuildConfig.DEBUG) - Log.d(TAG, - "Requesting download of url " + item.getDownload_url()); - String baseUrl = (container != null) ? container.getDownload_url() : null; - item.setDownload_url(URLChecker.prepareURL(item.getDownload_url(), baseUrl)); - - DownloadRequest request = new DownloadRequest(dest.toString(), - URLChecker.prepareURL(item.getDownload_url()), item.getHumanReadableIdentifier(), - item.getId(), item.getTypeAsInt(), username, password, deleteOnFailure, arguments); - - download(context, request); - } else { - Log.e(TAG, "URL " + item.getDownload_url() - + " is already being downloaded"); } + Log.d(TAG, "Requesting download of url " + item.getDownload_url()); + String baseUrl = (container != null) ? container.getDownload_url() : null; + item.setDownload_url(URLChecker.prepareURL(item.getDownload_url(), baseUrl)); + + DownloadRequest.Builder builder = new DownloadRequest.Builder(dest.toString(), item) + .withAuthentication(username, password) + .ifModifiedSince(ifModifiedSince) + .deleteOnFailure(deleteOnFailure) + .withArguments(arguments); + DownloadRequest request = builder.build(); + download(context, request); } /** @@ -163,18 +159,26 @@ public class DownloadRequester { return true; } + /** + * Downloads a feed + * + * @param context The application's environment. + * @param feed Feed to download + * @param loadAllPages Set to true to download all pages + */ public synchronized void downloadFeed(Context context, Feed feed, boolean loadAllPages) throws DownloadRequestException { if (feedFileValid(feed)) { String username = (feed.getPreferences() != null) ? feed.getPreferences().getUsername() : null; String password = (feed.getPreferences() != null) ? feed.getPreferences().getPassword() : null; + long ifModifiedSince = feed.getLastUpdate().getTime(); Bundle args = new Bundle(); args.putInt(REQUEST_ARG_PAGE_NR, feed.getPageNr()); args.putBoolean(REQUEST_ARG_LOAD_ALL_PAGES, loadAllPages); download(context, feed, null, new File(getFeedfilePath(context), - getFeedfileName(feed)), true, username, password, true, args); + getFeedfileName(feed)), true, username, password, ifModifiedSince, true, args); } } @@ -187,7 +191,7 @@ public class DownloadRequester { if (feedFileValid(image)) { FeedFile container = (image.getOwner() instanceof FeedFile) ? (FeedFile) image.getOwner() : null; download(context, image, container, new File(getImagefilePath(context), - getImagefileName(image)), false, null, null, false, null); + getImagefileName(image)), false, null, null, 0, false, null); } } @@ -213,7 +217,7 @@ public class DownloadRequester { getMediafilename(feedmedia)); } download(context, feedmedia, feed, - dest, false, username, password, false, null); + dest, false, username, password, 0, false, null); } } diff --git a/core/src/main/res/drawable-hdpi/ic_drag_handle.9.png b/core/src/main/res/drawable-hdpi/ic_drag_handle.9.png Binary files differnew file mode 100644 index 000000000..939454989 --- /dev/null +++ b/core/src/main/res/drawable-hdpi/ic_drag_handle.9.png diff --git a/core/src/main/res/drawable-hdpi/ic_drag_handle.png b/core/src/main/res/drawable-hdpi/ic_drag_handle.png Binary files differdeleted file mode 100755 index 38ec201de..000000000 --- a/core/src/main/res/drawable-hdpi/ic_drag_handle.png +++ /dev/null diff --git a/core/src/main/res/drawable-hdpi/ic_drag_handle_dark.9.png b/core/src/main/res/drawable-hdpi/ic_drag_handle_dark.9.png Binary files differnew file mode 100644 index 000000000..65b9ec1fa --- /dev/null +++ b/core/src/main/res/drawable-hdpi/ic_drag_handle_dark.9.png diff --git a/core/src/main/res/drawable-hdpi/ic_drag_handle_dark.png b/core/src/main/res/drawable-hdpi/ic_drag_handle_dark.png Binary files differdeleted file mode 100755 index e96d23252..000000000 --- a/core/src/main/res/drawable-hdpi/ic_drag_handle_dark.png +++ /dev/null diff --git a/core/src/main/res/drawable-mdpi/ic_drag_handle.9.png b/core/src/main/res/drawable-mdpi/ic_drag_handle.9.png Binary files differnew file mode 100644 index 000000000..8de13a08b --- /dev/null +++ b/core/src/main/res/drawable-mdpi/ic_drag_handle.9.png diff --git a/core/src/main/res/drawable-mdpi/ic_drag_handle.png b/core/src/main/res/drawable-mdpi/ic_drag_handle.png Binary files differdeleted file mode 100755 index 4afbdc67d..000000000 --- a/core/src/main/res/drawable-mdpi/ic_drag_handle.png +++ /dev/null diff --git a/core/src/main/res/drawable-mdpi/ic_drag_handle_dark.9.png b/core/src/main/res/drawable-mdpi/ic_drag_handle_dark.9.png Binary files differnew file mode 100644 index 000000000..e24681d12 --- /dev/null +++ b/core/src/main/res/drawable-mdpi/ic_drag_handle_dark.9.png diff --git a/core/src/main/res/drawable-mdpi/ic_drag_handle_dark.png b/core/src/main/res/drawable-mdpi/ic_drag_handle_dark.png Binary files differdeleted file mode 100755 index 2b25c4101..000000000 --- a/core/src/main/res/drawable-mdpi/ic_drag_handle_dark.png +++ /dev/null diff --git a/core/src/main/res/drawable-xhdpi/ic_drag_handle.9.png b/core/src/main/res/drawable-xhdpi/ic_drag_handle.9.png Binary files differnew file mode 100644 index 000000000..46b8a5ad8 --- /dev/null +++ b/core/src/main/res/drawable-xhdpi/ic_drag_handle.9.png diff --git a/core/src/main/res/drawable-xhdpi/ic_drag_handle.png b/core/src/main/res/drawable-xhdpi/ic_drag_handle.png Binary files differdeleted file mode 100755 index 5bdcac342..000000000 --- a/core/src/main/res/drawable-xhdpi/ic_drag_handle.png +++ /dev/null diff --git a/core/src/main/res/drawable-xhdpi/ic_drag_handle_dark.9.png b/core/src/main/res/drawable-xhdpi/ic_drag_handle_dark.9.png Binary files differnew file mode 100644 index 000000000..864fae9e8 --- /dev/null +++ b/core/src/main/res/drawable-xhdpi/ic_drag_handle_dark.9.png diff --git a/core/src/main/res/drawable-xhdpi/ic_drag_handle_dark.png b/core/src/main/res/drawable-xhdpi/ic_drag_handle_dark.png Binary files differdeleted file mode 100755 index d341c7c82..000000000 --- a/core/src/main/res/drawable-xhdpi/ic_drag_handle_dark.png +++ /dev/null diff --git a/core/src/main/res/drawable-xxhdpi/ic_drag_handle.9.png b/core/src/main/res/drawable-xxhdpi/ic_drag_handle.9.png Binary files differnew file mode 100644 index 000000000..0e99bde9e --- /dev/null +++ b/core/src/main/res/drawable-xxhdpi/ic_drag_handle.9.png diff --git a/core/src/main/res/drawable-xxhdpi/ic_drag_handle.png b/core/src/main/res/drawable-xxhdpi/ic_drag_handle.png Binary files differdeleted file mode 100755 index f834699c6..000000000 --- a/core/src/main/res/drawable-xxhdpi/ic_drag_handle.png +++ /dev/null diff --git a/core/src/main/res/drawable-xxhdpi/ic_drag_handle_dark.9.png b/core/src/main/res/drawable-xxhdpi/ic_drag_handle_dark.9.png Binary files differnew file mode 100644 index 000000000..0da191a69 --- /dev/null +++ b/core/src/main/res/drawable-xxhdpi/ic_drag_handle_dark.9.png diff --git a/core/src/main/res/drawable-xxhdpi/ic_drag_handle_dark.png b/core/src/main/res/drawable-xxhdpi/ic_drag_handle_dark.png Binary files differdeleted file mode 100755 index a9408bc9d..000000000 --- a/core/src/main/res/drawable-xxhdpi/ic_drag_handle_dark.png +++ /dev/null diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 72e7a2b31..e15bb10a6 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -71,7 +71,7 @@ <!-- 'Add Feed' Activity labels --> <string name="feedurl_label">Feed URL</string> - <string name="etxtFeedurlHint">URL of feed or website</string> + <string name="etxtFeedurlHint">www.example.com/feed</string> <string name="txtvfeedurl_label">Add Podcast by URL</string> <string name="podcastdirectories_label">Find podcast in directory</string> <string name="podcastdirectories_descr">You can search for new podcasts by name, category or popularity in the gpodder.net directory, or search the iTunes store.</string> @@ -293,8 +293,9 @@ <!-- OPML import and export --> <string name="opml_import_txtv_button_lable">OPML files allow you to move your podcasts from one podcatcher to another.</string> - <string name="opml_import_explanation">To import an OPML file, you have to place it in the following directory and press the button below to start the import process. </string> - <string name="start_import_label">Start import</string> + <string name="opml_import_explanation_1">Choose a specific file path from the local filesystem.</string> + <string name="opml_import_explanation_2">Use an external applications like Dropbox, Google Drive or your favourite file manager to open an OPML file.</string> + <string name="opml_import_explanation_3">Many applications like Google Mail, Dropbox, Google Drive and most file managers can <i>open</i> OPML files <i>with</i> AntennaPod.</string> <string name="start_import_label">Start import</string> <string name="opml_import_label">OPML import</string> <string name="opml_directory_error">ERROR!</string> <string name="reading_opml_label">Reading OPML file</string> @@ -302,11 +303,12 @@ <string name="opml_import_error_dir_empty">The import directory is empty.</string> <string name="select_all_label">Select all</string> <string name="deselect_all_label">Deselect all</string> - <string name="choose_file_to_import_label">Choose file to import</string> + <string name="choose_file_from_filesystem">From local filesystem</string> + <string name="choose_file_from_external_application">Use external application</string> <string name="opml_export_label">OPML export</string> <string name="exporting_label">Exporting...</string> <string name="export_error_label">Export error</string> - <string name="opml_export_success_title">Opml export successful.</string> + <string name="opml_export_success_title">OPML export successful.</string> <string name="opml_export_success_sum">The .opml file was written to:\u0020</string> <!-- Sleep timer --> diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml index e8b0e2b2b..4ac4a79fd 100644 --- a/core/src/main/res/values/styles.xml +++ b/core/src/main/res/values/styles.xml @@ -219,7 +219,6 @@ <style name="AntennaPod.TextView.Heading" parent="@android:style/TextAppearance.Medium"> <item name="android:textSize">@dimen/text_size_large</item> - <item name="android:textStyle">italic</item> <item name="android:textColor">?android:attr/textColorPrimary</item> </style> |