Prevent media files from being deleted after a failed download

This commit is contained in:
daniel oeh 2014-04-27 17:02:37 +02:00
parent 8769d29cef
commit 6f77dea838
5 changed files with 109 additions and 61 deletions

View File

@ -146,7 +146,7 @@ public abstract class OnlineFeedViewActivity extends ActionBarActivity {
.toString();
feed.setFile_url(fileUrl);
final DownloadRequest request = new DownloadRequest(feed.getFile_url(),
feed.getDownload_url(), "OnlineFeed", 0, Feed.FEEDFILETYPE_FEED, username, password);
feed.getDownload_url(), "OnlineFeed", 0, Feed.FEEDFILETYPE_FEED, username, password, true);
downloader = new HttpDownloader(
request);
new Thread() {

View File

@ -10,6 +10,7 @@ public class DownloadRequest implements Parcelable {
private final String title;
private String username;
private String password;
private boolean deleteOnFailure;
private final long feedfileId;
private final int feedfileType;
@ -19,7 +20,7 @@ public class DownloadRequest implements Parcelable {
protected int statusMsg;
public DownloadRequest(String destination, String source, String title,
long feedfileId, int feedfileType, String username, String password) {
long feedfileId, int feedfileType, String username, String password, boolean deleteOnFailure) {
if (destination == null) {
throw new IllegalArgumentException("Destination must not be null");
}
@ -37,11 +38,12 @@ public class DownloadRequest implements Parcelable {
this.feedfileType = feedfileType;
this.username = username;
this.password = password;
this.deleteOnFailure = deleteOnFailure;
}
public DownloadRequest(String destination, String source, String title,
long feedfileId, int feedfileType) {
this(destination, source, title, feedfileId, feedfileType, null, null);
this(destination, source, title, feedfileId, feedfileType, null, null, true);
}
private DownloadRequest(Parcel in) {
@ -50,6 +52,7 @@ public class DownloadRequest implements Parcelable {
title = in.readString();
feedfileId = in.readLong();
feedfileType = in.readInt();
deleteOnFailure = (in.readByte() > 0);
if (in.dataAvail() > 0) {
username = in.readString();
} else {
@ -74,6 +77,7 @@ public class DownloadRequest implements Parcelable {
dest.writeString(title);
dest.writeLong(feedfileId);
dest.writeInt(feedfileType);
dest.writeByte((deleteOnFailure) ? (byte) 1 : 0);
if (username != null) {
dest.writeString(username);
}
@ -93,59 +97,43 @@ public class DownloadRequest implements Parcelable {
};
@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;
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DownloadRequest that = (DownloadRequest) o;
if (deleteOnFailure != that.deleteOnFailure) return false;
if (feedfileId != that.feedfileId) return false;
if (feedfileType != that.feedfileType) return false;
if (progressPercent != that.progressPercent) return false;
if (size != that.size) return false;
if (soFar != that.soFar) return false;
if (statusMsg != that.statusMsg) return false;
if (destination != null ? !destination.equals(that.destination) : that.destination != null) return false;
if (password != null ? !password.equals(that.password) : that.password != null) return false;
if (source != null ? !source.equals(that.source) : that.source != null) return false;
if (title != null ? !title.equals(that.title) : that.title != null) return false;
if (username != null ? !username.equals(that.username) : that.username != null) return false;
return true;
}
@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 int hashCode() {
int result = destination != null ? destination.hashCode() : 0;
result = 31 * result + (source != null ? source.hashCode() : 0);
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 + (deleteOnFailure ? 1 : 0);
result = 31 * result + (int) (feedfileId ^ (feedfileId >>> 32));
result = 31 * result + feedfileType;
result = 31 * result + progressPercent;
result = 31 * result + (int) (soFar ^ (soFar >>> 32));
result = 31 * result + (int) (size ^ (size >>> 32));
result = 31 * result + statusMsg;
return result;
}
public String getDestination() {
@ -215,4 +203,8 @@ public class DownloadRequest implements Parcelable {
public void setPassword(String password) {
this.password = password;
}
public boolean isDeleteOnFailure() {
return deleteOnFailure;
}
}

View File

@ -163,6 +163,7 @@ public class DownloadService extends Service {
} else {
Log.e(TAG, "Download failed");
saveDownloadStatus(status);
handleFailedDownload(status, downloader.getDownloadRequest());
}
}
sendDownloadHandledIntent();
@ -608,6 +609,11 @@ public class DownloadService extends Service {
syncExecutor.execute(new MediaHandlerThread(status, request));
}
private void handleFailedDownload(DownloadStatus status, DownloadRequest request) {
if (BuildConfig.DEBUG) Log.d(TAG, "Handling failed download");
syncExecutor.execute(new FailedDownloadHandler(status, request));
}
/**
* Takes a single Feed, parses the corresponding file and refreshes
* information in the manager
@ -791,6 +797,46 @@ public class DownloadService extends Service {
}
/**
* Handles failed downloads.
* <p/>
* If the file has been partially downloaded, this handler will set the file_url of the FeedFile to the location
* of the downloaded file.
* <p/>
* Currently, this handler only handles FeedMedia objects, because Feeds and FeedImages are deleted if the download fails.
*/
class FailedDownloadHandler implements Runnable {
private DownloadRequest request;
private DownloadStatus status;
FailedDownloadHandler(DownloadStatus status, DownloadRequest request) {
this.request = request;
this.status = status;
}
@Override
public void run() {
if (request.isDeleteOnFailure()) {
if (BuildConfig.DEBUG) Log.d(TAG, "Ignoring failed download, deleteOnFailure=true");
} else {
File dest = new File(request.getDestination());
if (dest.exists() && request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
Log.d(TAG, "File has been partially downloaded. Writing file url");
FeedMedia media = DBReader.getFeedMedia(DownloadService.this, request.getFeedfileId());
media.setFile_url(request.getDestination());
try {
DBWriter.setFeedMedia(DownloadService.this, media).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
}
/**
* Handles a completed image download.
*/

View File

@ -182,7 +182,9 @@ public class HttpDownloader extends Downloader {
Log.d(TAG, "Download failed");
}
result.setFailed(reason, reasonDetailed);
cleanup();
if (request.isDeleteOnFailure()) {
cleanup();
}
}
private void onCancelled() {

View File

@ -12,6 +12,7 @@ import de.danoeh.antennapod.service.download.DownloadService;
import de.danoeh.antennapod.util.FileNameGenerator;
import de.danoeh.antennapod.util.URLChecker;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
@ -72,9 +73,9 @@ public class DownloadRequester {
}
private void download(Context context, FeedFile item, File dest,
boolean overwriteIfExists, String username, String password) {
boolean overwriteIfExists, String username, String password, boolean deleteOnFailure) {
if (!isDownloadingFile(item)) {
if (!isFilenameAvailable(dest.toString()) || dest.exists()) {
if (!isFilenameAvailable(dest.toString()) || (deleteOnFailure && dest.exists())) {
if (BuildConfig.DEBUG)
Log.d(TAG, "Filename already used.");
if (isFilenameAvailable(dest.toString()) && overwriteIfExists) {
@ -114,7 +115,7 @@ public class DownloadRequester {
DownloadRequest request = new DownloadRequest(dest.toString(),
item.getDownload_url(), item.getHumanReadableIdentifier(),
item.getId(), item.getTypeAsInt(), username, password);
item.getId(), item.getTypeAsInt(), username, password, deleteOnFailure);
download(context, request);
} else {
@ -149,7 +150,7 @@ public class DownloadRequester {
String password = (feed.getPreferences() != null) ? feed.getPreferences().getPassword() : null;
download(context, feed, new File(getFeedfilePath(context),
getFeedfileName(feed)), true, username, password);
getFeedfileName(feed)), true, username, password, true);
}
}
@ -157,7 +158,7 @@ public class DownloadRequester {
throws DownloadRequestException {
if (feedFileValid(image)) {
download(context, image, new File(getImagefilePath(context),
getImagefileName(image)), false, null, null);
getImagefileName(image)), false, null, null, false);
}
}
@ -174,9 +175,16 @@ public class DownloadRequester {
username = null;
password = null;
}
File dest;
if (feedmedia.getFile_url() != null) {
dest = new File(feedmedia.getFile_url());
} else {
dest = new File(getMediafilePath(context, feedmedia),
getMediafilename(feedmedia));
}
download(context, feedmedia,
new File(getMediafilePath(context, feedmedia),
getMediafilename(feedmedia)), false, username, password
dest, false, username, password, false
);
}
}