diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/group/AbsGroupCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/group/AbsGroupCmd.java index f8b2e0ed..56b8e17d 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/group/AbsGroupCmd.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/group/AbsGroupCmd.java @@ -16,8 +16,10 @@ package com.arialyy.aria.core.command.group; import com.arialyy.aria.core.command.AbsCmd; +import com.arialyy.aria.core.download.DownloadGroupTaskEntity; import com.arialyy.aria.core.download.DownloadTaskEntity; import com.arialyy.aria.core.inf.AbsTaskEntity; +import com.arialyy.aria.core.queue.DownloadGroupTaskQueue; import com.arialyy.aria.core.queue.DownloadTaskQueue; import com.arialyy.aria.core.queue.UploadTaskQueue; import com.arialyy.aria.core.upload.UploadTaskEntity; @@ -36,12 +38,9 @@ public abstract class AbsGroupCmd extends AbsCmd { mTargetName = targetName; mTaskEntity = entity; TAG = CommonUtil.getClassName(this); - if (entity instanceof DownloadTaskEntity) { - mQueue = DownloadTaskQueue.getInstance(); + if (entity instanceof DownloadGroupTaskEntity) { + mQueue = DownloadGroupTaskQueue.getInstance(); isDownloadCmd = true; - } else if (entity instanceof UploadTaskEntity) { - mQueue = UploadTaskQueue.getInstance(); - isDownloadCmd = false; } } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/normal/AddCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/normal/AddCmd.java index 9e0d094e..6f7f3e9f 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/normal/AddCmd.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/normal/AddCmd.java @@ -33,7 +33,7 @@ class AddCmd extends AbsNormalCmd { @Override public void executeCmd() { if (!canExeCmd) return; - AbsNormalTask task = mQueue.getTask(mTaskEntity.getEntity()); + AbsNormalTask task = (AbsNormalTask) mQueue.getTask(mTaskEntity.getEntity()); if (task == null) { mTaskEntity.getEntity().setState(IEntity.STATE_WAIT); mQueue.createTask(mTargetName, mTaskEntity); diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/normal/CancelCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/normal/CancelCmd.java index 5621da16..4e13b329 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/normal/CancelCmd.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/normal/CancelCmd.java @@ -31,9 +31,9 @@ class CancelCmd extends AbsNormalCmd { @Override public void executeCmd() { if (!canExeCmd) return; - AbsNormalTask task = mQueue.getTask(mTaskEntity.getEntity()); + AbsNormalTask task = (AbsNormalTask) mQueue.getTask(mTaskEntity.getEntity()); if (task == null) { - task = mQueue.createTask(mTargetName, mTaskEntity); + task = (AbsNormalTask) mQueue.createTask(mTargetName, mTaskEntity); } if (task != null) { if (!TextUtils.isEmpty(mTargetName)) { diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/normal/HighestPriorityCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/normal/HighestPriorityCmd.java index f12b6487..e0efa2f7 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/normal/HighestPriorityCmd.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/normal/HighestPriorityCmd.java @@ -16,8 +16,10 @@ package com.arialyy.aria.core.command.normal; import android.text.TextUtils; +import com.arialyy.aria.core.download.DownloadTask; import com.arialyy.aria.core.inf.AbsNormalTask; import com.arialyy.aria.core.inf.AbsTaskEntity; +import com.arialyy.aria.core.queue.DownloadTaskQueue; /** * Created by lyy on 2017/6/2. @@ -28,6 +30,8 @@ import com.arialyy.aria.core.inf.AbsTaskEntity; * 4、用户手动暂停或任务完成后,第二次重新执行该任务,该命令将失效 * 5、如果下载队列中已经满了,则会停止队尾的任务,当高优先级任务完成后,该队尾任务将自动执行 * 6、把任务设置为最高优先级任务后,将自动执行任务,不需要重新调用start()启动任务 + * + * 目前只只支持单下载任务的最高优先级任务 */ final class HighestPriorityCmd extends AbsNormalCmd { /** @@ -39,15 +43,15 @@ final class HighestPriorityCmd extends AbsNormalCmd @Override public void executeCmd() { if (!canExeCmd) return; - AbsNormalTask task = mQueue.getTask(mTaskEntity.getEntity()); + DownloadTask task = (DownloadTask) mQueue.getTask(mTaskEntity.getEntity()); if (task == null) { - task = mQueue.createTask(mTargetName, mTaskEntity); + task = (DownloadTask) mQueue.createTask(mTargetName, mTaskEntity); } if (task != null) { if (!TextUtils.isEmpty(mTargetName)) { task.setTargetName(mTargetName); } - mQueue.setTaskHighestPriority(task); + ((DownloadTaskQueue) mQueue).setTaskHighestPriority(task); } } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/normal/ResumeAllCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/normal/ResumeAllCmd.java index 8ae46e85..cd3336e7 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/normal/ResumeAllCmd.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/normal/ResumeAllCmd.java @@ -39,10 +39,10 @@ final class ResumeAllCmd extends AbsNormalCmd { } private AbsNormalTask createTask(DownloadEntity entity) { - AbsNormalTask task = mQueue.getTask(entity); + AbsNormalTask task = (AbsNormalTask) mQueue.getTask(entity); if (task == null) { DownloadTaskEntity taskEntity = new DownloadTaskEntity(entity); - task = mQueue.createTask(mTargetName, taskEntity); + task = (AbsNormalTask) mQueue.createTask(mTargetName, taskEntity); } else { Log.w(TAG, "添加命令执行失败,【该任务已经存在】"); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/normal/StartCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/normal/StartCmd.java index 39f58cd7..11c713af 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/normal/StartCmd.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/normal/StartCmd.java @@ -47,9 +47,9 @@ class StartCmd extends AbsNormalCmd { maxTaskNum = manager.getUploadConfig().getMaxTaskNum(); } - AbsNormalTask task = mQueue.getTask(mTaskEntity.getEntity()); + AbsNormalTask task = (AbsNormalTask) mQueue.getTask(mTaskEntity.getEntity()); if (task == null) { - task = mQueue.createTask(mTargetName, mTaskEntity); + task = (AbsNormalTask) mQueue.createTask(mTargetName, mTaskEntity); if (!TextUtils.isEmpty(mTargetName)) { task.setTargetName(mTargetName); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/normal/StopCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/normal/StopCmd.java index 84d55329..cd926b7c 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/normal/StopCmd.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/normal/StopCmd.java @@ -34,10 +34,10 @@ class StopCmd extends AbsNormalCmd { @Override public void executeCmd() { if (!canExeCmd) return; - AbsNormalTask task = mQueue.getTask(mTaskEntity.getEntity()); + AbsNormalTask task = (AbsNormalTask) mQueue.getTask(mTaskEntity.getEntity()); if (task == null) { if (mTaskEntity.getEntity().getState() == IEntity.STATE_RUNNING) { - task = mQueue.createTask(mTargetName, mTaskEntity); + task = (AbsNormalTask) mQueue.createTask(mTargetName, mTaskEntity); mQueue.stopTask(task); } else { Log.w(TAG, "停止命令执行失败,【调度器中没有该任务】"); diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTask.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTask.java index 308c041e..9c3d778e 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTask.java @@ -1,269 +1,205 @@ -///* -// * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) -// * -// * Licensed under the Apache License, Version 2.0 (the "License"); -// * you may not use this file except in compliance with the License. -// * You may obtain a copy of the License at -// * -// * http://www.apache.org/licenses/LICENSE-2.0 -// * -// * Unless required by applicable law or agreed to in writing, software -// * distributed under the License is distributed on an "AS IS" BASIS, -// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// * See the License for the specific language governing permissions and -// * limitations under the License. -// */ -//package com.arialyy.aria.core.download; -// -//import android.content.Context; -//import android.os.Handler; -//import android.util.SparseArray; -//import com.arialyy.aria.core.Aria; -//import com.arialyy.aria.core.AriaManager; -//import com.arialyy.aria.core.download.downloader.DownloadListener; -//import com.arialyy.aria.core.download.downloader.DownloadUtil; -//import com.arialyy.aria.core.inf.AbsGroupTask; -//import com.arialyy.aria.core.inf.IEntity; -//import com.arialyy.aria.core.scheduler.DownloadSchedulers; -//import com.arialyy.aria.core.scheduler.ISchedulers; -//import com.arialyy.aria.util.CheckUtil; -//import com.arialyy.aria.util.CommonUtil; -//import java.lang.ref.WeakReference; -//import java.util.HashMap; -//import java.util.List; -//import java.util.Map; -//import java.util.concurrent.ExecutorService; -//import java.util.concurrent.Executors; -// -///** -// * Created by AriaL on 2017/6/27. -// * 任务组任务 -// */ -//public class DownloadGroupTask extends AbsGroupTask { -// DListener mListener; -// SparseArray mUtils = new SparseArray<>(); -// boolean isStop = false; -// -// private ExecutorService mFixedThreadPool; -// -// private DownloadGroupTask(DownloadTaskEntity taskEntity, Handler outHandler) { -// mTaskEntity = taskEntity; -// mEntity = taskEntity.groupEntity; -// mOutHandler = outHandler; -// mContext = AriaManager.APP; -// mListener = new DListener(mContext, this, mOutHandler); -// mFixedThreadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); -// } -// -// @Override public void start() { -// List childs = mEntity.getChild(); -// int i = 1; -// mListener.sendInState2Target(ISchedulers.PRE); -// for (DownloadEntity entity : childs) { -// DownloadUtil util = createChildDownload(entity); -// if (isStop) break; -// mUtils.append(i, util); -// mFixedThreadPool.execute(util); -// i++; -// } -// } -// -// /** -// * 创建任务组单个任务下载工具 -// */ -// private DownloadUtil createChildDownload(DownloadEntity entity) { -// DownloadTaskEntity taskEntity = new DownloadTaskEntity(entity); -// taskEntity.headers = mTaskEntity.headers; -// taskEntity.requestEnum = mTaskEntity.requestEnum; -// taskEntity.redirectUrlKey = mTaskEntity.redirectUrlKey; -// taskEntity.removeFile = mTaskEntity.removeFile; -// return new DownloadUtil(mContext, taskEntity, mListener); -// } -// -// @Override public void stop() { -// isStop = true; -// if (mFixedThreadPool != null) { -// mFixedThreadPool.shutdown(); -// } -// for (int i = 1, len = mUtils.size(); i <= len; i++) { -// DownloadUtil util = mUtils.get(i); -// if (util != null && util.isDownloading()) { -// util.stopDownload(); -// } -// } -// } -// -// @Override public void cancel() { -// isStop = true; -// if (mFixedThreadPool != null) { -// mFixedThreadPool.shutdown(); -// } -// for (int i = 1, len = mUtils.size(); i <= len; i++) { -// DownloadUtil util = mUtils.get(i); -// if (util != null) { -// util.cancelDownload(); -// } -// } -// } -// -// /** -// * 下载监听类 -// */ -// private static class DListener extends DownloadListener { -// WeakReference outHandler; -// WeakReference wTask; -// Context context; -// long lastLen = 0; //上一次发送长度 -// long lastTime = 0; -// long INTERVAL_TIME = 1000; //1m更新周期 -// boolean isFirst = true; -// DownloadGroupEntity groupEntity; -// DownloadGroupTask task; -// boolean isConvertSpeed = false; -// Map mEntityMap = new HashMap<>(); -// -// DListener(Context context, DownloadGroupTask task, Handler outHandler) { -// this.context = context; -// this.outHandler = new WeakReference<>(outHandler); -// this.wTask = new WeakReference<>(task); -// this.task = wTask.get(); -// this.groupEntity = this.task.getEntity(); -// final AriaManager manager = AriaManager.getInstance(context); -// isConvertSpeed = manager.getDownloadConfig().isConvertSpeed(); -// for (DownloadEntity entity : groupEntity.getChild()) { -// mEntityMap.put(entity.getDownloadUrl(), entity); -// } -// } -// -// @Override public void onPre(String url) { -// saveData(url, IEntity.STATE_PRE, -1); -// } -// -// @Override public void onPostPre(String url, long fileSize) { -// DownloadEntity entity = mEntityMap.get(url); -// if (entity != null){ -// entity.setFileSize(fileSize); -// } -// saveData(url, IEntity.STATE_POST_PRE, -1); -// } -// -// @Override public void onStart(String url, long startLocation) { -// downloadEntity.setState(IEntity.STATE_RUNNING); -// sendInState2Target(ISchedulers.START); -// sendIntent(Aria.ACTION_START, startLocation); -// } -// -// @Override public void onResume(String url, long resumeLocation) { -// downloadEntity.setState(IEntity.STATE_RUNNING); -// sendInState2Target(ISchedulers.RESUME); -// sendIntent(Aria.ACTION_RESUME, resumeLocation); -// } -// -// @Override public void onProgress(String url, long currentLocation) { -// if (System.currentTimeMillis() - lastTime > INTERVAL_TIME) { -// long speed = currentLocation - lastLen; -// sendIntent.putExtra(Aria.CURRENT_LOCATION, currentLocation); -// sendIntent.putExtra(Aria.CURRENT_SPEED, speed); -// lastTime = System.currentTimeMillis(); -// if (isFirst) { -// speed = 0; -// isFirst = false; -// } -// handleSpeed(speed); -// downloadEntity.setCurrentProgress(currentLocation); -// lastLen = currentLocation; -// sendInState2Target(ISchedulers.RUNNING); -// context.sendBroadcast(sendIntent); -// } -// } -// -// @Override public void onStop(String url, long stopLocation) { -// downloadEntity.setState(task.isWait ? IEntity.STATE_WAIT : IEntity.STATE_STOP); -// handleSpeed(0); -// sendInState2Target(ISchedulers.STOP); -// sendIntent(Aria.ACTION_STOP, stopLocation); -// } -// -// @Override public void onCancel(String url) { -// downloadEntity.setState(IEntity.STATE_CANCEL); -// handleSpeed(0); -// sendInState2Target(ISchedulers.CANCEL); -// sendIntent(Aria.ACTION_CANCEL, -1); -// downloadEntity.deleteData(); -// } -// -// @Override public void onComplete(String url) { -// downloadEntity.setState(IEntity.STATE_COMPLETE); -// downloadEntity.setDownloadComplete(true); -// handleSpeed(0); -// sendInState2Target(ISchedulers.COMPLETE); -// sendIntent(Aria.ACTION_COMPLETE, downloadEntity.getFileSize()); -// } -// -// @Override public void onFail(String url) { -// downloadEntity.setFailNum(downloadEntity.getFailNum() + 1); -// downloadEntity.setState(IEntity.STATE_FAIL); -// handleSpeed(0); -// sendInState2Target(ISchedulers.FAIL); -// sendIntent(Aria.ACTION_FAIL, -1); -// } -// -// private void handleSpeed(long speed) { -// if (isConvertSpeed) { -// downloadEntity.setConvertSpeed(CommonUtil.formatFileSize(speed) + "/s"); -// } else { -// downloadEntity.setSpeed(speed); -// } -// } -// -// /** -// * 将任务状态发送给下载器 -// * -// * @param state {@link DownloadSchedulers#START} -// */ -// private void sendInState2Target(int state) { -// if (outHandler.get() != null) { -// outHandler.get().obtainMessage(state, task).sendToTarget(); -// } -// } -// -// private void saveData(String url, int state, long location) { -// DownloadEntity child = mEntityMap.get(url); -// if (child != null) { -// child.setState(state); -// child.setDownloadComplete(state == IEntity.STATE_COMPLETE); -// child.setCurrentProgress(location); -// child.update(); -// } -// } -// } -// -// public static class Builder { -// DownloadTaskEntity taskEntity; -// Handler outHandler; -// String targetName; -// -// public Builder(String targetName, DownloadTaskEntity taskEntity) { -// CheckUtil.checkTaskEntity(taskEntity); -// this.targetName = targetName; -// this.taskEntity = taskEntity; -// } -// -// /** -// * 设置自定义Handler处理下载状态时间 -// * -// * @param schedulers {@link ISchedulers} -// */ -// public DownloadGroupTask.Builder setOutHandler(ISchedulers schedulers) { -// this.outHandler = new Handler(schedulers); -// return this; -// } -// -// public DownloadGroupTask build() { -// DownloadGroupTask task = new DownloadGroupTask(taskEntity, outHandler); -// task.setTargetName(targetName); -// taskEntity.downloadEntity.save(); -// return task; -// } -// } -//} +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.download; + +import android.content.Context; +import android.os.Handler; +import com.arialyy.aria.core.AriaManager; +import com.arialyy.aria.core.download.downloader.DownloadGroupUtil; +import com.arialyy.aria.core.download.downloader.DownloadListener; +import com.arialyy.aria.core.download.downloader.IDownloadUtil; +import com.arialyy.aria.core.inf.AbsGroupTask; +import com.arialyy.aria.core.inf.IEntity; +import com.arialyy.aria.core.scheduler.DownloadSchedulers; +import com.arialyy.aria.core.scheduler.ISchedulers; +import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.CommonUtil; +import java.lang.ref.WeakReference; + +/** + * Created by AriaL on 2017/6/27. + * 任务组任务 + */ +public class DownloadGroupTask extends AbsGroupTask { + private DListener mListener; + private IDownloadUtil mUtil; + + private DownloadGroupTask(DownloadGroupTaskEntity taskEntity, Handler outHandler) { + mTaskEntity = taskEntity; + mEntity = taskEntity.getEntity(); + mOutHandler = outHandler; + mContext = AriaManager.APP; + mListener = new DListener(mContext, this, mOutHandler); + mUtil = new DownloadGroupUtil(mListener, mTaskEntity); + } + + @Override public boolean isRunning() { + return mUtil.isDownloading(); + } + + @Override public void start() { + mUtil.stopDownload(); + } + + @Override public void stop() { + mUtil.startDownload(); + } + + @Override public void cancel() { + mUtil.cancelDownload(); + } + + /** + * 下载监听类 + */ + private static class DListener extends DownloadListener { + WeakReference outHandler; + WeakReference wTask; + Context context; + long lastLen = 0; //上一次发送长度 + boolean isFirst = true; + DownloadGroupEntity entity; + DownloadGroupTask task; + boolean isConvertSpeed = false; + + DListener(Context context, DownloadGroupTask task, Handler outHandler) { + this.context = context; + this.outHandler = new WeakReference<>(outHandler); + this.wTask = new WeakReference<>(task); + this.task = wTask.get(); + this.entity = this.task.getEntity(); + final AriaManager manager = AriaManager.getInstance(context); + isConvertSpeed = manager.getDownloadConfig().isConvertSpeed(); + } + + @Override public void onPre() { + saveData(IEntity.STATE_PRE, -1); + sendInState2Target(ISchedulers.PRE); + } + + @Override public void onPostPre(long fileSize) { + entity.setFileSize(fileSize); + saveData(IEntity.STATE_POST_PRE, -1); + sendInState2Target(ISchedulers.POST_PRE); + } + + @Override public void onStart(long startLocation) { + saveData(IEntity.STATE_RUNNING, startLocation); + sendInState2Target(ISchedulers.START); + } + + @Override public void onResume(long resumeLocation) { + saveData(IEntity.STATE_RUNNING, resumeLocation); + sendInState2Target(ISchedulers.RESUME); + } + + @Override public void onProgress(long currentLocation) { + long speed = currentLocation - lastLen; + if (isFirst) { + speed = 0; + isFirst = false; + } + handleSpeed(speed); + lastLen = currentLocation; + sendInState2Target(ISchedulers.RUNNING); + } + + @Override public void onStop(long stopLocation) { + saveData(IEntity.STATE_STOP, stopLocation); + handleSpeed(0); + sendInState2Target(ISchedulers.STOP); + } + + @Override public void onCancel() { + saveData(IEntity.STATE_CANCEL, -1); + handleSpeed(0); + sendInState2Target(ISchedulers.CANCEL); + } + + @Override public void onComplete() { + saveData(IEntity.STATE_COMPLETE, entity.getFileSize()); + handleSpeed(0); + sendInState2Target(ISchedulers.COMPLETE); + } + + @Override public void onFail() { + entity.setFailNum(entity.getFailNum() + 1); + saveData(IEntity.STATE_FAIL, -1); + handleSpeed(0); + sendInState2Target(ISchedulers.FAIL); + } + + private void handleSpeed(long speed) { + if (isConvertSpeed) { + entity.setConvertSpeed(CommonUtil.formatFileSize(speed) + "/s"); + } else { + entity.setSpeed(speed); + } + } + + /** + * 将任务状态发送给下载器 + * + * @param state {@link DownloadSchedulers#START} + */ + private void sendInState2Target(int state) { + if (outHandler.get() != null) { + outHandler.get().obtainMessage(state, task).sendToTarget(); + } + } + + private void saveData(int state, long location) { + if (state == IEntity.STATE_CANCEL) { + entity.deleteData(); + } else { + entity.setState(state); + if (location != -1) { + entity.setCurrentProgress(location); + } + entity.update(); + } + } + } + + public static class Builder { + DownloadGroupTaskEntity taskEntity; + Handler outHandler; + String targetName; + + public Builder(String targetName, DownloadGroupTaskEntity taskEntity) { + CheckUtil.checkTaskEntity(taskEntity); + this.targetName = targetName; + this.taskEntity = taskEntity; + } + + /** + * 设置自定义Handler处理下载状态时间 + * + * @param schedulers {@link ISchedulers} + */ + public DownloadGroupTask.Builder setOutHandler(ISchedulers schedulers) { + this.outHandler = new Handler(schedulers); + return this; + } + + public DownloadGroupTask build() { + DownloadGroupTask task = new DownloadGroupTask(taskEntity, outHandler); + task.setTargetName(targetName); + taskEntity.save(); + return task; + } + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTask.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTask.java index 46d87b73..e70f6eb4 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTask.java @@ -46,11 +46,11 @@ public class DownloadTask extends AbsNormalTask { private boolean isWait = false; private DownloadTask(DownloadTaskEntity taskEntity, Handler outHandler) { - mEntity = taskEntity.downloadEntity; + mEntity = taskEntity.getEntity(); mOutHandler = outHandler; mContext = AriaManager.APP; mListener = new DListener(mContext, this, mOutHandler); - mUtil = new DownloadUtil(mContext, taskEntity, mListener); + mUtil = new DownloadUtil(taskEntity, mListener); } /** @@ -194,7 +194,7 @@ public class DownloadTask extends AbsNormalTask { public DownloadTask build() { DownloadTask task = new DownloadTask(taskEntity, outHandler); task.setTargetName(targetName); - taskEntity.downloadEntity.save(); + taskEntity.getEntity().save(); return task; } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/DownloadGroupUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/DownloadGroupUtil.java index 1b1f7300..01e3c6bb 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/DownloadGroupUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/DownloadGroupUtil.java @@ -68,14 +68,14 @@ public class DownloadGroupUtil implements IDownloadUtil { /** * 下载器映射表,key为下载地址 */ - private Map mDownloaderMap = new HashMap<>(); + private Map mDownloaderMap = new HashMap<>(); /** * 文件信息回调组 */ private SparseArray mFileInfoCallbacks = new SparseArray<>(); - DownloadGroupUtil(IDownloadListener listener, DownloadGroupTaskEntity taskEntity) { + public DownloadGroupUtil(IDownloadListener listener, DownloadGroupTaskEntity taskEntity) { mListener = listener; mTaskEntity = taskEntity; mInfoPool = Executors.newCachedThreadPool(); @@ -116,9 +116,9 @@ public class DownloadGroupUtil implements IDownloadUtil { Set keys = mDownloaderMap.keySet(); for (String key : keys) { - DownloadThreader db = mDownloaderMap.get(key); - if (db != null) { - db.cancelDownload(); + Downloader dt = mDownloaderMap.get(key); + if (dt != null) { + dt.cancelDownload(); } } } @@ -135,9 +135,9 @@ public class DownloadGroupUtil implements IDownloadUtil { Set keys = mDownloaderMap.keySet(); for (String key : keys) { - DownloadThreader db = mDownloaderMap.get(key); - if (db != null) { - db.stopDownload(); + Downloader dt = mDownloaderMap.get(key); + if (dt != null) { + dt.stopDownload(); } } } @@ -188,7 +188,7 @@ public class DownloadGroupUtil implements IDownloadUtil { } mFailNum++; failNum++; - if (failNum < 10){ + if (failNum < 10) { mInfoPool.execute(createFileInfoThread(te)); } if (mInitNum + mFailNum == mTaskEntity.getEntity().getChild().size()) { @@ -228,7 +228,7 @@ public class DownloadGroupUtil implements IDownloadUtil { */ private void startChildDownload(DownloadTaskEntity taskEntity) { ChildDownloadListener listener = new ChildDownloadListener(taskEntity); - DownloadThreader dt = new DownloadThreader(listener, taskEntity); + Downloader dt = new Downloader(listener, taskEntity); mDownloaderMap.put(taskEntity.getEntity().getDownloadUrl(), dt); mExePool.execute(dt); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/DownloadUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/DownloadUtil.java index d2b3b8fe..1555dc67 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/DownloadUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/DownloadUtil.java @@ -16,23 +16,8 @@ package com.arialyy.aria.core.download.downloader; -import android.content.Context; import android.util.Log; -import android.util.SparseArray; -import com.arialyy.aria.core.AriaManager; -import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadTaskEntity; -import com.arialyy.aria.orm.DbEntity; -import com.arialyy.aria.util.BufferedRandomAccessFile; -import com.arialyy.aria.util.CommonUtil; -import java.io.File; -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.Properties; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; /** * Created by lyy on 2015/8/25. @@ -40,170 +25,49 @@ import java.util.concurrent.Executors; */ public class DownloadUtil implements IDownloadUtil, Runnable { private static final String TAG = "DownloadUtil"; - /** - * 线程数 - */ - private int THREAD_NUM; - /** - * 小于1m的文件不启用多线程 - */ - private static final long SUB_LEN = 1024 * 1024; - //下载监听 private IDownloadListener mListener; - private int mConnectTimeOut = 0; //连接超时时间 - private boolean isNewTask = true; - private boolean isSupportBreakpoint = true; - private Context mContext; - private DownloadEntity mDownloadEntity; + private Downloader mDT; private DownloadTaskEntity mTaskEntity; - private ExecutorService mFixedThreadPool; - private File mDownloadFile; //下载的文件 - private File mConfigFile;//下载信息配置文件 - private SparseArray mTask = new SparseArray<>(); - private DownloadStateConstance CONSTANCE; - DownloadUtil(Context context, DownloadTaskEntity entity, IDownloadListener downloadListener) { - mDownloadEntity = entity.getEntity(); - mContext = context.getApplicationContext(); + public DownloadUtil(DownloadTaskEntity entity, IDownloadListener downloadListener) { mTaskEntity = entity; mListener = downloadListener; - // 线程下载数改变后,新的下载才会生效 - //mFixedThreadPool = Executors.newFixedThreadPool(Integer.MAX_VALUE); - CONSTANCE = new DownloadStateConstance(); - init(); - } - - private void init() { - mConnectTimeOut = AriaManager.getInstance(mContext).getDownloadConfig().getConnectTimeOut(); - mDownloadFile = new File(mTaskEntity.getEntity().getDownloadPath()); - //读取已完成的线程数 - mConfigFile = new File(mContext.getFilesDir().getPath() - + AriaManager.DOWNLOAD_TEMP_DIR - + mDownloadFile.getName() - + ".properties"); - checkTask(); - } - - /** - * 检查任务是否是新任务,新任务条件: - * 1、文件不存在 - * 2、下载记录文件不存在 - * 3、下载记录文件缺失或不匹配 - * 4、数据库记录不存在 - */ - private void checkTask() { - try { - if (!mConfigFile.exists()) { //记录文件被删除,则重新下载 - isNewTask = true; - CommonUtil.createFile(mConfigFile.getPath()); - } else if (!mDownloadFile.exists()) { - isNewTask = true; - } else if (DbEntity.findData(DownloadEntity.class, "downloadUrl=?", - mDownloadEntity.getDownloadUrl()) == null) { - isNewTask = true; - } else { - isNewTask = !mDownloadFile.exists(); - } - } catch (Exception e) { - e.printStackTrace(); - failDownload("下载失败,记录文件被删除"); - } - } - - public IDownloadListener getListener() { - return mListener; + mDT = new Downloader(downloadListener, entity); } @Override public long getFileSize() { - return mDownloadEntity.getFileSize(); + return mDT.getFileSize(); } /** * 获取当前下载位置 */ @Override public long getCurrentLocation() { - return CONSTANCE.CURRENT_LOCATION; + return mDT.getCurrentLocation(); } @Override public boolean isDownloading() { - return CONSTANCE.isDownloading; - } - - public void setMaxSpeed(double maxSpeed) { - for (int i = 0; i < THREAD_NUM; i++) { - SingleThreadTask task = (SingleThreadTask) mTask.get(i); - if (task != null) { - task.setMaxSpeed(maxSpeed); - } - } + return mDT.isDownloading(); } /** * 取消下载 */ @Override public void cancelDownload() { - CONSTANCE.isCancel = true; - CONSTANCE.isDownloading = false; - if (mFixedThreadPool != null) { - mFixedThreadPool.shutdown(); - } - for (int i = 0; i < THREAD_NUM; i++) { - SingleThreadTask task = (SingleThreadTask) mTask.get(i); - if (task != null) { - task.cancel(); - } - } - CommonUtil.delDownloadTaskConfig(mTaskEntity.removeFile, mDownloadEntity); + mDT.cancelDownload(); } /** * 停止下载 */ @Override public void stopDownload() { - CONSTANCE.isStop = true; - CONSTANCE.isDownloading = false; - if (mFixedThreadPool != null) { - mFixedThreadPool.shutdown(); - } - for (int i = 0; i < THREAD_NUM; i++) { - SingleThreadTask task = (SingleThreadTask) mTask.get(i); - if (task != null) { - task.stop(); - } - } - } - - /** - * 删除下载记录文件 - */ - public void delConfigFile() { - if (mContext != null && mDownloadEntity != null) { - File dFile = new File(mDownloadEntity.getDownloadPath()); - File config = - new File(mContext.getFilesDir().getPath() + "/temp/" + dFile.getName() + ".properties"); - if (config.exists()) { - config.delete(); - } - } - } - - /** - * 删除temp文件 - */ - public void delTempFile() { - if (mContext != null && mDownloadEntity != null) { - File dFile = new File(mDownloadEntity.getDownloadPath()); - if (dFile.exists()) { - dFile.delete(); - } - } + mDT.stopDownload(); } /** * 多线程断点续传下载文件,开始下载 */ @Override public void startDownload() { - CONSTANCE.cleanState(); mListener.onPre(); new Thread(this).start(); } @@ -212,295 +76,24 @@ public class DownloadUtil implements IDownloadUtil, Runnable { startDownload(); } + public void setMaxSpeed(double maxSpeed) { + mDT.setMaxSpeed(maxSpeed); + } + private void failDownload(String msg) { Log.e(TAG, msg); - CONSTANCE.isDownloading = false; mListener.onFail(); } @Override public void run() { - HttpURLConnection conn = null; - try { - URL url = new URL(mDownloadEntity.getDownloadUrl()); - conn = ConnectionHelp.handleConnection(url); - conn = ConnectionHelp.setConnectParam(mTaskEntity, conn); - conn.setRequestProperty("Range", "bytes=" + 0 + "-"); - conn.setConnectTimeout(mConnectTimeOut); - conn.connect(); - handleConnect(conn); - } catch (IOException e) { - failDownload("下载失败【downloadUrl:" - + mDownloadEntity.getDownloadUrl() - + "】\n【filePath:" - + mDownloadFile.getPath() - + "】\n" - + CommonUtil.getPrintException(e)); - } finally { - if (conn != null) { - conn.disconnect(); - } - } - } - - /** - * 处理状态码 - */ - private void handleConnect(HttpURLConnection conn) throws IOException { - int len = conn.getContentLength(); - //if (len < 0) { //网络被劫持时会出现这个问题 - // failDownload("下载失败,网络被劫持"); - // return; - //} - int code = conn.getResponseCode(); - //https://zh.wikipedia.org/wiki/HTTP%E7%8A%B6%E6%80%81%E7%A0%81 - //206支持断点 - if (code == HttpURLConnection.HTTP_PARTIAL) { - if (!checkLen(len)) return; - isSupportBreakpoint = true; - mListener.supportBreakpoint(true); - handleBreakpoint(conn); - } else if (code == HttpURLConnection.HTTP_OK) { - //在conn.setRequestProperty("Range", "bytes=" + 0 + "-");下,200为不支持断点状态 - if (!checkLen(len)) return; - isSupportBreakpoint = false; - mListener.supportBreakpoint(false); - Log.w(TAG, "该下载链接不支持断点下载"); - handleBreakpoint(conn); - } else if (code == HttpURLConnection.HTTP_NOT_FOUND) { - Log.w(TAG, "任务【" + mDownloadEntity.getDownloadUrl() + "】下载失败,错误码:404"); - mListener.onCancel(); - } else if (code == HttpURLConnection.HTTP_MOVED_TEMP - || code == HttpURLConnection.HTTP_MOVED_PERM - || code == HttpURLConnection.HTTP_SEE_OTHER) { - handle302Turn(conn); - } else { - failDownload("任务【" + mDownloadEntity.getDownloadUrl() + "】下载失败,错误码:" + code); - } - } - - /** - * 检查长度是否合法 - * - * @param len 从服务器获取的文件长度 - * @return true, 合法 - */ - private boolean checkLen(long len) { - if (len < 0) { - failDownload("任务【" + mDownloadEntity.getDownloadUrl() + "】下载失败,文件长度小于0"); - return false; - } - return true; - } - - /** - * 处理30x跳转 - */ - private void handle302Turn(HttpURLConnection conn) throws IOException { - String newUrl = conn.getHeaderField(mTaskEntity.redirectUrlKey); - Log.d(TAG, "30x跳转,新url为【" + newUrl + "】"); - mDownloadEntity.setRedirect(true); - mDownloadEntity.setRedirectUrl(newUrl); - mDownloadEntity.update(); - String cookies = conn.getHeaderField("Set-Cookie"); - conn = (HttpURLConnection) new URL(newUrl).openConnection(); - conn = ConnectionHelp.setConnectParam(mTaskEntity, conn); - conn.setRequestProperty("Cookie", cookies); - conn.setRequestProperty("Range", "bytes=" + 0 + "-"); - conn.setConnectTimeout(mConnectTimeOut); - conn.connect(); - handleConnect(conn); - } - - /** - * 处理断点 - */ - private void handleBreakpoint(HttpURLConnection conn) throws IOException { - //不支持断点只能单线程下载 - if (!isSupportBreakpoint) { - handleNoSupportBreakpointDownload(conn); - return; - } - int fileLength = conn.getContentLength(); - Properties pro = createConfigFile(fileLength); - int blockSize = fileLength / THREAD_NUM; - int[] recordL = new int[THREAD_NUM]; - int rl = 0; - for (int i = 0; i < THREAD_NUM; i++) { - recordL[i] = -1; - } - for (int i = 0; i < THREAD_NUM; i++) { - long startL = i * blockSize, endL = (i + 1) * blockSize; - Object state = pro.getProperty(mDownloadFile.getName() + "_state_" + i); - if (state != null && Integer.parseInt(state + "") == 1) { //该线程已经完成 - if (resumeRecordLocation(i, startL, endL)) return; - continue; - } - //分配下载位置 - Object record = pro.getProperty(mDownloadFile.getName() + "_record_" + i); - //如果有记录,则恢复下载 - if (!isNewTask && record != null && Long.parseLong(record + "") >= 0) { - Long r = Long.parseLong(record + ""); - CONSTANCE.CURRENT_LOCATION += r - startL; - Log.d(TAG, "任务【" + mDownloadEntity.getFileName() + "】线程__" + i + "__恢复下载"); - mListener.onChildResume(r); - startL = r; - recordL[rl] = i; - rl++; - } else { - //handleNewTask(fileLength); - isNewTask = true; - } - if (isNewTask) { - recordL[rl] = i; - rl++; - } - if (i == (THREAD_NUM - 1)) { - //最后一个线程的结束位置即为文件的总长度 - endL = fileLength; - } - addSingleTask(i, startL, endL, fileLength); - } - startSingleTask(recordL); - } - - /** - * 处理不支持断点的下载 - */ - private void handleNoSupportBreakpointDownload(HttpURLConnection conn) { - ChildThreadConfigEntity entity = new ChildThreadConfigEntity(); - long len = conn.getContentLength(); - entity.FILE_SIZE = len; - entity.DOWNLOAD_URL = mDownloadEntity.isRedirect() ? mDownloadEntity.getRedirectUrl() - : mDownloadEntity.getDownloadUrl(); - entity.TEMP_FILE = mDownloadFile; - entity.THREAD_ID = 0; - entity.START_LOCATION = 0; - entity.END_LOCATION = entity.FILE_SIZE; - entity.CONFIG_FILE_PATH = mConfigFile.getPath(); - entity.IS_SUPPORT_BREAK_POINT = isSupportBreakpoint; - entity.DOWNLOAD_TASK_ENTITY = mTaskEntity; - THREAD_NUM = 1; - CONSTANCE.THREAD_NUM = THREAD_NUM; - SingleThreadTask task = new SingleThreadTask(CONSTANCE, mListener, entity); - mTask.put(0, task); - mFixedThreadPool.execute(task); - mListener.onPostPre(len); - mListener.onStart(0); - } - - /** - * 创建配置文件 - */ - private Properties createConfigFile(long fileLength) throws IOException { - Properties pro = null; - //必须建一个文件 - CommonUtil.createFile(mDownloadFile.getPath()); - BufferedRandomAccessFile file = - new BufferedRandomAccessFile(new File(mDownloadFile.getPath()), "rwd", 8192); - //设置文件长度 - file.setLength(fileLength); - file.close(); - mListener.onPostPre(fileLength); - //分配每条线程的下载区间 - pro = CommonUtil.loadConfig(mConfigFile); - if (pro.isEmpty()) { - handleNewTask(fileLength); - } else { - Set keys = pro.keySet(); - int num = 0; - for (Object key : keys) { - if (String.valueOf(key).contains("_record_")) { - num++; - } - } - if (num == 0) { - handleNewTask(fileLength); - return pro; - } - THREAD_NUM = num; - for (int i = 0; i < THREAD_NUM; i++) { - if (pro.getProperty(mDownloadFile.getName() + "_record_" + i) == null) { - Object state = pro.getProperty(mDownloadFile.getName() + "_state_" + i); - if (state != null && Integer.parseInt(state + "") == 1) { - continue; - } - handleNewTask(fileLength); - return pro; - } - } - isNewTask = false; - } - return pro; - } - - /** - * 处理新任务 - */ - private void handleNewTask(long fileLength) { - isNewTask = true; - THREAD_NUM = fileLength < SUB_LEN ? 1 - : AriaManager.getInstance(mContext).getDownloadConfig().getThreadNum(); - } - - /** - * 恢复记录地址 - * - * @return true 表示下载完成 - */ - private boolean resumeRecordLocation(int i, long startL, long endL) { - CONSTANCE.CURRENT_LOCATION += endL - startL; - Log.d(TAG, "++++++++++ 线程_" + i + "_已经下载完成 ++++++++++"); - CONSTANCE.COMPLETE_THREAD_NUM++; - CONSTANCE.STOP_NUM++; - CONSTANCE.CANCEL_NUM++; - if (CONSTANCE.isComplete()) { - if (mConfigFile.exists()) { - mConfigFile.delete(); + new Thread(new FileInfoThread(mTaskEntity, new FileInfoThread.OnFileInfoCallback() { + @Override public void onComplete(String url, int code) { + mDT.startDownload(); } - mListener.onComplete(); - CONSTANCE.isDownloading = false; - return true; - } - return false; - } - - /** - * 创建单线程任务 - */ - private void addSingleTask(int i, long startL, long endL, long fileLength) { - ChildThreadConfigEntity entity = new ChildThreadConfigEntity(); - entity.FILE_SIZE = fileLength; - entity.DOWNLOAD_URL = mDownloadEntity.isRedirect() ? mDownloadEntity.getRedirectUrl() - : mDownloadEntity.getDownloadUrl(); - entity.TEMP_FILE = mDownloadFile; - entity.THREAD_ID = i; - entity.START_LOCATION = startL; - entity.END_LOCATION = endL; - entity.CONFIG_FILE_PATH = mConfigFile.getPath(); - entity.IS_SUPPORT_BREAK_POINT = isSupportBreakpoint; - entity.DOWNLOAD_TASK_ENTITY = mTaskEntity; - CONSTANCE.THREAD_NUM = THREAD_NUM; - SingleThreadTask task = new SingleThreadTask(CONSTANCE, mListener, entity); - mTask.put(i, task); - } - /** - * 启动单线程下载任务 - */ - private void startSingleTask(int[] recordL) { - if (CONSTANCE.CURRENT_LOCATION > 0) { - mListener.onResume(CONSTANCE.CURRENT_LOCATION); - } else { - mListener.onStart(CONSTANCE.CURRENT_LOCATION); - } - mFixedThreadPool = Executors.newFixedThreadPool(recordL.length); - for (int l : recordL) { - if (l == -1) continue; - Runnable task = mTask.get(l); - if (task != null) { - mFixedThreadPool.execute(task); + @Override public void onFail(String url, String errorMsg) { + failDownload(errorMsg); } - } + })).start(); } - } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/DownloadThreader.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/Downloader.java similarity index 92% rename from Aria/src/main/java/com/arialyy/aria/core/download/downloader/DownloadThreader.java rename to Aria/src/main/java/com/arialyy/aria/core/download/downloader/Downloader.java index ca70cc7c..dd2f2e40 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/DownloadThreader.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/Downloader.java @@ -33,9 +33,10 @@ import java.util.concurrent.Executors; /** * Created by AriaL on 2017/7/1. + * 文件下载器 */ -class DownloadThreader implements Runnable, IDownloadUtil { - private final String TAG = "DownloadThreader"; +class Downloader implements Runnable, IDownloadUtil { + private final String TAG = "Downloader"; private IDownloadListener mListener; private DownloadTaskEntity mTaskEntity; private DownloadEntity mEntity; @@ -45,15 +46,33 @@ class DownloadThreader implements Runnable, IDownloadUtil { private File mTempFile; //下载的文件 private boolean isNewTask = true; private int mThreadNum, mRealThreadNum; - private DownloadStateConstance mConstance; + private StateConstance mConstance; private SparseArray mTask = new SparseArray<>(); - DownloadThreader(IDownloadListener listener, DownloadTaskEntity taskEntity) { + /** + * 小于1m的文件不启用多线程 + */ + private static final long SUB_LEN = 1024 * 1024; + + Downloader(IDownloadListener listener, DownloadTaskEntity taskEntity) { mListener = listener; mTaskEntity = taskEntity; mEntity = mTaskEntity.getEntity(); mContext = AriaManager.APP; - mConstance = new DownloadStateConstance(); + mConstance = new StateConstance(); + } + + void setMaxSpeed(double maxSpeed) { + for (int i = 0; i < mThreadNum; i++) { + SingleThreadTask task = (SingleThreadTask) mTask.get(i); + if (task != null) { + task.setMaxSpeed(maxSpeed); + } + } + } + + public StateConstance getConstance() { + return mConstance; } @Override public void run() { @@ -106,15 +125,16 @@ class DownloadThreader implements Runnable, IDownloadUtil { } @Override public void startDownload() { + mConstance.cleanState(); mConstance.isDownloading = true; try { if (!mTaskEntity.isSupportBP) { mThreadNum = 1; handleNoSupportBreakpointDownload(); } else { - mThreadNum = - isNewTask ? AriaManager.getInstance(mContext).getDownloadConfig().getThreadNum() - : mRealThreadNum; + mThreadNum = isNewTask ? (mEntity.getFileSize() <= SUB_LEN ? 1 + : AriaManager.getInstance(mContext).getDownloadConfig().getThreadNum()) + : mRealThreadNum; mFixedThreadPool = Executors.newFixedThreadPool(mThreadNum); handleBreakpoint(); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/IDownloadListener.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/IDownloadListener.java index d9c06376..7b77cd59 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/IDownloadListener.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/IDownloadListener.java @@ -19,7 +19,7 @@ package com.arialyy.aria.core.download.downloader; /** * 下载监听 */ -interface IDownloadListener { +public interface IDownloadListener { /** * 支持断点回调 diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/IDownloadUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/IDownloadUtil.java index f0265cf3..bcfe8a5a 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/IDownloadUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/IDownloadUtil.java @@ -20,7 +20,7 @@ package com.arialyy.aria.core.download.downloader; * Created by lyy on 2016/10/31. * 抽象的下载接口 */ -interface IDownloadUtil { +public interface IDownloadUtil { /** * 获取文件大小 diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/SingleThreadTask.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/SingleThreadTask.java index 245d32e6..278f4873 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/SingleThreadTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/SingleThreadTask.java @@ -41,10 +41,10 @@ final class SingleThreadTask implements Runnable { private long mChildCurrentLocation = 0; private int mBufSize; private IDownloadListener mListener; - private DownloadStateConstance CONSTANCE; + private StateConstance CONSTANCE; private long mSleepTime = 0; - SingleThreadTask(DownloadStateConstance constance, IDownloadListener listener, + SingleThreadTask(StateConstance constance, IDownloadListener listener, ChildThreadConfigEntity downloadInfo) { AriaManager manager = AriaManager.getInstance(AriaManager.APP); CONSTANCE = constance; diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/DownloadStateConstance.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/StateConstance.java similarity index 96% rename from Aria/src/main/java/com/arialyy/aria/core/download/downloader/DownloadStateConstance.java rename to Aria/src/main/java/com/arialyy/aria/core/download/downloader/StateConstance.java index 7d145a1a..fa082bd9 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/DownloadStateConstance.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/StateConstance.java @@ -19,7 +19,7 @@ package com.arialyy.aria.core.download.downloader; * Created by lyy on 2017/1/18. * 下载状态常量 */ -final class DownloadStateConstance { +final class StateConstance { int CANCEL_NUM = 0; int STOP_NUM = 0; int FAIL_NUM = 0; @@ -32,7 +32,7 @@ final class DownloadStateConstance { boolean isCancel = false; boolean isStop = false; - DownloadStateConstance() { + StateConstance() { } void cleanState() { diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsEntity.java b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsEntity.java index 63806454..d69d1b43 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsEntity.java +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsEntity.java @@ -32,6 +32,10 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable * 单位转换后的速度 */ @Ignore private String convertSpeed = "0b/s"; + /** + * 下载失败计数,每次开始都重置为0 + */ + @Ignore private int failNum = 0; /** * 扩展字段 @@ -51,6 +55,14 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable */ private long completeTime; + public int getFailNum() { + return failNum; + } + + public void setFailNum(int failNum) { + this.failNum = failNum; + } + public long getSpeed() { return speed; } @@ -117,6 +129,7 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable @Override public void writeToParcel(Parcel dest, int flags) { dest.writeLong(this.speed); dest.writeString(this.convertSpeed); + dest.writeInt(this.failNum); dest.writeString(this.str); dest.writeLong(this.fileSize); dest.writeInt(this.state); @@ -127,6 +140,7 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable protected AbsEntity(Parcel in) { this.speed = in.readLong(); this.convertSpeed = in.readString(); + this.failNum = in.readInt(); this.str = in.readString(); this.fileSize = in.readLong(); this.state = in.readInt(); diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsGroupTask.java b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsGroupTask.java index b7eb3a93..83bc8993 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsGroupTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsGroupTask.java @@ -15,7 +15,6 @@ */ package com.arialyy.aria.core.inf; -import com.arialyy.aria.util.CommonUtil; /** * Created by AriaL on 2017/6/29. @@ -25,47 +24,8 @@ public abstract class AbsGroupTask extends AbsTask implements ITask private String mTargetName; protected Context mContext; + /** + * 获取当前下载进度 + */ + @Override public long getCurrentProgress() { + return mEntity.getCurrentProgress(); + } + + /** + * 获取单位转换后的进度 + * + * @return 如:已经下载3mb的大小,则返回{@code 3mb} + */ + @Override public String getConvertCurrentProgress() { + if (mEntity.getCurrentProgress() == 0) { + return "0b"; + } + return CommonUtil.formatFileSize(mEntity.getCurrentProgress()); + } + + /** + * 转换单位后的文件长度 + * + * @return 如果文件长度为0,则返回0m,否则返回转换后的长度1b、1kb、1mb、1gb、1tb + */ + @Override public String getConvertFileSize() { + if (mEntity.getFileSize() == 0) { + return "0mb"; + } + return CommonUtil.formatFileSize(mEntity.getFileSize()); + } + + /** + * 获取文件大小 + */ + @Override public long getFileSize() { + return mEntity.getFileSize(); + } + + /** + * 获取百分比进度 + * + * @return 返回百分比进度,如果文件长度为0,返回0 + */ + @Override public int getPercent() { + if (mEntity.getFileSize() == 0) { + return 0; + } + return (int) (mEntity.getCurrentProgress() * 100 / mEntity.getFileSize()); + } + /** * 任务当前状态 * @@ -96,13 +147,6 @@ public abstract class AbsTask implements ITask return mEntity; } - /** - * 删除任务记录,删除后,再次启动该任务的下载时,将重新下载 - */ - @Override public void removeRecord() { - mEntity.deleteData(); - } - public String getTargetName() { return mTargetName; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/ITask.java b/Aria/src/main/java/com/arialyy/aria/core/inf/ITask.java index b5caee25..70bee951 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/inf/ITask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/ITask.java @@ -92,5 +92,4 @@ public interface ITask { public void setTargetName(String targetName); - public void removeRecord(); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java b/Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java index fa307650..2edafc91 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java +++ b/Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java @@ -18,22 +18,25 @@ package com.arialyy.aria.core.queue; import android.util.Log; import com.arialyy.aria.core.AriaManager; -import com.arialyy.aria.core.inf.AbsNormalEntity; -import com.arialyy.aria.core.inf.AbsNormalTask; +import com.arialyy.aria.core.download.DownloadEntity; +import com.arialyy.aria.core.download.DownloadTask; +import com.arialyy.aria.core.inf.AbsEntity; +import com.arialyy.aria.core.inf.AbsTask; import com.arialyy.aria.core.inf.AbsTaskEntity; -import com.arialyy.aria.core.queue.pool.NormalCachePool; -import com.arialyy.aria.core.queue.pool.NormalExecutePool; +import com.arialyy.aria.core.inf.IEntity; +import com.arialyy.aria.core.queue.pool.BaseCachePool; +import com.arialyy.aria.core.queue.pool.BaseExecutePool; import java.util.Set; /** * Created by lyy on 2017/2/23. * 任务队列 */ -abstract class AbsTaskQueue +abstract class AbsTaskQueue implements ITaskQueue { private final String TAG = "AbsTaskQueue"; - NormalCachePool mCachePool = new NormalCachePool<>(); - NormalExecutePool mExecutePool; + BaseCachePool mCachePool = new BaseCachePool<>(); + BaseExecutePool mExecutePool; @Override public boolean taskIsRunning(String key) { return mExecutePool.getTask(key) != null; @@ -70,17 +73,27 @@ abstract class AbsTaskQueue= oldMaxSize) { + for (int i = 0, len = Math.abs(diff); i < len; i++) { + TASK eTask = mExecutePool.pollTask(); + if (eTask != null) { + stopTask(eTask); + } + } + } + mExecutePool.setMaxNum(downloadNum); + if (diff >= 1) { + for (int i = 0; i < diff; i++) { + TASK nextTask = getNextTask(); + if (nextTask != null && nextTask.getState() == IEntity.STATE_WAIT) { + startTask(nextTask); + } + } + } } @Override public TASK getTask(String url) { @@ -124,7 +160,6 @@ abstract class AbsTaskQueue { + private static volatile DownloadGroupTaskQueue INSTANCE = null; + + private final String TAG = "DownloadGroupTaskQueue"; + + public static DownloadGroupTaskQueue getInstance() { + if (INSTANCE == null) { + synchronized (AriaManager.LOCK) { + INSTANCE = new DownloadGroupTaskQueue(); + } + } + return INSTANCE; + } + + private DownloadGroupTaskQueue() { + mExecutePool = new BaseExecutePool<>(true); + } + + @Override public DownloadGroupTask createTask(String targetName, DownloadGroupTaskEntity entity) { + DownloadGroupTask task = null; + if (!TextUtils.isEmpty(targetName)) { + task = (DownloadGroupTask) TaskFactory.getInstance() + .createTask(targetName, entity, DownloadGroupSchedulers.getInstance()); + mCachePool.putTask(task); + } else { + Log.e(TAG, "target name 为 null!!"); + } + return task; + } + + @Override public String getKey(DownloadGroupEntity entity) { + return entity.getGroupName(); + } + + @Override public int getConfigMaxNum() { + return AriaManager.getInstance(AriaManager.APP).getDownloadConfig().oldMaxTaskNum; + } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/DownloadTaskQueue.java b/Aria/src/main/java/com/arialyy/aria/core/queue/DownloadTaskQueue.java index f0e9d6f4..169a9839 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/queue/DownloadTaskQueue.java +++ b/Aria/src/main/java/com/arialyy/aria/core/queue/DownloadTaskQueue.java @@ -22,8 +22,7 @@ import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadTask; import com.arialyy.aria.core.download.DownloadTaskEntity; -import com.arialyy.aria.core.inf.IEntity; -import com.arialyy.aria.core.queue.pool.NormalExecutePool; +import com.arialyy.aria.core.queue.pool.DownloadExecutePool; import com.arialyy.aria.core.scheduler.DownloadSchedulers; import java.util.LinkedHashSet; import java.util.Map; @@ -48,10 +47,21 @@ public class DownloadTaskQueue } private DownloadTaskQueue() { - mExecutePool = new NormalExecutePool<>(true); + mExecutePool = new DownloadExecutePool(true); } - @Override public void setTaskHighestPriority(DownloadTask task) { + @Override public String getKey(DownloadEntity entity) { + return entity.getDownloadUrl(); + } + + @Override public int getConfigMaxNum() { + return AriaManager.getInstance(AriaManager.APP).getDownloadConfig().oldMaxTaskNum; + } + + /** + * 设置任务为最高优先级任务 + */ + public void setTaskHighestPriority(DownloadTask task) { task.setHighestPriority(true); Map exeTasks = mExecutePool.getAllTask(); if (exeTasks != null && !exeTasks.isEmpty()) { @@ -103,33 +113,6 @@ public class DownloadTaskQueue } } - @Override public void setMaxTaskNum(int downloadNum) { - int oldMaxSize = AriaManager.getInstance(AriaManager.APP).getDownloadConfig().oldMaxTaskNum; - int diff = downloadNum - oldMaxSize; - if (oldMaxSize == downloadNum) { - Log.d(TAG, "设置的下载任务数和配置文件的下载任务数一直,跳过"); - return; - } - //设置的任务数小于配置任务数 - if (diff <= -1 && mExecutePool.size() >= oldMaxSize) { - for (int i = 0, len = Math.abs(diff); i < len; i++) { - DownloadTask eTask = mExecutePool.pollTask(); - if (eTask != null) { - stopTask(eTask); - } - } - } - mExecutePool.setMaxNum(downloadNum); - if (diff >= 1) { - for (int i = 0; i < diff; i++) { - DownloadTask nextTask = getNextTask(); - if (nextTask != null && nextTask.getDownloadEntity().getState() == IEntity.STATE_WAIT) { - startTask(nextTask); - } - } - } - } - @Override public DownloadTask createTask(String target, DownloadTaskEntity entity) { DownloadTask task = null; if (!TextUtils.isEmpty(target)) { @@ -137,23 +120,13 @@ public class DownloadTaskQueue .createTask(target, entity, DownloadSchedulers.getInstance()); mCachePool.putTask(task); } else { - Log.e(TAG, "target name 为 null是!!"); + Log.e(TAG, "target name 为 null!!"); } return task; } - @Override public DownloadTask getTask(DownloadEntity entity) { - return getTask(entity.getDownloadUrl()); - } - - @Override public void removeTask(DownloadEntity entity) { - DownloadTask task = mExecutePool.getTask(entity.getDownloadUrl()); - if (task != null) { - Log.d(TAG, "从执行池删除任务,删除" + (mExecutePool.removeTask(task) ? "成功" : "失败")); - } - task = mCachePool.getTask(entity.getDownloadUrl()); - if (task != null) { - Log.d(TAG, "从缓存池删除任务,删除" + (mCachePool.removeTask(task) ? "成功" : "失败")); - } + @Override public void stopTask(DownloadTask task) { + task.setHighestPriority(false); + super.stopTask(task); } } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/ITaskQueue.java b/Aria/src/main/java/com/arialyy/aria/core/queue/ITaskQueue.java index 4ce69d80..01453ae0 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/queue/ITaskQueue.java +++ b/Aria/src/main/java/com/arialyy/aria/core/queue/ITaskQueue.java @@ -19,7 +19,9 @@ package com.arialyy.aria.core.queue; import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadTaskEntity; import com.arialyy.aria.core.download.DownloadTask; +import com.arialyy.aria.core.inf.AbsEntity; import com.arialyy.aria.core.inf.AbsNormalTask; +import com.arialyy.aria.core.inf.AbsTask; import com.arialyy.aria.core.inf.IEntity; import com.arialyy.aria.core.inf.AbsTaskEntity; import com.arialyy.aria.core.upload.UploadEntity; @@ -30,7 +32,7 @@ import com.arialyy.aria.core.upload.UploadTaskEntity; * Created by lyy on 2016/8/16. * 任务功能接口 */ -public interface ITaskQueue { +public interface ITaskQueue { /** * 通过key判断任务是否正在执行 @@ -50,13 +52,6 @@ public interface ITaskQueue {@link DownloadTaskEntity}、{@link UploadTaskEntity} - * @param {@link DownloadSchedulers} - * @return {@link DownloadTask}、{@link UploadTask} + * @param {@link DownloadTaskEntity}、{@link UploadTaskEntity}、{@link + * DownloadGroupTaskEntity} + * @param {@link DownloadSchedulers}、{@link UploadSchedulers} + * @return {@link DownloadTask}、{@link UploadTask}、{@link DownloadGroupTask} */ - ITask createTask(String targetName, - ENTITY entity, SCHEDULER schedulers) { + ITask createTask( + String targetName, TASK_ENTITY entity, SCHEDULER schedulers) { if (entity instanceof DownloadTaskEntity) { return createDownloadTask(targetName, (DownloadTaskEntity) entity, schedulers); } else if (entity instanceof UploadTaskEntity) { return createUploadTask(targetName, (UploadTaskEntity) entity, schedulers); + } else if (entity instanceof DownloadGroupTaskEntity) { + return createDownloadGroupTask(targetName, (DownloadGroupTaskEntity) entity, schedulers); } return null; } + /** + * 创建下载任务主任务 + * + * @param entity 下载任务实体{@link DownloadGroupTask} + * @param schedulers {@link ISchedulers} + */ + private DownloadGroupTask createDownloadGroupTask(String targetName, + DownloadGroupTaskEntity entity, ISchedulers schedulers) { + DownloadGroupTask.Builder builder = new DownloadGroupTask.Builder(targetName, entity); + builder.setOutHandler(schedulers); + return builder.build(); + } + /** * @param entity 上传任务实体{@link UploadTaskEntity} * @param schedulers {@link ISchedulers} diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/UploadTaskQueue.java b/Aria/src/main/java/com/arialyy/aria/core/queue/UploadTaskQueue.java index 3e0eb262..0d36f105 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/queue/UploadTaskQueue.java +++ b/Aria/src/main/java/com/arialyy/aria/core/queue/UploadTaskQueue.java @@ -19,7 +19,7 @@ package com.arialyy.aria.core.queue; import android.text.TextUtils; import android.util.Log; import com.arialyy.aria.core.AriaManager; -import com.arialyy.aria.core.queue.pool.NormalExecutePool; +import com.arialyy.aria.core.queue.pool.BaseExecutePool; import com.arialyy.aria.core.scheduler.UploadSchedulers; import com.arialyy.aria.core.upload.UploadEntity; import com.arialyy.aria.core.upload.UploadTask; @@ -43,13 +43,18 @@ public class UploadTaskQueue extends AbsTaskQueue(false); + mExecutePool = new BaseExecutePool<>(false); } - @Override public void setMaxTaskNum(int newMaxNum) { + @Override public String getKey(UploadEntity entity) { + return entity.getFilePath(); + } + @Override public int getConfigMaxNum() { + return AriaManager.getInstance(AriaManager.APP).getUploadConfig().oldMaxTaskNum; } + @Override public UploadTask createTask(String targetName, UploadTaskEntity entity) { UploadTask task = null; if (!TextUtils.isEmpty(targetName)) { @@ -61,19 +66,4 @@ public class UploadTaskQueue extends AbsTaskQueue implements IPool { - private static final String TAG = "NormalCachePool"; +public class BaseCachePool implements IPool { + private static final String TAG = "BaseCachePool"; private static final int MAX_NUM = Integer.MAX_VALUE; //最大下载任务数 private static final long TIME_OUT = 1000; private Map mCacheMap; private LinkedBlockingQueue mCacheQueue; - public NormalCachePool() { + public BaseCachePool() { mCacheQueue = new LinkedBlockingQueue<>(MAX_NUM); mCacheMap = new HashMap<>(); } @@ -95,7 +95,7 @@ public class NormalCachePool implements IPool { @Override public TASK pollTask() { synchronized (AriaManager.LOCK) { try { - TASK task = null; + TASK task; task = mCacheQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS); if (task != null) { String url = task.getKey(); diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/pool/NormalExecutePool.java b/Aria/src/main/java/com/arialyy/aria/core/queue/pool/BaseExecutePool.java similarity index 87% rename from Aria/src/main/java/com/arialyy/aria/core/queue/pool/NormalExecutePool.java rename to Aria/src/main/java/com/arialyy/aria/core/queue/pool/BaseExecutePool.java index 756d40cf..edcb67a4 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/queue/pool/NormalExecutePool.java +++ b/Aria/src/main/java/com/arialyy/aria/core/queue/pool/BaseExecutePool.java @@ -23,7 +23,6 @@ import com.arialyy.aria.core.inf.ITask; import com.arialyy.aria.util.CommonUtil; import java.util.HashMap; import java.util.Map; -import java.util.Set; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.TimeUnit; @@ -31,14 +30,14 @@ import java.util.concurrent.TimeUnit; * Created by lyy on 2016/8/15. * 任务执行池,所有当前下载任务都该任务池中,默认下载大小为2 */ -public class NormalExecutePool implements IPool { - private static final String TAG = "NormalExecutePool"; - private static final long TIME_OUT = 1000; - private ArrayBlockingQueue mExecuteQueue; - private Map mExecuteMap; - private int mSize; +public class BaseExecutePool implements IPool { + private final String TAG = "BaseExecutePool"; + final long TIME_OUT = 1000; + ArrayBlockingQueue mExecuteQueue; + Map mExecuteMap; + protected int mSize; - public NormalExecutePool(boolean isDownload) { + public BaseExecutePool(boolean isDownload) { if (isDownload) { mSize = AriaManager.getInstance(AriaManager.APP).getDownloadConfig().getMaxTaskNum(); } else { @@ -67,10 +66,6 @@ public class NormalExecutePool implements IPool { return false; } else { if (mExecuteQueue.size() >= mSize) { - Set keys = mExecuteMap.keySet(); - for (String key : keys) { - if (mExecuteMap.get(key).isHighestPriorityTask()) return false; - } if (pollFirstTask()) { return putNewTask(task); } @@ -106,7 +101,7 @@ public class NormalExecutePool implements IPool { * * @param newTask 新任务 */ - private boolean putNewTask(TASK newTask) { + boolean putNewTask(TASK newTask) { String url = newTask.getKey(); boolean s = mExecuteQueue.offer(newTask); Log.w(TAG, "任务添加" + (s ? "成功" : "失败,【" + url + "】")); @@ -119,16 +114,13 @@ public class NormalExecutePool implements IPool { /** * 队列满时,将移除下载队列中的第一个任务 */ - private boolean pollFirstTask() { + boolean pollFirstTask() { try { TASK oldTask = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS); if (oldTask == null) { Log.e(TAG, "移除任务失败"); return false; } - if (oldTask.isHighestPriorityTask()) { - return false; - } oldTask.stop(); String key = CommonUtil.keyToHashKey(oldTask.getKey()); mExecuteMap.remove(key); @@ -142,7 +134,7 @@ public class NormalExecutePool implements IPool { @Override public TASK pollTask() { synchronized (AriaManager.LOCK) { try { - TASK task = null; + TASK task; task = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS); if (task != null) { String url = task.getKey(); diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/pool/DownloadExecutePool.java b/Aria/src/main/java/com/arialyy/aria/core/queue/pool/DownloadExecutePool.java new file mode 100644 index 00000000..0e8e53b0 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/queue/pool/DownloadExecutePool.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.queue.pool; + +import android.util.Log; +import com.arialyy.aria.core.AriaManager; +import com.arialyy.aria.core.download.DownloadTask; +import com.arialyy.aria.util.CommonUtil; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * Created by AriaL on 2017/6/29. + * 单个下载任务的执行池 + */ +public class DownloadExecutePool extends BaseExecutePool { + private final String TAG = "DownloadExecutePool"; + + public DownloadExecutePool(boolean isDownload) { + super(isDownload); + } + + @Override public boolean putTask(DownloadTask task) { + synchronized (AriaManager.LOCK) { + if (task == null) { + Log.e(TAG, "任务不能为空!!"); + return false; + } + String url = task.getKey(); + if (mExecuteQueue.contains(task)) { + Log.e(TAG, "队列中已经包含了该任务,任务key【" + url + "】"); + return false; + } else { + if (mExecuteQueue.size() >= mSize) { + Set keys = mExecuteMap.keySet(); + for (String key : keys) { + if (mExecuteMap.get(key).isHighestPriorityTask()) return false; + } + if (pollFirstTask()) { + return putNewTask(task); + } + } else { + return putNewTask(task); + } + } + } + return false; + } + + @Override boolean pollFirstTask() { + try { + DownloadTask oldTask = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS); + if (oldTask == null) { + Log.e(TAG, "移除任务失败"); + return false; + } + if (oldTask.isHighestPriorityTask()) { + return false; + } + oldTask.stop(); + String key = CommonUtil.keyToHashKey(oldTask.getKey()); + mExecuteMap.remove(key); + } catch (InterruptedException e) { + e.printStackTrace(); + return false; + } + return true; + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/pool/GroupCachePool.java b/Aria/src/main/java/com/arialyy/aria/core/queue/pool/GroupCachePool.java deleted file mode 100644 index 3e256198..00000000 --- a/Aria/src/main/java/com/arialyy/aria/core/queue/pool/GroupCachePool.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.arialyy.aria.core.queue.pool; - -/** - * Created by AriaL on 2017/6/29. - * 任务组缓冲池 - */ -public class GroupCachePool { -} diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/pool/GroupExecutePool.java b/Aria/src/main/java/com/arialyy/aria/core/queue/pool/GroupExecutePool.java deleted file mode 100644 index 188b84d4..00000000 --- a/Aria/src/main/java/com/arialyy/aria/core/queue/pool/GroupExecutePool.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.arialyy.aria.core.queue.pool; - -/** - * Created by AriaL on 2017/6/29. - */ - -public class GroupExecutePool { -} diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/pool/IPool.java b/Aria/src/main/java/com/arialyy/aria/core/queue/pool/IPool.java index 970c22b9..7e143b9b 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/queue/pool/IPool.java +++ b/Aria/src/main/java/com/arialyy/aria/core/queue/pool/IPool.java @@ -22,18 +22,18 @@ import com.arialyy.aria.core.inf.ITask; * Created by lyy on 2016/8/14. * 任务池 */ -public interface IPool { +interface IPool { /** * 将下载任务添加到任务池中 */ - public boolean putTask(T task); + boolean putTask(T task); /** * 按照队列原则取出下载任务 * * @return 返回null或者下载任务 */ - public T pollTask(); + T pollTask(); /** * 通过下载链接获取下载任务,当任务不为空时,队列将删除该下载任务 @@ -41,7 +41,7 @@ public interface IPool { * @param downloadUrl 下载链接 * @return 返回null或者下载任务 */ - public T getTask(String downloadUrl); + T getTask(String downloadUrl); /** * 删除任务池中的下载任务 @@ -49,7 +49,7 @@ public interface IPool { * @param task 下载任务 * @return true:移除成功 */ - public boolean removeTask(T task); + boolean removeTask(T task); /** * 通过key除下载任务 @@ -57,12 +57,12 @@ public interface IPool { * @param key 下载链接 * @return true:移除成功 */ - public boolean removeTask(String key); + boolean removeTask(String key); /** * 池子大小 * * @return 返回缓存池或者执行池大小 */ - public int size(); + int size(); } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java index 8e097f48..255662ab 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java @@ -20,8 +20,8 @@ import android.os.Message; import android.util.Log; import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.download.DownloadTask; -import com.arialyy.aria.core.inf.AbsNormalEntity; -import com.arialyy.aria.core.inf.AbsNormalTask; +import com.arialyy.aria.core.inf.AbsEntity; +import com.arialyy.aria.core.inf.AbsTask; import com.arialyy.aria.core.inf.AbsTaskEntity; import com.arialyy.aria.core.inf.IEntity; import com.arialyy.aria.core.queue.ITaskQueue; @@ -34,19 +34,19 @@ import java.util.concurrent.ConcurrentHashMap; /** * Created by lyy on 2017/6/4. */ -public abstract class AbsSchedulers, QUEUE extends ITaskQueue> +abstract class AbsSchedulers, QUEUE extends ITaskQueue> implements ISchedulers { - private static final String TAG = "AbsSchedulers"; + private final String TAG = "AbsSchedulers"; /** * 下载的动态生成的代理类后缀 */ - String DOWNLOAD_PROXY_CLASS_SUFFIX = "$$DownloadListenerProxy"; + private String DOWNLOAD_PROXY_CLASS_SUFFIX = "$$DownloadListenerProxy"; /** * 上传的动态生成的代理类后缀 */ - String UPLOAD_PROXY_CLASS_SUFFIX = "$$UploadListenerProxy"; + private String UPLOAD_PROXY_CLASS_SUFFIX = "$$UploadListenerProxy"; protected QUEUE mQueue; protected boolean isDownload = true; diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadGroupSchedulers.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadGroupSchedulers.java new file mode 100644 index 00000000..d7d98fef --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadGroupSchedulers.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.scheduler; + +import com.arialyy.aria.core.AriaManager; +import com.arialyy.aria.core.download.DownloadGroupEntity; +import com.arialyy.aria.core.download.DownloadGroupTask; +import com.arialyy.aria.core.download.DownloadGroupTaskEntity; +import com.arialyy.aria.core.queue.DownloadGroupTaskQueue; + +/** + * Created by AriaL on 2017/7/2. + */ +public class DownloadGroupSchedulers extends + AbsSchedulers { + private final String TAG = "DownloadGroupSchedulers"; + private static volatile DownloadGroupSchedulers INSTANCE = null; + + private DownloadGroupSchedulers() { + mQueue = DownloadGroupTaskQueue.getInstance(); + isDownload = true; + } + + public static DownloadGroupSchedulers getInstance() { + if (INSTANCE == null) { + synchronized (AriaManager.LOCK) { + INSTANCE = new DownloadGroupSchedulers(); + } + } + return INSTANCE; + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadSchedulers.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadSchedulers.java index f6137abf..46e80fc0 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadSchedulers.java +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadSchedulers.java @@ -29,7 +29,7 @@ import com.arialyy.aria.core.download.DownloadTask; public class DownloadSchedulers extends AbsSchedulers { - private static final String TAG = "DownloadSchedulers"; + private final String TAG = "DownloadSchedulers"; private static volatile DownloadSchedulers INSTANCE = null; private DownloadSchedulers() { diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadUtil.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadUtil.java index 88a87caa..008869ef 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadUtil.java @@ -51,7 +51,7 @@ final class UploadUtil implements Runnable { UploadUtil(UploadTaskEntity taskEntity, IUploadListener listener) { mTaskEntity = taskEntity; CheckUtil.checkTaskEntity(taskEntity); - mUploadEntity = taskEntity.uploadEntity; + mUploadEntity = taskEntity.getEntity(); if (listener == null) { throw new IllegalArgumentException("上传监听不能为空"); } @@ -162,11 +162,11 @@ final class UploadUtil implements Runnable { writer.append("Content-Disposition: form-data; name=\"") .append(attachment) .append("\"; filename=\"") - .append(mTaskEntity.uploadEntity.getFileName()) + .append(mTaskEntity.getEntity().getFileName()) .append("\"") .append(LINE_END); writer.append("Content-Type: ") - .append(URLConnection.guessContentTypeFromName(mTaskEntity.uploadEntity.getFileName())) + .append(URLConnection.guessContentTypeFromName(mTaskEntity.getEntity().getFileName())) .append(LINE_END); writer.append("Content-Transfer-Encoding: binary").append(LINE_END); writer.append(LINE_END); diff --git a/Aria/src/main/java/com/arialyy/aria/util/CheckUtil.java b/Aria/src/main/java/com/arialyy/aria/util/CheckUtil.java index c083c46e..41841d5b 100644 --- a/Aria/src/main/java/com/arialyy/aria/util/CheckUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/util/CheckUtil.java @@ -88,9 +88,9 @@ public class CheckUtil { */ public static void checkTaskEntity(AbsTaskEntity entity) { if (entity instanceof DownloadTaskEntity) { - checkDownloadTaskEntity(((DownloadTaskEntity) entity).downloadEntity); + checkDownloadTaskEntity(((DownloadTaskEntity) entity).getEntity()); } else if (entity instanceof UploadTaskEntity) { - checkUploadTaskEntity(((UploadTaskEntity) entity).uploadEntity); + checkUploadTaskEntity(((UploadTaskEntity) entity).getEntity()); } } @@ -103,7 +103,7 @@ public class CheckUtil { public static boolean checkCmdEntity(AbsTaskEntity entity, boolean checkType) { boolean b = false; if (entity instanceof DownloadTaskEntity) { - DownloadEntity entity1 = ((DownloadTaskEntity) entity).downloadEntity; + DownloadEntity entity1 = ((DownloadTaskEntity) entity).getEntity(); if (entity1 == null) { Log.e(TAG, "下载实体不能为空"); } else if (checkType && TextUtils.isEmpty(entity1.getDownloadUrl())) { @@ -114,7 +114,7 @@ public class CheckUtil { b = true; } } else if (entity instanceof UploadTaskEntity) { - UploadEntity entity1 = ((UploadTaskEntity) entity).uploadEntity; + UploadEntity entity1 = ((UploadTaskEntity) entity).getEntity(); if (entity1 == null) { Log.e(TAG, "上传实体不能为空"); } else if (TextUtils.isEmpty(entity1.getFilePath())) { diff --git a/aria/src/main/java/com/arialyy/aria/core/Configuration.java b/aria/src/main/java/com/arialyy/aria/core/Configuration.java index d23974f1..8adcb24a 100644 --- a/aria/src/main/java/com/arialyy/aria/core/Configuration.java +++ b/aria/src/main/java/com/arialyy/aria/core/Configuration.java @@ -40,7 +40,7 @@ class Configuration { /** * 旧任务数 */ - public static int oldMaxTaskNum = 2; + public int oldMaxTaskNum = 2; /** * 是否发送任务广播,true,发送 @@ -176,7 +176,8 @@ class Configuration { try { for (Field field : fields) { int m = field.getModifiers(); - if (Modifier.isFinal(m) || Modifier.isStatic(m)) { + if (field.getName().equals("oldMaxTaskNum") || Modifier.isFinal(m) || Modifier.isStatic( + m)) { continue; } field.setAccessible(true); diff --git a/aria/src/main/java/com/arialyy/aria/core/upload/UploadTaskEntity.java b/aria/src/main/java/com/arialyy/aria/core/upload/UploadTaskEntity.java index 84ea56f1..5200e761 100644 --- a/aria/src/main/java/com/arialyy/aria/core/upload/UploadTaskEntity.java +++ b/aria/src/main/java/com/arialyy/aria/core/upload/UploadTaskEntity.java @@ -23,8 +23,7 @@ import java.util.Map; * Created by lyy on 2017/2/9. * 上传任务实体 */ -public class UploadTaskEntity extends AbsTaskEntity { - public UploadEntity uploadEntity; +public class UploadTaskEntity extends AbsTaskEntity { public String uploadUrl; //上传路径 public String attachment; //文件上传需要的key public String contentType = "multipart/form-data"; //上传的文件类型 @@ -36,11 +35,8 @@ public class UploadTaskEntity extends AbsTaskEntity { */ public Map formFields = new HashMap<>(); - public UploadTaskEntity(UploadEntity downloadEntity) { - this.uploadEntity = downloadEntity; + public UploadTaskEntity(UploadEntity entity) { + this.entity = entity; } - @Override public UploadEntity getEntity() { - return uploadEntity; - } }