summaryrefslogtreecommitdiff
path: root/src/de/danoeh/antennapod/service/download
diff options
context:
space:
mode:
Diffstat (limited to 'src/de/danoeh/antennapod/service/download')
-rw-r--r--src/de/danoeh/antennapod/service/download/APRedirectHandler.java11
-rw-r--r--src/de/danoeh/antennapod/service/download/AntennapodHttpClient.java3
-rw-r--r--src/de/danoeh/antennapod/service/download/DownloadRequest.java379
-rw-r--r--src/de/danoeh/antennapod/service/download/DownloadService.java210
-rw-r--r--src/de/danoeh/antennapod/service/download/DownloadStatus.java4
-rw-r--r--src/de/danoeh/antennapod/service/download/HttpDownloader.java90
6 files changed, 423 insertions, 274 deletions
diff --git a/src/de/danoeh/antennapod/service/download/APRedirectHandler.java b/src/de/danoeh/antennapod/service/download/APRedirectHandler.java
index 8a31c9390..ddf8d605d 100644
--- a/src/de/danoeh/antennapod/service/download/APRedirectHandler.java
+++ b/src/de/danoeh/antennapod/service/download/APRedirectHandler.java
@@ -1,14 +1,13 @@
package de.danoeh.antennapod.service.download;
-import java.net.URI;
-
+import android.util.Log;
+import de.danoeh.antennapod.BuildConfig;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.impl.client.DefaultRedirectHandler;
import org.apache.http.protocol.HttpContext;
-import android.util.Log;
-import de.danoeh.antennapod.AppConfig;
+import java.net.URI;
public class APRedirectHandler extends DefaultRedirectHandler {
// Identifier for logger
@@ -39,12 +38,12 @@ public class APRedirectHandler extends DefaultRedirectHandler {
// If anything had to be fixed, then replace the header
if (!s.equals(h[0].getValue()))
{
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Original URL: " + h[0].getValue());
response.setHeader(LOC, s);
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Fixed URL: " + s);
}
}
diff --git a/src/de/danoeh/antennapod/service/download/AntennapodHttpClient.java b/src/de/danoeh/antennapod/service/download/AntennapodHttpClient.java
index 7e1c9178a..7b3f014e8 100644
--- a/src/de/danoeh/antennapod/service/download/AntennapodHttpClient.java
+++ b/src/de/danoeh/antennapod/service/download/AntennapodHttpClient.java
@@ -2,6 +2,7 @@ package de.danoeh.antennapod.service.download;
import android.util.Log;
import de.danoeh.antennapod.AppConfig;
+import de.danoeh.antennapod.BuildConfig;
import org.apache.http.client.HttpClient;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.conn.ClientConnectionManager;
@@ -42,7 +43,7 @@ public class AntennapodHttpClient {
*/
public static synchronized HttpClient getHttpClient() {
if (httpClient == null) {
- if (AppConfig.DEBUG) Log.d(TAG, "Creating new instance of HTTP client");
+ if (BuildConfig.DEBUG) Log.d(TAG, "Creating new instance of HTTP client");
HttpParams params = new BasicHttpParams();
params.setParameter(CoreProtocolPNames.USER_AGENT, AppConfig.USER_AGENT);
diff --git a/src/de/danoeh/antennapod/service/download/DownloadRequest.java b/src/de/danoeh/antennapod/service/download/DownloadRequest.java
index 1f4e32e1b..be22bbebb 100644
--- a/src/de/danoeh/antennapod/service/download/DownloadRequest.java
+++ b/src/de/danoeh/antennapod/service/download/DownloadRequest.java
@@ -5,173 +5,214 @@ import android.os.Parcelable;
public class DownloadRequest implements Parcelable {
- private final String destination;
- private final String source;
- private final String title;
- private final long feedfileId;
- private final int feedfileType;
-
- protected int progressPercent;
- protected long soFar;
- protected long size;
- protected int statusMsg;
-
- public DownloadRequest(String destination, String source, String title,
- long feedfileId, int feedfileType) {
- if (destination == null) {
- throw new IllegalArgumentException("Destination must not be null");
- }
- if (source == null) {
- throw new IllegalArgumentException("Source must not be null");
- }
- if (title == null) {
- throw new IllegalArgumentException("Title must not be null");
- }
-
- this.destination = destination;
- this.source = source;
- this.title = title;
- this.feedfileId = feedfileId;
- this.feedfileType = feedfileType;
- }
-
- private DownloadRequest(Parcel in) {
- destination = in.readString();
- source = in.readString();
- title = in.readString();
- feedfileId = in.readLong();
- feedfileType = in.readInt();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(destination);
- dest.writeString(source);
- dest.writeString(title);
- dest.writeLong(feedfileId);
- dest.writeInt(feedfileType);
- }
-
- public static final Parcelable.Creator<DownloadRequest> CREATOR = new Parcelable.Creator<DownloadRequest>() {
- public DownloadRequest createFromParcel(Parcel in) {
- return new DownloadRequest(in);
- }
-
- public DownloadRequest[] newArray(int size) {
- return new DownloadRequest[size];
- }
- };
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result
- + ((destination == null) ? 0 : destination.hashCode());
- result = prime * result + (int) (feedfileId ^ (feedfileId >>> 32));
- result = prime * result + feedfileType;
- result = prime * result + progressPercent;
- result = prime * result + (int) (size ^ (size >>> 32));
- result = prime * result + (int) (soFar ^ (soFar >>> 32));
- result = prime * result + ((source == null) ? 0 : source.hashCode());
- result = prime * result + statusMsg;
- result = prime * result + ((title == null) ? 0 : title.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- DownloadRequest other = (DownloadRequest) obj;
- if (destination == null) {
- if (other.destination != null)
- return false;
- } else if (!destination.equals(other.destination))
- return false;
- if (feedfileId != other.feedfileId)
- return false;
- if (feedfileType != other.feedfileType)
- return false;
- if (progressPercent != other.progressPercent)
- return false;
- if (size != other.size)
- return false;
- if (soFar != other.soFar)
- return false;
- if (source == null) {
- if (other.source != null)
- return false;
- } else if (!source.equals(other.source))
- return false;
- if (statusMsg != other.statusMsg)
- return false;
- if (title == null) {
- if (other.title != null)
- return false;
- } else if (!title.equals(other.title))
- return false;
- return true;
- }
-
- public String getDestination() {
- return destination;
- }
-
- public String getSource() {
- return source;
- }
-
- public String getTitle() {
- return title;
- }
-
- public long getFeedfileId() {
- return feedfileId;
- }
-
- public int getFeedfileType() {
- return feedfileType;
- }
-
- public int getProgressPercent() {
- return progressPercent;
- }
-
- public void setProgressPercent(int progressPercent) {
- this.progressPercent = progressPercent;
- }
-
- public long getSoFar() {
- return soFar;
- }
-
- public void setSoFar(long soFar) {
- this.soFar = soFar;
- }
-
- public long getSize() {
- return size;
- }
-
- public void setSize(long size) {
- this.size = size;
- }
-
- public int getStatusMsg() {
- return statusMsg;
- }
-
- public void setStatusMsg(int statusMsg) {
- this.statusMsg = statusMsg;
- }
+ private final String destination;
+ private final String source;
+ private final String title;
+ private String username;
+ private String password;
+ private final long feedfileId;
+ private final int feedfileType;
+
+ protected int progressPercent;
+ protected long soFar;
+ protected long size;
+ protected int statusMsg;
+
+ public DownloadRequest(String destination, String source, String title,
+ long feedfileId, int feedfileType, String username, String password) {
+ if (destination == null) {
+ throw new IllegalArgumentException("Destination must not be null");
+ }
+ if (source == null) {
+ throw new IllegalArgumentException("Source must not be null");
+ }
+ if (title == null) {
+ throw new IllegalArgumentException("Title must not be null");
+ }
+
+ this.destination = destination;
+ this.source = source;
+ this.title = title;
+ this.feedfileId = feedfileId;
+ this.feedfileType = feedfileType;
+ this.username = username;
+ this.password = password;
+ }
+
+ public DownloadRequest(String destination, String source, String title,
+ long feedfileId, int feedfileType) {
+ this(destination, source, title, feedfileId, feedfileType, null, null);
+ }
+
+ private DownloadRequest(Parcel in) {
+ destination = in.readString();
+ source = in.readString();
+ title = in.readString();
+ feedfileId = in.readLong();
+ feedfileType = in.readInt();
+ if (in.dataAvail() > 0) {
+ username = in.readString();
+ } else {
+ username = null;
+ }
+ if (in.dataAvail() > 0) {
+ password = in.readString();
+ } else {
+ password = null;
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(destination);
+ dest.writeString(source);
+ dest.writeString(title);
+ dest.writeLong(feedfileId);
+ dest.writeInt(feedfileType);
+ if (username != null) {
+ dest.writeString(username);
+ }
+ if (password != null) {
+ dest.writeString(password);
+ }
+ }
+
+ public static final Parcelable.Creator<DownloadRequest> CREATOR = new Parcelable.Creator<DownloadRequest>() {
+ public DownloadRequest createFromParcel(Parcel in) {
+ return new DownloadRequest(in);
+ }
+
+ public DownloadRequest[] newArray(int size) {
+ return new DownloadRequest[size];
+ }
+ };
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((destination == null) ? 0 : destination.hashCode());
+ result = prime * result + (int) (feedfileId ^ (feedfileId >>> 32));
+ result = prime * result + feedfileType;
+ result = prime * result + progressPercent;
+ result = prime * result + (int) (size ^ (size >>> 32));
+ result = prime * result + (int) (soFar ^ (soFar >>> 32));
+ result = prime * result + ((source == null) ? 0 : source.hashCode());
+ result = prime * result + statusMsg;
+ result = prime * result + ((title == null) ? 0 : title.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ DownloadRequest other = (DownloadRequest) obj;
+ if (destination == null) {
+ if (other.destination != null)
+ return false;
+ } else if (!destination.equals(other.destination))
+ return false;
+ if (feedfileId != other.feedfileId)
+ return false;
+ if (feedfileType != other.feedfileType)
+ return false;
+ if (progressPercent != other.progressPercent)
+ return false;
+ if (size != other.size)
+ return false;
+ if (soFar != other.soFar)
+ return false;
+ if (source == null) {
+ if (other.source != null)
+ return false;
+ } else if (!source.equals(other.source))
+ return false;
+ if (statusMsg != other.statusMsg)
+ return false;
+ if (title == null) {
+ if (other.title != null)
+ return false;
+ } else if (!title.equals(other.title))
+ return false;
+ return true;
+ }
+
+ public String getDestination() {
+ return destination;
+ }
+
+ public String getSource() {
+ return source;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public long getFeedfileId() {
+ return feedfileId;
+ }
+
+ public int getFeedfileType() {
+ return feedfileType;
+ }
+
+ public int getProgressPercent() {
+ return progressPercent;
+ }
+
+ public void setProgressPercent(int progressPercent) {
+ this.progressPercent = progressPercent;
+ }
+
+ public long getSoFar() {
+ return soFar;
+ }
+
+ public void setSoFar(long soFar) {
+ this.soFar = soFar;
+ }
+
+ public long getSize() {
+ return size;
+ }
+
+ public void setSize(long size) {
+ this.size = size;
+ }
+
+ public int getStatusMsg() {
+ return statusMsg;
+ }
+
+ public void setStatusMsg(int statusMsg) {
+ this.statusMsg = statusMsg;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
}
diff --git a/src/de/danoeh/antennapod/service/download/DownloadService.java b/src/de/danoeh/antennapod/service/download/DownloadService.java
index c27b4d4fe..72e0852bb 100644
--- a/src/de/danoeh/antennapod/service/download/DownloadService.java
+++ b/src/de/danoeh/antennapod/service/download/DownloadService.java
@@ -1,20 +1,5 @@
package de.danoeh.antennapod.service.download;
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import javax.xml.parsers.ParserConfigurationException;
-
-import android.media.MediaMetadataRetriever;
-import de.danoeh.antennapod.storage.*;
-import org.xml.sax.SAXException;
-
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationManager;
@@ -26,27 +11,37 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
-import android.os.AsyncTask;
+import android.media.MediaMetadataRetriever;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.webkit.URLUtil;
-import de.danoeh.antennapod.AppConfig;
+import de.danoeh.antennapod.BuildConfig;
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.feed.EventDistributor;
-import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.feed.FeedImage;
-import de.danoeh.antennapod.feed.FeedItem;
-import de.danoeh.antennapod.feed.FeedMedia;
+import de.danoeh.antennapod.feed.*;
+import de.danoeh.antennapod.storage.*;
import de.danoeh.antennapod.syndication.handler.FeedHandler;
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;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* Manages the download of feedfiles in the app. Downloads can be enqueued viathe startService intent.
@@ -140,11 +135,11 @@ public class DownloadService extends Service {
@Override
public void run() {
- if (AppConfig.DEBUG) Log.d(TAG, "downloadCompletionThread was started");
+ if (BuildConfig.DEBUG) Log.d(TAG, "downloadCompletionThread was started");
while (!isInterrupted()) {
try {
Downloader downloader = downloadExecutor.take().get();
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Received 'Download Complete' - message.");
removeDownload(downloader);
DownloadStatus status = downloader.getResult();
@@ -162,21 +157,25 @@ public class DownloadService extends Service {
}
} else {
numberOfDownloads.decrementAndGet();
- if (!successful && !status.isCancelled()) {
- Log.e(TAG, "Download failed");
- saveDownloadStatus(status);
+ if (!status.isCancelled()) {
+ if (status.getReason() == DownloadError.ERROR_UNAUTHORIZED) {
+ postAuthenticationNotification(downloader.getDownloadRequest());
+ } else {
+ Log.e(TAG, "Download failed");
+ saveDownloadStatus(status);
+ }
}
sendDownloadHandledIntent();
queryDownloadsAsync();
}
} catch (InterruptedException e) {
- if (AppConfig.DEBUG) Log.d(TAG, "DownloadCompletionThread was interrupted");
+ if (BuildConfig.DEBUG) Log.d(TAG, "DownloadCompletionThread was interrupted");
} catch (ExecutionException e) {
e.printStackTrace();
numberOfDownloads.decrementAndGet();
}
}
- if (AppConfig.DEBUG) Log.d(TAG, "End of downloadCompletionThread");
+ if (BuildConfig.DEBUG) Log.d(TAG, "End of downloadCompletionThread");
}
};
@@ -193,7 +192,7 @@ public class DownloadService extends Service {
@SuppressLint("NewApi")
@Override
public void onCreate() {
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Service started");
isRunning = true;
handler = new Handler();
@@ -224,7 +223,9 @@ public class DownloadService extends Service {
t.setPriority(Thread.MIN_PRIORITY);
return t;
}
- }));
+ }
+ )
+ );
schedExecutor = new ScheduledThreadPoolExecutor(SCHED_EX_POOL_SIZE,
new ThreadFactory() {
@@ -255,7 +256,7 @@ public class DownloadService extends Service {
@Override
public void onDestroy() {
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Service shutting down");
isRunning = false;
updateReport();
@@ -274,8 +275,9 @@ public class DownloadService extends Service {
@SuppressLint("NewApi")
private void setupNotificationBuilders() {
PendingIntent pIntent = PendingIntent.getActivity(this, 0, new Intent(
- this, DownloadActivity.class),
- PendingIntent.FLAG_UPDATE_CURRENT);
+ this, DownloadActivity.class),
+ PendingIntent.FLAG_UPDATE_CURRENT
+ );
Bitmap icon = BitmapFactory.decodeResource(getResources(),
R.drawable.stat_notify_sync);
@@ -284,14 +286,15 @@ public class DownloadService extends Service {
notificationBuilder = new Notification.BigTextStyle(
new Notification.Builder(this).setOngoing(true)
.setContentIntent(pIntent).setLargeIcon(icon)
- .setSmallIcon(R.drawable.stat_notify_sync));
+ .setSmallIcon(R.drawable.stat_notify_sync)
+ );
} else {
notificationCompatBuilder = new NotificationCompat.Builder(this)
.setOngoing(true).setContentIntent(pIntent)
.setLargeIcon(icon)
.setSmallIcon(R.drawable.stat_notify_sync);
}
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Notification set up");
}
@@ -368,7 +371,7 @@ public class DownloadService extends Service {
throw new IllegalArgumentException(
"ACTION_CANCEL_DOWNLOAD intent needs download url extra");
}
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Cancelling download with url " + url);
Downloader d = getDownloader(url);
if (d != null) {
@@ -380,7 +383,7 @@ public class DownloadService extends Service {
} else if (intent.getAction().equals(ACTION_CANCEL_ALL_DOWNLOADS)) {
for (Downloader d : downloads) {
d.cancel();
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Cancelled all downloads");
}
sendBroadcast(new Intent(ACTION_DOWNLOADS_CONTENT_CHANGED));
@@ -392,7 +395,7 @@ public class DownloadService extends Service {
};
private void onDownloadQueued(Intent intent) {
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Received enqueue request");
DownloadRequest request = intent.getParcelableExtra(EXTRA_REQUEST);
if (request == null) {
@@ -413,12 +416,13 @@ public class DownloadService extends Service {
private Downloader getDownloader(DownloadRequest request) {
if (URLUtil.isHttpUrl(request.getSource())
- || URLUtil.isHttpsUrl(request.getSource())) {
+ || URLUtil.isHttpsUrl(request.getSource())) {
return new HttpDownloader(request);
}
Log.e(TAG,
"Could not find appropriate downloader for "
- + request.getSource());
+ + request.getSource()
+ );
return null;
}
@@ -430,11 +434,11 @@ public class DownloadService extends Service {
handler.post(new Runnable() {
@Override
public void run() {
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Removing downloader: "
+ d.getDownloadRequest().getSource());
boolean rc = downloads.remove(d);
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Result of downloads.remove: " + rc);
DownloadRequester.getInstance().removeDownload(d.getDownloadRequest());
sendBroadcast(new Intent(ACTION_DOWNLOADS_CONTENT_CHANGED));
@@ -484,7 +488,7 @@ public class DownloadService extends Service {
}
if (createReport) {
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Creating report");
// create notification object
Notification notification = new NotificationCompat.Builder(this)
@@ -495,19 +499,22 @@ public class DownloadService extends Service {
.setContentText(
String.format(
getString(R.string.download_report_content),
- successfulDownloads, failedDownloads))
+ successfulDownloads, failedDownloads)
+ )
.setSmallIcon(R.drawable.stat_notify_sync)
.setLargeIcon(
BitmapFactory.decodeResource(getResources(),
- R.drawable.stat_notify_sync))
+ R.drawable.stat_notify_sync)
+ )
.setContentIntent(
PendingIntent.getActivity(this, 0, new Intent(this,
- DownloadLogActivity.class), 0))
+ DownloadLogActivity.class), 0)
+ )
.setAutoCancel(true).getNotification();
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify(REPORT_ID, notification);
} else {
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "No report is created");
}
completedDownloads.clear();
@@ -530,12 +537,12 @@ public class DownloadService extends Service {
* Check if there's something else to download, otherwise stop
*/
void queryDownloads() {
- if (AppConfig.DEBUG) {
+ if (BuildConfig.DEBUG) {
Log.d(TAG, numberOfDownloads.get() + " downloads left");
}
if (numberOfDownloads.get() <= 0 && DownloadRequester.getInstance().hasNoDownloads()) {
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Number of downloads is " + numberOfDownloads.get() + ", attempting shutdown");
stopSelf();
} else {
@@ -544,11 +551,40 @@ public class DownloadService extends Service {
}
}
+ private void postAuthenticationNotification(final DownloadRequest downloadRequest) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ final String resourceTitle = (downloadRequest.getTitle() != null)
+ ? downloadRequest.getTitle() : downloadRequest.getSource();
+
+ final Intent activityIntent = new Intent(getApplicationContext(), DownloadAuthenticationActivity.class);
+ activityIntent.putExtra(DownloadAuthenticationActivity.ARG_DOWNLOAD_REQUEST, downloadRequest);
+ activityIntent.putExtra(DownloadAuthenticationActivity.ARG_SEND_TO_DOWNLOAD_REQUESTER_BOOL, true);
+ final PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, activityIntent, PendingIntent.FLAG_ONE_SHOT);
+
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(DownloadService.this);
+ builder.setTicker(getText(R.string.authentication_notification_title))
+ .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))
+ .setSmallIcon(R.drawable.ic_stat_authentication)
+ .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_stat_authentication))
+ .setAutoCancel(true)
+ .setContentIntent(contentIntent);
+ Notification n = builder.build();
+ NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+ nm.notify(downloadRequest.getSource().hashCode(), n);
+ }
+ });
+ }
+
/**
* Is called whenever a Feed is downloaded
*/
private void handleCompletedFeedDownload(DownloadRequest request) {
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Handling completed Feed Download");
syncExecutor.execute(new FeedSyncThread(request));
@@ -558,7 +594,7 @@ public class DownloadService extends Service {
* Is called whenever a Feed-Image is downloaded
*/
private void handleCompletedImageDownload(DownloadStatus status, DownloadRequest request) {
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Handling completed Image Download");
syncExecutor.execute(new ImageHandlerThread(status, request));
}
@@ -567,7 +603,7 @@ public class DownloadService extends Service {
* Is called whenever a FeedMedia is downloaded.
*/
private void handleCompletedFeedMediaDownload(DownloadStatus status, DownloadRequest request) {
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Handling completed FeedMedia Download");
syncExecutor.execute(new MediaHandlerThread(status, request));
}
@@ -598,6 +634,7 @@ public class DownloadService extends Service {
Feed feed = new Feed(request.getSource(), new Date());
feed.setFile_url(request.getDestination());
feed.setDownloaded(true);
+ feed.setPreferences(new FeedPreferences(0, true, request.getUsername(), request.getPassword()));
reason = null;
String reasonDetailed = null;
@@ -606,19 +643,22 @@ public class DownloadService extends Service {
try {
feed = feedHandler.parseFeed(feed);
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, feed.getTitle() + " parsed");
if (checkFeedData(feed) == false) {
throw new InvalidFeedException();
}
+
+ removeDuplicateImages(feed); // duplicate images have to removed because the DownloadRequester does not accept two downloads with the same download URL yet.
+
// Save information of feed in DB
savedFeed = DBTasks.updateFeed(DownloadService.this, feed);
// Download Feed Image if provided and not downloaded
if (savedFeed.getImage() != null
&& savedFeed.getImage().isDownloaded() == false) {
- if (AppConfig.DEBUG)
+ if (BuildConfig.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,
@@ -633,9 +673,36 @@ public class DownloadService extends Service {
.getImage()
.getHumanReadableIdentifier(),
DownloadError.ERROR_REQUEST_ERROR,
- false, e.getMessage()));
+ false, e.getMessage()
+ )
+ );
}
}
+ // download FeedItem images if provided and not downloaded
+ for (FeedItem item : savedFeed.getItems()) {
+ if (item.hasItemImage() && (!item.getImage().isDownloaded())) {
+ if (BuildConfig.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;
@@ -689,10 +756,29 @@ public class DownloadService extends Service {
Log.e(TAG, "Feed has invalid items");
return false;
}
- if (AppConfig.DEBUG)
+ if (BuildConfig.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. If two FeedItems have an image that points to
+ * the same URL, the reference of the second item is removed, so that every image
+ * reference is unique.
+ */
+ private void removeDuplicateImages(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())) {
+ item2.setImage(null);
+ }
+ }
+ }
+ }
}
private boolean hasValidFeedItems(Feed feed) {
@@ -719,12 +805,12 @@ public class DownloadService extends Service {
private void cleanup(Feed feed) {
if (feed.getFile_url() != null) {
if (new File(feed.getFile_url()).delete())
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Successfully deleted cache file.");
else
Log.e(TAG, "Failed to delete cache file.");
feed.setFile_url(null);
- } else if (AppConfig.DEBUG) {
+ } else if (BuildConfig.DEBUG) {
Log.d(TAG, "Didn't delete cache file: File url is not set.");
}
}
@@ -807,7 +893,7 @@ public class DownloadService extends Service {
mmr.setDataSource(media.getFile_url());
String durationStr = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
media.setDuration(Integer.parseInt(durationStr));
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Duration of file is " + media.getDuration());
} catch (NumberFormatException e) {
e.printStackTrace();
@@ -854,7 +940,7 @@ public class DownloadService extends Service {
* Schedules the notification updater task if it hasn't been scheduled yet.
*/
private void setupNotificationUpdater() {
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Setting up notification updater");
if (notificationUpdater == null) {
notificationUpdater = new NotificationUpdater();
diff --git a/src/de/danoeh/antennapod/service/download/DownloadStatus.java b/src/de/danoeh/antennapod/service/download/DownloadStatus.java
index 487c3b3de..b240cddbc 100644
--- a/src/de/danoeh/antennapod/service/download/DownloadStatus.java
+++ b/src/de/danoeh/antennapod/service/download/DownloadStatus.java
@@ -1,10 +1,10 @@
package de.danoeh.antennapod.service.download;
-import java.util.Date;
-
import de.danoeh.antennapod.feed.FeedFile;
import de.danoeh.antennapod.util.DownloadError;
+import java.util.Date;
+
/** Contains status attributes for one download */
public class DownloadStatus {
/**
diff --git a/src/de/danoeh/antennapod/service/download/HttpDownloader.java b/src/de/danoeh/antennapod/service/download/HttpDownloader.java
index fc2b3178b..84bafb027 100644
--- a/src/de/danoeh/antennapod/service/download/HttpDownloader.java
+++ b/src/de/danoeh/antennapod/service/download/HttpDownloader.java
@@ -2,20 +2,27 @@ package de.danoeh.antennapod.service.download;
import android.net.http.AndroidHttpClient;
import android.util.Log;
-import de.danoeh.antennapod.AppConfig;
+import de.danoeh.antennapod.BuildConfig;
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;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
+import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.auth.BasicScheme;
import java.io.*;
-import java.net.*;
+import java.net.HttpURLConnection;
+import java.net.SocketTimeoutException;
+import java.net.UnknownHostException;
public class HttpDownloader extends Downloader {
private static final String TAG = "HttpDownloader";
@@ -26,24 +33,37 @@ public class HttpDownloader extends Downloader {
super(request);
}
- private URI getURIFromRequestUrl(String source) {
- try {
- URL url = new URL(source);
- return new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
- } catch (MalformedURLException e) {
- throw new IllegalArgumentException(e);
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
@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;
try {
- HttpGet httpGet = new HttpGet(getURIFromRequestUrl(request.getSource()));
+ HttpGet httpGet = new HttpGet(URIUtil.getURIFromRequestUrl(request.getSource()));
+ String userInfo = httpGet.getURI().getUserInfo();
+ if (userInfo != null) {
+ String[] parts = userInfo.split(":");
+ if (parts.length == 2) {
+ httpGet.addHeader(BasicScheme.authenticate(
+ new UsernamePasswordCredentials(parts[0], parts[1]),
+ "UTF-8", false));
+ }
+ } else if (!StringUtils.isEmpty(request.getUsername()) && request.getPassword() != null) {
+ httpGet.addHeader(BasicScheme.authenticate(new UsernamePasswordCredentials(request.getUsername(),
+ request.getPassword()), "UTF-8", false));
+ }
HttpResponse response = httpClient.execute(httpGet);
HttpEntity httpEntity = response.getEntity();
int responseCode = response.getStatusLine().getStatusCode();
@@ -52,12 +72,20 @@ public class HttpDownloader extends Downloader {
final boolean isGzip = contentEncodingHeader != null &&
contentEncodingHeader.getValue().equalsIgnoreCase("gzip");
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Response code is " + responseCode);
if (responseCode != HttpURLConnection.HTTP_OK || httpEntity == null) {
- onFail(DownloadError.ERROR_HTTP_DATA_ERROR,
- String.valueOf(responseCode));
+ final DownloadError error;
+ final String details;
+ if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
+ error = DownloadError.ERROR_UNAUTHORIZED;
+ details = String.valueOf(responseCode);
+ } else {
+ error = DownloadError.ERROR_HTTP_DATA_ERROR;
+ details = String.valueOf(responseCode);
+ }
+ onFail(error, details);
return;
}
@@ -66,13 +94,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(
@@ -80,17 +101,17 @@ public class HttpDownloader extends Downloader {
byte[] buffer = new byte[BUFFER_SIZE];
int count = 0;
request.setStatusMsg(R.string.download_running);
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Getting size of download");
request.setSize(httpEntity.getContentLength());
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Size is " + request.getSize());
if (request.getSize() < 0) {
request.setSize(DownloadStatus.SIZE_UNKNOWN);
}
long freeSpace = StorageUtils.getFreeSpaceAvailable();
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Free space is " + freeSpace);
if (request.getSize() != DownloadStatus.SIZE_UNKNOWN
@@ -99,7 +120,7 @@ public class HttpDownloader extends Downloader {
return;
}
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Starting download");
while (!cancelled
&& (count = connection.read(buffer)) != -1) {
@@ -121,7 +142,8 @@ public class HttpDownloader extends Downloader {
"Download completed but size: " +
request.getSoFar() +
" does not equal expected size " +
- request.getSize());
+ request.getSize()
+ );
return;
}
onSuccess();
@@ -150,13 +172,13 @@ public class HttpDownloader extends Downloader {
}
private void onSuccess() {
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Download was successful");
result.setSuccessful();
}
private void onFail(DownloadError reason, String reasonDetailed) {
- if (AppConfig.DEBUG) {
+ if (BuildConfig.DEBUG) {
Log.d(TAG, "Download failed");
}
result.setFailed(reason, reasonDetailed);
@@ -164,7 +186,7 @@ public class HttpDownloader extends Downloader {
}
private void onCancelled() {
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Download was cancelled");
result.setCancelled();
cleanup();
@@ -178,11 +200,11 @@ public class HttpDownloader extends Downloader {
File dest = new File(request.getDestination());
if (dest.exists()) {
boolean rc = dest.delete();
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "Deleted file " + dest.getName() + "; Result: "
+ rc);
} else {
- if (AppConfig.DEBUG)
+ if (BuildConfig.DEBUG)
Log.d(TAG, "cleanup() didn't delete file: does not exist.");
}
}