任务组队列完成

pull/330/head
AriaLyy 8 years ago
parent ad136576dc
commit 4e305dcf01
  1. 9
      Aria/src/main/java/com/arialyy/aria/core/command/group/AbsGroupCmd.java
  2. 2
      Aria/src/main/java/com/arialyy/aria/core/command/normal/AddCmd.java
  3. 4
      Aria/src/main/java/com/arialyy/aria/core/command/normal/CancelCmd.java
  4. 10
      Aria/src/main/java/com/arialyy/aria/core/command/normal/HighestPriorityCmd.java
  5. 4
      Aria/src/main/java/com/arialyy/aria/core/command/normal/ResumeAllCmd.java
  6. 4
      Aria/src/main/java/com/arialyy/aria/core/command/normal/StartCmd.java
  7. 4
      Aria/src/main/java/com/arialyy/aria/core/command/normal/StopCmd.java
  8. 474
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTask.java
  9. 6
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadTask.java
  10. 20
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/DownloadGroupUtil.java
  11. 443
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/DownloadUtil.java
  12. 34
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/Downloader.java
  13. 2
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/IDownloadListener.java
  14. 2
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/IDownloadUtil.java
  15. 4
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/SingleThreadTask.java
  16. 4
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/StateConstance.java
  17. 14
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsEntity.java
  18. 40
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsGroupTask.java
  19. 15
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsNormalEntity.java
  20. 2
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsNormalTarget.java
  21. 52
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsNormalTask.java
  22. 58
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsTask.java
  23. 1
      Aria/src/main/java/com/arialyy/aria/core/inf/ITask.java
  24. 74
      Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java
  25. 48
      Aria/src/main/java/com/arialyy/aria/core/queue/DownloadGroupTaskQueue.java
  26. 63
      Aria/src/main/java/com/arialyy/aria/core/queue/DownloadTaskQueue.java
  27. 11
      Aria/src/main/java/com/arialyy/aria/core/queue/ITaskQueue.java
  28. 32
      Aria/src/main/java/com/arialyy/aria/core/queue/TaskFactory.java
  29. 26
      Aria/src/main/java/com/arialyy/aria/core/queue/UploadTaskQueue.java
  30. 8
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/BaseCachePool.java
  31. 28
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/BaseExecutePool.java
  32. 82
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/DownloadExecutePool.java
  33. 23
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/GroupCachePool.java
  34. 23
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/GroupExecutePool.java
  35. 14
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/IPool.java
  36. 12
      Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java
  37. 45
      Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadGroupSchedulers.java
  38. 2
      Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadSchedulers.java
  39. 6
      Aria/src/main/java/com/arialyy/aria/core/upload/UploadUtil.java
  40. 8
      Aria/src/main/java/com/arialyy/aria/util/CheckUtil.java
  41. 5
      aria/src/main/java/com/arialyy/aria/core/Configuration.java
  42. 10
      aria/src/main/java/com/arialyy/aria/core/upload/UploadTaskEntity.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<T extends AbsTaskEntity> extends AbsCmd<T> {
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;
}
}
}

@ -33,7 +33,7 @@ class AddCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
@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);

@ -31,9 +31,9 @@ class CancelCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
@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)) {

@ -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<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
/**
@ -39,15 +43,15 @@ final class HighestPriorityCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T>
@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);
}
}
}

@ -39,10 +39,10 @@ final class ResumeAllCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
}
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, "添加命令执行失败,【该任务已经存在】");
}

@ -47,9 +47,9 @@ class StartCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
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);
}

@ -34,10 +34,10 @@ class StopCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
@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, "停止命令执行失败,【调度器中没有该任务】");

@ -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<DownloadTaskEntity, DownloadGroupEntity> {
// DListener mListener;
// SparseArray<DownloadUtil> 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<DownloadEntity> 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<Handler> outHandler;
// WeakReference<DownloadGroupTask> 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<String, DownloadEntity> 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<DownloadGroupTaskEntity, DownloadGroupEntity> {
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<Handler> outHandler;
WeakReference<DownloadGroupTask> 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;
}
}
}

@ -46,11 +46,11 @@ public class DownloadTask extends AbsNormalTask<DownloadEntity> {
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<DownloadEntity> {
public DownloadTask build() {
DownloadTask task = new DownloadTask(taskEntity, outHandler);
task.setTargetName(targetName);
taskEntity.downloadEntity.save();
taskEntity.getEntity().save();
return task;
}
}

@ -68,14 +68,14 @@ public class DownloadGroupUtil implements IDownloadUtil {
/**
* 下载器映射表key为下载地址
*/
private Map<String, DownloadThreader> mDownloaderMap = new HashMap<>();
private Map<String, Downloader> mDownloaderMap = new HashMap<>();
/**
* 文件信息回调组
*/
private SparseArray<FileInfoThread.OnFileInfoCallback> 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<String> 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<String> 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);
}

@ -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<Runnable> 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();
}
}
new Thread(new FileInfoThread(mTaskEntity, new FileInfoThread.OnFileInfoCallback() {
@Override public void onComplete(String url, int code) {
mDT.startDownload();
}
/**
* 处理状态码
*/
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);
@Override public void onFail(String url, String errorMsg) {
failDownload(errorMsg);
}
})).start();
}
/**
* 检查长度是否合法
*
* @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<Object> 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();
}
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);
}
}
}
}

@ -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<Runnable> 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,14 +125,15 @@ 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()
mThreadNum = isNewTask ? (mEntity.getFileSize() <= SUB_LEN ? 1
: AriaManager.getInstance(mContext).getDownloadConfig().getThreadNum())
: mRealThreadNum;
mFixedThreadPool = Executors.newFixedThreadPool(mThreadNum);
handleBreakpoint();

@ -19,7 +19,7 @@ package com.arialyy.aria.core.download.downloader;
/**
* 下载监听
*/
interface IDownloadListener {
public interface IDownloadListener {
/**
* 支持断点回调

@ -20,7 +20,7 @@ package com.arialyy.aria.core.download.downloader;
* Created by lyy on 2016/10/31.
* 抽象的下载接口
*/
interface IDownloadUtil {
public interface IDownloadUtil {
/**
* 获取文件大小

@ -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;

@ -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() {

@ -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();

@ -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<TASK_ENTITY extends AbsTaskEntity, ENTITY ext
protected TASK_ENTITY mTaskEntity;
@Override public int getPercent() {
return 0;
}
@Override public long getFileSize() {
return 0;
}
@Override public String getConvertFileSize() {
return null;
}
@Override public long getCurrentProgress() {
return 0;
}
@Override public String getConvertCurrentProgress() {
return null;
}
@Override public int getState() {
return mEntity.getState();
}
@Override public String getExtendField() {
return mEntity.getStr();
}
@Override public String getKey() {
return mEntity.getGroupName();
}
@Override public boolean isRunning() {
return false;
}
@Override public ENTITY getEntity() {
return mEntity;
}
@Override public void removeRecord() {
}
}

@ -24,10 +24,7 @@ import com.arialyy.aria.orm.Ignore;
* Created by AriaL on 2017/6/3.
*/
public abstract class AbsNormalEntity extends AbsEntity implements Parcelable {
/**
* 下载失败计数每次开始都重置为0
*/
@Ignore private int failNum = 0;
/**
* 文件名
*/
@ -46,14 +43,6 @@ public abstract class AbsNormalEntity extends AbsEntity implements Parcelable {
isGroupChild = groupChild;
}
public int getFailNum() {
return failNum;
}
public void setFailNum(int failNum) {
this.failNum = failNum;
}
public String getFileName() {
return fileName;
}
@ -71,14 +60,12 @@ public abstract class AbsNormalEntity extends AbsEntity implements Parcelable {
@Override public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(this.failNum);
dest.writeString(this.fileName);
dest.writeByte(this.isGroupChild ? (byte) 1 : (byte) 0);
}
protected AbsNormalEntity(Parcel in) {
super(in);
this.failNum = in.readInt();
this.fileName = in.readString();
this.isGroupChild = in.readByte() != 0;
}

@ -233,7 +233,7 @@ public abstract class AbsNormalTarget<TARGET extends AbsNormalTarget, ENTITY ext
*
* @see #stop()
*/
@Deprecated protected void pause() {
@Deprecated public void pause() {
stop();
}

@ -15,8 +15,6 @@
*/
package com.arialyy.aria.core.inf;
import com.arialyy.aria.util.CommonUtil;
/**
* Created by lyy on 2017/6/3.
*/
@ -47,54 +45,4 @@ public abstract class AbsNormalTask<ENTITY extends AbsEntity> extends AbsTask<EN
public boolean isHighestPriorityTask() {
return isHeighestTask;
}
/**
* 获取百分比进度
*
* @return 返回百分比进度如果文件长度为0返回0
*/
@Override public int getPercent() {
if (mEntity.getFileSize() == 0) {
return 0;
}
return (int) (mEntity.getCurrentProgress() * 100 / mEntity.getFileSize());
}
/**
* 获取文件大小
*/
@Override public long getFileSize() {
return mEntity.getFileSize();
}
/**
* 转换单位后的文件长度
*
* @return 如果文件长度为0则返回0m否则返回转换后的长度1b1kb1mb1gb1tb
*/
@Override public String getConvertFileSize() {
if (mEntity.getFileSize() == 0) {
return "0mb";
}
return CommonUtil.formatFileSize(mEntity.getFileSize());
}
/**
* 获取当前下载进度
*/
@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());
}
}

@ -17,6 +17,7 @@ package com.arialyy.aria.core.inf;
import android.content.Context;
import android.os.Handler;
import com.arialyy.aria.util.CommonUtil;
/**
* Created by AriaL on 2017/6/29.
@ -32,6 +33,56 @@ public abstract class AbsTask<ENTITY extends AbsEntity> implements ITask<ENTITY>
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否则返回转换后的长度1b1kb1mb1gb1tb
*/
@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<ENTITY extends AbsEntity> implements ITask<ENTITY>
return mEntity;
}
/**
* 删除任务记录删除后再次启动该任务的下载时将重新下载
*/
@Override public void removeRecord() {
mEntity.deleteData();
}
public String getTargetName() {
return mTargetName;
}

@ -92,5 +92,4 @@ public interface ITask<ENTITY extends AbsEntity> {
public void setTargetName(String targetName);
public void removeRecord();
}

@ -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<TASK extends AbsNormalTask, TASK_ENTITY extends AbsTaskEntity, ENTITY extends AbsNormalEntity>
abstract class AbsTaskQueue<TASK extends AbsTask, TASK_ENTITY extends AbsTaskEntity, ENTITY extends AbsEntity>
implements ITaskQueue<TASK, TASK_ENTITY, ENTITY> {
private final String TAG = "AbsTaskQueue";
NormalCachePool<TASK> mCachePool = new NormalCachePool<>();
NormalExecutePool<TASK> mExecutePool;
BaseCachePool<TASK> mCachePool = new BaseCachePool<>();
BaseExecutePool<TASK> mExecutePool;
@Override public boolean taskIsRunning(String key) {
return mExecutePool.getTask(key) != null;
@ -70,17 +73,27 @@ abstract class AbsTaskQueue<TASK extends AbsNormalTask, TASK_ENTITY extends AbsT
return AriaManager.getInstance(AriaManager.APP).getDownloadConfig().getMaxTaskNum();
}
/**
* 获取实体的索引
*/
public abstract String getKey(ENTITY entity);
/**
* 获取配置文件配置的最大可执行任务数
*/
public abstract int getConfigMaxNum();
/**
* 获取任务执行池
*/
public NormalExecutePool getExecutePool() {
public BaseExecutePool getExecutePool() {
return mExecutePool;
}
/**
* 获取缓存池
*/
public NormalCachePool getCachePool() {
public BaseCachePool getCachePool() {
return mCachePool;
}
@ -102,8 +115,31 @@ abstract class AbsTaskQueue<TASK extends AbsNormalTask, TASK_ENTITY extends AbsT
return mExecutePool.size();
}
@Override public void setTaskHighestPriority(TASK task) {
@Override public void setMaxTaskNum(int downloadNum) {
int oldMaxSize = getConfigMaxNum();
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++) {
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<TASK extends AbsNormalTask, TASK_ENTITY extends AbsT
@Override public void stopTask(TASK task) {
if (!task.isRunning()) Log.w(TAG, "停止任务失败,【任务已经停止】");
task.setHighestPriority(false);
if (mExecutePool.removeTask(task)) {
task.stop();
} else {
@ -133,6 +168,17 @@ abstract class AbsTaskQueue<TASK extends AbsNormalTask, TASK_ENTITY extends AbsT
}
}
@Override public void removeTask(ENTITY entity) {
TASK task = mExecutePool.getTask(getKey(entity));
if (task != null) {
Log.d(TAG, "从执行池删除任务,删除" + (mExecutePool.removeTask(task) ? "成功" : "失败"));
}
task = mCachePool.getTask(getKey(entity));
if (task != null) {
Log.d(TAG, "从缓存池删除任务,删除" + (mCachePool.removeTask(task) ? "成功" : "失败"));
}
}
@Override public void reTryStart(TASK task) {
if (task == null) {
Log.w(TAG, "重试下载失败,task 为null");
@ -145,6 +191,10 @@ abstract class AbsTaskQueue<TASK extends AbsNormalTask, TASK_ENTITY extends AbsT
}
}
@Override public TASK getTask(ENTITY entity) {
return getTask(getKey(entity));
}
@Override public void removeTask(TASK task) {
task.cancel();
}

@ -16,9 +16,55 @@
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.download.DownloadGroupEntity;
import com.arialyy.aria.core.download.DownloadGroupTask;
import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
import com.arialyy.aria.core.queue.pool.BaseExecutePool;
import com.arialyy.aria.core.scheduler.DownloadGroupSchedulers;
/**
* Created by AriaL on 2017/6/29.
* 任务组下载队列
*/
public class DownloadGroupTaskQueue {
public class DownloadGroupTaskQueue
extends AbsTaskQueue<DownloadGroupTask, DownloadGroupTaskEntity, DownloadGroupEntity> {
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;
}
}

@ -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<String, DownloadTask> 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);
}
}

@ -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<TASK extends AbsNormalTask, TASK_ENTITY extends AbsTaskEntity, ENTITY extends IEntity> {
public interface ITaskQueue<TASK extends AbsTask, TASK_ENTITY extends AbsTaskEntity, ENTITY extends AbsEntity> {
/**
* 通过key判断任务是否正在执行
@ -50,13 +52,6 @@ public interface ITaskQueue<TASK extends AbsNormalTask, TASK_ENTITY extends AbsT
*/
void removeAllTask();
/**
* 设置任务为最高优先级任务
*
* @param task {@link DownloadTask}{@link UploadTask}
*/
void setTaskHighestPriority(TASK task);
/**
* 开始任务
*

@ -17,12 +17,15 @@
package com.arialyy.aria.core.queue;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.download.DownloadGroupTask;
import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.core.download.DownloadTaskEntity;
import com.arialyy.aria.core.inf.ITask;
import com.arialyy.aria.core.inf.AbsTaskEntity;
import com.arialyy.aria.core.scheduler.DownloadSchedulers;
import com.arialyy.aria.core.scheduler.ISchedulers;
import com.arialyy.aria.core.scheduler.UploadSchedulers;
import com.arialyy.aria.core.upload.UploadTask;
import com.arialyy.aria.core.upload.UploadTaskEntity;
@ -30,8 +33,7 @@ import com.arialyy.aria.core.upload.UploadTaskEntity;
* Created by lyy on 2016/8/18.
* 任务工厂
*/
public class TaskFactory {
private static final String TAG = "TaskFactory";
class TaskFactory {
private static volatile TaskFactory INSTANCE = null;
@ -53,20 +55,36 @@ public class TaskFactory {
*
* @param entity 下载实体
* @param schedulers 对应的任务调度器
* @param <ENTITY> {@link DownloadTaskEntity}{@link UploadTaskEntity}
* @param <SCHEDULER> {@link DownloadSchedulers}
* @return {@link DownloadTask}{@link UploadTask}
* @param <TASK_ENTITY> {@link DownloadTaskEntity}{@link UploadTaskEntity}{@link
* DownloadGroupTaskEntity}
* @param <SCHEDULER> {@link DownloadSchedulers}{@link UploadSchedulers}
* @return {@link DownloadTask}{@link UploadTask}{@link DownloadGroupTask}
*/
<ENTITY extends AbsTaskEntity, SCHEDULER extends ISchedulers> ITask createTask(String targetName,
ENTITY entity, SCHEDULER schedulers) {
<TASK_ENTITY extends AbsTaskEntity, SCHEDULER extends ISchedulers> 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}

@ -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<UploadTask, UploadTaskEntity,
}
private UploadTaskQueue() {
mExecutePool = new NormalExecutePool<>(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<UploadTask, UploadTaskEntity,
}
return task;
}
@Override public UploadTask getTask(UploadEntity entity) {
return getTask(entity.getFilePath());
}
@Override public void removeTask(UploadEntity entity) {
UploadTask task = mExecutePool.getTask(entity.getFilePath());
if (task != null) {
Log.d(TAG, "从执行池删除任务,删除" + (mExecutePool.removeTask(task) ? "成功" : "失败"));
}
task = mCachePool.getTask(entity.getFilePath());
if (task != null) {
Log.d(TAG, "从缓存池删除任务,删除" + (mCachePool.removeTask(task) ? "成功" : "失败"));
}
}
}

@ -32,14 +32,14 @@ import java.util.concurrent.TimeUnit;
* Created by lyy on 2016/8/14.
* 任务缓存池所有下载任务最先缓存在这个池中
*/
public class NormalCachePool<TASK extends ITask> implements IPool<TASK> {
private static final String TAG = "NormalCachePool";
public class BaseCachePool<TASK extends ITask> implements IPool<TASK> {
private static final String TAG = "BaseCachePool";
private static final int MAX_NUM = Integer.MAX_VALUE; //最大下载任务数
private static final long TIME_OUT = 1000;
private Map<String, TASK> mCacheMap;
private LinkedBlockingQueue<TASK> mCacheQueue;
public NormalCachePool() {
public BaseCachePool() {
mCacheQueue = new LinkedBlockingQueue<>(MAX_NUM);
mCacheMap = new HashMap<>();
}
@ -95,7 +95,7 @@ public class NormalCachePool<TASK extends ITask> implements IPool<TASK> {
@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();

@ -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<TASK extends ITask> implements IPool<TASK> {
private static final String TAG = "NormalExecutePool";
private static final long TIME_OUT = 1000;
private ArrayBlockingQueue<TASK> mExecuteQueue;
private Map<String, TASK> mExecuteMap;
private int mSize;
public class BaseExecutePool<TASK extends ITask> implements IPool<TASK> {
private final String TAG = "BaseExecutePool";
final long TIME_OUT = 1000;
ArrayBlockingQueue<TASK> mExecuteQueue;
Map<String, TASK> 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<TASK extends ITask> implements IPool<TASK> {
return false;
} else {
if (mExecuteQueue.size() >= mSize) {
Set<String> 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<TASK extends ITask> implements IPool<TASK> {
*
* @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<TASK extends ITask> implements IPool<TASK> {
/**
* 队列满时将移除下载队列中的第一个任务
*/
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<TASK extends ITask> implements IPool<TASK> {
@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();

@ -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<DownloadTask> {
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<String> 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;
}
}

@ -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 {
}

@ -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 {
}

@ -22,18 +22,18 @@ import com.arialyy.aria.core.inf.ITask;
* Created by lyy on 2016/8/14.
* 任务池
*/
public interface IPool<T extends ITask> {
interface IPool<T extends ITask> {
/**
* 将下载任务添加到任务池中
*/
public boolean putTask(T task);
boolean putTask(T task);
/**
* 按照队列原则取出下载任务
*
* @return 返回null或者下载任务
*/
public T pollTask();
T pollTask();
/**
* 通过下载链接获取下载任务当任务不为空时队列将删除该下载任务
@ -41,7 +41,7 @@ public interface IPool<T extends ITask> {
* @param downloadUrl 下载链接
* @return 返回null或者下载任务
*/
public T getTask(String downloadUrl);
T getTask(String downloadUrl);
/**
* 删除任务池中的下载任务
@ -49,7 +49,7 @@ public interface IPool<T extends ITask> {
* @param task 下载任务
* @return true:移除成功
*/
public boolean removeTask(T task);
boolean removeTask(T task);
/**
* 通过key除下载任务
@ -57,12 +57,12 @@ public interface IPool<T extends ITask> {
* @param key 下载链接
* @return true:移除成功
*/
public boolean removeTask(String key);
boolean removeTask(String key);
/**
* 池子大小
*
* @return 返回缓存池或者执行池大小
*/
public int size();
int size();
}

@ -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<TASK_ENTITY extends AbsTaskEntity, ENTITY extends AbsNormalEntity, TASK extends AbsNormalTask<TASK_ENTITY, ENTITY>, QUEUE extends ITaskQueue<TASK, TASK_ENTITY, ENTITY>>
abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, ENTITY extends AbsEntity, TASK extends AbsTask<ENTITY>, QUEUE extends ITaskQueue<TASK, TASK_ENTITY, ENTITY>>
implements ISchedulers<TASK> {
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;

@ -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<DownloadGroupTaskEntity, DownloadGroupEntity, DownloadGroupTask, DownloadGroupTaskQueue> {
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;
}
}

@ -29,7 +29,7 @@ import com.arialyy.aria.core.download.DownloadTask;
public class DownloadSchedulers
extends AbsSchedulers<DownloadTaskEntity, DownloadEntity, DownloadTask, DownloadTaskQueue> {
private static final String TAG = "DownloadSchedulers";
private final String TAG = "DownloadSchedulers";
private static volatile DownloadSchedulers INSTANCE = null;
private DownloadSchedulers() {

@ -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);

@ -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())) {

@ -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);

@ -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<UploadEntity> {
public String uploadUrl; //上传路径
public String attachment; //文件上传需要的key
public String contentType = "multipart/form-data"; //上传的文件类型
@ -36,11 +35,8 @@ public class UploadTaskEntity extends AbsTaskEntity {
*/
public Map<String, String> formFields = new HashMap<>();
public UploadTaskEntity(UploadEntity downloadEntity) {
this.uploadEntity = downloadEntity;
public UploadTaskEntity(UploadEntity entity) {
this.entity = entity;
}
@Override public UploadEntity getEntity() {
return uploadEntity;
}
}

Loading…
Cancel
Save