merge code
This commit is contained in:
@ -22,8 +22,8 @@ dependencies {
|
||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||
testCompile 'junit:junit:4.12'
|
||||
compile 'com.android.support:appcompat-v7:23.1.1'
|
||||
compile project(':AriaCompiler')
|
||||
// compile project(':AriaAnnotations')
|
||||
// compile project(':AriaCompiler')
|
||||
compile project(':AriaAnnotations')
|
||||
}
|
||||
//apply from: 'bintray-release.gradle'
|
||||
apply from: 'bintray-release.gradle'
|
||||
//apply from: 'jcenter.gradle'
|
||||
|
@ -59,62 +59,6 @@ import com.arialyy.aria.core.upload.UploadTask;
|
||||
* </pre>
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) public class Aria {
|
||||
/**
|
||||
* 不支持断点
|
||||
*/
|
||||
public static final String ACTION_SUPPORT_BREAK_POINT = "ACTION_SUPPORT_BREAK_POINT";
|
||||
/**
|
||||
* 预处理完成
|
||||
*/
|
||||
public static final String ACTION_PRE = "ACTION_PRE";
|
||||
/**
|
||||
* 下载开始前事件
|
||||
*/
|
||||
public static final String ACTION_POST_PRE = "ACTION_POST_PRE";
|
||||
/**
|
||||
* 开始下载事件
|
||||
*/
|
||||
public static final String ACTION_START = "ACTION_START";
|
||||
/**
|
||||
* 恢复下载事件
|
||||
*/
|
||||
public static final String ACTION_RESUME = "ACTION_RESUME";
|
||||
/**
|
||||
* 正在下载事件
|
||||
*/
|
||||
public static final String ACTION_RUNNING = "ACTION_RUNNING";
|
||||
/**
|
||||
* 停止下载事件
|
||||
*/
|
||||
public static final String ACTION_STOP = "ACTION_STOP";
|
||||
/**
|
||||
* 取消下载事件
|
||||
*/
|
||||
public static final String ACTION_CANCEL = "ACTION_CANCEL";
|
||||
/**
|
||||
* 下载完成事件
|
||||
*/
|
||||
public static final String ACTION_COMPLETE = "ACTION_COMPLETE";
|
||||
/**
|
||||
* 下载失败事件
|
||||
*/
|
||||
public static final String ACTION_FAIL = "ACTION_FAIL";
|
||||
/**
|
||||
* 下载实体
|
||||
*/
|
||||
public static final String DOWNLOAD_ENTITY = "DOWNLOAD_ENTITY";
|
||||
/**
|
||||
* 上传实体
|
||||
*/
|
||||
public static final String UPLOAD_ENTITY = "UPLOAD_ENTITY";
|
||||
/**
|
||||
* 位置
|
||||
*/
|
||||
public static final String CURRENT_LOCATION = "CURRENT_LOCATION";
|
||||
/**
|
||||
* 速度
|
||||
*/
|
||||
public static final String CURRENT_SPEED = "CURRENT_SPEED";
|
||||
|
||||
private Aria() {
|
||||
}
|
||||
|
@ -29,14 +29,13 @@ import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.widget.PopupWindow;
|
||||
import com.arialyy.aria.core.download.DownloadReceiver;
|
||||
import com.arialyy.aria.core.inf.ICmd;
|
||||
import com.arialyy.aria.core.command.ICmd;
|
||||
import com.arialyy.aria.core.inf.IReceiver;
|
||||
import com.arialyy.aria.core.upload.UploadReceiver;
|
||||
import com.arialyy.aria.orm.DbUtil;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
@ -54,9 +54,6 @@ class ConfigHelper extends DefaultHandler {
|
||||
case "threadNum":
|
||||
loadThreadNum(value);
|
||||
break;
|
||||
case "openBroadcast":
|
||||
loadBroadcast(value);
|
||||
break;
|
||||
case "maxTaskNum":
|
||||
loadMaxQueue(value);
|
||||
break;
|
||||
@ -224,16 +221,6 @@ class ConfigHelper extends DefaultHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private void loadBroadcast(String value) {
|
||||
boolean open = Boolean.parseBoolean(value);
|
||||
if (isDownloadConfig) {
|
||||
mDownloadConfig.isOpenBreadCast = open;
|
||||
}
|
||||
if (isUploadConfig) {
|
||||
mUploadConfig.isOpenBreadCast = open;
|
||||
}
|
||||
}
|
||||
|
||||
private void loadThreadNum(String value) {
|
||||
int num = 3;
|
||||
if (!TextUtils.isEmpty(value)) {
|
||||
|
@ -6,8 +6,10 @@ package com.arialyy.aria.core;
|
||||
*/
|
||||
public enum QueueMod {
|
||||
/**
|
||||
* 等待模式,如果执行队列已经满了,再次使用start命令执行任务时,该任务会被添加到缓存队列中
|
||||
* 当执行队列的任务完成时,将自动执行缓存队列中的任务
|
||||
* 等待模式,
|
||||
* 如果执行队列已经满了,再对其它任务(TASK_A)使用start命令执行任务时
|
||||
* 1、TASK_A添加到缓存队列中,当执行队列中的任务完成时,系统会将自动执行缓存队列中的TASK_A
|
||||
* 2、如果再次对TASK_A使用start命令,TASK_A将会立刻执行
|
||||
*/
|
||||
WAIT("wait"),
|
||||
|
||||
|
@ -16,50 +16,20 @@
|
||||
|
||||
package com.arialyy.aria.core.command;
|
||||
|
||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
import com.arialyy.aria.core.queue.DownloadTaskQueue;
|
||||
import com.arialyy.aria.core.queue.ITaskQueue;
|
||||
import com.arialyy.aria.core.inf.ICmd;
|
||||
import com.arialyy.aria.core.queue.UploadTaskQueue;
|
||||
import com.arialyy.aria.core.upload.UploadTaskEntity;
|
||||
import com.arialyy.aria.util.CheckUtil;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2016/8/22.
|
||||
* 下载命令
|
||||
* Created by AriaL on 2017/6/29.
|
||||
*/
|
||||
public abstract class AbsCmd<T extends AbsTaskEntity> implements ICmd {
|
||||
ITaskQueue mQueue;
|
||||
T mTaskEntity;
|
||||
String TAG;
|
||||
String mTargetName;
|
||||
/**
|
||||
* 能否执行命令
|
||||
*/
|
||||
boolean canExeCmd = true;
|
||||
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} 上传任务的命令
|
||||
*/
|
||||
boolean isDownloadCmd = true;
|
||||
|
||||
/**
|
||||
* @param targetName 产生任务的对象名
|
||||
*/
|
||||
AbsCmd(String targetName, T entity) {
|
||||
canExeCmd = CheckUtil.checkCmdEntity(entity,
|
||||
!(this instanceof CancelCmd) || !(this instanceof StopCmd));
|
||||
mTargetName = targetName;
|
||||
mTaskEntity = entity;
|
||||
TAG = CommonUtil.getClassName(this);
|
||||
if (entity instanceof DownloadTaskEntity) {
|
||||
mQueue = DownloadTaskQueue.getInstance();
|
||||
isDownloadCmd = true;
|
||||
} else if (entity instanceof UploadTaskEntity) {
|
||||
mQueue = UploadTaskQueue.getInstance();
|
||||
isDownloadCmd = false;
|
||||
}
|
||||
}
|
||||
protected boolean isDownloadCmd = true;
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.command;
|
||||
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/29.
|
||||
*/
|
||||
public abstract class AbsCmdFactory<CMD extends AbsCmd> {
|
||||
|
||||
/**
|
||||
* @param target 创建任务的对象
|
||||
* @param entity 下载实体
|
||||
*/
|
||||
public abstract <T extends AbsTaskEntity> CMD createCmd(String target, T entity, int type);
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.inf;
|
||||
package com.arialyy.aria.core.command;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2017/2/9.
|
||||
@ -23,5 +23,5 @@ public interface ICmd {
|
||||
/**
|
||||
* 执行命令
|
||||
*/
|
||||
public abstract void executeCmd();
|
||||
void executeCmd();
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.command.group;
|
||||
|
||||
import com.arialyy.aria.core.command.AbsCmd;
|
||||
import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
|
||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
import com.arialyy.aria.core.queue.DownloadGroupTaskQueue;
|
||||
import com.arialyy.aria.core.queue.DownloadTaskQueue;
|
||||
import com.arialyy.aria.core.queue.UploadTaskQueue;
|
||||
import com.arialyy.aria.core.upload.UploadTaskEntity;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/29.
|
||||
* 任务组命令
|
||||
*/
|
||||
public abstract class AbsGroupCmd<T extends AbsTaskEntity> extends AbsCmd<T> {
|
||||
|
||||
/**
|
||||
* @param targetName 创建任务的对象名
|
||||
*/
|
||||
AbsGroupCmd(String targetName, T entity) {
|
||||
mTargetName = targetName;
|
||||
mTaskEntity = entity;
|
||||
TAG = CommonUtil.getClassName(this);
|
||||
if (entity instanceof DownloadGroupTaskEntity) {
|
||||
mQueue = DownloadGroupTaskQueue.getInstance();
|
||||
isDownloadCmd = true;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.command.group;
|
||||
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/29.
|
||||
* 删除任务组
|
||||
*/
|
||||
class GroupCancelCmd<T extends AbsTaskEntity> extends AbsGroupCmd<T> {
|
||||
/**
|
||||
* @param targetName 创建任务的对象名
|
||||
*/
|
||||
GroupCancelCmd(String targetName, T entity) {
|
||||
super(targetName, entity);
|
||||
}
|
||||
|
||||
@Override public void executeCmd() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.command.group;
|
||||
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.command.AbsCmdFactory;
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/29.
|
||||
*/
|
||||
public class GroupCmdFactory extends AbsCmdFactory<AbsGroupCmd> {
|
||||
/**
|
||||
* 启动任务
|
||||
*/
|
||||
public static final int TASK_START = 0xa1;
|
||||
/**
|
||||
* 停止任务
|
||||
*/
|
||||
public static final int TASK_STOP = 0xa2;
|
||||
/**
|
||||
* 取消任务
|
||||
*/
|
||||
public static final int TASK_CANCEL = 0xa3;
|
||||
|
||||
private static volatile GroupCmdFactory INSTANCE = null;
|
||||
|
||||
private GroupCmdFactory() {
|
||||
|
||||
}
|
||||
|
||||
public static GroupCmdFactory getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
INSTANCE = new GroupCmdFactory();
|
||||
}
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param target 创建任务的对象
|
||||
* @param entity 下载实体
|
||||
* @param type 命令类型{@link #TASK_START}、{@link #TASK_CANCEL}、{@link #TASK_STOP}
|
||||
*/
|
||||
public <T extends AbsTaskEntity> AbsGroupCmd<T> createCmd(String target, T entity, int type) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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.command.group;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.QueueMod;
|
||||
import com.arialyy.aria.core.inf.AbsGroupTask;
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/29.
|
||||
* 任务组开始命令,该命令负责开始下载或恢复下载的操作
|
||||
*/
|
||||
class GroupStartCmd<T extends AbsTaskEntity> extends AbsGroupCmd<T> {
|
||||
/**
|
||||
* @param targetName 创建任务的对象名
|
||||
*/
|
||||
GroupStartCmd(String targetName, T entity) {
|
||||
super(targetName, entity);
|
||||
}
|
||||
|
||||
@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.getExePoolSize() < maxTaskNum) {
|
||||
mQueue.startTask(task);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 任务不存在时,根据配置不同,对任务执行操作
|
||||
if (!task.isRunning()
|
||||
&& mod.equals(QueueMod.WAIT.getTag())
|
||||
&& task.getState() == IEntity.STATE_WAIT) {
|
||||
mQueue.startTask(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.command.group;
|
||||
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/29.
|
||||
* 停止任务组的命令
|
||||
*/
|
||||
class GroupStopCmd<T extends AbsTaskEntity> extends AbsGroupCmd<T>{
|
||||
/**
|
||||
* @param targetName 创建任务的对象名
|
||||
*/
|
||||
GroupStopCmd(String targetName, T entity) {
|
||||
super(targetName, entity);
|
||||
}
|
||||
|
||||
@Override public void executeCmd() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.command.normal;
|
||||
|
||||
import com.arialyy.aria.core.command.AbsCmd;
|
||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
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.CheckUtil;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2016/8/22.
|
||||
* 下载命令
|
||||
*/
|
||||
public abstract class AbsNormalCmd<T extends AbsTaskEntity> extends AbsCmd<T> {
|
||||
|
||||
/**
|
||||
* 能否执行命令
|
||||
*/
|
||||
boolean canExeCmd = true;
|
||||
|
||||
/**
|
||||
* @param targetName 产生任务的对象名
|
||||
*/
|
||||
AbsNormalCmd(String targetName, T entity) {
|
||||
canExeCmd = CheckUtil.checkCmdEntity(entity,
|
||||
!(this instanceof CancelCmd) || !(this instanceof StopCmd));
|
||||
mTargetName = targetName;
|
||||
mTaskEntity = entity;
|
||||
TAG = CommonUtil.getClassName(this);
|
||||
if (entity instanceof DownloadTaskEntity) {
|
||||
mQueue = DownloadTaskQueue.getInstance();
|
||||
isDownloadCmd = true;
|
||||
} else if (entity instanceof UploadTaskEntity) {
|
||||
mQueue = UploadTaskQueue.getInstance();
|
||||
isDownloadCmd = false;
|
||||
}
|
||||
}
|
||||
}
|
@ -14,18 +14,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.arialyy.aria.core.command;
|
||||
package com.arialyy.aria.core.command.normal;
|
||||
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.inf.AbsNormalTask;
|
||||
import com.arialyy.aria.core.inf.AbsTask;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.core.inf.ITask;
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2016/8/22.
|
||||
* 添加任务的命令
|
||||
*/
|
||||
class AddCmd<T extends AbsTaskEntity> extends AbsCmd<T> {
|
||||
class AddCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
|
||||
|
||||
AddCmd(String targetName, T entity) {
|
||||
super(targetName, entity);
|
||||
@ -33,7 +34,7 @@ class AddCmd<T extends AbsTaskEntity> extends AbsCmd<T> {
|
||||
|
||||
@Override public void executeCmd() {
|
||||
if (!canExeCmd) return;
|
||||
ITask task = mQueue.getTask(mTaskEntity.getEntity());
|
||||
AbsTask task = mQueue.getTask(mTaskEntity.getEntity());
|
||||
if (task == null) {
|
||||
mTaskEntity.getEntity().setState(IEntity.STATE_WAIT);
|
||||
mQueue.createTask(mTargetName, mTaskEntity);
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.command.normal;
|
||||
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
import com.arialyy.aria.core.upload.UploadEntity;
|
||||
import com.arialyy.aria.orm.DbEntity;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/27.
|
||||
* 删除所有任务,并且删除所有回掉
|
||||
*/
|
||||
final class CancelAllCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
|
||||
/**
|
||||
* @param targetName 产生任务的对象名
|
||||
*/
|
||||
CancelAllCmd(String targetName, T entity) {
|
||||
super(targetName, entity);
|
||||
}
|
||||
|
||||
@Override public void executeCmd() {
|
||||
mQueue.removeAllTask();
|
||||
if (mTaskEntity instanceof DownloadTaskEntity) {
|
||||
handleDownloadRemove();
|
||||
} else {
|
||||
handleUploadRemove();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理上传的删除
|
||||
*/
|
||||
private void handleUploadRemove() {
|
||||
List<UploadEntity> allEntity = DbEntity.findAllData(UploadEntity.class);
|
||||
for (UploadEntity entity : allEntity) {
|
||||
CommonUtil.delUploadTaskConfig(mTaskEntity.removeFile, entity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理下载的删除
|
||||
*/
|
||||
private void handleDownloadRemove() {
|
||||
List<DownloadEntity> allEntity = DbEntity.findAllData(DownloadEntity.class);
|
||||
for (DownloadEntity entity : allEntity) {
|
||||
CommonUtil.delDownloadTaskConfig(mTaskEntity.removeFile, entity);
|
||||
}
|
||||
}
|
||||
}
|
@ -14,24 +14,25 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.arialyy.aria.core.command;
|
||||
package com.arialyy.aria.core.command.normal;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import com.arialyy.aria.core.inf.ITask;
|
||||
import com.arialyy.aria.core.inf.AbsNormalTask;
|
||||
import com.arialyy.aria.core.inf.AbsTask;
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2016/9/20.
|
||||
* 取消命令
|
||||
*/
|
||||
class CancelCmd<T extends AbsTaskEntity> extends AbsCmd<T> {
|
||||
class CancelCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
|
||||
CancelCmd(String targetName, T entity) {
|
||||
super(targetName, entity);
|
||||
}
|
||||
|
||||
@Override public void executeCmd() {
|
||||
if (!canExeCmd) return;
|
||||
ITask task = mQueue.getTask(mTaskEntity.getEntity());
|
||||
AbsTask task = mQueue.getTask(mTaskEntity.getEntity());
|
||||
if (task == null) {
|
||||
task = mQueue.createTask(mTargetName, mTaskEntity);
|
||||
}
|
@ -13,11 +13,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.command;
|
||||
package com.arialyy.aria.core.command.normal;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import com.arialyy.aria.core.inf.ITask;
|
||||
import com.arialyy.aria.core.download.DownloadTask;
|
||||
import com.arialyy.aria.core.inf.AbsNormalTask;
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
import com.arialyy.aria.core.queue.DownloadTaskQueue;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2017/6/2.
|
||||
@ -28,8 +30,10 @@ import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
* 4、用户手动暂停或任务完成后,第二次重新执行该任务,该命令将失效
|
||||
* 5、如果下载队列中已经满了,则会停止队尾的任务,当高优先级任务完成后,该队尾任务将自动执行
|
||||
* 6、把任务设置为最高优先级任务后,将自动执行任务,不需要重新调用start()启动任务
|
||||
*
|
||||
* 目前只只支持单下载任务的最高优先级任务
|
||||
*/
|
||||
final class HighestPriorityCmd<T extends AbsTaskEntity> extends AbsCmd<T> {
|
||||
final class HighestPriorityCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
|
||||
/**
|
||||
* @param targetName 产生任务的对象名
|
||||
*/
|
||||
@ -39,15 +43,15 @@ final class HighestPriorityCmd<T extends AbsTaskEntity> extends AbsCmd<T> {
|
||||
|
||||
@Override public void executeCmd() {
|
||||
if (!canExeCmd) return;
|
||||
ITask task = mQueue.getTask(mTaskEntity.getEntity());
|
||||
DownloadTask task = (DownloadTask) mQueue.getTask(mTaskEntity.getEntity());
|
||||
if (task == null) {
|
||||
task = mQueue.createTask(mTargetName, mTaskEntity);
|
||||
task = (DownloadTask) mQueue.createTask(mTargetName, mTaskEntity);
|
||||
}
|
||||
if (task != null) {
|
||||
if (!TextUtils.isEmpty(mTargetName)) {
|
||||
task.setTargetName(mTargetName);
|
||||
}
|
||||
mQueue.setTaskHighestPriority(task);
|
||||
((DownloadTaskQueue) mQueue).setTaskHighestPriority(task);
|
||||
}
|
||||
}
|
||||
}
|
@ -14,16 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.arialyy.aria.core.command;
|
||||
package com.arialyy.aria.core.command.normal;
|
||||
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.command.AbsCmdFactory;
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
|
||||
/**
|
||||
* Created by Lyy on 2016/9/23.
|
||||
* 命令工厂
|
||||
*/
|
||||
public class CmdFactory {
|
||||
public class NormalCmdFactory extends AbsCmdFactory<AbsNormalCmd> {
|
||||
/**
|
||||
* 创建任务
|
||||
*/
|
||||
@ -56,17 +57,20 @@ public class CmdFactory {
|
||||
* 恢复所有停止的任务
|
||||
*/
|
||||
public static final int TASK_RESUME_ALL = 0x130;
|
||||
/**
|
||||
* 删除所有任务,
|
||||
*/
|
||||
public static final int TASK_CANCEL_ALL = 0x131;
|
||||
private static volatile NormalCmdFactory INSTANCE = null;
|
||||
|
||||
private static volatile CmdFactory INSTANCE = null;
|
||||
|
||||
private CmdFactory() {
|
||||
private NormalCmdFactory() {
|
||||
|
||||
}
|
||||
|
||||
public static CmdFactory getInstance() {
|
||||
public static NormalCmdFactory getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
INSTANCE = new CmdFactory();
|
||||
INSTANCE = new NormalCmdFactory();
|
||||
}
|
||||
}
|
||||
return INSTANCE;
|
||||
@ -78,7 +82,7 @@ public class CmdFactory {
|
||||
* @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> AbsCmd<T> createCmd(String target, T entity, int type) {
|
||||
public <T extends AbsTaskEntity> AbsNormalCmd<T> createCmd(String target, T entity, int type) {
|
||||
switch (type) {
|
||||
case TASK_CREATE:
|
||||
return new AddCmd<>(target, entity);
|
||||
@ -95,6 +99,8 @@ public class CmdFactory {
|
||||
return new StopAllCmd<>(target, entity);
|
||||
case TASK_RESUME_ALL:
|
||||
return new ResumeAllCmd<>(target, entity);
|
||||
case TASK_CANCEL_ALL:
|
||||
return new CancelAllCmd<>(target, entity);
|
||||
default:
|
||||
return null;
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
package com.arialyy.aria.core.command;
|
||||
package com.arialyy.aria.core.command.normal;
|
||||
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||
import com.arialyy.aria.core.inf.AbsTask;
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.core.inf.ITask;
|
||||
import com.arialyy.aria.orm.DbEntity;
|
||||
import java.util.List;
|
||||
|
||||
@ -15,7 +15,7 @@ import java.util.List;
|
||||
* 1.如果执行队列没有满,则开始下载任务,直到执行队列满
|
||||
* 2.如果队列执行队列已经满了,则将所有任务添加到等待队列中
|
||||
*/
|
||||
final class ResumeAllCmd<T extends AbsTaskEntity> extends AbsCmd<T> {
|
||||
final class ResumeAllCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
|
||||
/**
|
||||
* @param targetName 产生任务的对象名
|
||||
*/
|
||||
@ -29,7 +29,7 @@ final class ResumeAllCmd<T extends AbsTaskEntity> extends AbsCmd<T> {
|
||||
for (DownloadEntity entity : allEntity) {
|
||||
int exeNum = mQueue.getExePoolSize();
|
||||
if (exeNum == 0 || exeNum < mQueue.getMaxTaskNum()) {
|
||||
ITask task = createTask(entity);
|
||||
AbsTask task = createTask(entity);
|
||||
mQueue.startTask(task);
|
||||
} else {
|
||||
entity.setState(IEntity.STATE_WAIT);
|
||||
@ -38,10 +38,11 @@ final class ResumeAllCmd<T extends AbsTaskEntity> extends AbsCmd<T> {
|
||||
}
|
||||
}
|
||||
|
||||
private ITask createTask(DownloadEntity entity) {
|
||||
ITask task = mQueue.getTask(entity);
|
||||
private AbsTask createTask(DownloadEntity entity) {
|
||||
AbsTask task = mQueue.getTask(entity);
|
||||
if (task == null) {
|
||||
DownloadTaskEntity taskEntity = new DownloadTaskEntity(entity);
|
||||
DownloadTaskEntity taskEntity = new DownloadTaskEntity();
|
||||
taskEntity.entity = entity;
|
||||
task = mQueue.createTask(mTargetName, taskEntity);
|
||||
} else {
|
||||
Log.w(TAG, "添加命令执行失败,【该任务已经存在】");
|
@ -14,19 +14,21 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.arialyy.aria.core.command;
|
||||
package com.arialyy.aria.core.command.normal;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.QueueMod;
|
||||
import com.arialyy.aria.core.inf.ITask;
|
||||
import com.arialyy.aria.core.inf.AbsTask;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2016/8/22.
|
||||
* 开始命令
|
||||
* 队列模型{@link QueueMod#NOW}、{@link QueueMod#WAIT}
|
||||
*/
|
||||
class StartCmd<T extends AbsTaskEntity> extends AbsCmd<T> {
|
||||
class StartCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
|
||||
|
||||
StartCmd(String targetName, T entity) {
|
||||
super(targetName, entity);
|
||||
@ -34,31 +36,38 @@ class StartCmd<T extends AbsTaskEntity> extends AbsCmd<T> {
|
||||
|
||||
@Override public void executeCmd() {
|
||||
if (!canExeCmd) return;
|
||||
ITask task = mQueue.getTask(mTaskEntity.getEntity());
|
||||
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();
|
||||
}
|
||||
|
||||
AbsTask task = mQueue.getTask(mTaskEntity.getEntity());
|
||||
if (task == null) {
|
||||
task = mQueue.createTask(mTargetName, mTaskEntity);
|
||||
}
|
||||
if (task != null) {
|
||||
if (!TextUtils.isEmpty(mTargetName)) {
|
||||
task.setTargetName(mTargetName);
|
||||
}
|
||||
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();
|
||||
}
|
||||
// 任务不存在时,根据配置不同,对任务执行操作
|
||||
if (mod.equals(QueueMod.NOW.getTag())) {
|
||||
mQueue.startTask(task);
|
||||
}else if (mod.equals(QueueMod.WAIT.getTag())){
|
||||
if (mQueue.getExePoolSize() < maxTaskNum){
|
||||
} else if (mod.equals(QueueMod.WAIT.getTag())) {
|
||||
if (mQueue.getExePoolSize() < maxTaskNum) {
|
||||
mQueue.startTask(task);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 任务不存在时,根据配置不同,对任务执行操作
|
||||
if (!task.isRunning()
|
||||
&& mod.equals(QueueMod.WAIT.getTag())
|
||||
&& task.getState() == IEntity.STATE_WAIT) {
|
||||
mQueue.startTask(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.arialyy.aria.core.command;
|
||||
package com.arialyy.aria.core.command.normal;
|
||||
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
|
||||
@ -6,7 +6,7 @@ import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
* Created by AriaL on 2017/6/13.
|
||||
* 停止所有任务的命令,并清空所有等待队列
|
||||
*/
|
||||
final class StopAllCmd<T extends AbsTaskEntity> extends AbsCmd<T> {
|
||||
final class StopAllCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
|
||||
/**
|
||||
* @param targetName 产生任务的对象名
|
||||
*/
|
@ -14,19 +14,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.arialyy.aria.core.command;
|
||||
package com.arialyy.aria.core.command.normal;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.inf.AbsTask;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.core.inf.ITask;
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2016/9/20.
|
||||
* 停止命令
|
||||
*/
|
||||
class StopCmd<T extends AbsTaskEntity> extends AbsCmd<T> {
|
||||
class StopCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
|
||||
|
||||
StopCmd(String targetName, T entity) {
|
||||
super(targetName, entity);
|
||||
@ -34,7 +34,7 @@ class StopCmd<T extends AbsTaskEntity> extends AbsCmd<T> {
|
||||
|
||||
@Override public void executeCmd() {
|
||||
if (!canExeCmd) return;
|
||||
ITask task = mQueue.getTask(mTaskEntity.getEntity());
|
||||
AbsTask task = mQueue.getTask(mTaskEntity.getEntity());
|
||||
if (task == null) {
|
||||
if (mTaskEntity.getEntity().getState() == IEntity.STATE_RUNNING) {
|
||||
task = mQueue.createTask(mTargetName, mTaskEntity);
|
@ -18,25 +18,35 @@ package com.arialyy.aria.core.download;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import com.arialyy.aria.core.inf.AbsEntity;
|
||||
import com.arialyy.aria.orm.Ignore;
|
||||
import com.arialyy.aria.core.inf.AbsNormalEntity;
|
||||
import com.arialyy.aria.orm.Primary;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2015/12/25.
|
||||
* 下载实体
|
||||
* !!! 注意:CREATOR要进行@Ignore注解
|
||||
* !!!并且需要Parcelable时需要手动填写rowID;
|
||||
*/
|
||||
public class DownloadEntity extends AbsEntity implements Parcelable {
|
||||
private String downloadUrl = ""; //下载路径
|
||||
public class DownloadEntity extends AbsNormalEntity implements Parcelable {
|
||||
@Primary private String downloadUrl = ""; //下载路径
|
||||
private String downloadPath = ""; //保存路径
|
||||
private boolean isDownloadComplete = false; //是否下载完成
|
||||
private boolean isRedirect = false; //是否重定向
|
||||
private String redirectUrl = ""; //重定向链接
|
||||
|
||||
/**
|
||||
* 所属任务组
|
||||
*/
|
||||
private String groupName = "";
|
||||
|
||||
public DownloadEntity() {
|
||||
}
|
||||
|
||||
public String getGroupName() {
|
||||
return groupName;
|
||||
}
|
||||
|
||||
public void setGroupName(String groupName) {
|
||||
this.groupName = groupName;
|
||||
}
|
||||
|
||||
public String getDownloadUrl() {
|
||||
return downloadUrl;
|
||||
@ -95,6 +105,7 @@ public class DownloadEntity extends AbsEntity implements Parcelable {
|
||||
dest.writeByte(this.isDownloadComplete ? (byte) 1 : (byte) 0);
|
||||
dest.writeByte(this.isRedirect ? (byte) 1 : (byte) 0);
|
||||
dest.writeString(this.redirectUrl);
|
||||
dest.writeString(this.groupName);
|
||||
}
|
||||
|
||||
protected DownloadEntity(Parcel in) {
|
||||
@ -104,9 +115,31 @@ public class DownloadEntity extends AbsEntity implements Parcelable {
|
||||
this.isDownloadComplete = in.readByte() != 0;
|
||||
this.isRedirect = in.readByte() != 0;
|
||||
this.redirectUrl = in.readString();
|
||||
this.groupName = in.readString();
|
||||
}
|
||||
|
||||
@Ignore public static final Creator<DownloadEntity> CREATOR = new Creator<DownloadEntity>() {
|
||||
@Override public String toString() {
|
||||
return "DownloadEntity{"
|
||||
+ "downloadUrl='"
|
||||
+ downloadUrl
|
||||
+ '\''
|
||||
+ ", downloadPath='"
|
||||
+ downloadPath
|
||||
+ '\''
|
||||
+ ", isDownloadComplete="
|
||||
+ isDownloadComplete
|
||||
+ ", isRedirect="
|
||||
+ isRedirect
|
||||
+ ", redirectUrl='"
|
||||
+ redirectUrl
|
||||
+ '\''
|
||||
+ ", groupName='"
|
||||
+ groupName
|
||||
+ '\''
|
||||
+ '}';
|
||||
}
|
||||
|
||||
public static final Creator<DownloadEntity> CREATOR = new Creator<DownloadEntity>() {
|
||||
@Override public DownloadEntity createFromParcel(Parcel source) {
|
||||
return new DownloadEntity(source);
|
||||
}
|
||||
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.download;
|
||||
|
||||
import android.os.Parcel;
|
||||
import com.arialyy.aria.core.inf.AbsGroupEntity;
|
||||
import com.arialyy.aria.orm.OneToMany;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/29.
|
||||
* 下载任务组实体
|
||||
*/
|
||||
public class DownloadGroupEntity extends AbsGroupEntity {
|
||||
|
||||
@OneToMany(table = DownloadEntity.class, key = "groupName")
|
||||
private List<DownloadEntity> mChild = new LinkedList<>();
|
||||
|
||||
public List<DownloadEntity> getChild() {
|
||||
return mChild;
|
||||
}
|
||||
|
||||
public void setChild(List<DownloadEntity> child) {
|
||||
this.mChild = child;
|
||||
}
|
||||
|
||||
@Override public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
dest.writeTypedList(this.mChild);
|
||||
}
|
||||
|
||||
public DownloadGroupEntity() {
|
||||
}
|
||||
|
||||
protected DownloadGroupEntity(Parcel in) {
|
||||
super(in);
|
||||
this.mChild = in.createTypedArrayList(DownloadEntity.CREATOR);
|
||||
}
|
||||
|
||||
public static final Creator<DownloadGroupEntity> CREATOR = new Creator<DownloadGroupEntity>() {
|
||||
@Override public DownloadGroupEntity createFromParcel(Parcel source) {
|
||||
return new DownloadGroupEntity(source);
|
||||
}
|
||||
|
||||
@Override public DownloadGroupEntity[] newArray(int size) {
|
||||
return new DownloadGroupEntity[size];
|
||||
}
|
||||
};
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/30.
|
||||
*/
|
||||
|
||||
public class DownloadGroupListener {
|
||||
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.download;
|
||||
|
||||
import com.arialyy.aria.core.inf.AbsGroupTarget;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.util.CheckUtil;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/29.
|
||||
*/
|
||||
public class DownloadGroupTarget
|
||||
extends AbsGroupTarget<DownloadGroupTarget, DownloadGroupEntity, DownloadGroupTaskEntity> {
|
||||
private List<String> mUrls;
|
||||
|
||||
DownloadGroupTarget(DownloadGroupEntity entity, String targetName, List<String> urls) {
|
||||
this.mEntity = entity;
|
||||
this.mTargetName = targetName;
|
||||
this.mUrls = urls;
|
||||
mTaskEntity = new DownloadGroupTaskEntity();
|
||||
mTaskEntity.entity = entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置保存路径组
|
||||
*/
|
||||
public DownloadGroupTarget setDownloadPaths(List<String> paths) {
|
||||
CheckUtil.checkDownloadPaths(paths);
|
||||
if (mUrls.size() != paths.size()) {
|
||||
throw new IllegalArgumentException("下载链接数必须要和保存路径的数量一致");
|
||||
}
|
||||
for (int i = 0, len = mUrls.size(); i < len; i++) {
|
||||
mTaskEntity.getEntity().getChild().add(createDownloadEntity(mUrls.get(i), paths.get(i)));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建子任务下载实体
|
||||
*
|
||||
* @param url 下载地址
|
||||
* @param path 保存路径
|
||||
*/
|
||||
private DownloadEntity createDownloadEntity(String url, String path) {
|
||||
DownloadEntity entity = DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", url);
|
||||
if (entity == null) {
|
||||
entity = new DownloadEntity();
|
||||
}
|
||||
File file = new File(path);
|
||||
if (!file.exists()) {
|
||||
entity.setState(IEntity.STATE_WAIT);
|
||||
}
|
||||
entity.setDownloadPath(path);
|
||||
entity.setDownloadUrl(url);
|
||||
entity.setFileName(file.getName());
|
||||
return entity;
|
||||
}
|
||||
}
|
@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.download;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.download.downloader.DownloadGroupUtil;
|
||||
import com.arialyy.aria.core.download.downloader.DownloadListener;
|
||||
import com.arialyy.aria.core.download.downloader.IDownloadUtil;
|
||||
import com.arialyy.aria.core.inf.AbsGroupTask;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.core.scheduler.DownloadSchedulers;
|
||||
import com.arialyy.aria.core.scheduler.ISchedulers;
|
||||
import com.arialyy.aria.util.CheckUtil;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/27.
|
||||
* 任务组任务
|
||||
*/
|
||||
public class DownloadGroupTask extends AbsGroupTask<DownloadGroupTaskEntity, DownloadGroupEntity> {
|
||||
private DListener mListener;
|
||||
private IDownloadUtil mUtil;
|
||||
|
||||
private DownloadGroupTask(DownloadGroupTaskEntity taskEntity, Handler outHandler) {
|
||||
mTaskEntity = taskEntity;
|
||||
mEntity = taskEntity.getEntity();
|
||||
mOutHandler = outHandler;
|
||||
mContext = AriaManager.APP;
|
||||
mListener = new DListener(mContext, this, mOutHandler);
|
||||
mUtil = new DownloadGroupUtil(mListener, mTaskEntity);
|
||||
}
|
||||
|
||||
@Override public boolean isRunning() {
|
||||
return mUtil.isDownloading();
|
||||
}
|
||||
|
||||
@Override public void start() {
|
||||
mUtil.stopDownload();
|
||||
}
|
||||
|
||||
@Override public void stop() {
|
||||
mUtil.startDownload();
|
||||
}
|
||||
|
||||
@Override public void cancel() {
|
||||
mUtil.cancelDownload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载监听类
|
||||
*/
|
||||
private static class DListener extends DownloadListener {
|
||||
WeakReference<Handler> outHandler;
|
||||
WeakReference<DownloadGroupTask> wTask;
|
||||
Context context;
|
||||
long lastLen = 0; //上一次发送长度
|
||||
boolean isFirst = true;
|
||||
DownloadGroupEntity entity;
|
||||
DownloadGroupTask task;
|
||||
boolean isConvertSpeed = false;
|
||||
|
||||
DListener(Context context, DownloadGroupTask task, Handler outHandler) {
|
||||
this.context = context;
|
||||
this.outHandler = new WeakReference<>(outHandler);
|
||||
this.wTask = new WeakReference<>(task);
|
||||
this.task = wTask.get();
|
||||
this.entity = this.task.getEntity();
|
||||
final AriaManager manager = AriaManager.getInstance(context);
|
||||
isConvertSpeed = manager.getDownloadConfig().isConvertSpeed();
|
||||
}
|
||||
|
||||
@Override public void onPre() {
|
||||
saveData(IEntity.STATE_PRE, -1);
|
||||
sendInState2Target(ISchedulers.PRE);
|
||||
}
|
||||
|
||||
@Override public void onPostPre(long fileSize) {
|
||||
entity.setFileSize(fileSize);
|
||||
saveData(IEntity.STATE_POST_PRE, -1);
|
||||
sendInState2Target(ISchedulers.POST_PRE);
|
||||
}
|
||||
|
||||
@Override public void onStart(long startLocation) {
|
||||
saveData(IEntity.STATE_RUNNING, startLocation);
|
||||
sendInState2Target(ISchedulers.START);
|
||||
}
|
||||
|
||||
@Override public void onResume(long resumeLocation) {
|
||||
saveData(IEntity.STATE_RUNNING, resumeLocation);
|
||||
sendInState2Target(ISchedulers.RESUME);
|
||||
}
|
||||
|
||||
@Override public void onProgress(long currentLocation) {
|
||||
long speed = currentLocation - lastLen;
|
||||
if (isFirst) {
|
||||
speed = 0;
|
||||
isFirst = false;
|
||||
}
|
||||
handleSpeed(speed);
|
||||
lastLen = currentLocation;
|
||||
sendInState2Target(ISchedulers.RUNNING);
|
||||
}
|
||||
|
||||
@Override public void onStop(long stopLocation) {
|
||||
saveData(IEntity.STATE_STOP, stopLocation);
|
||||
handleSpeed(0);
|
||||
sendInState2Target(ISchedulers.STOP);
|
||||
}
|
||||
|
||||
@Override public void onCancel() {
|
||||
saveData(IEntity.STATE_CANCEL, -1);
|
||||
handleSpeed(0);
|
||||
sendInState2Target(ISchedulers.CANCEL);
|
||||
}
|
||||
|
||||
@Override public void onComplete() {
|
||||
saveData(IEntity.STATE_COMPLETE, entity.getFileSize());
|
||||
handleSpeed(0);
|
||||
sendInState2Target(ISchedulers.COMPLETE);
|
||||
}
|
||||
|
||||
@Override public void onFail() {
|
||||
entity.setFailNum(entity.getFailNum() + 1);
|
||||
saveData(IEntity.STATE_FAIL, -1);
|
||||
handleSpeed(0);
|
||||
sendInState2Target(ISchedulers.FAIL);
|
||||
}
|
||||
|
||||
private void handleSpeed(long speed) {
|
||||
if (isConvertSpeed) {
|
||||
entity.setConvertSpeed(CommonUtil.formatFileSize(speed) + "/s");
|
||||
} else {
|
||||
entity.setSpeed(speed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将任务状态发送给下载器
|
||||
*
|
||||
* @param state {@link DownloadSchedulers#START}
|
||||
*/
|
||||
private void sendInState2Target(int state) {
|
||||
if (outHandler.get() != null) {
|
||||
outHandler.get().obtainMessage(state, task).sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
private void saveData(int state, long location) {
|
||||
if (state == IEntity.STATE_CANCEL) {
|
||||
entity.deleteData();
|
||||
} else {
|
||||
entity.setState(state);
|
||||
if (location != -1) {
|
||||
entity.setCurrentProgress(location);
|
||||
}
|
||||
entity.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
DownloadGroupTaskEntity taskEntity;
|
||||
Handler outHandler;
|
||||
String targetName;
|
||||
|
||||
public Builder(String targetName, DownloadGroupTaskEntity taskEntity) {
|
||||
CheckUtil.checkTaskEntity(taskEntity);
|
||||
this.targetName = targetName;
|
||||
this.taskEntity = taskEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置自定义Handler处理下载状态时间
|
||||
*
|
||||
* @param schedulers {@link ISchedulers}
|
||||
*/
|
||||
public DownloadGroupTask.Builder setOutHandler(ISchedulers schedulers) {
|
||||
this.outHandler = new Handler(schedulers);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DownloadGroupTask build() {
|
||||
DownloadGroupTask task = new DownloadGroupTask(taskEntity, outHandler);
|
||||
task.setTargetName(targetName);
|
||||
taskEntity.save();
|
||||
return task;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.download;
|
||||
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
import com.arialyy.aria.orm.OneToOne;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/7/1.
|
||||
*/
|
||||
public class DownloadGroupTaskEntity extends AbsTaskEntity<DownloadGroupEntity> {
|
||||
|
||||
@OneToOne(table = DownloadGroupEntity.class, key = "groupName") public DownloadGroupEntity entity;
|
||||
|
||||
@Override public DownloadGroupEntity getEntity() {
|
||||
return entity;
|
||||
}
|
||||
}
|
@ -17,17 +17,16 @@ package com.arialyy.aria.core.download;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.inf.AbsReceiver;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.core.inf.IReceiver;
|
||||
import com.arialyy.aria.core.command.CmdFactory;
|
||||
import com.arialyy.aria.core.command.AbsCmd;
|
||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
||||
import com.arialyy.aria.core.scheduler.DownloadSchedulers;
|
||||
import com.arialyy.aria.core.scheduler.ISchedulerListener;
|
||||
import com.arialyy.aria.orm.DbEntity;
|
||||
import com.arialyy.aria.util.CheckUtil;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@ -35,10 +34,8 @@ import java.util.Set;
|
||||
* Created by lyy on 2016/12/5.
|
||||
* 下载功能接收器
|
||||
*/
|
||||
public class DownloadReceiver implements IReceiver<DownloadEntity> {
|
||||
private static final String TAG = "DownloadReceiver";
|
||||
public String targetName;
|
||||
public Object obj;
|
||||
public class DownloadReceiver extends AbsReceiver<DownloadEntity> {
|
||||
private final String TAG = "DownloadReceiver";
|
||||
public ISchedulerListener<DownloadTask> listener;
|
||||
|
||||
/**
|
||||
@ -77,15 +74,17 @@ public class DownloadReceiver implements IReceiver<DownloadEntity> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加调度器回调
|
||||
*
|
||||
* @see #register()
|
||||
* 加载下载地址,如果任务组的中的下载地址改变了,则任务从新的一个任务组
|
||||
*/
|
||||
@Deprecated public DownloadReceiver addSchedulerListener(
|
||||
ISchedulerListener<DownloadTask> listener) {
|
||||
this.listener = listener;
|
||||
DownloadSchedulers.getInstance().addSchedulerListener(targetName, listener);
|
||||
return this;
|
||||
public DownloadGroupTarget load(List<String> urls) {
|
||||
CheckUtil.checkDownloadUrls(urls);
|
||||
DownloadGroupEntity entity =
|
||||
DbEntity.findData(DownloadGroupEntity.class, "urlHash=?", CommonUtil.getMd5Code(urls));
|
||||
|
||||
if (entity == null) {
|
||||
entity = new DownloadGroupEntity();
|
||||
}
|
||||
return new DownloadGroupTarget(entity, targetName, urls);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -103,6 +102,18 @@ public class DownloadReceiver implements IReceiver<DownloadEntity> {
|
||||
DownloadSchedulers.getInstance().unRegister(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加调度器回调
|
||||
*
|
||||
* @see #register()
|
||||
*/
|
||||
@Deprecated public DownloadReceiver addSchedulerListener(
|
||||
ISchedulerListener<DownloadTask> listener) {
|
||||
this.listener = listener;
|
||||
DownloadSchedulers.getInstance().addSchedulerListener(targetName, listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除回调
|
||||
*
|
||||
@ -142,9 +153,10 @@ public class DownloadReceiver implements IReceiver<DownloadEntity> {
|
||||
* 停止所有正在下载的任务,并清空等待队列。
|
||||
*/
|
||||
@Override public void stopAllTask() {
|
||||
final AriaManager ariaManager = AriaManager.getInstance(AriaManager.APP);
|
||||
ariaManager.setCmd(CmdFactory.getInstance()
|
||||
.createCmd(targetName, new DownloadTaskEntity(), CmdFactory.TASK_STOP_ALL)).exe();
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(NormalCmdFactory.getInstance()
|
||||
.createCmd(targetName, new DownloadTaskEntity(), NormalCmdFactory.TASK_STOP_ALL))
|
||||
.exe();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -153,23 +165,25 @@ public class DownloadReceiver implements IReceiver<DownloadEntity> {
|
||||
* 2.如果队列执行队列已经满了,则将所有任务添加到等待队列中
|
||||
*/
|
||||
public void resumeAllTask() {
|
||||
final AriaManager ariaManager = AriaManager.getInstance(AriaManager.APP);
|
||||
ariaManager.setCmd(CmdFactory.getInstance()
|
||||
.createCmd(targetName, new DownloadTaskEntity(), CmdFactory.TASK_RESUME_ALL)).exe();
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(NormalCmdFactory.getInstance()
|
||||
.createCmd(targetName, new DownloadTaskEntity(), NormalCmdFactory.TASK_RESUME_ALL))
|
||||
.exe();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除所有任务
|
||||
*
|
||||
* @param removeFile {@code true} 删除已经下载完成的任务,不仅删除下载记录,还会删除已经下载完成的文件,{@code false}
|
||||
* 如果文件已经下载完成,只删除下载记录
|
||||
*/
|
||||
@Override public void removeAllTask() {
|
||||
@Override public void removeAllTask(boolean removeFile) {
|
||||
final AriaManager ariaManager = AriaManager.getInstance(AriaManager.APP);
|
||||
List<DownloadEntity> allEntity = DbEntity.findAllData(DownloadEntity.class);
|
||||
List<AbsCmd> cancelCmds = new ArrayList<>();
|
||||
for (DownloadEntity entity : allEntity) {
|
||||
cancelCmds.add(
|
||||
CommonUtil.createCmd(targetName, new DownloadTaskEntity(entity), CmdFactory.TASK_CANCEL));
|
||||
}
|
||||
ariaManager.setCmds(cancelCmds).exe();
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(CommonUtil.createCmd(targetName, new DownloadTaskEntity(),
|
||||
NormalCmdFactory.TASK_CANCEL_ALL))
|
||||
.exe();
|
||||
|
||||
Set<String> keys = ariaManager.getReceiver().keySet();
|
||||
for (String key : keys) {
|
||||
IReceiver receiver = ariaManager.getReceiver().get(key);
|
||||
|
@ -17,31 +17,22 @@ package com.arialyy.aria.core.download;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.RequestEnum;
|
||||
import com.arialyy.aria.core.inf.AbsTarget;
|
||||
import com.arialyy.aria.core.inf.AbsNormalTarget;
|
||||
import com.arialyy.aria.core.queue.DownloadTaskQueue;
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2016/12/5.
|
||||
* https://github.com/AriaLyy/Aria
|
||||
*/
|
||||
public class DownloadTarget extends AbsTarget<DownloadEntity, DownloadTaskEntity> {
|
||||
public class DownloadTarget extends
|
||||
AbsNormalTarget<DownloadTarget, DownloadEntity, DownloadTaskEntity> {
|
||||
|
||||
DownloadTarget(DownloadEntity entity, String targetName) {
|
||||
this.entity = entity;
|
||||
this.targetName = targetName;
|
||||
taskEntity = new DownloadTaskEntity(entity);
|
||||
}
|
||||
|
||||
@Override public void pause() {
|
||||
super.pause();
|
||||
}
|
||||
|
||||
@Override public void resume() {
|
||||
super.resume();
|
||||
mEntity = entity;
|
||||
mTargetName = targetName;
|
||||
mTaskEntity = new DownloadTaskEntity();
|
||||
mTaskEntity.entity = mEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -65,54 +56,14 @@ public class DownloadTarget extends AbsTarget<DownloadEntity, DownloadTaskEntity
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override public int getPercent() {
|
||||
if (entity == null) {
|
||||
Log.e("DownloadTarget", "下载管理器中没有该任务");
|
||||
return 0;
|
||||
}
|
||||
if (entity.getFileSize() != 0) {
|
||||
return (int) (entity.getCurrentProgress() * 100 / entity.getFileSize());
|
||||
}
|
||||
return super.getPercent();
|
||||
}
|
||||
|
||||
/**
|
||||
* 给url请求添加头部
|
||||
*
|
||||
* @param key 头部key
|
||||
* @param header 头部value
|
||||
*/
|
||||
public DownloadTarget addHeader(@NonNull String key, @NonNull String header) {
|
||||
super._addHeader(key, header);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给url请求添加头部
|
||||
*
|
||||
* @param headers key为http头部的key,Value为http头对应的配置
|
||||
*/
|
||||
public DownloadTarget addHeaders(Map<String, String> headers) {
|
||||
super._addHeaders(headers);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载任务是否存在
|
||||
*/
|
||||
@Override public boolean taskExists() {
|
||||
return DownloadTaskQueue.getInstance().getTask(entity.getDownloadUrl()) != null;
|
||||
return DownloadTaskQueue.getInstance().getTask(mEntity.getDownloadUrl()) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置请求类型
|
||||
*
|
||||
* @param requestEnum {@link RequestEnum}
|
||||
*/
|
||||
public DownloadTarget setRequestMode(RequestEnum requestEnum) {
|
||||
super._setRequestMode(requestEnum);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置文件存储路径
|
||||
@ -122,8 +73,8 @@ public class DownloadTarget extends AbsTarget<DownloadEntity, DownloadTaskEntity
|
||||
throw new IllegalArgumentException("文件保持路径不能为null");
|
||||
}
|
||||
File file = new File(downloadPath);
|
||||
entity.setDownloadPath(downloadPath);
|
||||
entity.setFileName(file.getName());
|
||||
mEntity.setDownloadPath(downloadPath);
|
||||
mEntity.setFileName(file.getName());
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -136,7 +87,7 @@ public class DownloadTarget extends AbsTarget<DownloadEntity, DownloadTaskEntity
|
||||
if (TextUtils.isEmpty(downloadName)) {
|
||||
throw new IllegalArgumentException("文件名不能为null");
|
||||
}
|
||||
entity.setFileName(downloadName);
|
||||
mEntity.setFileName(downloadName);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -147,19 +98,19 @@ public class DownloadTarget extends AbsTarget<DownloadEntity, DownloadTaskEntity
|
||||
if (TextUtils.isEmpty(fileName)) {
|
||||
throw new IllegalArgumentException("文件名不能为null");
|
||||
}
|
||||
entity.setFileName(fileName);
|
||||
mEntity.setFileName(fileName);
|
||||
return this;
|
||||
}
|
||||
|
||||
private DownloadEntity getDownloadEntity() {
|
||||
return entity;
|
||||
return mEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否在下载
|
||||
*/
|
||||
public boolean isDownloading() {
|
||||
DownloadTask task = DownloadTaskQueue.getInstance().getTask(entity);
|
||||
DownloadTask task = DownloadTaskQueue.getInstance().getTask(mEntity);
|
||||
return task != null && task.isRunning();
|
||||
}
|
||||
}
|
||||
|
@ -20,9 +20,11 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.Aria;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.inf.AbsTask;
|
||||
import com.arialyy.aria.core.download.downloader.DownloadListener;
|
||||
import com.arialyy.aria.core.download.downloader.DownloadUtil;
|
||||
import com.arialyy.aria.core.download.downloader.IDownloadListener;
|
||||
import com.arialyy.aria.core.inf.AbsNormalTask;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.core.scheduler.ISchedulers;
|
||||
import com.arialyy.aria.util.CheckUtil;
|
||||
@ -34,20 +36,19 @@ import java.lang.ref.WeakReference;
|
||||
* Created by lyy on 2016/8/11.
|
||||
* 下载任务类
|
||||
*/
|
||||
public class DownloadTask extends AbsTask<DownloadTaskEntity, DownloadEntity> {
|
||||
public class DownloadTask extends AbsNormalTask<DownloadEntity> {
|
||||
public static final String TAG = "DownloadTask";
|
||||
|
||||
private IDownloadListener mListener;
|
||||
private Handler mOutHandler;
|
||||
private IDownloadUtil mUtil;
|
||||
private DownloadUtil mUtil;
|
||||
private boolean isWait = false;
|
||||
|
||||
private DownloadTask(DownloadTaskEntity taskEntity, Handler outHandler) {
|
||||
mEntity = taskEntity.downloadEntity;
|
||||
mEntity = taskEntity.getEntity();
|
||||
mOutHandler = outHandler;
|
||||
mContext = AriaManager.APP;
|
||||
mListener = new DListener(mContext, this, mOutHandler);
|
||||
mUtil = new DownloadUtil(mContext, taskEntity, mListener);
|
||||
mUtil = new DownloadUtil(taskEntity, mListener);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -97,7 +98,6 @@ public class DownloadTask extends AbsTask<DownloadTaskEntity, DownloadEntity> {
|
||||
* 暂停任务,并让任务处于等待状态
|
||||
*/
|
||||
@Override public void stopAndWait() {
|
||||
super.stopAndWait();
|
||||
stop(true);
|
||||
}
|
||||
|
||||
@ -142,11 +142,6 @@ public class DownloadTask extends AbsTask<DownloadTaskEntity, DownloadEntity> {
|
||||
if (mOutHandler != null) {
|
||||
mOutHandler.obtainMessage(ISchedulers.STOP, this).sendToTarget();
|
||||
}
|
||||
// 发送停止下载的广播
|
||||
Intent intent = CommonUtil.createIntent(mContext.getPackageName(), Aria.ACTION_STOP);
|
||||
intent.putExtra(Aria.CURRENT_LOCATION, mEntity.getCurrentProgress());
|
||||
intent.putExtra(Aria.DOWNLOAD_ENTITY, mEntity);
|
||||
mContext.sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,15 +154,8 @@ public class DownloadTask extends AbsTask<DownloadTaskEntity, DownloadEntity> {
|
||||
if (mOutHandler != null) {
|
||||
mOutHandler.obtainMessage(ISchedulers.CANCEL, this).sendToTarget();
|
||||
}
|
||||
//发送取消下载的广播
|
||||
Intent intent = CommonUtil.createIntent(mContext.getPackageName(), Aria.ACTION_CANCEL);
|
||||
intent.putExtra(Aria.DOWNLOAD_ENTITY, mEntity);
|
||||
mContext.sendBroadcast(intent);
|
||||
}
|
||||
mUtil.cancelDownload();
|
||||
mUtil.delConfigFile();
|
||||
mUtil.delTempFile();
|
||||
mEntity.deleteData();
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,7 +183,7 @@ public class DownloadTask extends AbsTask<DownloadTaskEntity, DownloadEntity> {
|
||||
public DownloadTask build() {
|
||||
DownloadTask task = new DownloadTask(taskEntity, outHandler);
|
||||
task.setTargetName(targetName);
|
||||
taskEntity.downloadEntity.save();
|
||||
taskEntity.getEntity().save();
|
||||
return task;
|
||||
}
|
||||
}
|
||||
@ -207,14 +195,12 @@ public class DownloadTask extends AbsTask<DownloadTaskEntity, DownloadEntity> {
|
||||
WeakReference<Handler> outHandler;
|
||||
WeakReference<DownloadTask> wTask;
|
||||
Context context;
|
||||
Intent sendIntent;
|
||||
long lastLen = 0; //上一次发送长度
|
||||
long lastTime = 0;
|
||||
long INTERVAL_TIME = 1000; //1m更新周期
|
||||
boolean isFirst = true;
|
||||
DownloadEntity downloadEntity;
|
||||
DownloadEntity entity;
|
||||
DownloadTask task;
|
||||
boolean isOpenBroadCast = false;
|
||||
boolean isConvertSpeed = false;
|
||||
|
||||
DListener(Context context, DownloadTask task, Handler outHandler) {
|
||||
@ -222,110 +208,84 @@ public class DownloadTask extends AbsTask<DownloadTaskEntity, DownloadEntity> {
|
||||
this.outHandler = new WeakReference<>(outHandler);
|
||||
this.wTask = new WeakReference<>(task);
|
||||
this.task = wTask.get();
|
||||
this.downloadEntity = this.task.getDownloadEntity();
|
||||
sendIntent = CommonUtil.createIntent(context.getPackageName(), Aria.ACTION_RUNNING);
|
||||
sendIntent.putExtra(Aria.DOWNLOAD_ENTITY, downloadEntity);
|
||||
this.entity = this.task.getDownloadEntity();
|
||||
final AriaManager manager = AriaManager.getInstance(context);
|
||||
isOpenBroadCast = manager.getDownloadConfig().isOpenBreadCast();
|
||||
isConvertSpeed = manager.getDownloadConfig().isConvertSpeed();
|
||||
}
|
||||
|
||||
@Override public void supportBreakpoint(boolean support) {
|
||||
super.supportBreakpoint(support);
|
||||
if (!support) {
|
||||
sendInState2Target(ISchedulers.SUPPORT_BREAK_POINT);
|
||||
sendIntent(Aria.ACTION_SUPPORT_BREAK_POINT, -1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void onPre() {
|
||||
super.onPre();
|
||||
downloadEntity.setState(IEntity.STATE_PRE);
|
||||
sendInState2Target(ISchedulers.PRE);
|
||||
sendIntent(Aria.ACTION_PRE, -1);
|
||||
saveData(IEntity.STATE_PRE, -1);
|
||||
}
|
||||
|
||||
@Override public void onPostPre(long fileSize) {
|
||||
super.onPostPre(fileSize);
|
||||
downloadEntity.setFileSize(fileSize);
|
||||
downloadEntity.setState(IEntity.STATE_POST_PRE);
|
||||
entity.setFileSize(fileSize);
|
||||
sendInState2Target(ISchedulers.POST_PRE);
|
||||
sendIntent(Aria.ACTION_POST_PRE, -1);
|
||||
saveData(IEntity.STATE_POST_PRE, -1);
|
||||
}
|
||||
|
||||
@Override public void onResume(long resumeLocation) {
|
||||
super.onResume(resumeLocation);
|
||||
downloadEntity.setState(IEntity.STATE_RUNNING);
|
||||
sendInState2Target(ISchedulers.RESUME);
|
||||
sendIntent(Aria.ACTION_RESUME, resumeLocation);
|
||||
saveData(IEntity.STATE_RUNNING, resumeLocation);
|
||||
}
|
||||
|
||||
@Override public void onStart(long startLocation) {
|
||||
super.onStart(startLocation);
|
||||
downloadEntity.setState(IEntity.STATE_RUNNING);
|
||||
sendInState2Target(ISchedulers.START);
|
||||
sendIntent(Aria.ACTION_START, startLocation);
|
||||
saveData(IEntity.STATE_RUNNING, startLocation);
|
||||
}
|
||||
|
||||
@Override public void onProgress(long currentLocation) {
|
||||
super.onProgress(currentLocation);
|
||||
if (System.currentTimeMillis() - lastTime > INTERVAL_TIME) {
|
||||
long speed = currentLocation - lastLen;
|
||||
sendIntent.putExtra(Aria.CURRENT_LOCATION, currentLocation);
|
||||
sendIntent.putExtra(Aria.CURRENT_SPEED, speed);
|
||||
lastTime = System.currentTimeMillis();
|
||||
if (isFirst) {
|
||||
speed = 0;
|
||||
isFirst = false;
|
||||
}
|
||||
handleSpeed(speed);
|
||||
downloadEntity.setCurrentProgress(currentLocation);
|
||||
entity.setCurrentProgress(currentLocation);
|
||||
lastLen = currentLocation;
|
||||
sendInState2Target(ISchedulers.RUNNING);
|
||||
context.sendBroadcast(sendIntent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void onStop(long stopLocation) {
|
||||
super.onStop(stopLocation);
|
||||
downloadEntity.setState(task.isWait ? IEntity.STATE_WAIT : IEntity.STATE_STOP);
|
||||
handleSpeed(0);
|
||||
sendInState2Target(ISchedulers.STOP);
|
||||
sendIntent(Aria.ACTION_STOP, stopLocation);
|
||||
saveData(task.isWait ? IEntity.STATE_WAIT : IEntity.STATE_STOP, stopLocation);
|
||||
}
|
||||
|
||||
@Override public void onCancel() {
|
||||
super.onCancel();
|
||||
downloadEntity.setState(IEntity.STATE_CANCEL);
|
||||
handleSpeed(0);
|
||||
sendInState2Target(ISchedulers.CANCEL);
|
||||
sendIntent(Aria.ACTION_CANCEL, -1);
|
||||
downloadEntity.deleteData();
|
||||
saveData(IEntity.STATE_CANCEL, -1);
|
||||
entity.deleteData();
|
||||
}
|
||||
|
||||
@Override public void onComplete() {
|
||||
super.onComplete();
|
||||
downloadEntity.setState(IEntity.STATE_COMPLETE);
|
||||
downloadEntity.setDownloadComplete(true);
|
||||
handleSpeed(0);
|
||||
sendInState2Target(ISchedulers.COMPLETE);
|
||||
sendIntent(Aria.ACTION_COMPLETE, downloadEntity.getFileSize());
|
||||
saveData(IEntity.STATE_COMPLETE, entity.getFileSize());
|
||||
}
|
||||
|
||||
@Override public void onFail() {
|
||||
super.onFail();
|
||||
downloadEntity.setFailNum(downloadEntity.getFailNum() + 1);
|
||||
downloadEntity.setState(IEntity.STATE_FAIL);
|
||||
entity.setFailNum(entity.getFailNum() + 1);
|
||||
handleSpeed(0);
|
||||
sendInState2Target(ISchedulers.FAIL);
|
||||
sendIntent(Aria.ACTION_FAIL, -1);
|
||||
saveData(IEntity.STATE_FAIL, -1);
|
||||
}
|
||||
|
||||
private void handleSpeed(long speed) {
|
||||
if (isConvertSpeed) {
|
||||
downloadEntity.setConvertSpeed(CommonUtil.formatFileSize(speed) + "/s");
|
||||
entity.setConvertSpeed(CommonUtil.formatFileSize(speed) + "/s");
|
||||
} else {
|
||||
downloadEntity.setSpeed(speed);
|
||||
entity.setSpeed(speed);
|
||||
}
|
||||
}
|
||||
|
||||
@ -340,17 +300,11 @@ public class DownloadTask extends AbsTask<DownloadTaskEntity, DownloadEntity> {
|
||||
}
|
||||
}
|
||||
|
||||
private void sendIntent(String action, long location) {
|
||||
downloadEntity.setDownloadComplete(action.equals(Aria.ACTION_COMPLETE));
|
||||
downloadEntity.setCurrentProgress(location);
|
||||
downloadEntity.update();
|
||||
if (!isOpenBroadCast) return;
|
||||
Intent intent = CommonUtil.createIntent(context.getPackageName(), action);
|
||||
intent.putExtra(Aria.DOWNLOAD_ENTITY, downloadEntity);
|
||||
if (location != -1) {
|
||||
intent.putExtra(Aria.CURRENT_LOCATION, location);
|
||||
}
|
||||
context.sendBroadcast(intent);
|
||||
private void saveData(int state, long location) {
|
||||
entity.setState(state);
|
||||
entity.setDownloadComplete(state == IEntity.STATE_COMPLETE);
|
||||
entity.setCurrentProgress(location);
|
||||
entity.update();
|
||||
}
|
||||
}
|
||||
}
|
@ -16,22 +16,20 @@
|
||||
package com.arialyy.aria.core.download;
|
||||
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
import com.arialyy.aria.orm.OneToOne;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2017/1/23.
|
||||
* 下载任务实体
|
||||
*/
|
||||
public class DownloadTaskEntity extends AbsTaskEntity {
|
||||
public class DownloadTaskEntity extends AbsTaskEntity<DownloadEntity> {
|
||||
|
||||
public DownloadEntity downloadEntity;
|
||||
@OneToOne(table = DownloadEntity.class, key = "downloadUrl") public DownloadEntity entity;
|
||||
|
||||
public DownloadTaskEntity(){}
|
||||
|
||||
public DownloadTaskEntity(DownloadEntity downloadEntity) {
|
||||
this.downloadEntity = downloadEntity;
|
||||
public DownloadTaskEntity() {
|
||||
}
|
||||
|
||||
@Override public DownloadEntity getEntity() {
|
||||
return downloadEntity;
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
@ -1,496 +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;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2015/8/25.
|
||||
* 下载工具类
|
||||
*/
|
||||
class DownloadUtil implements IDownloadUtil, Runnable {
|
||||
private static final String TAG = "DownloadUtil";
|
||||
/**
|
||||
* 线程数
|
||||
*/
|
||||
private int THREAD_NUM;
|
||||
/**
|
||||
* 小于1m的文件不启用多线程
|
||||
*/
|
||||
private static final long SUB_LEN = 1024 * 1024;
|
||||
//下载监听
|
||||
private IDownloadListener mListener;
|
||||
private int mConnectTimeOut = 0; //连接超时时间
|
||||
private boolean isNewTask = true;
|
||||
private boolean isSupportBreakpoint = true;
|
||||
private Context mContext;
|
||||
private DownloadEntity mDownloadEntity;
|
||||
private DownloadTaskEntity mDownloadTaskEntity;
|
||||
private ExecutorService mFixedThreadPool;
|
||||
private File mDownloadFile; //下载的文件
|
||||
private File mConfigFile;//下载信息配置文件
|
||||
private SparseArray<Runnable> mTask = new SparseArray<>();
|
||||
private DownloadStateConstance CONSTANCE;
|
||||
|
||||
DownloadUtil(Context context, DownloadTaskEntity entity, IDownloadListener downloadListener) {
|
||||
mDownloadEntity = entity.downloadEntity;
|
||||
mContext = context.getApplicationContext();
|
||||
mDownloadTaskEntity = entity;
|
||||
mListener = downloadListener;
|
||||
// 线程下载数改变后,新的下载才会生效
|
||||
//mFixedThreadPool = Executors.newFixedThreadPool(Integer.MAX_VALUE);
|
||||
CONSTANCE = new DownloadStateConstance();
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
mConnectTimeOut = AriaManager.getInstance(mContext).getDownloadConfig().getConnectTimeOut();
|
||||
mDownloadFile = new File(mDownloadTaskEntity.downloadEntity.getDownloadPath());
|
||||
//读取已完成的线程数
|
||||
mConfigFile = new File(mContext.getFilesDir().getPath()
|
||||
+ AriaManager.DOWNLOAD_TEMP_DIR
|
||||
+ mDownloadFile.getName()
|
||||
+ ".properties");
|
||||
try {
|
||||
if (!mConfigFile.exists()) { //记录文件被删除,则重新下载
|
||||
isNewTask = true;
|
||||
CommonUtil.createFile(mConfigFile.getPath());
|
||||
} else {
|
||||
isNewTask = !mDownloadFile.exists();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
failDownload("下载失败,记录文件被删除");
|
||||
}
|
||||
}
|
||||
|
||||
public IDownloadListener getListener() {
|
||||
return mListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前下载位置
|
||||
*/
|
||||
@Override public long getCurrentLocation() {
|
||||
return CONSTANCE.CURRENT_LOCATION;
|
||||
}
|
||||
|
||||
@Override public boolean isDownloading() {
|
||||
return CONSTANCE.isDownloading;
|
||||
}
|
||||
|
||||
public void setMaxSpeed(double maxSpeed) {
|
||||
for (int i = 0; i < THREAD_NUM; i++) {
|
||||
SingleThreadTask task = (SingleThreadTask) mTask.get(i);
|
||||
if (task != null) {
|
||||
task.setMaxSpeed(maxSpeed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消下载
|
||||
*/
|
||||
@Override public void cancelDownload() {
|
||||
CONSTANCE.isCancel = true;
|
||||
CONSTANCE.isDownloading = false;
|
||||
if (mFixedThreadPool != null) {
|
||||
mFixedThreadPool.shutdown();
|
||||
}
|
||||
for (int i = 0; i < THREAD_NUM; i++) {
|
||||
SingleThreadTask task = (SingleThreadTask) mTask.get(i);
|
||||
if (task != null) {
|
||||
task.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止下载
|
||||
*/
|
||||
@Override public void stopDownload() {
|
||||
CONSTANCE.isStop = true;
|
||||
CONSTANCE.isDownloading = false;
|
||||
if (mFixedThreadPool != null) {
|
||||
mFixedThreadPool.shutdown();
|
||||
}
|
||||
for (int i = 0; i < THREAD_NUM; i++) {
|
||||
SingleThreadTask task = (SingleThreadTask) mTask.get(i);
|
||||
if (task != null) {
|
||||
task.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除下载记录文件
|
||||
*/
|
||||
@Override public void delConfigFile() {
|
||||
if (mContext != null && mDownloadEntity != null) {
|
||||
File dFile = new File(mDownloadEntity.getDownloadPath());
|
||||
File config =
|
||||
new File(mContext.getFilesDir().getPath() + "/temp/" + dFile.getName() + ".properties");
|
||||
if (config.exists()) {
|
||||
config.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除temp文件
|
||||
*/
|
||||
@Override public void delTempFile() {
|
||||
if (mContext != null && mDownloadEntity != null) {
|
||||
File dFile = new File(mDownloadEntity.getDownloadPath());
|
||||
if (dFile.exists()) {
|
||||
dFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 多线程断点续传下载文件,开始下载
|
||||
*/
|
||||
@Override public void startDownload() {
|
||||
CONSTANCE.cleanState();
|
||||
mListener.onPre();
|
||||
new Thread(this).start();
|
||||
}
|
||||
|
||||
@Override public void resumeDownload() {
|
||||
startDownload();
|
||||
}
|
||||
|
||||
private void failDownload(String msg) {
|
||||
Log.e(TAG, msg);
|
||||
CONSTANCE.isDownloading = false;
|
||||
mListener.onFail();
|
||||
}
|
||||
|
||||
@Override public void run() {
|
||||
try {
|
||||
URL url = new URL(mDownloadEntity.getDownloadUrl());
|
||||
HttpURLConnection conn = ConnectionHelp.handleConnection(url);
|
||||
conn = ConnectionHelp.setConnectParam(mDownloadTaskEntity, conn);
|
||||
conn.setRequestProperty("Range", "bytes=" + 0 + "-");
|
||||
conn.setConnectTimeout(mConnectTimeOut);
|
||||
conn.connect();
|
||||
handleConnect(conn);
|
||||
} catch (IOException e) {
|
||||
failDownload("下载失败【downloadUrl:"
|
||||
+ mDownloadEntity.getDownloadUrl()
|
||||
+ "】\n【filePath:"
|
||||
+ mDownloadFile.getPath()
|
||||
+ "】\n"
|
||||
+ CommonUtil.getPrintException(e));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理状态吗
|
||||
*/
|
||||
private void handleConnect(HttpURLConnection conn) throws IOException {
|
||||
int len = conn.getContentLength();
|
||||
//if (len < 0) { //网络被劫持时会出现这个问题
|
||||
// failDownload("下载失败,网络被劫持");
|
||||
// return;
|
||||
//}
|
||||
int code = conn.getResponseCode();
|
||||
//https://zh.wikipedia.org/wiki/HTTP%E7%8A%B6%E6%80%81%E7%A0%81
|
||||
//206支持断点
|
||||
if (code == HttpURLConnection.HTTP_PARTIAL) {
|
||||
if (!checkLen(len)) return;
|
||||
isSupportBreakpoint = true;
|
||||
mListener.supportBreakpoint(true);
|
||||
handleBreakpoint(conn);
|
||||
} else if (code == HttpURLConnection.HTTP_OK) {
|
||||
//在conn.setRequestProperty("Range", "bytes=" + 0 + "-");下,200为不支持断点状态
|
||||
if (!checkLen(len)) return;
|
||||
isSupportBreakpoint = false;
|
||||
mListener.supportBreakpoint(false);
|
||||
Log.w(TAG, "该下载链接不支持断点下载");
|
||||
handleBreakpoint(conn);
|
||||
} else if (code == HttpURLConnection.HTTP_NOT_FOUND) {
|
||||
Log.w(TAG, "任务【" + mDownloadEntity.getDownloadUrl() + "】下载失败,错误码:404");
|
||||
mListener.onCancel();
|
||||
} else if (code == HttpURLConnection.HTTP_MOVED_TEMP
|
||||
|| code == HttpURLConnection.HTTP_MOVED_PERM
|
||||
|| code == HttpURLConnection.HTTP_SEE_OTHER) {
|
||||
handle302Turn(conn);
|
||||
} else {
|
||||
failDownload("任务【" + mDownloadEntity.getDownloadUrl() + "】下载失败,错误码:" + code);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查长度是否合法
|
||||
*
|
||||
* @param len 从服务器获取的文件长度
|
||||
* @return true, 合法
|
||||
*/
|
||||
private boolean checkLen(long len) {
|
||||
if (len < 0) {
|
||||
failDownload("任务【" + mDownloadEntity.getDownloadUrl() + "】下载失败,文件长度小于0");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理30x跳转
|
||||
*/
|
||||
private void handle302Turn(HttpURLConnection conn) throws IOException {
|
||||
String newUrl = conn.getHeaderField(mDownloadTaskEntity.redirectUrlKey);
|
||||
Log.d(TAG, "30x跳转,新url为【" + newUrl + "】");
|
||||
mDownloadEntity.setRedirect(true);
|
||||
mDownloadEntity.setRedirectUrl(newUrl);
|
||||
mDownloadEntity.update();
|
||||
String cookies = conn.getHeaderField("Set-Cookie");
|
||||
conn = (HttpURLConnection) new URL(newUrl).openConnection();
|
||||
conn = ConnectionHelp.setConnectParam(mDownloadTaskEntity, conn);
|
||||
conn.setRequestProperty("Cookie", cookies);
|
||||
conn.setRequestProperty("Range", "bytes=" + 0 + "-");
|
||||
conn.setConnectTimeout(mConnectTimeOut);
|
||||
conn.connect();
|
||||
|
||||
handleConnect(conn);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理断点
|
||||
*/
|
||||
private void handleBreakpoint(HttpURLConnection conn) throws IOException {
|
||||
//不支持断点只能单线程下载
|
||||
if (!isSupportBreakpoint) {
|
||||
handleNoSupportBreakpointDownload(conn);
|
||||
return;
|
||||
}
|
||||
int fileLength = conn.getContentLength();
|
||||
Properties pro = createConfigFile(fileLength);
|
||||
int blockSize = fileLength / THREAD_NUM;
|
||||
int[] recordL = new int[THREAD_NUM];
|
||||
int rl = 0;
|
||||
for (int i = 0; i < THREAD_NUM; i++) {
|
||||
recordL[i] = -1;
|
||||
}
|
||||
for (int i = 0; i < THREAD_NUM; i++) {
|
||||
long startL = i * blockSize, endL = (i + 1) * blockSize;
|
||||
Object state = pro.getProperty(mDownloadFile.getName() + "_state_" + i);
|
||||
if (state != null && Integer.parseInt(state + "") == 1) { //该线程已经完成
|
||||
if (resumeRecordLocation(i, startL, endL)) return;
|
||||
continue;
|
||||
}
|
||||
//分配下载位置
|
||||
Object record = pro.getProperty(mDownloadFile.getName() + "_record_" + i);
|
||||
//如果有记录,则恢复下载
|
||||
if (!isNewTask && record != null && Long.parseLong(record + "") > 0) {
|
||||
Long r = Long.parseLong(record + "");
|
||||
CONSTANCE.CURRENT_LOCATION += r - startL;
|
||||
Log.d(TAG, "任务【" + mDownloadEntity.getFileName() + "】线程__" + i + "__恢复下载");
|
||||
mListener.onChildResume(r);
|
||||
startL = r;
|
||||
recordL[rl] = i;
|
||||
rl++;
|
||||
} else {
|
||||
handleNewTask(fileLength);
|
||||
}
|
||||
if (isNewTask) {
|
||||
recordL[rl] = i;
|
||||
rl++;
|
||||
}
|
||||
if (i == (THREAD_NUM - 1)) {
|
||||
//最后一个线程的结束位置即为文件的总长度
|
||||
endL = fileLength;
|
||||
}
|
||||
addSingleTask(i, startL, endL, fileLength);
|
||||
}
|
||||
startSingleTask(recordL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理不支持断点的下载
|
||||
*/
|
||||
private void handleNoSupportBreakpointDownload(HttpURLConnection conn) {
|
||||
ChildThreadConfigEntity entity = new ChildThreadConfigEntity();
|
||||
long len = conn.getContentLength();
|
||||
entity.FILE_SIZE = len;
|
||||
entity.DOWNLOAD_URL = mDownloadEntity.isRedirect() ? mDownloadEntity.getRedirectUrl()
|
||||
: mDownloadEntity.getDownloadUrl();
|
||||
entity.TEMP_FILE = mDownloadFile;
|
||||
entity.THREAD_ID = 0;
|
||||
entity.START_LOCATION = 0;
|
||||
entity.END_LOCATION = entity.FILE_SIZE;
|
||||
entity.CONFIG_FILE_PATH = mConfigFile.getPath();
|
||||
entity.IS_SUPPORT_BREAK_POINT = isSupportBreakpoint;
|
||||
entity.DOWNLOAD_TASK_ENTITY = mDownloadTaskEntity;
|
||||
THREAD_NUM = 1;
|
||||
CONSTANCE.THREAD_NUM = THREAD_NUM;
|
||||
SingleThreadTask task = new SingleThreadTask(CONSTANCE, mListener, entity);
|
||||
mTask.put(0, task);
|
||||
mFixedThreadPool.execute(task);
|
||||
mListener.onPostPre(len);
|
||||
mListener.onStart(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建配置文件
|
||||
*/
|
||||
private Properties createConfigFile(long fileLength) throws IOException {
|
||||
Properties pro = null;
|
||||
//必须建一个文件
|
||||
CommonUtil.createFile(mDownloadFile.getPath());
|
||||
BufferedRandomAccessFile file =
|
||||
new BufferedRandomAccessFile(new File(mDownloadFile.getPath()), "rwd", 8192);
|
||||
//设置文件长度
|
||||
file.setLength(fileLength);
|
||||
file.close();
|
||||
mListener.onPostPre(fileLength);
|
||||
//分配每条线程的下载区间
|
||||
pro = CommonUtil.loadConfig(mConfigFile);
|
||||
if (pro.isEmpty()) {
|
||||
handleNewTask(fileLength);
|
||||
} else {
|
||||
Set<Object> keys = pro.keySet();
|
||||
int num = 0;
|
||||
for (Object key : keys) {
|
||||
if (String.valueOf(key).contains("_record_")) {
|
||||
num++;
|
||||
}
|
||||
}
|
||||
if (num == 0) {
|
||||
handleNewTask(fileLength);
|
||||
return pro;
|
||||
}
|
||||
THREAD_NUM = num;
|
||||
for (int i = 0; i < THREAD_NUM; i++) {
|
||||
if (pro.getProperty(mDownloadFile.getName() + "_record_" + i) == null) {
|
||||
Object state = pro.getProperty(mDownloadFile.getName() + "_state_" + i);
|
||||
if (state != null && Integer.parseInt(state + "") == 1) {
|
||||
continue;
|
||||
}
|
||||
handleNewTask(fileLength);
|
||||
return pro;
|
||||
}
|
||||
}
|
||||
isNewTask = false;
|
||||
}
|
||||
return pro;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理新任务
|
||||
*/
|
||||
private void handleNewTask(long fileLength) {
|
||||
isNewTask = true;
|
||||
THREAD_NUM = fileLength < SUB_LEN ? 1
|
||||
: AriaManager.getInstance(mContext).getDownloadConfig().getThreadNum();
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复记录地址
|
||||
*
|
||||
* @return true 表示下载完成
|
||||
*/
|
||||
private boolean resumeRecordLocation(int i, long startL, long endL) {
|
||||
CONSTANCE.CURRENT_LOCATION += endL - startL;
|
||||
Log.d(TAG, "++++++++++ 线程_" + i + "_已经下载完成 ++++++++++");
|
||||
CONSTANCE.COMPLETE_THREAD_NUM++;
|
||||
CONSTANCE.STOP_NUM++;
|
||||
CONSTANCE.CANCEL_NUM++;
|
||||
if (CONSTANCE.isComplete()) {
|
||||
if (mConfigFile.exists()) {
|
||||
mConfigFile.delete();
|
||||
}
|
||||
mListener.onComplete();
|
||||
CONSTANCE.isDownloading = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建单线程任务
|
||||
*/
|
||||
private void addSingleTask(int i, long startL, long endL, long fileLength) {
|
||||
ChildThreadConfigEntity entity = new ChildThreadConfigEntity();
|
||||
entity.FILE_SIZE = fileLength;
|
||||
entity.DOWNLOAD_URL = mDownloadEntity.isRedirect() ? mDownloadEntity.getRedirectUrl()
|
||||
: mDownloadEntity.getDownloadUrl();
|
||||
entity.TEMP_FILE = mDownloadFile;
|
||||
entity.THREAD_ID = i;
|
||||
entity.START_LOCATION = startL;
|
||||
entity.END_LOCATION = endL;
|
||||
entity.CONFIG_FILE_PATH = mConfigFile.getPath();
|
||||
entity.IS_SUPPORT_BREAK_POINT = isSupportBreakpoint;
|
||||
entity.DOWNLOAD_TASK_ENTITY = mDownloadTaskEntity;
|
||||
CONSTANCE.THREAD_NUM = THREAD_NUM;
|
||||
SingleThreadTask task = new SingleThreadTask(CONSTANCE, mListener, entity);
|
||||
mTask.put(i, task);
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动单线程下载任务
|
||||
*/
|
||||
private void startSingleTask(int[] recordL) {
|
||||
if (CONSTANCE.CURRENT_LOCATION > 0) {
|
||||
mListener.onResume(CONSTANCE.CURRENT_LOCATION);
|
||||
} else {
|
||||
mListener.onStart(CONSTANCE.CURRENT_LOCATION);
|
||||
}
|
||||
mFixedThreadPool = Executors.newFixedThreadPool(recordL.length);
|
||||
for (int l : recordL) {
|
||||
if (l == -1) continue;
|
||||
Runnable task = mTask.get(l);
|
||||
if (task != null) {
|
||||
mFixedThreadPool.execute(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 子线程下载信息类
|
||||
*/
|
||||
final static class ChildThreadConfigEntity {
|
||||
//线程Id
|
||||
int THREAD_ID;
|
||||
//下载文件大小
|
||||
long FILE_SIZE;
|
||||
//子线程启动下载位置
|
||||
long START_LOCATION;
|
||||
//子线程结束下载位置
|
||||
long END_LOCATION;
|
||||
//下载路径
|
||||
File TEMP_FILE;
|
||||
String DOWNLOAD_URL;
|
||||
String CONFIG_FILE_PATH;
|
||||
DownloadTaskEntity DOWNLOAD_TASK_ENTITY;
|
||||
boolean IS_SUPPORT_BREAK_POINT = true;
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.arialyy.aria.core.download.downloader;
|
||||
|
||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* 子线程下载信息类
|
||||
*/
|
||||
final class ChildThreadConfigEntity {
|
||||
//线程Id
|
||||
int THREAD_ID;
|
||||
//下载文件大小
|
||||
long FILE_SIZE;
|
||||
//子线程启动下载位置
|
||||
long START_LOCATION;
|
||||
//子线程结束下载位置
|
||||
long END_LOCATION;
|
||||
//下载路径
|
||||
File TEMP_FILE;
|
||||
String DOWNLOAD_URL;
|
||||
String CONFIG_FILE_PATH;
|
||||
DownloadTaskEntity DOWNLOAD_TASK_ENTITY;
|
||||
boolean IS_SUPPORT_BREAK_POINT = true;
|
||||
}
|
@ -13,8 +13,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.download;
|
||||
package com.arialyy.aria.core.download.downloader;
|
||||
|
||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||
import com.arialyy.aria.util.SSLContextUtil;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
@ -0,0 +1,312 @@
|
||||
/*
|
||||
* 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.util.SparseArray;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
|
||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.orm.DbEntity;
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/30.
|
||||
* 任务组下载工具
|
||||
*/
|
||||
public class DownloadGroupUtil implements IDownloadUtil {
|
||||
private static final String TAG = "DownloadGroupUtil";
|
||||
/**
|
||||
* 任务组所有任务总大小
|
||||
*/
|
||||
private long mTotalSize = 0;
|
||||
private long mCurrentProgress = 0;
|
||||
private ExecutorService mInfoPool;
|
||||
private ExecutorService mExePool;
|
||||
private IDownloadListener mListener;
|
||||
private DownloadGroupTaskEntity mTaskEntity;
|
||||
private boolean isRunning = true;
|
||||
private Timer mTimer;
|
||||
/**
|
||||
* 初始化完成的任务书数
|
||||
*/
|
||||
private int mInitNum = 0;
|
||||
/**
|
||||
* 初始化失败的任务数
|
||||
*/
|
||||
private int mFailNum = 0;
|
||||
/**
|
||||
* 保存所有没有下载完成的任务,key为下载地址
|
||||
*/
|
||||
private Map<String, DownloadTaskEntity> mExeMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 下载失败的映射表,key为下载地址
|
||||
*/
|
||||
private Map<String, DownloadTaskEntity> mFailMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 下载器映射表,key为下载地址
|
||||
*/
|
||||
private Map<String, Downloader> mDownloaderMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 文件信息回调组
|
||||
*/
|
||||
private SparseArray<FileInfoThread.OnFileInfoCallback> mFileInfoCallbacks = new SparseArray<>();
|
||||
|
||||
public DownloadGroupUtil(IDownloadListener listener, DownloadGroupTaskEntity taskEntity) {
|
||||
mListener = listener;
|
||||
mTaskEntity = taskEntity;
|
||||
mInfoPool = Executors.newCachedThreadPool();
|
||||
mExePool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
|
||||
|
||||
for (DownloadEntity entity : mTaskEntity.entity.getChild()) {
|
||||
File file = new File(entity.getDownloadPath());
|
||||
if (entity.isDownloadComplete() && file.exists()) {
|
||||
mTotalSize += entity.getFileSize();
|
||||
} else {
|
||||
mExeMap.put(entity.getDownloadUrl(), createDownloadTask(entity));
|
||||
}
|
||||
mCurrentProgress += entity.getCurrentProgress();
|
||||
}
|
||||
}
|
||||
|
||||
@Override public long getFileSize() {
|
||||
return mTotalSize;
|
||||
}
|
||||
|
||||
@Override public long getCurrentLocation() {
|
||||
return mCurrentProgress;
|
||||
}
|
||||
|
||||
@Override public boolean isDownloading() {
|
||||
return isRunning;
|
||||
}
|
||||
|
||||
@Override public void cancelDownload() {
|
||||
isRunning = false;
|
||||
closeTimer();
|
||||
if (!mInfoPool.isShutdown()) {
|
||||
mInfoPool.shutdown();
|
||||
}
|
||||
if (!mExePool.isShutdown()) {
|
||||
mExePool.shutdown();
|
||||
}
|
||||
|
||||
Set<String> keys = mDownloaderMap.keySet();
|
||||
for (String key : keys) {
|
||||
Downloader dt = mDownloaderMap.get(key);
|
||||
if (dt != null) {
|
||||
dt.cancelDownload();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void stopDownload() {
|
||||
isRunning = false;
|
||||
closeTimer();
|
||||
if (!mInfoPool.isShutdown()) {
|
||||
mInfoPool.shutdown();
|
||||
}
|
||||
if (!mExePool.isShutdown()) {
|
||||
mExePool.shutdown();
|
||||
}
|
||||
|
||||
Set<String> keys = mDownloaderMap.keySet();
|
||||
for (String key : keys) {
|
||||
Downloader dt = mDownloaderMap.get(key);
|
||||
if (dt != null) {
|
||||
dt.stopDownload();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void startDownload() {
|
||||
isRunning = true;
|
||||
Set<String> keys = mExeMap.keySet();
|
||||
mListener.onPre();
|
||||
for (String key : keys) {
|
||||
DownloadTaskEntity taskEntity = mExeMap.get(key);
|
||||
if (taskEntity != null) {
|
||||
mInfoPool.execute(createFileInfoThread(taskEntity));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void resumeDownload() {
|
||||
startDownload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建文件信息获取线程
|
||||
*/
|
||||
private FileInfoThread createFileInfoThread(DownloadTaskEntity taskEntity) {
|
||||
FileInfoThread.OnFileInfoCallback callback = mFileInfoCallbacks.get(taskEntity.hashCode());
|
||||
|
||||
if (callback == null) {
|
||||
callback = new FileInfoThread.OnFileInfoCallback() {
|
||||
int failNum = 0;
|
||||
|
||||
@Override public void onComplete(String url, int code) {
|
||||
DownloadTaskEntity te = mExeMap.get(url);
|
||||
if (te != null) {
|
||||
mTotalSize += te.getEntity().getFileSize();
|
||||
startChildDownload(te);
|
||||
}
|
||||
mInitNum++;
|
||||
if (mInitNum + mFailNum == mTaskEntity.getEntity().getChild().size()) {
|
||||
startRunningFlow();
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void onFail(String url, String errorMsg) {
|
||||
DownloadTaskEntity te = mExeMap.get(url);
|
||||
if (te != null) {
|
||||
mFailMap.put(url, te);
|
||||
mFileInfoCallbacks.put(te.hashCode(), this);
|
||||
}
|
||||
mFailNum++;
|
||||
failNum++;
|
||||
if (failNum < 10) {
|
||||
mInfoPool.execute(createFileInfoThread(te));
|
||||
}
|
||||
if (mInitNum + mFailNum == mTaskEntity.getEntity().getChild().size()) {
|
||||
startRunningFlow();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return new FileInfoThread(taskEntity, callback);
|
||||
}
|
||||
|
||||
private void closeTimer() {
|
||||
if (mTimer != null) {
|
||||
mTimer.purge();
|
||||
mTimer.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始进度流程
|
||||
*/
|
||||
private void startRunningFlow() {
|
||||
mListener.onPostPre(mTotalSize);
|
||||
mListener.onStart(mCurrentProgress);
|
||||
closeTimer();
|
||||
mTimer = new Timer(true);
|
||||
mTimer.schedule(new TimerTask() {
|
||||
@Override public void run() {
|
||||
mListener.onProgress(mCurrentProgress);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动子任务下载器
|
||||
*/
|
||||
private void startChildDownload(DownloadTaskEntity taskEntity) {
|
||||
ChildDownloadListener listener = new ChildDownloadListener(taskEntity);
|
||||
Downloader dt = new Downloader(listener, taskEntity);
|
||||
mDownloaderMap.put(taskEntity.getEntity().getDownloadUrl(), dt);
|
||||
mExePool.execute(dt);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建子任务下载信息
|
||||
*/
|
||||
private DownloadTaskEntity createDownloadTask(DownloadEntity entity) {
|
||||
DownloadTaskEntity taskEntity =
|
||||
DbEntity.findData(DownloadTaskEntity.class, "key=?", entity.getDownloadUrl());
|
||||
if (taskEntity != null) {
|
||||
return taskEntity;
|
||||
}
|
||||
taskEntity = new DownloadTaskEntity();
|
||||
taskEntity.entity = entity;
|
||||
taskEntity.headers = mTaskEntity.headers;
|
||||
taskEntity.requestEnum = mTaskEntity.requestEnum;
|
||||
taskEntity.redirectUrlKey = mTaskEntity.redirectUrlKey;
|
||||
taskEntity.removeFile = mTaskEntity.removeFile;
|
||||
return taskEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 子任务事件监听
|
||||
*/
|
||||
private class ChildDownloadListener extends DownloadListener {
|
||||
|
||||
DownloadTaskEntity taskEntity;
|
||||
DownloadEntity entity;
|
||||
|
||||
ChildDownloadListener(DownloadTaskEntity entity) {
|
||||
this.taskEntity = entity;
|
||||
this.entity = taskEntity.getEntity();
|
||||
}
|
||||
|
||||
@Override public void onPre() {
|
||||
saveData(IEntity.STATE_PRE, -1);
|
||||
}
|
||||
|
||||
@Override public void onPostPre(long fileSize) {
|
||||
entity.setFileSize(fileSize);
|
||||
saveData(IEntity.STATE_POST_PRE, -1);
|
||||
}
|
||||
|
||||
@Override public void onResume(long resumeLocation) {
|
||||
saveData(IEntity.STATE_POST_PRE, IEntity.STATE_RUNNING);
|
||||
}
|
||||
|
||||
@Override public void onStart(long startLocation) {
|
||||
saveData(IEntity.STATE_POST_PRE, IEntity.STATE_RUNNING);
|
||||
}
|
||||
|
||||
@Override public void onProgress(long currentLocation) {
|
||||
mCurrentProgress += currentLocation;
|
||||
}
|
||||
|
||||
@Override public void onStop(long stopLocation) {
|
||||
saveData(IEntity.STATE_STOP, stopLocation);
|
||||
}
|
||||
|
||||
@Override public void onCancel() {
|
||||
saveData(IEntity.STATE_CANCEL, -1);
|
||||
}
|
||||
|
||||
@Override public void onComplete() {
|
||||
saveData(IEntity.STATE_COMPLETE, entity.getFileSize());
|
||||
}
|
||||
|
||||
@Override public void onFail() {
|
||||
entity.setFailNum(entity.getFailNum() + 1);
|
||||
saveData(IEntity.STATE_FAIL, -1);
|
||||
}
|
||||
|
||||
private void saveData(int state, long location) {
|
||||
entity.setState(state);
|
||||
entity.setDownloadComplete(state == IEntity.STATE_COMPLETE);
|
||||
entity.setCurrentProgress(location);
|
||||
entity.update();
|
||||
}
|
||||
}
|
||||
}
|
@ -14,12 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.arialyy.aria.core.download;
|
||||
package com.arialyy.aria.core.download.downloader;
|
||||
|
||||
|
||||
/**
|
||||
* @author lyy
|
||||
*/
|
||||
class DownloadListener implements IDownloadListener {
|
||||
public class DownloadListener implements IDownloadListener {
|
||||
|
||||
@Override public void onResume(long resumeLocation) {
|
||||
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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.util.Log;
|
||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2015/8/25.
|
||||
* 下载工具类
|
||||
*/
|
||||
public class DownloadUtil implements IDownloadUtil, Runnable {
|
||||
private static final String TAG = "DownloadUtil";
|
||||
private IDownloadListener mListener;
|
||||
private Downloader mDT;
|
||||
private DownloadTaskEntity mTaskEntity;
|
||||
|
||||
public DownloadUtil(DownloadTaskEntity entity, IDownloadListener downloadListener) {
|
||||
mTaskEntity = entity;
|
||||
mListener = downloadListener;
|
||||
mDT = new Downloader(downloadListener, entity);
|
||||
}
|
||||
|
||||
@Override public long getFileSize() {
|
||||
return mDT.getFileSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前下载位置
|
||||
*/
|
||||
@Override public long getCurrentLocation() {
|
||||
return mDT.getCurrentLocation();
|
||||
}
|
||||
|
||||
@Override public boolean isDownloading() {
|
||||
return mDT.isDownloading();
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消下载
|
||||
*/
|
||||
@Override public void cancelDownload() {
|
||||
mDT.cancelDownload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止下载
|
||||
*/
|
||||
@Override public void stopDownload() {
|
||||
mDT.stopDownload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 多线程断点续传下载文件,开始下载
|
||||
*/
|
||||
@Override public void startDownload() {
|
||||
mListener.onPre();
|
||||
new Thread(this).start();
|
||||
}
|
||||
|
||||
@Override public void resumeDownload() {
|
||||
startDownload();
|
||||
}
|
||||
|
||||
public void setMaxSpeed(double maxSpeed) {
|
||||
mDT.setMaxSpeed(maxSpeed);
|
||||
}
|
||||
|
||||
private void failDownload(String msg) {
|
||||
Log.e(TAG, msg);
|
||||
mListener.onFail();
|
||||
}
|
||||
|
||||
@Override public void run() {
|
||||
new Thread(new FileInfoThread(mTaskEntity, new FileInfoThread.OnFileInfoCallback() {
|
||||
@Override public void onComplete(String url, int code) {
|
||||
mDT.startDownload();
|
||||
}
|
||||
|
||||
@Override public void onFail(String url, String errorMsg) {
|
||||
failDownload(errorMsg);
|
||||
}
|
||||
})).start();
|
||||
}
|
||||
}
|
@ -0,0 +1,376 @@
|
||||
/*
|
||||
* 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.content.Context;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||
import com.arialyy.aria.orm.DbEntity;
|
||||
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/7/1.
|
||||
* 文件下载器
|
||||
*/
|
||||
class Downloader implements Runnable, IDownloadUtil {
|
||||
private final String TAG = "Downloader";
|
||||
private IDownloadListener mListener;
|
||||
private DownloadTaskEntity mTaskEntity;
|
||||
private DownloadEntity mEntity;
|
||||
private ExecutorService mFixedThreadPool;
|
||||
private File mConfigFile;//下载信息配置文件
|
||||
private Context mContext;
|
||||
private File mTempFile; //下载的文件
|
||||
private boolean isNewTask = true;
|
||||
private int mThreadNum, mRealThreadNum;
|
||||
private StateConstance mConstance;
|
||||
private SparseArray<Runnable> mTask = new SparseArray<>();
|
||||
|
||||
/**
|
||||
* 小于1m的文件不启用多线程
|
||||
*/
|
||||
private static final long SUB_LEN = 1024 * 1024;
|
||||
|
||||
Downloader(IDownloadListener listener, DownloadTaskEntity taskEntity) {
|
||||
mListener = listener;
|
||||
mTaskEntity = taskEntity;
|
||||
mEntity = mTaskEntity.getEntity();
|
||||
mContext = AriaManager.APP;
|
||||
mConstance = new StateConstance();
|
||||
}
|
||||
|
||||
void setMaxSpeed(double maxSpeed) {
|
||||
for (int i = 0; i < mThreadNum; i++) {
|
||||
SingleThreadTask task = (SingleThreadTask) mTask.get(i);
|
||||
if (task != null) {
|
||||
task.setMaxSpeed(maxSpeed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public StateConstance getConstance() {
|
||||
return mConstance;
|
||||
}
|
||||
|
||||
@Override public void run() {
|
||||
startFlow();
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始下载流程
|
||||
*/
|
||||
private void startFlow(){
|
||||
checkTask();
|
||||
mConstance.cleanState();
|
||||
mConstance.isDownloading = true;
|
||||
try {
|
||||
if (!mTaskEntity.isSupportBP) {
|
||||
mThreadNum = 1;
|
||||
handleNoSupportBreakpointDownload();
|
||||
} else {
|
||||
mThreadNum = isNewTask ? (mEntity.getFileSize() <= SUB_LEN ? 1
|
||||
: AriaManager.getInstance(mContext).getDownloadConfig().getThreadNum())
|
||||
: mRealThreadNum;
|
||||
mFixedThreadPool = Executors.newFixedThreadPool(mThreadNum);
|
||||
handleBreakpoint();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
failDownload("下载失败【downloadUrl:"
|
||||
+ mEntity.getDownloadUrl()
|
||||
+ "】\n【filePath:"
|
||||
+ mEntity.getDownloadPath()
|
||||
+ "】\n"
|
||||
+ CommonUtil.getPrintException(e));
|
||||
}
|
||||
}
|
||||
|
||||
@Override public long getFileSize() {
|
||||
return mEntity.getFileSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前下载位置
|
||||
*/
|
||||
@Override public long getCurrentLocation() {
|
||||
return mConstance.CURRENT_LOCATION;
|
||||
}
|
||||
|
||||
@Override public boolean isDownloading() {
|
||||
return mConstance.isDownloading;
|
||||
}
|
||||
|
||||
@Override public void cancelDownload() {
|
||||
mConstance.isCancel = true;
|
||||
mConstance.isDownloading = false;
|
||||
if (mFixedThreadPool != null) {
|
||||
mFixedThreadPool.shutdown();
|
||||
}
|
||||
for (int i = 0; i < mThreadNum; i++) {
|
||||
SingleThreadTask task = (SingleThreadTask) mTask.get(i);
|
||||
if (task != null) {
|
||||
task.cancel();
|
||||
}
|
||||
}
|
||||
CommonUtil.delDownloadTaskConfig(mTaskEntity.removeFile, mEntity);
|
||||
}
|
||||
|
||||
@Override public void stopDownload() {
|
||||
mConstance.isStop = true;
|
||||
mConstance.isDownloading = false;
|
||||
if (mFixedThreadPool != null) {
|
||||
mFixedThreadPool.shutdown();
|
||||
}
|
||||
for (int i = 0; i < mThreadNum; i++) {
|
||||
SingleThreadTask task = (SingleThreadTask) mTask.get(i);
|
||||
if (task != null) {
|
||||
task.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接调用的时候会自动启动线程执行
|
||||
*/
|
||||
@Override public void startDownload() {
|
||||
new Thread(this).start();
|
||||
}
|
||||
|
||||
@Override public void resumeDownload() {
|
||||
startDownload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回该下载器的
|
||||
*/
|
||||
public IDownloadListener getListener() {
|
||||
return mListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查任务是否是新任务,新任务条件:
|
||||
* 1、文件不存在
|
||||
* 2、下载记录文件不存在
|
||||
* 3、下载记录文件缺失或不匹配
|
||||
* 4、数据库记录不存在
|
||||
* 5、不支持断点,则是新任务
|
||||
*/
|
||||
private void checkTask() {
|
||||
if (!mTaskEntity.isSupportBP) {
|
||||
isNewTask = true;
|
||||
return;
|
||||
}
|
||||
mConfigFile = new File(mContext.getFilesDir().getPath()
|
||||
+ AriaManager.DOWNLOAD_TEMP_DIR
|
||||
+ mEntity.getFileName()
|
||||
+ ".properties");
|
||||
mTempFile = new File(mEntity.getDownloadPath());
|
||||
if (!mConfigFile.exists()) { //记录文件被删除,则重新下载
|
||||
isNewTask = true;
|
||||
CommonUtil.createFile(mConfigFile.getPath());
|
||||
} else if (!mTempFile.exists()) {
|
||||
isNewTask = true;
|
||||
} else if (DbEntity.findData(DownloadEntity.class, "downloadUrl=?", mEntity.getDownloadUrl())
|
||||
== null) {
|
||||
isNewTask = true;
|
||||
} else {
|
||||
isNewTask = checkConfigFile();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查记录文件,如果是新任务返回{@code true},否则返回{@code false}
|
||||
*/
|
||||
private boolean checkConfigFile() {
|
||||
Properties pro = CommonUtil.loadConfig(mConfigFile);
|
||||
if (pro.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
Set<Object> keys = pro.keySet();
|
||||
int num = 0;
|
||||
for (Object key : keys) {
|
||||
if (String.valueOf(key).contains("_record_")) {
|
||||
num++;
|
||||
}
|
||||
}
|
||||
if (num == 0) {
|
||||
return true;
|
||||
}
|
||||
mRealThreadNum = num;
|
||||
for (int i = 0; i < mRealThreadNum; i++) {
|
||||
if (pro.getProperty(mTempFile.getName() + "_record_" + i) == null) {
|
||||
Object state = pro.getProperty(mTempFile.getName() + "_state_" + i);
|
||||
if (state != null && Integer.parseInt(state + "") == 1) {
|
||||
continue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复记录地址
|
||||
*
|
||||
* @return true 表示下载完成
|
||||
*/
|
||||
private boolean resumeRecordLocation(int i, long startL, long endL) {
|
||||
mConstance.CURRENT_LOCATION += endL - startL;
|
||||
Log.d(TAG, "++++++++++ 线程_" + i + "_已经下载完成 ++++++++++");
|
||||
mConstance.COMPLETE_THREAD_NUM++;
|
||||
mConstance.STOP_NUM++;
|
||||
mConstance.CANCEL_NUM++;
|
||||
if (mConstance.isComplete()) {
|
||||
if (mConfigFile.exists()) {
|
||||
mConfigFile.delete();
|
||||
}
|
||||
mListener.onComplete();
|
||||
mConstance.isDownloading = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建单线程任务
|
||||
*/
|
||||
private void addSingleTask(int i, long startL, long endL, long fileLength) {
|
||||
ChildThreadConfigEntity entity = new ChildThreadConfigEntity();
|
||||
entity.FILE_SIZE = fileLength;
|
||||
entity.DOWNLOAD_URL =
|
||||
mEntity.isRedirect() ? mEntity.getRedirectUrl() : mEntity.getDownloadUrl();
|
||||
entity.TEMP_FILE = mTempFile;
|
||||
entity.THREAD_ID = i;
|
||||
entity.START_LOCATION = startL;
|
||||
entity.END_LOCATION = endL;
|
||||
entity.CONFIG_FILE_PATH = mConfigFile.getPath();
|
||||
entity.IS_SUPPORT_BREAK_POINT = mTaskEntity.isSupportBP;
|
||||
entity.DOWNLOAD_TASK_ENTITY = mTaskEntity;
|
||||
mConstance.THREAD_NUM = mThreadNum;
|
||||
SingleThreadTask task = new SingleThreadTask(mConstance, mListener, entity);
|
||||
mTask.put(i, task);
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动单线程下载任务
|
||||
*/
|
||||
private void startSingleTask(int[] recordL) {
|
||||
if (mConstance.CURRENT_LOCATION > 0) {
|
||||
mListener.onResume(mConstance.CURRENT_LOCATION);
|
||||
} else {
|
||||
mListener.onStart(mConstance.CURRENT_LOCATION);
|
||||
}
|
||||
mFixedThreadPool = Executors.newFixedThreadPool(recordL.length);
|
||||
for (int l : recordL) {
|
||||
if (l == -1) continue;
|
||||
Runnable task = mTask.get(l);
|
||||
if (task != null) {
|
||||
mFixedThreadPool.execute(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理断点
|
||||
*/
|
||||
private void handleBreakpoint() throws IOException {
|
||||
long fileLength = mEntity.getFileSize();
|
||||
Properties pro = CommonUtil.loadConfig(mConfigFile);
|
||||
int blockSize = (int) (fileLength / mThreadNum);
|
||||
int[] recordL = new int[mThreadNum];
|
||||
for (int i = 0; i < mThreadNum; i++) {
|
||||
recordL[i] = -1;
|
||||
}
|
||||
int rl = 0;
|
||||
if (isNewTask) {
|
||||
CommonUtil.createFile(mTempFile.getPath());
|
||||
BufferedRandomAccessFile file =
|
||||
new BufferedRandomAccessFile(new File(mTempFile.getPath()), "rwd", 8192);
|
||||
//设置文件长度
|
||||
file.setLength(fileLength);
|
||||
file.close();
|
||||
}
|
||||
|
||||
for (int i = 0; i < mThreadNum; i++) {
|
||||
long startL = i * blockSize, endL = (i + 1) * blockSize;
|
||||
Object state = pro.getProperty(mTempFile.getName() + "_state_" + i);
|
||||
if (state != null && Integer.parseInt(state + "") == 1) { //该线程已经完成
|
||||
if (resumeRecordLocation(i, startL, endL)) return;
|
||||
continue;
|
||||
}
|
||||
//分配下载位置
|
||||
Object record = pro.getProperty(mTempFile.getName() + "_record_" + i);
|
||||
//如果有记录,则恢复下载
|
||||
if (!isNewTask && record != null && Long.parseLong(record + "") >= 0) {
|
||||
Long r = Long.parseLong(record + "");
|
||||
mConstance.CURRENT_LOCATION += r - startL;
|
||||
Log.d(TAG, "任务【" + mEntity.getFileName() + "】线程__" + i + "__恢复下载");
|
||||
mListener.onChildResume(r);
|
||||
startL = r;
|
||||
recordL[rl] = i;
|
||||
rl++;
|
||||
} else {
|
||||
recordL[rl] = i;
|
||||
rl++;
|
||||
}
|
||||
if (i == (mThreadNum - 1)) {
|
||||
//最后一个线程的结束位置即为文件的总长度
|
||||
endL = fileLength;
|
||||
}
|
||||
addSingleTask(i, startL, endL, fileLength);
|
||||
}
|
||||
startSingleTask(recordL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理不支持断点的下载
|
||||
*/
|
||||
private void handleNoSupportBreakpointDownload() {
|
||||
ChildThreadConfigEntity entity = new ChildThreadConfigEntity();
|
||||
long len = mEntity.getFileSize();
|
||||
entity.FILE_SIZE = len;
|
||||
entity.DOWNLOAD_URL =
|
||||
mEntity.isRedirect() ? mEntity.getRedirectUrl() : mEntity.getDownloadUrl();
|
||||
entity.TEMP_FILE = mTempFile;
|
||||
entity.THREAD_ID = 0;
|
||||
entity.START_LOCATION = 0;
|
||||
entity.END_LOCATION = entity.FILE_SIZE;
|
||||
entity.CONFIG_FILE_PATH = mConfigFile.getPath();
|
||||
entity.IS_SUPPORT_BREAK_POINT = mTaskEntity.isSupportBP;
|
||||
entity.DOWNLOAD_TASK_ENTITY = mTaskEntity;
|
||||
mConstance.THREAD_NUM = mThreadNum;
|
||||
SingleThreadTask task = new SingleThreadTask(mConstance, mListener, entity);
|
||||
mTask.put(0, task);
|
||||
mFixedThreadPool.execute(task);
|
||||
mListener.onPostPre(len);
|
||||
mListener.onStart(0);
|
||||
}
|
||||
|
||||
private void failDownload(String errorMsg) {
|
||||
Log.e(TAG, errorMsg);
|
||||
mConstance.isDownloading = false;
|
||||
mListener.onFail();
|
||||
}
|
||||
}
|
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* 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.util.Log;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* 下载文件信息获取
|
||||
*/
|
||||
class FileInfoThread implements Runnable {
|
||||
private final String TAG = "FileInfoThread";
|
||||
private DownloadEntity mEntity;
|
||||
private DownloadTaskEntity mTaskEntity;
|
||||
private int mConnectTimeOut;
|
||||
private OnFileInfoCallback onFileInfoListener;
|
||||
|
||||
interface OnFileInfoCallback {
|
||||
/**
|
||||
* 处理完成
|
||||
*
|
||||
* @param code 状态码
|
||||
*/
|
||||
void onComplete(String url, int code);
|
||||
|
||||
/**
|
||||
* 请求失败
|
||||
*
|
||||
* @param errorMsg 错误信息
|
||||
*/
|
||||
void onFail(String url, String errorMsg);
|
||||
}
|
||||
|
||||
FileInfoThread(DownloadTaskEntity taskEntity) {
|
||||
this(taskEntity, null);
|
||||
}
|
||||
|
||||
FileInfoThread(DownloadTaskEntity taskEntity, OnFileInfoCallback callback) {
|
||||
this.mTaskEntity = taskEntity;
|
||||
mEntity = taskEntity.getEntity();
|
||||
mConnectTimeOut =
|
||||
AriaManager.getInstance(AriaManager.APP).getDownloadConfig().getConnectTimeOut();
|
||||
onFileInfoListener = callback;
|
||||
}
|
||||
|
||||
@Override public void run() {
|
||||
HttpURLConnection conn = null;
|
||||
try {
|
||||
URL url = new URL(mEntity.getDownloadUrl());
|
||||
conn = ConnectionHelp.handleConnection(url);
|
||||
conn = ConnectionHelp.setConnectParam(mTaskEntity, conn);
|
||||
conn.setRequestProperty("Range", "bytes=" + 0 + "-");
|
||||
conn.setConnectTimeout(mConnectTimeOut);
|
||||
conn.connect();
|
||||
handleConnect(conn);
|
||||
} catch (IOException e) {
|
||||
failDownload("下载失败【downloadUrl:"
|
||||
+ mEntity.getDownloadUrl()
|
||||
+ "】\n【filePath:"
|
||||
+ mEntity.getDownloadPath()
|
||||
+ "】\n"
|
||||
+ CommonUtil.getPrintException(e));
|
||||
} finally {
|
||||
if (conn != null) {
|
||||
conn.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleConnect(HttpURLConnection conn) throws IOException {
|
||||
int len = conn.getContentLength();
|
||||
int code = conn.getResponseCode();
|
||||
boolean isComplete = false;
|
||||
mTaskEntity.code = code;
|
||||
if (code == HttpURLConnection.HTTP_PARTIAL) {
|
||||
if (!checkLen(len)) return;
|
||||
mEntity.setFileSize(len);
|
||||
mTaskEntity.isSupportBP = true;
|
||||
isComplete = true;
|
||||
} else if (code == HttpURLConnection.HTTP_OK) {
|
||||
if (!checkLen(len)) return;
|
||||
mEntity.setFileSize(len);
|
||||
mTaskEntity.isSupportBP = false;
|
||||
isComplete = true;
|
||||
} else if (code == HttpURLConnection.HTTP_NOT_FOUND) {
|
||||
failDownload("任务【" + mEntity.getDownloadUrl() + "】下载失败,错误码:404");
|
||||
} else if (code == HttpURLConnection.HTTP_MOVED_TEMP
|
||||
|| code == HttpURLConnection.HTTP_MOVED_PERM
|
||||
|| code == HttpURLConnection.HTTP_SEE_OTHER) {
|
||||
mTaskEntity.redirectUrlKey = conn.getHeaderField(mTaskEntity.redirectUrlKey);
|
||||
mEntity.setRedirect(true);
|
||||
mEntity.setRedirectUrl(mTaskEntity.redirectUrlKey);
|
||||
handle302Turn(conn);
|
||||
} else {
|
||||
failDownload("任务【" + mEntity.getDownloadUrl() + "】下载失败,错误码:" + code);
|
||||
}
|
||||
if (isComplete) {
|
||||
if (onFileInfoListener != null) {
|
||||
onFileInfoListener.onComplete(mEntity.getDownloadUrl(), code);
|
||||
}
|
||||
mEntity.save();
|
||||
mTaskEntity.save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理30x跳转
|
||||
*/
|
||||
private void handle302Turn(HttpURLConnection conn) throws IOException {
|
||||
String newUrl = conn.getHeaderField(mTaskEntity.redirectUrlKey);
|
||||
Log.d(TAG, "30x跳转,新url为【" + newUrl + "】");
|
||||
String cookies = conn.getHeaderField("Set-Cookie");
|
||||
conn = (HttpURLConnection) new URL(newUrl).openConnection();
|
||||
conn = ConnectionHelp.setConnectParam(mTaskEntity, conn);
|
||||
conn.setRequestProperty("Cookie", cookies);
|
||||
conn.setRequestProperty("Range", "bytes=" + 0 + "-");
|
||||
conn.setConnectTimeout(mConnectTimeOut);
|
||||
conn.connect();
|
||||
handleConnect(conn);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查长度是否合法
|
||||
*
|
||||
* @param len 从服务器获取的文件长度
|
||||
* @return true, 合法
|
||||
*/
|
||||
private boolean checkLen(long len) {
|
||||
if (len < 0) {
|
||||
failDownload("任务【" + mEntity.getDownloadUrl() + "】下载失败,文件长度小于0");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void failDownload(String errorMsg) {
|
||||
Log.e(TAG, errorMsg);
|
||||
if (onFileInfoListener != null) {
|
||||
onFileInfoListener.onFail(mEntity.getDownloadUrl(), errorMsg);
|
||||
}
|
||||
}
|
||||
}
|
@ -14,12 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.arialyy.aria.core.download;
|
||||
package com.arialyy.aria.core.download.downloader;
|
||||
|
||||
/**
|
||||
* 下载监听
|
||||
*/
|
||||
interface IDownloadListener {
|
||||
public interface IDownloadListener {
|
||||
|
||||
/**
|
||||
* 支持断点回调
|
@ -14,13 +14,18 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.arialyy.aria.core.download;
|
||||
package com.arialyy.aria.core.download.downloader;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2016/10/31.
|
||||
* 抽象的下载接口
|
||||
*/
|
||||
interface IDownloadUtil {
|
||||
public interface IDownloadUtil {
|
||||
|
||||
/**
|
||||
* 获取文件大小
|
||||
*/
|
||||
public long getFileSize();
|
||||
|
||||
/**
|
||||
* 获取当前下载位置
|
||||
@ -53,19 +58,4 @@ interface IDownloadUtil {
|
||||
* 从上次断点恢复下载
|
||||
*/
|
||||
public void resumeDownload();
|
||||
|
||||
/**
|
||||
* 删除下载记录文件
|
||||
*/
|
||||
public void delConfigFile();
|
||||
|
||||
/**
|
||||
* 删除temp文件
|
||||
*/
|
||||
public void delTempFile();
|
||||
|
||||
/**
|
||||
* 设置最大下载速度
|
||||
*/
|
||||
public void setMaxSpeed(double maxSpeed);
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.download;
|
||||
package com.arialyy.aria.core.download.downloader;
|
||||
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
@ -36,16 +36,16 @@ import java.util.Properties;
|
||||
*/
|
||||
final class SingleThreadTask implements Runnable {
|
||||
private static final String TAG = "SingleThreadTask";
|
||||
private DownloadUtil.ChildThreadConfigEntity mConfigEntity;
|
||||
private ChildThreadConfigEntity mConfigEntity;
|
||||
private String mConfigFPath;
|
||||
private long mChildCurrentLocation = 0;
|
||||
private int mBufSize;
|
||||
private IDownloadListener mListener;
|
||||
private DownloadStateConstance CONSTANCE;
|
||||
private StateConstance CONSTANCE;
|
||||
private long mSleepTime = 0;
|
||||
|
||||
SingleThreadTask(DownloadStateConstance constance, IDownloadListener listener,
|
||||
DownloadUtil.ChildThreadConfigEntity downloadInfo) {
|
||||
SingleThreadTask(StateConstance constance, IDownloadListener listener,
|
||||
ChildThreadConfigEntity downloadInfo) {
|
||||
AriaManager manager = AriaManager.getInstance(AriaManager.APP);
|
||||
CONSTANCE = constance;
|
||||
CONSTANCE.CONNECT_TIME_OUT = manager.getDownloadConfig().getConnectTimeOut();
|
@ -13,13 +13,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.download;
|
||||
package com.arialyy.aria.core.download.downloader;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2017/1/18.
|
||||
* 下载状态常量
|
||||
*/
|
||||
final class DownloadStateConstance {
|
||||
final class StateConstance {
|
||||
int CANCEL_NUM = 0;
|
||||
int STOP_NUM = 0;
|
||||
int FAIL_NUM = 0;
|
||||
@ -32,7 +32,7 @@ final class DownloadStateConstance {
|
||||
boolean isCancel = false;
|
||||
boolean isStop = false;
|
||||
|
||||
DownloadStateConstance() {
|
||||
StateConstance() {
|
||||
}
|
||||
|
||||
void cleanState() {
|
@ -21,7 +21,7 @@ import com.arialyy.aria.orm.DbEntity;
|
||||
import com.arialyy.aria.orm.Ignore;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/3.
|
||||
* Created by AriaL on 2017/6/29.
|
||||
*/
|
||||
public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable {
|
||||
/**
|
||||
@ -36,6 +36,7 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable
|
||||
* 下载失败计数,每次开始都重置为0
|
||||
*/
|
||||
@Ignore private int failNum = 0;
|
||||
|
||||
/**
|
||||
* 扩展字段
|
||||
*/
|
||||
@ -53,10 +54,14 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable
|
||||
* 完成时间
|
||||
*/
|
||||
private long completeTime;
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
private String fileName = "";
|
||||
|
||||
public int getFailNum() {
|
||||
return failNum;
|
||||
}
|
||||
|
||||
public void setFailNum(int failNum) {
|
||||
this.failNum = failNum;
|
||||
}
|
||||
|
||||
public long getSpeed() {
|
||||
return speed;
|
||||
@ -74,14 +79,6 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable
|
||||
this.convertSpeed = convertSpeed;
|
||||
}
|
||||
|
||||
public int getFailNum() {
|
||||
return failNum;
|
||||
}
|
||||
|
||||
public void setFailNum(int failNum) {
|
||||
this.failNum = failNum;
|
||||
}
|
||||
|
||||
public String getStr() {
|
||||
return str;
|
||||
}
|
||||
@ -122,14 +119,6 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable
|
||||
this.completeTime = completeTime;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public AbsEntity() {
|
||||
}
|
||||
|
||||
@ -146,7 +135,6 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable
|
||||
dest.writeInt(this.state);
|
||||
dest.writeLong(this.currentProgress);
|
||||
dest.writeLong(this.completeTime);
|
||||
dest.writeString(this.fileName);
|
||||
}
|
||||
|
||||
protected AbsEntity(Parcel in) {
|
||||
@ -158,6 +146,5 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable
|
||||
this.state = in.readInt();
|
||||
this.currentProgress = in.readLong();
|
||||
this.completeTime = in.readLong();
|
||||
this.fileName = in.readString();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import com.arialyy.aria.orm.Primary;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/3.
|
||||
*/
|
||||
public abstract class AbsGroupEntity extends AbsEntity implements Parcelable {
|
||||
/**
|
||||
* 组名
|
||||
*/
|
||||
@Primary
|
||||
private String groupName = "";
|
||||
|
||||
/**
|
||||
* 任务地址相加的urlmd5
|
||||
*/
|
||||
private String urlmd5 = "";
|
||||
|
||||
public String getUrlmd5() {
|
||||
return urlmd5;
|
||||
}
|
||||
|
||||
public void setUrlmd5(String urlmd5) {
|
||||
this.urlmd5 = urlmd5;
|
||||
}
|
||||
|
||||
public String getGroupName() {
|
||||
return groupName;
|
||||
}
|
||||
|
||||
public void setGroupName(String groupName) {
|
||||
this.groupName = groupName;
|
||||
}
|
||||
|
||||
public AbsGroupEntity() {
|
||||
}
|
||||
|
||||
@Override public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
dest.writeString(this.groupName);
|
||||
dest.writeString(this.urlmd5);
|
||||
}
|
||||
|
||||
protected AbsGroupEntity(Parcel in) {
|
||||
super(in);
|
||||
this.groupName = in.readString();
|
||||
this.urlmd5 = in.readString();
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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 AriaL on 2017/6/29.
|
||||
* 任务组超类
|
||||
*/
|
||||
public abstract class AbsGroupTarget<TARGET extends AbsTarget, ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity>
|
||||
extends AbsTarget<TARGET, ENTITY, TASK_ENTITY> {
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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 AriaL on 2017/6/29.
|
||||
*/
|
||||
public abstract class AbsGroupTask<TASK_ENTITY extends AbsTaskEntity, ENTITY extends AbsGroupEntity>
|
||||
extends AbsTask<ENTITY> {
|
||||
|
||||
protected TASK_ENTITY mTaskEntity;
|
||||
|
||||
|
||||
@Override public String getKey() {
|
||||
return mEntity.getGroupName();
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import com.arialyy.aria.orm.DbEntity;
|
||||
import com.arialyy.aria.orm.Ignore;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/3.
|
||||
*/
|
||||
public abstract class AbsNormalEntity extends AbsEntity implements Parcelable {
|
||||
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
private String fileName = "";
|
||||
|
||||
/**
|
||||
* 是否是任务组里面的下载实体
|
||||
*/
|
||||
private boolean isGroupChild = false;
|
||||
|
||||
|
||||
public boolean isGroupChild() {
|
||||
return isGroupChild;
|
||||
}
|
||||
|
||||
public void setGroupChild(boolean groupChild) {
|
||||
isGroupChild = groupChild;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public AbsNormalEntity() {
|
||||
}
|
||||
|
||||
@Override public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
dest.writeString(this.fileName);
|
||||
dest.writeByte(this.isGroupChild ? (byte) 1 : (byte) 0);
|
||||
}
|
||||
|
||||
protected AbsNormalEntity(Parcel in) {
|
||||
super(in);
|
||||
this.fileName = in.readString();
|
||||
this.isGroupChild = in.readByte() != 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2017/2/28.
|
||||
*/
|
||||
public abstract class AbsNormalTarget<TARGET extends AbsTarget, ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity>
|
||||
extends AbsTarget<TARGET, ENTITY, TASK_ENTITY> {
|
||||
|
||||
/**
|
||||
* 将任务设置为最高优先级任务,最高优先级任务有以下特点:
|
||||
* 1、在下载队列中,有且只有一个最高优先级任务
|
||||
* 2、最高优先级任务会一直存在,直到用户手动暂停或任务完成
|
||||
* 3、任务调度器不会暂停最高优先级任务
|
||||
* 4、用户手动暂停或任务完成后,第二次重新执行该任务,该命令将失效
|
||||
* 5、如果下载队列中已经满了,则会停止队尾的任务,当高优先级任务完成后,该队尾任务将自动执行
|
||||
* 6、把任务设置为最高优先级任务后,将自动执行任务,不需要重新调用start()启动任务
|
||||
*/
|
||||
protected void setHighestPriority() {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(
|
||||
CommonUtil.createCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_HIGHEST_PRIORITY))
|
||||
.exe();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重定向后,新url的key,默认为location
|
||||
*/
|
||||
protected void _setRedirectUrlKey(String redirectUrlKey) {
|
||||
if (TextUtils.isEmpty(redirectUrlKey)) {
|
||||
Log.w("AbsNormalTarget", "重定向后,新url的key不能为null");
|
||||
return;
|
||||
}
|
||||
mTaskEntity.redirectUrlKey = redirectUrlKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除记录
|
||||
*/
|
||||
public void removeRecord() {
|
||||
mEntity.deleteData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务文件大小
|
||||
*
|
||||
* @return 文件大小
|
||||
*/
|
||||
public long getFileSize() {
|
||||
return getSize();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取单位转换后的文件大小
|
||||
*
|
||||
* @return 文件大小{@code xxx mb}
|
||||
*/
|
||||
public String getConvertFileSize() {
|
||||
return getConvertSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载任务是否存在
|
||||
*/
|
||||
public boolean taskExists() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加任务
|
||||
*/
|
||||
public void add() {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(CommonUtil.createCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_CREATE))
|
||||
.exe();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新下载
|
||||
*/
|
||||
public void reStart() {
|
||||
cancel();
|
||||
start();
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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/6/3.
|
||||
*/
|
||||
public abstract class AbsNormalTask<ENTITY extends AbsEntity> extends AbsTask<ENTITY> {
|
||||
|
||||
private boolean isHeighestTask = false;
|
||||
|
||||
/**
|
||||
* 暂停任务,并让任务处于等待状态
|
||||
*/
|
||||
public void stopAndWait() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 最高优先级命令,最高优先级命令有以下属性
|
||||
* 1、在下载队列中,有且只有一个最高优先级任务
|
||||
* 2、最高优先级任务会一直存在,直到用户手动暂停或任务完成
|
||||
* 3、任务调度器不会暂停最高优先级任务
|
||||
* 4、用户手动暂停或任务完成后,第二次重新执行该任务,该命令将失效
|
||||
* 5、如果下载队列中已经满了,则会停止队尾的任务
|
||||
* 6、把任务设置为最高优先级任务后,将自动执行任务,不需要重新调用start()启动任务
|
||||
*/
|
||||
public void setHighestPriority(boolean isHighestPriority) {
|
||||
isHeighestTask = isHighestPriority;
|
||||
}
|
||||
|
||||
public boolean isHighestPriorityTask() {
|
||||
return isHeighestTask;
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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 AriaL on 2017/6/27.
|
||||
*/
|
||||
|
||||
public abstract class AbsReceiver<ENTITY extends AbsNormalEntity> implements IReceiver<ENTITY>{
|
||||
public String targetName;
|
||||
public Object obj;
|
||||
|
||||
}
|
@ -16,36 +16,58 @@
|
||||
package com.arialyy.aria.core.inf;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.RequestEnum;
|
||||
import com.arialyy.aria.core.command.AbsCmd;
|
||||
import com.arialyy.aria.core.command.CmdFactory;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.core.upload.UploadEntity;
|
||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2017/2/28.
|
||||
* Created by AriaL on 2017/7/3.
|
||||
*/
|
||||
public abstract class AbsTarget<ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity> {
|
||||
protected ENTITY entity;
|
||||
protected TASK_ENTITY taskEntity;
|
||||
protected String targetName;
|
||||
public abstract class AbsTarget<TARGET extends AbsTarget, ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity>
|
||||
implements ITarget<TARGET> {
|
||||
protected ENTITY mEntity;
|
||||
protected TASK_ENTITY mTaskEntity;
|
||||
protected String mTargetName;
|
||||
|
||||
/**
|
||||
* 获取任务进度,如果任务存在,则返回当前进度
|
||||
*
|
||||
* @return 该任务进度
|
||||
*/
|
||||
public long getCurrentProgress() {
|
||||
return mEntity == null ? -1 : mEntity.getCurrentProgress();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务文件大小
|
||||
*
|
||||
* @return 文件大小
|
||||
*/
|
||||
@Override public long getSize() {
|
||||
return mEntity == null ? 0 : mEntity.getFileSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单位转换后的文件大小
|
||||
*
|
||||
* @return 文件大小{@code xxx mb}
|
||||
*/
|
||||
@Override public String getConvertSize() {
|
||||
return mEntity == null ? "0b" : CommonUtil.formatFileSize(mEntity.getFileSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置扩展字段,用来保存你的其它数据,如果你的数据比较多,你可以把你的数据转换为JSON字符串,然后再存到Aria中
|
||||
*
|
||||
* @param str 扩展数据
|
||||
*/
|
||||
public AbsTarget setExtendField(String str) {
|
||||
entity.setStr(str);
|
||||
return this;
|
||||
public TARGET setExtendField(String str) {
|
||||
mEntity.setStr(str);
|
||||
return (TARGET) this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -53,7 +75,7 @@ public abstract class AbsTarget<ENTITY extends AbsEntity, TASK_ENTITY extends Ab
|
||||
* 设置扩展字段{@link #setExtendField(String)}
|
||||
*/
|
||||
public String getExtendField() {
|
||||
return entity.getStr();
|
||||
return mEntity.getStr();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -62,79 +84,7 @@ public abstract class AbsTarget<ENTITY extends AbsEntity, TASK_ENTITY extends Ab
|
||||
* @return {@link IEntity}
|
||||
*/
|
||||
public int getTaskState() {
|
||||
return entity.getState();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将任务设置为最高优先级任务,最高优先级任务有以下特点:
|
||||
* 1、在下载队列中,有且只有一个最高优先级任务
|
||||
* 2、最高优先级任务会一直存在,直到用户手动暂停或任务完成
|
||||
* 3、任务调度器不会暂停最高优先级任务
|
||||
* 4、用户手动暂停或任务完成后,第二次重新执行该任务,该命令将失效
|
||||
* 5、如果下载队列中已经满了,则会停止队尾的任务,当高优先级任务完成后,该队尾任务将自动执行
|
||||
* 6、把任务设置为最高优先级任务后,将自动执行任务,不需要重新调用start()启动任务
|
||||
*/
|
||||
protected void setHighestPriority() {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(CommonUtil.createCmd(targetName, taskEntity, CmdFactory.TASK_HIGHEST_PRIORITY))
|
||||
.exe();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重定向后,新url的key,默认为location
|
||||
*/
|
||||
protected void _setRedirectUrlKey(String redirectUrlKey) {
|
||||
if (TextUtils.isEmpty(redirectUrlKey)) {
|
||||
Log.w("AbsTarget", "重定向后,新url的key不能为null");
|
||||
return;
|
||||
}
|
||||
taskEntity.redirectUrlKey = redirectUrlKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除记录
|
||||
*/
|
||||
public void removeRecord() {
|
||||
entity.deleteData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务文件大小
|
||||
*
|
||||
* @return 文件大小
|
||||
*/
|
||||
public long getFileSize() {
|
||||
if (entity instanceof DownloadEntity) {
|
||||
DownloadEntity entity = (DownloadEntity) this.entity;
|
||||
return entity.getFileSize();
|
||||
} else if (entity instanceof UploadEntity) {
|
||||
UploadEntity entity = (UploadEntity) this.entity;
|
||||
return entity.getFileSize();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单位转换后的文件大小
|
||||
*
|
||||
* @return 文件大小{@code xxx mb}
|
||||
*/
|
||||
public String getConvertFileSize() {
|
||||
if (entity instanceof DownloadEntity) {
|
||||
DownloadEntity entity = (DownloadEntity) this.entity;
|
||||
return CommonUtil.formatFileSize(entity.getFileSize());
|
||||
} else if (entity instanceof UploadEntity) {
|
||||
UploadEntity entity = (UploadEntity) this.entity;
|
||||
return CommonUtil.formatFileSize(entity.getFileSize());
|
||||
}
|
||||
return "0b";
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载任务是否存在
|
||||
*/
|
||||
public boolean taskExists() {
|
||||
return false;
|
||||
return mEntity.getState();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -142,24 +92,15 @@ public abstract class AbsTarget<ENTITY extends AbsEntity, TASK_ENTITY extends Ab
|
||||
*
|
||||
* @return 返回任务进度
|
||||
*/
|
||||
protected int getPercent() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务进度,如果任务存在,则返回当前进度
|
||||
*
|
||||
* @return 该任务进度
|
||||
*/
|
||||
public long getCurrentProgress() {
|
||||
if (entity instanceof DownloadEntity) {
|
||||
DownloadEntity entity = (DownloadEntity) this.entity;
|
||||
return entity.getCurrentProgress();
|
||||
} else if (entity instanceof UploadEntity) {
|
||||
UploadEntity entity = (UploadEntity) this.entity;
|
||||
return entity.getCurrentProgress();
|
||||
@Override public int getPercent() {
|
||||
if (mEntity == null) {
|
||||
Log.e("AbsTarget", "下载管理器中没有该任务");
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
if (mEntity.getFileSize() != 0) {
|
||||
return (int) (mEntity.getCurrentProgress() * 100 / mEntity.getFileSize());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -168,20 +109,22 @@ public abstract class AbsTarget<ENTITY extends AbsEntity, TASK_ENTITY extends Ab
|
||||
* @param key 头部key
|
||||
* @param header 头部value
|
||||
*/
|
||||
protected void _addHeader(@NonNull String key, @NonNull String header) {
|
||||
taskEntity.headers.put(key, header);
|
||||
public TARGET addHeader(@NonNull String key, @NonNull String header) {
|
||||
mTaskEntity.headers.put(key, header);
|
||||
return (TARGET) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给url请求添加头部
|
||||
*/
|
||||
protected void _addHeaders(Map<String, String> headers) {
|
||||
public TARGET addHeaders(Map<String, String> headers) {
|
||||
if (headers != null && headers.size() > 0) {
|
||||
Set<String> keys = headers.keySet();
|
||||
for (String key : keys) {
|
||||
taskEntity.headers.put(key, headers.get(key));
|
||||
mTaskEntity.headers.put(key, headers.get(key));
|
||||
}
|
||||
}
|
||||
return (TARGET) this;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -189,62 +132,50 @@ public abstract class AbsTarget<ENTITY extends AbsEntity, TASK_ENTITY extends Ab
|
||||
*
|
||||
* @param requestEnum {@link RequestEnum}
|
||||
*/
|
||||
protected void _setRequestMode(RequestEnum requestEnum) {
|
||||
taskEntity.requestEnum = requestEnum;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加任务
|
||||
*/
|
||||
public void add() {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(CommonUtil.createCmd(targetName, taskEntity, CmdFactory.TASK_CREATE))
|
||||
.exe();
|
||||
public TARGET setRequestMode(RequestEnum requestEnum) {
|
||||
mTaskEntity.requestEnum = requestEnum;
|
||||
return (TARGET) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始下载
|
||||
*/
|
||||
public void start() {
|
||||
List<AbsCmd> cmds = new ArrayList<>();
|
||||
cmds.add(CommonUtil.createCmd(targetName, taskEntity, CmdFactory.TASK_CREATE));
|
||||
cmds.add(CommonUtil.createCmd(targetName, taskEntity, CmdFactory.TASK_START));
|
||||
AriaManager.getInstance(AriaManager.APP).setCmds(cmds).exe();
|
||||
cmds.clear();
|
||||
@Override public void start() {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(CommonUtil.createCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_START))
|
||||
.exe();
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止下载
|
||||
*
|
||||
* @see #stop()
|
||||
*/
|
||||
protected void pause() {
|
||||
@Deprecated public void pause() {
|
||||
stop();
|
||||
}
|
||||
|
||||
@Override public void stop() {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(CommonUtil.createCmd(targetName, taskEntity, CmdFactory.TASK_STOP))
|
||||
.setCmd(CommonUtil.createCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_STOP))
|
||||
.exe();
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复下载
|
||||
*/
|
||||
protected void resume() {
|
||||
@Override public void resume() {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(CommonUtil.createCmd(targetName, taskEntity, CmdFactory.TASK_START))
|
||||
.setCmd(CommonUtil.createCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_START))
|
||||
.exe();
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消下载
|
||||
*/
|
||||
public void cancel() {
|
||||
@Override public void cancel() {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(CommonUtil.createCmd(targetName, taskEntity, CmdFactory.TASK_CANCEL))
|
||||
.setCmd(CommonUtil.createCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_CANCEL))
|
||||
.exe();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新下载
|
||||
*/
|
||||
void reStart() {
|
||||
cancel();
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
@ -16,25 +16,89 @@
|
||||
package com.arialyy.aria.core.inf;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2017/6/3.
|
||||
* Created by AriaL on 2017/6/29.
|
||||
*/
|
||||
public abstract class AbsTask<TASK_ENTITY extends AbsTaskEntity, ENTITY extends AbsEntity>
|
||||
implements ITask<ENTITY> {
|
||||
public abstract class AbsTask<ENTITY extends AbsEntity> implements ITask<ENTITY> {
|
||||
|
||||
protected ENTITY mEntity;
|
||||
protected Handler mOutHandler;
|
||||
|
||||
/**
|
||||
* 用于生成该任务对象的hash码
|
||||
*/
|
||||
private String mTargetName;
|
||||
protected Context mContext;
|
||||
private boolean isHeighestTask = false;
|
||||
|
||||
@Override public void stopAndWait() {
|
||||
/**
|
||||
* 获取当前下载进度
|
||||
*/
|
||||
@Override public long getCurrentProgress() {
|
||||
return mEntity.getCurrentProgress();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单位转换后的进度
|
||||
*
|
||||
* @return 如:已经下载3mb的大小,则返回{@code 3mb}
|
||||
*/
|
||||
@Override public String getConvertCurrentProgress() {
|
||||
if (mEntity.getCurrentProgress() == 0) {
|
||||
return "0b";
|
||||
}
|
||||
return CommonUtil.formatFileSize(mEntity.getCurrentProgress());
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换单位后的文件长度
|
||||
*
|
||||
* @return 如果文件长度为0,则返回0m,否则返回转换后的长度1b、1kb、1mb、1gb、1tb
|
||||
*/
|
||||
@Override public String getConvertFileSize() {
|
||||
if (mEntity.getFileSize() == 0) {
|
||||
return "0mb";
|
||||
}
|
||||
return CommonUtil.formatFileSize(mEntity.getFileSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件大小
|
||||
*/
|
||||
@Override public long getFileSize() {
|
||||
return mEntity.getFileSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取百分比进度
|
||||
*
|
||||
* @return 返回百分比进度,如果文件长度为0,返回0
|
||||
*/
|
||||
@Override public int getPercent() {
|
||||
if (mEntity.getFileSize() == 0) {
|
||||
return 0;
|
||||
}
|
||||
return (int) (mEntity.getCurrentProgress() * 100 / mEntity.getFileSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务当前状态
|
||||
*
|
||||
* @return {@link IEntity}
|
||||
*/
|
||||
public int getState() {
|
||||
return mEntity == null ? IEntity.STATE_OTHER : mEntity.getState();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取保存的扩展字段
|
||||
*
|
||||
* @return 如果实体不存在,则返回null,否则返回扩展字段
|
||||
*/
|
||||
@Override public String getExtendField() {
|
||||
return mEntity == null ? null : mEntity.getStr();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,84 +143,10 @@ public abstract class AbsTask<TASK_ENTITY extends AbsTaskEntity, ENTITY extends
|
||||
return mEntity.getConvertSpeed();
|
||||
}
|
||||
|
||||
/**
|
||||
* 最高优先级命令,最高优先级命令有以下属性
|
||||
* 1、在下载队列中,有且只有一个最高优先级任务
|
||||
* 2、最高优先级任务会一直存在,直到用户手动暂停或任务完成
|
||||
* 3、任务调度器不会暂停最高优先级任务
|
||||
* 4、用户手动暂停或任务完成后,第二次重新执行该任务,该命令将失效
|
||||
* 5、如果下载队列中已经满了,则会停止队尾的任务
|
||||
* 6、把任务设置为最高优先级任务后,将自动执行任务,不需要重新调用start()启动任务
|
||||
*/
|
||||
@Override public void setHighestPriority(boolean isHighestPriority) {
|
||||
isHeighestTask = isHighestPriority;
|
||||
}
|
||||
|
||||
@Override public boolean isHighestPriorityTask() {
|
||||
return isHeighestTask;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取百分比进度
|
||||
*
|
||||
* @return 返回百分比进度,如果文件长度为0,返回0
|
||||
*/
|
||||
@Override public int getPercent() {
|
||||
if (mEntity.getFileSize() == 0) {
|
||||
return 0;
|
||||
}
|
||||
return (int) (mEntity.getCurrentProgress() * 100 / mEntity.getFileSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件大小
|
||||
*/
|
||||
@Override public long getFileSize() {
|
||||
return mEntity.getFileSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换单位后的文件长度
|
||||
*
|
||||
* @return 如果文件长度为0,则返回0m,否则返回转换后的长度1b、1kb、1mb、1gb、1tb
|
||||
*/
|
||||
@Override public String getConvertFileSize() {
|
||||
if (mEntity.getFileSize() == 0) {
|
||||
return "0mb";
|
||||
}
|
||||
return CommonUtil.formatFileSize(mEntity.getFileSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前下载进度
|
||||
*/
|
||||
@Override public long getCurrentProgress() {
|
||||
return mEntity.getCurrentProgress();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单位转换后的进度
|
||||
*
|
||||
* @return 如:已经下载3mb的大小,则返回{@code 3mb}
|
||||
*/
|
||||
@Override public String getConvertCurrentProgress() {
|
||||
if (mEntity.getCurrentProgress() == 0) {
|
||||
return "0b";
|
||||
}
|
||||
return CommonUtil.formatFileSize(mEntity.getCurrentProgress());
|
||||
}
|
||||
|
||||
@Override public ENTITY getEntity() {
|
||||
return mEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除任务记录,删除后,再次启动该任务的下载时,将重新下载
|
||||
*/
|
||||
@Override public void removeRecord() {
|
||||
mEntity.deleteData();
|
||||
}
|
||||
|
||||
public String getTargetName() {
|
||||
return mTargetName;
|
||||
}
|
||||
|
@ -16,14 +16,22 @@
|
||||
package com.arialyy.aria.core.inf;
|
||||
|
||||
import com.arialyy.aria.core.RequestEnum;
|
||||
import com.arialyy.aria.orm.DbEntity;
|
||||
import com.arialyy.aria.orm.Ignore;
|
||||
import com.arialyy.aria.orm.Primary;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2017/2/23.
|
||||
*/
|
||||
public abstract class AbsTaskEntity<ENTITY extends AbsEntity> extends DbEntity {
|
||||
|
||||
/**
|
||||
* Task实体对应的key
|
||||
*/
|
||||
@Primary public String key = "";
|
||||
|
||||
public abstract class AbsTaskEntity {
|
||||
/**
|
||||
* http 请求头
|
||||
*/
|
||||
@ -39,5 +47,20 @@ public abstract class AbsTaskEntity {
|
||||
*/
|
||||
public String redirectUrlKey = "location";
|
||||
|
||||
public abstract AbsEntity getEntity();
|
||||
/**
|
||||
* 用于判断删除任务时是否需要删除文件{@code true}删除
|
||||
*/
|
||||
@Ignore public boolean removeFile = false;
|
||||
|
||||
/**
|
||||
* 是否支持断点, {@code true} 为支持断点
|
||||
*/
|
||||
public boolean isSupportBP = true;
|
||||
|
||||
/**
|
||||
* 状态码
|
||||
*/
|
||||
public int code;
|
||||
|
||||
public abstract ENTITY getEntity();
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ public interface IReceiver<ENTITY extends IEntity> {
|
||||
/**
|
||||
* 删除所有任务
|
||||
*/
|
||||
public void removeAllTask();
|
||||
public void removeAllTask(boolean removeFile);
|
||||
|
||||
/**
|
||||
* 任务是否存在
|
||||
|
86
Aria/src/main/java/com/arialyy/aria/core/inf/ITarget.java
Normal file
86
Aria/src/main/java/com/arialyy/aria/core/inf/ITarget.java
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import com.arialyy.aria.core.RequestEnum;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/29.
|
||||
*/
|
||||
public interface ITarget<TARGET extends ITarget> {
|
||||
/**
|
||||
* 任务文件大小
|
||||
*/
|
||||
long getSize();
|
||||
|
||||
/**
|
||||
* 转换后的大小
|
||||
*/
|
||||
String getConvertSize();
|
||||
|
||||
/**
|
||||
* 获取任务进度百分比
|
||||
*/
|
||||
int getPercent();
|
||||
|
||||
/**
|
||||
* 获取任务进度,如果任务存在,则返回当前进度
|
||||
*/
|
||||
long getCurrentProgress();
|
||||
|
||||
/**
|
||||
* 给url请求添加头部
|
||||
*
|
||||
* @param key 头部key
|
||||
* @param header 头部value
|
||||
*/
|
||||
TARGET addHeader(@NonNull String key, @NonNull String header) ;
|
||||
|
||||
/**
|
||||
* 给url请求添加头部
|
||||
*/
|
||||
TARGET addHeaders(Map<String, String> headers);
|
||||
|
||||
/**
|
||||
* 设置请求类型
|
||||
*
|
||||
* @param requestEnum {@link RequestEnum}
|
||||
*/
|
||||
TARGET setRequestMode(RequestEnum requestEnum);
|
||||
|
||||
/**
|
||||
* 开始下载
|
||||
*/
|
||||
void start();
|
||||
|
||||
/**
|
||||
* 停止下载
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* 恢复下载
|
||||
*/
|
||||
void resume();
|
||||
|
||||
/**
|
||||
* 取消下载
|
||||
*/
|
||||
void cancel();
|
||||
|
||||
}
|
@ -18,25 +18,17 @@ package com.arialyy.aria.core.inf;
|
||||
/**
|
||||
* Created by lyy on 2017/2/13.
|
||||
*/
|
||||
|
||||
public interface ITask<ENTITY extends AbsEntity> {
|
||||
|
||||
/**
|
||||
* 暂停任务,并让任务处于等待状态
|
||||
* 获取下载状态
|
||||
*/
|
||||
public void stopAndWait();
|
||||
int getState();
|
||||
|
||||
/**
|
||||
* 设置任务为最高优先级任务,在下载队列中,有且只有一个最高优先级任务
|
||||
* 获取扩展字段
|
||||
*/
|
||||
public void setHighestPriority(boolean isHighestPriority);
|
||||
|
||||
/**
|
||||
* 该任务是否是最高优先级任务
|
||||
*
|
||||
* @return {@code true} 任务为最高优先级任务
|
||||
*/
|
||||
public boolean isHighestPriorityTask();
|
||||
String getExtendField();
|
||||
|
||||
/**
|
||||
* 唯一标识符,DownloadTask 为下载地址,UploadTask 为文件路径
|
||||
@ -100,5 +92,4 @@ public interface ITask<ENTITY extends AbsEntity> {
|
||||
|
||||
public void setTargetName(String targetName);
|
||||
|
||||
public void removeRecord();
|
||||
}
|
||||
|
@ -18,27 +18,42 @@ package com.arialyy.aria.core.queue;
|
||||
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.core.download.DownloadTask;
|
||||
import com.arialyy.aria.core.inf.AbsEntity;
|
||||
import com.arialyy.aria.core.inf.ITask;
|
||||
import com.arialyy.aria.core.inf.AbsTask;
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
import com.arialyy.aria.core.queue.pool.CachePool;
|
||||
import com.arialyy.aria.core.queue.pool.ExecutePool;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.core.queue.pool.BaseCachePool;
|
||||
import com.arialyy.aria.core.queue.pool.BaseExecutePool;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2017/2/23.
|
||||
* 任务队列
|
||||
*/
|
||||
abstract class AbsTaskQueue<TASK extends ITask, TASK_ENTITY extends AbsTaskEntity, ENTITY extends AbsEntity>
|
||||
abstract class AbsTaskQueue<TASK extends AbsTask, TASK_ENTITY extends AbsTaskEntity, ENTITY extends AbsEntity>
|
||||
implements ITaskQueue<TASK, TASK_ENTITY, ENTITY> {
|
||||
private final String TAG = "AbsTaskQueue";
|
||||
CachePool<TASK> mCachePool = new CachePool<>();
|
||||
ExecutePool<TASK> mExecutePool;
|
||||
BaseCachePool<TASK> mCachePool = new BaseCachePool<>();
|
||||
BaseExecutePool<TASK> mExecutePool;
|
||||
|
||||
@Override public boolean taskIsRunning(String key) {
|
||||
return mExecutePool.getTask(key) != null;
|
||||
}
|
||||
|
||||
@Override public void removeAllTask() {
|
||||
Set<String> exeKeys = mExecutePool.getAllTask().keySet();
|
||||
for (String key : exeKeys) {
|
||||
TASK task = mExecutePool.getAllTask().get(key);
|
||||
if (task != null) task.cancel();
|
||||
}
|
||||
Set<String> cacheKeys = mCachePool.getAllTask().keySet();
|
||||
for (String key : cacheKeys) {
|
||||
mExecutePool.removeTask(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止所有任务
|
||||
*/
|
||||
@ -58,17 +73,27 @@ abstract class AbsTaskQueue<TASK extends ITask, TASK_ENTITY extends AbsTaskEntit
|
||||
return AriaManager.getInstance(AriaManager.APP).getDownloadConfig().getMaxTaskNum();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取实体的索引
|
||||
*/
|
||||
public abstract String getKey(ENTITY entity);
|
||||
|
||||
/**
|
||||
* 获取配置文件配置的最大可执行任务数
|
||||
*/
|
||||
public abstract int getConfigMaxNum();
|
||||
|
||||
/**
|
||||
* 获取任务执行池
|
||||
*/
|
||||
public ExecutePool getExecutePool() {
|
||||
public BaseExecutePool getExecutePool() {
|
||||
return mExecutePool;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存池
|
||||
*/
|
||||
public CachePool getCachePool() {
|
||||
public BaseCachePool getCachePool() {
|
||||
return mCachePool;
|
||||
}
|
||||
|
||||
@ -90,8 +115,31 @@ abstract class AbsTaskQueue<TASK extends ITask, TASK_ENTITY extends AbsTaskEntit
|
||||
return mExecutePool.size();
|
||||
}
|
||||
|
||||
@Override public void setTaskHighestPriority(TASK task) {
|
||||
|
||||
@Override public void setMaxTaskNum(int downloadNum) {
|
||||
int oldMaxSize = getConfigMaxNum();
|
||||
int diff = downloadNum - oldMaxSize;
|
||||
if (oldMaxSize == downloadNum) {
|
||||
Log.d(TAG, "设置的下载任务数和配置文件的下载任务数一直,跳过");
|
||||
return;
|
||||
}
|
||||
//设置的任务数小于配置任务数
|
||||
if (diff <= -1 && mExecutePool.size() >= oldMaxSize) {
|
||||
for (int i = 0, len = Math.abs(diff); i < len; i++) {
|
||||
TASK eTask = mExecutePool.pollTask();
|
||||
if (eTask != null) {
|
||||
stopTask(eTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
mExecutePool.setMaxNum(downloadNum);
|
||||
if (diff >= 1) {
|
||||
for (int i = 0; i < diff; i++) {
|
||||
TASK nextTask = getNextTask();
|
||||
if (nextTask != null && nextTask.getState() == IEntity.STATE_WAIT) {
|
||||
startTask(nextTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public TASK getTask(String url) {
|
||||
@ -112,12 +160,22 @@ abstract class AbsTaskQueue<TASK extends ITask, TASK_ENTITY extends AbsTaskEntit
|
||||
|
||||
@Override public void stopTask(TASK task) {
|
||||
if (!task.isRunning()) Log.w(TAG, "停止任务失败,【任务已经停止】");
|
||||
task.setHighestPriority(false);
|
||||
if (mExecutePool.removeTask(task)) {
|
||||
task.stop();
|
||||
} else {
|
||||
task.stop();
|
||||
Log.w(TAG, "停止任务失败,【任务已经停止】");
|
||||
Log.w(TAG, "删除任务失败,【执行队列中没有该任务】");
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void removeTask(ENTITY entity) {
|
||||
TASK task = mExecutePool.getTask(getKey(entity));
|
||||
if (task != null) {
|
||||
Log.d(TAG, "从执行池删除任务,删除" + (mExecutePool.removeTask(task) ? "成功" : "失败"));
|
||||
}
|
||||
task = mCachePool.getTask(getKey(entity));
|
||||
if (task != null) {
|
||||
Log.d(TAG, "从缓存池删除任务,删除" + (mCachePool.removeTask(task) ? "成功" : "失败"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,6 +191,10 @@ abstract class AbsTaskQueue<TASK extends ITask, TASK_ENTITY extends AbsTaskEntit
|
||||
}
|
||||
}
|
||||
|
||||
@Override public TASK getTask(ENTITY entity) {
|
||||
return getTask(getKey(entity));
|
||||
}
|
||||
|
||||
@Override public void removeTask(TASK task) {
|
||||
task.cancel();
|
||||
}
|
||||
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.arialyy.aria.core.queue;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.download.DownloadGroupEntity;
|
||||
import com.arialyy.aria.core.download.DownloadGroupTask;
|
||||
import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
|
||||
import com.arialyy.aria.core.queue.pool.BaseExecutePool;
|
||||
import com.arialyy.aria.core.scheduler.DownloadGroupSchedulers;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/29.
|
||||
* 任务组下载队列
|
||||
*/
|
||||
public class DownloadGroupTaskQueue
|
||||
extends AbsTaskQueue<DownloadGroupTask, DownloadGroupTaskEntity, DownloadGroupEntity> {
|
||||
private static volatile DownloadGroupTaskQueue INSTANCE = null;
|
||||
|
||||
private final String TAG = "DownloadGroupTaskQueue";
|
||||
|
||||
public static DownloadGroupTaskQueue getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
INSTANCE = new DownloadGroupTaskQueue();
|
||||
}
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private DownloadGroupTaskQueue() {
|
||||
mExecutePool = new BaseExecutePool<>(true);
|
||||
}
|
||||
|
||||
@Override public DownloadGroupTask createTask(String targetName, DownloadGroupTaskEntity entity) {
|
||||
DownloadGroupTask task = null;
|
||||
if (!TextUtils.isEmpty(targetName)) {
|
||||
task = (DownloadGroupTask) TaskFactory.getInstance()
|
||||
.createTask(targetName, entity, DownloadGroupSchedulers.getInstance());
|
||||
entity.key = entity.getEntity().getGroupName();
|
||||
mCachePool.putTask(task);
|
||||
} else {
|
||||
Log.e(TAG, "target name 为 null!!");
|
||||
}
|
||||
return task;
|
||||
}
|
||||
|
||||
@Override public String getKey(DownloadGroupEntity entity) {
|
||||
return entity.getGroupName();
|
||||
}
|
||||
|
||||
@Override public int getConfigMaxNum() {
|
||||
return AriaManager.getInstance(AriaManager.APP).getDownloadConfig().oldMaxTaskNum;
|
||||
}
|
||||
}
|
@ -22,8 +22,7 @@ import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.core.download.DownloadTask;
|
||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.core.queue.pool.ExecutePool;
|
||||
import com.arialyy.aria.core.queue.pool.DownloadExecutePool;
|
||||
import com.arialyy.aria.core.scheduler.DownloadSchedulers;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
@ -48,10 +47,21 @@ public class DownloadTaskQueue
|
||||
}
|
||||
|
||||
private DownloadTaskQueue() {
|
||||
mExecutePool = new ExecutePool<>(true);
|
||||
mExecutePool = new DownloadExecutePool(true);
|
||||
}
|
||||
|
||||
@Override public void setTaskHighestPriority(DownloadTask task) {
|
||||
@Override public String getKey(DownloadEntity entity) {
|
||||
return entity.getDownloadUrl();
|
||||
}
|
||||
|
||||
@Override public int getConfigMaxNum() {
|
||||
return AriaManager.getInstance(AriaManager.APP).getDownloadConfig().oldMaxTaskNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置任务为最高优先级任务
|
||||
*/
|
||||
public void setTaskHighestPriority(DownloadTask task) {
|
||||
task.setHighestPriority(true);
|
||||
Map<String, DownloadTask> exeTasks = mExecutePool.getAllTask();
|
||||
if (exeTasks != null && !exeTasks.isEmpty()) {
|
||||
@ -103,57 +113,21 @@ public class DownloadTaskQueue
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void setMaxTaskNum(int downloadNum) {
|
||||
int oldMaxSize = AriaManager.getInstance(AriaManager.APP).getDownloadConfig().oldMaxTaskNum;
|
||||
int diff = downloadNum - oldMaxSize;
|
||||
if (oldMaxSize == downloadNum) {
|
||||
Log.d(TAG, "设置的下载任务数和配置文件的下载任务数一直,跳过");
|
||||
return;
|
||||
}
|
||||
//设置的任务数小于配置任务数
|
||||
if (diff <= -1 && mExecutePool.size() >= oldMaxSize) {
|
||||
for (int i = 0, len = Math.abs(diff); i < len; i++) {
|
||||
DownloadTask eTask = mExecutePool.pollTask();
|
||||
if (eTask != null) {
|
||||
stopTask(eTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
mExecutePool.setMaxNum(downloadNum);
|
||||
if (diff >= 1) {
|
||||
for (int i = 0; i < diff; i++) {
|
||||
DownloadTask nextTask = getNextTask();
|
||||
if (nextTask != null && nextTask.getDownloadEntity().getState() == IEntity.STATE_WAIT) {
|
||||
startTask(nextTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public DownloadTask createTask(String target, DownloadTaskEntity entity) {
|
||||
DownloadTask task = null;
|
||||
if (!TextUtils.isEmpty(target)) {
|
||||
task = (DownloadTask) TaskFactory.getInstance()
|
||||
.createTask(target, entity, DownloadSchedulers.getInstance());
|
||||
entity.key = entity.getEntity().getDownloadUrl();
|
||||
mCachePool.putTask(task);
|
||||
} else {
|
||||
Log.e(TAG, "target name 为 null是!!");
|
||||
Log.e(TAG, "target name 为 null!!");
|
||||
}
|
||||
return task;
|
||||
}
|
||||
|
||||
@Override public DownloadTask getTask(DownloadEntity entity) {
|
||||
return getTask(entity.getDownloadUrl());
|
||||
}
|
||||
|
||||
@Override public void removeTask(DownloadEntity entity) {
|
||||
DownloadTask task = mExecutePool.getTask(entity.getDownloadUrl());
|
||||
if (task != null) {
|
||||
Log.d(TAG, "从执行池删除任务,删除" + (mExecutePool.removeTask(task) ? "成功" : "失败"));
|
||||
}
|
||||
task = mCachePool.getTask(entity.getDownloadUrl());
|
||||
if (task != null) {
|
||||
Log.d(TAG, "从缓存池删除任务,删除" + (mCachePool.removeTask(task) ? "成功" : "失败"));
|
||||
}
|
||||
@Override public void stopTask(DownloadTask task) {
|
||||
task.setHighestPriority(false);
|
||||
super.stopTask(task);
|
||||
}
|
||||
}
|
@ -19,8 +19,10 @@ package com.arialyy.aria.core.queue;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||
import com.arialyy.aria.core.download.DownloadTask;
|
||||
import com.arialyy.aria.core.inf.AbsEntity;
|
||||
import com.arialyy.aria.core.inf.AbsNormalTask;
|
||||
import com.arialyy.aria.core.inf.AbsTask;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.core.inf.ITask;
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
import com.arialyy.aria.core.upload.UploadEntity;
|
||||
import com.arialyy.aria.core.upload.UploadTask;
|
||||
@ -30,7 +32,7 @@ import com.arialyy.aria.core.upload.UploadTaskEntity;
|
||||
* Created by lyy on 2016/8/16.
|
||||
* 任务功能接口
|
||||
*/
|
||||
public interface ITaskQueue<TASK extends ITask, TASK_ENTITY extends AbsTaskEntity, ENTITY extends IEntity> {
|
||||
public interface ITaskQueue<TASK extends AbsTask, TASK_ENTITY extends AbsTaskEntity, ENTITY extends AbsEntity> {
|
||||
|
||||
/**
|
||||
* 通过key判断任务是否正在执行
|
||||
@ -46,11 +48,9 @@ public interface ITaskQueue<TASK extends ITask, TASK_ENTITY extends AbsTaskEntit
|
||||
void stopAllTask();
|
||||
|
||||
/**
|
||||
* 设置任务为最高优先级任务
|
||||
*
|
||||
* @param task {@link DownloadTask}、{@link UploadTask}
|
||||
* 删除所有任务
|
||||
*/
|
||||
void setTaskHighestPriority(TASK task);
|
||||
void removeAllTask();
|
||||
|
||||
/**
|
||||
* 开始任务
|
||||
|
@ -17,12 +17,15 @@
|
||||
package com.arialyy.aria.core.queue;
|
||||
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.download.DownloadGroupTask;
|
||||
import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
|
||||
import com.arialyy.aria.core.download.DownloadTask;
|
||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||
import com.arialyy.aria.core.inf.ITask;
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
import com.arialyy.aria.core.scheduler.DownloadSchedulers;
|
||||
import com.arialyy.aria.core.scheduler.ISchedulers;
|
||||
import com.arialyy.aria.core.scheduler.UploadSchedulers;
|
||||
import com.arialyy.aria.core.upload.UploadTask;
|
||||
import com.arialyy.aria.core.upload.UploadTaskEntity;
|
||||
|
||||
@ -30,8 +33,7 @@ import com.arialyy.aria.core.upload.UploadTaskEntity;
|
||||
* Created by lyy on 2016/8/18.
|
||||
* 任务工厂
|
||||
*/
|
||||
public class TaskFactory {
|
||||
private static final String TAG = "TaskFactory";
|
||||
class TaskFactory {
|
||||
|
||||
private static volatile TaskFactory INSTANCE = null;
|
||||
|
||||
@ -53,20 +55,36 @@ public class TaskFactory {
|
||||
*
|
||||
* @param entity 下载实体
|
||||
* @param schedulers 对应的任务调度器
|
||||
* @param <ENTITY> {@link DownloadTaskEntity}、{@link UploadTaskEntity}
|
||||
* @param <SCHEDULER> {@link DownloadSchedulers}
|
||||
* @return {@link DownloadTask}、{@link UploadTask}
|
||||
* @param <TASK_ENTITY> {@link DownloadTaskEntity}、{@link UploadTaskEntity}、{@link
|
||||
* DownloadGroupTaskEntity}
|
||||
* @param <SCHEDULER> {@link DownloadSchedulers}、{@link UploadSchedulers}
|
||||
* @return {@link DownloadTask}、{@link UploadTask}、{@link DownloadGroupTask}
|
||||
*/
|
||||
<ENTITY extends AbsTaskEntity, SCHEDULER extends ISchedulers> ITask createTask(String targetName,
|
||||
ENTITY entity, SCHEDULER schedulers) {
|
||||
<TASK_ENTITY extends AbsTaskEntity, SCHEDULER extends ISchedulers> ITask createTask(
|
||||
String targetName, TASK_ENTITY entity, SCHEDULER schedulers) {
|
||||
if (entity instanceof DownloadTaskEntity) {
|
||||
return createDownloadTask(targetName, (DownloadTaskEntity) entity, schedulers);
|
||||
} else if (entity instanceof UploadTaskEntity) {
|
||||
return createUploadTask(targetName, (UploadTaskEntity) entity, schedulers);
|
||||
} else if (entity instanceof DownloadGroupTaskEntity) {
|
||||
return createDownloadGroupTask(targetName, (DownloadGroupTaskEntity) entity, schedulers);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建下载任务主任务
|
||||
*
|
||||
* @param entity 下载任务实体{@link DownloadGroupTask}
|
||||
* @param schedulers {@link ISchedulers}
|
||||
*/
|
||||
private DownloadGroupTask createDownloadGroupTask(String targetName,
|
||||
DownloadGroupTaskEntity entity, ISchedulers schedulers) {
|
||||
DownloadGroupTask.Builder builder = new DownloadGroupTask.Builder(targetName, entity);
|
||||
builder.setOutHandler(schedulers);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param entity 上传任务实体{@link UploadTaskEntity}
|
||||
* @param schedulers {@link ISchedulers}
|
||||
|
@ -19,7 +19,7 @@ package com.arialyy.aria.core.queue;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.queue.pool.ExecutePool;
|
||||
import com.arialyy.aria.core.queue.pool.BaseExecutePool;
|
||||
import com.arialyy.aria.core.scheduler.UploadSchedulers;
|
||||
import com.arialyy.aria.core.upload.UploadEntity;
|
||||
import com.arialyy.aria.core.upload.UploadTask;
|
||||
@ -43,11 +43,15 @@ public class UploadTaskQueue extends AbsTaskQueue<UploadTask, UploadTaskEntity,
|
||||
}
|
||||
|
||||
private UploadTaskQueue() {
|
||||
mExecutePool = new ExecutePool<>(false);
|
||||
mExecutePool = new BaseExecutePool<>(false);
|
||||
}
|
||||
|
||||
@Override public void setMaxTaskNum(int newMaxNum) {
|
||||
@Override public String getKey(UploadEntity entity) {
|
||||
return entity.getFilePath();
|
||||
}
|
||||
|
||||
@Override public int getConfigMaxNum() {
|
||||
return AriaManager.getInstance(AriaManager.APP).getUploadConfig().oldMaxTaskNum;
|
||||
}
|
||||
|
||||
@Override public UploadTask createTask(String targetName, UploadTaskEntity entity) {
|
||||
@ -55,25 +59,11 @@ public class UploadTaskQueue extends AbsTaskQueue<UploadTask, UploadTaskEntity,
|
||||
if (!TextUtils.isEmpty(targetName)) {
|
||||
task = (UploadTask) TaskFactory.getInstance()
|
||||
.createTask(targetName, entity, UploadSchedulers.getInstance());
|
||||
entity.key = entity.getEntity().getFilePath();
|
||||
mCachePool.putTask(task);
|
||||
} else {
|
||||
Log.e(TAG, "target name 为 null是!!");
|
||||
}
|
||||
return task;
|
||||
}
|
||||
|
||||
@Override public UploadTask getTask(UploadEntity entity) {
|
||||
return getTask(entity.getFilePath());
|
||||
}
|
||||
|
||||
@Override public void removeTask(UploadEntity entity) {
|
||||
UploadTask task = mExecutePool.getTask(entity.getFilePath());
|
||||
if (task != null) {
|
||||
Log.d(TAG, "从执行池删除任务,删除" + (mExecutePool.removeTask(task) ? "成功" : "失败"));
|
||||
}
|
||||
task = mCachePool.getTask(entity.getFilePath());
|
||||
if (task != null) {
|
||||
Log.d(TAG, "从缓存池删除任务,删除" + (mCachePool.removeTask(task) ? "成功" : "失败"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,14 +32,14 @@ import java.util.concurrent.TimeUnit;
|
||||
* Created by lyy on 2016/8/14.
|
||||
* 任务缓存池,所有下载任务最先缓存在这个池中
|
||||
*/
|
||||
public class CachePool<TASK extends ITask> implements IPool<TASK> {
|
||||
private static final String TAG = "CachePool";
|
||||
public class BaseCachePool<TASK extends ITask> implements IPool<TASK> {
|
||||
private static final String TAG = "BaseCachePool";
|
||||
private static final int MAX_NUM = Integer.MAX_VALUE; //最大下载任务数
|
||||
private static final long TIME_OUT = 1000;
|
||||
private Map<String, TASK> mCacheMap;
|
||||
private LinkedBlockingQueue<TASK> mCacheQueue;
|
||||
|
||||
public CachePool() {
|
||||
public BaseCachePool() {
|
||||
mCacheQueue = new LinkedBlockingQueue<>(MAX_NUM);
|
||||
mCacheMap = new HashMap<>();
|
||||
}
|
||||
@ -95,7 +95,7 @@ public class CachePool<TASK extends ITask> implements IPool<TASK> {
|
||||
@Override public TASK pollTask() {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
try {
|
||||
TASK task = null;
|
||||
TASK task;
|
||||
task = mCacheQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS);
|
||||
if (task != null) {
|
||||
String url = task.getKey();
|
@ -23,7 +23,6 @@ import com.arialyy.aria.core.inf.ITask;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@ -31,14 +30,14 @@ import java.util.concurrent.TimeUnit;
|
||||
* Created by lyy on 2016/8/15.
|
||||
* 任务执行池,所有当前下载任务都该任务池中,默认下载大小为2
|
||||
*/
|
||||
public class ExecutePool<TASK extends ITask> implements IPool<TASK> {
|
||||
private static final String TAG = "ExecutePool";
|
||||
private static final long TIME_OUT = 1000;
|
||||
private ArrayBlockingQueue<TASK> mExecuteQueue;
|
||||
private Map<String, TASK> mExecuteMap;
|
||||
private int mSize;
|
||||
public class BaseExecutePool<TASK extends ITask> implements IPool<TASK> {
|
||||
private final String TAG = "BaseExecutePool";
|
||||
final long TIME_OUT = 1000;
|
||||
ArrayBlockingQueue<TASK> mExecuteQueue;
|
||||
Map<String, TASK> mExecuteMap;
|
||||
protected int mSize;
|
||||
|
||||
public ExecutePool(boolean isDownload) {
|
||||
public BaseExecutePool(boolean isDownload) {
|
||||
if (isDownload) {
|
||||
mSize = AriaManager.getInstance(AriaManager.APP).getDownloadConfig().getMaxTaskNum();
|
||||
} else {
|
||||
@ -67,10 +66,6 @@ public class ExecutePool<TASK extends ITask> implements IPool<TASK> {
|
||||
return false;
|
||||
} else {
|
||||
if (mExecuteQueue.size() >= mSize) {
|
||||
Set<String> keys = mExecuteMap.keySet();
|
||||
for (String key : keys) {
|
||||
if (mExecuteMap.get(key).isHighestPriorityTask()) return false;
|
||||
}
|
||||
if (pollFirstTask()) {
|
||||
return putNewTask(task);
|
||||
}
|
||||
@ -106,7 +101,7 @@ public class ExecutePool<TASK extends ITask> implements IPool<TASK> {
|
||||
*
|
||||
* @param newTask 新任务
|
||||
*/
|
||||
private boolean putNewTask(TASK newTask) {
|
||||
boolean putNewTask(TASK newTask) {
|
||||
String url = newTask.getKey();
|
||||
boolean s = mExecuteQueue.offer(newTask);
|
||||
Log.w(TAG, "任务添加" + (s ? "成功" : "失败,【" + url + "】"));
|
||||
@ -119,16 +114,13 @@ public class ExecutePool<TASK extends ITask> implements IPool<TASK> {
|
||||
/**
|
||||
* 队列满时,将移除下载队列中的第一个任务
|
||||
*/
|
||||
private boolean pollFirstTask() {
|
||||
boolean pollFirstTask() {
|
||||
try {
|
||||
TASK oldTask = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS);
|
||||
if (oldTask == null) {
|
||||
Log.e(TAG, "移除任务失败");
|
||||
return false;
|
||||
}
|
||||
if (oldTask.isHighestPriorityTask()) {
|
||||
return false;
|
||||
}
|
||||
oldTask.stop();
|
||||
String key = CommonUtil.keyToHashKey(oldTask.getKey());
|
||||
mExecuteMap.remove(key);
|
||||
@ -142,7 +134,7 @@ public class ExecutePool<TASK extends ITask> implements IPool<TASK> {
|
||||
@Override public TASK pollTask() {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
try {
|
||||
TASK task = null;
|
||||
TASK task;
|
||||
task = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS);
|
||||
if (task != null) {
|
||||
String url = task.getKey();
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.queue.pool;
|
||||
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.download.DownloadTask;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/29.
|
||||
* 单个下载任务的执行池
|
||||
*/
|
||||
public class DownloadExecutePool extends BaseExecutePool<DownloadTask> {
|
||||
private final String TAG = "DownloadExecutePool";
|
||||
|
||||
public DownloadExecutePool(boolean isDownload) {
|
||||
super(isDownload);
|
||||
}
|
||||
|
||||
@Override public boolean putTask(DownloadTask task) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
if (task == null) {
|
||||
Log.e(TAG, "任务不能为空!!");
|
||||
return false;
|
||||
}
|
||||
String url = task.getKey();
|
||||
if (mExecuteQueue.contains(task)) {
|
||||
Log.e(TAG, "队列中已经包含了该任务,任务key【" + url + "】");
|
||||
return false;
|
||||
} else {
|
||||
if (mExecuteQueue.size() >= mSize) {
|
||||
Set<String> keys = mExecuteMap.keySet();
|
||||
for (String key : keys) {
|
||||
if (mExecuteMap.get(key).isHighestPriorityTask()) return false;
|
||||
}
|
||||
if (pollFirstTask()) {
|
||||
return putNewTask(task);
|
||||
}
|
||||
} else {
|
||||
return putNewTask(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override boolean pollFirstTask() {
|
||||
try {
|
||||
DownloadTask oldTask = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS);
|
||||
if (oldTask == null) {
|
||||
Log.e(TAG, "移除任务失败");
|
||||
return false;
|
||||
}
|
||||
if (oldTask.isHighestPriorityTask()) {
|
||||
return false;
|
||||
}
|
||||
oldTask.stop();
|
||||
String key = CommonUtil.keyToHashKey(oldTask.getKey());
|
||||
mExecuteMap.remove(key);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@ -22,18 +22,18 @@ import com.arialyy.aria.core.inf.ITask;
|
||||
* Created by lyy on 2016/8/14.
|
||||
* 任务池
|
||||
*/
|
||||
public interface IPool<T extends ITask> {
|
||||
interface IPool<T extends ITask> {
|
||||
/**
|
||||
* 将下载任务添加到任务池中
|
||||
*/
|
||||
public boolean putTask(T task);
|
||||
boolean putTask(T task);
|
||||
|
||||
/**
|
||||
* 按照队列原则取出下载任务
|
||||
*
|
||||
* @return 返回null或者下载任务
|
||||
*/
|
||||
public T pollTask();
|
||||
T pollTask();
|
||||
|
||||
/**
|
||||
* 通过下载链接获取下载任务,当任务不为空时,队列将删除该下载任务
|
||||
@ -41,7 +41,7 @@ public interface IPool<T extends ITask> {
|
||||
* @param downloadUrl 下载链接
|
||||
* @return 返回null或者下载任务
|
||||
*/
|
||||
public T getTask(String downloadUrl);
|
||||
T getTask(String downloadUrl);
|
||||
|
||||
/**
|
||||
* 删除任务池中的下载任务
|
||||
@ -49,7 +49,7 @@ public interface IPool<T extends ITask> {
|
||||
* @param task 下载任务
|
||||
* @return true:移除成功
|
||||
*/
|
||||
public boolean removeTask(T task);
|
||||
boolean removeTask(T task);
|
||||
|
||||
/**
|
||||
* 通过key除下载任务
|
||||
@ -57,12 +57,12 @@ public interface IPool<T extends ITask> {
|
||||
* @param key 下载链接
|
||||
* @return true:移除成功
|
||||
*/
|
||||
public boolean removeTask(String key);
|
||||
boolean removeTask(String key);
|
||||
|
||||
/**
|
||||
* 池子大小
|
||||
*
|
||||
* @return 返回缓存池或者执行池大小
|
||||
*/
|
||||
public int size();
|
||||
int size();
|
||||
}
|
@ -21,9 +21,9 @@ 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.AbsTask;
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.core.inf.ITask;
|
||||
import com.arialyy.aria.core.queue.ITaskQueue;
|
||||
import com.arialyy.aria.core.upload.UploadTask;
|
||||
import java.util.Iterator;
|
||||
@ -34,19 +34,19 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
/**
|
||||
* Created by lyy on 2017/6/4.
|
||||
*/
|
||||
public abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, ENTITY extends AbsEntity, TASK extends ITask<ENTITY>, QUEUE extends ITaskQueue<TASK, TASK_ENTITY, ENTITY>>
|
||||
abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, ENTITY extends AbsEntity, TASK extends AbsTask<ENTITY>, QUEUE extends ITaskQueue<TASK, TASK_ENTITY, ENTITY>>
|
||||
implements ISchedulers<TASK> {
|
||||
private static final String TAG = "AbsSchedulers";
|
||||
private final String TAG = "AbsSchedulers";
|
||||
|
||||
/**
|
||||
* 下载的动态生成的代理类后缀
|
||||
*/
|
||||
String DOWNLOAD_PROXY_CLASS_SUFFIX = "$$DownloadListenerProxy";
|
||||
private String DOWNLOAD_PROXY_CLASS_SUFFIX = "$$DownloadListenerProxy";
|
||||
|
||||
/**
|
||||
* 上传的动态生成的代理类后缀
|
||||
*/
|
||||
String UPLOAD_PROXY_CLASS_SUFFIX = "$$UploadListenerProxy";
|
||||
private String UPLOAD_PROXY_CLASS_SUFFIX = "$$UploadListenerProxy";
|
||||
|
||||
protected QUEUE mQueue;
|
||||
protected boolean isDownload = true;
|
||||
@ -131,7 +131,7 @@ public abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, ENTITY ex
|
||||
Log.e(TAG, "请传入下载任务");
|
||||
return true;
|
||||
}
|
||||
callback(msg.what, task);
|
||||
//callback(msg.what, task);
|
||||
ENTITY entity = task.getEntity();
|
||||
switch (msg.what) {
|
||||
case STOP:
|
||||
@ -154,6 +154,7 @@ public abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, ENTITY ex
|
||||
handleFailTask(task);
|
||||
break;
|
||||
}
|
||||
callback(msg.what, task);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.scheduler;
|
||||
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.download.DownloadGroupEntity;
|
||||
import com.arialyy.aria.core.download.DownloadGroupTask;
|
||||
import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
|
||||
import com.arialyy.aria.core.queue.DownloadGroupTaskQueue;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/7/2.
|
||||
*/
|
||||
public class DownloadGroupSchedulers extends
|
||||
AbsSchedulers<DownloadGroupTaskEntity, DownloadGroupEntity, DownloadGroupTask, DownloadGroupTaskQueue> {
|
||||
private final String TAG = "DownloadGroupSchedulers";
|
||||
private static volatile DownloadGroupSchedulers INSTANCE = null;
|
||||
|
||||
private DownloadGroupSchedulers() {
|
||||
mQueue = DownloadGroupTaskQueue.getInstance();
|
||||
isDownload = true;
|
||||
}
|
||||
|
||||
public static DownloadGroupSchedulers getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
INSTANCE = new DownloadGroupSchedulers();
|
||||
}
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
@ -29,7 +29,7 @@ import com.arialyy.aria.core.download.DownloadTask;
|
||||
public class DownloadSchedulers
|
||||
extends AbsSchedulers<DownloadTaskEntity, DownloadEntity, DownloadTask, DownloadTaskQueue> {
|
||||
|
||||
private static final String TAG = "DownloadSchedulers";
|
||||
private final String TAG = "DownloadSchedulers";
|
||||
private static volatile DownloadSchedulers INSTANCE = null;
|
||||
|
||||
private DownloadSchedulers() {
|
||||
|
@ -17,15 +17,16 @@ package com.arialyy.aria.core.upload;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import com.arialyy.aria.core.inf.AbsEntity;
|
||||
import com.arialyy.aria.core.inf.AbsNormalEntity;
|
||||
import com.arialyy.aria.orm.Ignore;
|
||||
import com.arialyy.aria.orm.Primary;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2017/2/9.
|
||||
* 上传文件实体
|
||||
*/
|
||||
public class UploadEntity extends AbsEntity implements Parcelable {
|
||||
|
||||
public class UploadEntity extends AbsNormalEntity implements Parcelable {
|
||||
@Primary
|
||||
private String filePath; //文件路径
|
||||
private boolean isComplete = false;
|
||||
|
||||
|
@ -17,12 +17,12 @@ package com.arialyy.aria.core.upload;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.command.AbsCmd;
|
||||
import com.arialyy.aria.core.command.CmdFactory;
|
||||
import com.arialyy.aria.core.download.DownloadReceiver;
|
||||
import com.arialyy.aria.core.command.normal.AbsNormalCmd;
|
||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
||||
import com.arialyy.aria.core.download.DownloadTaskEntity;
|
||||
import com.arialyy.aria.core.inf.AbsReceiver;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.core.inf.IReceiver;
|
||||
import com.arialyy.aria.core.scheduler.DownloadSchedulers;
|
||||
import com.arialyy.aria.core.scheduler.ISchedulerListener;
|
||||
import com.arialyy.aria.core.scheduler.UploadSchedulers;
|
||||
import com.arialyy.aria.orm.DbEntity;
|
||||
@ -37,10 +37,8 @@ import java.util.regex.Pattern;
|
||||
* Created by lyy on 2017/2/6.
|
||||
* 上传功能接收器
|
||||
*/
|
||||
public class UploadReceiver implements IReceiver<UploadEntity> {
|
||||
public class UploadReceiver extends AbsReceiver<UploadEntity> {
|
||||
private static final String TAG = "DownloadReceiver";
|
||||
public String targetName;
|
||||
public Object obj;
|
||||
public ISchedulerListener<UploadTask> listener;
|
||||
|
||||
/**
|
||||
@ -84,25 +82,30 @@ public class UploadReceiver implements IReceiver<UploadEntity> {
|
||||
|
||||
@Override public void stopAllTask() {
|
||||
List<UploadEntity> allEntity = DbEntity.findAllData(UploadEntity.class);
|
||||
List<AbsCmd> stopCmds = new ArrayList<>();
|
||||
List<AbsNormalCmd> stopCmds = new ArrayList<>();
|
||||
for (UploadEntity entity : allEntity) {
|
||||
if (entity.getState() == IEntity.STATE_RUNNING) {
|
||||
stopCmds.add(
|
||||
CommonUtil.createCmd(targetName, new UploadTaskEntity(entity), CmdFactory.TASK_STOP));
|
||||
CommonUtil.createCmd(targetName, new UploadTaskEntity(), NormalCmdFactory.TASK_STOP));
|
||||
}
|
||||
}
|
||||
AriaManager.getInstance(AriaManager.APP).setCmds(stopCmds).exe();
|
||||
}
|
||||
|
||||
@Override public void removeAllTask() {
|
||||
/**
|
||||
* 删除所有任务
|
||||
*
|
||||
* @param removeFile {@code true} 删除已经上传完成的任务,不仅删除上传记录,还会删除已经上传完成的文件,{@code false}
|
||||
* 如果文件已经上传完成,只删除上传记录
|
||||
*/
|
||||
@Override public void removeAllTask(boolean removeFile) {
|
||||
final AriaManager am = AriaManager.getInstance(AriaManager.APP);
|
||||
List<UploadEntity> allEntity = DbEntity.findAllData(UploadEntity.class);
|
||||
List<AbsCmd> cancelCmds = new ArrayList<>();
|
||||
for (UploadEntity entity : allEntity) {
|
||||
cancelCmds.add(
|
||||
CommonUtil.createCmd(targetName, new UploadTaskEntity(entity), CmdFactory.TASK_CANCEL));
|
||||
}
|
||||
am.setCmds(cancelCmds).exe();
|
||||
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(
|
||||
CommonUtil.createCmd(targetName, new DownloadTaskEntity(), NormalCmdFactory.TASK_CANCEL_ALL))
|
||||
.exe();
|
||||
|
||||
Set<String> keys = am.getReceiver().keySet();
|
||||
for (String key : keys) {
|
||||
IReceiver receiver = am.getReceiver().get(key);
|
||||
@ -118,8 +121,10 @@ public class UploadReceiver implements IReceiver<UploadEntity> {
|
||||
|
||||
/**
|
||||
* 添加调度器回调
|
||||
*
|
||||
* @see #register()
|
||||
*/
|
||||
public UploadReceiver addSchedulerListener(ISchedulerListener<UploadTask> listener) {
|
||||
@Deprecated public UploadReceiver addSchedulerListener(ISchedulerListener<UploadTask> listener) {
|
||||
this.listener = listener;
|
||||
UploadSchedulers.getInstance().addSchedulerListener(targetName, listener);
|
||||
return this;
|
||||
|
@ -16,27 +16,26 @@
|
||||
package com.arialyy.aria.core.upload;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import com.arialyy.aria.core.RequestEnum;
|
||||
import com.arialyy.aria.core.inf.AbsTarget;
|
||||
import com.arialyy.aria.core.inf.AbsNormalTarget;
|
||||
import com.arialyy.aria.core.queue.UploadTaskQueue;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2017/2/28.
|
||||
*/
|
||||
public class UploadTarget extends AbsTarget<UploadEntity, UploadTaskEntity> {
|
||||
public class UploadTarget extends AbsNormalTarget<UploadTarget, UploadEntity, UploadTaskEntity> {
|
||||
|
||||
UploadTarget(UploadEntity entity, String targetName) {
|
||||
this.entity = entity;
|
||||
this.targetName = targetName;
|
||||
taskEntity = new UploadTaskEntity(entity);
|
||||
this.mEntity = entity;
|
||||
this.mTargetName = targetName;
|
||||
mTaskEntity = new UploadTaskEntity();
|
||||
mTaskEntity.entity = entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置userAgent
|
||||
*/
|
||||
public UploadTarget setUserAngent(@NonNull String userAgent) {
|
||||
taskEntity.userAgent = userAgent;
|
||||
mTaskEntity.userAgent = userAgent;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -46,7 +45,7 @@ public class UploadTarget extends AbsTarget<UploadEntity, UploadTaskEntity> {
|
||||
* @param uploadUrl 上传路径
|
||||
*/
|
||||
public UploadTarget setUploadUrl(@NonNull String uploadUrl) {
|
||||
taskEntity.uploadUrl = uploadUrl;
|
||||
mTaskEntity.uploadUrl = uploadUrl;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -56,7 +55,7 @@ public class UploadTarget extends AbsTarget<UploadEntity, UploadTaskEntity> {
|
||||
* @param attachment 附件key
|
||||
*/
|
||||
public UploadTarget setAttachment(@NonNull String attachment) {
|
||||
taskEntity.attachment = attachment;
|
||||
mTaskEntity.attachment = attachment;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -64,7 +63,7 @@ public class UploadTarget extends AbsTarget<UploadEntity, UploadTaskEntity> {
|
||||
* 设置文件名
|
||||
*/
|
||||
public UploadTarget setFileName(String fileName) {
|
||||
entity.setFileName(fileName);
|
||||
mEntity.setFileName(fileName);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -74,28 +73,7 @@ public class UploadTarget extends AbsTarget<UploadEntity, UploadTaskEntity> {
|
||||
* @param contentType tip:multipart/form-data
|
||||
*/
|
||||
public UploadTarget setContentType(String contentType) {
|
||||
taskEntity.contentType = contentType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给url请求添加头部
|
||||
*
|
||||
* @param key 头部key
|
||||
* @param header 头部value
|
||||
*/
|
||||
public UploadTarget addHeader(@NonNull String key, @NonNull String header) {
|
||||
super._addHeader(key, header);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给url请求添加头部
|
||||
*
|
||||
* @param headers key为http头部的key,Value为http头对应的配置
|
||||
*/
|
||||
public UploadTarget addHeaders(Map<String, String> headers) {
|
||||
super._addHeaders(headers);
|
||||
mTaskEntity.contentType = contentType;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -103,28 +81,15 @@ public class UploadTarget extends AbsTarget<UploadEntity, UploadTaskEntity> {
|
||||
* 下载任务是否存在
|
||||
*/
|
||||
@Override public boolean taskExists() {
|
||||
return UploadTaskQueue.getInstance().getTask(entity.getFilePath()) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置请求类型
|
||||
*
|
||||
* @param requestEnum {@link RequestEnum}
|
||||
*/
|
||||
public UploadTarget setRequestMode(RequestEnum requestEnum) {
|
||||
super._setRequestMode(requestEnum);
|
||||
return this;
|
||||
}
|
||||
|
||||
private UploadEntity getUploadEntity() {
|
||||
return entity;
|
||||
return UploadTaskQueue.getInstance().getTask(mEntity.getFilePath()) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否在下载
|
||||
*/
|
||||
public boolean isUploading() {
|
||||
UploadTask task = UploadTaskQueue.getInstance().getTask(entity);
|
||||
UploadTask task = UploadTaskQueue.getInstance().getTask(mEntity);
|
||||
return task != null && task.isRunning();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ final class UploadUtil implements Runnable {
|
||||
UploadUtil(UploadTaskEntity taskEntity, IUploadListener listener) {
|
||||
mTaskEntity = taskEntity;
|
||||
CheckUtil.checkTaskEntity(taskEntity);
|
||||
mUploadEntity = taskEntity.uploadEntity;
|
||||
mUploadEntity = taskEntity.getEntity();
|
||||
if (listener == null) {
|
||||
throw new IllegalArgumentException("上传监听不能为空");
|
||||
}
|
||||
@ -162,11 +162,11 @@ final class UploadUtil implements Runnable {
|
||||
writer.append("Content-Disposition: form-data; name=\"")
|
||||
.append(attachment)
|
||||
.append("\"; filename=\"")
|
||||
.append(mTaskEntity.uploadEntity.getFileName())
|
||||
.append(mTaskEntity.getEntity().getFileName())
|
||||
.append("\"")
|
||||
.append(LINE_END);
|
||||
writer.append("Content-Type: ")
|
||||
.append(URLConnection.guessContentTypeFromName(mTaskEntity.uploadEntity.getFileName()))
|
||||
.append(URLConnection.guessContentTypeFromName(mTaskEntity.getEntity().getFileName()))
|
||||
.append(LINE_END);
|
||||
writer.append("Content-Transfer-Encoding: binary").append(LINE_END);
|
||||
writer.append(LINE_END);
|
||||
|
@ -17,7 +17,11 @@ package com.arialyy.aria.orm;
|
||||
|
||||
import android.text.TextUtils;
|
||||
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.upload.UploadEntity;
|
||||
import com.arialyy.aria.core.upload.UploadTaskEntity;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ -28,7 +32,7 @@ import java.util.Map;
|
||||
public class DBConfig {
|
||||
static Map<String, Class> mapping = new HashMap<>();
|
||||
static String DB_NAME;
|
||||
static int VERSION = 3;
|
||||
static int VERSION = 6;
|
||||
|
||||
static {
|
||||
if (TextUtils.isEmpty(DB_NAME)) {
|
||||
@ -41,6 +45,10 @@ public class DBConfig {
|
||||
|
||||
static {
|
||||
mapping.put("DownloadEntity", DownloadEntity.class);
|
||||
mapping.put("DownloadGroupEntity", DownloadGroupEntity.class);
|
||||
mapping.put("DownloadTaskEntity", DownloadTaskEntity.class);
|
||||
mapping.put("DownloadGroupTaskEntity", DownloadGroupTaskEntity.class);
|
||||
mapping.put("UploadEntity", UploadEntity.class);
|
||||
mapping.put("UploadTaskEntity", UploadTaskEntity.class);
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,10 @@ package com.arialyy.aria.orm;
|
||||
import android.support.annotation.NonNull;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2015/11/2.
|
||||
@ -156,7 +158,7 @@ public class DbEntity {
|
||||
|
||||
private void updateRowID() {
|
||||
try {
|
||||
Field[] fields = CommonUtil.getFields(getClass());
|
||||
List<Field> fields = CommonUtil.getAllFields(getClass());
|
||||
List<String> where = new ArrayList<>();
|
||||
List<String> values = new ArrayList<>();
|
||||
for (Field field : fields) {
|
||||
@ -165,7 +167,16 @@ public class DbEntity {
|
||||
continue;
|
||||
}
|
||||
where.add(field.getName());
|
||||
values.add(field.get(this) + "");
|
||||
Type type = field.getType();
|
||||
if (SqlHelper.isOneToOne(field)) {
|
||||
values.add(SqlHelper.getOneToOneParams(field));
|
||||
} else if (type == List.class) {
|
||||
values.add(SqlHelper.getListElementParams(field));
|
||||
} else if (type == Map.class) {
|
||||
values.add(SqlHelper.map2Str((Map<String, String>) field.get(this)));
|
||||
} else {
|
||||
values.add(field.get(this) + "");
|
||||
}
|
||||
}
|
||||
DbEntity entity = findData(getClass(), where.toArray(new String[where.size()]),
|
||||
values.toArray(new String[values.size()]));
|
||||
|
36
Aria/src/main/java/com/arialyy/aria/orm/OneToMany.java
Normal file
36
Aria/src/main/java/com/arialyy/aria/orm/OneToMany.java
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.orm;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/7/4.
|
||||
* 一对多
|
||||
*/
|
||||
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface OneToMany {
|
||||
/**
|
||||
* 关联的表
|
||||
*/
|
||||
Class<? extends DbEntity> table();
|
||||
/**
|
||||
* 关联的主键
|
||||
*/
|
||||
String key();
|
||||
}
|
38
Aria/src/main/java/com/arialyy/aria/orm/OneToOne.java
Normal file
38
Aria/src/main/java/com/arialyy/aria/orm/OneToOne.java
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.orm;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/7/4.
|
||||
* 一对一
|
||||
*/
|
||||
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface OneToOne {
|
||||
|
||||
/**
|
||||
* 关联的表
|
||||
*/
|
||||
Class<? extends DbEntity> table();
|
||||
|
||||
/**
|
||||
* 关联的主键
|
||||
*/
|
||||
String key();
|
||||
}
|
@ -25,6 +25,6 @@ import java.lang.annotation.Target;
|
||||
* Created by lyy on 2015/11/2.
|
||||
* 表ID字段指定
|
||||
*/
|
||||
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Id {
|
||||
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Primary {
|
||||
int value() default -1;
|
||||
}
|
@ -28,9 +28,13 @@ import com.arialyy.aria.util.CheckUtil;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@ -186,12 +190,26 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
sql = String.format(sql, params);
|
||||
print(FIND_DATA, sql);
|
||||
Cursor cursor = db.rawQuery(sql, null);
|
||||
List<T> data = cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor) : null;
|
||||
List<T> data = cursor.getCount() > 0 ? newInstanceEntity(db, clazz, cursor) : null;
|
||||
cursor.close();
|
||||
close(db);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件查寻数据
|
||||
*/
|
||||
static synchronized <T extends DbEntity> List<T> findData(SQLiteDatabase db, String tableName,
|
||||
String... expression) {
|
||||
Class<T> clazz = null;
|
||||
try {
|
||||
clazz = (Class<T>) Class.forName(tableName);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return findData(db, clazz, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件查寻数据
|
||||
*/
|
||||
@ -215,7 +233,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(clazz, cursor) : null;
|
||||
List<T> data = cursor.getCount() > 0 ? newInstanceEntity(db, clazz, cursor) : null;
|
||||
cursor.close();
|
||||
close(db);
|
||||
return data;
|
||||
@ -230,7 +248,7 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
sb.append("SELECT rowid, * FROM ").append(CommonUtil.getClassName(clazz));
|
||||
print(FIND_ALL_DATA, sb.toString());
|
||||
Cursor cursor = db.rawQuery(sb.toString(), null);
|
||||
List<T> data = cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor) : null;
|
||||
List<T> data = cursor.getCount() > 0 ? newInstanceEntity(db, clazz, cursor) : null;
|
||||
cursor.close();
|
||||
close(db);
|
||||
return data;
|
||||
@ -273,11 +291,22 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
}
|
||||
sb.append(i > 0 ? ", " : "");
|
||||
try {
|
||||
Object value = field.get(dbEntity);
|
||||
sb.append(field.getName())
|
||||
.append("='")
|
||||
.append(value == null ? "" : value.toString())
|
||||
.append("'");
|
||||
String value;
|
||||
sb.append(field.getName()).append("='");
|
||||
Type type = field.getType();
|
||||
if (type == Map.class) {
|
||||
value = map2Str((Map<String, String>) field.get(dbEntity));
|
||||
} else if (type == List.class) {
|
||||
value = getListElementParams(field);
|
||||
} else if (isOneToOne(field)) {
|
||||
value = getOneToOneParams(field);
|
||||
} else {
|
||||
Object obj = field.get(dbEntity);
|
||||
value = obj == null ? "" : obj.toString();
|
||||
}
|
||||
|
||||
sb.append(value == null ? "" : value);
|
||||
sb.append("'");
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -307,24 +336,35 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
continue;
|
||||
}
|
||||
sb.append(i > 0 ? ", " : "");
|
||||
//sb.append(getFieldName(field.getType(), field));
|
||||
sb.append(field.getName());
|
||||
i++;
|
||||
}
|
||||
sb.append(") VALUES (");
|
||||
i = 0;
|
||||
for (Field field : fields) {
|
||||
field.setAccessible(true);
|
||||
if (ignoreField(field)) {
|
||||
continue;
|
||||
try {
|
||||
for (Field field : fields) {
|
||||
field.setAccessible(true);
|
||||
if (ignoreField(field)) {
|
||||
continue;
|
||||
}
|
||||
sb.append(i > 0 ? ", " : "");
|
||||
sb.append("'");
|
||||
Type type = field.getType();
|
||||
if (type == Map.class) {
|
||||
sb.append(map2Str((Map<String, String>) field.get(dbEntity)));
|
||||
} else if (type == List.class) {
|
||||
sb.append(getListElementParams(field));
|
||||
} else if (isOneToOne(field)) {
|
||||
sb.append(getOneToOneParams(field));
|
||||
} else {
|
||||
sb.append(field.get(dbEntity));
|
||||
}
|
||||
sb.append("'");
|
||||
i++;
|
||||
}
|
||||
sb.append(i > 0 ? ", " : "");
|
||||
sb.append("'");
|
||||
try {
|
||||
sb.append(field.get(dbEntity)).append("'");
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
i++;
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
sb.append(")");
|
||||
print(INSERT_DATA, sb.toString());
|
||||
@ -333,6 +373,47 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
close(db);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一对一参数
|
||||
*/
|
||||
static String getOneToOneParams(Field field) {
|
||||
OneToOne oneToOne = field.getAnnotation(OneToOne.class);
|
||||
if (oneToOne == null) {
|
||||
throw new IllegalArgumentException("@OneToOne注解的对象必须要有@Primary注解的字段");
|
||||
}
|
||||
return oneToOne.table().getName() + "$$" + oneToOne.key();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取List一对多参数
|
||||
*
|
||||
* @param field list反射字段
|
||||
*/
|
||||
static String getListElementParams(Field field) {
|
||||
OneToMany oneToMany = field.getAnnotation(OneToMany.class);
|
||||
if (oneToMany == null) {
|
||||
throw new IllegalArgumentException("List中元素必须被@OneToMany注解");
|
||||
}
|
||||
//关联的表名
|
||||
String tableName = oneToMany.table().getName();
|
||||
//关联的字段
|
||||
String key = oneToMany.key();
|
||||
return tableName + "$$" + key;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找class的主键字段
|
||||
*
|
||||
* @return 返回主键字段名
|
||||
*/
|
||||
private static String getPrimaryName(Class<? extends DbEntity> clazz) {
|
||||
List<Field> fields = CommonUtil.getAllFields(clazz);
|
||||
for (Field field : fields) {
|
||||
if (isPrimary(field)) return field.getName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找表是否存在
|
||||
*
|
||||
@ -383,9 +464,13 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
if (ignoreField(field)) {
|
||||
continue;
|
||||
}
|
||||
sb.append(field.getName());
|
||||
Class<?> type = field.getType();
|
||||
if (type == String.class) {
|
||||
sb.append(field.getName());
|
||||
if (type == String.class
|
||||
|| type == Map.class
|
||||
|| type == List.class
|
||||
|| isOneToOne(field)
|
||||
|| type.isEnum()) {
|
||||
sb.append(" varchar");
|
||||
} else if (type == int.class || type == Integer.class) {
|
||||
sb.append(" interger");
|
||||
@ -404,6 +489,9 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
if (isPrimary(field)) {
|
||||
sb.append(" PRIMARY KEY");
|
||||
}
|
||||
sb.append(",");
|
||||
}
|
||||
String str = sb.toString();
|
||||
@ -414,15 +502,32 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
close(db);
|
||||
}
|
||||
|
||||
///**
|
||||
// * 通过字段类型和获取保存在数据库表字段名
|
||||
// */
|
||||
//private static String getFieldName(Class<?> type, Field field) {
|
||||
// String fieldName;
|
||||
// if (type == Map.class) {
|
||||
// fieldName = MAP_FIELD + field.getName();
|
||||
// } else if (type == List.class) {
|
||||
// fieldName = LIST_FIELD + field.getName();
|
||||
// } else if (isGeneric(field)) {
|
||||
// fieldName = GENERIC_FIELD + field.getName();
|
||||
// } else {
|
||||
// fieldName = field.getName();
|
||||
// }
|
||||
// return fieldName;
|
||||
//}
|
||||
|
||||
/**
|
||||
* 打印数据库日志
|
||||
*
|
||||
* @param type {@link DbUtil}
|
||||
*/
|
||||
static void print(int type, String sql) {
|
||||
if (true) {
|
||||
return;
|
||||
}
|
||||
//if (true) {
|
||||
// return;
|
||||
//}
|
||||
String str = "";
|
||||
switch (type) {
|
||||
case CREATE_TABLE:
|
||||
@ -450,8 +555,8 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
/**
|
||||
* 根据数据游标创建一个具体的对象
|
||||
*/
|
||||
static synchronized <T extends DbEntity> List<T> newInstanceEntity(Class<T> clazz,
|
||||
Cursor cursor) {
|
||||
private static synchronized <T extends DbEntity> List<T> newInstanceEntity(SQLiteDatabase db,
|
||||
Class<T> clazz, Cursor cursor) {
|
||||
List<Field> fields = CommonUtil.getAllFields(clazz);
|
||||
List<T> entitys = new ArrayList<>();
|
||||
if (fields != null && fields.size() > 0) {
|
||||
@ -482,8 +587,35 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
field.set(entity, new Date(cursor.getString(column)));
|
||||
} else if (type == byte[].class) {
|
||||
field.set(entity, cursor.getBlob(column));
|
||||
} else {
|
||||
continue;
|
||||
} else if (type == Map.class) {
|
||||
field.set(entity, str2Map(cursor.getString(column)));
|
||||
} else if (type == List.class) {
|
||||
//主键字段
|
||||
String primaryKey = getPrimaryName(clazz);
|
||||
if (TextUtils.isEmpty(primaryKey)) {
|
||||
throw new IllegalArgumentException("List中的元素对象必须需要@Primary注解的字段");
|
||||
}
|
||||
//list字段保存的数据
|
||||
int kc = cursor.getColumnIndex(primaryKey);
|
||||
String params = cursor.getString(column);
|
||||
String primaryData = cursor.getString(kc);
|
||||
if (TextUtils.isEmpty(primaryData)) continue;
|
||||
List<T> list = findForeignData(db, primaryData, params);
|
||||
if (list == null) continue;
|
||||
field.set(entity, findForeignData(db, primaryKey, params));
|
||||
} else if (isOneToOne(field)) {
|
||||
String primaryKey = getPrimaryName(clazz);
|
||||
if (TextUtils.isEmpty(primaryKey)) {
|
||||
throw new IllegalArgumentException("@OneToOne的注解对象必须需要@Primary注解的字段");
|
||||
}
|
||||
int kc = cursor.getColumnIndex(primaryKey);
|
||||
String params = cursor.getString(column);
|
||||
String primaryData = cursor.getString(kc);
|
||||
if (TextUtils.isEmpty(primaryData) || primaryData.equalsIgnoreCase("null")) continue;
|
||||
List<T> list = findForeignData(db, primaryData, params);
|
||||
if (list != null && list.size() > 1) {
|
||||
field.set(entity, list.get(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
entity.rowID = cursor.getInt(cursor.getColumnIndex("rowid"));
|
||||
@ -499,6 +631,53 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
return entitys;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找一对多、一对一的关联数据
|
||||
*
|
||||
* @param primary 当前表的主键
|
||||
* @param childParams 当前表关联数据的类名 $$ 主键名
|
||||
*/
|
||||
private static <T extends DbEntity> List<T> findForeignData(SQLiteDatabase db, String primary,
|
||||
String childParams) {
|
||||
String[] params = childParams.split("\\$\\$");
|
||||
return findData(db, params[0], params[1] + "=?", primary);
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转Map,只支持
|
||||
* <pre>
|
||||
* {@code Map<String, String>}
|
||||
* </pre>
|
||||
*/
|
||||
private static Map<String, String> str2Map(String str) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
if (TextUtils.isEmpty(str)) {
|
||||
return map;
|
||||
}
|
||||
String[] element = str.split(",");
|
||||
for (String data : element) {
|
||||
String[] s = data.split("\\$");
|
||||
map.put(s[0], s[1]);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map转字符串,只支持
|
||||
* <pre>
|
||||
* {@code Map<String, String>}
|
||||
* </pre>
|
||||
*/
|
||||
static String map2Str(Map<String, String> map) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Set<String> keys = map.keySet();
|
||||
for (String key : keys) {
|
||||
sb.append(key).append("$").append(map.get(key)).append(",");
|
||||
}
|
||||
String str = sb.toString();
|
||||
return TextUtils.isEmpty(str) ? str : str.substring(0, str.length() - 1);
|
||||
}
|
||||
|
||||
private static void close(SQLiteDatabase db) {
|
||||
//if (db != null && db.isOpen()) db.close();
|
||||
}
|
||||
@ -523,4 +702,28 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
|| Modifier.isStatic(modifiers)
|
||||
|| Modifier.isFinal(modifiers);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否一对多注解
|
||||
*/
|
||||
static boolean isOneToMany(Field field) {
|
||||
OneToMany oneToMany = field.getAnnotation(OneToMany.class);
|
||||
return oneToMany != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是一对一注解
|
||||
*/
|
||||
static boolean isOneToOne(Field field) {
|
||||
OneToOne oneToOne = field.getAnnotation(OneToOne.class);
|
||||
return oneToOne != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是主键
|
||||
*/
|
||||
static boolean isPrimary(Field field) {
|
||||
Primary pk = field.getAnnotation(Primary.class);
|
||||
return pk != null;
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
import com.arialyy.aria.core.upload.UploadEntity;
|
||||
import com.arialyy.aria.core.upload.UploadTaskEntity;
|
||||
import com.arialyy.aria.exception.FileException;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -76,6 +77,24 @@ public class CheckUtil {
|
||||
if (TextUtils.isEmpty(downloadUrl)) throw new IllegalArgumentException("下载链接不能为null");
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测下载链接组是否为null
|
||||
*/
|
||||
public static void checkDownloadUrls(List<String> urls) {
|
||||
if (urls == null || urls.isEmpty()) {
|
||||
throw new IllegalArgumentException("链接组不能为null");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查下载任务组保存路径
|
||||
*/
|
||||
public static void checkDownloadPaths(List<String> paths) {
|
||||
if (paths == null || paths.isEmpty()) {
|
||||
throw new IllegalArgumentException("链接保存路径不能为null");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测上传地址是否为null
|
||||
*/
|
||||
@ -88,9 +107,9 @@ public class CheckUtil {
|
||||
*/
|
||||
public static void checkTaskEntity(AbsTaskEntity entity) {
|
||||
if (entity instanceof DownloadTaskEntity) {
|
||||
checkDownloadTaskEntity(((DownloadTaskEntity) entity).downloadEntity);
|
||||
checkDownloadTaskEntity(((DownloadTaskEntity) entity).getEntity());
|
||||
} else if (entity instanceof UploadTaskEntity) {
|
||||
checkUploadTaskEntity(((UploadTaskEntity) entity).uploadEntity);
|
||||
checkUploadTaskEntity(((UploadTaskEntity) entity).getEntity());
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,7 +122,7 @@ public class CheckUtil {
|
||||
public static boolean checkCmdEntity(AbsTaskEntity entity, boolean checkType) {
|
||||
boolean b = false;
|
||||
if (entity instanceof DownloadTaskEntity) {
|
||||
DownloadEntity entity1 = ((DownloadTaskEntity) entity).downloadEntity;
|
||||
DownloadEntity entity1 = ((DownloadTaskEntity) entity).getEntity();
|
||||
if (entity1 == null) {
|
||||
Log.e(TAG, "下载实体不能为空");
|
||||
} else if (checkType && TextUtils.isEmpty(entity1.getDownloadUrl())) {
|
||||
@ -114,7 +133,7 @@ public class CheckUtil {
|
||||
b = true;
|
||||
}
|
||||
} else if (entity instanceof UploadTaskEntity) {
|
||||
UploadEntity entity1 = ((UploadTaskEntity) entity).uploadEntity;
|
||||
UploadEntity entity1 = ((UploadTaskEntity) entity).getEntity();
|
||||
if (entity1 == null) {
|
||||
Log.e(TAG, "上传实体不能为空");
|
||||
} else if (TextUtils.isEmpty(entity1.getFilePath())) {
|
||||
|
@ -22,9 +22,12 @@ import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.command.CmdFactory;
|
||||
import com.arialyy.aria.core.command.AbsCmd;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
||||
import com.arialyy.aria.core.command.normal.AbsNormalCmd;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
import com.arialyy.aria.core.upload.UploadEntity;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileInputStream;
|
||||
@ -42,6 +45,11 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
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.
|
||||
@ -49,10 +57,123 @@ import java.util.regex.Pattern;
|
||||
public class CommonUtil {
|
||||
private static final String TAG = "CommonUtil";
|
||||
|
||||
/**
|
||||
* 实例化泛型的实际类型参数
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void typeCheck(Type type) throws Exception {
|
||||
System.out.println("该类型是" + type);
|
||||
// 参数化类型
|
||||
if (type instanceof ParameterizedType) {
|
||||
Type[] typeArguments = ((ParameterizedType) type).getActualTypeArguments();
|
||||
for (int i = 0; i < typeArguments.length; i++) {
|
||||
// 类型变量
|
||||
if (typeArguments[i] instanceof TypeVariable) {
|
||||
System.out.println("第" + (i + 1) + "个泛型参数类型是类型变量" + typeArguments[i] + ",无法实例化。");
|
||||
}
|
||||
// 通配符表达式
|
||||
else if (typeArguments[i] instanceof WildcardType) {
|
||||
System.out.println("第" + (i + 1) + "个泛型参数类型是通配符表达式" + typeArguments[i] + ",无法实例化。");
|
||||
}
|
||||
// 泛型的实际类型,即实际存在的类型
|
||||
else if (typeArguments[i] instanceof Class) {
|
||||
System.out.println("第" + (i + 1) + "个泛型参数类型是:" + typeArguments[i] + ",可以直接实例化对象");
|
||||
}
|
||||
}
|
||||
// 参数化类型数组或类型变量数组
|
||||
} else if (type instanceof GenericArrayType) {
|
||||
System.out.println("该泛型类型是参数化类型数组或类型变量数组,可以获取其原始类型。");
|
||||
Type componentType = ((GenericArrayType) type).getGenericComponentType();
|
||||
// 类型变量
|
||||
if (componentType instanceof TypeVariable) {
|
||||
System.out.println("该类型变量数组的原始类型是类型变量" + componentType + ",无法实例化。");
|
||||
}
|
||||
// 参数化类型,参数化类型数组或类型变量数组
|
||||
// 参数化类型数组或类型变量数组也可以是多维的数组,getGenericComponentType()方法仅仅是去掉最右边的[]
|
||||
else {
|
||||
// 递归调用方法自身
|
||||
typeCheck(componentType);
|
||||
}
|
||||
} else if (type instanceof TypeVariable) {
|
||||
System.out.println("该类型是类型变量");
|
||||
} else if (type instanceof WildcardType) {
|
||||
System.out.println("该类型是通配符表达式");
|
||||
} else if (type instanceof Class) {
|
||||
System.out.println("该类型不是泛型类型");
|
||||
} else {
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据下载任务组的url创建key
|
||||
*
|
||||
* @return urls 为 null 或者 size为0,返回""
|
||||
*/
|
||||
public static String getMd5Code(List<String> urls) {
|
||||
if (urls == null || urls.size() < 1) return "";
|
||||
String md5 = "";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String url : urls) {
|
||||
sb.append(url);
|
||||
}
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
md.update(sb.toString().getBytes());
|
||||
md5 = new BigInteger(1, md.digest()).toString(16);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
return md5;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除上传任务的配置,包括
|
||||
*
|
||||
* @param removeFile {@code true} 删除已经上传完成的任务,不仅删除上传记录,还会删除已经上传完成的文件,{@code false}
|
||||
* 如果文件已经上传完成,只删除上传记录
|
||||
*/
|
||||
public static void delUploadTaskConfig(boolean removeFile, UploadEntity entity) {
|
||||
if (removeFile) {
|
||||
File file = new File(entity.getFilePath());
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
File config = new File(
|
||||
AriaManager.APP.getFilesDir().getPath() + "/temp/" + entity.getFileName() + ".properties");
|
||||
if (config.exists()) {
|
||||
config.delete();
|
||||
}
|
||||
entity.deleteData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除下载任务的配置,包括
|
||||
*
|
||||
* @param removeFile{@code true} 删除已经下载完成的任务,不仅删除下载记录,还会删除已经下载完成的文件,{@code false}
|
||||
* 如果文件已经下载完成,只删除下载记录
|
||||
*/
|
||||
public static void delDownloadTaskConfig(boolean removeFile, DownloadEntity entity) {
|
||||
if (removeFile) {
|
||||
File file = new File(entity.getDownloadPath());
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
File config = new File(
|
||||
AriaManager.APP.getFilesDir().getPath() + "/temp/" + entity.getFileName() + ".properties");
|
||||
if (config.exists()) {
|
||||
config.delete();
|
||||
}
|
||||
entity.deleteData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取CPU核心数
|
||||
*/
|
||||
public static int getNumCores() {
|
||||
public static int getCoresNum() {
|
||||
//Private Class to display only CPU devices in the directory listing
|
||||
class CpuFilter implements FileFilter {
|
||||
@Override public boolean accept(File pathname) {
|
||||
@ -180,8 +301,8 @@ public class CommonUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static <T extends AbsTaskEntity> AbsCmd createCmd(String target, T entity, int cmd) {
|
||||
return CmdFactory.getInstance().createCmd(target, entity, cmd);
|
||||
public static <T extends AbsTaskEntity> AbsNormalCmd createCmd(String target, T entity, int cmd) {
|
||||
return NormalCmdFactory.getInstance().createCmd(target, entity, cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -11,4 +11,4 @@ dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
}
|
||||
|
||||
//apply from: 'bintray-release.gradle'
|
||||
apply from: 'bintray-release.gradle'
|
@ -14,4 +14,4 @@ dependencies {
|
||||
compile project(':AriaAnnotations')
|
||||
}
|
||||
|
||||
//apply from: 'bintray-release.gradle'
|
||||
apply from: 'bintray-release.gradle'
|
@ -42,7 +42,6 @@ dependencies {
|
||||
compile 'com.squareup.okhttp3:okhttp:3.2.0'
|
||||
compile 'com.arialyy.frame:MVVM2:2.2.0'
|
||||
compile project(':Aria')
|
||||
// compile 'com.arialyy.aria:aria-core:3.2.0'
|
||||
// annotationProcessor 'com.arialyy.aria:aria-compiler:3.2.0'
|
||||
compile project(':AriaCompiler')
|
||||
|
||||
}
|
||||
|
@ -7,9 +7,6 @@
|
||||
<!--设置下载线程,线程下载数改变后,新的下载任务才会生效,如果任务大小小于1m,该设置也不会生效-->
|
||||
<threadNum value="4"/>
|
||||
|
||||
<!--是否打开下载广播,默认为false,不建议使用广播,你可以使用Download注解来实现事件回调-->
|
||||
<openBroadcast value="false"/>
|
||||
|
||||
<!--设置下载队列最大任务数, 默认为2-->
|
||||
<maxTaskNum value="2"/>
|
||||
|
||||
@ -40,8 +37,6 @@
|
||||
</download>
|
||||
|
||||
<upload>
|
||||
<!--是否打开上传广播,默认为false,不建议使用广播,你可以使用Upload注解来实现事件回调-->
|
||||
<openBroadcast value="false"/>
|
||||
|
||||
<!--设置上传队列最大任务数, 默认为2-->
|
||||
<maxTaskNum value="2"/>
|
||||
|
@ -92,69 +92,4 @@ public class DownloadModule extends BaseModule {
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载广播过滤器
|
||||
*/
|
||||
public IntentFilter getDownloadFilter() {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addDataScheme(getContext().getPackageName());
|
||||
filter.addAction(Aria.ACTION_PRE);
|
||||
filter.addAction(Aria.ACTION_POST_PRE);
|
||||
filter.addAction(Aria.ACTION_RESUME);
|
||||
filter.addAction(Aria.ACTION_START);
|
||||
filter.addAction(Aria.ACTION_RUNNING);
|
||||
filter.addAction(Aria.ACTION_STOP);
|
||||
filter.addAction(Aria.ACTION_CANCEL);
|
||||
filter.addAction(Aria.ACTION_COMPLETE);
|
||||
filter.addAction(Aria.ACTION_FAIL);
|
||||
return filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Receiver
|
||||
*/
|
||||
public BroadcastReceiver createReceiver(final Handler handler) {
|
||||
|
||||
return new BroadcastReceiver() {
|
||||
long len = 0;
|
||||
|
||||
@Override public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
switch (action) {
|
||||
case Aria.ACTION_POST_PRE:
|
||||
DownloadEntity entity = intent.getParcelableExtra(Aria.DOWNLOAD_ENTITY);
|
||||
len = entity.getFileSize();
|
||||
L.d(TAG, "download onPre");
|
||||
handler.obtainMessage(SingleTaskActivity.DOWNLOAD_PRE, len).sendToTarget();
|
||||
break;
|
||||
case Aria.ACTION_START:
|
||||
L.d(TAG, "download start");
|
||||
break;
|
||||
case Aria.ACTION_RESUME:
|
||||
L.d(TAG, "download resume");
|
||||
long location = intent.getLongExtra(Aria.CURRENT_LOCATION, 1);
|
||||
handler.obtainMessage(SingleTaskActivity.DOWNLOAD_RESUME, location).sendToTarget();
|
||||
break;
|
||||
case Aria.ACTION_RUNNING:
|
||||
long current = intent.getLongExtra(Aria.CURRENT_LOCATION, 0);
|
||||
int progress = len == 0 ? 0 : (int) ((current * 100) / len);
|
||||
handler.obtainMessage(SingleTaskActivity.DOWNLOAD_RUNNING, progress).sendToTarget();
|
||||
break;
|
||||
case Aria.ACTION_STOP:
|
||||
L.d(TAG, "download stop");
|
||||
handler.sendEmptyMessage(SingleTaskActivity.DOWNLOAD_STOP);
|
||||
break;
|
||||
case Aria.ACTION_COMPLETE:
|
||||
handler.sendEmptyMessage(SingleTaskActivity.DOWNLOAD_COMPLETE);
|
||||
break;
|
||||
case Aria.ACTION_CANCEL:
|
||||
handler.sendEmptyMessage(SingleTaskActivity.DOWNLOAD_CANCEL);
|
||||
break;
|
||||
case Aria.ACTION_FAIL:
|
||||
handler.sendEmptyMessage(SingleTaskActivity.DOWNLOAD_FAILE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -65,7 +65,7 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
|
||||
"http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk";
|
||||
//"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://static.gaoshouyou.com/d/36/69/2d3699acfa69e9632262442c46516ad8.apk";
|
||||
//"http://static.gaoshouyou.com/d/36/69/2d3699acfa69e9632262442c46516ad8.apk";
|
||||
//"http://oqcpqqvuf.bkt.clouddn.com/ceshi.txt";
|
||||
//"http://down8.androidgame-store.com/201706122321/97967927DD4E53D9905ECAA7874C8128/new/game1/19/45319/com.neuralprisma-2.5.2.174-2000174_1494784835.apk?f=web_1";
|
||||
//不支持断点的链接
|
||||
@ -209,6 +209,10 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
|
||||
@Download.onTaskCancel(DOWNLOAD_URL) void taskCancel(DownloadTask task) {
|
||||
mUpdateHandler.sendEmptyMessage(DOWNLOAD_CANCEL);
|
||||
L.d(TAG, "task__cancel");
|
||||
//Aria.download(this)
|
||||
// .load(DOWNLOAD_URL)
|
||||
// .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk")
|
||||
// .add();
|
||||
}
|
||||
|
||||
@Download.onTaskFail(DOWNLOAD_URL) void taskFail(DownloadTask task) {
|
||||
@ -242,7 +246,6 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
|
||||
setBtState(false);
|
||||
}
|
||||
mSize.setText(target.getConvertFileSize());
|
||||
Aria.get(this).getDownloadConfig().setOpenBreadCast(true);
|
||||
}
|
||||
|
||||
public void onClick(View view) {
|
||||
@ -257,6 +260,11 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
|
||||
} else if (text.equals("恢复")) {
|
||||
Aria.download(this).load(DOWNLOAD_URL).resume();
|
||||
}
|
||||
//DownloadTarget target = Aria.download(this)
|
||||
// .load(DOWNLOAD_URL)
|
||||
// .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk");
|
||||
//target.add();
|
||||
//target.cancel();
|
||||
break;
|
||||
case R.id.stop:
|
||||
Aria.download(this).load(DOWNLOAD_URL).pause();
|
||||
|
@ -106,10 +106,7 @@ public class MultiDownloadActivity extends BaseActivity<ActivityMultiDownloadBin
|
||||
mAdapter.updateState(task.getDownloadEntity());
|
||||
}
|
||||
|
||||
@Download.onTaskRunning({
|
||||
"https://g37.gdl.netease.com/onmyoji_netease_10_1.0.20.apk",
|
||||
"http://static.gaoshouyou.com/d/eb/f2/dfeba30541f209ab8a50d847fc1661ce.apk"
|
||||
}) void taskRunning(DownloadTask task) {
|
||||
@Download.onTaskRunning() void taskRunning(DownloadTask task) {
|
||||
mAdapter.setProgress(task.getDownloadEntity());
|
||||
}
|
||||
}
|
||||
|
@ -40,12 +40,8 @@ class Configuration {
|
||||
/**
|
||||
* 旧任务数
|
||||
*/
|
||||
public static int oldMaxTaskNum = 2;
|
||||
public int oldMaxTaskNum = 2;
|
||||
|
||||
/**
|
||||
* 是否发送任务广播,true,发送
|
||||
*/
|
||||
boolean isOpenBreadCast = false;
|
||||
/**
|
||||
* 任务队列最大任务数, 默认为2
|
||||
*/
|
||||
@ -85,16 +81,6 @@ class Configuration {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isOpenBreadCast() {
|
||||
return isOpenBreadCast;
|
||||
}
|
||||
|
||||
public BaseConfig setOpenBreadCast(boolean openBreadCast) {
|
||||
isOpenBreadCast = openBreadCast;
|
||||
saveKey("isOpenBreadCast", openBreadCast + "");
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getMaxTaskNum() {
|
||||
return maxTaskNum;
|
||||
}
|
||||
@ -176,7 +162,8 @@ class Configuration {
|
||||
try {
|
||||
for (Field field : fields) {
|
||||
int m = field.getModifiers();
|
||||
if (Modifier.isFinal(m) || Modifier.isStatic(m)) {
|
||||
if (field.getName().equals("oldMaxTaskNum") || Modifier.isFinal(m) || Modifier.isStatic(
|
||||
m)) {
|
||||
continue;
|
||||
}
|
||||
field.setAccessible(true);
|
||||
|
@ -16,12 +16,10 @@
|
||||
package com.arialyy.aria.core.upload;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.Aria;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.inf.AbsTask;
|
||||
import com.arialyy.aria.core.inf.AbsNormalTask;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.core.scheduler.ISchedulers;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
@ -31,16 +29,15 @@ import java.lang.ref.WeakReference;
|
||||
* Created by lyy on 2017/2/23.
|
||||
* 上传任务
|
||||
*/
|
||||
public class UploadTask extends AbsTask<UploadTaskEntity, UploadEntity> {
|
||||
public class UploadTask extends AbsNormalTask<UploadEntity> {
|
||||
private static final String TAG = "UploadTask";
|
||||
private Handler mOutHandler;
|
||||
|
||||
private UploadUtil mUtil;
|
||||
private UListener mListener;
|
||||
|
||||
private UploadTask(UploadTaskEntity taskEntity, Handler outHandler) {
|
||||
mOutHandler = outHandler;
|
||||
mEntity = taskEntity.uploadEntity;
|
||||
mEntity = taskEntity.getEntity();
|
||||
mListener = new UListener(mOutHandler, this);
|
||||
mUtil = new UploadUtil(taskEntity, mListener);
|
||||
}
|
||||
@ -77,118 +74,99 @@ public class UploadTask extends AbsTask<UploadTaskEntity, UploadEntity> {
|
||||
if (mOutHandler != null) {
|
||||
mOutHandler.obtainMessage(ISchedulers.CANCEL, this).sendToTarget();
|
||||
}
|
||||
//发送取消下载的广播
|
||||
Intent intent = CommonUtil.createIntent(AriaManager.APP.getPackageName(), Aria.ACTION_CANCEL);
|
||||
intent.putExtra(Aria.UPLOAD_ENTITY, mEntity);
|
||||
AriaManager.APP.sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
|
||||
private static class UListener extends UploadListener {
|
||||
private static class
|
||||
UListener extends UploadListener {
|
||||
WeakReference<Handler> outHandler;
|
||||
WeakReference<UploadTask> task;
|
||||
long lastLen = 0; //上一次发送长度
|
||||
long lastTime = 0;
|
||||
long INTERVAL_TIME = 1000; //1m更新周期
|
||||
boolean isFirst = true;
|
||||
UploadEntity uploadEntity;
|
||||
Intent sendIntent;
|
||||
boolean isOpenBroadCast = false;
|
||||
UploadEntity entity;
|
||||
boolean isConvertSpeed = false;
|
||||
Context context;
|
||||
|
||||
UListener(Handler outHandle, UploadTask task) {
|
||||
this.outHandler = new WeakReference<>(outHandle);
|
||||
this.task = new WeakReference<>(task);
|
||||
uploadEntity = this.task.get().getEntity();
|
||||
sendIntent = CommonUtil.createIntent(AriaManager.APP.getPackageName(), Aria.ACTION_RUNNING);
|
||||
sendIntent.putExtra(Aria.UPLOAD_ENTITY, uploadEntity);
|
||||
entity = this.task.get().getEntity();
|
||||
context = AriaManager.APP;
|
||||
final AriaManager manager = AriaManager.getInstance(context);
|
||||
isOpenBroadCast = manager.getUploadConfig().isOpenBreadCast();
|
||||
isConvertSpeed = manager.getUploadConfig().isConvertSpeed();
|
||||
}
|
||||
|
||||
@Override public void onPre() {
|
||||
uploadEntity.setState(IEntity.STATE_PRE);
|
||||
sendIntent(Aria.ACTION_PRE, -1);
|
||||
sendInState2Target(ISchedulers.PRE);
|
||||
saveData(IEntity.STATE_PRE, -1);
|
||||
}
|
||||
|
||||
@Override public void onPostPre(long fileSize) {
|
||||
super.onPostPre(fileSize);
|
||||
uploadEntity.setFileSize(fileSize);
|
||||
uploadEntity.setState(IEntity.STATE_POST_PRE);
|
||||
sendIntent(Aria.ACTION_POST_PRE, 0);
|
||||
entity.setFileSize(fileSize);
|
||||
sendInState2Target(ISchedulers.POST_PRE);
|
||||
saveData(IEntity.STATE_POST_PRE, 0);
|
||||
}
|
||||
|
||||
@Override public void onStart() {
|
||||
uploadEntity.setState(IEntity.STATE_RUNNING);
|
||||
sendIntent(Aria.ACTION_START, 0);
|
||||
sendInState2Target(ISchedulers.START);
|
||||
saveData(IEntity.STATE_RUNNING, 0);
|
||||
}
|
||||
|
||||
@Override public void onResume(long resumeLocation) {
|
||||
uploadEntity.setState(IEntity.STATE_RUNNING);
|
||||
sendInState2Target(ISchedulers.RESUME);
|
||||
sendIntent(Aria.ACTION_RESUME, resumeLocation);
|
||||
saveData(IEntity.STATE_RUNNING, resumeLocation);
|
||||
}
|
||||
|
||||
@Override public void onStop(long stopLocation) {
|
||||
uploadEntity.setState(IEntity.STATE_STOP);
|
||||
handleSpeed(0);
|
||||
sendInState2Target(ISchedulers.STOP);
|
||||
sendIntent(Aria.ACTION_STOP, stopLocation);
|
||||
saveData(IEntity.STATE_STOP, stopLocation);
|
||||
}
|
||||
|
||||
@Override public void onProgress(long currentLocation) {
|
||||
if (System.currentTimeMillis() - lastTime > INTERVAL_TIME) {
|
||||
long speed = currentLocation - lastLen;
|
||||
sendIntent.putExtra(Aria.CURRENT_LOCATION, currentLocation);
|
||||
sendIntent.putExtra(Aria.CURRENT_SPEED, speed);
|
||||
lastTime = System.currentTimeMillis();
|
||||
if (isFirst) {
|
||||
speed = 0;
|
||||
isFirst = false;
|
||||
}
|
||||
handleSpeed(speed);
|
||||
uploadEntity.setCurrentProgress(currentLocation);
|
||||
entity.setCurrentProgress(currentLocation);
|
||||
lastLen = currentLocation;
|
||||
sendInState2Target(ISchedulers.RUNNING);
|
||||
AriaManager.APP.sendBroadcast(sendIntent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void onCancel() {
|
||||
uploadEntity.setState(IEntity.STATE_CANCEL);
|
||||
handleSpeed(0);
|
||||
sendInState2Target(ISchedulers.CANCEL);
|
||||
sendIntent(Aria.ACTION_CANCEL, -1);
|
||||
uploadEntity.deleteData();
|
||||
saveData(IEntity.STATE_CANCEL, -1);
|
||||
entity.deleteData();
|
||||
}
|
||||
|
||||
@Override public void onComplete() {
|
||||
uploadEntity.setState(IEntity.STATE_COMPLETE);
|
||||
uploadEntity.setComplete(true);
|
||||
entity.setComplete(true);
|
||||
handleSpeed(0);
|
||||
sendInState2Target(ISchedulers.COMPLETE);
|
||||
sendIntent(Aria.ACTION_COMPLETE, uploadEntity.getFileSize());
|
||||
saveData(IEntity.STATE_COMPLETE, entity.getFileSize());
|
||||
}
|
||||
|
||||
@Override public void onFail() {
|
||||
uploadEntity.setFailNum(uploadEntity.getFailNum() + 1);
|
||||
uploadEntity.setState(IEntity.STATE_FAIL);
|
||||
entity.setFailNum(entity.getFailNum() + 1);
|
||||
handleSpeed(0);
|
||||
sendInState2Target(ISchedulers.FAIL);
|
||||
sendIntent(Aria.ACTION_FAIL, -1);
|
||||
saveData(IEntity.STATE_FAIL, -1);
|
||||
}
|
||||
|
||||
private void handleSpeed(long speed) {
|
||||
if (isConvertSpeed) {
|
||||
uploadEntity.setConvertSpeed(CommonUtil.formatFileSize(speed) + "/s");
|
||||
entity.setConvertSpeed(CommonUtil.formatFileSize(speed) + "/s");
|
||||
} else {
|
||||
uploadEntity.setSpeed(speed);
|
||||
entity.setSpeed(speed);
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,17 +181,11 @@ public class UploadTask extends AbsTask<UploadTaskEntity, UploadEntity> {
|
||||
}
|
||||
}
|
||||
|
||||
private void sendIntent(String action, long location) {
|
||||
uploadEntity.setComplete(action.equals(Aria.ACTION_COMPLETE));
|
||||
uploadEntity.setCurrentProgress(location);
|
||||
uploadEntity.update();
|
||||
if (!isOpenBroadCast) return;
|
||||
Intent intent = CommonUtil.createIntent(context.getPackageName(), action);
|
||||
intent.putExtra(Aria.UPLOAD_ENTITY, uploadEntity);
|
||||
if (location != -1) {
|
||||
intent.putExtra(Aria.CURRENT_LOCATION, location);
|
||||
}
|
||||
context.sendBroadcast(intent);
|
||||
private void saveData(int state, long location) {
|
||||
entity.setState(state);
|
||||
entity.setComplete(state == IEntity.STATE_COMPLETE);
|
||||
entity.setCurrentProgress(location);
|
||||
entity.update();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,9 @@
|
||||
*/
|
||||
package com.arialyy.aria.core.upload;
|
||||
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
||||
import com.arialyy.aria.orm.OneToOne;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ -23,24 +25,23 @@ import java.util.Map;
|
||||
* Created by lyy on 2017/2/9.
|
||||
* 上传任务实体
|
||||
*/
|
||||
public class UploadTaskEntity extends AbsTaskEntity {
|
||||
public UploadEntity uploadEntity;
|
||||
public class UploadTaskEntity extends AbsTaskEntity<UploadEntity> {
|
||||
public String uploadUrl; //上传路径
|
||||
public String attachment; //文件上传需要的key
|
||||
public String contentType = "multipart/form-data"; //上传的文件类型
|
||||
public String userAgent = "User-Agent";
|
||||
public String charset = "utf-8";
|
||||
@OneToOne(table = UploadEntity.class, key = "filePath") public UploadEntity entity;
|
||||
|
||||
/**
|
||||
* 文件上传表单
|
||||
*/
|
||||
public Map<String, String> formFields = new HashMap<>();
|
||||
|
||||
public UploadTaskEntity(UploadEntity downloadEntity) {
|
||||
this.uploadEntity = downloadEntity;
|
||||
public UploadTaskEntity() {
|
||||
}
|
||||
|
||||
@Override public UploadEntity getEntity() {
|
||||
return uploadEntity;
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ buildscript {
|
||||
dependencies {
|
||||
// classpath 'com.android.tools.build:gradle:2.3.0'
|
||||
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.github.dcendents:android-maven-gradle-plugin:1.5'
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
@ -37,8 +37,8 @@ task clean(type: Delete) {
|
||||
ext {
|
||||
userOrg = 'arialyy'
|
||||
groupId = 'com.arialyy.aria'
|
||||
// publishVersion = '0.0.6'
|
||||
publishVersion = '3.1.9'
|
||||
// publishVersion = '0.0.8'
|
||||
publishVersion = '3.2.0'
|
||||
repoName='maven'
|
||||
desc = 'android 下载框架'
|
||||
website = 'https://github.com/AriaLyy/Aria'
|
||||
|
Reference in New Issue
Block a user