From ac99cc581f2d353a98980d5378573b23094ea57a Mon Sep 17 00:00:00 2001 From: AriaLyy <511455842@qq.com> Date: Tue, 5 Sep 2017 18:03:48 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AD=90=E4=BB=BB=E5=8A=A1=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/arialyy/aria/core/SubTaskManager.java | 103 +++++++++++++++ .../com/arialyy/aria/core/command/AbsCmd.java | 3 +- .../aria/core/command/AbsCmdFactory.java | 4 +- .../aria/core/command/group/AbsGroupCmd.java | 25 +++- .../core/command/group/GroupCancelCmd.java | 8 +- .../core/command/group/GroupCmdFactory.java | 45 ++++--- .../core/command/group/GroupStartCmd.java | 45 +------ .../aria/core/command/group/GroupStopCmd.java | 8 +- .../core/command/normal/NormalCmdFactory.java | 5 +- .../aria/core/download/BaseGroupTarget.java | 19 ++- .../core/download/DownloadGroupEntity.java | 13 -- .../aria/core/download/DownloadGroupTask.java | 2 +- .../download/DownloadGroupTaskEntity.java | 4 +- .../aria/core/download/DownloadReceiver.java | 2 +- .../download/downloader/AbsGroupUtil.java | 52 +++++++- .../aria/core/inf/AbsDownloadTarget.java | 4 +- .../arialyy/aria/core/inf/AbsGroupEntity.java | 16 +++ .../arialyy/aria/core/inf/AbsGroupTask.java | 36 +++++ .../com/arialyy/aria/core/inf/AbsTarget.java | 10 +- .../aria/core/inf/BaseGroupTaskEntity.java | 26 ++++ .../aria/core/upload/UploadReceiver.java | 2 +- .../com/arialyy/aria/util/CommonUtil.java | 34 +++-- .../arialyy/annotations/DownloadGroup.java | 79 +++++++++-- .../download/group/ChildHandleDialog.java | 123 ++++++++++++++++++ .../download/group/DownloadGroupActivity.java | 23 +++- .../simple/widget/SubStateLinearLayout.java | 44 ++++++- app/src/main/res/anim/dialog_enter.xml | 5 + app/src/main/res/anim/dialog_exit.xml | 6 + .../res/layout/activity_download_group.xml | 14 +- .../res/layout/dialog_sub_task_handler.xml | 76 +++++++++++ .../main/res/layout/test_activity_multi.xml | 14 +- app/src/main/res/values/strings.xml | 4 +- app/src/main/res/values/styles.xml | 17 +++ 33 files changed, 722 insertions(+), 149 deletions(-) create mode 100644 Aria/src/main/java/com/arialyy/aria/core/SubTaskManager.java create mode 100644 Aria/src/main/java/com/arialyy/aria/core/inf/BaseGroupTaskEntity.java create mode 100644 app/src/main/java/com/arialyy/simple/download/group/ChildHandleDialog.java create mode 100644 app/src/main/res/anim/dialog_enter.xml create mode 100644 app/src/main/res/anim/dialog_exit.xml create mode 100644 app/src/main/res/layout/dialog_sub_task_handler.xml diff --git a/Aria/src/main/java/com/arialyy/aria/core/SubTaskManager.java b/Aria/src/main/java/com/arialyy/aria/core/SubTaskManager.java new file mode 100644 index 00000000..058c713a --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/SubTaskManager.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core; + +import android.text.TextUtils; +import android.util.Log; +import com.arialyy.aria.core.command.group.GroupCmdFactory; +import com.arialyy.aria.core.inf.BaseGroupTaskEntity; +import com.arialyy.aria.util.CommonUtil; +import java.util.List; + +/** + * Created by lyy on 2017/9/4. + * 子任务管理器 + */ +public class SubTaskManager { + private String TAG = "SubTaskManager"; + private BaseGroupTaskEntity mEntity; + private String mTargetName; + + public SubTaskManager(String targetName, BaseGroupTaskEntity entity) { + mTargetName = targetName; + mEntity = entity; + } + + /** + * 启动任务组中的子任务 + * + * @param url 子任务下载地址 + */ + public void startSubTask(String url) { + if (checkUrl(url)) { + AriaManager.getInstance(AriaManager.APP) + .setCmd( + CommonUtil.createGroupCmd(mTargetName, mEntity, GroupCmdFactory.SUB_TASK_START, url)) + .exe(); + } + } + + /** + * 停止任务组中的子任务 + * + * @param url 子任务下载地址 + */ + public void stopSubTask(String url) { + if (checkUrl(url)) { + AriaManager.getInstance(AriaManager.APP) + .setCmd( + CommonUtil.createGroupCmd(mTargetName, mEntity, GroupCmdFactory.SUB_TASK_STOP, url)) + .exe(); + } + } + + /** + * 删除子任务组中的子任务 + * + * @param url 子任务下载地址 + */ + public void cancelSubTask(String url) { + if (checkUrl(url)) { + AriaManager.getInstance(AriaManager.APP) + .setCmd( + CommonUtil.createGroupCmd(mTargetName, mEntity, GroupCmdFactory.SUB_TASK_CANCEL, url)) + .exe(); + } + } + + /** + * 检查任务地址 + * + * @param url 子任务地址 + * @return {@code false} 任务地址不合法 + */ + private boolean checkUrl(String url) { + if (TextUtils.isEmpty(url)) { + Log.e(TAG, "子任务地址不能为null"); + return false; + } + List urls = mEntity.getEntity().getUrls(); + if (urls == null || urls.isEmpty()) { + Log.e(TAG, "任务组任务链接为null"); + return false; + } + if (!urls.contains(url)) { + Log.e(TAG, "任务组中没有改Url【+ " + url + "】"); + return false; + } + return true; + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/AbsCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/AbsCmd.java index d337a453..34c80642 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/AbsCmd.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/AbsCmd.java @@ -22,11 +22,12 @@ import com.arialyy.aria.core.queue.ITaskQueue; /** * Created by AriaL on 2017/6/29. */ -public abstract class AbsCmd implements ICmd{ +public abstract class AbsCmd implements ICmd { protected ITaskQueue mQueue; protected T mTaskEntity; protected String TAG; protected String mTargetName; + /** * 是否是下载任务的命令 * {@code true} 下载任务的命令,{@code false} 上传任务的命令 diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/AbsCmdFactory.java b/Aria/src/main/java/com/arialyy/aria/core/command/AbsCmdFactory.java index 8ed0d498..75fcb5ef 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/AbsCmdFactory.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/AbsCmdFactory.java @@ -21,11 +21,11 @@ import com.arialyy.aria.core.inf.AbsTaskEntity; * Created by AriaL on 2017/6/29. * 抽象命令工厂 */ -public abstract class AbsCmdFactory { +public abstract class AbsCmdFactory { /** * @param target 创建任务的对象 * @param entity 下载实体 */ - public abstract CMD createCmd(String target, T entity, int type); + public abstract CMD createCmd(String target, TASK_ENTITY entity, int type); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/group/AbsGroupCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/group/AbsGroupCmd.java index 5d24fa67..9dca385f 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/group/AbsGroupCmd.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/group/AbsGroupCmd.java @@ -15,21 +15,25 @@ */ package com.arialyy.aria.core.command.group; +import android.util.Log; import com.arialyy.aria.core.command.AbsCmd; import com.arialyy.aria.core.download.DownloadGroupTaskEntity; -import com.arialyy.aria.core.download.DownloadTaskEntity; -import com.arialyy.aria.core.inf.AbsTaskEntity; +import com.arialyy.aria.core.inf.AbsGroupTask; +import com.arialyy.aria.core.inf.BaseGroupTaskEntity; import com.arialyy.aria.core.queue.DownloadGroupTaskQueue; -import com.arialyy.aria.core.queue.DownloadTaskQueue; -import com.arialyy.aria.core.queue.UploadTaskQueue; -import com.arialyy.aria.core.upload.UploadTaskEntity; import com.arialyy.aria.util.CommonUtil; /** * Created by AriaL on 2017/6/29. * 任务组命令 */ -abstract class AbsGroupCmd extends AbsCmd { +public abstract class AbsGroupCmd extends AbsCmd { + /** + * 需要控制的子任务url + */ + String childUrl; + + AbsGroupTask tempTask; /** * @param targetName 创建任务的对象名 @@ -43,4 +47,13 @@ abstract class AbsGroupCmd extends AbsCmd { isDownloadCmd = true; } } + + boolean checkTask() { + tempTask = (AbsGroupTask) mQueue.getTask(mTaskEntity.getEntity()); + if (tempTask == null || !tempTask.isRunning()) { + Log.d(TAG, "任务组没有执行,先执行任务组任务才能够执行子任务"); + return false; + } + return true; + } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/group/GroupCancelCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/group/GroupCancelCmd.java index 5b6e5cf9..44fb4241 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/group/GroupCancelCmd.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/group/GroupCancelCmd.java @@ -15,13 +15,13 @@ */ package com.arialyy.aria.core.command.group; -import com.arialyy.aria.core.inf.AbsTaskEntity; +import com.arialyy.aria.core.inf.BaseGroupTaskEntity; /** * Created by AriaL on 2017/6/29. * 删除任务组 */ -class GroupCancelCmd extends AbsGroupCmd { +class GroupCancelCmd extends AbsGroupCmd { /** * @param targetName 创建任务的对象名 */ @@ -30,6 +30,8 @@ class GroupCancelCmd extends AbsGroupCmd { } @Override public void executeCmd() { - + if (checkTask()) { + tempTask.cancelSubTask(childUrl); + } } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/group/GroupCmdFactory.java b/Aria/src/main/java/com/arialyy/aria/core/command/group/GroupCmdFactory.java index a818d688..f2dbfa63 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/group/GroupCmdFactory.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/group/GroupCmdFactory.java @@ -16,25 +16,25 @@ package com.arialyy.aria.core.command.group; import com.arialyy.aria.core.AriaManager; -import com.arialyy.aria.core.command.AbsCmdFactory; -import com.arialyy.aria.core.inf.AbsTaskEntity; +import com.arialyy.aria.core.inf.BaseGroupTaskEntity; /** * Created by AriaL on 2017/6/29. + * 任务组子任务控制命令 */ -class GroupCmdFactory extends AbsCmdFactory { +public class GroupCmdFactory { /** - * 启动任务 + * 启动子任务 */ - public static final int TASK_START = 0xa1; + public static final int SUB_TASK_START = 0xa1; /** - * 停止任务 + * 停止子任务 */ - public static final int TASK_STOP = 0xa2; + public static final int SUB_TASK_STOP = 0xa2; /** - * 取消任务 + * 取消子任务 */ - public static final int TASK_CANCEL = 0xa3; + public static final int SUB_TASK_CANCEL = 0xa3; private static volatile GroupCmdFactory INSTANCE = null; @@ -54,18 +54,25 @@ class GroupCmdFactory extends AbsCmdFactory { /** * @param target 创建任务的对象 * @param entity 下载实体 - * @param type 命令类型{@link #TASK_START}、{@link #TASK_CANCEL}、{@link #TASK_STOP} + * @param type 命令类型{@link #SUB_TASK_START}、{@link #SUB_TASK_STOP}、{@link #SUB_TASK_CANCEL} + * @param childUrl 需要控制的子任务url */ - public AbsGroupCmd createCmd(String target, T entity, int type) { + public AbsGroupCmd createCmd(String target, BaseGroupTaskEntity entity, int type, + String childUrl) { + AbsGroupCmd cmd = null; switch (type) { - case TASK_START: - return new GroupStartCmd<>(target, entity); - case TASK_STOP: - return new GroupStopCmd<>(target, entity); - case TASK_CANCEL: - return new GroupCancelCmd<>(target, entity); - default: - return null; + case SUB_TASK_START: + cmd = new GroupStartCmd<>(target, entity); + break; + case SUB_TASK_STOP: + cmd = new GroupStopCmd<>(target, entity); + break; + case SUB_TASK_CANCEL: + cmd = new GroupCancelCmd<>(target, entity); } + if (cmd != null) { + cmd.childUrl = childUrl; + } + return cmd; } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/group/GroupStartCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/group/GroupStartCmd.java index 8f890987..c4dba5b0 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/group/GroupStartCmd.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/group/GroupStartCmd.java @@ -15,18 +15,13 @@ */ package com.arialyy.aria.core.command.group; -import android.text.TextUtils; -import com.arialyy.aria.core.AriaManager; -import com.arialyy.aria.core.common.QueueMod; -import com.arialyy.aria.core.inf.AbsGroupTask; -import com.arialyy.aria.core.inf.AbsTaskEntity; -import com.arialyy.aria.core.inf.IEntity; +import com.arialyy.aria.core.inf.BaseGroupTaskEntity; /** * Created by AriaL on 2017/6/29. - * 任务组开始命令,该命令负责开始下载或恢复下载的操作 + * 任务组开始命令,该命令负责处理任务组子任务的开始\恢复等工作 */ -class GroupStartCmd extends AbsGroupCmd { +class GroupStartCmd extends AbsGroupCmd { /** * @param targetName 创建任务的对象名 */ @@ -35,38 +30,8 @@ class GroupStartCmd extends AbsGroupCmd { } @Override public void executeCmd() { - String mod; - int maxTaskNum; - AriaManager manager = AriaManager.getInstance(AriaManager.APP); - if (isDownloadCmd) { - mod = manager.getDownloadConfig().getQueueMod(); - maxTaskNum = manager.getDownloadConfig().getMaxTaskNum(); - } else { - mod = manager.getUploadConfig().getQueueMod(); - maxTaskNum = manager.getUploadConfig().getMaxTaskNum(); - } - - AbsGroupTask task = (AbsGroupTask) mQueue.getTask(mTaskEntity.getEntity()); - if (task == null) { - task = (AbsGroupTask) mQueue.createTask(mTargetName, mTaskEntity); - if (!TextUtils.isEmpty(mTargetName)) { - task.setTargetName(mTargetName); - } - // 任务不存在时,根据配置不同,对任务执行操作 - if (mod.equals(QueueMod.NOW.getTag())) { - mQueue.startTask(task); - } else if (mod.equals(QueueMod.WAIT.getTag())) { - if (mQueue.getCurrentExePoolNum() < maxTaskNum) { - mQueue.startTask(task); - } - } - } else { - // 任务不存在时,根据配置不同,对任务执行操作 - if (!task.isRunning() - && mod.equals(QueueMod.WAIT.getTag()) - && task.getState() == IEntity.STATE_WAIT) { - mQueue.startTask(task); - } + if (checkTask()) { + tempTask.startSubTask(childUrl); } } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/group/GroupStopCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/group/GroupStopCmd.java index 85c400bd..66262e66 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/group/GroupStopCmd.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/group/GroupStopCmd.java @@ -15,13 +15,13 @@ */ package com.arialyy.aria.core.command.group; -import com.arialyy.aria.core.inf.AbsTaskEntity; +import com.arialyy.aria.core.inf.BaseGroupTaskEntity; /** * Created by AriaL on 2017/6/29. * 停止任务组的命令 */ -class GroupStopCmd extends AbsGroupCmd{ +class GroupStopCmd extends AbsGroupCmd { /** * @param targetName 创建任务的对象名 */ @@ -30,6 +30,8 @@ class GroupStopCmd extends AbsGroupCmd{ } @Override public void executeCmd() { - + if (checkTask()) { + tempTask.stopSubTask(childUrl); + } } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/normal/NormalCmdFactory.java b/Aria/src/main/java/com/arialyy/aria/core/command/normal/NormalCmdFactory.java index 85aa33fc..69c10cf9 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/normal/NormalCmdFactory.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/normal/NormalCmdFactory.java @@ -24,7 +24,7 @@ import com.arialyy.aria.core.inf.AbsTaskEntity; * Created by Lyy on 2016/9/23. * 命令工厂 */ -public class NormalCmdFactory extends AbsCmdFactory { +public class NormalCmdFactory extends AbsCmdFactory { /** * 创建任务 */ @@ -82,7 +82,7 @@ public class NormalCmdFactory extends AbsCmdFactory { * @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 AbsNormalCmd createCmd(String target, T entity, int type) { + public AbsNormalCmd createCmd(String target, AbsTaskEntity entity, int type) { switch (type) { case TASK_CREATE: return new AddCmd<>(target, entity); @@ -105,4 +105,5 @@ public class NormalCmdFactory extends AbsCmdFactory { return null; } } + } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/BaseGroupTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/BaseGroupTarget.java index dd9e74b3..3aba2a50 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/BaseGroupTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/BaseGroupTarget.java @@ -16,9 +16,10 @@ package com.arialyy.aria.core.download; import android.text.TextUtils; +import com.arialyy.aria.core.SubTaskManager; import com.arialyy.aria.core.inf.AbsDownloadTarget; import com.arialyy.aria.core.inf.AbsTarget; -import com.arialyy.aria.core.inf.AbsTaskEntity; +import com.arialyy.aria.core.inf.BaseGroupTaskEntity; import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.util.CommonUtil; import java.io.File; @@ -28,7 +29,7 @@ import java.util.List; /** * Created by Aria.Lao on 2017/7/26. */ -abstract class BaseGroupTarget +abstract class BaseGroupTarget extends AbsDownloadTarget { List mUrls = new ArrayList<>(); @@ -42,6 +43,8 @@ abstract class BaseGroupTarget subtask = new ArrayList<>(); - /** - * 子任务链接组 - */ - @NormalList(clazz = String.class) private List urls = new ArrayList<>(); - /** * 任务组下载文件的文件夹地址 * @@ -59,14 +54,6 @@ public class DownloadGroupEntity extends AbsGroupEntity { this.dirPath = dirPath; } - public List getUrls() { - return urls; - } - - public void setUrls(List urls) { - this.urls = urls; - } - void setGroupName(String key) { this.groupName = key; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTask.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTask.java index e8d59788..63dc0f5f 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTask.java @@ -19,6 +19,7 @@ import android.os.Handler; import android.os.Looper; import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.common.IUtil; +import com.arialyy.aria.core.download.downloader.AbsGroupUtil; import com.arialyy.aria.core.download.downloader.DownloadGroupUtil; import com.arialyy.aria.core.download.downloader.FtpDirDownloadUtil; import com.arialyy.aria.core.inf.AbsGroupTask; @@ -33,7 +34,6 @@ import com.arialyy.aria.util.CheckUtil; public class DownloadGroupTask extends AbsGroupTask { private final String TAG = "DownloadGroupTask"; private DownloadGroupListener mListener; - private IUtil mUtil; private DownloadGroupTask(DownloadGroupTaskEntity taskEntity, Handler outHandler) { mTaskEntity = taskEntity; diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTaskEntity.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTaskEntity.java index 4987a1d0..aabe80bb 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTaskEntity.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTaskEntity.java @@ -15,13 +15,13 @@ */ package com.arialyy.aria.core.download; -import com.arialyy.aria.core.inf.AbsTaskEntity; +import com.arialyy.aria.core.inf.BaseGroupTaskEntity; import com.arialyy.aria.orm.OneToOne; /** * Created by AriaL on 2017/7/1. */ -public class DownloadGroupTaskEntity extends AbsTaskEntity { +public class DownloadGroupTaskEntity extends BaseGroupTaskEntity { @OneToOne(table = DownloadGroupEntity.class, key = "groupName") public DownloadGroupEntity entity; diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java index 20f9fd79..a7b0f8c8 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java @@ -300,7 +300,7 @@ public class DownloadReceiver extends AbsReceiver { @Override public void removeAllTask(boolean removeFile) { final AriaManager ariaManager = AriaManager.getInstance(AriaManager.APP); CancelAllCmd cancelCmd = - (CancelAllCmd) CommonUtil.createCmd(targetName, new DownloadTaskEntity(), + (CancelAllCmd) CommonUtil.createNormalCmd(targetName, new DownloadTaskEntity(), NormalCmdFactory.TASK_CANCEL_ALL); cancelCmd.removeFile = removeFile; ariaManager.setCmd(cancelCmd).exe(); diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/AbsGroupUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/AbsGroupUtil.java index 47fab43c..19efe055 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/AbsGroupUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/AbsGroupUtil.java @@ -15,6 +15,7 @@ */ package com.arialyy.aria.core.download.downloader; +import android.util.Log; import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.common.IUtil; import com.arialyy.aria.core.download.DownloadEntity; @@ -38,7 +39,7 @@ import java.util.concurrent.Executors; * Created by AriaL on 2017/6/30. * 任务组核心逻辑 */ -abstract class AbsGroupUtil implements IUtil { +public abstract class AbsGroupUtil implements IUtil { private final String TAG = "AbsGroupUtil"; /** * 任务组所有任务总大小 @@ -126,6 +127,55 @@ abstract class AbsGroupUtil implements IUtil { mTaskEntity.getEntity().update(); } } + /** + * 启动子任务下载 + * + * @param url 子任务下载地址 + */ + public void startSubTask(String url) { + Downloader d = getDownloader(url); + if (d != null && !d.isRunning()) { + d.start(); + } + } + + /** + * 停止子任务下载 + * + * @param url 子任务下载地址 + */ + public void stopSubTask(String url) { + Downloader d = getDownloader(url); + if (d != null && d.isRunning()) { + d.stop(); + } + } + + /** + * 删除子任务 + * + * @param url 子任务下载地址 + */ + public void cancelSunTask(String url) { + Downloader d = getDownloader(url); + if (d != null) { + d.cancel(); + } + } + + /** + * 通过地址获取下载器 + * + * @param url 子任务下载地址 + */ + private Downloader getDownloader(String url) { + Downloader d = mDownloaderMap.get(url); + if (d == null) { + Log.e(TAG, "链接【" + url + "】对应的下载器不存在"); + return null; + } + return d; + } @Override public long getFileSize() { return mTotalSize; diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsDownloadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsDownloadTarget.java index 23c62afb..bebe3282 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsDownloadTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsDownloadTarget.java @@ -98,7 +98,7 @@ public abstract class AbsDownloadTarget urls = new ArrayList<>(); + + public List getUrls() { + return urls; + } + + public void setUrls(List urls) { + this.urls = urls; + } + public String getGroupName() { return groupName; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsGroupTask.java b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsGroupTask.java index 83bc8993..38612219 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsGroupTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsGroupTask.java @@ -15,17 +15,53 @@ */ package com.arialyy.aria.core.inf; +import com.arialyy.aria.core.download.downloader.AbsGroupUtil; /** * Created by AriaL on 2017/6/29. + * 任务组任务抽象类 */ public abstract class AbsGroupTask extends AbsTask { protected TASK_ENTITY mTaskEntity; + protected AbsGroupUtil mUtil; @Override public String getKey() { return mEntity.getGroupName(); } + + /** + * 启动任务组中的子任务 + * + * @param url 子任务下载地址 + */ + public void startSubTask(String url) { + if (mUtil != null) { + mUtil.startSubTask(url); + } + } + + /** + * 停止任务组中的子任务 + * + * @param url 子任务下载地址 + */ + public void stopSubTask(String url) { + if (mUtil != null) { + mUtil.stopSubTask(url); + } + } + + /** + * 删除子任务组中的子任务 + * + * @param url 子任务下载地址 + */ + public void cancelSubTask(String url) { + if (mUtil != null) { + mUtil.cancelSunTask(url); + } + } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java index 57d0879b..f0a24b9e 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java @@ -162,7 +162,7 @@ public abstract class AbsTarget extends AbsTaskEntity{ + @Override public ENTITY getEntity() { + return null; + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java index e1fe10d7..70cdee95 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java @@ -92,7 +92,7 @@ public class UploadReceiver extends AbsReceiver { @Override public void removeAllTask(boolean removeFile) { final AriaManager am = AriaManager.getInstance(AriaManager.APP); - am.setCmd(CommonUtil.createCmd(targetName, new DownloadTaskEntity(), + am.setCmd(CommonUtil.createNormalCmd(targetName, new DownloadTaskEntity(), NormalCmdFactory.TASK_CANCEL_ALL)).exe(); Set keys = am.getReceiver().keySet(); diff --git a/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java b/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java index fa0cc8b9..abf7bf66 100644 --- a/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java @@ -24,16 +24,16 @@ import android.text.TextUtils; import android.util.Base64; import android.util.Log; import com.arialyy.aria.core.AriaManager; -import com.arialyy.aria.core.command.normal.NormalCmdFactory; +import com.arialyy.aria.core.command.group.AbsGroupCmd; +import com.arialyy.aria.core.command.group.GroupCmdFactory; import com.arialyy.aria.core.command.normal.AbsNormalCmd; +import com.arialyy.aria.core.command.normal.NormalCmdFactory; import com.arialyy.aria.core.download.DownloadEntity; -import com.arialyy.aria.core.download.DownloadGroupEntity; -import com.arialyy.aria.core.download.DownloadGroupTaskEntity; import com.arialyy.aria.core.download.DownloadTaskEntity; import com.arialyy.aria.core.inf.AbsTaskEntity; +import com.arialyy.aria.core.inf.BaseGroupTaskEntity; import com.arialyy.aria.core.upload.UploadEntity; import com.arialyy.aria.core.upload.UploadTaskEntity; -import com.arialyy.aria.orm.DbEntity; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; @@ -43,6 +43,11 @@ import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.Field; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; import java.math.BigDecimal; import java.math.BigInteger; import java.net.URLEncoder; @@ -58,11 +63,6 @@ import java.util.Properties; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.lang.reflect.GenericArrayType; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.lang.reflect.WildcardType; /** * Created by lyy on 2016/1/22. @@ -398,10 +398,24 @@ public class CommonUtil { } } - public static AbsNormalCmd createCmd(String target, T entity, int cmd) { + /** + * 创建任务命令 + */ + public static AbsNormalCmd createNormalCmd(String target, T entity, + int cmd) { return NormalCmdFactory.getInstance().createCmd(target, entity, cmd); } + /** + * 创建任务组命令 + * + * @param childUrl 子任务url + */ + public static AbsGroupCmd createGroupCmd(String target, T entity, + int cmd, String childUrl) { + return GroupCmdFactory.getInstance().createCmd(target, entity, cmd, childUrl); + } + /** * 创建隐性的Intent */ diff --git a/AriaAnnotations/src/main/java/com/arialyy/annotations/DownloadGroup.java b/AriaAnnotations/src/main/java/com/arialyy/annotations/DownloadGroup.java index c0777d82..67ef1f6a 100644 --- a/AriaAnnotations/src/main/java/com/arialyy/annotations/DownloadGroup.java +++ b/AriaAnnotations/src/main/java/com/arialyy/annotations/DownloadGroup.java @@ -25,75 +25,134 @@ import java.lang.annotation.Target; * Aria下载事件被注解的方法中,参数仅能有一个,参数类型为{@link com.arialyy.aria.core.download.DownloadGroupTask} *
  *   
- *      {@literal @}Download.onPre(groupName)
+ *      {@literal @}DownloadGroup.onPre(groupName)
  *       protected void onPre(DownloadGroupTask task) {
  *       }
  *   
  * 
* {@literal @}Download.onPre("myGroupName"),如果你的注解中增加了url描述, * 则表示,所有下载任务中,只有下载地址为"myGroupName"的任务才能回调该注解的方法。 + * + * + * 如果希望获取子任务的状态,可以使用onSub..类的注解 + *
+ *   
+ *      {@literal @}DownloadGroup.onSubPre(groupName)
+ *        protected void onPre(DownloadGroupTask task, String url) {
+ *      }
+ *   
+ * 
*/ @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) public @interface DownloadGroup { /** - * 如果你在方法中添加{@code @Download.onPre}注解,在预处理完成时,Aria会调用该方法 + * 如果你在方法中添加{@code @DownloadGroup.onPre}注解,在预处理完成时,Aria会调用该方法 */ @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onPre { String[] value() default { AriaConstance.NO_URL }; } /** - * 如果你在方法中添加{@code @Download.onTaskPre}注解,在任务预处理完成时,Aria会调用该方法 + * 如果你在方法中添加{@code @DownloadGroup.onTaskPre}注解,在任务预处理完成时,Aria会调用该方法 */ @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onTaskPre { String[] value() default { AriaConstance.NO_URL }; } /** - * 如果你在方法中添加{@code @Download.onTaskResume}注解,在任务恢复下载时,Aria会调用该方法 + * 如果你在方法中添加{@code @DownloadGroup.onTaskResume}注解,在任务恢复下载时,Aria会调用该方法 */ @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onTaskResume { String[] value() default { AriaConstance.NO_URL }; } /** - * 如果你在方法中添加{@code @Download.onTaskStart}注解,在任务开始下载时,Aria会调用该方法 + * 如果你在方法中添加{@code @DownloadGroup.onTaskStart}注解,在任务开始下载时,Aria会调用该方法 */ @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onTaskStart { String[] value() default { AriaConstance.NO_URL }; } /** - * 如果你在方法中添加{@code @Download.onTaskStop}注解,在任务停止时,Aria会调用该方法 + * 如果你在方法中添加{@code @DownloadGroup.onTaskStop}注解,在任务停止时,Aria会调用该方法 */ @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onTaskStop { String[] value() default { AriaConstance.NO_URL }; } /** - * 如果你在方法中添加{@code @Download.onTaskCancel}l注解,在任务取消时,Aria会调用该方法 + * 如果你在方法中添加{@code @DownloadGroup.onTaskCancel}l注解,在任务取消时,Aria会调用该方法 */ @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onTaskCancel { String[] value() default { AriaConstance.NO_URL }; } /** - * 如果你在方法中添加{@code @Download.onTaskFail)注解,在任务预失败时,Aria会调用该方法 + * 如果你在方法中添加{@code @DownloadGroup.onTaskFail)注解,在任务预失败时,Aria会调用该方法 */ @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onTaskFail { String[] value() default { AriaConstance.NO_URL }; } /** - * 如果你在方法中添加{@code @Download.onTaskComplete}注解,在任务完成时,Aria会调用该方法 + * 如果你在方法中添加{@code @DownloadGroup.onTaskComplete}注解,在任务完成时,Aria会调用该方法 */ @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onTaskComplete { String[] value() default { AriaConstance.NO_URL }; } /** - * 如果你在方法中添加{@code @Download.onTaskRunning}注解,在任务正在下载,Aria会调用该方法 + * 如果你在方法中添加{@code @DownloadGroup.onTaskRunning}注解,在任务正在下载,Aria会调用该方法 */ @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onTaskRunning { String[] value() default { AriaConstance.NO_URL }; } + + /** + * 任务组子任务预处理的注解 + */ + @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onSubTaskPre { + String value() default AriaConstance.NO_URL; + } + + /** + * 任务组子任务开始的注解 + */ + @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onSubTaskStart { + String value() default AriaConstance.NO_URL; + } + + /** + * 任务组子任务停止的注解 + */ + @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onSubTaskStop { + String value() default AriaConstance.NO_URL; + } + + /** + * 任务组子任务删除的注解 + */ + @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onSubTaskCancel { + String value() default AriaConstance.NO_URL; + } + + /** + * 任务组子任务失败的注解 + */ + @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onSubTaskFail { + String value() default AriaConstance.NO_URL; + } + + /** + * 任务组子任务完成的注解 + */ + @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onSubTaskComplete { + String value() default AriaConstance.NO_URL; + } + + /** + * 任务组子任务正在执行的注解 + */ + @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onSubTaskRunning { + String value() default AriaConstance.NO_URL; + } } diff --git a/app/src/main/java/com/arialyy/simple/download/group/ChildHandleDialog.java b/app/src/main/java/com/arialyy/simple/download/group/ChildHandleDialog.java new file mode 100644 index 00000000..34369f31 --- /dev/null +++ b/app/src/main/java/com/arialyy/simple/download/group/ChildHandleDialog.java @@ -0,0 +1,123 @@ +/* + * 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.simple.download.group; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.os.Bundle; +import android.util.Log; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.TextView; +import butterknife.Bind; +import butterknife.OnClick; +import com.arialyy.annotations.DownloadGroup; +import com.arialyy.aria.core.Aria; +import com.arialyy.aria.core.download.DownloadEntity; +import com.arialyy.aria.core.download.DownloadGroupTask; +import com.arialyy.simple.R; +import com.arialyy.simple.base.BaseDialog; +import com.arialyy.simple.databinding.DialogSubTaskHandlerBinding; +import com.arialyy.simple.widget.HorizontalProgressBarWithNumber; +import java.util.List; + +/** + * Created by Aria.Lao on 2017/9/5. + */ +@SuppressLint("ValidFragment") public class ChildHandleDialog + extends BaseDialog { + @Bind(R.id.sub_task) TextView mSub; + @Bind(R.id.task_group) TextView mGroup; + @Bind(R.id.pb) HorizontalProgressBarWithNumber mPb; + private String mGroupName; + private String mChildName; + private DownloadEntity mChildEntity; + + public ChildHandleDialog(Context context, String groupAliaName, DownloadEntity childEntity) { + super(context); + setStyle(STYLE_NO_TITLE, R.style.Theme_Light_Dialog); + mChildEntity = childEntity; + mGroupName = groupAliaName; + mChildName = childEntity.getFileName(); + } + + @Override protected void init(Bundle savedInstanceState) { + super.init(savedInstanceState); + Aria.download(this).register(); + initWidget(); + } + + @Override public void onDestroy() { + super.onDestroy(); + Aria.download(this).unRegister(); + } + + private void initWidget() { + mGroup.setText("任务组:" + mGroupName); + mSub.setText("子任务:" + mChildName); + mPb.setProgress((int) (mChildEntity.getCurrentProgress() * 100 / mChildEntity.getFileSize())); + + Window window = getDialog().getWindow(); + window.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM); + WindowManager.LayoutParams p = window.getAttributes(); + p.width = ViewGroup.LayoutParams.MATCH_PARENT; + window.setAttributes(p); + window.setWindowAnimations(R.style.dialogStyle); + } + + @DownloadGroup.onTaskResume void onTaskResume(DownloadGroupTask task) { + mSub.setText("子任务:" + mChildName + ",状态:下载中"); + } + + @DownloadGroup.onTaskCancel void onTaskCancel(DownloadGroupTask task) { + mSub.setText("子任务:" + mChildName + ",状态:取消下载"); + } + + @DownloadGroup.onTaskRunning void onTaskRunning(DownloadGroupTask task) { + mPb.setProgress((int) (mChildEntity.getCurrentProgress() * 100 / mChildEntity.getFileSize())); + } + + @DownloadGroup.onTaskStop void onTaskStop(DownloadGroupTask task) { + mSub.setText("子任务:" + mChildName + ",状态:任务停止"); + } + + @DownloadGroup.onTaskComplete void onTaskComplete(DownloadGroupTask task) { + mSub.setText("子任务:" + mChildName + ",状态:任务完成"); + mPb.setProgress(100); + } + + @Override protected int setLayoutId() { + return R.layout.dialog_sub_task_handler; + } + + @OnClick({ R.id.start, R.id.stop, R.id.cancel }) void onClick(View view) { + switch (view.getId()) { + case R.id.start: + break; + case R.id.stop: + break; + case R.id.cancel: + break; + } + } + + @Override protected void dataCallback(int result, Object obj) { + + } +} diff --git a/app/src/main/java/com/arialyy/simple/download/group/DownloadGroupActivity.java b/app/src/main/java/com/arialyy/simple/download/group/DownloadGroupActivity.java index 0b36fb72..7d97644c 100644 --- a/app/src/main/java/com/arialyy/simple/download/group/DownloadGroupActivity.java +++ b/app/src/main/java/com/arialyy/simple/download/group/DownloadGroupActivity.java @@ -17,17 +17,15 @@ package com.arialyy.simple.download.group; import android.os.Bundle; import android.os.Environment; -import android.os.Handler; -import android.util.Log; +import android.view.Gravity; import android.view.View; -import android.widget.Button; import butterknife.Bind; import com.arialyy.annotations.DownloadGroup; import com.arialyy.aria.core.Aria; -import com.arialyy.aria.core.common.RequestEnum; import com.arialyy.aria.core.download.DownloadGroupEntity; import com.arialyy.aria.core.download.DownloadGroupTask; import com.arialyy.aria.core.download.DownloadGroupTaskEntity; +import com.arialyy.frame.util.AndroidUtils; import com.arialyy.frame.util.show.L; import com.arialyy.frame.util.show.T; import com.arialyy.simple.R; @@ -62,6 +60,18 @@ public class DownloadGroupActivity extends BaseActivity " + task.getPercent()); getBinding().setProgress(task.getPercent()); getBinding().setSpeed(task.getConvertSpeed()); mChildList.updateChildProgress(task.getEntity().getSubTask()); diff --git a/app/src/main/java/com/arialyy/simple/widget/SubStateLinearLayout.java b/app/src/main/java/com/arialyy/simple/widget/SubStateLinearLayout.java index 6c6b4660..337b873b 100644 --- a/app/src/main/java/com/arialyy/simple/widget/SubStateLinearLayout.java +++ b/app/src/main/java/com/arialyy/simple/widget/SubStateLinearLayout.java @@ -1,8 +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.simple.widget; import android.content.Context; import android.support.annotation.Nullable; import android.util.AttributeSet; +import android.util.SparseArray; import android.view.LayoutInflater; import android.view.View; import android.widget.LinearLayout; @@ -17,16 +33,22 @@ import java.util.WeakHashMap; /** * Created by Aria.Lao on 2017/7/17. */ -public class SubStateLinearLayout extends LinearLayout { +public class SubStateLinearLayout extends LinearLayout implements View.OnClickListener { interface OnShowCallback { void onShow(boolean visibility); } - OnShowCallback callback; + public interface OnItemClickListener { + void onItemClick(int position, View view); + } + + OnShowCallback mShowCallback; + OnItemClickListener mItemClickListener; List mSubData = new LinkedList<>(); Map mPosition = new WeakHashMap<>(); + SparseArray mViews = new SparseArray<>(); public SubStateLinearLayout(Context context) { super(context); @@ -50,15 +72,25 @@ public class SubStateLinearLayout extends LinearLayout { createShowView(); int i = 1; for (DownloadEntity entity : datas) { - TextView view = createView(entity); + TextView view = createView(i - 1, entity); mPosition.put(entity.getDownloadPath(), i); addView(view, i); i++; } } + @Override public void onClick(View v) { + if (mItemClickListener != null) { + mItemClickListener.onItemClick(mViews.indexOfValue(v), v); + } + } + public void setOnShowCallback(OnShowCallback callback) { - this.callback = callback; + this.mShowCallback = callback; + } + + public void setOnItemClickListener(OnItemClickListener listener) { + this.mItemClickListener = listener; } public List getSubData() { @@ -79,10 +111,12 @@ public class SubStateLinearLayout extends LinearLayout { } } - private TextView createView(DownloadEntity entity) { + private TextView createView(int position, DownloadEntity entity) { TextView view = (TextView) LayoutInflater.from(getContext()).inflate(R.layout.layout_child_state, null); view.setText(entity.getFileName() + ": " + getPercent(entity) + "%"); + view.setOnClickListener(this); + mViews.append(position, view); return view; } diff --git a/app/src/main/res/anim/dialog_enter.xml b/app/src/main/res/anim/dialog_enter.xml new file mode 100644 index 00000000..1437665d --- /dev/null +++ b/app/src/main/res/anim/dialog_enter.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/dialog_exit.xml b/app/src/main/res/anim/dialog_exit.xml new file mode 100644 index 00000000..dd5f9db7 --- /dev/null +++ b/app/src/main/res/anim/dialog_exit.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_download_group.xml b/app/src/main/res/layout/activity_download_group.xml index 98d73bdc..f3582f0e 100644 --- a/app/src/main/res/layout/activity_download_group.xml +++ b/app/src/main/res/layout/activity_download_group.xml @@ -17,7 +17,7 @@ /> - - + diff --git a/app/src/main/res/layout/dialog_sub_task_handler.xml b/app/src/main/res/layout/dialog_sub_task_handler.xml new file mode 100644 index 00000000..44f01a62 --- /dev/null +++ b/app/src/main/res/layout/dialog_sub_task_handler.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + +