package download_manager.services;
import activity.ABase;
import activity.ADownloadManager;
import adapter.CompleteListAdapter;
import adapter.DownloadListAdapter;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Vibrator;
import android.widget.Toast;
import application.App;
import com.softcsoftware.aio.R;
import data.object_holder.DownloadData;
import data_handler_system.CDM;
import data_handler_system.DM;
import tools.StorageUtils;
import tts.TTS;
import java.io.File;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import static java.lang.String.valueOf;
import static tools.StorageUtils.size;
/**
* DownloadController is responsible for controlling the download task running.
*/
public class DownloadController extends Thread {
public static final String INTENT_OPEN_ACTION = "INTENT_OPEN_ACTION";
private static final int MAX_DOWNLOAD_TASK = 100;
private static int MAX_RUNNING_TASK = 1;
private final List<DownloadTask> runningTaskArray;
private Context context;
private TaskQueue waitingTaskArray;
private Boolean isRunning = false;
private DM databaseManager;
private CDM cdm;
private App application;
private DownloadListAdapter downloadListAdapter;
private CompleteListAdapter completeListAdapter;
private TTS tts;
private NotificationManager notificationManager;
private int download_status_icon;
{
download_status_icon = R.drawable.ic_downloading_notification;
}
private int failedIcon = R.drawable.ic_download_falied_notification;
private int completeIcon = R.drawable.ic_download_complete_notification;
/**
* Public constructor.
*
* @param context the application service context.
* @param app the application reference.
*/
public DownloadController(Context context, App app) {
this.context = context;
this.application = app;
tts = new TTS(context);
//set the notification.
notificationManager = (NotificationManager)
this.context.getSystemService(Context.NOTIFICATION_SERVICE);
MAX_RUNNING_TASK = application.getSettingsHolder().maxDownloadTask;
//waiting task amd the running task list.
waitingTaskArray = new TaskQueue();
runningTaskArray = application.getDataHandler().getRunningDownloadTask();
databaseManager = application.getDataHandler().getDownloadingDM();
cdm = application.getDataHandler().getCompleteCDM();
downloadListAdapter = application.getDataHandler().getDownloadingListAdapter();
completeListAdapter = application.getDataHandler().getCompleteListAdapter();
startProcess();
}
public void startProcess() {
isRunning = true;
start();
}
public void close() {
isRunning = false;
try {
interrupt();
} catch (Exception e) {
e.printStackTrace();
}
}
public boolean isRunning() {
return isRunning;
}
@Override
public void run() {
super.run();
while (isRunning) {
DownloadTask task = waitingTaskArray.poll();
runningTaskArray.add(task);
task.execute();
((DownloadService) context).startForeground();
}
}
protected synchronized PendingIntent getPendingIntent() {
Intent intent = new Intent(context, ADownloadManager.class);
return PendingIntent.getActivity(context, 0, intent, 0);
}
private DownloadData findDownloadData(String u, String n, String p) {
for (DownloadData data : this.databaseManager.getDatabase()) {
String name = data.getFileName();
String url = data.getFileUrl();
String path = data.getFilePath();
if (name.equals(n) && url.equals(u) && path.equals(p)) {
return data;
}
}
return null;
}
public synchronized List<DownloadTask> getRunningTasks() {
synchronized (runningTaskArray) {
return runningTaskArray;
}
}
public void addDownloadTask(String _url, String _path, String _name, String _webpage) {
if (!StorageUtils.isSDCardPresent()) {
Toast.makeText(context, "Sdcard not present", Toast.LENGTH_LONG).show();
return;
}
if (!StorageUtils.isSdCardWriteable()) {
Toast.makeText(context, "Sdcard not writable", Toast.LENGTH_LONG).show();
return;
}
if (databaseManager.getDatabase().size() >= MAX_DOWNLOAD_TASK) {
Toast.makeText(context, "Can't move, This is the maximum downloading space", Toast.LENGTH_LONG).show();
return;
}
try {
addTaskAndNotify(getNewDownloadTask(_webpage, _url, _path, _name));
} catch (Exception error) {
error.printStackTrace();
Toast.makeText(context, _name + " - Has failed to add.", Toast.LENGTH_SHORT).show();
}
}
private void addTaskAndNotify(DownloadTask task) throws Exception {
DownloadData data = new DownloadData();
data.setFileName(task.getFileName());
data.setFilePath(task.getFilePath());
data.setFileUrl(task.getFileUrl());
data.setFileWebpage(task.getFileWebpage());
data.setDownloaded(size(task.getDownloadSize()));
data.setTotalFileSize(size(task.getTotalSize()));
data.setPercent(valueOf(task.getDownloadPercent()));
data.setTraffic(size(task.getDownloadSpeed()));
data.setIsPause(valueOf(task.isPause()));
data.isDelete("false");
data.setIsFailed(valueOf(false));
data.autoResume = application.getSettingsHolder().isAutoResume;
int id = 0;
for (DownloadData d : databaseManager.getDatabase()) {
if (d.getId() == id) {
id++;
}
if (id < d.getId()) {
id = d.getId() + 1;
}
}
data.setId(id);
boolean suc = databaseManager.saveDataToSdcard(data);
if (suc) {
databaseManager.getDatabase().add(data);
waitingTaskArray.offer(task);
Intent intent = new Intent();
intent.setAction(ABase.ACTION_UPDATE);
intent.putExtra("Index", data.getId());
this.context.sendBroadcast(intent);
Toast.makeText(context, data.getFileName() + " - Has added to the list.", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, data.getFileName() + " - Has failed to add.", Toast.LENGTH_SHORT).show();
}
if (!this.isAlive()) {
startProcess();
}
}
public synchronized List<DownloadTask> getRunningList() {
return this.runningTaskArray;
}
public TaskQueue getTaskQueue() {
return this.waitingTaskArray;
}
public synchronized boolean setTaskQueue() {
try {
this.waitingTaskArray = new TaskQueue();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public synchronized boolean isThatARunningTask(String url, String name, String path) {
boolean result = false;
for (DownloadTask task1 : this.runningTaskArray) {
if (task1.getFileUrl().equals(url) && task1.getFilePath().equals(path) && task1.getFileName().equals(name)) {
result = true;
}
}
return result;
}
public synchronized DownloadTask findRunningTask(String url, String name, String path) {
DownloadTask result = null;
for (DownloadTask task1 : this.runningTaskArray) {
if (task1.getFileUrl().equals(url) && task1.getFilePath().equals(path) && task1.getFileName().equals(name)) {
result = task1;
}
}
return result;
}
public synchronized DownloadTask findWaitingTask(String url, String name, String path) {
for (int i = 0; i < this.waitingTaskArray.size(); i++) {
DownloadTask task = waitingTaskArray.get(i);
if (task.getFileUrl().equals(url) &&
task.getFilePath().equals(path) &&
task.getFileName().equals(name)) {
return task;
}
}
return null;
}
public synchronized boolean removeRunningTask(DownloadTask task) {
synchronized (this.runningTaskArray) {
return this.runningTaskArray.remove(task);
}
}
//----------------------------------------------------------------------------------//
public void pauseAll() {
for (DownloadTask t : runningTaskArray) {
this.pauseTask(t.getFileUrl(), t.getFileName(), t.getFilePath());
}
for (int i = 0; i < this.waitingTaskArray.size(); i++) {
DownloadTask task = waitingTaskArray.get(i);
pauseTask(task.getFileUrl(), task.getFilePath(), task.getFileName());
}
}
public void pauseTask(String url, String name, String path) {
if (!isThatARunningTask(url, name, path)) { //this is not a running task but a waiting task.
App.log('e', getClass().getName(), "Pausing the data.>>>>>>>>>>>" +
" This is not a running task. ");
//find a waiting task.
DownloadTask task = findWaitingTask(url, name, path);
if (task != null) {
App.log('e', getClass().getName(), "Pausing the data.>>>>>>>>>>>" +
" Is a waiting task. ");
//remove the task from waiting task.
waitingTaskArray.remove(task);
DownloadData data = findDownloadData(url, name, path);
if (data != null) {
data.setIsPause(valueOf(true));
data.autoResume = false;
data.pauseOrder = true;
data.forcePause = true;
Intent intent = new Intent();
intent.setAction(ABase.ACTION_UPDATE);
intent.putExtra("Index", data.getId());
context.sendBroadcast(intent);
return;
}
}
//this is not a waiting task either.
else {
App.log('e', getClass().getName(), "Pausing the data.>>>>>>>>>>>" +
" Is a paused data. ");
DownloadData data = findDownloadData(url, name, path);
if (data != null) {
App.log('e', getClass().getName(), "Pausing the data.>>>>>>>>>>>" +
" Data is not null. ");
if (data.autoResume) {
data.autoResume = false;
data.pauseOrder = true;
data.forcePause = true;
return;
}
}
}
String message = "This task is not running, so it can't be paused.";
Intent intent = new Intent();
intent.setAction(ABase.ACTION_MESSAGE);
intent.putExtra("Index", message);
this.context.sendBroadcast(intent);
return;
}
DownloadTask runningTask = findRunningTask(url, name, path);
if (runningTask != null) {
removeRunningTask(runningTask);
DownloadData data = findDownloadData(url, name, path);
if (data != null) {
data.autoResume = false;
data.pauseOrder = true;
data.forcePause = true;
data.setIsPause(valueOf(true));
runningTask.onCancelled();
Intent intent = new Intent();
intent.setAction(ABase.ACTION_UPDATE);
intent.putExtra("Index", data.getId());
context.sendBroadcast(intent);
return;
}
}
Toast.makeText(context, name + " - Has failed to pause", Toast.LENGTH_SHORT).show();
}
public void removeTaskFromList(String url, String name, String path) {
try {
App.log('i', getClass().getName(), "going to delete the tmp file.");
//delete the cache tmp file from the sdcard.
new File(DM.CACHE_PATH, name + ".tmp").delete();
//the download file.
File downloadTmpFile = new File(path, name + ".download");
//rename the file to it's original name.
if (downloadTmpFile.exists())
downloadTmpFile.renameTo(new File(path, name));
//get a waiting task.
DownloadTask waitingTask = findWaitingTask(url, name, path);
if (waitingTask != null) { //this is a waiting task.
//remove the waiting task from the waiting list.
waitingTaskArray.remove(waitingTask);
//get the matching download data.
DownloadData downloadData = findDownloadData(url, name, path);
if (downloadData != null) { //found matching download data.
//remove the data from the database.
boolean remove = databaseManager.getDatabase().remove(downloadData);
if (remove) { //successfully removed.
//notify the data set change of adapter.
downloadListAdapter.notifyDataSetChanged();
}
}
}
//if the task is not a waiting task but a running task.
else if (isThatARunningTask(url, name, path)) {
DownloadTask runningTask = findRunningTask(url, name, path);
if (runningTask != null) { //running task has found.
//remove the running task from the running list.
removeRunningTask(runningTask);
//stop the running task.
runningTask.onCancelled();
DownloadData downloadData = findDownloadData(url, name, path);
if (downloadData != null) {
//set the download data that it is ordered for deleting itself.
downloadData.deleteOrder = true;
downloadData.pauseOrder = true;
downloadData.autoResume = false;
//cancel the notification.
notificationManager.cancel(downloadData.getId());
//remove the data from database.
databaseManager.getDatabase().remove(downloadData);
//update the adapter.
downloadListAdapter.notifyDataSetChanged();
}
}
}
//the task is not running. it is just a paused task.
else {
DownloadData downloadData = findDownloadData(url, name, path);
if (downloadData != null) {
//cancel the notification.
notificationManager.cancel(downloadData.getId());
//remove the data from database.
databaseManager.getDatabase().remove(downloadData);
//update the adapter.
downloadListAdapter.notifyDataSetChanged();
}
}
} catch (Exception error) {
App.log('e', getClass().getName(), error.getMessage());
error.printStackTrace();
//update the ui.
downloadListAdapter.notifyDataSetChanged();
}
}
public void removeTaskWithSource(String url, String name, String path) {
//remove the task from the task list.
removeTaskFromList(url, name, path);
//delete the original file from sdcard.
new File(path, name).delete();
}
public void restartTask(String url, String name, String path) {
try {
StorageUtils.delete(new File(DM.CACHE_PATH, name + ".tmp"));
StorageUtils.delete(new File(path, name + DownloadTask.TEMP_SUFFIX));
DownloadTask task = this.findWaitingTask(url, name, path);
if (task != null) {
this.waitingTaskArray.remove(task);
for (DownloadData data1 : this.databaseManager.getDatabase()) {
if (data1.getFileUrl().equals(url) &&
data1.getFileName().equals(name) &&
data1.getFilePath().equals(path)) {
this.databaseManager.getDatabase().remove(data1);
Intent intent = new Intent();
intent.setAction(ABase.ACTION_UPDATE);
intent.putExtra("Index", data1.getId());
this.context.sendBroadcast(intent);
addDownloadTask(url, path, name, data1.getFileWebpage());
return;
}
}
} else if (isThatARunningTask(url, name, path)) {
for (DownloadTask task1 : this.runningTaskArray) {
if (task1.getFileUrl().equals(url) &&
task1.getFilePath().equals(path) &&
task1.getFileName().equals(name)) {
boolean s = this.removeRunningTask(task1);
task1.onCancelled();
for (DownloadData data1 : this.databaseManager.getDatabase()) {
if (data1.getFileUrl().equals(url) &&
data1.getFileName().equals(name) &&
data1.getFilePath().equals(path)) {
data1.isDelete("false");
this.notificationManager.cancel(data1.getId());
this.databaseManager.getDatabase().remove(data1);
Intent intent = new Intent();
intent.setAction(ABase.ACTION_UPDATE);
intent.putExtra("Index", data1.getId());
this.context.sendBroadcast(intent);
addDownloadTask(url, path, name, data1.getFileWebpage());
return;
}
}
}
}
} else {
for (DownloadData data1 : this.databaseManager.getDatabase()) {
if (data1.getFileUrl().equals(url) &&
data1.getFileName().equals(name) &&
data1.getFilePath().equals(path)) {
this.databaseManager.getDatabase().remove(data1);
Intent intent = new Intent();
intent.setAction(ABase.ACTION_UPDATE);
intent.putExtra("Index", data1.getId());
this.context.sendBroadcast(intent);
addDownloadTask(url, path, name, data1.getFileWebpage());
return;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
//-----------------------------------------------------------------------------------//
public void resumeTask(boolean isAutoResume, String webpage, String url, String name, String path) {
if (isThatARunningTask(url, name, path)) {
if (!isAutoResume) { //auto resume is off.
String message = "This is a running task.";
Intent intent = new Intent();
intent.setAction(ABase.ACTION_MESSAGE);
intent.putExtra("Index", message);
context.sendBroadcast(intent);
}
return;
}
//that is not a running task but a waiting task.
else {
DownloadTask waitingTask = findWaitingTask(url, name, path);
if (waitingTask != null) {
if (!isAutoResume) { //auto resume is off.
String message = "This is a waiting task.";
Intent intent = new Intent();
intent.setAction(ABase.ACTION_MESSAGE);
intent.putExtra("Index", message);
this.context.sendBroadcast(intent);
}
return;
}
}
try {
DownloadTask task = getNewDownloadTask(webpage, url, path, name);
DownloadData data = findDownloadData(url, name, path);
if (data != null) {
data.setIsPause(valueOf(false));
data.pauseOrder = false;
data.forcePause = false;
data.deleteOrder = false;
data.autoResume = isAutoResume;
waitingTaskArray.offer(task);
Intent intent = new Intent();
intent.setAction(ABase.ACTION_UPDATE);
intent.putExtra("Index", data.getId());
context.sendBroadcast(intent);
}
} catch (Exception e) {
DownloadData data = findDownloadData(url, name, path);
if (data != null) {
data.setIsPause(valueOf(true));
data.pauseOrder = true;
data.deleteOrder = false;
Intent intent = new Intent();
intent.setAction(ABase.ACTION_UPDATE);
intent.putExtra("Index", data.getId());
context.sendBroadcast(intent);
}
Toast.makeText(context, name + " - Has failed to resume. try again.", Toast.LENGTH_LONG).show();
}
}
private synchronized void updateNotification(DownloadData data, Notification notification) {
notificationManager.notify(data.getId(), notification);
}
/**
* Get a new downloadTask.
*
* @param webpage the webpage.
* @param url the url.
* @param path the file path.
* @param name the file name.
* @return DownloadTask
* @throws Exception
*/
private DownloadTask getNewDownloadTask(String webpage, String url, String path, String name) throws Exception {
DownloadTaskListener taskListener = new DownloadTaskListener() {
private Notification notification = new Notification();
private PendingIntent pendingIntent = getPendingIntent();
private DownloadData data = new DownloadData();
/**
* Callback for updating the download process.
* @param task the download task
*/
@Override
public void updateProcess(final DownloadTask task) {
data = updateData(notification, pendingIntent, data, task);
}
@Override
public void preDownload(DownloadTask task) {
if (data == null) {
data = new DownloadData();
}
//update the new data set with original data.
preData(data, task);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.icon = download_status_icon;
notification.when = System.currentTimeMillis();
notification.setLatestEventInfo(context, data.getFileName(),
data.getDownloaded() + "/" + data.getTotal() //downloaded / total size
+ " Percent : " + data.getPercent() + "/100", //percentage.
pendingIntent); //pending intent.
updateNotification(data, notification);
}
/** Called after download will finished */
@Override
public void finishDownload(DownloadTask task) {
notification.icon = completeIcon;
this.notification.setLatestEventInfo(context, data.getFileName(), data.getDownloaded() + "/" + data.getTotal() + " Percent : " + "100/100", pendingIntent);
updateNotification(data, notification);
finishData(data, task);
}
/** Called if a error occur. */
@Override
public void errorDownload(DownloadTask task, Throwable error) {
onErrorDownload(data, task, notification, pendingIntent, error);
}
};
return new DownloadTask(application, context, webpage, url, path, name, taskListener);
}
/**
* Update the download data and replace it with original dataset.
*
* @param data the new download data.
* @param task the download task.
* @return the new download data.
*/
private DownloadData preData(DownloadData data, DownloadTask task) {
data.setFileName(task.getFileName());
data.setFilePath(task.getFilePath());
data.setFileUrl(task.getFileUrl());
data.setFileWebpage(task.getFileWebpage());
data.setDownloaded(size(task.getDownloadSize()));
data.setTotalFileSize(size(task.getTotalSize()));
data.setPercent(valueOf(task.getDownloadPercent()));
data.setTraffic(size(task.getDownloadSpeed()));
data.setIsPause(valueOf(task.isPause()));
data.pauseOrder = false;
data.deleteOrder = false;
data.autoResume = application.getSettingsHolder().isAutoResume;
//Find the original data set from database. and replace it.
DownloadData originalData = findDownloadData(task.getFileUrl(), task.getFileName(), task.getFilePath());
if (originalData != null) {
data.setId(originalData.getId());
if (originalData.forcePause) {
data.autoResume = false;
task.onCancelled();
}
databaseManager.updateDataset(originalData, data);
databaseManager.saveDataToSdcard(data);
}
return data;
}
/**
* Update the download data and ui.
*
* @param notification notification to the shown.
* @param pendingIntent pending intent for the notification.
* @param data download data to be updated.
* @param task download task
* @return new updated data.
*/
private DownloadData updateData(Notification notification, PendingIntent pendingIntent,
DownloadData data, DownloadTask task) {
//update the download data.
data.setDownloaded(size(task.getDownloadSize()));
data.setTotalFileSize(size(task.getTotalSize()));
data.setPercent(valueOf(task.getDownloadPercent()));
data.setTraffic(size(task.getDownloadSpeed()));
data.setIsPause(valueOf(task.isPause()));
if (data.forcePause) {
task.onCancelled();
}
try {
//Update the notification.
notification.setLatestEventInfo(context, data.getFileName(),
data.getDownloaded() + "/" + data.getTotal() //downloaded / total size
+ " Percent : " + data.getPercent() + "/100", //percentage.
pendingIntent); //pending intent.
//update the notification.
updateNotification(data, notification);
if (task.isPause()) { //download has been pause.
removeRunningTask(task); //remove the download task from running list.
if (data.pauseOrder) { //data has pause order.
if (!data.deleteOrder) //data has been set for delete order.
databaseManager.saveDataToSdcard(data);
}
//Update the notification for Pause task.
notification.icon = failedIcon;
notification.setLatestEventInfo(context, data.getFileName(),
data.getDownloaded() + "/" + data.getTotal() //downloaded / total size
+ " Percent : " + data.getPercent() + "/100", //percentage.
pendingIntent); //pending intent.
updateNotification(data, notification);
}
} catch (Exception error) {
error.printStackTrace();
removeRunningTask(task);
}
Intent intent = new Intent();
intent.setAction(ABase.ACTION_UPDATE);
intent.putExtra("Index", data.getId());
this.context.sendBroadcast(intent);
return data;
}
/**
* Update the ui after download will complete.
*
* @param downloadData the download data.
* @param task the download task.
* @return DownloadData
*/
private void finishData(DownloadData downloadData, DownloadTask task) {
//remove the task.
runningTaskArray.remove(task);
//toast a download message.
((Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE)).vibrate(20);
Toast.makeText(context, downloadData.getFileName() + " - Downloaded Successfully.", Toast.LENGTH_SHORT).show();
//remove the data from the database.
databaseManager.getDatabase().remove(databaseManager.getIndex(downloadData));
downloadListAdapter.notifyDataSetChanged();
StorageUtils.delete(new File(DM.CACHE_PATH, downloadData.getFileName() + ".tmp"));
if (cdm.addNewData(downloadData)) {
cdm.getDatabase().add(0, downloadData);
completeListAdapter.notifyDataSetChanged();
}
if (application.getSettingsHolder().isDownloadCompleteNotify) {
String readingText = task.getFileName().replaceAll("_", " ").replaceAll("-", " ");
tts.speak(readingText + " has successfully downloaded.");
}
}
/**
* Called when a download error has occur.
*
* @param data the download data.
* @param task the download task.
* @param notification the notification
* @param pendingIntent the pending intent.
* @param throwable the error.
*/
private void onErrorDownload(DownloadData data, DownloadTask task,
Notification notification, PendingIntent pendingIntent, Throwable throwable) {
//Update notification
notification.icon = failedIcon;
String notificationMessage = "Download has stopped.";
if (throwable != null)
if (throwable.getMessage() != null)
notificationMessage += " : " + throwable.getMessage();
notification.setLatestEventInfo(context, data.getFileName(), notificationMessage, pendingIntent);
//update notification.
updateNotification(data, notification);
if (!databaseManager.getDatabase().contains(data)) {
notificationManager.cancel(data.getId());
}
try {
removeRunningTask(task);
data.setDownloaded(size(task.getDownloadSize()));
data.setTotalFileSize(size(task.getTotalSize()));
data.setPercent(valueOf(task.getDownloadPercent()));
data.setTraffic(size(task.getDownloadSpeed()));
data.setIsPause(valueOf(true));
//Update the download data.
try {
if (data.pauseOrder) { //data has pause order.
if (!data.deleteOrder) //data has been set for delete order.
databaseManager.saveDataToSdcard(data);
}
} catch (Exception error) {
error.printStackTrace();
}
//update the ui.
try {
Intent intent = new Intent();
intent.setAction(ABase.ACTION_UPDATE);
intent.putExtra("Index", data.getId());
this.context.sendBroadcast(intent);
} catch (Exception error) {
error.printStackTrace();
App.log('e', getClass().getName(), "Failed to update the ui. going to directly notify " +
"the data set change of the adapter.");
}
if (application.getSettingsHolder().isAutoResume) {
if (throwable != null) {
throwable.printStackTrace();
if (application.getSettingsHolder().isAutoResumeOnAnyError) {
App.log('i', getClass().getName(), "Auto resuming task >>>>>>>>>>>> " + data.getFileName() +
"\n" +
"auto resume order = " + data.autoResume);
if (data.autoResume) {
resumeTask(true, null, task.getFileUrl(), task.getFileName(), task.getFilePath());
data.autoResume = true;
}
} else {
String message = throwable.getMessage();
if (message == null)
message = "";
message = message.toLowerCase();
//connection time out.
if (throwable instanceof SocketTimeoutException) {
if (data.autoResume) {
resumeTask(true, null, task.getFileUrl(), task.getFileName(), task.getFilePath());
data.autoResume = true;
}
} //UnknownHostException
else if (throwable instanceof UnknownHostException) {
if (data.autoResume) {
resumeTask(true, null, task.getFileUrl(), task.getFileName(), task.getFilePath());
data.autoResume = true;
}
} //end of stream.
else if (message.contains("unexpected end of stream".toLowerCase())) {
if (data.autoResume) {
resumeTask(true, null, task.getFileUrl(), task.getFileName(), task.getFilePath());
data.autoResume = true;
}
} else {
//Vibrate and make_toast to user
((Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE)).vibrate(20);
Toast.makeText(context, task.getFileName() + " - Downloading has stopped.",
Toast.LENGTH_LONG).show();
}
}
}
}
} catch (Exception error) {
error.printStackTrace();
}
}
/**
* <b>TaskQueue</b> is the private class that manage the waiting download task.
* It buffers the task and hold until a upper download task is completed or paused.
*/
private class TaskQueue {
/**
* The BlockingQueue is the list that holds the download tasks.
*/
private BlockingQueue<DownloadTask> taskQueue;
/**
* Public constructor.
*/
public TaskQueue() {
App.log('i', getClass().getName(), "Initializing the TaskQueue class...");
taskQueue = new ArrayBlockingQueue<DownloadTask>(MAX_DOWNLOAD_TASK);
}
/**
* Put a download task to the task queue holder.
*
* @param task the download task.
* @return the success signal.
*/
public boolean offer(DownloadTask task) {
boolean suc = taskQueue.offer(task);
App.log('i', getClass().getName(), "A new Download Task is added to TaskQueue... The" +
"\n result is " + (suc ? "Successful" : "Unsuccessful"));
return suc;
}
/**
* pu a download task to execution list or Running list.
*
* @return The download Task.,
*/
public DownloadTask poll() {
App.log('i', getClass().getName(), "Poll a download task to running list.");
DownloadTask task;
while (runningTaskArray.size() >= MAX_RUNNING_TASK || (task = taskQueue.poll()) == null) {
try {
Thread.sleep(2000); // sleep the thread.
} catch (InterruptedException error) {
App.log('e', getClass().getName(), "Error when selling the thread for 2sec in TaskQueue.");
error.printStackTrace();
}
}
return task;
}
/**
* Get a download task by task list position.
*
* @param position the tak index position.
* @return the download task.
*/
public DownloadTask get(int position) {
App.log('i', getClass().getName(), "Getting a download task from TaskQueue class.");
DownloadTask[] downloadTasks = taskQueue.toArray(new DownloadTask[this.size()]);
if (position >= size()) {
return null;
}
return downloadTasks[position];
}
/**
* Get queue list size.
*
* @return
*/
public int size() {
return taskQueue.size();
}
@SuppressWarnings("unused")
public boolean remove(int position) {
return taskQueue.remove(get(position));
}
public boolean remove(DownloadTask task) {
return taskQueue.remove(task);
}
}
}