package com.dotcool.reader.task;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.util.Date;
import android.os.AsyncTask;
import android.preference.PreferenceManager;
import android.util.Log;
import com.dotcool.reader.Constants;
import com.dotcool.reader.LNReaderApplication;
import com.dotcool.reader.UIHelper;
import com.dotcool.reader.callback.CallbackEventData;
import com.dotcool.reader.callback.DownloadCallbackEventData;
import com.dotcool.reader.callback.ICallbackNotifier;
import com.dotcool.reader.helper.AsyncTaskResult;
import com.dotcool.reader.helper.Util;
import com.dotcool.reader.model.ImageModel;
public class DownloadFileTask extends AsyncTask<URL, Integer, AsyncTaskResult<ImageModel>> {
private static final String TAG = DownloadFileTask.class.toString();
private ICallbackNotifier notifier = null;
public DownloadFileTask(ICallbackNotifier notifier) {
super();
this.notifier = notifier;
}
@Override
protected AsyncTaskResult<ImageModel> doInBackground(URL... urls) {
try {
ImageModel image = downloadImage(urls[0]);
return new AsyncTaskResult<ImageModel>(image);
} catch (Exception e) {
return new AsyncTaskResult<ImageModel>(e);
}
}
public ImageModel downloadImage(URL url) throws Exception {
Log.d(TAG, "Start Downloading: " + url.toString());
InputStream input = null;
OutputStream output = null;
String filepath = UIHelper.getImageRoot(LNReaderApplication.getInstance().getApplicationContext()) + url.getFile();
@SuppressWarnings("deprecation")
String decodedUrl = Util.sanitizeFilename(URLDecoder.decode(filepath));
Log.d(TAG, "Saving to: " + decodedUrl);
// create dir if not exist
String path = decodedUrl.substring(0, decodedUrl.lastIndexOf("/"));
File cacheDir = new File(path);
if (cacheDir.mkdirs() || cacheDir.isDirectory()) {
Log.d(TAG, "Path to: " + path);
} else {
Log.e(TAG, "Failed to create Path: " + path);
}
File tempFilename = new File(decodedUrl + ".!tmp");
File decodedFile = new File(decodedUrl);
Log.d(TAG, "Start downloading image: " + url);
// remove temp file if exist
if (tempFilename.exists()) {
tempFilename.delete();
}
URLConnection connection = url.openConnection();
int timeout = UIHelper.getIntFromPreferences(Constants.PREF_TIMEOUT, 60) * 1000;
connection.setConnectTimeout(timeout);
connection.setReadTimeout(timeout);
connection.connect();
// this will be useful so that you can show a typical 0-100% progress bar
// I'm not using it AT them moment, but don't remove, might be useful for real.
int fileLength = connection.getContentLength();
// check saved filesize if already downloaded
boolean download = true;
if (decodedFile.exists()) {
if (decodedFile.length() == fileLength) {
download = false;
Log.d(TAG, "File exists: " + decodedUrl + " Size: " + fileLength);
} else {
decodedFile.delete();
Log.d(TAG, "File exists but different size: " + decodedUrl + " " + decodedFile.length() + "!=" + fileLength);
}
}
if (download) {
for (int i = 0; i < UIHelper.getIntFromPreferences(Constants.PREF_RETRY, 3); ++i) {
try {
boolean increase_retry = PreferenceManager.getDefaultSharedPreferences(LNReaderApplication.getInstance().getApplicationContext()).getBoolean(Constants.PREF_INCREASE_RETRY, false);
if (increase_retry) {
timeout = timeout * (i + 1);
connection.setConnectTimeout(timeout);
connection.setReadTimeout(timeout);
}
// download the file
input = new BufferedInputStream(url.openStream());
output = new FileOutputStream(tempFilename);
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
int progress = (int) (total * 100 / fileLength);
publishProgress(progress);
// via notifier, C# style :)
if (notifier != null) {
DownloadCallbackEventData message = new DownloadCallbackEventData();
message.setUrl(url.toString());
message.setTotalSize(fileLength);
message.setDownloadedSize(total);
message.setFilePath(decodedUrl);
notifier.onCallback(message);// "Downloading: " + url + "\nProgress: " + progress + "%");
}
// Log.d(TAG, "Downloading: " + url + " " + progress + "%");
output.write(data, 0, count);
}
Log.d(TAG, "Filesize: " + total);
if (total > 0)
break;
} catch (Exception ex) {
if (i > UIHelper.getIntFromPreferences(Constants.PREF_RETRY, 3)) {
Log.e(TAG, "Failed to download: " + url.toString(), ex);
throw ex;
} else {
if (notifier != null) {
notifier.onCallback(new CallbackEventData("Downloading: " + url + "\nRetry: " + i + "x"));
}
}
} finally {
if (output != null) {
output.flush();
output.close();
}
if (input != null) {
input.close();
}
}
}
// Rename file
tempFilename.renameTo(decodedFile);
Log.d(TAG, "Downloading image complete, saved to: " + decodedUrl);
}
ImageModel image = new ImageModel();
image.setDedepath(decodedUrl);
image.setName(url.getFile());
image.setUrl(url);
image.setPath(filepath);
image.setLastCheck(new Date());
image.setLastUpdate(new Date());
Log.d(TAG, "Complete Downloading: " + url.toString());
return image;
}
}