pull/330/head
AriaLyy 7 years ago
commit 12521e0e55
  1. 49
      Aria/src/main/java/com/arialyy/aria/core/AriaManager.java
  2. 77
      Aria/src/main/java/com/arialyy/aria/core/ErrorEntity.java
  3. 85
      Aria/src/main/java/com/arialyy/aria/core/TaskManager.java
  4. 14
      Aria/src/main/java/com/arialyy/aria/core/command/normal/CancelAllCmd.java
  5. 9
      Aria/src/main/java/com/arialyy/aria/core/command/normal/CancelCmd.java
  6. 30
      Aria/src/main/java/com/arialyy/aria/core/command/normal/ResumeAllCmd.java
  7. 14
      Aria/src/main/java/com/arialyy/aria/core/common/AbsThreadTask.java
  8. 6
      Aria/src/main/java/com/arialyy/aria/core/download/BaseGroupTarget.java
  9. 16
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java
  10. 14
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java
  11. 5
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java
  12. 21
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/AbsGroupUtil.java
  13. 3
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/Downloader.java
  14. 2
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpDirDownloadUtil.java
  15. 4
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpThreadTask.java
  16. 4
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java
  17. 2
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/SimpleDownloadUtil.java
  18. 11
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java
  19. 2
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsTask.java
  20. 6
      Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java
  21. 11
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/BaseCachePool.java
  22. 6
      Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpThreadTask.java
  23. 4
      Aria/src/main/java/com/arialyy/aria/core/upload/uploader/HttpThreadTask.java
  24. 4
      Aria/src/main/java/com/arialyy/aria/orm/DBConfig.java
  25. 7
      Aria/src/main/java/com/arialyy/aria/orm/DbEntity.java
  26. 12
      Aria/src/main/java/com/arialyy/aria/orm/DbUtil.java
  27. 25
      Aria/src/main/java/com/arialyy/aria/orm/SqlUtil.java
  28. 7
      Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java
  29. 58
      Aria/src/main/java/com/arialyy/aria/util/ErrorHelp.java
  30. 29
      DEV_LOG.md
  31. 3
      ENGLISH_README.md
  32. 348
      MORE_API.md
  33. 312
      README.md
  34. 8
      app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java
  35. 4
      app/src/main/java/com/arialyy/simple/download/group/DownloadGroupActivity.java
  36. 6
      build.gradle

@ -29,12 +29,18 @@ import android.support.v4.app.Fragment;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.widget.PopupWindow; import android.widget.PopupWindow;
import com.arialyy.aria.core.command.ICmd;
import com.arialyy.aria.core.common.QueueMod; import com.arialyy.aria.core.common.QueueMod;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
import com.arialyy.aria.core.download.DownloadReceiver; import com.arialyy.aria.core.download.DownloadReceiver;
import com.arialyy.aria.core.command.ICmd; import com.arialyy.aria.core.download.DownloadTaskEntity;
import com.arialyy.aria.core.inf.IReceiver; import com.arialyy.aria.core.inf.IReceiver;
import com.arialyy.aria.core.scheduler.AbsSchedulerListener; import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.upload.UploadReceiver; import com.arialyy.aria.core.upload.UploadReceiver;
import com.arialyy.aria.core.upload.UploadTaskEntity;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.orm.DbUtil; import com.arialyy.aria.orm.DbUtil;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import java.io.File; import java.io.File;
@ -184,6 +190,45 @@ import org.xml.sax.SAXException;
return (receiver instanceof UploadReceiver) ? (UploadReceiver) receiver : null; return (receiver instanceof UploadReceiver) ? (UploadReceiver) receiver : null;
} }
/**
* 获取Aria下载错误日志
*
* @return 如果错误日志不存在则返回空否则返回错误日志列表
*/
public List<ErrorEntity> getErrorLog() {
return DbEntity.findAllData(ErrorEntity.class);
}
/**
* 清楚错误日志
*/
public void cleanLog() {
DbEntity.clean(ErrorEntity.class);
}
/**
* 删除任务记录
*
* @param type 需要删除的任务类型1表示单任务下载2表示任务组下载3单任务上传
* @param key 下载为保存路径任务组为任务组名上传为上传文件路径
*/
public void delRecord(int type, String key) {
switch (type) {
case 1:
DbEntity.deleteData(DownloadEntity.class, "url=?", key);
DbEntity.deleteData(DownloadTaskEntity.class, "key=? and isGroupTask='false'", key);
break;
case 2:
DbEntity.deleteData(DownloadGroupEntity.class, "groupName=?", key);
DbEntity.deleteData(DownloadGroupTaskEntity.class, "key=?", key);
break;
case 3:
DbEntity.deleteData(UploadEntity.class, "filePath=?", key);
DbEntity.deleteData(UploadTaskEntity.class, "key=?", key);
break;
}
}
private IReceiver putReceiver(boolean isDownload, Object obj) { private IReceiver putReceiver(boolean isDownload, Object obj) {
final String key = getKey(isDownload, obj); final String key = getKey(isDownload, obj);
IReceiver receiver = mReceivers.get(key); IReceiver receiver = mReceivers.get(key);

@ -0,0 +1,77 @@
/*
* 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;
import com.arialyy.aria.orm.DbEntity;
/**
* Created by Aria.Lao on 2017/8/29.
* 错误实体
*/
public class ErrorEntity extends DbEntity {
/**
* 插入时间
*/
public long insertTime;
/**
* 错误信息
*/
public String err;
/**
* 任务名
*/
public String taskName;
/**
*任务类型
*/
public String taskType;
/**
* 提示
*/
public String msg;
/**
* 任务key
*/
public String key;
@Override public String toString() {
return "ErrorEntity{"
+ "insertTime="
+ insertTime
+ ", err='"
+ err
+ '\''
+ ", taskName='"
+ taskName
+ '\''
+ ", taskType='"
+ taskType
+ '\''
+ ", msg='"
+ msg
+ '\''
+ ", key='"
+ key
+ '\''
+ '}';
}
}

@ -0,0 +1,85 @@
/*
* 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;
import android.util.Log;
import com.arialyy.aria.core.inf.AbsTask;
import com.arialyy.aria.util.CommonUtil;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Created by Aria.Lao on 2017/9/1.
* 任务管理器
*/
public class TaskManager {
private static final String TAG = "TaskManager";
private static volatile TaskManager INSTANCE = null;
private Map<String, AbsTask> map = new ConcurrentHashMap<>();
public TaskManager getInstance() {
if (INSTANCE == null) {
synchronized (AriaManager.LOCK) {
INSTANCE = new TaskManager();
}
}
return INSTANCE;
}
private TaskManager() {
}
/**
* 管理器添加任务
*
* @param key 任务的key下载为保存路径任务组为任务组名上传为文件上传路径
* @param task 任务
* @return {@code true}添加成功
*/
public boolean addTask(String key, AbsTask task) {
String hash = CommonUtil.keyToHashKey(key);
if (map.keySet().contains(hash)) {
Log.e(TAG, "任务【" + key + "】已存在");
return false;
}
map.put(CommonUtil.keyToHashKey(key), task);
return true;
}
/**
* 移除任务
*
* @param key 任务的key下载为保存路径任务组为任务组名上传为文件上传路径
*/
public void removeTask(String key) {
String hash = CommonUtil.keyToHashKey(key);
for (Iterator<Map.Entry<String, AbsTask>> iter = map.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry<String, AbsTask> entry = iter.next();
if (entry.getKey().equals(hash)) iter.remove();
}
}
/**
* 通过key获取任务
*
* @return 入梅找不到任务返回null否则返回key对应的任务
*/
public AbsTask getTask(String key) {
return map.get(CommonUtil.keyToHashKey(key));
}
}

@ -27,7 +27,13 @@ import java.util.List;
* Created by AriaL on 2017/6/27. * Created by AriaL on 2017/6/27.
* 删除所有任务并且删除所有回掉 * 删除所有任务并且删除所有回掉
*/ */
final class CancelAllCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> { public class CancelAllCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
/**
* removeFile {@code true} 删除已经下载完成的任务不仅删除下载记录还会删除已经下载完成的文件{@code false}
* 如果文件已经下载完成只删除下载记录
*/
public boolean removeFile = false;
/** /**
* @param targetName 产生任务的对象名 * @param targetName 产生任务的对象名
*/ */
@ -39,7 +45,7 @@ final class CancelAllCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
removeAll(); removeAll();
if (mTaskEntity instanceof DownloadTaskEntity) { if (mTaskEntity instanceof DownloadTaskEntity) {
handleDownloadRemove(); handleDownloadRemove();
} else if (mTaskEntity instanceof UploadTaskEntity){ } else if (mTaskEntity instanceof UploadTaskEntity) {
handleUploadRemove(); handleUploadRemove();
} }
} }
@ -51,7 +57,7 @@ final class CancelAllCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
List<UploadTaskEntity> allEntity = DbEntity.findAllData(UploadTaskEntity.class); List<UploadTaskEntity> allEntity = DbEntity.findAllData(UploadTaskEntity.class);
if (allEntity == null || allEntity.size() == 0) return; if (allEntity == null || allEntity.size() == 0) return;
for (UploadTaskEntity entity : allEntity) { for (UploadTaskEntity entity : allEntity) {
CommonUtil.delUploadTaskConfig(mTaskEntity.removeFile, entity); CommonUtil.delUploadTaskConfig(removeFile, entity);
} }
} }
@ -62,7 +68,7 @@ final class CancelAllCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
List<DownloadTaskEntity> allEntity = DbEntity.findAllData(DownloadTaskEntity.class); List<DownloadTaskEntity> allEntity = DbEntity.findAllData(DownloadTaskEntity.class);
if (allEntity == null || allEntity.size() == 0) return; if (allEntity == null || allEntity.size() == 0) return;
for (DownloadTaskEntity entity : allEntity) { for (DownloadTaskEntity entity : allEntity) {
CommonUtil.delDownloadTaskConfig(mTaskEntity.removeFile, entity); CommonUtil.delDownloadTaskConfig(removeFile, entity);
} }
} }
} }

@ -24,7 +24,13 @@ import com.arialyy.aria.core.inf.AbsTaskEntity;
* Created by lyy on 2016/9/20. * Created by lyy on 2016/9/20.
* 取消命令 * 取消命令
*/ */
class CancelCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> { public class CancelCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
/**
* removeFile {@code true} 删除已经下载完成的任务不仅删除下载记录还会删除已经下载完成的文件{@code false}
* 如果文件已经下载完成只删除下载记录
*/
public boolean removeFile = false;
CancelCmd(String targetName, T entity) { CancelCmd(String targetName, T entity) {
super(targetName, entity); super(targetName, entity);
} }
@ -36,6 +42,7 @@ class CancelCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
task = createTask(); task = createTask();
} }
if (task != null) { if (task != null) {
mTaskEntity.removeFile = removeFile;
if (!TextUtils.isEmpty(mTargetName)) { if (!TextUtils.isEmpty(mTargetName)) {
task.setTargetName(mTargetName); task.setTargetName(mTargetName);
} }

@ -39,17 +39,21 @@ final class ResumeAllCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
private void resumeDownload() { private void resumeDownload() {
List<DownloadTaskEntity> dTaskEntity = List<DownloadTaskEntity> dTaskEntity =
DbEntity.findDatas(DownloadTaskEntity.class, "isGroupTask=?", "false"); DbEntity.findDatas(DownloadTaskEntity.class, "isGroupTask=?", "false");
for (DownloadTaskEntity te : dTaskEntity) { if (dTaskEntity != null && !dTaskEntity.isEmpty()) {
int state = te.getState(); for (DownloadTaskEntity te : dTaskEntity) {
if (state == IEntity.STATE_COMPLETE || state == IEntity.STATE_FAIL) continue; int state = te.getState();
resumeEntity(te); if (state == IEntity.STATE_COMPLETE || state == IEntity.STATE_FAIL) continue;
resumeEntity(te);
}
} }
List<DownloadGroupTaskEntity> groupTask = DbEntity.findAllData(DownloadGroupTaskEntity.class); List<DownloadGroupTaskEntity> groupTask = DbEntity.findAllData(DownloadGroupTaskEntity.class);
for (DownloadGroupTaskEntity te : groupTask) { if (groupTask != null && !groupTask.isEmpty()) {
int state = te.getState(); for (DownloadGroupTaskEntity te : groupTask) {
if (state == IEntity.STATE_COMPLETE || state == IEntity.STATE_FAIL) continue; int state = te.getState();
resumeEntity(te); if (state == IEntity.STATE_COMPLETE || state == IEntity.STATE_FAIL) continue;
resumeEntity(te);
}
} }
} }
@ -59,10 +63,12 @@ final class ResumeAllCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
private void resumeUpload() { private void resumeUpload() {
List<UploadTaskEntity> dTaskEntity = List<UploadTaskEntity> dTaskEntity =
DbEntity.findDatas(UploadTaskEntity.class, "isGroupTask=?", "false"); DbEntity.findDatas(UploadTaskEntity.class, "isGroupTask=?", "false");
for (UploadTaskEntity te : dTaskEntity) { if (dTaskEntity != null && !dTaskEntity.isEmpty()) {
int state = te.getState(); for (UploadTaskEntity te : dTaskEntity) {
if (state == IEntity.STATE_COMPLETE || state == IEntity.STATE_FAIL) continue; int state = te.getState();
resumeEntity(te); if (state == IEntity.STATE_COMPLETE || state == IEntity.STATE_FAIL) continue;
resumeEntity(te);
}
} }
} }

@ -24,6 +24,7 @@ import com.arialyy.aria.core.inf.AbsTaskEntity;
import com.arialyy.aria.core.inf.IEventListener; import com.arialyy.aria.core.inf.IEventListener;
import com.arialyy.aria.core.upload.UploadEntity; import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.ErrorHelp;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -33,7 +34,7 @@ import java.util.TimerTask;
/** /**
* Created by lyy on 2017/1/18. * Created by lyy on 2017/1/18.
* 下载线程 * 任务线程
*/ */
public abstract class AbsThreadTask<ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity<ENTITY>> public abstract class AbsThreadTask<ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity<ENTITY>>
implements Runnable { implements Runnable {
@ -59,6 +60,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsEntity, TASK_ENTITY extend
*/ */
public static String SERVER_CHARSET = "ISO-8859-1"; public static String SERVER_CHARSET = "ISO-8859-1";
private int mFailNum = 0; private int mFailNum = 0;
private String mTaskType;
private Timer mFailTimer; private Timer mFailTimer;
protected AbsThreadTask(StateConstance constance, IEventListener listener, protected AbsThreadTask(StateConstance constance, IEventListener listener,
@ -76,8 +78,11 @@ public abstract class AbsThreadTask<ENTITY extends AbsEntity, TASK_ENTITY extend
} }
mBufSize = manager.getDownloadConfig().getBuffSize(); mBufSize = manager.getDownloadConfig().getBuffSize();
setMaxSpeed(AriaManager.getInstance(AriaManager.APP).getDownloadConfig().getMsxSpeed()); setMaxSpeed(AriaManager.getInstance(AriaManager.APP).getDownloadConfig().getMsxSpeed());
mTaskType = getTaskType();
} }
protected abstract String getTaskType();
public void setMaxSpeed(double maxSpeed) { public void setMaxSpeed(double maxSpeed) {
if (-0.9999 < maxSpeed && maxSpeed < 0.00001) { if (-0.9999 < maxSpeed && maxSpeed < 0.00001) {
mSleepTime = 0; mSleepTime = 0;
@ -93,7 +98,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsEntity, TASK_ENTITY extend
} }
/** /**
* 停止下载 * 停止任务
*/ */
public void stop() { public void stop() {
synchronized (AriaManager.LOCK) { synchronized (AriaManager.LOCK) {
@ -124,7 +129,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsEntity, TASK_ENTITY extend
} }
/** /**
* 下载 * 执行
*/ */
protected void progress(long len) { protected void progress(long len) {
synchronized (AriaManager.LOCK) { synchronized (AriaManager.LOCK) {
@ -134,7 +139,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsEntity, TASK_ENTITY extend
} }
/** /**
* 取消下载 * 取消任务
*/ */
public void cancel() { public void cancel() {
synchronized (AriaManager.LOCK) { synchronized (AriaManager.LOCK) {
@ -185,6 +190,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsEntity, TASK_ENTITY extend
} else { } else {
Log.e(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】执行失败"); Log.e(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】执行失败");
mListener.onFail(true); mListener.onFail(true);
ErrorHelp.saveError(mTaskType, mEntity, "", CommonUtil.getPrintException(ex));
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();

@ -161,8 +161,10 @@ abstract class BaseGroupTarget<TARGET extends AbsTarget, TASK_ENTITY extends Abs
List<DownloadEntity> entities = mEntity.getSubTask(); List<DownloadEntity> entities = mEntity.getSubTask();
int i = 0; int i = 0;
for (DownloadEntity entity : entities) { for (DownloadEntity entity : entities) {
String newName = mSubTaskFileName.get(i); if (i < mSubTaskFileName.size()) {
updateSubFileName(entity, newName); String newName = mSubTaskFileName.get(i);
updateSubFileName(entity, newName);
}
i++; i++;
} }
} }

@ -16,7 +16,9 @@
package com.arialyy.aria.core.download; package com.arialyy.aria.core.download;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.text.TextUtils;
import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.command.normal.CancelAllCmd;
import com.arialyy.aria.core.command.normal.NormalCmdFactory; import com.arialyy.aria.core.command.normal.NormalCmdFactory;
import com.arialyy.aria.core.common.ProxyHelper; import com.arialyy.aria.core.common.ProxyHelper;
import com.arialyy.aria.core.inf.AbsEntity; import com.arialyy.aria.core.inf.AbsEntity;
@ -205,8 +207,10 @@ public class DownloadReceiver extends AbsReceiver {
*/ */
public DownloadTaskEntity getDownloadTask(String downloadUrl) { public DownloadTaskEntity getDownloadTask(String downloadUrl) {
CheckUtil.checkDownloadUrl(downloadUrl); CheckUtil.checkDownloadUrl(downloadUrl);
return DbEntity.findFirst(DownloadTaskEntity.class, "groupName=? and isGroupTask='false'", DownloadEntity entity = getDownloadEntity(downloadUrl);
downloadUrl); if (entity == null || TextUtils.isEmpty(entity.getDownloadPath())) return null;
return DbEntity.findFirst(DownloadTaskEntity.class, "key=? and isGroupTask='false'",
entity.getDownloadPath());
} }
/** /**
@ -295,9 +299,11 @@ public class DownloadReceiver extends AbsReceiver {
*/ */
@Override public void removeAllTask(boolean removeFile) { @Override public void removeAllTask(boolean removeFile) {
final AriaManager ariaManager = AriaManager.getInstance(AriaManager.APP); final AriaManager ariaManager = AriaManager.getInstance(AriaManager.APP);
ariaManager.setCmd(CommonUtil.createCmd(targetName, new DownloadTaskEntity(), CancelAllCmd cancelCmd =
NormalCmdFactory.TASK_CANCEL_ALL)).exe(); (CancelAllCmd) CommonUtil.createCmd(targetName, new DownloadTaskEntity(),
NormalCmdFactory.TASK_CANCEL_ALL);
cancelCmd.removeFile = removeFile;
ariaManager.setCmd(cancelCmd).exe();
Set<String> keys = ariaManager.getReceiver().keySet(); Set<String> keys = ariaManager.getReceiver().keySet();
for (String key : keys) { for (String key : keys) {
ariaManager.getReceiver().remove(key); ariaManager.getReceiver().remove(key);

@ -56,16 +56,22 @@ public class DownloadTarget
} }
private void initTask(DownloadEntity entity) { private void initTask(DownloadEntity entity) {
mTaskEntity = DbEntity.findFirst(DownloadTaskEntity.class, "key=? and isGroupTask='false'", mTaskEntity =
entity.getDownloadPath()); DbEntity.findFirst(DownloadTaskEntity.class, "key=? and isGroupTask='false' and url=?",
entity.getDownloadPath(), entity.getUrl());
if (mTaskEntity == null) { if (mTaskEntity == null) {
mTaskEntity = new DownloadTaskEntity(); mTaskEntity = new DownloadTaskEntity();
mTaskEntity.url = entity.getUrl();
mTaskEntity.key = entity.getDownloadPath(); mTaskEntity.key = entity.getDownloadPath();
mTaskEntity.entity = entity; mTaskEntity.entity = entity;
mTaskEntity.save(); mTaskEntity.save();
} } else if (mTaskEntity.entity == null || TextUtils.isEmpty(mTaskEntity.entity.getUrl())) {
if (mTaskEntity.entity == null || TextUtils.isEmpty(mTaskEntity.entity.getUrl())) { mTaskEntity.entity = entity;
mTaskEntity.save();
} else if (!mTaskEntity.entity.getUrl().equals(entity.getUrl())) { //处理地址切换而保存路径不变
mTaskEntity.entity.deleteData();
mTaskEntity.entity = entity; mTaskEntity.entity = entity;
entity.save();
mTaskEntity.save(); mTaskEntity.save();
} }

@ -27,6 +27,11 @@ public class DownloadTaskEntity extends AbsTaskEntity<DownloadEntity> {
@OneToOne(table = DownloadEntity.class, key = "downloadPath") public DownloadEntity entity; @OneToOne(table = DownloadEntity.class, key = "downloadPath") public DownloadEntity entity;
/**
* 任务的url
*/
public String url = "";
/** /**
* 所属的任务组组名如果不属于任务组则为null * 所属的任务组组名如果不属于任务组则为null
*/ */

@ -39,7 +39,7 @@ import java.util.concurrent.Executors;
* 任务组核心逻辑 * 任务组核心逻辑
*/ */
abstract class AbsGroupUtil implements IUtil { abstract class AbsGroupUtil implements IUtil {
private final String TAG = "DownloadGroupUtil"; private final String TAG = "AbsGroupUtil";
/** /**
* 任务组所有任务总大小 * 任务组所有任务总大小
*/ */
@ -96,6 +96,7 @@ abstract class AbsGroupUtil implements IUtil {
DbEntity.findDatas(DownloadTaskEntity.class, "groupName=?", mTaskEntity.key); DbEntity.findDatas(DownloadTaskEntity.class, "groupName=?", mTaskEntity.key);
if (tasks != null && !tasks.isEmpty()) { if (tasks != null && !tasks.isEmpty()) {
for (DownloadTaskEntity te : tasks) { for (DownloadTaskEntity te : tasks) {
te.removeFile = mTaskEntity.removeFile;
mTasksMap.put(te.getEntity().getUrl(), te); mTasksMap.put(te.getEntity().getUrl(), te);
} }
} }
@ -167,9 +168,21 @@ abstract class AbsGroupUtil implements IUtil {
private void delDownloadInfo() { private void delDownloadInfo() {
List<DownloadTaskEntity> tasks = List<DownloadTaskEntity> tasks =
DbEntity.findDatas(DownloadTaskEntity.class, "groupName=?", mTaskEntity.key); DbEntity.findDatas(DownloadTaskEntity.class, "groupName=?", mTaskEntity.key);
if (tasks == null || tasks.isEmpty()) return; if (tasks != null && !tasks.isEmpty()) {
for (DownloadTaskEntity taskEntity : tasks) { for (DownloadTaskEntity taskEntity : tasks) {
CommonUtil.delDownloadTaskConfig(taskEntity.removeFile, taskEntity); CommonUtil.delDownloadTaskConfig(mTaskEntity.removeFile, taskEntity);
}
}
File dir = new File(mTaskEntity.getEntity().getDirPath());
if (mTaskEntity.removeFile) {
if (dir.exists()) {
dir.delete();
}
} else {
if (!mTaskEntity.getEntity().isComplete()) {
dir.delete();
}
} }
} }

@ -27,6 +27,7 @@ import com.arialyy.aria.core.inf.IDownloadListener;
import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.BufferedRandomAccessFile; import com.arialyy.aria.util.BufferedRandomAccessFile;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.ErrorHelp;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -103,11 +104,11 @@ class Downloader extends AbsFileer<DownloadEntity, DownloadTaskEntity> {
return null; return null;
} }
private void failDownload(String errorMsg) { private void failDownload(String errorMsg) {
closeTimer(); closeTimer();
Log.e(TAG, errorMsg); Log.e(TAG, errorMsg);
mConstance.isRunning = false; mConstance.isRunning = false;
mListener.onFail(false); mListener.onFail(false);
ErrorHelp.saveError("", mEntity, "", errorMsg);
} }
} }

@ -18,6 +18,7 @@ package com.arialyy.aria.core.download.downloader;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupTaskEntity; import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
import com.arialyy.aria.core.download.DownloadTaskEntity; import com.arialyy.aria.core.download.DownloadTaskEntity;
import com.arialyy.aria.util.ErrorHelp;
import java.util.Set; import java.util.Set;
/** /**
@ -47,6 +48,7 @@ public class FtpDirDownloadUtil extends AbsGroupUtil {
@Override public void onFail(String url, String errorMsg) { @Override public void onFail(String url, String errorMsg) {
mListener.onFail(true); mListener.onFail(true);
ErrorHelp.saveError("FTP_DIR", mTaskEntity.getEntity(), "", errorMsg);
} }
}).start(); }).start();
} }

@ -148,4 +148,8 @@ class FtpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEntity> {
} }
} }
} }
@Override protected String getTaskType() {
return "FTP_DOWNLOAD";
}
} }

@ -126,4 +126,8 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEnt
} }
} }
} }
@Override protected String getTaskType() {
return "HTTP_DOWNLOAD";
}
} }

@ -20,6 +20,7 @@ import com.arialyy.aria.core.common.IUtil;
import com.arialyy.aria.core.download.DownloadTaskEntity; import com.arialyy.aria.core.download.DownloadTaskEntity;
import com.arialyy.aria.core.inf.AbsTaskEntity; import com.arialyy.aria.core.inf.AbsTaskEntity;
import com.arialyy.aria.core.inf.IDownloadListener; import com.arialyy.aria.core.inf.IDownloadListener;
import com.arialyy.aria.util.ErrorHelp;
/** /**
* Created by lyy on 2015/8/25. * Created by lyy on 2015/8/25.
@ -83,6 +84,7 @@ public class SimpleDownloadUtil implements IUtil, Runnable {
private void failDownload(String msg) { private void failDownload(String msg) {
mListener.onFail(true); mListener.onFail(true);
ErrorHelp.saveError("HTTP_DOWNLOAD", mTaskEntity.getEntity(), msg, "");
} }
@Override public void run() { @Override public void run() {

@ -19,8 +19,9 @@ import android.support.annotation.NonNull;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.common.RequestEnum; import com.arialyy.aria.core.command.normal.CancelCmd;
import com.arialyy.aria.core.command.normal.NormalCmdFactory; import com.arialyy.aria.core.command.normal.NormalCmdFactory;
import com.arialyy.aria.core.common.RequestEnum;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -205,10 +206,10 @@ public abstract class AbsTarget<TARGET extends AbsTarget, ENTITY extends AbsEnti
* {@code false}如果任务已经完成只删除任务数据库记录 * {@code false}如果任务已经完成只删除任务数据库记录
*/ */
public void cancel(boolean removeFile) { public void cancel(boolean removeFile) {
mTaskEntity.removeFile = removeFile; CancelCmd cancelCmd =
AriaManager.getInstance(AriaManager.APP) (CancelCmd) CommonUtil.createCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_CANCEL);
.setCmd(CommonUtil.createCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_CANCEL)) cancelCmd.removeFile = removeFile;
.exe(); AriaManager.getInstance(AriaManager.APP).setCmd(cancelCmd).exe();
} }
/** /**

@ -17,6 +17,7 @@ package com.arialyy.aria.core.inf;
import android.content.Context; import android.content.Context;
import android.os.Handler; import android.os.Handler;
import com.arialyy.aria.orm.Ignore;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
/** /**
@ -35,7 +36,6 @@ public abstract class AbsTask<ENTITY extends AbsEntity> implements ITask<ENTITY>
*/ */
private String mTargetName; private String mTargetName;
protected Context mContext; protected Context mContext;
protected boolean isHeighestTask = false; protected boolean isHeighestTask = false;
/** /**

@ -26,7 +26,9 @@ import com.arialyy.aria.core.inf.AbsTaskEntity;
import com.arialyy.aria.core.inf.IEntity; import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.queue.pool.BaseCachePool; import com.arialyy.aria.core.queue.pool.BaseCachePool;
import com.arialyy.aria.core.queue.pool.BaseExecutePool; import com.arialyy.aria.core.queue.pool.BaseExecutePool;
import java.security.Key;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map;
import java.util.Set; import java.util.Set;
/** /**
@ -66,13 +68,11 @@ abstract class AbsTaskQueue<TASK extends AbsTask, TASK_ENTITY extends AbsTaskEnt
* 停止所有任务 * 停止所有任务
*/ */
@Override public void stopAllTask() { @Override public void stopAllTask() {
mCachePool.clear();
for (String key : mExecutePool.getAllTask().keySet()) { for (String key : mExecutePool.getAllTask().keySet()) {
TASK task = mExecutePool.getAllTask().get(key); TASK task = mExecutePool.getAllTask().get(key);
if (task != null && task.isRunning()) task.stop(); if (task != null && task.isRunning()) task.stop();
} }
for (String key : mCachePool.getAllTask().keySet()) {
mCachePool.removeTask(key);
}
} }
@Override public int getMaxTaskNum() { @Override public int getMaxTaskNum() {

@ -53,6 +53,17 @@ public class BaseCachePool<TASK extends AbsTask> implements IPool<TASK> {
return mCacheMap; return mCacheMap;
} }
/**
* 清除所有缓存的任务
*/
public void clear(){
for (String key : mCacheMap.keySet()){
TASK task = mCacheMap.get(key);
mCacheQueue.remove(task);
mCacheMap.remove(key);
}
}
/** /**
* 将任务放在队首 * 将任务放在队首
*/ */

@ -45,6 +45,7 @@ class FtpThreadTask extends AbsThreadTask<UploadEntity, UploadTaskEntity> {
super(constance, listener, info); super(constance, listener, info);
} }
@Override public void run() { @Override public void run() {
FTPClient client = null; FTPClient client = null;
OutputStream os = null; OutputStream os = null;
@ -181,4 +182,9 @@ class FtpThreadTask extends AbsThreadTask<UploadEntity, UploadTaskEntity> {
client.allocate(mBufSize); client.allocate(mBufSize);
return client; return client;
} }
@Override protected String getTaskType() {
return "FTP_UPLOAD";
}
} }

@ -202,4 +202,8 @@ class HttpThreadTask extends AbsThreadTask<UploadEntity, UploadTaskEntity> {
mOutputStream.close(); mOutputStream.close();
return response.toString(); return response.toString();
} }
@Override protected String getTaskType() {
return "HTTP_UPLOAD";
}
} }

@ -16,6 +16,7 @@
package com.arialyy.aria.orm; package com.arialyy.aria.orm;
import android.text.TextUtils; import android.text.TextUtils;
import com.arialyy.aria.core.ErrorEntity;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity; import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.download.DownloadGroupTaskEntity; import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
@ -32,7 +33,7 @@ import java.util.Map;
class DBConfig { class DBConfig {
static Map<String, Class> mapping = new HashMap<>(); static Map<String, Class> mapping = new HashMap<>();
static String DB_NAME; static String DB_NAME;
static int VERSION = 12; static int VERSION = 14;
static { static {
if (TextUtils.isEmpty(DB_NAME)) { if (TextUtils.isEmpty(DB_NAME)) {
@ -50,5 +51,6 @@ class DBConfig {
mapping.put("DownloadGroupTaskEntity", DownloadGroupTaskEntity.class); mapping.put("DownloadGroupTaskEntity", DownloadGroupTaskEntity.class);
mapping.put("UploadEntity", UploadEntity.class); mapping.put("UploadEntity", UploadEntity.class);
mapping.put("UploadTaskEntity", UploadTaskEntity.class); mapping.put("UploadTaskEntity", UploadTaskEntity.class);
mapping.put("ErrorEntity", ErrorEntity.class);
} }
} }

@ -36,6 +36,13 @@ public class DbEntity {
} }
/**
* 清空表数据
*/
public static <T extends DbEntity> void clean(Class<T> clazz) {
DbUtil.getInstance().clean(clazz);
}
/** /**
* 直接执行sql语句 * 直接执行sql语句
*/ */

@ -64,6 +64,18 @@ public class DbUtil {
return INSTANCE; return INSTANCE;
} }
/**
* 清空表数据
*/
synchronized <T extends DbEntity> void clean(Class<T> clazz) {
checkDb();
String tableName = CommonUtil.getClassName(clazz);
if (tableExists(clazz)) {
String sql = "DELETE FROM " + tableName;
exeSql(sql);
}
}
/** /**
* 执行sql语句 * 执行sql语句
*/ */

@ -17,6 +17,7 @@ package com.arialyy.aria.orm;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
@ -91,11 +92,11 @@ final class SqlUtil {
throw new IllegalArgumentException("List中元素必须被@NormalList注解"); throw new IllegalArgumentException("List中元素必须被@NormalList注解");
} }
if (TextUtils.isEmpty(str)) return null; if (TextUtils.isEmpty(str)) return null;
String[] datas = str.split("$$"); String[] datas = str.split("\\$\\$");
List list = new ArrayList(); List list = new ArrayList();
String type = normalList.clazz().getName(); String type = normalList.clazz().getName();
for (String data : datas) { for (String data : datas) {
list.add(checkData(data, type)); list.add(checkData(type, data));
} }
return list; return list;
} }
@ -176,18 +177,14 @@ final class SqlUtil {
} }
private static Object checkData(String type, String data) { private static Object checkData(String type, String data) {
switch (type) { if (type.equalsIgnoreCase("java.lang.String")){
case "String": return data;
return data; }else if (type.equalsIgnoreCase("int") || type.equals("java.lang.Integer")){
case "int": return Integer.parseInt(data);
case "Integer": }else if (type.equalsIgnoreCase("double") || type.equals("java.lang.Double")){
return Integer.parseInt(data); return Double.parseDouble(data);
case "double": }else if (type.equalsIgnoreCase("float") || type.equals("java.lang.Float")){
case "Double": return Float.parseFloat(data);
return Double.parseDouble(data);
case "float":
case "Float":
return Float.parseFloat(data);
} }
return null; return null;
} }

@ -27,10 +27,13 @@ import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.command.normal.NormalCmdFactory; import com.arialyy.aria.core.command.normal.NormalCmdFactory;
import com.arialyy.aria.core.command.normal.AbsNormalCmd; import com.arialyy.aria.core.command.normal.AbsNormalCmd;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
import com.arialyy.aria.core.download.DownloadTaskEntity; import com.arialyy.aria.core.download.DownloadTaskEntity;
import com.arialyy.aria.core.inf.AbsTaskEntity; import com.arialyy.aria.core.inf.AbsTaskEntity;
import com.arialyy.aria.core.upload.UploadEntity; import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.upload.UploadTaskEntity; import com.arialyy.aria.core.upload.UploadTaskEntity;
import com.arialyy.aria.orm.DbEntity;
import java.io.File; import java.io.File;
import java.io.FileFilter; import java.io.FileFilter;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -214,7 +217,7 @@ public class CommonUtil {
} }
/** /**
* 删除上传任务的配置包括 * 删除上传任务的配置
* *
* @param removeFile {@code true} 不仅删除任务数据库记录还会删除已经删除完成的文件 * @param removeFile {@code true} 不仅删除任务数据库记录还会删除已经删除完成的文件
* {@code false}如果任务已经完成只删除任务数据库记录 * {@code false}如果任务已经完成只删除任务数据库记录
@ -236,7 +239,7 @@ public class CommonUtil {
} }
/** /**
* 删除下载任务的配置包括 * 删除下载任务的配置
* *
* @param removeFile {@code true} 不仅删除任务数据库记录还会删除已经下载完成的文件 * @param removeFile {@code true} 不仅删除任务数据库记录还会删除已经下载完成的文件
* {@code false}如果任务已经完成只删除任务数据库记录 * {@code false}如果任务已经完成只删除任务数据库记录

@ -0,0 +1,58 @@
/*
* 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.util;
import com.arialyy.aria.core.ErrorEntity;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.inf.AbsEntity;
import com.arialyy.aria.core.upload.UploadEntity;
/**
* Created by Aria.Lao on 2017/8/29.
* 错误帮助类
*/
public class ErrorHelp {
/**
* 保存错误信息
*
* @param taskType 任务类型
* @param entity 任务实体
* @param msg 错误提示
* @param ex 异常
*/
public static void saveError(String taskType, AbsEntity entity, String msg, String ex) {
ErrorEntity errorEntity = new ErrorEntity();
errorEntity.insertTime = System.currentTimeMillis();
errorEntity.err = ex;
errorEntity.msg = msg;
errorEntity.taskType = taskType;
String name = "";
String key = entity.getKey();
if (entity instanceof DownloadEntity) {
name = ((DownloadEntity) entity).getFileName();
} else if (entity instanceof DownloadGroupEntity) {
name = ((DownloadGroupEntity) entity).getGroupName();
} else if (entity instanceof UploadEntity) {
name = ((UploadEntity) entity).getFileName();
}
errorEntity.taskName = name;
errorEntity.key = key;
errorEntity.insert();
}
}

@ -0,0 +1,29 @@
## 开发日志
+ v_3.2.17 修复一个版本兼容性问题,线程中使用Aria出错问题
+ v_3.2.15 修复大型文件分段下载失败的问题,修复中文URL乱码问题
+ v_3.2.14 修复恢复所有任务的api接口,不能恢复下载组任务的问题
+ v_3.2.13 修复某些服务器头文件返回描述文件格式错误的问题、修复有时删除任务,需要两次删除的问题
+ v_3.2.12 实现FTP多线程断点续传下载,FTP断点续传上传功能
+ v_3.2.9 修复任务组下载完成两次回掉的问题,修复又是获取不到下载状态的问题
+ v_3.2.8 修复下载超过2G大小的文件失败的问题
+ v_3.2.7 移除设置文件名的api接口,修复断开网络时出现的进度条错误的问题
+ v_3.2.6 移除广播事件,增加任务组下载功能
+ v_3.1.9 修复stopAll队列没有任务时崩溃的问题,增加针对单个任务监听的功能
+ v_3.1.7 修复某些文件下载不了的bug,增加apt注解方法,事件获取更加简单了
+ v_3.1.6 取消任务时onTaskCancel回调两次的bug
+ v_3.1.5 优化代码结构,增加优先下载任务功能。
+ v_3.1.4 修复快速切换,暂停、恢复功能时,概率性出现的重新下载问题,添加onPre()回调,onPre()用于请求地址之前执行界面UI更新操作。
+ v_3.1.0 添加Aria配置文件,优化代码
+ v_3.0.3 修复暂停后删除任务,闪退问题,添加删除记录的api
+ v_3.0.2 支持30x重定向链接下载
+ v_3.0.0 添加上传任务支持,修复一些已发现的bug
+ v_2.4.4 修复不支持断点的下载链接拿不到文件大小的问题
+ v_2.4.3 修复404链接卡顿的问题
+ v_2.4.2 修复失败重试无效的bug
+ v_2.4.1 修复下载慢的问题,修复application、service 不能使用的问题
+ v_2.4.0 支持https链接下载
+ v_2.3.8 修复数据错乱的bug、添加fragment支持
+ v_2.3.6 添加dialog、popupWindow支持
+ v_2.3.3 添加断点支持、修改下载逻辑,让使用更加简单、修复一个内存泄露的bug
+ v_2.3.1 重命名为Aria,下载流程简化
+ v_2.1.1 增加,选择最大下载任务数接口

@ -3,6 +3,7 @@
## [中文文档](https://github.com/AriaLyy/Aria/blob/master/CHINESE_README.md) ## [中文文档](https://github.com/AriaLyy/Aria/blob/master/CHINESE_README.md)
Aria project is from the moment taht the work encountered in a file download management needs adn i was tortured at the time of the pain.</br> Aria project is from the moment taht the work encountered in a file download management needs adn i was tortured at the time of the pain.</br>
Since then i have a idea which is to program a simple and easy to use,stable and efficient download framework. Since then i have a idea which is to program a simple and easy to use,stable and efficient download framework.
Aria experienced 1.0 to 3.0 development, be more and more close to the original set by the target. Aria experienced 1.0 to 3.0 development, be more and more close to the original set by the target.
@ -25,7 +26,7 @@ Aria has the following characteristics:
How do we to use Aria? How do we to use Aria?
* [download](#Using) * [download](#Using)
* [upload](#Upload) * [upload](#Upload) s
If you feel that Aria is helpful to you, your star and issues will be the greatest support for me.`^_^` If you feel that Aria is helpful to you, your star and issues will be the greatest support for me.`^_^`

@ -0,0 +1,348 @@
# Aria
![图标](https://github.com/AriaLyy/DownloadUtil/blob/v_2.0/app/src/main/res/mipmap-hdpi/ic_launcher.png)</br>
## [ENGLISH DOC](https://github.com/AriaLyy/Aria/blob/master/ENGLISH_README.md)</br>
Aria项目源于工作中遇到的一个文件下载管理的需求,当时被下载折磨的痛不欲生,从那时起便萌生了编写一个简单易用,稳当高效的下载框架,aria经历了1.0到3.0的开发,算是越来越接近当初所制定的目标了。
Aria有以下特点:
+ 简单、方便
- 可以在Activity、Service、Fragment、Dialog、popupWindow、Notification等组件中使用
- 支持任务自动调度,使用者不需要关心任务状态切换的逻辑
- [通过Aria的事件,能很容易获取当前下载任务的下载状态](#下载状态获取)
- [一句代码加可以获取当前的下载速度](#任务实体常用数据)
- [一句代码就可以动态设置最大下载数](#代码中设置参数)
- [一句代码实现速度限制](#常用接口)
- [通过修改配置文件很容易就能修改下载线程数](#配置文件设置参数)
- [优先下载某一个任务](#常用接口)
- [支持任务组下载,多个任务可共享一个progress](#一组任务下载)
+ 支持https地址下载
- 在配置文件中很容易就可以设置CA证书的信息
+ 支持300、301、302重定向下载链接下载
+ 支持上传操作
+ 支持FTP断点续传下载、上传
- [FTP 文件夹下载](#文件夹下载)
- [FTP 单文件下载](#单文件下载)
- [FTP 单文件上传](#单文件上传)
如果你觉得Aria对你有帮助,您的star和issues将是对我最大支持.`^_^`
## 下载
[![Download](https://api.bintray.com/packages/arialyy/maven/AriaApi/images/download.svg)](https://bintray.com/arialyy/maven/AriaApi/_latestVersion)
[![Download](https://api.bintray.com/packages/arialyy/maven/AriaCompiler/images/download.svg)](https://bintray.com/arialyy/maven/AriaCompiler/_latestVersion)
```java
compile 'com.arialyy.aria:aria-core:3.2.20'
annotationProcessor 'com.arialyy.aria:aria-compiler:3.2.20'
```
## 示例
![多任务下载](https://github.com/AriaLyy/DownloadUtil/blob/master/img/download_img.gif)
![网速下载限制](https://github.com/AriaLyy/DownloadUtil/blob/master/img/max_speed.gif)
![下载任务组](https://github.com/AriaLyy/DownloadUtil/blob/master/img/download_group.gif)
## 性能
![性能展示](https://github.com/AriaLyy/DownloadUtil/blob/master/img/performance.png)
***
## 使用
由于Aria涉及到文件和网络的操作,因此需要你在manifest文件中添加以下权限,如果你希望在6.0以上的系统中使用Aria,那么你需要动态向安卓系统申请文件系统读写权限,[如何使用安卓系统权限](https://developer.android.com/training/permissions/index.html?hl=zh-cn)
```xml
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
```
## 使用Aria进行下载
### 普通任务下载
* 下载\恢复下载
```java
Aria.download(this)
.load(DOWNLOAD_URL) //读取下载地址
.setDownloadPath(DOWNLOAD_PATH) //设置文件保存的完整路径
.start(); //启动下载
```
* 暂停
```java
Aria.download(this).load(DOWNLOAD_URL).pause();
```
* 取消下载
```java
Aria.download(this).load(DOWNLOAD_URL).cancel();
```
### 一组任务下载
任务组的下载和普通任务的下载基本上差不多,区别在于,任务组下载不需要对每一个子任务设置保存路径,**但是需要设置任务组保存文件夹路径,所有子任务都保存在该文件夹下**
* 下载\恢复下载
```java
Aria.download(this)
.load(urls) //设置一主任务,参数为List<String>
.setDownloadDirPath(groupDirPath) //设置任务组的文件夹路径
.start(); //启动下载
```
* 暂停
```java
Aria.download(this).load(urls).pause();
```
* 取消下载
```java
Aria.download(this).load(urls).cancel();
```
## 上传
* 添加任务(只添加,不上传)
```java
Aria.upload(this)
.load(filePath) //文件路径
.setUploadUrl(uploadUrl) //上传路径
.setAttachment(fileKey) //服务器读取文件的key
.add();
```
* 上传
```java
Aria.upload(this)
.load(filePath) //文件路径
.setUploadUrl(uploadUrl) //上传路径
.setAttachment(fileKey) //服务器读取文件的key
.start();
```
* 取消上传
```java
Aria.upload(this).load(filePath).cancel();
```
## FTP
### 单文件下载
* 开始\恢复下载
```java
Aria.download(this)
.loadFtp("ftp://172.18.104.129:21/haha/large.rar")
.login("lao", "123456") //登录FTP服务器
.setDownloadPath("/mnt/sdcard/") //设置文件保存文件夹
.start();
```
* 暂停
```java
Aria.download(this).loadFtp(URL).stop();
```
* 删除任务
```java
Aria.download(this).loadFtp(URL).cancel();
```
### 文件夹下载
* 开始\恢复下载
```java
Aria.download(this)
.loadFtpDir("ftp://172.18.104.129:21/haha/")
.setDownloadDirPath(downloadPath)
.login("lao", "123456")
.start();
```
* 暂停
```java
Aria.download(this).loadFtpDir(dir).stop();
```
* 删除任务
```java
Aria.download(this).loadFtpDir(dir).cancel();
```
### 单文件上传
* 开始\恢复上传
```java
Aria.upload(this)
.loadFtp("/mnt/sdcard/gggg.apk") //上传文件路径
.setUploadUrl(URL) //上传的ftp服务器地址
.login("lao", "123456")
.start();
```
* 暂停
```java
Aria.upload(this).loadFtp(FILE_PATH).stop();
```
* 删除任务
```java
Aria.upload(this).loadFtp(FILE_PATH).cancel();
```
## 任务状态获取
如果你希望读取任务进度或任务的信息,那么你需要创建事件类,并在onResume(Activity、Fragment)或构造函数(Dialog、PopupWindow),将该事件类注册到Aria管理器。
1. 将对象注册到Aria
`Aria.download(this).register();`或`Aria.upload(this).register();`
```java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Aria.download(this).register();
}
```
2. 使用 `@Download``@Upload``@DownloadGroup` 注解你的函数
**注意:**
- 注解回掉采用Apt的方式实现,所以,你不需要担心这会影响你机器的性能
- 被注解的方法**不能被private修饰**
- 被注解的方法**只能有一个参数,并且参数类型必须是`DownloadTask`或`UploadTask`或`DownloadGroupTask`**
- 方法名可以为任意字符串
3. 除了在widget(Activity、Fragment、Dialog、Popupwindow)中使用注解方法外,你还可以在Service、Notification等组件中使用注解函数。
| 注解 | 说明 | 示例 |
| ------| ------ | ------ |
| `@Download.onPre` | 预处理的注解,在任务为开始前回调(一般在此处预处理UI界面) | `@Download.onPre void onPre(DownloadTask task) {}` |
| `@Download.onTaskStart` | 任务开始时的注解,新任务开始时进行回调 | `@Download.onTaskStart void taskStart(DownloadTask task) {}`|
| `@Download.onTaskResume` | 任务恢复时的注解,任务从停止恢复到运行前进行回调 | `@Download.onTaskResume void taskResume(DownloadTask task) {}` |
| ` @Download.onTaskRunning` | 任务执行时的注解,任务正在执行时进行回调 | `@Download.onTaskRunning void running(DownloadTask task) {}` |
| `@Download.onTaskStop` | 任务停止时的注解,任务停止时进行回调 | `@Download.onTaskStop void taskStop(DownloadTask task) {}` |
| `@Download.onTaskCancel` | 任务被删除时的注解,任务被删除时进行回调 | `@Download.onTaskCancel void taskCancel(DownloadTask task) {}` |
| `@Download.onTaskFail` | 任务失败时的注解,任务执行失败时进行回调 | `@Download.onTaskFail void taskFail(DownloadTask task) {}` |
| ` @Download.onTaskComplete` | 任务完成时的注解,任务完成时进行回调 | ` @Download.onTaskComplete void taskComplete(DownloadTask task) {}` |
| `@Download.onNoSupportBreakPoint` | 这是一个特殊的注解,用于处理不支持断点续传的任务 | `@Download.onNoSupportBreakPoint void onNoSupportBreakPoint(DownloadTask task) {}` |
**TIP:如果你子希望对单个任务,或某一些特定任务设置监听器。** <br>
**在注解中添加任务的下载地址,则表示只有该任务才会触发被注解的方法**。
```java
@Download.onTaskRunning({
"https://test.xx.apk",
"http://test.xx2.apk"
}) void taskRunning(DownloadTask task) {
mAdapter.setProgress(task.getDownloadEntity());
}
```
在上面的例子中,只有下载地址是`https://test.xx.apk`和`http://test.xx2.apk`才会触发
`taskRunning(DownloadTask task)`方法。
## Aria参数配置
#### 配置文件设置参数
创建 [aria_config.xml](https://github.com/AriaLyy/Aria/blob/master/app/src/main/assets/aria_config.xml) 文件,将其放在`assets`目录下
#### 代码中设置参数
除了文件方式外修改Aria参数外,同样的,你也可以在代码中动态修改Aria参数</br>
通过`Aria.get(this).getDownloadConfig()`或`Aria.get(this).getUploadConfig()`直接获取配置文件,然后修改参数</br>
如以下所示:
```java
// 修改最大下载数,调用完成后,立即生效
// 如当前下载任务数是4,修改完成后,当前任务数会被Aria自动调度任务数
Aria.get(this).getDownloadConfig().setMaxTaskNum(3);
```
### 常用接口
| api | 说明 |
| ------| ------ |
| `Aria.download(this).stopAllTask();` | 停止所有正在下载的任务 |
| `Aria.download(this).resumeAllTask();` | 恢复所有停止的任务 |
| `Aria.download(this).removeAllTask();` | 删除所有任务</br> 1、如果任务为完成,会删除没有完成的文件</br> 2、如果使用`removeAllTask(true)`方法,会将已经下载完成和未完成的文件删除</br> 3、如果是上传任务,不会删除本地的上传文件,但如果使用`removeAllTask(true)`,同样会删除本地上传文件 |
| `Aria.download(this).setMaxSpeed(speed)` | 限制单个任务的上传、下载的最大速度(单位为 kb) |
| `Aria.download(this).load(DOWNLOAD_URL)`<br>`.setExtendField(str)` | 设置扩展字段,有的时候,你可能希望在下载的时候存放一些自己的数据,这时你可以调用该接口将数据保存下来(如果你数据比较多,或者数据比较复杂,你可以先把数据转换为**JSON**,然后再将其存到Aria的下载实体中) |
| `Aria.download(this).load(DOWNLOAD_URL)`<br>`.getExtendField()` | 获取保存的扩展字段 |
| `Aria.download(this).load(DOWNLOAD_URL)`<br>`.setDownloadPath(PATH).setHighestPriority();` | 将任务设置为最高优先级任务,最高优先级任务有以下特点:<br>1、在下载队列中,有且只有一个最高优先级任务<br> 2、最高优先级任务会一直存在,直到用户手动暂停或任务完成<br>3、任务调度器不会暂停最高优先级任务<br>4、用户手动暂停或任务完成后,第二次重新执行该任务,该命令将失效<br>5、如果下载队列中已经满了,则会停止队尾的任务,当高优先级任务完成后,该队尾任务将自动执行<br>6、把任务设置为最高优先级任务后,将自动执行任务,不需要重新调用start()启动任务 |
### 任务实体常用数据
* 获取当前任务的下载速度<br>
速度参数有点特殊,需要[下载事件支持](#下载状态获取)
``` java
@Override public void onTaskRunning(DownloadTask task) {
//如果你打开了速度单位转换配置,将可以通过以下方法获取带单位的下载速度,如:1 mb/s
String convertSpeed = task.getConvertSpeed();
//如果你有自己的单位格式,可以通过以下方法获取原始byte长度
long speed = task.getSpeed();
}
```
* 获取下载的文件大小、当前进度百分比</br>
同样的,你也可以在DownloadTask对象中获取下载的文件大小
```
@Override public void onTaskRunning(DownloadTask task) {
 //获取文件大小
long fileSize = task.getFileSize();
//获取单位转换后的文件大小
String fileSize1 = task.getConvertFileSize();
//当前进度百分比
int percent = task.getPercent();
}
```
## 混淆配置
```
-dontwarn com.arialyy.aria.**
-keep class com.arialyy.aria.**{*;}
-keep class **$$DownloadListenerProxy{ *; }
-keep class **$$UploadListenerProxy{ *; }
-keep class **$$DownloadGroupListenerProxy{ *; }
-keepclasseswithmembernames class * {
@Download.* <methods>;
@Upload.* <methods>;
@DownloadGroup.* <methods>;
}
```
## 其他
有任何问题,可以在[issues](https://github.com/AriaLyy/Aria/issues)给我留言反馈。</br>
**Aria交流群:524329160**
***
## 后续版本开发规划
* ~~代码优化~~
## 开发日志
+ v_3.2.17 修复一个版本兼容性问题,线程中使用Aria出错问题
+ v_3.2.15 修复大型文件分段下载失败的问题,修复中文URL乱码问题
+ v_3.2.14 修复恢复所有任务的api接口,不能恢复下载组任务的问题
+ v_3.2.13 修复某些服务器头文件返回描述文件格式错误的问题、修复有时删除任务,需要两次删除的问题
+ v_3.2.12 实现FTP多线程断点续传下载,FTP断点续传上传功能
+ v_3.2.9 修复任务组下载完成两次回掉的问题,修复又是获取不到下载状态的问题
+ v_3.2.8 修复下载超过2G大小的文件失败的问题
+ v_3.2.7 移除设置文件名的api接口,修复断开网络时出现的进度条错误的问题
+ v_3.2.6 移除广播事件,增加任务组下载功能
+ v_3.1.9 修复stopAll队列没有任务时崩溃的问题,增加针对单个任务监听的功能
+ v_3.1.7 修复某些文件下载不了的bug,增加apt注解方法,事件获取更加简单了
+ v_3.1.6 取消任务时onTaskCancel回调两次的bug
+ v_3.1.5 优化代码结构,增加优先下载任务功能。
+ v_3.1.4 修复快速切换,暂停、恢复功能时,概率性出现的重新下载问题,添加onPre()回调,onPre()用于请求地址之前执行界面UI更新操作。
+ v_3.1.0 添加Aria配置文件,优化代码
License
-------
Copyright 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.

@ -6,40 +6,30 @@ Aria项目源于工作中遇到的一个文件下载管理的需求,当时被
Aria有以下特点: Aria有以下特点:
+ 简单、方便 + 简单、方便
- 可以在Activity、Service、Fragment、Dialog、popupWindow、Notification等组件中使用 - 可以在Activity、Service、Fragment、Dialog、popupWindow、Notification等组件中使用
- 支持任务自动调度,使用者不需要关心任务状态切换的逻辑 - 一行代码实现HTTP\FTP断线续传、多任务自动调度
- [通过Aria的事件,能很容易获取当前下载任务的下载状态](#下载状态获取) - 一行代码实现HTTP任务组\FTP文件夹下载
- [一句代码加可以获取当前的下载速度](#任务实体常用数据) - 一行代码实现HTTP\FTP断点续传上传
- [一句代码就可以动态设置最大下载数](#代码中设置参数)
- [一句代码实现速度限制](#常用接口)
- [通过修改配置文件很容易就能修改下载线程数](#配置文件设置参数)
- [优先下载某一个任务](#常用接口)
- [支持任务组下载,多个任务可共享一个progress](#一组任务下载)
+ 支持https地址下载 + 支持https地址下载
- 在配置文件中很容易就可以设置CA证书的信息 - 在配置文件中很容易就可以设置CA证书的信息
+ 支持300、301、302重定向下载链接下载 + 支持300、301、302重定向下载链接下载
+ 支持上传操作
+ 支持FTP断点续传下载、上传 [怎样使用Aria?](#使用)
- [FTP 文件夹下载](#文件夹下载)
- [FTP 单文件下载](#单文件下载)
- [FTP 单文件上传](#单文件上传)
如果你觉得Aria对你有帮助,您的star和issues将是对我最大支持.`^_^` 如果你觉得Aria对你有帮助,您的star和issues将是对我最大支持.`^_^`
## 下载
[![Download](https://api.bintray.com/packages/arialyy/maven/AriaApi/images/download.svg)](https://bintray.com/arialyy/maven/AriaApi/_latestVersion)
[![Download](https://api.bintray.com/packages/arialyy/maven/AriaCompiler/images/download.svg)](https://bintray.com/arialyy/maven/AriaCompiler/_latestVersion)
```java
compile 'com.arialyy.aria:aria-core:3.2.22'
annotationProcessor 'com.arialyy.aria:aria-compiler:3.2.22'
```
## 示例 ## 示例
![多任务下载](https://github.com/AriaLyy/DownloadUtil/blob/master/img/download_img.gif) ![多任务下载](https://github.com/AriaLyy/DownloadUtil/blob/master/img/download_img.gif)
![网速下载限制](https://github.com/AriaLyy/DownloadUtil/blob/master/img/max_speed.gif) ![网速下载限制](https://github.com/AriaLyy/DownloadUtil/blob/master/img/max_speed.gif)
![下载任务组](https://github.com/AriaLyy/DownloadUtil/blob/master/img/download_group.gif) ![下载任务组](https://github.com/AriaLyy/DownloadUtil/blob/master/img/download_group.gif)
## 性能
![性能展示](https://github.com/AriaLyy/DownloadUtil/blob/master/img/performance.png) ## 下载
[![Download](https://api.bintray.com/packages/arialyy/maven/AriaApi/images/download.svg)](https://bintray.com/arialyy/maven/AriaApi/_latestVersion)
[![Download](https://api.bintray.com/packages/arialyy/maven/AriaCompiler/images/download.svg)](https://bintray.com/arialyy/maven/AriaCompiler/_latestVersion)
```java
compile 'com.arialyy.aria:aria-core:3.2.25'
annotationProcessor 'com.arialyy.aria:aria-compiler:3.2.25'
```
*** ***
## 使用 ## 使用
@ -50,243 +40,54 @@ annotationProcessor 'com.arialyy.aria:aria-compiler:3.2.22'
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
``` ```
## 使用Aria进行下载 ## 使用Aria
### 普通任务下载 ### 基本使用
* 下载\恢复下载 例子为单任务下载,只需要很简单的代码,便可以实现下载功能
```java ```java
Aria.download(this) Aria.download(this)
.load(DOWNLOAD_URL) //读取下载地址 .load(DOWNLOAD_URL) //读取下载地址
.setDownloadPath(DOWNLOAD_PATH) //设置文件保存的完整路径 .setDownloadPath(DOWNLOAD_PATH) //设置文件保存的完整路径
.start(); //启动下载
```
* 暂停
```java
Aria.download(this).load(DOWNLOAD_URL).pause();
```
* 取消下载
```java
Aria.download(this).load(DOWNLOAD_URL).cancel();
```
### 一组任务下载
任务组的下载和普通任务的下载基本上差不多,区别在于,任务组下载不需要对每一个子任务设置保存路径,**但是需要设置任务组保存文件夹路径,所有子任务都保存在该文件夹下**
* 下载\恢复下载
```java
Aria.download(this)
.load(urls) //设置一主任务,参数为List<String>
.setDownloadDirPath(groupDirPath) //设置任务组的文件夹路径
.start(); //启动下载 .start(); //启动下载
``` ```
* 暂停
```java
Aria.download(this).load(urls).pause();
```
* 取消下载
```java
Aria.download(this).load(urls).cancel();
```
## 上传
* 添加任务(只添加,不上传)
```java
Aria.upload(this)
.load(filePath) //文件路径
.setUploadUrl(uploadUrl) //上传路径
.setAttachment(fileKey) //服务器读取文件的key
.add();
```
* 上传
```java
Aria.upload(this)
.load(filePath) //文件路径
.setUploadUrl(uploadUrl) //上传路径
.setAttachment(fileKey) //服务器读取文件的key
.start();
```
* 取消上传
```java
Aria.upload(this).load(filePath).cancel();
```
## FTP
### 单文件下载
* 开始\恢复下载
```java
Aria.download(this)
.loadFtp("ftp://172.18.104.129:21/haha/large.rar")
.login("lao", "123456") //登录FTP服务器
.setDownloadPath("/mnt/sdcard/") //设置文件保存文件夹
.start();
```
* 暂停
```java
Aria.download(this).loadFtp(URL).stop();
```
* 删除任务 ### 任务状态的获取
```java 基于解耦合的考虑,Aria的下载功能是和状态获取相分离的,状态的获取并不会集成到链式代码中,但是Aria提供了另一种更简单更灵活的方案。
Aria.download(this).loadFtp(URL).cancel(); 通过注解,你可以很容易获取任务的所有状态。
```
### 文件夹下载
* 开始\恢复下载
```java
Aria.download(this)
.loadFtpDir("ftp://172.18.104.129:21/haha/")
.setDownloadDirPath(downloadPath)
.login("lao", "123456")
.start();
```
* 暂停
```java
Aria.download(this).loadFtpDir(dir).stop();
```
* 删除任务
```java
Aria.download(this).loadFtpDir(dir).cancel();
```
### 单文件上传
* 开始\恢复上传
```java
Aria.upload(this)
.loadFtp("/mnt/sdcard/gggg.apk") //上传文件路径
.setUploadUrl(URL) //上传的ftp服务器地址
.login("lao", "123456")
.start();
```
* 暂停
```java
Aria.upload(this).loadFtp(FILE_PATH).stop();
```
* 删除任务
```java
Aria.upload(this).loadFtp(FILE_PATH).cancel();
```
## 任务状态获取
如果你希望读取任务进度或任务的信息,那么你需要创建事件类,并在onResume(Activity、Fragment)或构造函数(Dialog、PopupWindow),将该事件类注册到Aria管理器。
1. 将对象注册到Aria 1. 将对象注册到Aria
```java
`Aria.download(this).register();`或`Aria.upload(this).register();` protected void onCreate(Bundle savedInstanceState) {
```java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Aria.download(this).register(); Aria.download(this).register();
} }
``` ```
2. 使用 `@Download``@Upload``@DownloadGroup` 注解你的函数
2. 通过注解获取任务执行状态
**注意:** **注意:**
- 注解回掉采用Apt的方式实现,所以,你不需要担心这会影响你机器的性能 - 注解回掉采用Apt的方式实现,所以,你不需要担心这会影响你机器的性能
- 被注解的方法**不能被private修饰** - 被注解的方法**不能被private修饰**
- 被注解的方法**只能有一个参数,并且参数类型必须是`DownloadTask`或`UploadTask`或`DownloadGroupTask`** - 被注解的方法**只能有一个参数,并且参数类型必须是`DownloadTask`或`UploadTask`或`DownloadGroupTask`**
- 方法名可以为任意字符串 - 方法名可以为任意字符串
3. 除了在widget(Activity、Fragment、Dialog、Popupwindow)中使用注解方法外,你还可以在Service、Notification等组件中使用注解函数。
| 注解 | 说明 | 示例 |
| ------| ------ | ------ |
| `@Download.onPre` | 预处理的注解,在任务为开始前回调(一般在此处预处理UI界面) | `@Download.onPre void onPre(DownloadTask task) {}` |
| `@Download.onTaskStart` | 任务开始时的注解,新任务开始时进行回调 | `@Download.onTaskStart void taskStart(DownloadTask task) {}`|
| `@Download.onTaskResume` | 任务恢复时的注解,任务从停止恢复到运行前进行回调 | `@Download.onTaskResume void taskResume(DownloadTask task) {}` |
| ` @Download.onTaskRunning` | 任务执行时的注解,任务正在执行时进行回调 | `@Download.onTaskRunning void running(DownloadTask task) {}` |
| `@Download.onTaskStop` | 任务停止时的注解,任务停止时进行回调 | `@Download.onTaskStop void taskStop(DownloadTask task) {}` |
| `@Download.onTaskCancel` | 任务被删除时的注解,任务被删除时进行回调 | `@Download.onTaskCancel void taskCancel(DownloadTask task) {}` |
| `@Download.onTaskFail` | 任务失败时的注解,任务执行失败时进行回调 | `@Download.onTaskFail void taskFail(DownloadTask task) {}` |
| ` @Download.onTaskComplete` | 任务完成时的注解,任务完成时进行回调 | ` @Download.onTaskComplete void taskComplete(DownloadTask task) {}` |
| `@Download.onNoSupportBreakPoint` | 这是一个特殊的注解,用于处理不支持断点续传的任务 | `@Download.onNoSupportBreakPoint void onNoSupportBreakPoint(DownloadTask task) {}` |
**TIP:如果你子希望对单个任务,或某一些特定任务设置监听器。** <br>
**在注解中添加任务的下载地址,则表示只有该任务才会触发被注解的方法**。
```java
@Download.onTaskRunning({
"https://test.xx.apk",
"http://test.xx2.apk"
}) void taskRunning(DownloadTask task) {
mAdapter.setProgress(task.getDownloadEntity());
}
```
在上面的例子中,只有下载地址是`https://test.xx.apk`和`http://test.xx2.apk`才会触发
`taskRunning(DownloadTask task)`方法。
## Aria参数配置
#### 配置文件设置参数
创建 [aria_config.xml](https://github.com/AriaLyy/Aria/blob/master/app/src/main/assets/aria_config.xml) 文件,将其放在`assets`目录下
#### 代码中设置参数
除了文件方式外修改Aria参数外,同样的,你也可以在代码中动态修改Aria参数</br>
通过`Aria.get(this).getDownloadConfig()`或`Aria.get(this).getUploadConfig()`直接获取配置文件,然后修改参数</br>
如以下所示:
```java ```java
// 修改最大下载数,调用完成后,立即生效 //在这里处理任务执行中的状态,如进度进度条的刷新
// 如当前下载任务数是4,修改完成后,当前任务数会被Aria自动调度任务数 @Download.onTaskRunning(DOWNLOAD_URL) protected void running(DownloadTask task) {
Aria.get(this).getDownloadConfig().setMaxTaskNum(3); int p = task.getPercent(); //任务进度百分比
``` String speed = task.getConvertSpeed(); //转换单位后的下载速度,单位转换需要在配置文件中打开
String speed1 = task.getSpeed(); //原始byte长度速度
### 常用接口
| api | 说明 |
| ------| ------ |
| `Aria.download(this).stopAllTask();` | 停止所有正在下载的任务 |
| `Aria.download(this).resumeAllTask();` | 恢复所有停止的任务 |
| `Aria.download(this).removeAllTask();` | 删除所有任务</br> 1、如果任务为完成,会删除没有完成的文件</br> 2、如果使用`removeAllTask(true)`方法,会将已经下载完成和未完成的文件删除</br> 3、如果是上传任务,不会删除本地的上传文件,但如果使用`removeAllTask(true)`,同样会删除本地上传文件 |
| `Aria.download(this).setMaxSpeed(speed)` | 限制单个任务的上传、下载的最大速度(单位为 kb) |
| `Aria.download(this).load(DOWNLOAD_URL)`<br>`.setExtendField(str)` | 设置扩展字段,有的时候,你可能希望在下载的时候存放一些自己的数据,这时你可以调用该接口将数据保存下来(如果你数据比较多,或者数据比较复杂,你可以先把数据转换为**JSON**,然后再将其存到Aria的下载实体中) |
| `Aria.download(this).load(DOWNLOAD_URL)`<br>`.getExtendField()` | 获取保存的扩展字段 |
| `Aria.download(this).load(DOWNLOAD_URL)`<br>`.setDownloadPath(PATH).setHighestPriority();` | 将任务设置为最高优先级任务,最高优先级任务有以下特点:<br>1、在下载队列中,有且只有一个最高优先级任务<br> 2、最高优先级任务会一直存在,直到用户手动暂停或任务完成<br>3、任务调度器不会暂停最高优先级任务<br>4、用户手动暂停或任务完成后,第二次重新执行该任务,该命令将失效<br>5、如果下载队列中已经满了,则会停止队尾的任务,当高优先级任务完成后,该队尾任务将自动执行<br>6、把任务设置为最高优先级任务后,将自动执行任务,不需要重新调用start()启动任务 |
### 任务实体常用数据
* 获取当前任务的下载速度<br>
速度参数有点特殊,需要[下载事件支持](#下载状态获取)
``` java
@Override public void onTaskRunning(DownloadTask task) {
//如果你打开了速度单位转换配置,将可以通过以下方法获取带单位的下载速度,如:1 mb/s
String convertSpeed = task.getConvertSpeed();
//如果你有自己的单位格式,可以通过以下方法获取原始byte长度
long speed = task.getSpeed();
} }
```
* 获取下载的文件大小、当前进度百分比</br> @Download.onTaskComplete(DOWNLOAD_URL) void taskComplete(DownloadTask task) {
同样的,你也可以在DownloadTask对象中获取下载的文件大小 //在这里处理任务完成的状态
```
@Override public void onTaskRunning(DownloadTask task) {
 //获取文件大小
long fileSize = task.getFileSize();
//获取单位转换后的文件大小
String fileSize1 = task.getConvertFileSize();
//当前进度百分比
int percent = task.getPercent();
} }
``` ```
[更多注解使用方法](https://github.com/AriaLyy/Aria/wiki/%E6%B3%A8%E8%A7%A3%E4%BD%BF%E7%94%A8)
### [HTTP任务组下载\FTP下载;HTTP\FTP文件上传](https://github.com/AriaLyy/Aria/wiki/Aria%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8)
### [参数配置](https://github.com/AriaLyy/Aria/wiki/Aria%E5%8F%82%E6%95%B0%E9%85%8D%E7%BD%AE)
### [更多说明,见WIKI](https://github.com/AriaLyy/Aria/wiki)
## 混淆配置 ## 混淆配置
``` ```
@ -309,29 +110,6 @@ Aria.get(this).getDownloadConfig().setMaxTaskNum(3);
*** ***
## 后续版本开发规划
* ~~代码优化~~
## 开发日志
+ v_3.2.20 修复任务组文件删除,第二次下载进度不准确的问题
+ v_3.2.18 增加一个刷新文件信息的api接口
+ v_3.2.17 修复一个版本兼容性问题,线程中使用Aria出错问题
+ v_3.2.15 修复大型文件分段下载失败的问题,修复中文URL乱码问题
+ v_3.2.14 修复恢复所有任务的api接口,不能恢复下载组任务的问题
+ v_3.2.13 修复某些服务器头文件返回描述文件格式错误的问题、修复有时删除任务,需要两次删除的问题
+ v_3.2.12 实现FTP多线程断点续传下载,FTP断点续传上传功能
+ v_3.2.9 修复任务组下载完成两次回掉的问题,修复又是获取不到下载状态的问题
+ v_3.2.8 修复下载超过2G大小的文件失败的问题
+ v_3.2.7 移除设置文件名的api接口,修复断开网络时出现的进度条错误的问题
+ v_3.2.6 移除广播事件,增加任务组下载功能
+ v_3.1.9 修复stopAll队列没有任务时崩溃的问题,增加针对单个任务监听的功能
+ v_3.1.7 修复某些文件下载不了的bug,增加apt注解方法,事件获取更加简单了
+ v_3.1.6 取消任务时onTaskCancel回调两次的bug
+ v_3.1.5 优化代码结构,增加优先下载任务功能。
+ v_3.1.4 修复快速切换,暂停、恢复功能时,概率性出现的重新下载问题,添加onPre()回调,onPre()用于请求地址之前执行界面UI更新操作。
+ v_3.1.0 添加Aria配置文件,优化代码
License License
------- -------
@ -348,3 +126,13 @@ License
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.

@ -18,6 +18,7 @@ package com.arialyy.simple.download;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.util.Log;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
@ -29,6 +30,7 @@ import com.arialyy.annotations.Download;
import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.download.DownloadTarget; import com.arialyy.aria.core.download.DownloadTarget;
import com.arialyy.aria.core.download.DownloadTask; 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.inf.IEntity;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.frame.util.show.L; import com.arialyy.frame.util.show.L;
@ -43,8 +45,8 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
private static final String DOWNLOAD_URL = private static final String DOWNLOAD_URL =
//"http://kotlinlang.org/docs/kotlin-docs.pdf"; //"http://kotlinlang.org/docs/kotlin-docs.pdf";
//"https://atom-installer.github.com/v1.13.0/AtomSetup.exe?s=1484074138&ext=.exe"; //"https://atom-installer.github.com/v1.13.0/AtomSetup.exe?s=1484074138&ext=.exe";
//"http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk";
"http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk"; "http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk";
//"http://120.25.196.56:8000/filereq?id=15692406294&ipncid=105635&client=android&filename=20170819185541.avi";
//"http://down2.xiaoshuofuwuqi.com/d/file/filetxt/20170608/14/%BA%DA%CE%D7%CA%A6%E1%C8%C6%F0.txt"; //"http://down2.xiaoshuofuwuqi.com/d/file/filetxt/20170608/14/%BA%DA%CE%D7%CA%A6%E1%C8%C6%F0.txt";
//"http://tinghuaapp.oss-cn-shanghai.aliyuncs.com/20170612201739607815"; //"http://tinghuaapp.oss-cn-shanghai.aliyuncs.com/20170612201739607815";
//"http://static.gaoshouyou.com/d/36/69/2d3699acfa69e9632262442c46516ad8.apk"; //"http://static.gaoshouyou.com/d/36/69/2d3699acfa69e9632262442c46516ad8.apk";
@ -53,6 +55,7 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
//不支持断点的链接 //不支持断点的链接
//"http://ox.konsung.net:5555/ksdc-web/download/downloadFile/?fileName=ksdc_1.0.2.apk&rRange=0-"; //"http://ox.konsung.net:5555/ksdc-web/download/downloadFile/?fileName=ksdc_1.0.2.apk&rRange=0-";
//"http://172.18.104.50:8080/download/_302turn"; //"http://172.18.104.50:8080/download/_302turn";
//"http://gdown.baidu.com/data/wisegame/0904344dee4a2d92/QQ_718.apk";
@Bind(R.id.start) Button mStart; @Bind(R.id.start) Button mStart;
@Bind(R.id.stop) Button mStop; @Bind(R.id.stop) Button mStop;
@Bind(R.id.cancel) Button mCancel; @Bind(R.id.cancel) Button mCancel;
@ -193,9 +196,8 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
Aria.download(SingleTaskActivity.this) Aria.download(SingleTaskActivity.this)
.load(DOWNLOAD_URL, true) .load(DOWNLOAD_URL, true)
.addHeader("groupName", "value") .addHeader("groupName", "value")
.setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/gggg.apk") .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/hhhhhhhh.apk")
.start(); .start();
break; break;
case R.id.stop: case R.id.stop:
Aria.download(this).load(DOWNLOAD_URL).stop(); Aria.download(this).load(DOWNLOAD_URL).stop();

@ -24,6 +24,7 @@ import android.widget.Button;
import butterknife.Bind; import butterknife.Bind;
import com.arialyy.annotations.DownloadGroup; import com.arialyy.annotations.DownloadGroup;
import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.common.RequestEnum;
import com.arialyy.aria.core.download.DownloadGroupEntity; import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.download.DownloadGroupTask; import com.arialyy.aria.core.download.DownloadGroupTask;
import com.arialyy.aria.core.download.DownloadGroupTaskEntity; import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
@ -48,6 +49,7 @@ public class DownloadGroupActivity extends BaseActivity<ActivityDownloadGroupBin
Aria.download(this).register(); Aria.download(this).register();
setTitle("任务组"); setTitle("任务组");
mUrls = getModule(GroupModule.class).getUrls(); mUrls = getModule(GroupModule.class).getUrls();
DownloadGroupEntity e = Aria.download(this).getGroupTaskList().get(0);
DownloadGroupTaskEntity entity = Aria.download(this).getDownloadGroupTask(mUrls); DownloadGroupTaskEntity entity = Aria.download(this).getDownloadGroupTask(mUrls);
if (entity != null && entity.getEntity() != null) { if (entity != null && entity.getEntity() != null) {
DownloadGroupEntity groupEntity = entity.getEntity(); DownloadGroupEntity groupEntity = entity.getEntity();
@ -82,7 +84,7 @@ public class DownloadGroupActivity extends BaseActivity<ActivityDownloadGroupBin
Aria.download(this).load(mUrls).stop(); Aria.download(this).load(mUrls).stop();
break; break;
case R.id.cancel: case R.id.cancel:
Aria.download(this).load(mUrls).cancel(); Aria.download(this).load(mUrls).cancel(true);
break; break;
} }
} }

@ -5,8 +5,8 @@ buildscript {
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:2.3.3' // classpath 'com.android.tools.build:gradle:2.3.3'
// classpath 'com.android.tools.build:gradle:2.2.2' classpath 'com.android.tools.build:gradle:2.2.2'
classpath 'com.novoda:bintray-release:0.5.0' classpath 'com.novoda:bintray-release:0.5.0'
// classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7' // classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7'
// classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' // classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
@ -37,7 +37,7 @@ task clean(type: Delete) {
ext { ext {
userOrg = 'arialyy' userOrg = 'arialyy'
groupId = 'com.arialyy.aria' groupId = 'com.arialyy.aria'
publishVersion = '3.2.22' publishVersion = '3.2.25'
repoName='maven' repoName='maven'
desc = 'android 下载框架' desc = 'android 下载框架'
website = 'https://github.com/AriaLyy/Aria' website = 'https://github.com/AriaLyy/Aria'

Loading…
Cancel
Save