diff --git a/Aria/src/main/java/com/arialyy/aria/core/Aria.java b/Aria/src/main/java/com/arialyy/aria/core/Aria.java index 538f8504..011086ad 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/Aria.java +++ b/Aria/src/main/java/com/arialyy/aria/core/Aria.java @@ -114,110 +114,4 @@ import com.arialyy.aria.core.upload.UploadTask; throw new IllegalArgumentException("不支持的类型"); } } - - /** - * 上传任务状态监听 - * - * @see Upload - * @deprecated 请使用注解函数的方式来实现事件的获取 - */ - @Deprecated public static class UploadSchedulerListener - implements ISchedulerListener { - - /** - * 预处理,有时有些地址链接比较慢,这时可以先在这个地方出来一些界面上的UI,如按钮的状态。 - * - * @param task 上传文物实体 - */ - @Override public void onPre(UploadTask task) { - - } - - @Override public void onTaskPre(UploadTask task) { - - } - - @Override public void onTaskResume(UploadTask task) { - - } - - @Override public void onTaskStart(UploadTask task) { - - } - - @Override public void onTaskStop(UploadTask task) { - - } - - @Override public void onTaskCancel(UploadTask task) { - - } - - @Override public void onTaskFail(UploadTask task) { - - } - - @Override public void onTaskComplete(UploadTask task) { - - } - - @Override public void onTaskRunning(UploadTask task) { - - } - } - - /** - * 下载任务状态监听 - * - * @see Download - * @deprecated 请使用注解函数的方式来实现事件的获取 - */ - @Deprecated public static class DownloadSchedulerListener - implements IDownloadSchedulerListener { - /** - * 预处理,有时有些地址链接比较慢,这时可以先在这个地方出来一些界面上的UI,如按钮的状态。 - * 需要注意的是,在该回调中,是得不到文件长度的,如果需要获取文件长度,需要在onTaskPre中获取 - * - * @param task 下载任务 - */ - @Override public void onPre(DownloadTask task) { - - } - - @Override public void onTaskPre(DownloadTask task) { - - } - - @Override public void onTaskResume(DownloadTask task) { - - } - - @Override public void onTaskStart(DownloadTask task) { - - } - - @Override public void onTaskStop(DownloadTask task) { - - } - - @Override public void onTaskCancel(DownloadTask task) { - - } - - @Override public void onTaskFail(DownloadTask task) { - - } - - @Override public void onTaskComplete(DownloadTask task) { - - } - - @Override public void onTaskRunning(DownloadTask task) { - - } - - @Override public void onNoSupportBreakPoint(DownloadTask task) { - - } - } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java b/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java index eaa834c8..2e8df2fa 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java +++ b/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java @@ -398,7 +398,6 @@ import org.xml.sax.SAXException; if (key.contains(clsName)) { IReceiver receiver = mReceivers.get(key); if (receiver != null) { - receiver.removeSchedulerListener(); receiver.unRegister(); receiver.destroy(); } 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..e73abdbd 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,26 @@ */ package com.arialyy.aria.core.command.group; +import android.util.Log; import com.arialyy.aria.core.command.AbsCmd; import com.arialyy.aria.core.download.DownloadGroupTaskEntity; -import com.arialyy.aria.core.download.DownloadTaskEntity; -import com.arialyy.aria.core.inf.AbsTaskEntity; +import com.arialyy.aria.core.inf.AbsGroupTask; +import com.arialyy.aria.core.inf.AbsTask; +import com.arialyy.aria.core.inf.BaseGroupTaskEntity; import com.arialyy.aria.core.queue.DownloadGroupTaskQueue; -import com.arialyy.aria.core.queue.DownloadTaskQueue; -import com.arialyy.aria.core.queue.UploadTaskQueue; -import com.arialyy.aria.core.upload.UploadTaskEntity; import com.arialyy.aria.util.CommonUtil; /** * Created by AriaL on 2017/6/29. * 任务组命令 */ -abstract class AbsGroupCmd extends AbsCmd { +public abstract class AbsGroupCmd extends AbsCmd { + /** + * 需要控制的子任务url + */ + String childUrl; + + AbsGroupTask tempTask; /** * @param targetName 创建任务的对象名 @@ -43,4 +48,26 @@ abstract class AbsGroupCmd extends AbsCmd { isDownloadCmd = true; } } + + /** + * 创建任务 + * + * @return 创建的任务 + */ + AbsTask createTask() { + tempTask = (AbsGroupTask) mQueue.createTask(mTargetName, mTaskEntity); + return tempTask; + } + + boolean checkTask() { + tempTask = (AbsGroupTask) mQueue.getTask(mTaskEntity.getEntity()); + if (tempTask == null) { + createTask(); + if (tempTask.isComplete()) { + Log.w(TAG, "任务已完成"); + return false; + } + } + return true; + } } 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/CancelAllCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/normal/CancelAllCmd.java index ddc81b6b..cd31f719 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/normal/CancelAllCmd.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/normal/CancelAllCmd.java @@ -47,7 +47,6 @@ public class CancelAllCmd extends AbsNormalCmd { if (mTaskEntity instanceof DownloadTaskEntity || mTaskEntity instanceof DownloadGroupTaskEntity) { handleDownloadRemove(); - handleDownloadRemove(); handleDownloadGroupRemove(); } else if (mTaskEntity instanceof UploadTaskEntity) { handleUploadRemove(); 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/common/AbsFileer.java b/Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java index 74f7eb8c..4dee42c4 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java @@ -67,6 +67,10 @@ public abstract class AbsFileer downloadCounter, uploadCounter, downloadGroupCounter; + public Set downloadCounter, uploadCounter, downloadGroupCounter, downloadGroupSubCounter; public static volatile ProxyHelper INSTANCE = null; @@ -49,6 +49,7 @@ public class ProxyHelper { Class clazz = Class.forName("com.arialyy.aria.ProxyClassCounter"); Method download = clazz.getMethod("getDownloadCounter"); Method downloadGroup = clazz.getMethod("getDownloadGroupCounter"); + Method downloadGroupSub = clazz.getMethod("getDownloadGroupSubCounter"); Method upload = clazz.getMethod("getUploadCounter"); Object object = clazz.newInstance(); Object dc = download.invoke(object); @@ -59,6 +60,10 @@ public class ProxyHelper { if (dgc != null) { downloadGroupCounter = unmodifiableSet((Set) dgc); } + Object dgsc = downloadGroupSub.invoke(object); + if (dgsc != null){ + downloadGroupSubCounter = unmodifiableSet((Set) dgsc); + } Object uc = upload.invoke(object); if (uc != null) { uploadCounter = unmodifiableSet((Set) uc); diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java b/Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java index dd0ba87d..9422e90c 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java @@ -30,7 +30,7 @@ import java.lang.ref.WeakReference; */ class BaseDListener> implements IDownloadListener { - private WeakReference outHandler; + protected WeakReference outHandler; private long mLastLen = 0; //上一次发送长度 private boolean isFirst = true; protected ENTITY mEntity; @@ -117,6 +117,7 @@ class BaseDListener> } else { mEntity.setSpeed(speed < 0 ? 0 : speed); } + mEntity.setPercent((int) (mEntity.getCurrentProgress() * 100 / mEntity.getFileSize())); } /** 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/DownloadGroupListener.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupListener.java index 650772b6..e127bec8 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupListener.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupListener.java @@ -17,6 +17,8 @@ package com.arialyy.aria.core.download; import android.os.Handler; import com.arialyy.aria.core.download.downloader.IDownloadGroupListener; +import com.arialyy.aria.core.inf.GroupSendParams; +import com.arialyy.aria.core.scheduler.ISchedulers; /** * Created by Aria.Lao on 2017/7/20. @@ -25,9 +27,16 @@ import com.arialyy.aria.core.download.downloader.IDownloadGroupListener; class DownloadGroupListener extends BaseDListener implements IDownloadGroupListener { private final String TAG = "DownloadGroupListener"; + private GroupSendParams mSeedEntity; DownloadGroupListener(DownloadGroupTask task, Handler outHandler) { super(task, outHandler); + mSeedEntity = new GroupSendParams<>(); + mSeedEntity.groupTask = task; + } + + @Override public void onSubPre(DownloadEntity subEntity) { + sendInState2Target(ISchedulers.SUB_PRE, subEntity); } @Override public void supportBreakpoint(boolean support, DownloadEntity subEntity) { @@ -35,23 +44,43 @@ class DownloadGroupListener extends BaseDListener { 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..aeb323c3 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 @@ -139,10 +139,12 @@ public class DownloadReceiver extends AbsReceiver { String className = obj.getClass().getName(); Set dCounter = ProxyHelper.getInstance().downloadCounter; Set dgCounter = ProxyHelper.getInstance().downloadGroupCounter; + Set dgsCounter = ProxyHelper.getInstance().downloadGroupSubCounter; if (dCounter != null && dCounter.contains(className)) { DownloadSchedulers.getInstance().register(obj); } - if (dgCounter != null && dgCounter.contains(className)) { + if ((dgCounter != null && dgCounter.contains(className)) || (dgsCounter != null + && dgsCounter.contains(className))) { DownloadGroupSchedulers.getInstance().register(obj); } return this; @@ -155,10 +157,12 @@ public class DownloadReceiver extends AbsReceiver { String className = obj.getClass().getName(); Set dCounter = ProxyHelper.getInstance().downloadCounter; Set dgCounter = ProxyHelper.getInstance().downloadGroupCounter; + Set dgsCounter = ProxyHelper.getInstance().downloadGroupSubCounter; if (dCounter != null && dCounter.contains(className)) { DownloadSchedulers.getInstance().unRegister(obj); } - if (dgCounter != null && dgCounter.contains(className)) { + if (dgCounter != null && dgCounter.contains(className) || (dgsCounter != null + && dgsCounter.contains(className))) { DownloadGroupSchedulers.getInstance().unRegister(obj); } if (needRmReceiver) { @@ -166,29 +170,6 @@ public class DownloadReceiver extends AbsReceiver { } } - /** - * 添加调度器回调 - * - * @see #register() - */ - @Deprecated public DownloadReceiver addSchedulerListener( - ISchedulerListener listener) { - this.listener = listener; - DownloadSchedulers.getInstance().addSchedulerListener(targetName, listener); - return this; - } - - /** - * 移除回调 - * - * @see #unRegister() - */ - @Deprecated @Override public void removeSchedulerListener() { - if (listener != null) { - DownloadSchedulers.getInstance().removeSchedulerListener(targetName, listener); - } - } - @Override public void destroy() { targetName = null; listener = null; @@ -300,7 +281,7 @@ public class DownloadReceiver extends AbsReceiver { @Override public void removeAllTask(boolean removeFile) { final AriaManager ariaManager = AriaManager.getInstance(AriaManager.APP); CancelAllCmd cancelCmd = - (CancelAllCmd) CommonUtil.createCmd(targetName, new DownloadTaskEntity(), + (CancelAllCmd) CommonUtil.createNormalCmd(targetName, new DownloadTaskEntity(), NormalCmdFactory.TASK_CANCEL_ALL); cancelCmd.removeFile = removeFile; ariaManager.setCmd(cancelCmd).exe(); 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..3a4678d0 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"; /** * 任务组所有任务总大小 @@ -48,7 +49,7 @@ abstract class AbsGroupUtil implements IUtil { private ExecutorService mExePool; protected IDownloadGroupListener mListener; protected DownloadGroupTaskEntity mTaskEntity; - private boolean isRunning = true; + private boolean isRunning = false; private Timer mTimer; /** * 初始化完成的任务书数 @@ -81,6 +82,8 @@ abstract class AbsGroupUtil implements IUtil { private int mCompleteNum = 0; //失败的任务数 private int mFailNum = 0; + //停止的任务数 + private int mStopNum = 0; //实际的下载任务数 int mActualTaskNum = 0; /** @@ -97,6 +100,7 @@ abstract class AbsGroupUtil implements IUtil { if (tasks != null && !tasks.isEmpty()) { for (DownloadTaskEntity te : tasks) { te.removeFile = mTaskEntity.removeFile; + if (te.getEntity() == null) continue; mTasksMap.put(te.getEntity().getUrl(), te); } } @@ -107,6 +111,7 @@ abstract class AbsGroupUtil implements IUtil { if (entity.getState() == IEntity.STATE_COMPLETE && file.exists()) { mCompleteNum++; mInitNum++; + mStopNum++; mCurrentLocation += entity.getFileSize(); } else { mExeMap.put(entity.getUrl(), createChildDownloadTask(entity)); @@ -127,6 +132,84 @@ abstract class AbsGroupUtil implements IUtil { } } + /** + * 启动子任务下载 + * + * @param url 子任务下载地址 + */ + public void startSubTask(String url) { + if (!checkSubTask(url, "开始")) return; + if (!isRunning) { + isRunning = true; + startTimer(); + } + Downloader d = getDownloader(url, false); + if (d != null && !d.isRunning()) { + d.setNewTask(false); + d.start(); + } + } + + /** + * 停止子任务下载 + * + * @param url 子任务下载地址 + */ + public void stopSubTask(String url) { + if (!checkSubTask(url, "停止")) return; + Downloader d = getDownloader(url, false); + if (d != null && d.isRunning()) { + d.stop(); + } + } + + /** + * 删除子任务 + * + * @param url 子任务下载地址 + */ + public void cancelSunTask(String url) { + Downloader d = getDownloader(url, false); + if (d != null) { + d.cancel(); + } + } + + /** + * 检查子任务 + * + * @param url 子任务url + * @param type 任务类型 + * @return {@code true} 任务可以下载 + */ + private boolean checkSubTask(String url, String type) { + DownloadTaskEntity entity = mTasksMap.get(url); + if (entity != null) { + if (entity.getState() == IEntity.STATE_COMPLETE) { + Log.w(TAG, "任务【" + url + "】已完成," + type + "失败"); + return false; + } + } else { + Log.w(TAG, "任务组中没有该任务【" + url + "】," + type + "失败"); + return false; + } + return true; + } + + /** + * 通过地址获取下载器 + * + * @param url 子任务下载地址 + * @param start 是否启动任务 + */ + private Downloader getDownloader(String url, boolean start) { + Downloader d = mDownloaderMap.get(url); + if (d == null) { + return createChildDownload(mTasksMap.get(url), start); + } + return d; + } + @Override public long getFileSize() { return mTotalSize; } @@ -232,6 +315,7 @@ abstract class AbsGroupUtil implements IUtil { if (mTimer != null) { mTimer.purge(); mTimer.cancel(); + mTimer = null; } } @@ -242,6 +326,10 @@ abstract class AbsGroupUtil implements IUtil { closeTimer(true); mListener.onPostPre(mTotalSize); mListener.onStart(mCurrentLocation); + startTimer(); + } + + private void startTimer() { mTimer = new Timer(true); mTimer.schedule(new TimerTask() { @Override public void run() { @@ -255,14 +343,26 @@ abstract class AbsGroupUtil implements IUtil { } /** - * 启动子任务下载器 + * 创建子任务下载器,默认创建完成自动启动 */ - void startChildDownload(DownloadTaskEntity taskEntity) { + Downloader createChildDownload(DownloadTaskEntity taskEntity) { + return createChildDownload(taskEntity, true); + } + + /** + * 创建子任务下载器,启动子任务下载器 + * + * @param start 是否启动下载 + */ + Downloader createChildDownload(DownloadTaskEntity taskEntity, boolean start) { ChildDownloadListener listener = new ChildDownloadListener(taskEntity); Downloader dt = new Downloader(listener, taskEntity); mDownloaderMap.put(taskEntity.getEntity().getUrl(), dt); - if (mExePool.isShutdown()) return; - mExePool.execute(dt); + if (mExePool.isShutdown()) return dt; + if (start) { + mExePool.execute(dt); + } + return dt; } /** @@ -276,6 +376,7 @@ abstract class AbsGroupUtil implements IUtil { taskEntity.userName = mTaskEntity.userName; taskEntity.userPw = mTaskEntity.userPw; taskEntity.account = mTaskEntity.account; + mTasksMap.put(entity.getUrl(), taskEntity); return taskEntity; } taskEntity = new DownloadTaskEntity(); @@ -293,6 +394,7 @@ abstract class AbsGroupUtil implements IUtil { taskEntity.account = mTaskEntity.account; taskEntity.key = entity.getDownloadPath(); taskEntity.save(); + mTasksMap.put(entity.getUrl(), taskEntity); return taskEntity; } @@ -321,30 +423,39 @@ abstract class AbsGroupUtil implements IUtil { entity.setFileSize(fileSize); entity.setConvertFileSize(CommonUtil.formatFileSize(fileSize)); saveData(IEntity.STATE_POST_PRE, -1); + mListener.onSubPre(entity); } @Override public void onResume(long resumeLocation) { saveData(IEntity.STATE_POST_PRE, IEntity.STATE_RUNNING); lastLen = resumeLocation; + mListener.onSubStart(entity); } @Override public void onStart(long startLocation) { saveData(IEntity.STATE_POST_PRE, IEntity.STATE_RUNNING); lastLen = startLocation; + mListener.onSubStart(entity); } @Override public void onProgress(long currentLocation) { long speed = currentLocation - lastLen; mCurrentLocation += speed; - lastLen = currentLocation; entity.setCurrentProgress(currentLocation); handleSpeed(speed); + mListener.onSubRunning(entity); + lastLen = currentLocation; } @Override public void onStop(long stopLocation) { saveData(IEntity.STATE_STOP, stopLocation); handleSpeed(0); mListener.onSubStop(entity); + mStopNum++; + if (mStopNum + mCompleteNum >= mInitNum) { + closeTimer(false); + mListener.onStop(mCurrentLocation); + } } @Override public void onCancel() { @@ -407,6 +518,7 @@ abstract class AbsGroupUtil implements IUtil { private void handleSpeed(long speed) { entity.setSpeed(speed); entity.setConvertSpeed(speed <= 0 ? "" : CommonUtil.formatFileSize(speed) + "/s"); + entity.setPercent((int) (entity.getCurrentProgress() * 100 / entity.getFileSize())); } private void saveData(int state, long location) { diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/DownloadGroupUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/DownloadGroupUtil.java index b49a3189..6191e9e5 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/DownloadGroupUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/DownloadGroupUtil.java @@ -65,7 +65,7 @@ public class DownloadGroupUtil extends AbsGroupUtil implements IUtil { if (taskEntity != null) { if (taskEntity.getState() != IEntity.STATE_FAIL && taskEntity.getState() != IEntity.STATE_WAIT) { - startChildDownload(taskEntity); + createChildDownload(taskEntity); i++; } else { mInfoPool.execute(createFileInfoThread(taskEntity)); @@ -94,7 +94,7 @@ public class DownloadGroupUtil extends AbsGroupUtil implements IUtil { if (isNeedLoadFileSize) { mTotalSize += te.getEntity().getFileSize(); } - startChildDownload(te); + createChildDownload(te); } mInitNum++; if (mInitNum + mInitFailNum >= mTaskEntity.getEntity().getSubTask().size() diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpClientHelp.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpClientHelp.java deleted file mode 100644 index 338d114b..00000000 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpClientHelp.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.arialyy.aria.core.download.downloader; - -import android.text.TextUtils; -import android.util.Log; -import com.arialyy.aria.core.AriaManager; -import java.io.IOException; -import org.apache.commons.net.ftp.FTPClient; -import org.apache.commons.net.ftp.FTPReply; - -/** - * Created by Aria.Lao on 2017/7/26. - */ -public class FtpClientHelp { - private final String TAG = "FtpClientHelp"; - private static volatile FtpClientHelp INSTANCE = null; - - private FTPClient client; - private String serverIp, user, pw, account; - private int port; - - private FtpClientHelp() { - } - - public static FtpClientHelp getInstnce() { - if (INSTANCE == null) { - synchronized (AriaManager.LOCK) { - INSTANCE = new FtpClientHelp(); - } - } - return INSTANCE; - } - - public FTPClient getClient() { - if (client == null || !client.isConnected()) { - createClient(); - } - return client; - } - - /** - * 登录到FTP服务器,当客户端为null或客户端没有连接到FTP服务器时才会执行登录操作 - */ - public FTPClient login(String serverIp, int port, String user, String pw, String account) { - this.serverIp = serverIp; - this.port = port; - this.user = user; - this.pw = pw; - this.account = account; - if (client == null || !client.isConnected()) { - createClient(); - } - return client; - } - - /** - * 登出 - */ - public void logout() { - try { - if (client != null && client.isConnected()) { - client.logout(); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - FTPClient createClient() { - new Thread(new Runnable() { - @Override public void run() { - client = new FTPClient(); - try { - client.connect(serverIp, port); - if (!TextUtils.isEmpty(account)) { - client.login(user, pw); - } else { - client.login(user, pw, account); - } - int reply = client.getReplyCode(); - if (!FTPReply.isPositiveCompletion(reply)) { - client.disconnect(); - Log.e(TAG, "无法连接到ftp服务器,错误码为:" + reply); - } - } catch (IOException e) { - Log.d(TAG, e.getMessage()); - } finally { - synchronized (FtpClientHelp.this) { - FtpClientHelp.this.notify(); - } - } - } - }).start(); - synchronized (FtpClientHelp.this) { - try { - wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - return client; - } -} diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpDirDownloadUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpDirDownloadUtil.java index 0e5b2a15..a2c46894 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpDirDownloadUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpDirDownloadUtil.java @@ -60,7 +60,7 @@ public class FtpDirDownloadUtil extends AbsGroupUtil { for (String key : keys) { DownloadTaskEntity taskEntity = mExeMap.get(key); if (taskEntity != null) { - startChildDownload(taskEntity); + createChildDownload(taskEntity); i++; } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java index bcbcd13f..5b3597c3 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java @@ -24,6 +24,7 @@ import com.arialyy.aria.core.download.DownloadTaskEntity; import com.arialyy.aria.core.inf.IDownloadListener; import com.arialyy.aria.util.BufferedRandomAccessFile; import com.arialyy.aria.util.CommonUtil; +import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -45,7 +46,7 @@ final class HttpThreadTask extends AbsThreadTask 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/inf/GroupSendParams.java b/Aria/src/main/java/com/arialyy/aria/core/inf/GroupSendParams.java new file mode 100644 index 00000000..2a977b9e --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/GroupSendParams.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.inf; + +/** + * Created by lyy on 2017/9/8. + * 任务组参数传递 + */ +public class GroupSendParams { + + public GROUP_TASK groupTask; + public ENTITY entity; + + public GroupSendParams() { + } + + public GroupSendParams(GROUP_TASK groupTask, ENTITY entity) { + this.groupTask = groupTask; + this.entity = entity; + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/IReceiver.java b/Aria/src/main/java/com/arialyy/aria/core/inf/IReceiver.java index 0242daf3..aed2ad9a 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/inf/IReceiver.java +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/IReceiver.java @@ -26,10 +26,6 @@ public interface IReceiver { */ void destroy(); - /** - * 移除事件回调 - */ - void removeSchedulerListener(); /** * 移除观察者 diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulerListener.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulerListener.java index a77db95e..863c595b 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulerListener.java +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulerListener.java @@ -15,12 +15,14 @@ */ package com.arialyy.aria.core.scheduler; +import com.arialyy.aria.core.inf.AbsNormalEntity; import com.arialyy.aria.core.inf.ITask; /** * Created by Aria.Lao on 2017/6/7. */ -public class AbsSchedulerListener implements ISchedulerListener { +public class AbsSchedulerListener implements ISchedulerListener { + @Override public void onPre(TASK task) { } @@ -64,4 +66,32 @@ public class AbsSchedulerListener implements ISchedulerListe public void setListener(Object obj) { } + + public void onSubTaskPre(TASK task, SUB_ENTITY subTask) { + + } + + public void onSubTaskStart(TASK task, SUB_ENTITY subTask) { + + } + + public void onSubTaskStop(TASK task, SUB_ENTITY subTask) { + + } + + public void onSubTaskCancel(TASK task, SUB_ENTITY subTask) { + + } + + public void onSubTaskComplete(TASK task, SUB_ENTITY subTask) { + + } + + public void onSubTaskFail(TASK task, SUB_ENTITY subTask) { + + } + + public void onSubTaskRunning(TASK task, SUB_ENTITY subTask) { + + } } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java index 281324c9..144b6216 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java @@ -21,8 +21,10 @@ import android.util.Log; import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.download.DownloadTask; import com.arialyy.aria.core.inf.AbsEntity; +import com.arialyy.aria.core.inf.AbsNormalEntity; import com.arialyy.aria.core.inf.AbsTask; import com.arialyy.aria.core.inf.AbsTaskEntity; +import com.arialyy.aria.core.inf.GroupSendParams; import com.arialyy.aria.core.inf.IEntity; import com.arialyy.aria.core.queue.ITaskQueue; import com.arialyy.aria.core.upload.UploadTask; @@ -45,9 +47,8 @@ abstract class AbsSchedulers> mSchedulerListeners = new ConcurrentHashMap<>(); - - private Map> mObservers = new ConcurrentHashMap<>(); + private Map> mObservers = + new ConcurrentHashMap<>(); /** * 设置调度器类型 @@ -59,33 +60,9 @@ abstract class AbsSchedulers schedulerListener) { - mSchedulerListeners.put(targetName, schedulerListener); - } - - /** - * @param targetName 观察者,创建该监听器的对象类名 - * @see #unRegister(Object) - */ - @Override public void removeSchedulerListener(String targetName, - ISchedulerListener schedulerListener) { - //该内存泄露解决方案:http://stackoverflow.com/questions/14585829/how-safe-is-to-delete-already-removed-concurrenthashmap-element - for (Iterator>> iter = - mSchedulerListeners.entrySet().iterator(); iter.hasNext(); ) { - Map.Entry> entry = iter.next(); - if (entry.getKey().equals(targetName)) iter.remove(); - } - } - @Override public void register(Object obj) { String targetName = obj.getClass().getName(); - AbsSchedulerListener listener = mObservers.get(targetName); + AbsSchedulerListener listener = mObservers.get(targetName); if (listener == null) { listener = createListener(targetName); if (listener != null) { @@ -98,9 +75,9 @@ abstract class AbsSchedulers>> iter = + for (Iterator>> iter = mObservers.entrySet().iterator(); iter.hasNext(); ) { - Map.Entry> entry = iter.next(); + Map.Entry> entry = iter.next(); if (entry.getKey().equals(obj.getClass().getName())) iter.remove(); } } @@ -110,11 +87,11 @@ abstract class AbsSchedulers createListener(String targetName) { - AbsSchedulerListener listener = null; + private AbsSchedulerListener createListener(String targetName) { + AbsSchedulerListener listener = null; try { Class clazz = Class.forName(targetName + getProxySuffix()); - listener = (AbsSchedulerListener) clazz.newInstance(); + listener = (AbsSchedulerListener) clazz.newInstance(); } catch (ClassNotFoundException e) { Log.e(TAG, targetName + ",没有Aria的Download或Upload注解方法"); } catch (InstantiationException e) { @@ -126,13 +103,62 @@ abstract class AbsSchedulers 0) { + Set keys = mObservers.keySet(); + for (String key : keys) { + AbsSchedulerListener listener = mObservers.get(key); + switch (msg.what) { + case SUB_PRE: + listener.onSubTaskPre((TASK) params.groupTask, params.entity); + break; + case SUB_START: + listener.onSubTaskStart((TASK) params.groupTask, params.entity); + break; + case SUB_STOP: + listener.onSubTaskStop((TASK) params.groupTask, params.entity); + break; + case SUB_FAIL: + listener.onSubTaskFail((TASK) params.groupTask, params.entity); + break; + case SUB_RUNNING: + listener.onSubTaskRunning((TASK) params.groupTask, params.entity); + break; + case SUB_CANCEL: + listener.onSubTaskCancel((TASK) params.groupTask, params.entity); + break; + case SUB_COMPLETE: + listener.onSubTaskComplete((TASK) params.groupTask, params.entity); + break; + } + } + } + return true; + } + + /** + * 处理普通任务事件 + */ + private void handleNormalEvent(TASK task, int what) { ENTITY entity = task.getEntity(); - switch (msg.what) { + switch (what) { case STOP: if (task.getEntity().getState() == IEntity.STATE_WAIT) { break; @@ -153,8 +179,7 @@ abstract class AbsSchedulers 0) { - Set keys = mSchedulerListeners.keySet(); - for (String key : keys) { - callback(state, task, mSchedulerListeners.get(key)); - } - } else if (mObservers.size() > 0) { + if (mObservers.size() > 0) { Set keys = mObservers.keySet(); for (String key : keys) { callback(state, task, mObservers.get(key)); @@ -176,7 +196,8 @@ abstract class AbsSchedulers listener) { + private void callback(int state, TASK task, + AbsSchedulerListener listener) { if (listener != null) { if (task == null) { Log.e(TAG, "TASK 为null,回调失败"); @@ -211,9 +232,7 @@ abstract class AbsSchedulers) listener).onNoSupportBreakPoint(task); - } + listener.onNoSupportBreakPoint(task); break; } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulerListener.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulerListener.java index b8128680..533fecc3 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulerListener.java +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulerListener.java @@ -66,4 +66,8 @@ public interface ISchedulerListener { * 任务执行中 */ void onTaskRunning(TASK task); + + + + } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulers.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulers.java index a88e1f29..c48ebf2e 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulers.java +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulers.java @@ -24,6 +24,11 @@ import com.arialyy.aria.core.inf.AbsTask; * 调度器功能接口 */ public interface ISchedulers extends Handler.Callback { + /** + * 为任务组任务 + */ + int IS_SUB_TASK = 0xd1; + /** * 断点支持 */ @@ -67,18 +72,39 @@ public interface ISchedulers extends Handler.Callback { int RESUME = 8; /** - * 注册下载器监听,一个观察者只能注册一次监听 - * - * @param targetName 观察者,创建该监听器的对象类名 - * @param schedulerListener {@link ISchedulerListener} + * 任务组子任务预处理 */ - void addSchedulerListener(String targetName, ISchedulerListener schedulerListener); + int SUB_PRE = 0xa1; /** - * @param targetName 观察者,创建该监听器的对象类名 - * 取消注册监听器 + * 任务组子任务开始 */ - void removeSchedulerListener(String targetName, ISchedulerListener schedulerListener); + int SUB_START = 0xa2; + + /** + * 任务组子任务停止 + */ + int SUB_STOP = 0xa3; + + /** + * 任务组子任务取消 + */ + int SUB_CANCEL = 0xa4; + + /** + * 任务组子任务失败 + */ + int SUB_FAIL = 0xa5; + + /** + * 任务组子任务执行执行中 + */ + int SUB_RUNNING = 0xa6; + + /** + * 任务组子任务完成 + */ + int SUB_COMPLETE = 0xa7; /** * 将当前类注册到Aria diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/BaseUListener.java b/Aria/src/main/java/com/arialyy/aria/core/upload/BaseUListener.java index 4ec59630..0c0d9f6e 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/BaseUListener.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/BaseUListener.java @@ -106,6 +106,7 @@ class BaseUListener> } else { mEntity.setSpeed(speed < 0 ? 0 : speed); } + mEntity.setPercent((int) (mEntity.getCurrentProgress() * 100 / mEntity.getFileSize())); } /** 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..2036547c 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,13 +92,11 @@ 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(); for (String key : keys) { - IReceiver receiver = am.getReceiver().get(key); - receiver.removeSchedulerListener(); am.getReceiver().remove(key); } } @@ -108,26 +106,6 @@ public class UploadReceiver extends AbsReceiver { listener = null; } - /** - * 添加调度器回调 - * - * @see #register() - */ - @Deprecated public UploadReceiver addSchedulerListener(ISchedulerListener listener) { - this.listener = listener; - UploadSchedulers.getInstance().addSchedulerListener(targetName, listener); - return this; - } - - /** - * @see #unRegister() - */ - @Deprecated @Override public void removeSchedulerListener() { - if (listener != null) { - UploadSchedulers.getInstance().removeSchedulerListener(targetName, listener); - } - } - /** * 将当前类注册到Aria */ diff --git a/Aria/src/main/java/com/arialyy/aria/orm/DBConfig.java b/Aria/src/main/java/com/arialyy/aria/orm/DBConfig.java index 9e1dabfc..ceecb7d6 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/DBConfig.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/DBConfig.java @@ -33,7 +33,7 @@ import java.util.Map; class DBConfig { static Map mapping = new HashMap<>(); static String DB_NAME; - static int VERSION = 14; + static int VERSION = 15; static { if (TextUtils.isEmpty(DB_NAME)) { diff --git a/Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java b/Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java index c5affd31..f31fe386 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java @@ -26,6 +26,7 @@ import android.util.Log; import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.util.CheckUtil; import com.arialyy.aria.util.CommonUtil; +import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Type; import java.util.ArrayList; @@ -180,7 +181,7 @@ final class SqlHelper extends SQLiteOpenHelper { print(FIND_DATA, sql); Cursor cursor = db.rawQuery(sql, null); List data = cursor.getCount() > 0 ? newInstanceEntity(db, clazz, cursor) : null; - cursor.close(); + closeCursor(cursor); close(db); return data; } @@ -223,7 +224,7 @@ final class SqlHelper extends SQLiteOpenHelper { print(FIND_DATA, sb.toString()); Cursor cursor = db.rawQuery(sb.toString(), null); List data = cursor.getCount() > 0 ? newInstanceEntity(db, clazz, cursor) : null; - cursor.close(); + closeCursor(cursor); close(db); return data; } @@ -238,7 +239,7 @@ final class SqlHelper extends SQLiteOpenHelper { print(FIND_ALL_DATA, sb.toString()); Cursor cursor = db.rawQuery(sb.toString(), null); List data = cursor.getCount() > 0 ? newInstanceEntity(db, clazz, cursor) : null; - cursor.close(); + closeCursor(cursor); close(db); return data; } @@ -394,7 +395,7 @@ final class SqlHelper extends SQLiteOpenHelper { } catch (Exception e) { e.printStackTrace(); } finally { - if (cursor != null) cursor.close(); + closeCursor(cursor); close(db); } return false; @@ -564,7 +565,7 @@ final class SqlHelper extends SQLiteOpenHelper { entity.rowID = cursor.getInt(cursor.getColumnIndex("rowid")); entitys.add(entity); } - cursor.close(); + closeCursor(cursor); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { @@ -586,6 +587,16 @@ final class SqlHelper extends SQLiteOpenHelper { return findData(db, params[0], params[1] + "=?", primary); } + private static void closeCursor(Cursor cursor){ + if (cursor != null && !cursor.isClosed()) { + try { + cursor.close(); + } catch (android.database.SQLException e) { + e.printStackTrace(); + } + } + } + private static void close(SQLiteDatabase db) { //if (db != null && db.isOpen()) db.close(); } diff --git a/Aria/src/main/java/com/arialyy/aria/orm/SqlUtil.java b/Aria/src/main/java/com/arialyy/aria/orm/SqlUtil.java index 616e17b9..b6e8eed0 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/SqlUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/SqlUtil.java @@ -145,8 +145,11 @@ final class SqlUtil { // field.isSynthetic(), 使用as热启动App时,AS会自动给你的class添加change字段 Ignore ignore = field.getAnnotation(Ignore.class); int modifiers = field.getModifiers(); + String fieldName = field.getName(); return (ignore != null && ignore.value()) - || field.getName().equals("rowID") + || fieldName.equals("rowID") + || fieldName.equals("shadow$_klass_") + || fieldName.equals("shadow$_monitor_") || field.isSynthetic() || Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers); 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 f862764c..d8be3e6a 100644 --- a/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java @@ -24,13 +24,16 @@ import android.text.TextUtils; import android.util.Base64; import android.util.Log; import com.arialyy.aria.core.AriaManager; -import com.arialyy.aria.core.command.normal.NormalCmdFactory; +import com.arialyy.aria.core.command.group.AbsGroupCmd; +import com.arialyy.aria.core.command.group.GroupCmdFactory; import com.arialyy.aria.core.command.normal.AbsNormalCmd; +import com.arialyy.aria.core.command.normal.NormalCmdFactory; import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadGroupEntity; import com.arialyy.aria.core.download.DownloadGroupTaskEntity; import com.arialyy.aria.core.download.DownloadTaskEntity; import com.arialyy.aria.core.inf.AbsTaskEntity; +import com.arialyy.aria.core.inf.BaseGroupTaskEntity; import com.arialyy.aria.core.upload.UploadEntity; import com.arialyy.aria.core.upload.UploadTaskEntity; import com.arialyy.aria.orm.DbEntity; @@ -43,6 +46,11 @@ import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.Field; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; import java.math.BigDecimal; import java.math.BigInteger; import java.net.URLEncoder; @@ -58,11 +66,6 @@ import java.util.Properties; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.lang.reflect.GenericArrayType; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.lang.reflect.WildcardType; /** * Created by lyy on 2016/1/22. @@ -432,10 +435,24 @@ public class CommonUtil { } } - public static 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..45cdd262 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/AriaCompiler/src/main/java/com/arialyy/compiler/AriaProcessor.java b/AriaCompiler/src/main/java/com/arialyy/compiler/AriaProcessor.java index 9bdef7d9..ede028cc 100644 --- a/AriaCompiler/src/main/java/com/arialyy/compiler/AriaProcessor.java +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/AriaProcessor.java @@ -54,7 +54,7 @@ import javax.lang.model.element.TypeElement; annotataions.add(Download.onTaskRunning.class.getCanonicalName()); annotataions.add(Download.onTaskStart.class.getCanonicalName()); annotataions.add(Download.onTaskStop.class.getCanonicalName()); - //下载任务的注解 + //下载任务组的注解 annotataions.add(DownloadGroup.onPre.class.getCanonicalName()); annotataions.add(DownloadGroup.onTaskCancel.class.getCanonicalName()); annotataions.add(DownloadGroup.onTaskComplete.class.getCanonicalName()); @@ -64,6 +64,14 @@ import javax.lang.model.element.TypeElement; annotataions.add(DownloadGroup.onTaskRunning.class.getCanonicalName()); annotataions.add(DownloadGroup.onTaskStart.class.getCanonicalName()); annotataions.add(DownloadGroup.onTaskStop.class.getCanonicalName()); + //任务组子任务的注解 + annotataions.add(DownloadGroup.onSubTaskPre.class.getCanonicalName()); + //annotataions.add(DownloadGroup.onSubTaskCancel.class.getCanonicalName()); + annotataions.add(DownloadGroup.onSubTaskComplete.class.getCanonicalName()); + annotataions.add(DownloadGroup.onSubTaskFail.class.getCanonicalName()); + annotataions.add(DownloadGroup.onSubTaskRunning.class.getCanonicalName()); + annotataions.add(DownloadGroup.onSubTaskStart.class.getCanonicalName()); + annotataions.add(DownloadGroup.onSubTaskStop.class.getCanonicalName()); //上传任务的注解 annotataions.add(Upload.onPre.class.getCanonicalName()); annotataions.add(Upload.onNoSupportBreakPoint.class.getCanonicalName()); @@ -86,6 +94,7 @@ import javax.lang.model.element.TypeElement; mHandler.clean(); mHandler.handleDownload(roundEnv); mHandler.handleDownloadGroup(roundEnv); + mHandler.handleDownloadGroupSub(roundEnv); mHandler.handleUpload(roundEnv); mHandler.createProxyFile(); return true; diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/CountFiler.java b/AriaCompiler/src/main/java/com/arialyy/compiler/CountFiler.java new file mode 100644 index 00000000..ec874cd6 --- /dev/null +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/CountFiler.java @@ -0,0 +1,127 @@ +/* + * 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.compiler; + +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.JavaFile; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeSpec; +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.annotation.processing.Filer; +import javax.lang.model.element.Modifier; + +/** + * Created by lyy on 2017/9/6. + * 各类注解统计技术类 + */ +final class CountFiler { + private Filer mFiler; + private ParamObtainUtil mPbUtil; + + CountFiler(Filer filer, ParamObtainUtil pbUtil) { + mFiler = filer; + mPbUtil = pbUtil; + } + + /** + * 每一种注解对应的统计类 + */ + void createCountFile() throws IOException { + Set keys = mPbUtil.getListenerClass().keySet(); + if (keys.size() == 0) return; + TypeSpec.Builder builder = TypeSpec.classBuilder(ProxyConstance.PROXY_COUNTER_NAME) + .addModifiers(Modifier.PUBLIC, Modifier.FINAL); + + FieldSpec mappingField = FieldSpec.builder( + ParameterizedTypeName.get(ClassName.get(Map.class), ClassName.get(String.class), + ParameterizedTypeName.get(ClassName.get(Set.class), ClassName.get(String.class))), + ProxyConstance.PROXY_COUNTER_MAP) + .addModifiers(Modifier.PRIVATE) + .initializer("new $T()", HashMap.class) + .build(); + builder.addField(mappingField); + + //增加构造函数 + CodeBlock.Builder cb = CodeBlock.builder(); + cb.add("Set set = null;\n"); + for (String key : keys) { + addTypeData(key, mPbUtil.getListenerClass().get(key), cb); + } + MethodSpec structure = + MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC).addCode(cb.build()).build(); + builder.addMethod(structure); + + builder.addMethod( + createMethod(ProxyConstance.COUNT_METHOD_DOWNLOAD, ProxyConstance.COUNT_DOWNLOAD)); + builder.addMethod( + createMethod(ProxyConstance.COUNT_METHOD_UPLOAD, ProxyConstance.COUNT_UPLOAD)); + builder.addMethod(createMethod(ProxyConstance.COUNT_METHOD_DOWNLOAD_GROUP, + ProxyConstance.COUNT_DOWNLOAD_GROUP)); + builder.addMethod(createMethod(ProxyConstance.COUNT_METHOD_DOWNLOAD_GROUP_SUB, + ProxyConstance.COUNT_DOWNLOAD_GROUP_SUB)); + + JavaFile jf = JavaFile.builder(ProxyConstance.PROXY_COUNTER_PACKAGE, builder.build()).build(); + createFile(jf); + } + + /** + * 创建不同任务类型的代理类集合 + * + * @param key {@link ParamObtainUtil#addListenerMapping(String, String)} + */ + private MethodSpec createMethod(String methodName, String key) { + MethodSpec.Builder builder = MethodSpec.methodBuilder(methodName); + ParameterizedTypeName returnName = + ParameterizedTypeName.get(ClassName.get(Set.class), ClassName.get(String.class)); + builder.addModifiers(Modifier.PUBLIC, Modifier.FINAL) + .returns(returnName) + .addCode("return " + ProxyConstance.PROXY_COUNTER_MAP + ".get(\"" + key + "\");\n"); + return builder.build(); + } + + /** + * 添加每一种注解对应类 + * + * @param type {@link ParamObtainUtil#addListenerMapping(String, String)} + */ + private void addTypeData(String type, Set clsNames, CodeBlock.Builder cb) { + if (clsNames == null || clsNames.isEmpty()) return; + StringBuilder sb = new StringBuilder(); + sb.append("set = new $T();\n"); + for (String clsName : clsNames) { + sb.append("set.add(\"").append(clsName).append("\");\n"); + } + sb.append("typeMapping.put(\"").append(type).append("\", ").append("set);\n"); + cb.add(sb.toString(), ClassName.get(HashSet.class)); + } + + private void createFile(JavaFile jf) throws IOException { + //jf.writeTo(System.out); + if (ProxyConstance.DEBUG) { + // 如果需要在控制台打印生成的文件,则去掉下面的注释 + jf.writeTo(System.out); + } else { + jf.writeTo(mFiler); + } + } +} diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/ElementHandler.java b/AriaCompiler/src/main/java/com/arialyy/compiler/ElementHandler.java index fa4ce99e..bcb697a5 100644 --- a/AriaCompiler/src/main/java/com/arialyy/compiler/ElementHandler.java +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/ElementHandler.java @@ -18,31 +18,9 @@ package com.arialyy.compiler; import com.arialyy.annotations.Download; import com.arialyy.annotations.DownloadGroup; import com.arialyy.annotations.Upload; -import com.squareup.javapoet.ClassName; -import com.squareup.javapoet.CodeBlock; -import com.squareup.javapoet.FieldSpec; -import com.squareup.javapoet.JavaFile; -import com.squareup.javapoet.MethodSpec; -import com.squareup.javapoet.ParameterSpec; -import com.squareup.javapoet.TypeSpec; -import com.squareup.javapoet.ParameterizedTypeName; import java.io.IOException; -import java.lang.annotation.Annotation; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; import javax.annotation.processing.Filer; import javax.annotation.processing.RoundEnvironment; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.PackageElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; import javax.lang.model.util.Elements; /** @@ -50,16 +28,13 @@ import javax.lang.model.util.Elements; * 元素处理 */ class ElementHandler { - private static final boolean DEBUG = false; private Filer mFiler; - private Elements mElementUtil; - private Map mMethods = new HashMap<>(); - private Map> mListenerClass = new HashMap<>(); + private ParamObtainUtil mPbUtil; ElementHandler(Filer filer, Elements elements) { mFiler = filer; - mElementUtil = elements; + mPbUtil = new ParamObtainUtil(elements); } /** @@ -69,43 +44,68 @@ class ElementHandler { * PackageElement 一般代表Package */ void handleDownload(RoundEnvironment roundEnv) { - saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onNoSupportBreakPoint.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onNoSupportBreakPoint.class, ProxyConstance.TASK_NO_SUPPORT_BREAKPOINT); - saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onPre.class, ProxyConstance.PRE); - saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskCancel.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onPre.class, ProxyConstance.PRE); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskCancel.class, ProxyConstance.TASK_CANCEL); - saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskComplete.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskComplete.class, ProxyConstance.TASK_COMPLETE); - saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskFail.class, ProxyConstance.TASK_FAIL); - saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskPre.class, ProxyConstance.TASK_PRE); - saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskResume.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskFail.class, + ProxyConstance.TASK_FAIL); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskPre.class, + ProxyConstance.TASK_PRE); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskResume.class, ProxyConstance.TASK_RESUME); - saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskRunning.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskRunning.class, ProxyConstance.TASK_RUNNING); - saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskStart.class, ProxyConstance.TASK_START); - saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskStop.class, ProxyConstance.TASK_STOP); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskStart.class, + ProxyConstance.TASK_START); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskStop.class, + ProxyConstance.TASK_STOP); } /** * 处理搜索到的下载任务组注解 */ void handleDownloadGroup(RoundEnvironment roundEnv) { - saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onPre.class, ProxyConstance.PRE); - saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskCancel.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onPre.class, + ProxyConstance.PRE); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskCancel.class, ProxyConstance.TASK_CANCEL); - saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskComplete.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskComplete.class, ProxyConstance.TASK_COMPLETE); - saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskFail.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskFail.class, ProxyConstance.TASK_FAIL); - saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskPre.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskPre.class, ProxyConstance.TASK_PRE); - saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskResume.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskResume.class, ProxyConstance.TASK_RESUME); - saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskRunning.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskRunning.class, ProxyConstance.TASK_RUNNING); - saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskStart.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskStart.class, ProxyConstance.TASK_START); - saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskStop.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskStop.class, + ProxyConstance.TASK_STOP); + } + + /** + * 处理搜索到的下载任务组子任务注解 + */ + void handleDownloadGroupSub(RoundEnvironment roundEnv) { + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP_SUB, roundEnv, DownloadGroup.onSubTaskPre.class, + ProxyConstance.TASK_PRE); + //mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP_SUB, roundEnv, DownloadGroup.onSubTaskCancel.class, + // ProxyConstance.TASK_CANCEL); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP_SUB, roundEnv, DownloadGroup.onSubTaskComplete.class, + ProxyConstance.TASK_COMPLETE); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP_SUB, roundEnv, DownloadGroup.onSubTaskFail.class, + ProxyConstance.TASK_FAIL); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP_SUB, roundEnv, DownloadGroup.onSubTaskRunning.class, + ProxyConstance.TASK_RUNNING); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP_SUB, roundEnv, DownloadGroup.onSubTaskStart.class, + ProxyConstance.TASK_START); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP_SUB, roundEnv, DownloadGroup.onSubTaskStop.class, ProxyConstance.TASK_STOP); } @@ -113,488 +113,39 @@ class ElementHandler { * 处理搜索到的上传注解F */ void handleUpload(RoundEnvironment roundEnv) { - saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onNoSupportBreakPoint.class, + mPbUtil.saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onNoSupportBreakPoint.class, ProxyConstance.TASK_NO_SUPPORT_BREAKPOINT); - saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onPre.class, ProxyConstance.PRE); - saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskCancel.class, ProxyConstance.TASK_CANCEL); - saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskComplete.class, + mPbUtil.saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onPre.class, ProxyConstance.PRE); + mPbUtil.saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskCancel.class, + ProxyConstance.TASK_CANCEL); + mPbUtil.saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskComplete.class, ProxyConstance.TASK_COMPLETE); - saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskFail.class, ProxyConstance.TASK_FAIL); - saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskResume.class, ProxyConstance.TASK_RESUME); - saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskRunning.class, ProxyConstance.TASK_RUNNING); - saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskStart.class, ProxyConstance.TASK_START); - saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskStop.class, ProxyConstance.TASK_STOP); + mPbUtil.saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskFail.class, + ProxyConstance.TASK_FAIL); + mPbUtil.saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskResume.class, + ProxyConstance.TASK_RESUME); + mPbUtil.saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskRunning.class, + ProxyConstance.TASK_RUNNING); + mPbUtil.saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskStart.class, + ProxyConstance.TASK_START); + mPbUtil.saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskStop.class, + ProxyConstance.TASK_STOP); } /** - * 在build文件夹中生成如下代码的文件 - *
-   *   
-   * package com.arialyy.simple.download;
-   *
-   * import com.arialyy.aria.core.download.DownloadTask;
-   * import com.arialyy.aria.core.scheduler.AbsSchedulerListener;
-   *
-   * public final class SingleTaskActivity$$DownloadListenerProxy extends
-   * AbsSchedulerListener {
-   * private SingleTaskActivity obj;
-   *
-   *    public void onPre(final DownloadTask task) {
-   *      obj.onPre((DownloadTask)task);
-   *    }
-   *
-   *    public void onTaskStart(final DownloadTask task) {
-   *      obj.onStart((DownloadTask)task);
-   *    }
-   *
-   *    public void setListener(final Object obj) {
-   *      this.obj = (SingleTaskActivity)obj;
-   *    }
-   * }
-   *   
-   * 
+ * 在build文件夹中生成代理文件 */ void createProxyFile() { try { - createProxyListenerFile(); - createProxyClassFile(); + new EventProxyFiler(mFiler, mPbUtil).createEventProxyFile(); + new CountFiler(mFiler, mPbUtil).createCountFile(); } catch (IOException e) { e.printStackTrace(); } } - /** - * 创建事件代理文件 - */ - private void createProxyListenerFile() throws IOException { - Set keys = mMethods.keySet(); - for (String key : keys) { - ProxyMethodParam entity = mMethods.get(key); - for (TaskEnum taskEnum : entity.taskEnums) { - JavaFile jf = - JavaFile.builder(entity.packageName, createProxyClass(entity, taskEnum)).build(); - createFile(jf); - } - } - } - - private void createFile(JavaFile jf) throws IOException { - if (DEBUG) { - // 如果需要在控制台打印生成的文件,则去掉下面的注释 - jf.writeTo(System.out); - } else { - jf.writeTo(mFiler); - } - } - - /** - * 每一种注解对应的类集合 - */ - private void createProxyClassFile() throws IOException { - Set keys = mListenerClass.keySet(); - TypeSpec.Builder builder = TypeSpec.classBuilder(ProxyConstance.PROXY_COUNTER_NAME) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL); - - FieldSpec mappingField = FieldSpec.builder( - ParameterizedTypeName.get(ClassName.get(Map.class), ClassName.get(String.class), - ParameterizedTypeName.get(ClassName.get(Set.class), ClassName.get(String.class))), - ProxyConstance.PROXY_COUNTER_MAP) - .addModifiers(Modifier.PRIVATE) - .initializer("new $T()", HashMap.class) - .build(); - builder.addField(mappingField); - - //增加构造函数 - CodeBlock.Builder cb = CodeBlock.builder(); - cb.add("Set set = null;\n"); - for (String key : keys) { - addTypeData(key, mListenerClass.get(key), cb); - } - MethodSpec structure = - MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC).addCode(cb.build()).build(); - builder.addMethod(structure); - - builder.addMethod( - creatMethod(ProxyConstance.COUNT_METHOD_DOWNLOAD, ProxyConstance.COUNT_DOWNLOAD)); - builder.addMethod(creatMethod(ProxyConstance.COUNT_METHOD_UPLOAD, ProxyConstance.COUNT_UPLOAD)); - builder.addMethod(creatMethod(ProxyConstance.COUNT_METHOD_DOWNLOAD_GROUP, - ProxyConstance.COUNT_DOWNLOAD_GROUP)); - - JavaFile jf = JavaFile.builder(ProxyConstance.PROXY_COUNTER_PACKAGE, builder.build()).build(); - createFile(jf); - } - - /** - * 创建不同任务类型的代理类集合 - * - * @param key {@link #addListenerMapping(String, String)} - */ - private MethodSpec creatMethod(String methodName, String key) { - MethodSpec.Builder builder = MethodSpec.methodBuilder(methodName); - ParameterizedTypeName returnName = - ParameterizedTypeName.get(ClassName.get(Set.class), ClassName.get(String.class)); - builder.addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .returns(returnName) - .addCode("return " + ProxyConstance.PROXY_COUNTER_MAP + ".get(\"" + key + "\");\n"); - return builder.build(); - } - - /** - * 添加每一种注解对应类 - * - * @param type {@link #addListenerMapping(String, String)} - */ - private void addTypeData(String type, Set clsNames, CodeBlock.Builder cb) { - if (clsNames == null || clsNames.isEmpty()) return; - StringBuilder sb = new StringBuilder(); - sb.append("set = new $T();\n"); - for (String clsName : clsNames) { - sb.append("set.add(\"").append(clsName).append("\");\n"); - } - sb.append("typeMapping.put(\"").append(type).append("\", ").append("set);\n"); - cb.add(sb.toString(), ClassName.get(HashSet.class)); - } - - /** - * 创建代理方法 - * - * @param taskEnum 任务类型枚举{@link TaskEnum} - * @param annotation {@link Download}、{@link Upload} - * @param methodName 被代理类注解的方法名 - */ - private MethodSpec createProxyMethod(TaskEnum taskEnum, Class annotation, - String methodName) { - ClassName task = ClassName.get(taskEnum.getPkg(), taskEnum.getClassName()); - - ParameterSpec parameterSpec = - ParameterSpec.builder(task, "task").addModifiers(Modifier.FINAL).build(); - StringBuilder sb = new StringBuilder(); - sb.append("Set keys = keyMapping.get(\"").append(methodName).append("\");\n"); - sb.append("if (keys != null) {\n\tif (keys.contains(task.getKey())) {\n") - .append("\t\tobj.") - .append(methodName) - .append("((") - .append(taskEnum.getClassName()) - .append(")task);\n") - .append("\t}\n} else {\n") - .append("\tobj.") - .append(methodName) - .append("((") - .append(taskEnum.getClassName()) - .append(")task);\n}\n"); - - return MethodSpec.methodBuilder(annotation.getSimpleName()) - .addModifiers(Modifier.PUBLIC) - .returns(void.class) - .addParameter(parameterSpec) - .addAnnotation(Override.class) - .addCode(sb.toString()) - .build(); - } - - /** - * 创建代理类 - */ - private TypeSpec createProxyClass(ProxyMethodParam entity, TaskEnum taskEnum) { - TypeSpec.Builder builder = TypeSpec.classBuilder(entity.className + taskEnum.getProxySuffix()) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL); - - //添加被代理的类的字段 - ClassName obj = ClassName.get(entity.packageName, entity.className); - FieldSpec observerField = FieldSpec.builder(obj, "obj").addModifiers(Modifier.PRIVATE).build(); - builder.addField(observerField); - - //添加url映射表 - FieldSpec mappingField = FieldSpec.builder( - ParameterizedTypeName.get(ClassName.get(Map.class), ClassName.get(String.class), - ParameterizedTypeName.get(ClassName.get(Set.class), ClassName.get(String.class))), - "keyMapping").addModifiers(Modifier.PRIVATE).initializer("new $T()", HashMap.class).build(); - builder.addField(mappingField); - - //添加注解方法 - Map, String> temp = entity.methods.get(taskEnum); - if (temp != null) { - for (Class annotation : temp.keySet()) { - MethodSpec method = createProxyMethod(taskEnum, annotation, temp.get(annotation)); - builder.addMethod(method); - } - } - - //增加构造函数 - CodeBlock.Builder cb = CodeBlock.builder(); - cb.add("Set set = null;\n"); - for (String methodName : entity.keyMappings.keySet()) { - Set keys = entity.keyMappings.get(methodName); - if (keys == null || keys.size() == 0) continue; - StringBuilder sb = new StringBuilder(); - sb.append("set = new $T();\n"); - for (String key : keys) { - if (key.isEmpty()) continue; - sb.append("set.add(\"").append(key).append("\");\n"); - } - - sb.append("keyMapping.put(\"").append(methodName).append("\", ").append("set);\n"); - cb.add(sb.toString(), ClassName.get(HashSet.class)); - } - MethodSpec structure = - MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC).addCode(cb.build()).build(); - builder.addMethod(structure); - - //添加设置代理的类 - ParameterSpec parameterSpec = - ParameterSpec.builder(Object.class, "obj").addModifiers(Modifier.FINAL).build(); - MethodSpec listener = MethodSpec.methodBuilder(ProxyConstance.SET_LISTENER) - .addModifiers(Modifier.PUBLIC) - .returns(void.class) - .addParameter(parameterSpec) - .addAnnotation(Override.class) - .addCode("this.obj = (" + entity.className + ")obj;\n") - .build(); - builder.addJavadoc("该文件为Aria自动生成的代理文件,请不要修改该文件的任何代码!\n"); - - //创建父类参数 - ClassName superClass = ClassName.get("com.arialyy.aria.core.scheduler", "AbsSchedulerListener"); - //创建泛型 - ClassName typeVariableName = ClassName.get(taskEnum.getPkg(), taskEnum.getClassName()); - builder.superclass(ParameterizedTypeName.get(superClass, typeVariableName)); - builder.addMethod(listener); - return builder.build(); - } - void clean() { - mMethods.clear(); - } - - /** - * 查找并保存扫描到的方法 - */ - private void saveMethod(TaskEnum taskEnum, RoundEnvironment roundEnv, - Class annotationClazz, int annotationType) { - for (Element element : roundEnv.getElementsAnnotatedWith(annotationClazz)) { - ElementKind kind = element.getKind(); - if (kind == ElementKind.METHOD) { - ExecutableElement method = (ExecutableElement) element; - TypeElement classElement = (TypeElement) method.getEnclosingElement(); - PackageElement packageElement = mElementUtil.getPackageOf(classElement); - checkDownloadMethod(taskEnum, method); - String methodName = method.getSimpleName().toString(); - String className = method.getEnclosingElement().toString(); //全类名 - ProxyMethodParam proxyEntity = mMethods.get(className); - if (proxyEntity == null) { - proxyEntity = new ProxyMethodParam(); - proxyEntity.taskEnums = new HashSet<>(); - proxyEntity.packageName = packageElement.getQualifiedName().toString(); - proxyEntity.className = classElement.getSimpleName().toString(); - mMethods.put(className, proxyEntity); - } - proxyEntity.taskEnums.add(taskEnum); - if (proxyEntity.methods.get(taskEnum) == null) { - proxyEntity.methods.put(taskEnum, new HashMap, String>()); - } - proxyEntity.methods.get(taskEnum).put(annotationClazz, methodName); - proxyEntity.keyMappings.put(methodName, getValues(taskEnum, method, annotationType)); - } - } - } - - /** - * 获取注解的内容 - */ - private Set getValues(TaskEnum taskEnum, ExecutableElement method, int annotationType) { - String clsName = method.getEnclosingElement().toString(); - String[] keys = null; - switch (taskEnum) { - case DOWNLOAD: - keys = getDownloadValues(method, annotationType); - addListenerMapping(clsName, ProxyConstance.COUNT_DOWNLOAD); - break; - case UPLOAD: - keys = getUploadValues(method, annotationType); - addListenerMapping(clsName, ProxyConstance.COUNT_UPLOAD); - break; - case DOWNLOAD_GROUP: - keys = getDownloadGroupValues(method, annotationType); - addListenerMapping(clsName, ProxyConstance.COUNT_DOWNLOAD_GROUP); - break; - } - return keys == null ? null : convertSet(keys); - } - - /** - * 添加方法映射 - * - * @param clsName 注解事件的类 - * @param key {@link ProxyConstance#COUNT_DOWNLOAD}、{@link ProxyConstance#COUNT_UPLOAD}、{@link - * ProxyConstance#COUNT_DOWNLOAD_GROUP} - */ - private void addListenerMapping(String clsName, String key) { - Set cls = mListenerClass.get(key); - if (cls == null) { - cls = new HashSet<>(); - mListenerClass.put(key, cls); - } - cls.add(clsName); - } - - /** - * 获取下载任务组的注解数据 - */ - private String[] getDownloadGroupValues(ExecutableElement method, int annotationType) { - String[] values = null; - switch (annotationType) { - case ProxyConstance.PRE: - values = method.getAnnotation(DownloadGroup.onPre.class).value(); - break; - case ProxyConstance.TASK_PRE: - values = method.getAnnotation(DownloadGroup.onTaskPre.class).value(); - break; - case ProxyConstance.TASK_RESUME: - values = method.getAnnotation(DownloadGroup.onTaskResume.class).value(); - break; - case ProxyConstance.TASK_START: - values = method.getAnnotation(DownloadGroup.onTaskStart.class).value(); - break; - case ProxyConstance.TASK_RUNNING: - values = method.getAnnotation(DownloadGroup.onTaskRunning.class).value(); - break; - case ProxyConstance.TASK_STOP: - values = method.getAnnotation(DownloadGroup.onTaskStop.class).value(); - break; - case ProxyConstance.TASK_COMPLETE: - values = method.getAnnotation(DownloadGroup.onTaskComplete.class).value(); - break; - case ProxyConstance.TASK_CANCEL: - values = method.getAnnotation(DownloadGroup.onTaskCancel.class).value(); - break; - case ProxyConstance.TASK_FAIL: - values = method.getAnnotation(DownloadGroup.onTaskFail.class).value(); - break; - } - return values; - } - - /** - * 获取上传的注解数据 - */ - private String[] getUploadValues(ExecutableElement method, int annotationType) { - String[] values = null; - switch (annotationType) { - case ProxyConstance.PRE: - values = method.getAnnotation(Upload.onPre.class).value(); - break; - case ProxyConstance.TASK_PRE: - //values = method.getAnnotation(Upload.onTaskPre.class).value(); - break; - case ProxyConstance.TASK_RESUME: - values = method.getAnnotation(Upload.onTaskResume.class).value(); - break; - case ProxyConstance.TASK_START: - values = method.getAnnotation(Upload.onTaskStart.class).value(); - break; - case ProxyConstance.TASK_RUNNING: - values = method.getAnnotation(Upload.onTaskRunning.class).value(); - break; - case ProxyConstance.TASK_STOP: - values = method.getAnnotation(Upload.onTaskStop.class).value(); - break; - case ProxyConstance.TASK_COMPLETE: - values = method.getAnnotation(Upload.onTaskComplete.class).value(); - break; - case ProxyConstance.TASK_CANCEL: - values = method.getAnnotation(Upload.onTaskCancel.class).value(); - break; - case ProxyConstance.TASK_FAIL: - values = method.getAnnotation(Upload.onTaskFail.class).value(); - break; - case ProxyConstance.TASK_NO_SUPPORT_BREAKPOINT: - //values = method.getAnnotation(Upload.onNoSupportBreakPoint.class).value(); - break; - } - return values; - } - - /** - * 获取下载的注解数据 - */ - private String[] getDownloadValues(ExecutableElement method, int annotationType) { - String[] values = null; - switch (annotationType) { - case ProxyConstance.PRE: - values = method.getAnnotation(Download.onPre.class).value(); - break; - case ProxyConstance.TASK_PRE: - values = method.getAnnotation(Download.onTaskPre.class).value(); - break; - case ProxyConstance.TASK_RESUME: - values = method.getAnnotation(Download.onTaskResume.class).value(); - break; - case ProxyConstance.TASK_START: - values = method.getAnnotation(Download.onTaskStart.class).value(); - break; - case ProxyConstance.TASK_RUNNING: - values = method.getAnnotation(Download.onTaskRunning.class).value(); - break; - case ProxyConstance.TASK_STOP: - values = method.getAnnotation(Download.onTaskStop.class).value(); - break; - case ProxyConstance.TASK_COMPLETE: - values = method.getAnnotation(Download.onTaskComplete.class).value(); - break; - case ProxyConstance.TASK_CANCEL: - values = method.getAnnotation(Download.onTaskCancel.class).value(); - break; - case ProxyConstance.TASK_FAIL: - values = method.getAnnotation(Download.onTaskFail.class).value(); - break; - case ProxyConstance.TASK_NO_SUPPORT_BREAKPOINT: - values = method.getAnnotation(Download.onNoSupportBreakPoint.class).value(); - break; - } - return values; - } - - /** - * 检查和下载相关的方法,如果被注解的方法为private或参数不合法,则抛异常 - */ - private void checkDownloadMethod(TaskEnum taskEnum, ExecutableElement method) { - String methodName = method.getSimpleName().toString(); - String className = method.getEnclosingElement().toString(); - Set modifiers = method.getModifiers(); - if (modifiers.contains(Modifier.PRIVATE)) { - throw new IllegalAccessError(className + "." + methodName + "不能为private方法"); - } - List params = (List) method.getParameters(); - if (params.size() > 1) { - throw new IllegalArgumentException( - className + "." + methodName + "参数错误, 参数只有一个,且参数必须是" + getCheckParams(taskEnum)); - } - if (!params.get(0).asType().toString().equals(getCheckParams(taskEnum))) { - throw new IllegalArgumentException(className - + "." - + methodName - + "参数【" - + params.get(0).getSimpleName() - + "】类型错误,参数必须是" - + getCheckParams(taskEnum)); - } - } - - /** - * 字符串数组转set - * - * @param keys 注解中查到的key - */ - private Set convertSet(final String[] keys) { - if (keys == null || keys.length == 0) { - return null; - } - if (keys[0].isEmpty()) return null; - Set set = new HashSet<>(); - Collections.addAll(set, keys); - return set; - } - - private String getCheckParams(TaskEnum taskEnum) { - return taskEnum.pkg + "." + taskEnum.getClassName(); + mPbUtil.getMethodParams().clear(); + mPbUtil.getListenerClass().clear(); } } diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/EventProxyFiler.java b/AriaCompiler/src/main/java/com/arialyy/compiler/EventProxyFiler.java new file mode 100644 index 00000000..440b4bcc --- /dev/null +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/EventProxyFiler.java @@ -0,0 +1,231 @@ +/* + * 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.compiler; + +import com.arialyy.annotations.Download; +import com.arialyy.annotations.Upload; +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.JavaFile; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeSpec; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.annotation.processing.Filer; +import javax.lang.model.element.Modifier; + +/** + * Created by lyy on 2017/9/6. + * 任务事件代理文件 + * + *
+ *   
+ * package com.arialyy.simple.download;
+ *
+ * import com.arialyy.aria.core.download.DownloadTask;
+ * import com.arialyy.aria.core.scheduler.AbsSchedulerListener;
+ *
+ * public final class SingleTaskActivity$$DownloadListenerProxy extends
+ * AbsSchedulerListener {
+ * private SingleTaskActivity obj;
+ *
+ *    public void onPre(final DownloadTask task) {
+ *      obj.onPre((DownloadTask)task);
+ *    }
+ *
+ *    public void onTaskStart(final DownloadTask task) {
+ *      obj.onStart((DownloadTask)task);
+ *    }
+ *
+ *    public void setListener(final Object obj) {
+ *      this.obj = (SingleTaskActivity)obj;
+ *    }
+ * }
+ *   
+ * 
+ */ +final class EventProxyFiler { + + private Filer mFiler; + private ParamObtainUtil mPbUtil; + + EventProxyFiler(Filer filer, ParamObtainUtil pbUtil) { + mFiler = filer; + mPbUtil = pbUtil; + } + + /** + * 创建任务事件代理文件 + */ + void createEventProxyFile() throws IOException { + Set keys = mPbUtil.getMethodParams().keySet(); + for (String key : keys) { + ProxyClassParam entity = mPbUtil.getMethodParams().get(key); + JavaFile jf = JavaFile.builder(entity.packageName, createProxyClass(entity)).build(); + createFile(jf); + } + } + + /** + * 创建代理方法 + * + * @param taskEnum 任务类型枚举{@link TaskEnum} + * @param annotation {@link Download}、{@link Upload} + * @param methodName 被代理类注解的方法名 + */ + private MethodSpec createProxyMethod(TaskEnum taskEnum, Class annotation, + String methodName) { + ClassName task = ClassName.get(taskEnum.getPkg(), taskEnum.getClassName()); + + ParameterSpec taskParam = + ParameterSpec.builder(task, "task").addModifiers(Modifier.FINAL).build(); + + String callCode; + if (taskEnum == TaskEnum.DOWNLOAD_GROUP_SUB) { + callCode = "task, subEntity"; + } else { + callCode = "task"; + } + StringBuilder sb = new StringBuilder(); + sb.append("Set keys = keyMapping.get(\"").append(methodName).append("\");\n"); + sb.append("if (keys != null) {\n\tif (keys.contains(task.getKey())) {\n") + .append("\t\tobj.") + .append(methodName) + .append("((") + .append(taskEnum.getClassName()) + .append(")") + .append(callCode) + .append(");\n\t}\n} else {\n") + .append("\tobj.") + .append(methodName) + .append("((") + .append(taskEnum.getClassName()) + .append(")") + .append(callCode) + .append(");\n}\n"); + + MethodSpec.Builder builder = MethodSpec.methodBuilder(annotation.getSimpleName()) + .addModifiers(Modifier.PUBLIC) + .returns(void.class) + .addParameter(taskParam) + .addAnnotation(Override.class) + .addCode(sb.toString()); + + //任务组接口 + if (taskEnum == TaskEnum.DOWNLOAD_GROUP_SUB) { + ClassName subTask = ClassName.get(TaskEnum.DOWNLOAD_ENTITY.pkg, TaskEnum.DOWNLOAD_ENTITY.className); + ParameterSpec subTaskParam = + ParameterSpec.builder(subTask, "subEntity").addModifiers(Modifier.FINAL).build(); + + builder.addParameter(subTaskParam); + } + return builder.build(); + } + + /** + * 创建代理类 + */ + private TypeSpec createProxyClass(ProxyClassParam entity) { + TypeSpec.Builder builder = + TypeSpec.classBuilder(entity.proxyClassName).addModifiers(Modifier.PUBLIC, Modifier.FINAL); + + //添加被代理的类的字段 + ClassName obj = ClassName.get(entity.packageName, entity.className); + FieldSpec observerField = FieldSpec.builder(obj, "obj").addModifiers(Modifier.PRIVATE).build(); + builder.addField(observerField); + + //添加url映射表 + FieldSpec mappingField = FieldSpec.builder( + ParameterizedTypeName.get(ClassName.get(Map.class), ClassName.get(String.class), + ParameterizedTypeName.get(ClassName.get(Set.class), ClassName.get(String.class))), + "keyMapping").addModifiers(Modifier.PRIVATE).initializer("new $T()", HashMap.class).build(); + builder.addField(mappingField); + + //添加注解方法 + for (TaskEnum te : entity.methods.keySet()) { + Map, String> temp = entity.methods.get(te); + if (temp != null) { + for (Class annotation : temp.keySet()) { + MethodSpec method = createProxyMethod(te, annotation, temp.get(annotation)); + builder.addMethod(method); + } + } + } + + //增加构造函数 + CodeBlock.Builder cb = CodeBlock.builder(); + cb.add("Set set = null;\n"); + for (String methodName : entity.keyMappings.keySet()) { + //PrintLog.getInstance().info("methodName ====> " + methodName); + Set keys = entity.keyMappings.get(methodName); + if (keys == null || keys.size() == 0) continue; + StringBuilder sb = new StringBuilder(); + sb.append("set = new $T();\n"); + for (String key : keys) { + if (key.isEmpty()) continue; + sb.append("set.add(\"").append(key).append("\");\n"); + } + + sb.append("keyMapping.put(\"").append(methodName).append("\", ").append("set);\n"); + cb.add(sb.toString(), ClassName.get(HashSet.class)); + } + MethodSpec structure = + MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC).addCode(cb.build()).build(); + builder.addMethod(structure); + + //添加设置代理的类 + ParameterSpec parameterSpec = + ParameterSpec.builder(Object.class, "obj").addModifiers(Modifier.FINAL).build(); + MethodSpec listener = MethodSpec.methodBuilder(ProxyConstance.SET_LISTENER) + .addModifiers(Modifier.PUBLIC) + .returns(void.class) + .addParameter(parameterSpec) + .addAnnotation(Override.class) + .addCode("this.obj = (" + entity.className + ")obj;\n") + .build(); + builder.addJavadoc("该文件为Aria自动生成的代理文件,请不要修改该文件的任何代码!\n"); + + //创建父类参数 + ClassName superClass = ClassName.get("com.arialyy.aria.core.scheduler", "AbsSchedulerListener"); + //主任务泛型参数 + ClassName taskTypeVariable = + ClassName.get(entity.mainTaskEnum.pkg, entity.mainTaskEnum.className); + //子任务泛型参数 + ClassName subTaskTypeVariable = + ClassName.get(entity.subTaskEnum.pkg, entity.subTaskEnum.className); + + builder.superclass( + ParameterizedTypeName.get(superClass, taskTypeVariable, subTaskTypeVariable)); + builder.addMethod(listener); + return builder.build(); + } + + private void createFile(JavaFile jf) throws IOException { + if (ProxyConstance.DEBUG) { + // 如果需要在控制台打印生成的文件,则去掉下面的注释 + jf.writeTo(System.out); + } else { + jf.writeTo(mFiler); + } + } +} diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/ParamObtainUtil.java b/AriaCompiler/src/main/java/com/arialyy/compiler/ParamObtainUtil.java new file mode 100644 index 00000000..128b361a --- /dev/null +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/ParamObtainUtil.java @@ -0,0 +1,221 @@ +/* + * 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.compiler; + +import java.lang.annotation.Annotation; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.util.Elements; + +/** + * Created by Aria.Lao on 2017/9/6. + * 构建代理文件的参数获取工具 + */ +class ParamObtainUtil { + private Map mMethodParams = new HashMap<>(); + private Map> mListenerClass = new HashMap<>(); + private Elements mElementUtil; + + ParamObtainUtil(Elements elements) { + mElementUtil = elements; + } + + /** + * 获取需要创建的代理类参数 + */ + Map> getListenerClass() { + return mListenerClass; + } + + /** + * 获取搜索到的代理方法参数 + */ + Map getMethodParams() { + return mMethodParams; + } + + /** + * 查找并保存扫描到的方法 + */ + void saveMethod(TaskEnum taskEnum, RoundEnvironment roundEnv, + Class annotationClazz, int annotationType) { + for (Element element : roundEnv.getElementsAnnotatedWith(annotationClazz)) { + ElementKind kind = element.getKind(); + if (kind == ElementKind.METHOD) { + ExecutableElement method = (ExecutableElement) element; + TypeElement classElement = (TypeElement) method.getEnclosingElement(); + PackageElement packageElement = mElementUtil.getPackageOf(classElement); + checkDownloadMethod(taskEnum, method); + String methodName = method.getSimpleName().toString(); + String className = method.getEnclosingElement().toString(); //全类名\ + String key = className + taskEnum.proxySuffix; + ProxyClassParam proxyEntity = mMethodParams.get(key); + + if (proxyEntity == null) { + proxyEntity = new ProxyClassParam(); + proxyEntity.taskEnums = new HashSet<>(); + proxyEntity.packageName = packageElement.getQualifiedName().toString(); + proxyEntity.className = classElement.getSimpleName().toString(); + proxyEntity.proxyClassName = proxyEntity.className + taskEnum.proxySuffix; + proxyEntity.mainTaskEnum = taskEnum; + if (taskEnum == TaskEnum.DOWNLOAD_GROUP_SUB || taskEnum == TaskEnum.DOWNLOAD_GROUP) { + proxyEntity.subTaskEnum = TaskEnum.DOWNLOAD_ENTITY; + } + mMethodParams.put(key, proxyEntity); + } + proxyEntity.taskEnums.add(taskEnum); + if (proxyEntity.methods.get(taskEnum) == null) { + proxyEntity.methods.put(taskEnum, new HashMap, String>()); + } + proxyEntity.methods.get(taskEnum).put(annotationClazz, methodName); + proxyEntity.keyMappings.put(methodName, getValues(taskEnum, method, annotationType)); + } + } + } + + /** + * 获取注解的内容 + */ + private Set getValues(TaskEnum taskEnum, ExecutableElement method, int annotationType) { + String clsName = method.getEnclosingElement().toString(); + String[] keys = null; + switch (taskEnum) { + case DOWNLOAD: + keys = ValuesUtil.getDownloadValues(method, annotationType); + addListenerMapping(clsName, ProxyConstance.COUNT_DOWNLOAD); + break; + case UPLOAD: + keys = ValuesUtil.getUploadValues(method, annotationType); + addListenerMapping(clsName, ProxyConstance.COUNT_UPLOAD); + break; + case DOWNLOAD_GROUP: + keys = ValuesUtil.getDownloadGroupValues(method, annotationType); + addListenerMapping(clsName, ProxyConstance.COUNT_DOWNLOAD_GROUP); + break; + case DOWNLOAD_GROUP_SUB: + keys = ValuesUtil.getDownloadGroupSubValues(method, annotationType); + addListenerMapping(clsName, ProxyConstance.COUNT_DOWNLOAD_GROUP_SUB); + break; + } + return keys == null ? null : convertSet(keys); + } + + /** + * 添加方法映射 + * + * @param clsName 注解事件的类 + * @param key {@link ProxyConstance#COUNT_DOWNLOAD}、{@link ProxyConstance#COUNT_UPLOAD}、{@link + * ProxyConstance#COUNT_DOWNLOAD_GROUP}、{@link ProxyConstance#COUNT_DOWNLOAD_GROUP_SUB} + */ + void addListenerMapping(String clsName, String key) { + Set cls = mListenerClass.get(key); + if (cls == null) { + cls = new HashSet<>(); + mListenerClass.put(key, cls); + } + cls.add(clsName); + } + + /** + * 检查和下载相关的方法,如果被注解的方法为private或参数不合法,则抛异常 + */ + private void checkDownloadMethod(TaskEnum taskEnum, ExecutableElement method) { + String methodName = method.getSimpleName().toString(); + String className = method.getEnclosingElement().toString(); + Set modifiers = method.getModifiers(); + if (modifiers.contains(Modifier.PRIVATE)) { + throw new IllegalAccessError(className + "." + methodName + "不能为private方法"); + } + List params = (List) method.getParameters(); + if (taskEnum == TaskEnum.DOWNLOAD_GROUP_SUB) { + if (params.size() != 2) { + throw new IllegalArgumentException(className + + "." + + methodName + + "参数错误, 参数只有两个,且第一个参数必须是" + + getCheckParams(taskEnum) + + ",第二个参数必须是" + + getCheckSubParams(taskEnum)); + } + } else { + if (params.size() != 1) { + throw new IllegalArgumentException( + className + "." + methodName + "参数错误, 参数只能有一个,且参数必须是" + getCheckParams(taskEnum)); + } + } + if (!params.get(0).asType().toString().equals(getCheckParams(taskEnum))) { + throw new IllegalArgumentException(className + + "." + + methodName + + "参数【" + + params.get(0).getSimpleName() + + "】类型错误,参数必须是" + + getCheckParams(taskEnum)); + } + if (taskEnum == TaskEnum.DOWNLOAD_GROUP_SUB) { + if (!params.get(1).asType().toString().equals(getCheckSubParams(taskEnum))) { + throw new IllegalArgumentException(className + + "." + + methodName + + "参数【" + + params.get(0).getSimpleName() + + "】类型错误,参数必须是" + + getCheckSubParams(taskEnum)); + } + } + } + + /** + * 字符串数组转set + * + * @param keys 注解中查到的key + */ + private Set convertSet(final String[] keys) { + if (keys == null || keys.length == 0) { + return null; + } + if (keys[0].isEmpty()) return null; + Set set = new HashSet<>(); + Collections.addAll(set, keys); + return set; + } + + private String getCheckParams(TaskEnum taskEnum) { + return taskEnum.pkg + "." + taskEnum.className; + } + + /** + * 检查任务组子任务第二个参数 + */ + private String getCheckSubParams(TaskEnum taskEnum) { + if (taskEnum == TaskEnum.DOWNLOAD_GROUP_SUB) { + return TaskEnum.DOWNLOAD_ENTITY.pkg + "." + TaskEnum.DOWNLOAD_ENTITY.className; + } + return ""; + } +} diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/PrintLog.java b/AriaCompiler/src/main/java/com/arialyy/compiler/PrintLog.java index 161a2214..2ad5d754 100644 --- a/AriaCompiler/src/main/java/com/arialyy/compiler/PrintLog.java +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/PrintLog.java @@ -55,7 +55,7 @@ class PrintLog { mMessager.printMessage(Diagnostic.Kind.ERROR, String.format(msg, args)); } - private void warning(String msg) { + public void warning(String msg) { mMessager.printMessage(Diagnostic.Kind.WARNING, msg); } diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/ProxyMethodParam.java b/AriaCompiler/src/main/java/com/arialyy/compiler/ProxyClassParam.java similarity index 75% rename from AriaCompiler/src/main/java/com/arialyy/compiler/ProxyMethodParam.java rename to AriaCompiler/src/main/java/com/arialyy/compiler/ProxyClassParam.java index 3cc813aa..ddfaaeaf 100644 --- a/AriaCompiler/src/main/java/com/arialyy/compiler/ProxyMethodParam.java +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/ProxyClassParam.java @@ -22,11 +22,30 @@ import java.util.Set; /** * Created by Aria.Lao on 2017/6/7. - * 创建代理方法的参数 + * 代理类参数 */ -class ProxyMethodParam { +class ProxyClassParam { + /** + * 代理文件名 + */ + String proxyClassName; + /** + * 被代理的类所在的包 + */ String packageName; + /** + * 被代理的类 + */ String className; + /** + * 主任务泛型参数 + */ + TaskEnum mainTaskEnum; + /** + * 子任务泛型参数 + */ + TaskEnum subTaskEnum = TaskEnum.NORMAL_ENTITY; + Set taskEnums; Map> keyMappings = new HashMap<>(); Map, String>> methods = new HashMap<>(); diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/ProxyConstance.java b/AriaCompiler/src/main/java/com/arialyy/compiler/ProxyConstance.java index 98fcb980..002d0d89 100644 --- a/AriaCompiler/src/main/java/com/arialyy/compiler/ProxyConstance.java +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/ProxyConstance.java @@ -20,6 +20,7 @@ package com.arialyy.compiler; * 扫描器常量 */ interface ProxyConstance { + boolean DEBUG = false; /** * 设置观察者的方法 */ @@ -41,10 +42,12 @@ interface ProxyConstance { String COUNT_DOWNLOAD = "download"; String COUNT_DOWNLOAD_GROUP = "downloadGroup"; + String COUNT_DOWNLOAD_GROUP_SUB = "downloadGroupSub"; String COUNT_UPLOAD = "upload"; String COUNT_METHOD_DOWNLOAD = "getDownloadCounter"; String COUNT_METHOD_DOWNLOAD_GROUP = "getDownloadGroupCounter"; + String COUNT_METHOD_DOWNLOAD_GROUP_SUB = "getDownloadGroupSubCounter"; String COUNT_METHOD_UPLOAD = "getUploadCounter"; int PRE = 0X11; diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/TaskEnum.java b/AriaCompiler/src/main/java/com/arialyy/compiler/TaskEnum.java index 7620f1df..ee0fb4c8 100644 --- a/AriaCompiler/src/main/java/com/arialyy/compiler/TaskEnum.java +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/TaskEnum.java @@ -22,9 +22,12 @@ package com.arialyy.compiler; enum TaskEnum { DOWNLOAD("com.arialyy.aria.core.download", "DownloadTask", "$$DownloadListenerProxy"), DOWNLOAD_GROUP("com.arialyy.aria.core.download", - "DownloadGroupTask", "$$DownloadGroupListenerProxy"), UPLOAD("com.arialyy.aria.core.upload", - "UploadTask", "$$UploadListenerProxy"), UPLOAD_GROUP("com.arialyy.aria.core.upload", - "UploadGroupTask", "$$UploadGroupListenerProxy"); + "DownloadGroupTask", "$$DownloadGroupListenerProxy"), DOWNLOAD_GROUP_SUB( + "com.arialyy.aria.core.download", "DownloadGroupTask", "$$DownloadGroupListenerProxy"), UPLOAD( + "com.arialyy.aria.core.upload", "UploadTask", "$$UploadListenerProxy"), UPLOAD_GROUP( + "com.arialyy.aria.core.upload", "UploadGroupTask", + "$$UploadGroupListenerProxy"), NORMAL_ENTITY("com.arialyy.aria.core.inf", "AbsNormalEntity", + ""), DOWNLOAD_ENTITY("com.arialyy.aria.core.download", "DownloadEntity", ""); String pkg, className, proxySuffix; diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/ValuesUtil.java b/AriaCompiler/src/main/java/com/arialyy/compiler/ValuesUtil.java new file mode 100644 index 00000000..f9c23f1c --- /dev/null +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/ValuesUtil.java @@ -0,0 +1,175 @@ +/* + * 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.compiler; + +import com.arialyy.annotations.Download; +import com.arialyy.annotations.DownloadGroup; +import com.arialyy.annotations.Upload; +import javax.lang.model.element.ExecutableElement; + +/** + * Created by lyy on 2017/9/6. + * 获取注解value工具 + */ +final class ValuesUtil { + /** + * 获取下载任务组子任务的的注解数据 + */ + static String[] getDownloadGroupSubValues(ExecutableElement method, int annotationType) { + String[] values = null; + switch (annotationType) { + case ProxyConstance.TASK_PRE: + values = method.getAnnotation(DownloadGroup.onSubTaskPre.class).value(); + break; + case ProxyConstance.TASK_START: + values = method.getAnnotation(DownloadGroup.onSubTaskStart.class).value(); + break; + case ProxyConstance.TASK_RUNNING: + values = method.getAnnotation(DownloadGroup.onSubTaskRunning.class).value(); + break; + case ProxyConstance.TASK_STOP: + values = method.getAnnotation(DownloadGroup.onSubTaskStop.class).value(); + break; + case ProxyConstance.TASK_COMPLETE: + values = method.getAnnotation(DownloadGroup.onSubTaskComplete.class).value(); + break; + case ProxyConstance.TASK_CANCEL: + //values = method.getAnnotation(DownloadGroup.onSubTaskCancel.class).value(); + break; + case ProxyConstance.TASK_FAIL: + values = method.getAnnotation(DownloadGroup.onSubTaskFail.class).value(); + break; + } + return values; + } + + /** + * 获取下载任务组的注解数据 + */ + static String[] getDownloadGroupValues(ExecutableElement method, int annotationType) { + String[] values = null; + switch (annotationType) { + case ProxyConstance.PRE: + values = method.getAnnotation(DownloadGroup.onPre.class).value(); + break; + case ProxyConstance.TASK_PRE: + values = method.getAnnotation(DownloadGroup.onTaskPre.class).value(); + break; + case ProxyConstance.TASK_RESUME: + values = method.getAnnotation(DownloadGroup.onTaskResume.class).value(); + break; + case ProxyConstance.TASK_START: + values = method.getAnnotation(DownloadGroup.onTaskStart.class).value(); + break; + case ProxyConstance.TASK_RUNNING: + values = method.getAnnotation(DownloadGroup.onTaskRunning.class).value(); + break; + case ProxyConstance.TASK_STOP: + values = method.getAnnotation(DownloadGroup.onTaskStop.class).value(); + break; + case ProxyConstance.TASK_COMPLETE: + values = method.getAnnotation(DownloadGroup.onTaskComplete.class).value(); + break; + case ProxyConstance.TASK_CANCEL: + values = method.getAnnotation(DownloadGroup.onTaskCancel.class).value(); + break; + case ProxyConstance.TASK_FAIL: + values = method.getAnnotation(DownloadGroup.onTaskFail.class).value(); + break; + } + return values; + } + + /** + * 获取上传的注解数据 + */ + static String[] getUploadValues(ExecutableElement method, int annotationType) { + String[] values = null; + switch (annotationType) { + case ProxyConstance.PRE: + values = method.getAnnotation(Upload.onPre.class).value(); + break; + case ProxyConstance.TASK_PRE: + //values = method.getAnnotation(Upload.onTaskPre.class).value(); + break; + case ProxyConstance.TASK_RESUME: + values = method.getAnnotation(Upload.onTaskResume.class).value(); + break; + case ProxyConstance.TASK_START: + values = method.getAnnotation(Upload.onTaskStart.class).value(); + break; + case ProxyConstance.TASK_RUNNING: + values = method.getAnnotation(Upload.onTaskRunning.class).value(); + break; + case ProxyConstance.TASK_STOP: + values = method.getAnnotation(Upload.onTaskStop.class).value(); + break; + case ProxyConstance.TASK_COMPLETE: + values = method.getAnnotation(Upload.onTaskComplete.class).value(); + break; + case ProxyConstance.TASK_CANCEL: + values = method.getAnnotation(Upload.onTaskCancel.class).value(); + break; + case ProxyConstance.TASK_FAIL: + values = method.getAnnotation(Upload.onTaskFail.class).value(); + break; + case ProxyConstance.TASK_NO_SUPPORT_BREAKPOINT: + //values = method.getAnnotation(Upload.onNoSupportBreakPoint.class).value(); + break; + } + return values; + } + + /** + * 获取下载的注解数据 + */ + static String[] getDownloadValues(ExecutableElement method, int annotationType) { + String[] values = null; + switch (annotationType) { + case ProxyConstance.PRE: + values = method.getAnnotation(Download.onPre.class).value(); + break; + case ProxyConstance.TASK_PRE: + values = method.getAnnotation(Download.onTaskPre.class).value(); + break; + case ProxyConstance.TASK_RESUME: + values = method.getAnnotation(Download.onTaskResume.class).value(); + break; + case ProxyConstance.TASK_START: + values = method.getAnnotation(Download.onTaskStart.class).value(); + break; + case ProxyConstance.TASK_RUNNING: + values = method.getAnnotation(Download.onTaskRunning.class).value(); + break; + case ProxyConstance.TASK_STOP: + values = method.getAnnotation(Download.onTaskStop.class).value(); + break; + case ProxyConstance.TASK_COMPLETE: + values = method.getAnnotation(Download.onTaskComplete.class).value(); + break; + case ProxyConstance.TASK_CANCEL: + values = method.getAnnotation(Download.onTaskCancel.class).value(); + break; + case ProxyConstance.TASK_FAIL: + values = method.getAnnotation(Download.onTaskFail.class).value(); + break; + case ProxyConstance.TASK_NO_SUPPORT_BREAKPOINT: + values = method.getAnnotation(Download.onNoSupportBreakPoint.class).value(); + break; + } + return values; + } +} diff --git a/CHINESE_README.md b/CHINESE_README.md index 391c0f1b..72a13264 100644 --- a/CHINESE_README.md +++ b/CHINESE_README.md @@ -317,6 +317,7 @@ Aria.download(this).load(DOWNLOAD_URL).setExtendField(str) -keep class com.arialyy.aria.**{*;} -keep class **$$DownloadListenerProxy{ *; } -keep class **$$UploadListenerProxy{ *; } +-keep class **$$DownloadGroupSubListenerProxy{*;} -keepclasseswithmembernames class * { @Download.* ; @Upload.* ; diff --git a/DEV_LOG.md b/DEV_LOG.md index d3b7a3f2..cf78df06 100644 --- a/DEV_LOG.md +++ b/DEV_LOG.md @@ -1,4 +1,5 @@ ## 开发日志 + + v_3.3.0 增加任务组子任务暂停和开始控制功能、修复5.0系统以上数据库多生成两个字段的bug、去掉addSchedulerListener事件 + v_3.2.26 修复任务组有时注解不起作用的问题 + v_3.2.25 修复删除任务组文件,记录无法删除的问题 + v_3.2.17 修复一个版本兼容性问题,线程中使用Aria出错问题 diff --git a/app/src/main/java/com/arialyy/simple/download/SimpleNotification.java b/app/src/main/java/com/arialyy/simple/download/SimpleNotification.java index 15c0fa88..a2e47588 100644 --- a/app/src/main/java/com/arialyy/simple/download/SimpleNotification.java +++ b/app/src/main/java/com/arialyy/simple/download/SimpleNotification.java @@ -20,6 +20,7 @@ import android.app.NotificationManager; import android.content.Context; import android.os.Environment; import android.support.v4.app.NotificationCompat; +import com.arialyy.annotations.Download; import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.download.DownloadTask; import com.arialyy.simple.R; @@ -50,14 +51,13 @@ public class SimpleNotification { .setProgress(100, 0, false) .setSmallIcon(R.mipmap.ic_launcher); mManager.notify(mNotifiyId, mBuilder.build()); - Aria.download(mContext).addSchedulerListener(new DownloadCallback(mBuilder, mManager)); + Aria.download(mContext).register(); } public void start() { Aria.download(mContext) .load(DOWNLOAD_URL) - .setDownloadPath( - Environment.getExternalStorageDirectory() + "/Download/消灭星星.apk") + .setDownloadPath(Environment.getExternalStorageDirectory() + "/Download/消灭星星.apk") .start(); } @@ -65,47 +65,31 @@ public class SimpleNotification { Aria.download(mContext).load(DOWNLOAD_URL).pause(); } - private static class DownloadCallback extends Aria.DownloadSchedulerListener { - NotificationCompat.Builder mBuilder; - NotificationManager mManager; + @Download.onTaskStart public void onTaskStart(DownloadTask task) { + } - private DownloadCallback(NotificationCompat.Builder builder, NotificationManager manager) { - mBuilder = builder; - mManager = manager; - } + @Download.onTaskPre public void onTaskPre(DownloadTask task) { + } - @Override public void onTaskStart(DownloadTask task) { - super.onTaskStart(task); - } + @Download.onTaskStop public void onTaskStop(DownloadTask task) { + } - @Override public void onTaskPre(DownloadTask task) { - super.onTaskPre(task); - } - - @Override public void onTaskStop(DownloadTask task) { - super.onTaskStop(task); - } - - @Override public void onTaskRunning(DownloadTask task) { - super.onTaskRunning(task); - long len = task.getFileSize(); - int p = (int) (task.getCurrentProgress() * 100 / len); - if (mBuilder != null) { - mBuilder.setProgress(100, p, false); - mManager.notify(mNotifiyId, mBuilder.build()); - } - } - - @Override public void onTaskComplete(DownloadTask task) { - super.onTaskComplete(task); - if (mBuilder != null) { - mBuilder.setProgress(100, 100, false); - mManager.notify(mNotifiyId, mBuilder.build()); - } - } - - @Override public void onTaskCancel(DownloadTask task) { - super.onTaskCancel(task); + @Download.onTaskRunning public void onTaskRunning(DownloadTask task) { + long len = task.getFileSize(); + int p = (int) (task.getCurrentProgress() * 100 / len); + if (mBuilder != null) { + mBuilder.setProgress(100, p, false); + mManager.notify(mNotifiyId, mBuilder.build()); } } + + @Download.onTaskComplete public void onTaskComplete(DownloadTask task) { + if (mBuilder != null) { + mBuilder.setProgress(100, 100, false); + mManager.notify(mNotifiyId, mBuilder.build()); + } + } + + @Download.onTaskCancel public void onTaskCancel(DownloadTask task) { + } } diff --git a/app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java b/app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java index 53bf464f..86f428a0 100644 --- a/app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java +++ b/app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java @@ -18,7 +18,6 @@ package com.arialyy.simple.download; import android.os.Bundle; import android.os.Environment; -import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -27,10 +26,12 @@ import android.widget.RadioGroup; import android.widget.Toast; import butterknife.Bind; import com.arialyy.annotations.Download; +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.aria.core.download.DownloadTarget; 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.util.CommonUtil; import com.arialyy.frame.util.show.L; @@ -45,7 +46,8 @@ public class SingleTaskActivity extends BaseActivity { private static final String DOWNLOAD_URL = //"http://kotlinlang.org/docs/kotlin-docs.pdf"; //"https://atom-installer.github.com/v1.13.0/AtomSetup.exe?s=1484074138&ext=.exe"; - "http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk"; + //"http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk"; + "http://sitcac.daxincf.cn/wp-content/uploads/swift_vido/01/element.mp4"; //"http://120.25.196.56:8000/filereq?id=15692406294&ipncid=105635&client=android&filename=20170819185541.avi"; //"http://down2.xiaoshuofuwuqi.com/d/file/filetxt/20170608/14/%BA%DA%CE%D7%CA%A6%E1%C8%C6%F0.txt"; //"http://tinghuaapp.oss-cn-shanghai.aliyuncs.com/20170612201739607815"; 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..474557b1 --- /dev/null +++ b/app/src/main/java/com/arialyy/simple/download/group/ChildHandleDialog.java @@ -0,0 +1,149 @@ +/* + * 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.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.frame.util.show.L; +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 List mUrls; + private DownloadEntity mChildEntity; + + public ChildHandleDialog(Context context, List urls, DownloadEntity childEntity) { + super(context); + setStyle(STYLE_NO_TITLE, R.style.Theme_Light_Dialog); + mChildEntity = childEntity; + mGroupName = "任务组测试"; + mUrls = urls; + 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.onSubTaskRunning void onSubTaskRunning(DownloadGroupTask groupTask, + DownloadEntity subEntity) { + if (!subEntity.getUrl().equals(mChildEntity.getUrl())) return; + mPb.setProgress(subEntity.getPercent()); + } + + @DownloadGroup.onSubTaskPre void onSubTaskPre(DownloadGroupTask groupTask, + DownloadEntity subEntity) { + if (!subEntity.getUrl().equals(mChildEntity.getUrl())) return; + L.d(TAG, subEntity.getPercent() + ""); + } + + @DownloadGroup.onSubTaskStop void onSubTaskStop(DownloadGroupTask groupTask, + DownloadEntity subEntity) { + if (!subEntity.getUrl().equals(mChildEntity.getUrl())) return; + mSub.setText("子任务:" + mChildName + ",状态:任务停止"); + } + + @DownloadGroup.onSubTaskStart void onSubTaskStart(DownloadGroupTask groupTask, + DownloadEntity subEntity) { + if (!subEntity.getUrl().equals(mChildEntity.getUrl())) return; + mSub.setText("子任务:" + mChildName + ",状态:下载中"); + } + + //@DownloadGroup.onSubTaskCancel void onSubTaskCancel(DownloadGroupTask groupTask, + // DownloadEntity subEntity) { + // mSub.setText("子任务:" + mChildName + ",状态:取消下载"); + //} + + @DownloadGroup.onSubTaskComplete void onSubTaskComplete(DownloadGroupTask groupTask, + DownloadEntity subEntity) { + if (!subEntity.getUrl().equals(mChildEntity.getUrl())) return; + mSub.setText("子任务:" + mChildName + ",状态:任务完成"); + mPb.setProgress(100); + } + + @DownloadGroup.onSubTaskFail void onSubTaskFail(DownloadGroupTask groupTask, + DownloadEntity subEntity) { + if (!subEntity.getUrl().equals(mChildEntity.getUrl())) return; + L.d(TAG, subEntity.getPercent() + ""); + } + + @Override protected int setLayoutId() { + return R.layout.dialog_sub_task_handler; + } + + @OnClick({ R.id.start, R.id.stop }) void onClick(View view) { + switch (view.getId()) { + case R.id.start: + Aria.download(this).load(mUrls).getSubTaskManager().startSubTask(mChildEntity.getUrl()); + break; + case R.id.stop: + Aria.download(this).load(mUrls).getSubTaskManager().stopSubTask(mChildEntity.getUrl()); + break; + //case R.id.cancel: + // Aria.download(this).load(mUrls).getSubTaskManager().cancelSubTask(mChildEntity.getUrl()); + // 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..66b9034b 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,14 +17,12 @@ package com.arialyy.simple.download.group; import android.os.Bundle; import android.os.Environment; -import android.os.Handler; -import android.util.Log; +import android.support.design.widget.FloatingActionButton; 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.DownloadEntity; import com.arialyy.aria.core.download.DownloadGroupEntity; import com.arialyy.aria.core.download.DownloadGroupTask; import com.arialyy.aria.core.download.DownloadGroupTaskEntity; @@ -49,7 +47,6 @@ public class DownloadGroupActivity extends BaseActivity " + task.getPercent()); getBinding().setProgress(task.getPercent()); getBinding().setSpeed(task.getConvertSpeed()); mChildList.updateChildProgress(task.getEntity().getSubTask()); @@ -141,4 +150,5 @@ public class DownloadGroupActivity extends BaseActivity { dialog.show(getSupportFragmentManager(), "download_num"); break; case R.id.stop_all: - Aria.download(this).stopAllTask(); + //Aria.download(this).stopAllTask(); + Aria.download(this).removeAllTask(true); break; case R.id.turn: startActivity(new Intent(this, MultiDownloadActivity.class)); 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..29120818 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..d833226f --- /dev/null +++ b/app/src/main/res/layout/dialog_sub_task_handler.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + +