This commit is contained in:
AriaLyy
2017-09-18 23:35:38 +08:00
73 changed files with 2016 additions and 1084 deletions

View File

@@ -114,110 +114,4 @@ import com.arialyy.aria.core.upload.UploadTask;
throw new IllegalArgumentException("不支持的类型");
}
}
/**
* 上传任务状态监听
*
* @see Upload
* @deprecated 请使用注解函数的方式来实现事件的获取
*/
@Deprecated public static class UploadSchedulerListener
implements ISchedulerListener<UploadTask> {
/**
* 预处理有时有些地址链接比较慢这时可以先在这个地方出来一些界面上的UI如按钮的状态。
*
* @param task 上传文物实体
*/
@Override public void onPre(UploadTask task) {
}
@Override public void onTaskPre(UploadTask task) {
}
@Override public void onTaskResume(UploadTask task) {
}
@Override public void onTaskStart(UploadTask task) {
}
@Override public void onTaskStop(UploadTask task) {
}
@Override public void onTaskCancel(UploadTask task) {
}
@Override public void onTaskFail(UploadTask task) {
}
@Override public void onTaskComplete(UploadTask task) {
}
@Override public void onTaskRunning(UploadTask task) {
}
}
/**
* 下载任务状态监听
*
* @see Download
* @deprecated 请使用注解函数的方式来实现事件的获取
*/
@Deprecated public static class DownloadSchedulerListener
implements IDownloadSchedulerListener<DownloadTask> {
/**
* 预处理有时有些地址链接比较慢这时可以先在这个地方出来一些界面上的UI如按钮的状态。
* 需要注意的是在该回调中是得不到文件长度的如果需要获取文件长度需要在onTaskPre中获取
*
* @param task 下载任务
*/
@Override public void onPre(DownloadTask task) {
}
@Override public void onTaskPre(DownloadTask task) {
}
@Override public void onTaskResume(DownloadTask task) {
}
@Override public void onTaskStart(DownloadTask task) {
}
@Override public void onTaskStop(DownloadTask task) {
}
@Override public void onTaskCancel(DownloadTask task) {
}
@Override public void onTaskFail(DownloadTask task) {
}
@Override public void onTaskComplete(DownloadTask task) {
}
@Override public void onTaskRunning(DownloadTask task) {
}
@Override public void onNoSupportBreakPoint(DownloadTask task) {
}
}
}

View File

@@ -398,7 +398,6 @@ import org.xml.sax.SAXException;
if (key.contains(clsName)) {
IReceiver receiver = mReceivers.get(key);
if (receiver != null) {
receiver.removeSchedulerListener();
receiver.unRegister();
receiver.destroy();
}

View File

@@ -0,0 +1,103 @@
/*
* 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.text.TextUtils;
import android.util.Log;
import com.arialyy.aria.core.command.group.GroupCmdFactory;
import com.arialyy.aria.core.inf.BaseGroupTaskEntity;
import com.arialyy.aria.util.CommonUtil;
import java.util.List;
/**
* Created by lyy on 2017/9/4.
* 子任务管理器
*/
public class SubTaskManager {
private String TAG = "SubTaskManager";
private BaseGroupTaskEntity mEntity;
private String mTargetName;
public SubTaskManager(String targetName, BaseGroupTaskEntity entity) {
mTargetName = targetName;
mEntity = entity;
}
/**
* 启动任务组中的子任务
*
* @param url 子任务下载地址
*/
public void startSubTask(String url) {
if (checkUrl(url)) {
AriaManager.getInstance(AriaManager.APP)
.setCmd(
CommonUtil.createGroupCmd(mTargetName, mEntity, GroupCmdFactory.SUB_TASK_START, url))
.exe();
}
}
/**
* 停止任务组中的子任务
*
* @param url 子任务下载地址
*/
public void stopSubTask(String url) {
if (checkUrl(url)) {
AriaManager.getInstance(AriaManager.APP)
.setCmd(
CommonUtil.createGroupCmd(mTargetName, mEntity, GroupCmdFactory.SUB_TASK_STOP, url))
.exe();
}
}
/**
* 删除子任务组中的子任务
*
* @param url 子任务下载地址
*/
public void cancelSubTask(String url) {
if (checkUrl(url)) {
AriaManager.getInstance(AriaManager.APP)
.setCmd(
CommonUtil.createGroupCmd(mTargetName, mEntity, GroupCmdFactory.SUB_TASK_CANCEL, url))
.exe();
}
}
/**
* 检查任务地址
*
* @param url 子任务地址
* @return {@code false} 任务地址不合法
*/
private boolean checkUrl(String url) {
if (TextUtils.isEmpty(url)) {
Log.e(TAG, "子任务地址不能为null");
return false;
}
List<String> urls = mEntity.getEntity().getUrls();
if (urls == null || urls.isEmpty()) {
Log.e(TAG, "任务组任务链接为null");
return false;
}
if (!urls.contains(url)) {
Log.e(TAG, "任务组中没有改Url【+ " + url + "");
return false;
}
return true;
}
}

View File

@@ -22,11 +22,12 @@ import com.arialyy.aria.core.queue.ITaskQueue;
/**
* Created by AriaL on 2017/6/29.
*/
public abstract class AbsCmd<T extends AbsTaskEntity> implements ICmd{
public abstract class AbsCmd<T extends AbsTaskEntity> implements ICmd {
protected ITaskQueue mQueue;
protected T mTaskEntity;
protected String TAG;
protected String mTargetName;
/**
* 是否是下载任务的命令
* {@code true} 下载任务的命令,{@code false} 上传任务的命令

View File

@@ -21,11 +21,11 @@ import com.arialyy.aria.core.inf.AbsTaskEntity;
* Created by AriaL on 2017/6/29.
* 抽象命令工厂
*/
public abstract class AbsCmdFactory<CMD extends AbsCmd> {
public abstract class AbsCmdFactory<TASK_ENTITY extends AbsTaskEntity, CMD extends AbsCmd> {
/**
* @param target 创建任务的对象
* @param entity 下载实体
*/
public abstract <T extends AbsTaskEntity> CMD createCmd(String target, T entity, int type);
public abstract CMD createCmd(String target, TASK_ENTITY entity, int type);
}

View File

@@ -15,21 +15,26 @@
*/
package com.arialyy.aria.core.command.group;
import android.util.Log;
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.inf.AbsGroupTask;
import com.arialyy.aria.core.inf.AbsTask;
import com.arialyy.aria.core.inf.BaseGroupTaskEntity;
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;
import com.arialyy.aria.util.CommonUtil;
/**
* Created by AriaL on 2017/6/29.
* 任务组命令
*/
abstract class AbsGroupCmd<T extends AbsTaskEntity> extends AbsCmd<T> {
public abstract class AbsGroupCmd<T extends BaseGroupTaskEntity> extends AbsCmd<T> {
/**
* 需要控制的子任务url
*/
String childUrl;
AbsGroupTask tempTask;
/**
* @param targetName 创建任务的对象名
@@ -43,4 +48,26 @@ abstract class AbsGroupCmd<T extends AbsTaskEntity> extends AbsCmd<T> {
isDownloadCmd = true;
}
}
/**
* 创建任务
*
* @return 创建的任务
*/
AbsTask createTask() {
tempTask = (AbsGroupTask) mQueue.createTask(mTargetName, mTaskEntity);
return tempTask;
}
boolean checkTask() {
tempTask = (AbsGroupTask) mQueue.getTask(mTaskEntity.getEntity());
if (tempTask == null) {
createTask();
if (tempTask.isComplete()) {
Log.w(TAG, "任务已完成");
return false;
}
}
return true;
}
}

View File

@@ -15,13 +15,13 @@
*/
package com.arialyy.aria.core.command.group;
import com.arialyy.aria.core.inf.AbsTaskEntity;
import com.arialyy.aria.core.inf.BaseGroupTaskEntity;
/**
* Created by AriaL on 2017/6/29.
* 删除任务组
*/
class GroupCancelCmd<T extends AbsTaskEntity> extends AbsGroupCmd<T> {
class GroupCancelCmd<T extends BaseGroupTaskEntity> extends AbsGroupCmd<T> {
/**
* @param targetName 创建任务的对象名
*/
@@ -30,6 +30,8 @@ class GroupCancelCmd<T extends AbsTaskEntity> extends AbsGroupCmd<T> {
}
@Override public void executeCmd() {
if (checkTask()) {
tempTask.cancelSubTask(childUrl);
}
}
}

View File

@@ -16,25 +16,25 @@
package com.arialyy.aria.core.command.group;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.command.AbsCmdFactory;
import com.arialyy.aria.core.inf.AbsTaskEntity;
import com.arialyy.aria.core.inf.BaseGroupTaskEntity;
/**
* Created by AriaL on 2017/6/29.
* 任务组子任务控制命令
*/
class GroupCmdFactory extends AbsCmdFactory<AbsGroupCmd> {
public class GroupCmdFactory {
/**
* 启动任务
* 启动任务
*/
public static final int TASK_START = 0xa1;
public static final int SUB_TASK_START = 0xa1;
/**
* 停止任务
* 停止任务
*/
public static final int TASK_STOP = 0xa2;
public static final int SUB_TASK_STOP = 0xa2;
/**
* 取消任务
* 取消任务
*/
public static final int TASK_CANCEL = 0xa3;
public static final int SUB_TASK_CANCEL = 0xa3;
private static volatile GroupCmdFactory INSTANCE = null;
@@ -54,18 +54,25 @@ class GroupCmdFactory extends AbsCmdFactory<AbsGroupCmd> {
/**
* @param target 创建任务的对象
* @param entity 下载实体
* @param type 命令类型{@link #TASK_START}、{@link #TASK_CANCEL}、{@link #TASK_STOP}
* @param type 命令类型{@link #SUB_TASK_START}、{@link #SUB_TASK_STOP}、{@link #SUB_TASK_CANCEL}
* @param childUrl 需要控制的子任务url
*/
public <T extends AbsTaskEntity> AbsGroupCmd<T> createCmd(String target, T entity, int type) {
public AbsGroupCmd createCmd(String target, BaseGroupTaskEntity entity, int type,
String childUrl) {
AbsGroupCmd cmd = null;
switch (type) {
case TASK_START:
return new GroupStartCmd<>(target, entity);
case TASK_STOP:
return new GroupStopCmd<>(target, entity);
case TASK_CANCEL:
return new GroupCancelCmd<>(target, entity);
default:
return null;
case SUB_TASK_START:
cmd = new GroupStartCmd<>(target, entity);
break;
case SUB_TASK_STOP:
cmd = new GroupStopCmd<>(target, entity);
break;
case SUB_TASK_CANCEL:
cmd = new GroupCancelCmd<>(target, entity);
}
if (cmd != null) {
cmd.childUrl = childUrl;
}
return cmd;
}
}

View File

@@ -15,18 +15,13 @@
*/
package com.arialyy.aria.core.command.group;
import android.text.TextUtils;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.common.QueueMod;
import com.arialyy.aria.core.inf.AbsGroupTask;
import com.arialyy.aria.core.inf.AbsTaskEntity;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.BaseGroupTaskEntity;
/**
* Created by AriaL on 2017/6/29.
* 任务组开始命令,该命令负责开始下载或恢复下载的操
* 任务组开始命令,该命令负责处理任务组子任务的开始\恢复等工
*/
class GroupStartCmd<T extends AbsTaskEntity> extends AbsGroupCmd<T> {
class GroupStartCmd<T extends BaseGroupTaskEntity> extends AbsGroupCmd<T> {
/**
* @param targetName 创建任务的对象名
*/
@@ -35,38 +30,8 @@ class GroupStartCmd<T extends AbsTaskEntity> extends AbsGroupCmd<T> {
}
@Override public void executeCmd() {
String mod;
int maxTaskNum;
AriaManager manager = AriaManager.getInstance(AriaManager.APP);
if (isDownloadCmd) {
mod = manager.getDownloadConfig().getQueueMod();
maxTaskNum = manager.getDownloadConfig().getMaxTaskNum();
} else {
mod = manager.getUploadConfig().getQueueMod();
maxTaskNum = manager.getUploadConfig().getMaxTaskNum();
}
AbsGroupTask task = (AbsGroupTask) mQueue.getTask(mTaskEntity.getEntity());
if (task == null) {
task = (AbsGroupTask) mQueue.createTask(mTargetName, mTaskEntity);
if (!TextUtils.isEmpty(mTargetName)) {
task.setTargetName(mTargetName);
}
// 任务不存在时,根据配置不同,对任务执行操作
if (mod.equals(QueueMod.NOW.getTag())) {
mQueue.startTask(task);
} else if (mod.equals(QueueMod.WAIT.getTag())) {
if (mQueue.getCurrentExePoolNum() < maxTaskNum) {
mQueue.startTask(task);
}
}
} else {
// 任务不存在时,根据配置不同,对任务执行操作
if (!task.isRunning()
&& mod.equals(QueueMod.WAIT.getTag())
&& task.getState() == IEntity.STATE_WAIT) {
mQueue.startTask(task);
}
if (checkTask()) {
tempTask.startSubTask(childUrl);
}
}
}

View File

@@ -15,13 +15,13 @@
*/
package com.arialyy.aria.core.command.group;
import com.arialyy.aria.core.inf.AbsTaskEntity;
import com.arialyy.aria.core.inf.BaseGroupTaskEntity;
/**
* Created by AriaL on 2017/6/29.
* 停止任务组的命令
*/
class GroupStopCmd<T extends AbsTaskEntity> extends AbsGroupCmd<T>{
class GroupStopCmd<T extends BaseGroupTaskEntity> extends AbsGroupCmd<T> {
/**
* @param targetName 创建任务的对象名
*/
@@ -30,6 +30,8 @@ class GroupStopCmd<T extends AbsTaskEntity> extends AbsGroupCmd<T>{
}
@Override public void executeCmd() {
if (checkTask()) {
tempTask.stopSubTask(childUrl);
}
}
}

View File

@@ -47,7 +47,6 @@ public class CancelAllCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
if (mTaskEntity instanceof DownloadTaskEntity
|| mTaskEntity instanceof DownloadGroupTaskEntity) {
handleDownloadRemove();
handleDownloadRemove();
handleDownloadGroupRemove();
} else if (mTaskEntity instanceof UploadTaskEntity) {
handleUploadRemove();

View File

@@ -24,7 +24,7 @@ import com.arialyy.aria.core.inf.AbsTaskEntity;
* Created by Lyy on 2016/9/23.
* 命令工厂
*/
public class NormalCmdFactory extends AbsCmdFactory<AbsNormalCmd> {
public class NormalCmdFactory extends AbsCmdFactory<AbsTaskEntity, AbsNormalCmd> {
/**
* 创建任务
*/
@@ -82,7 +82,7 @@ public class NormalCmdFactory extends AbsCmdFactory<AbsNormalCmd> {
* @param type 命令类型{@link #TASK_CREATE}、{@link #TASK_START}、{@link #TASK_CANCEL}、{@link
* #TASK_STOP}、{@link #TASK_HIGHEST_PRIORITY}、{@link #TASK_STOP_ALL}、{@link #TASK_RESUME_ALL}
*/
public <T extends AbsTaskEntity> AbsNormalCmd<T> createCmd(String target, T entity, int type) {
public AbsNormalCmd createCmd(String target, AbsTaskEntity entity, int type) {
switch (type) {
case TASK_CREATE:
return new AddCmd<>(target, entity);
@@ -105,4 +105,5 @@ public class NormalCmdFactory extends AbsCmdFactory<AbsNormalCmd> {
return null;
}
}
}

View File

@@ -67,6 +67,10 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
mConstance = new StateConstance();
}
public void setNewTask(boolean newTask) {
mTaskEntity.isNewTask = newTask;
}
@Override public void setMaxSpeed(double maxSpeed) {
for (int i = 0; i < mThreadNum; i++) {
AbsThreadTask task = mTask.get(i);
@@ -134,6 +138,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
if (mTimer != null) {
mTimer.purge();
mTimer.cancel();
mTimer = null;
}
}

View File

@@ -27,7 +27,7 @@ import static java.util.Collections.unmodifiableSet;
* 代理参数获取
*/
public class ProxyHelper {
public Set<String> downloadCounter, uploadCounter, downloadGroupCounter;
public Set<String> downloadCounter, uploadCounter, downloadGroupCounter, downloadGroupSubCounter;
public static volatile ProxyHelper INSTANCE = null;
@@ -49,6 +49,7 @@ public class ProxyHelper {
Class clazz = Class.forName("com.arialyy.aria.ProxyClassCounter");
Method download = clazz.getMethod("getDownloadCounter");
Method downloadGroup = clazz.getMethod("getDownloadGroupCounter");
Method downloadGroupSub = clazz.getMethod("getDownloadGroupSubCounter");
Method upload = clazz.getMethod("getUploadCounter");
Object object = clazz.newInstance();
Object dc = download.invoke(object);
@@ -59,6 +60,10 @@ public class ProxyHelper {
if (dgc != null) {
downloadGroupCounter = unmodifiableSet((Set<String>) dgc);
}
Object dgsc = downloadGroupSub.invoke(object);
if (dgsc != null){
downloadGroupSubCounter = unmodifiableSet((Set<? extends String>) dgsc);
}
Object uc = upload.invoke(object);
if (uc != null) {
uploadCounter = unmodifiableSet((Set<String>) uc);

View File

@@ -30,7 +30,7 @@ import java.lang.ref.WeakReference;
*/
class BaseDListener<ENTITY extends AbsEntity, TASK extends AbsTask<ENTITY>>
implements IDownloadListener {
private WeakReference<Handler> outHandler;
protected WeakReference<Handler> outHandler;
private long mLastLen = 0; //上一次发送长度
private boolean isFirst = true;
protected ENTITY mEntity;
@@ -117,6 +117,7 @@ class BaseDListener<ENTITY extends AbsEntity, TASK extends AbsTask<ENTITY>>
} else {
mEntity.setSpeed(speed < 0 ? 0 : speed);
}
mEntity.setPercent((int) (mEntity.getCurrentProgress() * 100 / mEntity.getFileSize()));
}
/**

View File

@@ -16,9 +16,10 @@
package com.arialyy.aria.core.download;
import android.text.TextUtils;
import com.arialyy.aria.core.SubTaskManager;
import com.arialyy.aria.core.inf.AbsDownloadTarget;
import com.arialyy.aria.core.inf.AbsTarget;
import com.arialyy.aria.core.inf.AbsTaskEntity;
import com.arialyy.aria.core.inf.BaseGroupTaskEntity;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.CommonUtil;
import java.io.File;
@@ -28,7 +29,7 @@ import java.util.List;
/**
* Created by Aria.Lao on 2017/7/26.
*/
abstract class BaseGroupTarget<TARGET extends AbsTarget, TASK_ENTITY extends AbsTaskEntity>
abstract class BaseGroupTarget<TARGET extends AbsTarget, TASK_ENTITY extends BaseGroupTaskEntity>
extends AbsDownloadTarget<TARGET, DownloadGroupEntity, TASK_ENTITY> {
List<String> mUrls = new ArrayList<>();
@@ -42,6 +43,8 @@ abstract class BaseGroupTarget<TARGET extends AbsTarget, TASK_ENTITY extends Abs
*/
private boolean isSetDirPathed = false;
private SubTaskManager mSubTaskManager;
/**
* 查询任务组实体,如果数据库不存在该实体,则新创建一个新的任务组实体
*/
@@ -57,6 +60,18 @@ abstract class BaseGroupTarget<TARGET extends AbsTarget, TASK_ENTITY extends Abs
return entity;
}
/**
* 获取子任务管理器
*
* @return 子任务管理器
*/
public SubTaskManager getSubTaskManager() {
if (mSubTaskManager == null) {
mSubTaskManager = new SubTaskManager(mTargetName, mTaskEntity);
}
return mSubTaskManager;
}
/**
* 设置任务组别名
*/

View File

@@ -31,11 +31,6 @@ public class DownloadGroupEntity extends AbsGroupEntity {
@OneToMany(table = DownloadEntity.class, key = "groupName") private List<DownloadEntity> subtask =
new ArrayList<>();
/**
* 子任务链接组
*/
@NormalList(clazz = String.class) private List<String> urls = new ArrayList<>();
/**
* 任务组下载文件的文件夹地址
*
@@ -59,14 +54,6 @@ public class DownloadGroupEntity extends AbsGroupEntity {
this.dirPath = dirPath;
}
public List<String> getUrls() {
return urls;
}
public void setUrls(List<String> urls) {
this.urls = urls;
}
void setGroupName(String key) {
this.groupName = key;
}

View File

@@ -17,6 +17,8 @@ package com.arialyy.aria.core.download;
import android.os.Handler;
import com.arialyy.aria.core.download.downloader.IDownloadGroupListener;
import com.arialyy.aria.core.inf.GroupSendParams;
import com.arialyy.aria.core.scheduler.ISchedulers;
/**
* Created by Aria.Lao on 2017/7/20.
@@ -25,9 +27,16 @@ import com.arialyy.aria.core.download.downloader.IDownloadGroupListener;
class DownloadGroupListener extends BaseDListener<DownloadGroupEntity, DownloadGroupTask>
implements IDownloadGroupListener {
private final String TAG = "DownloadGroupListener";
private GroupSendParams<DownloadGroupTask, DownloadEntity> mSeedEntity;
DownloadGroupListener(DownloadGroupTask task, Handler outHandler) {
super(task, outHandler);
mSeedEntity = new GroupSendParams<>();
mSeedEntity.groupTask = task;
}
@Override public void onSubPre(DownloadEntity subEntity) {
sendInState2Target(ISchedulers.SUB_PRE, subEntity);
}
@Override public void supportBreakpoint(boolean support, DownloadEntity subEntity) {
@@ -35,23 +44,43 @@ class DownloadGroupListener extends BaseDListener<DownloadGroupEntity, DownloadG
}
@Override public void onSubStart(DownloadEntity subEntity) {
sendInState2Target(ISchedulers.SUB_START, subEntity);
}
@Override public void onSubStop(DownloadEntity subEntity) {
saveCurrentLocation();
sendInState2Target(ISchedulers.SUB_STOP, subEntity);
}
@Override public void onSubComplete(DownloadEntity subEntity) {
saveCurrentLocation();
sendInState2Target(ISchedulers.SUB_COMPLETE, subEntity);
}
@Override public void onSubFail(DownloadEntity subEntity) {
saveCurrentLocation();
sendInState2Target(ISchedulers.SUB_FAIL, subEntity);
}
@Override public void onSubCancel(DownloadEntity entity) {
@Override public void onSubCancel(DownloadEntity subEntity) {
saveCurrentLocation();
sendInState2Target(ISchedulers.SUB_CANCEL, subEntity);
}
@Override public void onSubRunning(DownloadEntity subEntity) {
sendInState2Target(ISchedulers.SUB_RUNNING, subEntity);
}
/**
* 将任务状态发送给下载器
*
* @param state {@link ISchedulers#START}
*/
private void sendInState2Target(int state, DownloadEntity subEntity) {
if (outHandler.get() != null) {
mSeedEntity.entity = subEntity;
outHandler.get().obtainMessage(state, ISchedulers.IS_SUB_TASK, 0, mSeedEntity).sendToTarget();
}
}
private void saveCurrentLocation() {

View File

@@ -19,6 +19,7 @@ import android.os.Handler;
import android.os.Looper;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.common.IUtil;
import com.arialyy.aria.core.download.downloader.AbsGroupUtil;
import com.arialyy.aria.core.download.downloader.DownloadGroupUtil;
import com.arialyy.aria.core.download.downloader.FtpDirDownloadUtil;
import com.arialyy.aria.core.inf.AbsGroupTask;
@@ -33,7 +34,6 @@ import com.arialyy.aria.util.CheckUtil;
public class DownloadGroupTask extends AbsGroupTask<DownloadGroupTaskEntity, DownloadGroupEntity> {
private final String TAG = "DownloadGroupTask";
private DownloadGroupListener mListener;
private IUtil mUtil;
private DownloadGroupTask(DownloadGroupTaskEntity taskEntity, Handler outHandler) {
mTaskEntity = taskEntity;

View File

@@ -15,13 +15,13 @@
*/
package com.arialyy.aria.core.download;
import com.arialyy.aria.core.inf.AbsTaskEntity;
import com.arialyy.aria.core.inf.BaseGroupTaskEntity;
import com.arialyy.aria.orm.OneToOne;
/**
* Created by AriaL on 2017/7/1.
*/
public class DownloadGroupTaskEntity extends AbsTaskEntity<DownloadGroupEntity> {
public class DownloadGroupTaskEntity extends BaseGroupTaskEntity<DownloadGroupEntity> {
@OneToOne(table = DownloadGroupEntity.class, key = "groupName") public DownloadGroupEntity entity;

View File

@@ -139,10 +139,12 @@ public class DownloadReceiver extends AbsReceiver {
String className = obj.getClass().getName();
Set<String> dCounter = ProxyHelper.getInstance().downloadCounter;
Set<String> dgCounter = ProxyHelper.getInstance().downloadGroupCounter;
Set<String> dgsCounter = ProxyHelper.getInstance().downloadGroupSubCounter;
if (dCounter != null && dCounter.contains(className)) {
DownloadSchedulers.getInstance().register(obj);
}
if (dgCounter != null && dgCounter.contains(className)) {
if ((dgCounter != null && dgCounter.contains(className)) || (dgsCounter != null
&& dgsCounter.contains(className))) {
DownloadGroupSchedulers.getInstance().register(obj);
}
return this;
@@ -155,10 +157,12 @@ public class DownloadReceiver extends AbsReceiver {
String className = obj.getClass().getName();
Set<String> dCounter = ProxyHelper.getInstance().downloadCounter;
Set<String> dgCounter = ProxyHelper.getInstance().downloadGroupCounter;
Set<String> dgsCounter = ProxyHelper.getInstance().downloadGroupSubCounter;
if (dCounter != null && dCounter.contains(className)) {
DownloadSchedulers.getInstance().unRegister(obj);
}
if (dgCounter != null && dgCounter.contains(className)) {
if (dgCounter != null && dgCounter.contains(className) || (dgsCounter != null
&& dgsCounter.contains(className))) {
DownloadGroupSchedulers.getInstance().unRegister(obj);
}
if (needRmReceiver) {
@@ -166,29 +170,6 @@ public class DownloadReceiver extends AbsReceiver {
}
}
/**
* 添加调度器回调
*
* @see #register()
*/
@Deprecated public DownloadReceiver addSchedulerListener(
ISchedulerListener<DownloadTask> listener) {
this.listener = listener;
DownloadSchedulers.getInstance().addSchedulerListener(targetName, listener);
return this;
}
/**
* 移除回调
*
* @see #unRegister()
*/
@Deprecated @Override public void removeSchedulerListener() {
if (listener != null) {
DownloadSchedulers.getInstance().removeSchedulerListener(targetName, listener);
}
}
@Override public void destroy() {
targetName = null;
listener = null;
@@ -300,7 +281,7 @@ public class DownloadReceiver extends AbsReceiver {
@Override public void removeAllTask(boolean removeFile) {
final AriaManager ariaManager = AriaManager.getInstance(AriaManager.APP);
CancelAllCmd cancelCmd =
(CancelAllCmd) CommonUtil.createCmd(targetName, new DownloadTaskEntity(),
(CancelAllCmd) CommonUtil.createNormalCmd(targetName, new DownloadTaskEntity(),
NormalCmdFactory.TASK_CANCEL_ALL);
cancelCmd.removeFile = removeFile;
ariaManager.setCmd(cancelCmd).exe();

View File

@@ -15,6 +15,7 @@
*/
package com.arialyy.aria.core.download.downloader;
import android.util.Log;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.common.IUtil;
import com.arialyy.aria.core.download.DownloadEntity;
@@ -38,7 +39,7 @@ import java.util.concurrent.Executors;
* Created by AriaL on 2017/6/30.
* 任务组核心逻辑
*/
abstract class AbsGroupUtil implements IUtil {
public abstract class AbsGroupUtil implements IUtil {
private final String TAG = "AbsGroupUtil";
/**
* 任务组所有任务总大小
@@ -48,7 +49,7 @@ abstract class AbsGroupUtil implements IUtil {
private ExecutorService mExePool;
protected IDownloadGroupListener mListener;
protected DownloadGroupTaskEntity mTaskEntity;
private boolean isRunning = true;
private boolean isRunning = false;
private Timer mTimer;
/**
* 初始化完成的任务书数
@@ -81,6 +82,8 @@ abstract class AbsGroupUtil implements IUtil {
private int mCompleteNum = 0;
//失败的任务数
private int mFailNum = 0;
//停止的任务数
private int mStopNum = 0;
//实际的下载任务数
int mActualTaskNum = 0;
/**
@@ -97,6 +100,7 @@ abstract class AbsGroupUtil implements IUtil {
if (tasks != null && !tasks.isEmpty()) {
for (DownloadTaskEntity te : tasks) {
te.removeFile = mTaskEntity.removeFile;
if (te.getEntity() == null) continue;
mTasksMap.put(te.getEntity().getUrl(), te);
}
}
@@ -107,6 +111,7 @@ abstract class AbsGroupUtil implements IUtil {
if (entity.getState() == IEntity.STATE_COMPLETE && file.exists()) {
mCompleteNum++;
mInitNum++;
mStopNum++;
mCurrentLocation += entity.getFileSize();
} else {
mExeMap.put(entity.getUrl(), createChildDownloadTask(entity));
@@ -127,6 +132,84 @@ abstract class AbsGroupUtil implements IUtil {
}
}
/**
* 启动子任务下载
*
* @param url 子任务下载地址
*/
public void startSubTask(String url) {
if (!checkSubTask(url, "开始")) return;
if (!isRunning) {
isRunning = true;
startTimer();
}
Downloader d = getDownloader(url, false);
if (d != null && !d.isRunning()) {
d.setNewTask(false);
d.start();
}
}
/**
* 停止子任务下载
*
* @param url 子任务下载地址
*/
public void stopSubTask(String url) {
if (!checkSubTask(url, "停止")) return;
Downloader d = getDownloader(url, false);
if (d != null && d.isRunning()) {
d.stop();
}
}
/**
* 删除子任务
*
* @param url 子任务下载地址
*/
public void cancelSunTask(String url) {
Downloader d = getDownloader(url, false);
if (d != null) {
d.cancel();
}
}
/**
* 检查子任务
*
* @param url 子任务url
* @param type 任务类型
* @return {@code true} 任务可以下载
*/
private boolean checkSubTask(String url, String type) {
DownloadTaskEntity entity = mTasksMap.get(url);
if (entity != null) {
if (entity.getState() == IEntity.STATE_COMPLETE) {
Log.w(TAG, "任务【" + url + "】已完成," + type + "失败");
return false;
}
} else {
Log.w(TAG, "任务组中没有该任务【" + url + "】," + type + "失败");
return false;
}
return true;
}
/**
* 通过地址获取下载器
*
* @param url 子任务下载地址
* @param start 是否启动任务
*/
private Downloader getDownloader(String url, boolean start) {
Downloader d = mDownloaderMap.get(url);
if (d == null) {
return createChildDownload(mTasksMap.get(url), start);
}
return d;
}
@Override public long getFileSize() {
return mTotalSize;
}
@@ -232,6 +315,7 @@ abstract class AbsGroupUtil implements IUtil {
if (mTimer != null) {
mTimer.purge();
mTimer.cancel();
mTimer = null;
}
}
@@ -242,6 +326,10 @@ abstract class AbsGroupUtil implements IUtil {
closeTimer(true);
mListener.onPostPre(mTotalSize);
mListener.onStart(mCurrentLocation);
startTimer();
}
private void startTimer() {
mTimer = new Timer(true);
mTimer.schedule(new TimerTask() {
@Override public void run() {
@@ -255,14 +343,26 @@ abstract class AbsGroupUtil implements IUtil {
}
/**
* 启动子任务下载器
* 创建子任务下载器,默认创建完成自动启动
*/
void startChildDownload(DownloadTaskEntity taskEntity) {
Downloader createChildDownload(DownloadTaskEntity taskEntity) {
return createChildDownload(taskEntity, true);
}
/**
* 创建子任务下载器,启动子任务下载器
*
* @param start 是否启动下载
*/
Downloader createChildDownload(DownloadTaskEntity taskEntity, boolean start) {
ChildDownloadListener listener = new ChildDownloadListener(taskEntity);
Downloader dt = new Downloader(listener, taskEntity);
mDownloaderMap.put(taskEntity.getEntity().getUrl(), dt);
if (mExePool.isShutdown()) return;
mExePool.execute(dt);
if (mExePool.isShutdown()) return dt;
if (start) {
mExePool.execute(dt);
}
return dt;
}
/**
@@ -276,6 +376,7 @@ abstract class AbsGroupUtil implements IUtil {
taskEntity.userName = mTaskEntity.userName;
taskEntity.userPw = mTaskEntity.userPw;
taskEntity.account = mTaskEntity.account;
mTasksMap.put(entity.getUrl(), taskEntity);
return taskEntity;
}
taskEntity = new DownloadTaskEntity();
@@ -293,6 +394,7 @@ abstract class AbsGroupUtil implements IUtil {
taskEntity.account = mTaskEntity.account;
taskEntity.key = entity.getDownloadPath();
taskEntity.save();
mTasksMap.put(entity.getUrl(), taskEntity);
return taskEntity;
}
@@ -321,30 +423,39 @@ abstract class AbsGroupUtil implements IUtil {
entity.setFileSize(fileSize);
entity.setConvertFileSize(CommonUtil.formatFileSize(fileSize));
saveData(IEntity.STATE_POST_PRE, -1);
mListener.onSubPre(entity);
}
@Override public void onResume(long resumeLocation) {
saveData(IEntity.STATE_POST_PRE, IEntity.STATE_RUNNING);
lastLen = resumeLocation;
mListener.onSubStart(entity);
}
@Override public void onStart(long startLocation) {
saveData(IEntity.STATE_POST_PRE, IEntity.STATE_RUNNING);
lastLen = startLocation;
mListener.onSubStart(entity);
}
@Override public void onProgress(long currentLocation) {
long speed = currentLocation - lastLen;
mCurrentLocation += speed;
lastLen = currentLocation;
entity.setCurrentProgress(currentLocation);
handleSpeed(speed);
mListener.onSubRunning(entity);
lastLen = currentLocation;
}
@Override public void onStop(long stopLocation) {
saveData(IEntity.STATE_STOP, stopLocation);
handleSpeed(0);
mListener.onSubStop(entity);
mStopNum++;
if (mStopNum + mCompleteNum >= mInitNum) {
closeTimer(false);
mListener.onStop(mCurrentLocation);
}
}
@Override public void onCancel() {
@@ -407,6 +518,7 @@ abstract class AbsGroupUtil implements IUtil {
private void handleSpeed(long speed) {
entity.setSpeed(speed);
entity.setConvertSpeed(speed <= 0 ? "" : CommonUtil.formatFileSize(speed) + "/s");
entity.setPercent((int) (entity.getCurrentProgress() * 100 / entity.getFileSize()));
}
private void saveData(int state, long location) {

View File

@@ -65,7 +65,7 @@ public class DownloadGroupUtil extends AbsGroupUtil implements IUtil {
if (taskEntity != null) {
if (taskEntity.getState() != IEntity.STATE_FAIL
&& taskEntity.getState() != IEntity.STATE_WAIT) {
startChildDownload(taskEntity);
createChildDownload(taskEntity);
i++;
} else {
mInfoPool.execute(createFileInfoThread(taskEntity));
@@ -94,7 +94,7 @@ public class DownloadGroupUtil extends AbsGroupUtil implements IUtil {
if (isNeedLoadFileSize) {
mTotalSize += te.getEntity().getFileSize();
}
startChildDownload(te);
createChildDownload(te);
}
mInitNum++;
if (mInitNum + mInitFailNum >= mTaskEntity.getEntity().getSubTask().size()

View File

@@ -1,118 +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.download.downloader;
import android.text.TextUtils;
import android.util.Log;
import com.arialyy.aria.core.AriaManager;
import java.io.IOException;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
/**
* Created by Aria.Lao on 2017/7/26.
*/
public class FtpClientHelp {
private final String TAG = "FtpClientHelp";
private static volatile FtpClientHelp INSTANCE = null;
private FTPClient client;
private String serverIp, user, pw, account;
private int port;
private FtpClientHelp() {
}
public static FtpClientHelp getInstnce() {
if (INSTANCE == null) {
synchronized (AriaManager.LOCK) {
INSTANCE = new FtpClientHelp();
}
}
return INSTANCE;
}
public FTPClient getClient() {
if (client == null || !client.isConnected()) {
createClient();
}
return client;
}
/**
* 登录到FTP服务器当客户端为null或客户端没有连接到FTP服务器时才会执行登录操作
*/
public FTPClient login(String serverIp, int port, String user, String pw, String account) {
this.serverIp = serverIp;
this.port = port;
this.user = user;
this.pw = pw;
this.account = account;
if (client == null || !client.isConnected()) {
createClient();
}
return client;
}
/**
* 登出
*/
public void logout() {
try {
if (client != null && client.isConnected()) {
client.logout();
}
} catch (IOException e) {
e.printStackTrace();
}
}
FTPClient createClient() {
new Thread(new Runnable() {
@Override public void run() {
client = new FTPClient();
try {
client.connect(serverIp, port);
if (!TextUtils.isEmpty(account)) {
client.login(user, pw);
} else {
client.login(user, pw, account);
}
int reply = client.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
client.disconnect();
Log.e(TAG, "无法连接到ftp服务器错误码为" + reply);
}
} catch (IOException e) {
Log.d(TAG, e.getMessage());
} finally {
synchronized (FtpClientHelp.this) {
FtpClientHelp.this.notify();
}
}
}
}).start();
synchronized (FtpClientHelp.this) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return client;
}
}

View File

@@ -60,7 +60,7 @@ public class FtpDirDownloadUtil extends AbsGroupUtil {
for (String key : keys) {
DownloadTaskEntity taskEntity = mExeMap.get(key);
if (taskEntity != null) {
startChildDownload(taskEntity);
createChildDownload(taskEntity);
i++;
}
}

View File

@@ -24,6 +24,7 @@ import com.arialyy.aria.core.download.DownloadTaskEntity;
import com.arialyy.aria.core.inf.IDownloadListener;
import com.arialyy.aria.util.BufferedRandomAccessFile;
import com.arialyy.aria.util.CommonUtil;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -45,7 +46,7 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEnt
@Override public void run() {
HttpURLConnection conn = null;
InputStream is = null;
BufferedInputStream is = null;
BufferedRandomAccessFile file = null;
try {
URL url = new URL(CommonUtil.convertUrl(mConfig.URL));
@@ -69,7 +70,8 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEnt
conn = ConnectionHelp.setConnectParam(mConfig.TASK_ENTITY, conn);
conn.setConnectTimeout(STATE.CONNECT_TIME_OUT);
conn.setReadTimeout(STATE.READ_TIME_OUT); //设置读取流的等待时间,必须设置该参数
is = conn.getInputStream();
//is = conn.getInputStream();
is = new BufferedInputStream(conn.getInputStream());
//创建可设置位置的文件
file = new BufferedRandomAccessFile(mConfig.TEMP_FILE, "rwd", mBufSize);
//设置每条线程写入文件的位置

View File

@@ -17,7 +17,6 @@ package com.arialyy.aria.core.download.downloader;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.inf.IDownloadListener;
import com.arialyy.aria.core.inf.IEventListener;
/**
* Created by Aria.Lao on 2017/7/20.
@@ -25,6 +24,11 @@ import com.arialyy.aria.core.inf.IEventListener;
*/
public interface IDownloadGroupListener extends IDownloadListener {
/**
* 子任务预处理
*/
void onSubPre(DownloadEntity subEntity);
/**
* 子任务支持断点回调
*
@@ -56,4 +60,9 @@ public interface IDownloadGroupListener extends IDownloadListener {
* 子任务取消下载
*/
void onSubCancel(DownloadEntity subEntity);
/**
* 子任务执行中
*/
void onSubRunning(DownloadEntity subEntity);
}

View File

@@ -98,7 +98,7 @@ public abstract class AbsDownloadTarget<TARGET extends AbsTarget, ENTITY extends
protected void setHighestPriority() {
AriaManager.getInstance(AriaManager.APP)
.setCmd(
CommonUtil.createCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_HIGHEST_PRIORITY))
CommonUtil.createNormalCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_HIGHEST_PRIORITY))
.exe();
}
@@ -136,7 +136,7 @@ public abstract class AbsDownloadTarget<TARGET extends AbsTarget, ENTITY extends
*/
public void add() {
AriaManager.getInstance(AriaManager.APP)
.setCmd(CommonUtil.createCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_CREATE))
.setCmd(CommonUtil.createNormalCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_CREATE))
.exe();
}

View File

@@ -60,6 +60,11 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable
*/
private long completeTime;
/**
* 进度百分比
*/
@Ignore private int percent;
private boolean isComplete = false;
public boolean isComplete() {
@@ -142,6 +147,14 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable
this.completeTime = completeTime;
}
public int getPercent() {
return percent;
}
public void setPercent(int percent) {
this.percent = percent;
}
/**
* 实体唯一标识符
*/
@@ -165,6 +178,7 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable
dest.writeLong(this.currentProgress);
dest.writeLong(this.completeTime);
dest.writeByte(this.isComplete ? (byte) 1 : (byte) 0);
dest.writeInt(this.percent);
}
protected AbsEntity(Parcel in) {
@@ -178,5 +192,6 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable
this.currentProgress = in.readLong();
this.completeTime = in.readLong();
this.isComplete = in.readByte() != 0;
this.percent = in.readInt();
}
}

View File

@@ -17,7 +17,10 @@ package com.arialyy.aria.core.inf;
import android.os.Parcel;
import android.os.Parcelable;
import com.arialyy.aria.orm.NormalList;
import com.arialyy.aria.orm.Primary;
import java.util.ArrayList;
import java.util.List;
/**
* Created by AriaL on 2017/6/3.
@@ -33,6 +36,19 @@ public abstract class AbsGroupEntity extends AbsEntity implements Parcelable {
*/
private String alias = "";
/**
* 子任务链接组
*/
@NormalList(clazz = String.class) private List<String> urls = new ArrayList<>();
public List<String> getUrls() {
return urls;
}
public void setUrls(List<String> urls) {
this.urls = urls;
}
public String getGroupName() {
return groupName;
}

View File

@@ -15,17 +15,53 @@
*/
package com.arialyy.aria.core.inf;
import com.arialyy.aria.core.download.downloader.AbsGroupUtil;
/**
* Created by AriaL on 2017/6/29.
* 任务组任务抽象类
*/
public abstract class AbsGroupTask<TASK_ENTITY extends AbsTaskEntity, ENTITY extends AbsGroupEntity>
extends AbsTask<ENTITY> {
protected TASK_ENTITY mTaskEntity;
protected AbsGroupUtil mUtil;
@Override public String getKey() {
return mEntity.getGroupName();
}
/**
* 启动任务组中的子任务
*
* @param url 子任务下载地址
*/
public void startSubTask(String url) {
if (mUtil != null) {
mUtil.startSubTask(url);
}
}
/**
* 停止任务组中的子任务
*
* @param url 子任务下载地址
*/
public void stopSubTask(String url) {
if (mUtil != null) {
mUtil.stopSubTask(url);
}
}
/**
* 删除子任务组中的子任务
*
* @param url 子任务下载地址
*/
public void cancelSubTask(String url) {
if (mUtil != null) {
mUtil.cancelSunTask(url);
}
}
}

View File

@@ -162,7 +162,7 @@ public abstract class AbsTarget<TARGET extends AbsTarget, ENTITY extends AbsEnti
*/
@Override public void start() {
AriaManager.getInstance(AriaManager.APP)
.setCmd(CommonUtil.createCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_START))
.setCmd(CommonUtil.createNormalCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_START))
.exe();
}
@@ -177,7 +177,7 @@ public abstract class AbsTarget<TARGET extends AbsTarget, ENTITY extends AbsEnti
@Override public void stop() {
AriaManager.getInstance(AriaManager.APP)
.setCmd(CommonUtil.createCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_STOP))
.setCmd(CommonUtil.createNormalCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_STOP))
.exe();
}
@@ -186,7 +186,7 @@ public abstract class AbsTarget<TARGET extends AbsTarget, ENTITY extends AbsEnti
*/
@Override public void resume() {
AriaManager.getInstance(AriaManager.APP)
.setCmd(CommonUtil.createCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_START))
.setCmd(CommonUtil.createNormalCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_START))
.exe();
}
@@ -195,7 +195,7 @@ public abstract class AbsTarget<TARGET extends AbsTarget, ENTITY extends AbsEnti
*/
@Override public void cancel() {
AriaManager.getInstance(AriaManager.APP)
.setCmd(CommonUtil.createCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_CANCEL))
.setCmd(CommonUtil.createNormalCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_CANCEL))
.exe();
}
@@ -207,7 +207,7 @@ public abstract class AbsTarget<TARGET extends AbsTarget, ENTITY extends AbsEnti
*/
public void cancel(boolean removeFile) {
CancelCmd cancelCmd =
(CancelCmd) CommonUtil.createCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_CANCEL);
(CancelCmd) CommonUtil.createNormalCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_CANCEL);
cancelCmd.removeFile = removeFile;
AriaManager.getInstance(AriaManager.APP).setCmd(cancelCmd).exe();
}

View File

@@ -0,0 +1,26 @@
/*
* 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.inf;
/**
* Created by lyy on 2017/9/5.
*/
public abstract class BaseGroupTaskEntity<ENTITY extends AbsGroupEntity> extends AbsTaskEntity<ENTITY>{
@Override public ENTITY getEntity() {
return null;
}
}

View File

@@ -0,0 +1,34 @@
/*
* 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.inf;
/**
* Created by lyy on 2017/9/8.
* 任务组参数传递
*/
public class GroupSendParams<GROUP_TASK extends AbsGroupTask, ENTITY extends AbsNormalEntity> {
public GROUP_TASK groupTask;
public ENTITY entity;
public GroupSendParams() {
}
public GroupSendParams(GROUP_TASK groupTask, ENTITY entity) {
this.groupTask = groupTask;
this.entity = entity;
}
}

View File

@@ -26,10 +26,6 @@ public interface IReceiver<ENTITY extends IEntity> {
*/
void destroy();
/**
* 移除事件回调
*/
void removeSchedulerListener();
/**
* 移除观察者

View File

@@ -15,12 +15,14 @@
*/
package com.arialyy.aria.core.scheduler;
import com.arialyy.aria.core.inf.AbsNormalEntity;
import com.arialyy.aria.core.inf.ITask;
/**
* Created by Aria.Lao on 2017/6/7.
*/
public class AbsSchedulerListener<TASK extends ITask> implements ISchedulerListener<TASK> {
public class AbsSchedulerListener<TASK extends ITask, SUB_ENTITY extends AbsNormalEntity> implements ISchedulerListener<TASK> {
@Override public void onPre(TASK task) {
}
@@ -64,4 +66,32 @@ public class AbsSchedulerListener<TASK extends ITask> implements ISchedulerListe
public void setListener(Object obj) {
}
public void onSubTaskPre(TASK task, SUB_ENTITY subTask) {
}
public void onSubTaskStart(TASK task, SUB_ENTITY subTask) {
}
public void onSubTaskStop(TASK task, SUB_ENTITY subTask) {
}
public void onSubTaskCancel(TASK task, SUB_ENTITY subTask) {
}
public void onSubTaskComplete(TASK task, SUB_ENTITY subTask) {
}
public void onSubTaskFail(TASK task, SUB_ENTITY subTask) {
}
public void onSubTaskRunning(TASK task, SUB_ENTITY subTask) {
}
}

View File

@@ -21,8 +21,10 @@ import android.util.Log;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.core.inf.AbsEntity;
import com.arialyy.aria.core.inf.AbsNormalEntity;
import com.arialyy.aria.core.inf.AbsTask;
import com.arialyy.aria.core.inf.AbsTaskEntity;
import com.arialyy.aria.core.inf.GroupSendParams;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.queue.ITaskQueue;
import com.arialyy.aria.core.upload.UploadTask;
@@ -45,9 +47,8 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, ENTITY extends A
protected QUEUE mQueue;
private Map<String, ISchedulerListener<TASK>> mSchedulerListeners = new ConcurrentHashMap<>();
private Map<String, AbsSchedulerListener<TASK>> mObservers = new ConcurrentHashMap<>();
private Map<String, AbsSchedulerListener<TASK, AbsNormalEntity>> mObservers =
new ConcurrentHashMap<>();
/**
* 设置调度器类型
@@ -59,33 +60,9 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, ENTITY extends A
*/
abstract String getProxySuffix();
/**
* @param targetName 观察者,创建该监听器的对象类名
* @param schedulerListener {@link ISchedulerListener}
* @see #register(Object)
*/
@Deprecated @Override public void addSchedulerListener(String targetName,
ISchedulerListener<TASK> schedulerListener) {
mSchedulerListeners.put(targetName, schedulerListener);
}
/**
* @param targetName 观察者,创建该监听器的对象类名
* @see #unRegister(Object)
*/
@Override public void removeSchedulerListener(String targetName,
ISchedulerListener<TASK> schedulerListener) {
//该内存泄露解决方案http://stackoverflow.com/questions/14585829/how-safe-is-to-delete-already-removed-concurrenthashmap-element
for (Iterator<Map.Entry<String, ISchedulerListener<TASK>>> iter =
mSchedulerListeners.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry<String, ISchedulerListener<TASK>> entry = iter.next();
if (entry.getKey().equals(targetName)) iter.remove();
}
}
@Override public void register(Object obj) {
String targetName = obj.getClass().getName();
AbsSchedulerListener<TASK> listener = mObservers.get(targetName);
AbsSchedulerListener<TASK, AbsNormalEntity> listener = mObservers.get(targetName);
if (listener == null) {
listener = createListener(targetName);
if (listener != null) {
@@ -98,9 +75,9 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, ENTITY extends A
}
@Override public void unRegister(Object obj) {
for (Iterator<Map.Entry<String, AbsSchedulerListener<TASK>>> iter =
for (Iterator<Map.Entry<String, AbsSchedulerListener<TASK, AbsNormalEntity>>> iter =
mObservers.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry<String, AbsSchedulerListener<TASK>> entry = iter.next();
Map.Entry<String, AbsSchedulerListener<TASK, AbsNormalEntity>> entry = iter.next();
if (entry.getKey().equals(obj.getClass().getName())) iter.remove();
}
}
@@ -110,11 +87,11 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, ENTITY extends A
*
* @param targetName 通过观察者创建对应的Aria事件代理
*/
private AbsSchedulerListener<TASK> createListener(String targetName) {
AbsSchedulerListener<TASK> listener = null;
private AbsSchedulerListener<TASK, AbsNormalEntity> createListener(String targetName) {
AbsSchedulerListener<TASK, AbsNormalEntity> listener = null;
try {
Class clazz = Class.forName(targetName + getProxySuffix());
listener = (AbsSchedulerListener<TASK>) clazz.newInstance();
listener = (AbsSchedulerListener<TASK, AbsNormalEntity>) clazz.newInstance();
} catch (ClassNotFoundException e) {
Log.e(TAG, targetName + "没有Aria的Download或Upload注解方法");
} catch (InstantiationException e) {
@@ -126,13 +103,62 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, ENTITY extends A
}
@Override public boolean handleMessage(Message msg) {
if (msg.arg1 == IS_SUB_TASK) {
return handleSubEvent(msg);
}
TASK task = (TASK) msg.obj;
if (task == null) {
Log.e(TAG, "请传入下载任务");
return true;
}
handleNormalEvent(task, msg.what);
return true;
}
/**
* 处理任务组子任务事件
*/
private boolean handleSubEvent(Message msg) {
GroupSendParams params = (GroupSendParams) msg.obj;
if (mObservers.size() > 0) {
Set<String> keys = mObservers.keySet();
for (String key : keys) {
AbsSchedulerListener<TASK, AbsNormalEntity> listener = mObservers.get(key);
switch (msg.what) {
case SUB_PRE:
listener.onSubTaskPre((TASK) params.groupTask, params.entity);
break;
case SUB_START:
listener.onSubTaskStart((TASK) params.groupTask, params.entity);
break;
case SUB_STOP:
listener.onSubTaskStop((TASK) params.groupTask, params.entity);
break;
case SUB_FAIL:
listener.onSubTaskFail((TASK) params.groupTask, params.entity);
break;
case SUB_RUNNING:
listener.onSubTaskRunning((TASK) params.groupTask, params.entity);
break;
case SUB_CANCEL:
listener.onSubTaskCancel((TASK) params.groupTask, params.entity);
break;
case SUB_COMPLETE:
listener.onSubTaskComplete((TASK) params.groupTask, params.entity);
break;
}
}
}
return true;
}
/**
* 处理普通任务事件
*/
private void handleNormalEvent(TASK task, int what) {
ENTITY entity = task.getEntity();
switch (msg.what) {
switch (what) {
case STOP:
if (task.getEntity().getState() == IEntity.STATE_WAIT) {
break;
@@ -153,8 +179,7 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, ENTITY extends A
handleFailTask(task);
break;
}
callback(msg.what, task);
return true;
callback(what, task);
}
/**
@@ -163,12 +188,7 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, ENTITY extends A
* @param state 状态
*/
private void callback(int state, TASK task) {
if (mSchedulerListeners.size() > 0) {
Set<String> keys = mSchedulerListeners.keySet();
for (String key : keys) {
callback(state, task, mSchedulerListeners.get(key));
}
} else if (mObservers.size() > 0) {
if (mObservers.size() > 0) {
Set<String> keys = mObservers.keySet();
for (String key : keys) {
callback(state, task, mObservers.get(key));
@@ -176,7 +196,8 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, ENTITY extends A
}
}
private void callback(int state, TASK task, ISchedulerListener<TASK> listener) {
private void callback(int state, TASK task,
AbsSchedulerListener<TASK, AbsNormalEntity> listener) {
if (listener != null) {
if (task == null) {
Log.e(TAG, "TASK 为null回调失败");
@@ -211,9 +232,7 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, ENTITY extends A
listener.onTaskFail(task);
break;
case SUPPORT_BREAK_POINT:
if (listener instanceof IDownloadSchedulerListener) {
((IDownloadSchedulerListener<TASK>) listener).onNoSupportBreakPoint(task);
}
listener.onNoSupportBreakPoint(task);
break;
}
}

View File

@@ -66,4 +66,8 @@ public interface ISchedulerListener<TASK extends ITask> {
* 任务执行中
*/
void onTaskRunning(TASK task);
}

View File

@@ -24,6 +24,11 @@ import com.arialyy.aria.core.inf.AbsTask;
* 调度器功能接口
*/
public interface ISchedulers<Task extends AbsTask> extends Handler.Callback {
/**
* 为任务组任务
*/
int IS_SUB_TASK = 0xd1;
/**
* 断点支持
*/
@@ -67,18 +72,39 @@ public interface ISchedulers<Task extends AbsTask> extends Handler.Callback {
int RESUME = 8;
/**
* 注册下载器监听,一个观察者只能注册一次监听
*
* @param targetName 观察者,创建该监听器的对象类名
* @param schedulerListener {@link ISchedulerListener}
* 任务组子任务预处理
*/
void addSchedulerListener(String targetName, ISchedulerListener<Task> schedulerListener);
int SUB_PRE = 0xa1;
/**
* @param targetName 观察者,创建该监听器的对象类名
* 取消注册监听器
* 任务组子任务开始
*/
void removeSchedulerListener(String targetName, ISchedulerListener<Task> schedulerListener);
int SUB_START = 0xa2;
/**
* 任务组子任务停止
*/
int SUB_STOP = 0xa3;
/**
* 任务组子任务取消
*/
int SUB_CANCEL = 0xa4;
/**
* 任务组子任务失败
*/
int SUB_FAIL = 0xa5;
/**
* 任务组子任务执行执行中
*/
int SUB_RUNNING = 0xa6;
/**
* 任务组子任务完成
*/
int SUB_COMPLETE = 0xa7;
/**
* 将当前类注册到Aria

View File

@@ -106,6 +106,7 @@ class BaseUListener<ENTITY extends AbsEntity, TASK extends AbsTask<ENTITY>>
} else {
mEntity.setSpeed(speed < 0 ? 0 : speed);
}
mEntity.setPercent((int) (mEntity.getCurrentProgress() * 100 / mEntity.getFileSize()));
}
/**

View File

@@ -92,13 +92,11 @@ public class UploadReceiver extends AbsReceiver<UploadEntity> {
@Override public void removeAllTask(boolean removeFile) {
final AriaManager am = AriaManager.getInstance(AriaManager.APP);
am.setCmd(CommonUtil.createCmd(targetName, new DownloadTaskEntity(),
am.setCmd(CommonUtil.createNormalCmd(targetName, new DownloadTaskEntity(),
NormalCmdFactory.TASK_CANCEL_ALL)).exe();
Set<String> keys = am.getReceiver().keySet();
for (String key : keys) {
IReceiver receiver = am.getReceiver().get(key);
receiver.removeSchedulerListener();
am.getReceiver().remove(key);
}
}
@@ -108,26 +106,6 @@ public class UploadReceiver extends AbsReceiver<UploadEntity> {
listener = null;
}
/**
* 添加调度器回调
*
* @see #register()
*/
@Deprecated public UploadReceiver addSchedulerListener(ISchedulerListener<UploadTask> listener) {
this.listener = listener;
UploadSchedulers.getInstance().addSchedulerListener(targetName, listener);
return this;
}
/**
* @see #unRegister()
*/
@Deprecated @Override public void removeSchedulerListener() {
if (listener != null) {
UploadSchedulers.getInstance().removeSchedulerListener(targetName, listener);
}
}
/**
* 将当前类注册到Aria
*/

View File

@@ -33,7 +33,7 @@ import java.util.Map;
class DBConfig {
static Map<String, Class> mapping = new HashMap<>();
static String DB_NAME;
static int VERSION = 14;
static int VERSION = 15;
static {
if (TextUtils.isEmpty(DB_NAME)) {

View File

@@ -26,6 +26,7 @@ import android.util.Log;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.CommonUtil;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.ArrayList;
@@ -180,7 +181,7 @@ final class SqlHelper extends SQLiteOpenHelper {
print(FIND_DATA, sql);
Cursor cursor = db.rawQuery(sql, null);
List<T> data = cursor.getCount() > 0 ? newInstanceEntity(db, clazz, cursor) : null;
cursor.close();
closeCursor(cursor);
close(db);
return data;
}
@@ -223,7 +224,7 @@ final class SqlHelper extends SQLiteOpenHelper {
print(FIND_DATA, sb.toString());
Cursor cursor = db.rawQuery(sb.toString(), null);
List<T> data = cursor.getCount() > 0 ? newInstanceEntity(db, clazz, cursor) : null;
cursor.close();
closeCursor(cursor);
close(db);
return data;
}
@@ -238,7 +239,7 @@ final class SqlHelper extends SQLiteOpenHelper {
print(FIND_ALL_DATA, sb.toString());
Cursor cursor = db.rawQuery(sb.toString(), null);
List<T> data = cursor.getCount() > 0 ? newInstanceEntity(db, clazz, cursor) : null;
cursor.close();
closeCursor(cursor);
close(db);
return data;
}
@@ -394,7 +395,7 @@ final class SqlHelper extends SQLiteOpenHelper {
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null) cursor.close();
closeCursor(cursor);
close(db);
}
return false;
@@ -564,7 +565,7 @@ final class SqlHelper extends SQLiteOpenHelper {
entity.rowID = cursor.getInt(cursor.getColumnIndex("rowid"));
entitys.add(entity);
}
cursor.close();
closeCursor(cursor);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
@@ -586,6 +587,16 @@ final class SqlHelper extends SQLiteOpenHelper {
return findData(db, params[0], params[1] + "=?", primary);
}
private static void closeCursor(Cursor cursor){
if (cursor != null && !cursor.isClosed()) {
try {
cursor.close();
} catch (android.database.SQLException e) {
e.printStackTrace();
}
}
}
private static void close(SQLiteDatabase db) {
//if (db != null && db.isOpen()) db.close();
}

View File

@@ -145,8 +145,11 @@ final class SqlUtil {
// field.isSynthetic(), 使用as热启动App时AS会自动给你的class添加change字段
Ignore ignore = field.getAnnotation(Ignore.class);
int modifiers = field.getModifiers();
String fieldName = field.getName();
return (ignore != null && ignore.value())
|| field.getName().equals("rowID")
|| fieldName.equals("rowID")
|| fieldName.equals("shadow$_klass_")
|| fieldName.equals("shadow$_monitor_")
|| field.isSynthetic()
|| Modifier.isStatic(modifiers)
|| Modifier.isFinal(modifiers);

View File

@@ -24,13 +24,16 @@ import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
import com.arialyy.aria.core.command.group.AbsGroupCmd;
import com.arialyy.aria.core.command.group.GroupCmdFactory;
import com.arialyy.aria.core.command.normal.AbsNormalCmd;
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
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.inf.AbsTaskEntity;
import com.arialyy.aria.core.inf.BaseGroupTaskEntity;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.upload.UploadTaskEntity;
import com.arialyy.aria.orm.DbEntity;
@@ -43,6 +46,11 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URLEncoder;
@@ -58,11 +66,6 @@ import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
/**
* Created by lyy on 2016/1/22.
@@ -432,10 +435,24 @@ public class CommonUtil {
}
}
public static <T extends AbsTaskEntity> AbsNormalCmd createCmd(String target, T entity, int cmd) {
/**
* 创建任务命令
*/
public static <T extends AbsTaskEntity> AbsNormalCmd createNormalCmd(String target, T entity,
int cmd) {
return NormalCmdFactory.getInstance().createCmd(target, entity, cmd);
}
/**
* 创建任务组命令
*
* @param childUrl 子任务url
*/
public static <T extends BaseGroupTaskEntity> AbsGroupCmd createGroupCmd(String target, T entity,
int cmd, String childUrl) {
return GroupCmdFactory.getInstance().createCmd(target, entity, cmd, childUrl);
}
/**
* 创建隐性的Intent
*/