/*
* Zirco Browser for Android
*
* Copyright (C) 2010 J. Devauchelle and contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
package org.shadowsocks.zirco.ui.runnables;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import org.shadowsocks.zirco.model.items.DownloadItem;
import org.shadowsocks.zirco.utils.IOUtils;
import android.os.Handler;
import android.os.Message;
/**
* Background downloader.
*/
public class DownloadRunnable implements Runnable {
private static final int BUFFER_SIZE = 4096;
private DownloadItem mParent;
private boolean mAborted;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
mParent.onFinished();
}
};
/**
* Contructor.
*
* @param parent
* The item to download.
*/
public DownloadRunnable(DownloadItem parent) {
mParent = parent;
mAborted = false;
}
/**
* Abort this download.
*/
public void abort() {
mAborted = true;
}
/**
* Get a file object representation of the file name, in th right folder of
* the SD card.
*
* @return A file object.
*/
private File getFile() {
File downloadFolder = IOUtils.getDownloadFolder();
if (downloadFolder != null) {
return new File(downloadFolder, getFileNameFromUrl());
} else {
mParent.setErrorMessage("Unable to get download folder from SD Card.");
return null;
}
}
/**
* Compute the file name given the url.
*
* @return The file name.
*/
private String getFileNameFromUrl() {
return mParent.getUrl()
.substring(mParent.getUrl().lastIndexOf("/") + 1);
}
@Override
public void run() {
File downloadFile = getFile();
if (downloadFile != null) {
if (downloadFile.exists()) {
downloadFile.delete();
}
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
mParent.onStart();
URL url = new URL(mParent.getUrl());
URLConnection conn = url.openConnection();
InputStream is = conn.getInputStream();
int size = conn.getContentLength();
double oldCompleted = 0;
double completed = 0;
bis = new BufferedInputStream(is);
bos = new BufferedOutputStream(new FileOutputStream(
downloadFile));
boolean downLoading = true;
byte[] buffer = new byte[BUFFER_SIZE];
int downloaded = 0;
int read;
int stepRead = 0;
while ((downLoading) && (!mAborted)) {
if ((size - downloaded < BUFFER_SIZE)
&& (size - downloaded > 0)) {
buffer = new byte[size - downloaded];
}
read = bis.read(buffer);
if (read > 0) {
bos.write(buffer, 0, read);
downloaded += read;
completed = ((downloaded * 100f) / size);
stepRead++;
} else {
downLoading = false;
}
// Notify each 5% or more.
if (oldCompleted + 5 < completed) {
mParent.onProgress((int) completed);
oldCompleted = completed;
}
}
} catch (MalformedURLException mue) {
mParent.setErrorMessage(mue.getMessage());
} catch (IOException ioe) {
mParent.setErrorMessage(ioe.getMessage());
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException ioe) {
mParent.setErrorMessage(ioe.getMessage());
}
}
if (bos != null) {
try {
bos.close();
} catch (IOException ioe) {
mParent.setErrorMessage(ioe.getMessage());
}
}
}
if (mAborted) {
if (downloadFile.exists()) {
downloadFile.delete();
}
}
}
mHandler.sendEmptyMessage(0);
}
}