From a704a33e2b31a7312f35f33251faaf1017b982d9 Mon Sep 17 00:00:00 2001
From: daniel oeh <daniel.oeh@gmail.com>
Date: Sun, 19 May 2013 17:32:15 +0200
Subject: [PATCH] Split DownloadStatus into two separate classes

DownloadStatus is now used only for finished downloads, whereas
DownloadRequest is used for running/unfinished downloads
---
 .../antennapod/activity/DownloadActivity.java |  11 +-
 .../activity/OnlineFeedViewActivity.java      |  29 +-
 .../adapter/DownloadLogAdapter.java           |   2 +-
 .../adapter/DownloadlistAdapter.java          |  39 +--
 .../danoeh/antennapod/feed/FeedManager.java   |   7 +-
 .../service/download/DownloadRequest.java     | 177 +++++++++++++
 .../service/download/DownloadService.java     | 250 ++++++++----------
 .../download}/DownloadStatus.java             | 165 ++++--------
 .../service/download/Downloader.java          |  26 +-
 .../service/download/HttpDownloader.java      |  55 ++--
 .../danoeh/antennapod/storage/DBReader.java   |   2 +-
 .../danoeh/antennapod/storage/DBWriter.java   |   2 +-
 .../antennapod/storage/DownloadRequester.java |  36 +--
 .../antennapod/storage/PodDBAdapter.java      |  20 +-
 .../comparator/DownloadStatusComparator.java  |   2 +-
 .../antennapod/test/HttpDownloaderTest.java   |   2 +-
 16 files changed, 445 insertions(+), 380 deletions(-)
 create mode 100644 src/de/danoeh/antennapod/service/download/DownloadRequest.java
 rename src/de/danoeh/antennapod/{asynctask => service/download}/DownloadStatus.java (65%)

diff --git a/src/de/danoeh/antennapod/activity/DownloadActivity.java b/src/de/danoeh/antennapod/activity/DownloadActivity.java
index 10ebb1285..80fc1cdce 100644
--- a/src/de/danoeh/antennapod/activity/DownloadActivity.java
+++ b/src/de/danoeh/antennapod/activity/DownloadActivity.java
@@ -24,8 +24,8 @@ import com.actionbarsherlock.view.MenuItem;
 import de.danoeh.antennapod.AppConfig;
 import de.danoeh.antennapod.R;
 import de.danoeh.antennapod.adapter.DownloadlistAdapter;
-import de.danoeh.antennapod.asynctask.DownloadStatus;
 import de.danoeh.antennapod.preferences.UserPreferences;
+import de.danoeh.antennapod.service.download.DownloadRequest;
 import de.danoeh.antennapod.service.download.DownloadService;
 import de.danoeh.antennapod.storage.DownloadRequester;
 
@@ -43,7 +43,7 @@ public class DownloadActivity extends SherlockListActivity implements
 	private DownloadRequester requester;
 
 	private ActionMode mActionMode;
-	private DownloadStatus selectedDownload;
+	private DownloadRequest selectedDownload;
 
 	private DownloadService downloadService = null;
 	boolean mIsBound;
@@ -159,7 +159,8 @@ public class DownloadActivity extends SherlockListActivity implements
 			@Override
 			public boolean onItemLongClick(AdapterView<?> arg0, View view,
 					int position, long id) {
-				DownloadStatus selection = dla.getItem(position).getStatus();
+				DownloadRequest selection = dla.getItem(position)
+						.getDownloadRequest();
 				if (selection != null && mActionMode != null) {
 					mActionMode.finish();
 				}
@@ -204,7 +205,7 @@ public class DownloadActivity extends SherlockListActivity implements
 
 	@Override
 	public boolean onCreateActionMode(ActionMode mode, Menu menu) {
-		if (!selectedDownload.isDone()) {
+		if (selectedDownload != null) {
 			TypedArray drawables = obtainStyledAttributes(new int[] { R.attr.navigation_cancel });
 			menu.add(Menu.NONE, R.id.cancel_download_item, Menu.NONE,
 					R.string.cancel_download_label).setIcon(
@@ -223,7 +224,7 @@ public class DownloadActivity extends SherlockListActivity implements
 		boolean handled = false;
 		switch (item.getItemId()) {
 		case R.id.cancel_download_item:
-			requester.cancelDownload(this, selectedDownload.getFeedFile());
+			requester.cancelDownload(this, selectedDownload.getSource());
 			handled = true;
 			break;
 		}
diff --git a/src/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java b/src/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
index d6ff537a3..deb4602bb 100644
--- a/src/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
+++ b/src/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
@@ -21,9 +21,10 @@ import com.actionbarsherlock.app.SherlockFragmentActivity;
 
 import de.danoeh.antennapod.AppConfig;
 import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.DownloadStatus;
 import de.danoeh.antennapod.feed.Feed;
 import de.danoeh.antennapod.preferences.UserPreferences;
+import de.danoeh.antennapod.service.download.DownloadRequest;
+import de.danoeh.antennapod.service.download.DownloadStatus;
 import de.danoeh.antennapod.service.download.Downloader;
 import de.danoeh.antennapod.service.download.DownloaderCallback;
 import de.danoeh.antennapod.service.download.HttpDownloader;
@@ -45,7 +46,7 @@ import de.danoeh.antennapod.util.URLChecker;
 public abstract class OnlineFeedViewActivity extends SherlockFragmentActivity {
 	private static final String TAG = "OnlineFeedViewActivity";
 	private static final String ARG_FEEDURL = "arg.feedurl";
-	
+
 	public static final int RESULT_ERROR = 2;
 
 	private Feed feed;
@@ -70,7 +71,7 @@ public abstract class OnlineFeedViewActivity extends SherlockFragmentActivity {
 	@Override
 	protected void onStop() {
 		super.onStop();
-		if (downloader != null && downloader.getStatus().isDone() == false) {
+		if (downloader != null && !downloader.isFinished()) {
 			downloader.cancel();
 		}
 	}
@@ -82,7 +83,7 @@ public abstract class OnlineFeedViewActivity extends SherlockFragmentActivity {
 
 				@Override
 				public void run() {
-					DownloadStatus status = downloader.getStatus();
+					DownloadStatus status = downloader.getResult();
 					if (status != null) {
 						if (!status.isCancelled()) {
 							if (status.isSuccessful()) {
@@ -119,9 +120,10 @@ public abstract class OnlineFeedViewActivity extends SherlockFragmentActivity {
 				FileNameGenerator.generateFileName(feed.getDownload_url()))
 				.toString();
 		feed.setFile_url(fileUrl);
-		DownloadStatus status = new DownloadStatus(feed, "OnlineFeed");
+		DownloadRequest request = new DownloadRequest(feed.getFile_url(),
+				feed.getDownload_url(), "OnlineFeed", 0, Feed.FEEDFILETYPE_FEED);
 		HttpDownloader httpDownloader = new HttpDownloader(downloaderCallback,
-				status);
+				request);
 		httpDownloader.start();
 	}
 
@@ -217,13 +219,14 @@ public abstract class OnlineFeedViewActivity extends SherlockFragmentActivity {
 		} else {
 			builder.setMessage(R.string.error_msg_prefix);
 		}
-		builder.setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() {
-			
-			@Override
-			public void onClick(DialogInterface dialog, int which) {
-				dialog.cancel();
-			}
-		});
+		builder.setNeutralButton(android.R.string.ok,
+				new DialogInterface.OnClickListener() {
+
+					@Override
+					public void onClick(DialogInterface dialog, int which) {
+						dialog.cancel();
+					}
+				});
 		builder.setOnCancelListener(new OnCancelListener() {
 			@Override
 			public void onCancel(DialogInterface dialog) {
diff --git a/src/de/danoeh/antennapod/adapter/DownloadLogAdapter.java b/src/de/danoeh/antennapod/adapter/DownloadLogAdapter.java
index f97210cf3..4005be8ea 100644
--- a/src/de/danoeh/antennapod/adapter/DownloadLogAdapter.java
+++ b/src/de/danoeh/antennapod/adapter/DownloadLogAdapter.java
@@ -8,11 +8,11 @@ import android.view.ViewGroup;
 import android.widget.BaseAdapter;
 import android.widget.TextView;
 import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.DownloadStatus;
 import de.danoeh.antennapod.feed.Feed;
 import de.danoeh.antennapod.feed.FeedImage;
 import de.danoeh.antennapod.feed.FeedManager;
 import de.danoeh.antennapod.feed.FeedMedia;
+import de.danoeh.antennapod.service.download.DownloadStatus;
 import de.danoeh.antennapod.util.DownloadError;
 
 /** Displays a list of DownloadStatus entries. */
diff --git a/src/de/danoeh/antennapod/adapter/DownloadlistAdapter.java b/src/de/danoeh/antennapod/adapter/DownloadlistAdapter.java
index 685906d6f..75e837969 100644
--- a/src/de/danoeh/antennapod/adapter/DownloadlistAdapter.java
+++ b/src/de/danoeh/antennapod/adapter/DownloadlistAdapter.java
@@ -10,11 +10,12 @@ import android.widget.ArrayAdapter;
 import android.widget.ProgressBar;
 import android.widget.TextView;
 import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.DownloadStatus;
 import de.danoeh.antennapod.feed.Feed;
 import de.danoeh.antennapod.feed.FeedFile;
 import de.danoeh.antennapod.feed.FeedImage;
 import de.danoeh.antennapod.feed.FeedMedia;
+import de.danoeh.antennapod.service.download.DownloadRequest;
+import de.danoeh.antennapod.service.download.DownloadStatus;
 import de.danoeh.antennapod.service.download.Downloader;
 import de.danoeh.antennapod.util.Converter;
 import de.danoeh.antennapod.util.ThemeUtils;
@@ -33,8 +34,7 @@ public class DownloadlistAdapter extends ArrayAdapter<Downloader> {
 	@Override
 	public View getView(int position, View convertView, ViewGroup parent) {
 		Holder holder;
-		DownloadStatus status = getItem(position).getStatus();
-		FeedFile feedFile = status.getFeedFile();
+		DownloadRequest request = getItem(position).getDownloadRequest();
 		// Inflate layout
 		if (convertView == null) {
 			holder = new Holder();
@@ -62,31 +62,16 @@ public class DownloadlistAdapter extends ArrayAdapter<Downloader> {
 		} else {
 			convertView.setBackgroundResource(0);
 		}
-
-		String titleText = null;
-		if (feedFile.getClass() == FeedMedia.class) {
-			titleText = ((FeedMedia) feedFile).getItem().getTitle();
-		} else if (feedFile.getClass() == Feed.class) {
-			titleText = ((Feed) feedFile).getTitle();
-		} else if (feedFile.getClass() == FeedImage.class) {
-			FeedImage image = (FeedImage) feedFile;
-			if (image.getFeed() != null) {
-				titleText = convertView.getResources().getString(
-						R.string.image_of_prefix)
-						+ image.getFeed().getTitle();
-			} else {
-				titleText = ((FeedImage) feedFile).getTitle();
-			}
+		
+		holder.title.setText(request.getTitle());
+		if (request.getStatusMsg() != 0) {
+			holder.message.setText(request.getStatusMsg());
 		}
-		holder.title.setText(titleText);
-		if (status.getStatusMsg() != 0) {
-			holder.message.setText(status.getStatusMsg());
-		}
-		String strDownloaded = Converter.byteToString(status.getSoFar());
-		if (status.getSize() != DownloadStatus.SIZE_UNKNOWN) {
-			strDownloaded += " / " + Converter.byteToString(status.getSize());
-			holder.percent.setText(status.getProgressPercent() + "%");
-			holder.progbar.setProgress(status.getProgressPercent());
+		String strDownloaded = Converter.byteToString(request.getSoFar());
+		if (request.getSize() != DownloadStatus.SIZE_UNKNOWN) {
+			strDownloaded += " / " + Converter.byteToString(request.getSize());
+			holder.percent.setText(request.getProgressPercent() + "%");
+			holder.progbar.setProgress(request.getProgressPercent());
 			holder.percent.setVisibility(View.VISIBLE);
 		} else {
 			holder.progbar.setProgress(0);
diff --git a/src/de/danoeh/antennapod/feed/FeedManager.java b/src/de/danoeh/antennapod/feed/FeedManager.java
index ca62cfd0f..915e9a208 100644
--- a/src/de/danoeh/antennapod/feed/FeedManager.java
+++ b/src/de/danoeh/antennapod/feed/FeedManager.java
@@ -25,10 +25,10 @@ import android.os.Handler;
 import android.preference.PreferenceManager;
 import android.util.Log;
 import de.danoeh.antennapod.AppConfig;
-import de.danoeh.antennapod.asynctask.DownloadStatus;
 import de.danoeh.antennapod.preferences.PlaybackPreferences;
 import de.danoeh.antennapod.preferences.UserPreferences;
 import de.danoeh.antennapod.service.PlaybackService;
+import de.danoeh.antennapod.service.download.DownloadStatus;
 import de.danoeh.antennapod.storage.DBReader;
 import de.danoeh.antennapod.storage.DownloadRequestException;
 import de.danoeh.antennapod.storage.DownloadRequester;
@@ -1400,11 +1400,6 @@ public class FeedManager {
 
 	/** Get a download status object from the download log by its FeedFile. */
 	public DownloadStatus getDownloadStatus(FeedFile feedFile) {
-		for (DownloadStatus status : downloadLog) {
-			if (status.getFeedFile() == feedFile) {
-				return status;
-			}
-		}
 		return null;
 	}
 
diff --git a/src/de/danoeh/antennapod/service/download/DownloadRequest.java b/src/de/danoeh/antennapod/service/download/DownloadRequest.java
new file mode 100644
index 000000000..1f4e32e1b
--- /dev/null
+++ b/src/de/danoeh/antennapod/service/download/DownloadRequest.java
@@ -0,0 +1,177 @@
+package de.danoeh.antennapod.service.download;
+
+import android.os.Parcel;
+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;
+	}
+}
diff --git a/src/de/danoeh/antennapod/service/download/DownloadService.java b/src/de/danoeh/antennapod/service/download/DownloadService.java
index e1230e170..fe327db59 100644
--- a/src/de/danoeh/antennapod/service/download/DownloadService.java
+++ b/src/de/danoeh/antennapod/service/download/DownloadService.java
@@ -41,8 +41,6 @@ import android.os.AsyncTask;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
 import android.support.v4.app.NotificationCompat;
 import android.util.Log;
 import android.webkit.URLUtil;
@@ -50,10 +48,8 @@ import de.danoeh.antennapod.AppConfig;
 import de.danoeh.antennapod.R;
 import de.danoeh.antennapod.activity.DownloadActivity;
 import de.danoeh.antennapod.activity.DownloadLogActivity;
-import de.danoeh.antennapod.asynctask.DownloadStatus;
 import de.danoeh.antennapod.feed.EventDistributor;
 import de.danoeh.antennapod.feed.Feed;
-import de.danoeh.antennapod.feed.FeedFile;
 import de.danoeh.antennapod.feed.FeedImage;
 import de.danoeh.antennapod.feed.FeedItem;
 import de.danoeh.antennapod.feed.FeedManager;
@@ -257,30 +253,26 @@ public class DownloadService extends Service {
 				StringBuilder bigText = new StringBuilder("");
 				for (int i = 0; i < downloads.size(); i++) {
 					Downloader downloader = downloads.get(i);
-					if (downloader.getStatus() != null) {
-						FeedFile f = downloader.getStatus().getFeedFile();
-						if (f.getClass() == Feed.class) {
-							Feed feed = (Feed) f;
-							if (feed.getTitle() != null) {
-								if (i > 0) {
-									bigText.append("\n");
-								}
-								bigText.append("\u2022 " + feed.getTitle());
+					final DownloadRequest request = downloader
+							.getDownloadRequest();
+					if (request.getFeedfileType() == Feed.FEEDFILETYPE_FEED) {
+						if (request.getTitle() != null) {
+							if (i > 0) {
+								bigText.append("\n");
 							}
-						} else if (f.getClass() == FeedMedia.class) {
-							FeedMedia media = (FeedMedia) f;
-							if (media.getItem().getTitle() != null) {
-								if (i > 0) {
-									bigText.append("\n");
-								}
-								bigText.append("\u2022 "
-										+ media.getItem().getTitle()
-										+ " ("
-										+ downloader.getStatus()
-												.getProgressPercent() + "%)");
+							bigText.append("\u2022 " + request.getTitle());
+						}
+					} else if (request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
+						if (request.getTitle() != null) {
+							if (i > 0) {
+								bigText.append("\n");
 							}
+							bigText.append("\u2022 " + request.getTitle()
+									+ " (" + request.getProgressPercent()
+									+ "%)");
 						}
 					}
+
 				}
 				notificationBuilder.setSummaryText(downloadsLeft);
 				notificationBuilder.setBigContentTitle(contentTitle);
@@ -301,8 +293,7 @@ public class DownloadService extends Service {
 
 	private Downloader getDownloader(String downloadUrl) {
 		for (Downloader downloader : downloads) {
-			if (downloader.getStatus().getFeedFile().getDownload_url()
-					.equals(downloadUrl)) {
+			if (downloader.getDownloadRequest().getSource().equals(downloadUrl)) {
 				return downloader;
 			}
 		}
@@ -333,8 +324,7 @@ public class DownloadService extends Service {
 				for (Downloader d : downloads) {
 					d.cancel();
 					DownloadRequester.getInstance().removeDownload(
-							d.getStatus().getFeedFile());
-					d.getStatus().getFeedFile().setFile_url(null);
+							d.getDownloadRequest());
 					if (AppConfig.DEBUG)
 						Log.d(TAG, "Cancelled all downloads");
 				}
@@ -350,7 +340,7 @@ public class DownloadService extends Service {
 	private void onDownloadQueued(Intent intent) {
 		if (AppConfig.DEBUG)
 			Log.d(TAG, "Received enqueue request");
-		Request request = intent.getParcelableExtra(EXTRA_REQUEST);
+		DownloadRequest request = intent.getParcelableExtra(EXTRA_REQUEST);
 		if (request == null) {
 			throw new IllegalArgumentException(
 					"ACTION_ENQUEUE_DOWNLOAD intent needs request extra");
@@ -361,22 +351,13 @@ public class DownloadService extends Service {
 			shutdownInitiated = false;
 		}
 
-		DownloadRequester requester = DownloadRequester.getInstance();
-		FeedFile feedfile = requester.getDownload(request.source);
-		if (feedfile != null) {
-
-			DownloadStatus status = new DownloadStatus(feedfile,
-					feedfile.getHumanReadableIdentifier());
-			Downloader downloader = getDownloader(status);
-			if (downloader != null) {
-				downloads.add(downloader);
-				downloadExecutor.submit(downloader);
-				sendBroadcast(new Intent(ACTION_DOWNLOADS_CONTENT_CHANGED));
-			}
-		} else {
-			Log.e(TAG,
-					"Could not find feedfile in download requester when trying to enqueue new download");
+		Downloader downloader = getDownloader(request);
+		if (downloader != null) {
+			downloads.add(downloader);
+			downloadExecutor.submit(downloader);
+			sendBroadcast(new Intent(ACTION_DOWNLOADS_CONTENT_CHANGED));
 		}
+
 		queryDownloads();
 	}
 
@@ -389,8 +370,8 @@ public class DownloadService extends Service {
 
 	};
 
-	private Downloader getDownloader(DownloadStatus status) {
-		if (URLUtil.isHttpUrl(status.getFeedFile().getDownload_url())) {
+	private Downloader getDownloader(DownloadRequest request) {
+		if (URLUtil.isHttpUrl(request.getSource())) {
 			return new HttpDownloader(new DownloaderCallback() {
 
 				@Override
@@ -404,10 +385,11 @@ public class DownloadService extends Service {
 						}
 					});
 				}
-			}, status);
+			}, request);
 		}
-		Log.e(TAG, "Could not find appropriate downloader for "
-				+ status.getFeedFile().getDownload_url());
+		Log.e(TAG,
+				"Could not find appropriate downloader for "
+						+ request.getSource());
 		return null;
 	}
 
@@ -435,31 +417,28 @@ public class DownloadService extends Service {
 				if (AppConfig.DEBUG)
 					Log.d(TAG, "Received 'Download Complete' - message.");
 				downloadsBeingHandled += 1;
-				DownloadStatus status = downloader.getStatus();
-				status.setCompletionDate(new Date());
+				DownloadStatus status = downloader.getResult();
 				successful = status.isSuccessful();
 
-				FeedFile download = status.getFeedFile();
-				if (download != null) {
-					if (successful) {
-						if (download.getClass() == Feed.class) {
-							handleCompletedFeedDownload(status);
-						} else if (download.getClass() == FeedImage.class) {
-							handleCompletedImageDownload(status);
-						} else if (download.getClass() == FeedMedia.class) {
-							handleCompletedFeedMediaDownload(status);
-						}
-					} else {
-						download.setFile_url(null);
-						download.setDownloaded(false);
-						if (!successful && !status.isCancelled()) {
-							Log.e(TAG, "Download failed");
-							saveDownloadStatus(status);
-						}
-						sendDownloadHandledIntent();
-						downloadsBeingHandled -= 1;
+				final int type = status.getFeedfileType();
+				if (successful) {
+					if (type == Feed.FEEDFILETYPE_FEED) {
+						handleCompletedFeedDownload(downloader
+								.getDownloadRequest());
+					} else if (type == FeedImage.FEEDFILETYPE_FEEDIMAGE) {
+						handleCompletedImageDownload(status, downloader.getDownloadRequest());
+					} else if (type == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
+						handleCompletedFeedMediaDownload(status, downloader.getDownloadRequest());
 					}
+				} else {
+					if (!successful && !status.isCancelled()) {
+						Log.e(TAG, "Download failed");
+						saveDownloadStatus(status);
+					}
+					sendDownloadHandledIntent();
+					downloadsBeingHandled -= 1;
 				}
+
 				return null;
 			}
 		};
@@ -477,12 +456,11 @@ public class DownloadService extends Service {
 	private void removeDownload(final Downloader d) {
 		if (AppConfig.DEBUG)
 			Log.d(TAG, "Removing downloader: "
-					+ d.getStatus().getFeedFile().getDownload_url());
+					+ d.getDownloadRequest().getSource());
 		boolean rc = downloads.remove(d);
 		if (AppConfig.DEBUG)
 			Log.d(TAG, "Result of downloads.remove: " + rc);
-		DownloadRequester.getInstance().removeDownload(
-				d.getStatus().getFeedFile());
+		DownloadRequester.getInstance().removeDownload(d.getDownloadRequest());
 		sendBroadcast(new Intent(ACTION_DOWNLOADS_CONTENT_CHANGED));
 	}
 
@@ -521,7 +499,7 @@ public class DownloadService extends Service {
 			if (status.isSuccessful()) {
 				successfulDownloads++;
 			} else if (!status.isCancelled()) {
-				if (status.getFeedFile().getClass() != FeedImage.class) {
+				if (status.getFeedfileType() != FeedImage.FEEDFILETYPE_FEEDIMAGE) {
 					createReport = true;
 				}
 				failedDownloads++;
@@ -581,25 +559,25 @@ public class DownloadService extends Service {
 	}
 
 	/** Is called whenever a Feed is downloaded */
-	private void handleCompletedFeedDownload(DownloadStatus status) {
+	private void handleCompletedFeedDownload(DownloadRequest request) {
 		if (AppConfig.DEBUG)
 			Log.d(TAG, "Handling completed Feed Download");
-		syncExecutor.execute(new FeedSyncThread(status));
+		syncExecutor.execute(new FeedSyncThread(request));
 
 	}
 
 	/** Is called whenever a Feed-Image is downloaded */
-	private void handleCompletedImageDownload(DownloadStatus status) {
+	private void handleCompletedImageDownload(DownloadStatus status, DownloadRequest request) {
 		if (AppConfig.DEBUG)
 			Log.d(TAG, "Handling completed Image Download");
-		syncExecutor.execute(new ImageHandlerThread(status));
+		syncExecutor.execute(new ImageHandlerThread(status, request));
 	}
 
 	/** Is called whenever a FeedMedia is downloaded. */
-	private void handleCompletedFeedMediaDownload(DownloadStatus status) {
+	private void handleCompletedFeedMediaDownload(DownloadStatus status, DownloadRequest request) {
 		if (AppConfig.DEBUG)
 			Log.d(TAG, "Handling completed FeedMedia Download");
-		syncExecutor.execute(new MediaHandlerThread(status));
+		syncExecutor.execute(new MediaHandlerThread(status, request));
 	}
 
 	/**
@@ -609,25 +587,31 @@ public class DownloadService extends Service {
 	class FeedSyncThread implements Runnable {
 		private static final String TAG = "FeedSyncThread";
 
-		private Feed feed;
-		private DownloadStatus status;
+		private DownloadRequest request;
 
 		private int reason;
 		private boolean successful;
 
-		public FeedSyncThread(DownloadStatus status) {
-			this.feed = (Feed) status.getFeedFile();
-			this.status = status;
+		public FeedSyncThread(DownloadRequest request) {
+			if (request == null) {
+				throw new IllegalArgumentException("Request must not be null");
+			}
+
+			this.request = request;
 		}
 
 		public void run() {
 			Feed savedFeed = null;
+
+			Feed feed = new Feed(request.getSource(), new Date());
+			feed.setFile_url(request.getDestination());
+			feed.setDownloaded(true);
+
 			reason = 0;
 			String reasonDetailed = null;
 			successful = true;
 			final FeedManager manager = FeedManager.getInstance();
 			FeedHandler feedHandler = new FeedHandler();
-			feed.setDownloaded(true);
 
 			try {
 				feed = feedHandler.parseFeed(feed);
@@ -751,7 +735,7 @@ public class DownloadService extends Service {
 		}
 
 		/** Delete files that aren't needed anymore */
-		private void cleanup() {
+		private void cleanup(Feed feed) {
 			if (feed.getFile_url() != null) {
 				if (new File(feed.getFile_url()).delete())
 					if (AppConfig.DEBUG)
@@ -768,16 +752,29 @@ public class DownloadService extends Service {
 
 	/** Handles a completed image download. */
 	class ImageHandlerThread implements Runnable {
-		private FeedImage image;
+		
+		private DownloadRequest request;
 		private DownloadStatus status;
 
-		public ImageHandlerThread(DownloadStatus status) {
-			this.image = (FeedImage) status.getFeedFile();
+		public ImageHandlerThread(DownloadStatus status, DownloadRequest request) {
+			if (status == null) {
+				throw new IllegalArgumentException("Status must not be null");
+			}
+			if (request == null) {
+				throw new IllegalArgumentException("Request must not be null");
+			}
 			this.status = status;
+			this.request = request;
 		}
 
 		@Override
 		public void run() {
+			FeedImage image = FeedManager.getInstance().getFeedImage(request.getFeedfileId());
+			if (image == null) {
+				throw new IllegalStateException("Could not find downloaded image in database");
+			}
+			
+			image.setFile_url(request.getDestination());
 			image.setDownloaded(true);
 
 			saveDownloadStatus(status);
@@ -803,20 +800,34 @@ public class DownloadService extends Service {
 
 	/** Handles a completed media download. */
 	class MediaHandlerThread implements Runnable {
-		private FeedMedia media;
-		private DownloadStatus status;
 
-		public MediaHandlerThread(DownloadStatus status) {
-			super();
-			this.media = (FeedMedia) status.getFeedFile();
+		private DownloadRequest request;
+		private DownloadStatus status;
+		
+		public MediaHandlerThread(DownloadStatus status, DownloadRequest request) {
+			if (status == null) {
+				throw new IllegalArgumentException("Status must not be null");
+			}
+			if (request == null) {
+				throw new IllegalArgumentException("Request must not be null");
+			}
+			
 			this.status = status;
+			this.request = request;
 		}
 
 		@Override
 		public void run() {
+			FeedMedia media = FeedManager.getInstance().getFeedMedia(
+					request.getFeedfileId());
+			if (media == null) {
+				throw new IllegalStateException(
+						"Could not find downloaded media object in database");
+			}
 			boolean chaptersRead = false;
-
 			media.setDownloaded(true);
+			media.setFile_url(request.getDestination());
+			
 			// Get duration
 			MediaPlayer mediaplayer = new MediaPlayer();
 			try {
@@ -863,53 +874,6 @@ public class DownloadService extends Service {
 		}
 	}
 
-	/** Is used to request a new download. */
-	public static class Request implements Parcelable {
-		private String destination;
-		private String source;
-
-		public Request(String destination, String source) {
-			super();
-			this.destination = destination;
-			this.source = source;
-		}
-
-		private Request(Parcel in) {
-			destination = in.readString();
-			source = in.readString();
-		}
-
-		@Override
-		public int describeContents() {
-			return 0;
-		}
-
-		@Override
-		public void writeToParcel(Parcel dest, int flags) {
-			dest.writeString(destination);
-			dest.writeString(source);
-		}
-
-		public static final Parcelable.Creator<Request> CREATOR = new Parcelable.Creator<Request>() {
-			public Request createFromParcel(Parcel in) {
-				return new Request(in);
-			}
-
-			public Request[] newArray(int size) {
-				return new Request[size];
-			}
-		};
-
-		public String getDestination() {
-			return destination;
-		}
-
-		public String getSource() {
-			return source;
-		}
-
-	}
-
 	/** Schedules the notification updater task if it hasn't been scheduled yet. */
 	private void setupNotificationUpdater() {
 		if (AppConfig.DEBUG)
diff --git a/src/de/danoeh/antennapod/asynctask/DownloadStatus.java b/src/de/danoeh/antennapod/service/download/DownloadStatus.java
similarity index 65%
rename from src/de/danoeh/antennapod/asynctask/DownloadStatus.java
rename to src/de/danoeh/antennapod/service/download/DownloadStatus.java
index 734f9f78a..76091ec67 100644
--- a/src/de/danoeh/antennapod/asynctask/DownloadStatus.java
+++ b/src/de/danoeh/antennapod/service/download/DownloadStatus.java
@@ -1,4 +1,4 @@
-package de.danoeh.antennapod.asynctask;
+package de.danoeh.antennapod.service.download;
 
 import java.util.Date;
 
@@ -12,10 +12,6 @@ public class DownloadStatus {
 	 */
 	public static final int SIZE_UNKNOWN = -1;
 
-	public Date getCompletionDate() {
-		return completionDate;
-	}
-
 	// ----------------------------------- ATTRIBUTES STORED IN DB
 	/** Unique id for storing the object in database. */
 	protected long id;
@@ -33,7 +29,6 @@ public class DownloadStatus {
 	protected String reasonDetailed;
 	protected boolean successful;
 	protected Date completionDate;
-	protected FeedFile feedfile;
 	protected long feedfileId;
 	/**
 	 * Is used to determine the type of the feedfile even if the feedfile does
@@ -43,29 +38,13 @@ public class DownloadStatus {
 	protected int feedfileType;
 
 	// ------------------------------------ NOT STORED IN DB
-	protected int progressPercent;
-	protected long soFar;
-	protected long size;
-	protected int statusMsg;
 	protected boolean done;
 	protected boolean cancelled;
 
-	public DownloadStatus(FeedFile feedfile, String title) {
-		this.feedfile = feedfile;
-		if (feedfile != null) {
-			feedfileType = feedfile.getTypeAsInt();
-		}
-		this.title = title;
-	}
-
 	/** Constructor for restoring Download status entries from DB. */
 	public DownloadStatus(long id, String title, long feedfileId,
 			int feedfileType, boolean successful, int reason,
 			Date completionDate, String reasonDetailed) {
-		progressPercent = 100;
-		soFar = 0;
-		size = 0;
-
 		this.id = id;
 		this.title = title;
 		this.done = true;
@@ -77,21 +56,49 @@ public class DownloadStatus {
 		this.feedfileType = feedfileType;
 	}
 
+	public DownloadStatus(DownloadRequest request, int reason,
+			boolean successful, boolean cancelled, String reasonDetailed) {
+		if (request == null) {
+			throw new IllegalArgumentException("request must not be null");
+		}
+		this.title = request.getTitle();
+		this.feedfileId = request.getFeedfileId();
+		this.feedfileType = request.getFeedfileType();
+		this.reason = reason;
+		this.successful = successful;
+		this.cancelled = cancelled;
+		this.reasonDetailed = reasonDetailed;
+		this.completionDate = new Date();
+	}
+
 	/** Constructor for creating new completed downloads. */
 	public DownloadStatus(FeedFile feedfile, String title, int reason,
 			boolean successful, String reasonDetailed) {
-		progressPercent = 100;
-		soFar = 0;
-		size = 0;
+		if (feedfile == null) {
+			throw new IllegalArgumentException("feedfile must not be null");
+		}
 
 		this.title = title;
 		this.done = true;
-		this.feedfile = feedfile;
+		this.feedfileId = feedfile.getId();
+		this.feedfileType = feedfile.getTypeAsInt();
+		this.reason = reason;
+		this.successful = successful;
+		this.completionDate = new Date();
+		this.reasonDetailed = reasonDetailed;
+	}
+
+	/** Constructor for creating new completed downloads. */
+	public DownloadStatus(long feedfileId, int feedfileType, String title,
+			int reason, boolean successful, String reasonDetailed) {
+		this.title = title;
+		this.done = true;
+		this.feedfileId = feedfileId;
+		this.feedfileType = feedfileType;
 		this.reason = reason;
 		this.successful = successful;
 		this.completionDate = new Date();
 		this.reasonDetailed = reasonDetailed;
-		this.feedfileType = feedfile.getTypeAsInt();
 	}
 
 	@Override
@@ -99,115 +106,53 @@ public class DownloadStatus {
 		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;
-	}
-
-	public int getProgressPercent() {
-		return progressPercent;
-	}
-
-	public long getSoFar() {
-		return soFar;
-	}
-
-	public long getSize() {
-		return size;
-	}
-
-	public int getStatusMsg() {
-		return statusMsg;
-	}
-
-	public int getReason() {
-		return reason;
-	}
-
-	public boolean isSuccessful() {
-		return successful;
+				+ completionDate + ", feedfileId=" + feedfileId
+				+ ", feedfileType=" + feedfileType + ", done=" + done
+				+ ", cancelled=" + cancelled + "]";
 	}
 
 	public long getId() {
 		return id;
 	}
 
-	public void setId(long id) {
-		this.id = id;
+	public String getTitle() {
+		return title;
 	}
 
-	public boolean isDone() {
-		return done;
-	}
-
-	public void setProgressPercent(int progressPercent) {
-		this.progressPercent = progressPercent;
-	}
-
-	public void setSoFar(long soFar) {
-		this.soFar = soFar;
-	}
-
-	public void setSize(long size) {
-		this.size = size;
-	}
-
-	public void setStatusMsg(int statusMsg) {
-		this.statusMsg = statusMsg;
-	}
-
-	public void setReason(int reason) {
-		this.reason = reason;
-	}
-
-	public void setSuccessful(boolean successful) {
-		this.successful = successful;
-	}
-
-	public void setDone(boolean done) {
-		this.done = done;
-	}
-
-	public void setCompletionDate(Date completionDate) {
-		this.completionDate = completionDate;
+	public int getReason() {
+		return reason;
 	}
 
 	public String getReasonDetailed() {
 		return reasonDetailed;
 	}
 
-	public void setReasonDetailed(String reasonDetailed) {
-		this.reasonDetailed = reasonDetailed;
+	public boolean isSuccessful() {
+		return successful;
 	}
 
-	public String getTitle() {
-		return title;
-	}
-
-	public void setTitle(String title) {
-		this.title = title;
-	}
-
-	public int getFeedfileType() {
-		return feedfileType;
+	public Date getCompletionDate() {
+		return completionDate;
 	}
 
 	public long getFeedfileId() {
 		return feedfileId;
 	}
 
+	public int getFeedfileType() {
+		return feedfileType;
+	}
+
+	public boolean isDone() {
+		return done;
+	}
+
 	public boolean isCancelled() {
 		return cancelled;
 	}
 
-	public void setCancelled(boolean cancelled) {
-		this.cancelled = cancelled;
+	public void setId(long id) {
+		this.id = id;
 	}
 
 }
\ No newline at end of file
diff --git a/src/de/danoeh/antennapod/service/download/Downloader.java b/src/de/danoeh/antennapod/service/download/Downloader.java
index 9ed9d9a76..8df2bf977 100644
--- a/src/de/danoeh/antennapod/service/download/Downloader.java
+++ b/src/de/danoeh/antennapod/service/download/Downloader.java
@@ -1,7 +1,6 @@
 package de.danoeh.antennapod.service.download;
 
 import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.DownloadStatus;
 
 /** Downloads files */
 public abstract class Downloader extends Thread {
@@ -12,14 +11,15 @@ public abstract class Downloader extends Thread {
 
 	protected volatile boolean cancelled;
 
-	protected volatile DownloadStatus status;
+	protected volatile DownloadRequest request;
+	protected volatile DownloadStatus result;
 
 	public Downloader(DownloaderCallback downloaderCallback,
-			DownloadStatus status) {
+			DownloadRequest request) {
 		super();
 		this.downloaderCallback = downloaderCallback;
-		this.status = status;
-		this.status.setStatusMsg(R.string.download_pending);
+		this.request = request;
+		this.request.setStatusMsg(R.string.download_pending);
 		this.cancelled = false;
 	}
 
@@ -39,11 +39,23 @@ public abstract class Downloader extends Thread {
 	@Override
 	public final void run() {
 		download();
+		if (result == null) {
+			throw new IllegalStateException(
+					"Downloader hasn't created DownloadStatus object");
+		}
 		finish();
 	}
 
-	public DownloadStatus getStatus() {
-		return status;
+	public DownloadRequest getDownloadRequest() {
+		return request;
+	}
+
+	public DownloadStatus getResult() {
+		return result;
+	}
+
+	public boolean isFinished() {
+		return finished;
 	}
 
 	public void cancel() {
diff --git a/src/de/danoeh/antennapod/service/download/HttpDownloader.java b/src/de/danoeh/antennapod/service/download/HttpDownloader.java
index f8f26f6fd..77443956b 100644
--- a/src/de/danoeh/antennapod/service/download/HttpDownloader.java
+++ b/src/de/danoeh/antennapod/service/download/HttpDownloader.java
@@ -26,7 +26,6 @@ import android.util.Log;
 import de.danoeh.antennapod.AppConfig;
 import de.danoeh.antennapod.PodcastApp;
 import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.asynctask.DownloadStatus;
 import de.danoeh.antennapod.util.DownloadError;
 import de.danoeh.antennapod.util.StorageUtils;
 
@@ -40,8 +39,8 @@ public class HttpDownloader extends Downloader {
 	private static final int SOCKET_TIMEOUT = 30000;
 
 	public HttpDownloader(DownloaderCallback downloaderCallback,
-			DownloadStatus status) {
-		super(downloaderCallback, status);
+			DownloadRequest request) {
+		super(downloaderCallback, request);
 	}
 
 	private DefaultHttpClient createHttpClient() {
@@ -66,8 +65,7 @@ public class HttpDownloader extends Downloader {
 		OutputStream out = null;
 		InputStream connection = null;
 		try {
-			HttpGet httpGet = new HttpGet(status.getFeedFile()
-					.getDownload_url());
+			HttpGet httpGet = new HttpGet(request.getSource());
 			httpClient = createHttpClient();
 			HttpResponse response = httpClient.execute(httpGet);
 			HttpEntity httpEntity = response.getEntity();
@@ -76,8 +74,7 @@ public class HttpDownloader extends Downloader {
 				Log.d(TAG, "Response code is " + responseCode);
 			if (responseCode == HttpURLConnection.HTTP_OK && httpEntity != null) {
 				if (StorageUtils.storageAvailable(PodcastApp.getInstance())) {
-					File destination = new File(status.getFeedFile()
-							.getFile_url());
+					File destination = new File(request.getDestination());
 					if (!destination.exists()) {
 						connection = AndroidHttpClient
 								.getUngzippedContent(httpEntity);
@@ -86,29 +83,30 @@ public class HttpDownloader extends Downloader {
 								destination));
 						byte[] buffer = new byte[BUFFER_SIZE];
 						int count = 0;
-						status.setStatusMsg(R.string.download_running);
+						request.setStatusMsg(R.string.download_running);
 						if (AppConfig.DEBUG)
 							Log.d(TAG, "Getting size of download");
-						status.setSize(httpEntity.getContentLength());
+						request.setSize(httpEntity.getContentLength());
 						if (AppConfig.DEBUG)
-							Log.d(TAG, "Size is " + status.getSize());
-						if (status.getSize() < 0) {
-							status.setSize(DownloadStatus.SIZE_UNKNOWN);
+							Log.d(TAG, "Size is " + request.getSize());
+						if (request.getSize() < 0) {
+							request.setSize(DownloadStatus.SIZE_UNKNOWN);
 						}
 
 						long freeSpace = StorageUtils.getFreeSpaceAvailable();
 						if (AppConfig.DEBUG)
 							Log.d(TAG, "Free space is " + freeSpace);
-						if (status.getSize() == DownloadStatus.SIZE_UNKNOWN
-								|| status.getSize() <= freeSpace) {
+						if (request.getSize() == DownloadStatus.SIZE_UNKNOWN
+								|| request.getSize() <= freeSpace) {
 							if (AppConfig.DEBUG)
 								Log.d(TAG, "Starting download");
 							while (!cancelled
 									&& (count = in.read(buffer)) != -1) {
 								out.write(buffer, 0, count);
-								status.setSoFar(status.getSoFar() + count);
-								status.setProgressPercent((int) (((double) status
-										.getSoFar() / (double) status.getSize()) * 100));
+								request.setSoFar(request.getSoFar() + count);
+								request.setProgressPercent((int) (((double) request
+										.getSoFar() / (double) request
+										.getSize()) * 100));
 							}
 							if (cancelled) {
 								onCancelled();
@@ -144,8 +142,7 @@ public class HttpDownloader extends Downloader {
 		} catch (NullPointerException e) {
 			// might be thrown by connection.getInputStream()
 			e.printStackTrace();
-			onFail(DownloadError.ERROR_CONNECTION_ERROR, status.getFeedFile()
-					.getDownload_url());
+			onFail(DownloadError.ERROR_CONNECTION_ERROR, request.getSource());
 		} finally {
 			IOUtils.closeQuietly(connection);
 			IOUtils.closeQuietly(out);
@@ -158,36 +155,30 @@ public class HttpDownloader extends Downloader {
 	private void onSuccess() {
 		if (AppConfig.DEBUG)
 			Log.d(TAG, "Download was successful");
-		status.setSuccessful(true);
-		status.setDone(true);
+		result = new DownloadStatus(request, 0, true, false, null);
 	}
 
 	private void onFail(int reason, String reasonDetailed) {
 		if (AppConfig.DEBUG) {
 			Log.d(TAG, "Download failed");
 		}
-		status.setReason(reason);
-		status.setReasonDetailed(reasonDetailed);
-		status.setDone(true);
-		status.setSuccessful(false);
+		result = new DownloadStatus(request, reason, false, false,
+				reasonDetailed);
 		cleanup();
 	}
 
 	private void onCancelled() {
 		if (AppConfig.DEBUG)
 			Log.d(TAG, "Download was cancelled");
-		status.setReason(DownloadError.ERROR_DOWNLOAD_CANCELLED);
-		status.setDone(true);
-		status.setSuccessful(false);
-		status.setCancelled(true);
+		result = new DownloadStatus(request,
+				DownloadError.ERROR_DOWNLOAD_CANCELLED, false, true, null);
 		cleanup();
 	}
 
 	/** Deletes unfinished downloads. */
 	private void cleanup() {
-		if (status != null && status.getFeedFile() != null
-				&& status.getFeedFile().getFile_url() != null) {
-			File dest = new File(status.getFeedFile().getFile_url());
+		if (request.getDestination() != null) {
+			File dest = new File(request.getDestination());
 			if (dest.exists()) {
 				boolean rc = dest.delete();
 				if (AppConfig.DEBUG)
diff --git a/src/de/danoeh/antennapod/storage/DBReader.java b/src/de/danoeh/antennapod/storage/DBReader.java
index 739ecd4be..e731a360e 100644
--- a/src/de/danoeh/antennapod/storage/DBReader.java
+++ b/src/de/danoeh/antennapod/storage/DBReader.java
@@ -10,7 +10,6 @@ import android.database.Cursor;
 import android.database.SQLException;
 import android.util.Log;
 import de.danoeh.antennapod.AppConfig;
-import de.danoeh.antennapod.asynctask.DownloadStatus;
 import de.danoeh.antennapod.feed.Chapter;
 import de.danoeh.antennapod.feed.Feed;
 import de.danoeh.antennapod.feed.FeedImage;
@@ -19,6 +18,7 @@ import de.danoeh.antennapod.feed.FeedMedia;
 import de.danoeh.antennapod.feed.ID3Chapter;
 import de.danoeh.antennapod.feed.SimpleChapter;
 import de.danoeh.antennapod.feed.VorbisCommentChapter;
+import de.danoeh.antennapod.service.download.DownloadStatus;
 import de.danoeh.antennapod.util.comparator.DownloadStatusComparator;
 import de.danoeh.antennapod.util.comparator.FeedItemPubdateComparator;
 
diff --git a/src/de/danoeh/antennapod/storage/DBWriter.java b/src/de/danoeh/antennapod/storage/DBWriter.java
index aece811ca..1a2468782 100644
--- a/src/de/danoeh/antennapod/storage/DBWriter.java
+++ b/src/de/danoeh/antennapod/storage/DBWriter.java
@@ -14,13 +14,13 @@ import android.database.Cursor;
 import android.preference.PreferenceManager;
 import android.util.Log;
 import de.danoeh.antennapod.AppConfig;
-import de.danoeh.antennapod.asynctask.DownloadStatus;
 import de.danoeh.antennapod.feed.EventDistributor;
 import de.danoeh.antennapod.feed.Feed;
 import de.danoeh.antennapod.feed.FeedItem;
 import de.danoeh.antennapod.feed.FeedMedia;
 import de.danoeh.antennapod.preferences.PlaybackPreferences;
 import de.danoeh.antennapod.service.PlaybackService;
+import de.danoeh.antennapod.service.download.DownloadStatus;
 
 public class DBWriter {
 	private static final String TAG = "DBWriter";
diff --git a/src/de/danoeh/antennapod/storage/DownloadRequester.java b/src/de/danoeh/antennapod/storage/DownloadRequester.java
index 29bd764dd..30abc4491 100644
--- a/src/de/danoeh/antennapod/storage/DownloadRequester.java
+++ b/src/de/danoeh/antennapod/storage/DownloadRequester.java
@@ -5,6 +5,7 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang3.StringUtils;
 
 import android.content.Context;
 import android.content.Intent;
@@ -17,6 +18,7 @@ import de.danoeh.antennapod.feed.FeedFile;
 import de.danoeh.antennapod.feed.FeedImage;
 import de.danoeh.antennapod.feed.FeedMedia;
 import de.danoeh.antennapod.preferences.UserPreferences;
+import de.danoeh.antennapod.service.download.DownloadRequest;
 import de.danoeh.antennapod.service.download.DownloadService;
 import de.danoeh.antennapod.util.FileNameGenerator;
 import de.danoeh.antennapod.util.URLChecker;
@@ -30,10 +32,10 @@ public class DownloadRequester {
 
 	private static DownloadRequester downloader;
 
-	Map<String, FeedFile> downloads;
+	Map<String, DownloadRequest> downloads;
 
 	private DownloadRequester() {
-		downloads = new ConcurrentHashMap<String, FeedFile>();
+		downloads = new ConcurrentHashMap<String, DownloadRequest>();
 	}
 
 	public static DownloadRequester getInstance() {
@@ -83,11 +85,13 @@ public class DownloadRequester {
 				Log.d(TAG,
 						"Requesting download of url " + item.getDownload_url());
 			item.setDownload_url(URLChecker.prepareURL(item.getDownload_url()));
-			item.setFile_url(dest.toString());
-			downloads.put(item.getDownload_url(), item);
 
-			DownloadService.Request request = new DownloadService.Request(
-					item.getFile_url(), item.getDownload_url());
+			DownloadRequest request = new DownloadRequest(item.getFile_url(),
+					item.getDownload_url(), item.getHumanReadableIdentifier(),
+					item.getId(), item.getTypeAsInt());
+			
+			downloads.put(request.getSource(), request);
+
 
 			if (!DownloadService.isRunning) {
 				Intent launchIntent = new Intent(context, DownloadService.class);
@@ -112,8 +116,8 @@ public class DownloadRequester {
 	 */
 	private boolean isFilenameAvailable(String path) {
 		for (String key : downloads.keySet()) {
-			FeedFile f = downloads.get(key);
-			if (f.getFile_url() != null && f.getFile_url().equals(path)) {
+			DownloadRequest r = downloads.get(key);
+			if (StringUtils.equals(r.getDestination(), path)) {
 				if (AppConfig.DEBUG)
 					Log.d(TAG, path
 							+ " is already used by another requested download");
@@ -194,8 +198,8 @@ public class DownloadRequester {
 
 	/** Returns true if there is at least one Feed in the downloads queue. */
 	public boolean isDownloadingFeeds() {
-		for (FeedFile f : downloads.values()) {
-			if (f.getClass() == Feed.class) {
+		for (DownloadRequest r : downloads.values()) {
+			if (r.getFeedfileType() == Feed.FEEDFILETYPE_FEED) {
 				return true;
 			}
 		}
@@ -210,7 +214,7 @@ public class DownloadRequester {
 		return false;
 	}
 
-	public FeedFile getDownload(String downloadUrl) {
+	public DownloadRequest getDownload(String downloadUrl) {
 		return downloads.get(downloadUrl);
 	}
 
@@ -223,15 +227,11 @@ public class DownloadRequester {
 		return downloads.isEmpty();
 	}
 
-	public FeedFile getDownloadAt(int index) {
-		return downloads.get(index);
-	}
-
 	/** Remove an object from the downloads-list of the requester. */
-	public void removeDownload(FeedFile f) {
-		if (downloads.remove(f.getDownload_url()) == null) {
+	public void removeDownload(DownloadRequest r) {
+		if (downloads.remove(r.getSource()) == null) {
 			Log.e(TAG,
-					"Could not remove object with url " + f.getDownload_url());
+					"Could not remove object with url " + r.getSource());
 		}
 	}
 
diff --git a/src/de/danoeh/antennapod/storage/PodDBAdapter.java b/src/de/danoeh/antennapod/storage/PodDBAdapter.java
index 72c96b961..dcc9533a5 100644
--- a/src/de/danoeh/antennapod/storage/PodDBAdapter.java
+++ b/src/de/danoeh/antennapod/storage/PodDBAdapter.java
@@ -14,12 +14,12 @@ import android.database.sqlite.SQLiteDatabase.CursorFactory;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.util.Log;
 import de.danoeh.antennapod.AppConfig;
-import de.danoeh.antennapod.asynctask.DownloadStatus;
 import de.danoeh.antennapod.feed.Chapter;
 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.service.download.DownloadStatus;
 
 /**
  * Implements methods for accessing the database
@@ -456,16 +456,8 @@ public class PodDBAdapter {
 	 * */
 	public long setDownloadStatus(DownloadStatus status) {
 		ContentValues values = new ContentValues();
-		if (status.getFeedFile() != null) {
-			values.put(KEY_FEEDFILE, status.getFeedFile().getId());
-			if (status.getFeedFile().getClass() == Feed.class) {
-				values.put(KEY_FEEDFILETYPE, Feed.FEEDFILETYPE_FEED);
-			} else if (status.getFeedFile().getClass() == FeedImage.class) {
-				values.put(KEY_FEEDFILETYPE, FeedImage.FEEDFILETYPE_FEEDIMAGE);
-			} else if (status.getFeedFile().getClass() == FeedMedia.class) {
-				values.put(KEY_FEEDFILETYPE, FeedMedia.FEEDFILETYPE_FEEDMEDIA);
-			}
-		}
+		values.put(KEY_FEEDFILE, status.getFeedfileId());
+		values.put(KEY_FEEDFILETYPE, status.getFeedfileType());
 		values.put(KEY_REASON, status.getReason());
 		values.put(KEY_SUCCESSFUL, status.isSuccessful());
 		values.put(KEY_COMPLETION_DATE, status.getCompletionDate().getTime());
@@ -679,11 +671,11 @@ public class PodDBAdapter {
 				+ "=0", null, null, null, KEY_PUBDATE + " DESC");
 		return c;
 	}
-	
+
 	public final Cursor getUnreadItemIdsCursor() {
 		open();
-		Cursor c = db.query(TABLE_NAME_FEED_ITEMS, new String[]{KEY_ID}, KEY_READ
-				+ "=0", null, null, null, KEY_PUBDATE + " DESC");
+		Cursor c = db.query(TABLE_NAME_FEED_ITEMS, new String[] { KEY_ID },
+				KEY_READ + "=0", null, null, null, KEY_PUBDATE + " DESC");
 		return c;
 
 	}
diff --git a/src/de/danoeh/antennapod/util/comparator/DownloadStatusComparator.java b/src/de/danoeh/antennapod/util/comparator/DownloadStatusComparator.java
index 12f800565..1891addc9 100644
--- a/src/de/danoeh/antennapod/util/comparator/DownloadStatusComparator.java
+++ b/src/de/danoeh/antennapod/util/comparator/DownloadStatusComparator.java
@@ -2,7 +2,7 @@ package de.danoeh.antennapod.util.comparator;
 
 import java.util.Comparator;
 
-import de.danoeh.antennapod.asynctask.DownloadStatus;
+import de.danoeh.antennapod.service.download.DownloadStatus;
 
 /** Compares the completion date of two Downloadstatus objects. */
 public class DownloadStatusComparator implements Comparator<DownloadStatus> {
diff --git a/tests/src/de/danoeh/antennapod/test/HttpDownloaderTest.java b/tests/src/de/danoeh/antennapod/test/HttpDownloaderTest.java
index 24d48bce4..470a08881 100644
--- a/tests/src/de/danoeh/antennapod/test/HttpDownloaderTest.java
+++ b/tests/src/de/danoeh/antennapod/test/HttpDownloaderTest.java
@@ -6,8 +6,8 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 
-import de.danoeh.antennapod.asynctask.DownloadStatus;
 import de.danoeh.antennapod.feed.Feed;
+import de.danoeh.antennapod.service.download.DownloadStatus;
 import de.danoeh.antennapod.service.download.Downloader;
 import de.danoeh.antennapod.service.download.DownloaderCallback;
 import de.danoeh.antennapod.service.download.HttpDownloader;