增加允许不使用apt直接通过实现监听器来回调下载进度更新,该功能由[chenfei0928](https://github.com/chenfei0928)提交,感谢他的pr。如果注解不生效,只需要实现接口便可

修复m3u8任务地址错误时,无法删除实体的问题 https://github.com/AriaLyy/Aria/issues/71://github.com/AriaLyy/Aria/issues/712
pull/789/head
laoyuyu 4 years ago
parent 5f60b9ed57
commit fed2b4111f
  1. 19
      .github/stale.yml
  2. 26
      Aria/src/main/java/com/arialyy/aria/core/AriaManager.java
  3. 12
      Aria/src/main/java/com/arialyy/aria/core/common/ProxyHelper.java
  4. 9
      Aria/src/main/java/com/arialyy/aria/core/download/CheckDEntityUtil.java
  5. 6
      Aria/src/main/java/com/arialyy/aria/core/download/CheckDGEntityUtil.java
  6. 15
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTaskListener.java
  7. 19
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java
  8. 15
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskListener.java
  9. 1
      Aria/src/main/java/com/arialyy/aria/core/download/target/DNormalConfigHandler.java
  10. 2
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsReceiver.java
  11. 15
      Aria/src/main/java/com/arialyy/aria/core/scheduler/AptM3U8PeerTaskListener.java
  12. 2
      Aria/src/main/java/com/arialyy/aria/core/scheduler/AptNormalTaskListener.java
  13. 68
      Aria/src/main/java/com/arialyy/aria/core/scheduler/AptSubTaskListener.java
  14. 10
      Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadTaskInternalListenerInterface.java
  15. 15
      Aria/src/main/java/com/arialyy/aria/core/scheduler/M3U8PeerTaskListener.java
  16. 3
      Aria/src/main/java/com/arialyy/aria/core/scheduler/NormalTaskListenerInterface.java
  17. 45
      Aria/src/main/java/com/arialyy/aria/core/scheduler/SubTaskListener.java
  18. 42
      Aria/src/main/java/com/arialyy/aria/core/scheduler/SubTaskListenerInterface.java
  19. 25
      Aria/src/main/java/com/arialyy/aria/core/scheduler/TaskInternalListenerInterface.java
  20. 10
      Aria/src/main/java/com/arialyy/aria/core/scheduler/TaskSchedulers.java
  21. 8
      Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java
  22. 15
      Aria/src/main/java/com/arialyy/aria/core/upload/UploadTaskListener.java
  23. 10
      AriaAnnotations/src/main/java/com/arialyy/annotations/TaskEnum.java
  24. 7
      DEV_LOG.md
  25. 341
      ENGLISH_README.md
  26. 2
      PublicComponent/src/main/java/com/arialyy/aria/core/config/DownloadConfig.java
  27. 2
      PublicComponent/src/main/java/com/arialyy/aria/core/config/XMLReader.java
  28. 2
      PublicComponent/src/main/java/com/arialyy/aria/orm/DbEntity.java
  29. 28
      PublicComponent/src/main/java/com/arialyy/aria/util/CommonUtil.java
  30. 16
      PublicComponent/src/main/java/com/arialyy/aria/util/DeleteDGRecord.java
  31. 8
      PublicComponent/src/main/java/com/arialyy/aria/util/DeleteDRecord.java
  32. 11
      PublicComponent/src/main/java/com/arialyy/aria/util/DeleteM3u8Record.java
  33. 6
      PublicComponent/src/main/java/com/arialyy/aria/util/DeleteURecord.java
  34. 10
      README.md
  35. 3
      app/src/main/AndroidManifest.xml
  36. 9
      app/src/main/assets/aria_config.xml
  37. 9
      app/src/main/java/com/arialyy/simple/core/download/DownloadActivity.java
  38. 29
      app/src/main/java/com/arialyy/simple/core/download/SingleTaskActivity.java
  39. 104
      app/src/main/java/com/arialyy/simple/core/download/fragment/DownloadFragment.java
  40. 56
      app/src/main/java/com/arialyy/simple/core/download/fragment/MultiFragmentActivity.kt
  41. 124
      app/src/main/java/com/arialyy/simple/core/download/fragment/MultiItemFragment.java
  42. 3
      app/src/main/java/com/arialyy/simple/core/download/m3u8/M3U8VodDLoadActivity.java
  43. 3
      app/src/main/java/com/arialyy/simple/core/download/m3u8/M3U8VodModule.java
  44. 5
      app/src/main/java/com/arialyy/simple/core/download/mutil/MultiDownloadActivity.java
  45. 2
      app/src/main/java/com/arialyy/simple/core/download/mutil/MultiTaskListActivity.java
  46. 2
      app/src/main/java/com/arialyy/simple/widget/ProgressLayout.java
  47. 37
      app/src/main/res/layout/activity_multi_fragment_activity.xml
  48. 56
      app/src/main/res/layout/fragment_download.xml
  49. 2
      app/src/main/res/values/strings.xml
  50. 2
      build.gradle

@ -0,0 +1,19 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 30
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- bug
- adaptation
- new features
- suggest
# Label to use when marking an issue as stale
staleLabel: wontfix
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

@ -46,6 +46,8 @@ import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.DeleteURecord; import com.arialyy.aria.util.DeleteURecord;
import com.arialyy.aria.util.RecordUtil; import com.arialyy.aria.util.RecordUtil;
import java.io.File; import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -315,8 +317,28 @@ import java.util.concurrent.ConcurrentHashMap;
Map.Entry<String, AbsReceiver> entry = iter.next(); Map.Entry<String, AbsReceiver> entry = iter.next();
String key = entry.getKey(); String key = entry.getKey();
AbsReceiver receiver = entry.getValue(); AbsReceiver receiver = entry.getValue();
if ((receiver.isLocalOrAnonymousClass || receiver.isFragment())
&& key.startsWith(obj.getClass().getName())) { if (receiver.isFragment()){
Method method = CommonUtil.getMethod(receiver.obj.getClass(), "getActivity");
if (method != null){
try {
Activity ac = (Activity) method.invoke(receiver.obj);
if (ac == obj){
receiver.destroy();
iter.remove();
continue;
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
// 处理内部类的
String objClsName = obj.getClass().getName();
if (receiver.isLocalOrAnonymousClass && key.startsWith(objClsName)) {
receiver.destroy(); receiver.destroy();
iter.remove(); iter.remove();
continue; continue;

@ -18,9 +18,9 @@ package com.arialyy.aria.core.common;
import com.arialyy.annotations.TaskEnum; import com.arialyy.annotations.TaskEnum;
import com.arialyy.aria.core.download.DownloadGroupTaskListener; import com.arialyy.aria.core.download.DownloadGroupTaskListener;
import com.arialyy.aria.core.download.DownloadTaskListener; import com.arialyy.aria.core.download.DownloadTaskListener;
import com.arialyy.aria.core.scheduler.DownloadTaskInternalListenerInterface; import com.arialyy.aria.core.scheduler.TaskInternalListenerInterface;
import com.arialyy.aria.core.scheduler.M3U8PeerTaskListenerInterface; import com.arialyy.aria.core.scheduler.M3U8PeerTaskListener;
import com.arialyy.aria.core.scheduler.SubTaskListenerInterface; import com.arialyy.aria.core.scheduler.SubTaskListener;
import com.arialyy.aria.core.upload.UploadTaskListener; import com.arialyy.aria.core.upload.UploadTaskListener;
import java.util.HashSet; import java.util.HashSet;
@ -117,7 +117,7 @@ public class ProxyHelper {
} }
private Set<Integer> checkProxyTypeByInterface(Class clazz) { private Set<Integer> checkProxyTypeByInterface(Class clazz) {
if (!DownloadTaskInternalListenerInterface.class.isAssignableFrom(clazz)) { if (!TaskInternalListenerInterface.class.isAssignableFrom(clazz)) {
return null; return null;
} }
Set<Integer> result = new HashSet<>(); Set<Integer> result = new HashSet<>();
@ -132,11 +132,11 @@ public class ProxyHelper {
result.add(PROXY_TYPE_UPLOAD); result.add(PROXY_TYPE_UPLOAD);
} }
if (M3U8PeerTaskListenerInterface.class.isAssignableFrom(clazz)) { if (M3U8PeerTaskListener.class.isAssignableFrom(clazz)) {
result.add(PROXY_TYPE_M3U8_PEER); result.add(PROXY_TYPE_M3U8_PEER);
} }
if (SubTaskListenerInterface.class.isAssignableFrom(clazz)) { if (SubTaskListener.class.isAssignableFrom(clazz)) {
result.add(PROXY_TYPE_DOWNLOAD_GROUP_SUB); result.add(PROXY_TYPE_DOWNLOAD_GROUP_SUB);
} }
return result; return result;

@ -21,6 +21,7 @@ import com.arialyy.aria.core.inf.ICheckEntityUtil;
import com.arialyy.aria.core.inf.IOptionConstant; import com.arialyy.aria.core.inf.IOptionConstant;
import com.arialyy.aria.core.inf.ITargetHandler; import com.arialyy.aria.core.inf.ITargetHandler;
import com.arialyy.aria.core.wrapper.ITaskWrapper; import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CheckUtil; import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
@ -135,8 +136,16 @@ public class CheckDEntityUtil implements ICheckEntityUtil {
/** /**
* 检查路径冲突 * 检查路径冲突
* @return true 路径没有冲突
*/ */
private boolean checkPathConflicts(String filePath) { private boolean checkPathConflicts(String filePath) {
DownloadEntity de = DbEntity.findFirst(DownloadEntity.class, "downloadPath=?", filePath);
if (de != null && de.getUrl().equals(mEntity.getUrl())){
mEntity.rowID = de.rowID;
mEntity.setFilePath(filePath);
mEntity.setFileName(new File(filePath).getName());
return true;
}
//设置文件保存路径,如果新文件路径和旧文件路径不同,则修改路径 //设置文件保存路径,如果新文件路径和旧文件路径不同,则修改路径
if (!filePath.equals(mEntity.getFilePath())) { if (!filePath.equals(mEntity.getFilePath())) {
// 检查路径冲突 // 检查路径冲突

@ -123,6 +123,12 @@ public class CheckDGEntityUtil implements ICheckEntityUtil {
* @return false 任务不再执行true 任务继续执行 * @return false 任务不再执行true 任务继续执行
*/ */
private boolean checkGroupHash(boolean isIgnoreTaskOccupy, String groupHash) { private boolean checkGroupHash(boolean isIgnoreTaskOccupy, String groupHash) {
DownloadGroupEntity dge = DbEntity.findFirst(DownloadGroupEntity.class, "groupHash=?", groupHash);
if (dge != null && dge.getGroupHash().equals(mEntity.getGroupHash())){
mEntity.rowID = dge.rowID;
return true;
}
if (DbEntity.checkDataExist(DownloadGroupEntity.class, "groupHash=?", groupHash)) { if (DbEntity.checkDataExist(DownloadGroupEntity.class, "groupHash=?", groupHash)) {
if (!isIgnoreTaskOccupy) { if (!isIgnoreTaskOccupy) {
ALog.e(TAG, String.format("下载失败,数据库中已存在相同的url的组任务,groupHash = %s", groupHash)); ALog.e(TAG, String.format("下载失败,数据库中已存在相同的url的组任务,groupHash = %s", groupHash));

@ -1,3 +1,18 @@
/*
* 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; package com.arialyy.aria.core.download;
import com.arialyy.aria.core.scheduler.NormalTaskListenerInterface; import com.arialyy.aria.core.scheduler.NormalTaskListenerInterface;

@ -38,6 +38,9 @@ import com.arialyy.aria.core.inf.AbsReceiver;
import com.arialyy.aria.core.inf.ReceiverType; import com.arialyy.aria.core.inf.ReceiverType;
import com.arialyy.aria.core.queue.DGroupTaskQueue; import com.arialyy.aria.core.queue.DGroupTaskQueue;
import com.arialyy.aria.core.queue.DTaskQueue; import com.arialyy.aria.core.queue.DTaskQueue;
import com.arialyy.aria.core.scheduler.M3U8PeerTaskListener;
import com.arialyy.aria.core.scheduler.SubTaskListener;
import com.arialyy.aria.core.scheduler.TaskInternalListenerInterface;
import com.arialyy.aria.core.scheduler.TaskSchedulers; import com.arialyy.aria.core.scheduler.TaskSchedulers;
import com.arialyy.aria.core.task.ITask; import com.arialyy.aria.core.task.ITask;
import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.orm.DbEntity;
@ -171,6 +174,22 @@ public class DownloadReceiver extends AbsReceiver {
ALog.e(TAG, String.format("register【%s】观察者为空", getTargetName())); ALog.e(TAG, String.format("register【%s】观察者为空", getTargetName()));
return; return;
} }
if (obj instanceof TaskInternalListenerInterface){
if (obj instanceof DownloadTaskListener){
TaskSchedulers.getInstance().register(obj, TaskEnum.DOWNLOAD);
}
if (obj instanceof DownloadGroupTaskListener){
TaskSchedulers.getInstance().register(obj, TaskEnum.DOWNLOAD_GROUP);
}
if (obj instanceof M3U8PeerTaskListener){
TaskSchedulers.getInstance().register(obj, TaskEnum.M3U8_PEER);
}
if (obj instanceof SubTaskListener){
TaskSchedulers.getInstance().register(obj, TaskEnum.DOWNLOAD_GROUP_SUB);
}
return;
}
Set<Integer> set = ProxyHelper.getInstance().checkProxyType(obj.getClass()); Set<Integer> set = ProxyHelper.getInstance().checkProxyType(obj.getClass());
if (set != null && !set.isEmpty()) { if (set != null && !set.isEmpty()) {
for (Integer type : set) { for (Integer type : set) {

@ -1,3 +1,18 @@
/*
* 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; package com.arialyy.aria.core.download;
import com.arialyy.aria.core.scheduler.NormalTaskListenerInterface; import com.arialyy.aria.core.scheduler.NormalTaskListenerInterface;

@ -98,6 +98,7 @@ class DNormalConfigHandler<TARGET extends AbsTarget> implements IConfigHandler {
void setUrl(String url) { void setUrl(String url) {
mEntity.setUrl(url); mEntity.setUrl(url);
mWrapper.setTempUrl(url);
} }
String getUrl() { String getUrl() {

@ -37,7 +37,7 @@ public abstract class AbsReceiver implements IReceiver {
/** /**
* 观察者对象 * 观察者对象
*/ */
protected Object obj; public Object obj;
/** /**
* 观察者对象类的完整名称 * 观察者对象类的完整名称

@ -19,11 +19,18 @@ package com.arialyy.aria.core.scheduler;
* Created by Aria.Lao on 2019/6/26. * Created by Aria.Lao on 2019/6/26.
* m3u8切片事件回调类 * m3u8切片事件回调类
*/ */
public interface M3U8PeerTaskListenerInterface extends DownloadTaskInternalListenerInterface { public class AptM3U8PeerTaskListener implements M3U8PeerTaskListener, ISchedulerListener{
public void onPeerStart(final String m3u8Url, final String peerPath, final int peerIndex); @Override public void onPeerStart(final String m3u8Url, final String peerPath, final int peerIndex) {
}
public void onPeerComplete(final String m3u8Url, final String peerPath, final int peerIndex); @Override public void onPeerComplete(final String m3u8Url, final String peerPath, final int peerIndex) {
}
public void onPeerFail(final String m3u8Url, final String peerPath, final int peerIndex); @Override public void onPeerFail(final String m3u8Url, final String peerPath, final int peerIndex) {
}
@Override public void setListener(Object obj) {
}
} }

@ -24,7 +24,7 @@ import com.arialyy.aria.core.task.UploadTask;
* Created by Aria.Lao on 2017/6/7. * Created by Aria.Lao on 2017/6/7.
* 普通任务事件{@link DownloadTask}{@link UploadTask}{@link DownloadGroupTask}回调类 * 普通任务事件{@link DownloadTask}{@link UploadTask}{@link DownloadGroupTask}回调类
*/ */
public class NormalTaskListener<TASK extends ITask> implements NormalTaskListenerInterface<TASK>, ISchedulerListener { public class AptNormalTaskListener<TASK extends ITask> implements NormalTaskListenerInterface<TASK>, ISchedulerListener {
/** /**
* 队列已经满了继续创建任务将会回调该方法 * 队列已经满了继续创建任务将会回调该方法

@ -0,0 +1,68 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.scheduler;
import com.arialyy.aria.core.common.AbsNormalEntity;
import com.arialyy.aria.core.task.ITask;
/**
* Created by Aria.Lao on 2019/6/26.
* 子任务事件回调类
*/
public class AptSubTaskListener<TASK extends ITask, SUB_ENTITY extends AbsNormalEntity>
implements SubTaskListener<TASK, SUB_ENTITY>, ISchedulerListener {
@Override public void onNoSupportBreakPoint(TASK task) {
}
@Override public void onSubTaskPre(TASK task, SUB_ENTITY subTask) {
}
@Override public void onSubTaskStart(TASK task, SUB_ENTITY subTask) {
}
@Override public void onSubTaskStop(TASK task, SUB_ENTITY subTask) {
}
@Override public void onSubTaskCancel(TASK task, SUB_ENTITY subTask) {
}
@Override public void onSubTaskComplete(TASK task, SUB_ENTITY subTask) {
}
@Deprecated
public void onSubTaskFail(TASK task, SUB_ENTITY subTask) {
}
@Override public void onSubTaskFail(TASK task, SUB_ENTITY subTask, Exception e) {
}
@Override public void onSubTaskRunning(TASK task, SUB_ENTITY subTask) {
}
@Override public void setListener(Object obj) {
}
}

@ -1,10 +0,0 @@
package com.arialyy.aria.core.scheduler;
/**
* 直接实现监听器回调接口的基类不对外部直接开放仅作为内部监听器的父接口使用
*
* @author ChenFei(chenfei0928 @ gmail.com)
* @date 2020-07-07 15:18
*/
public interface DownloadTaskInternalListenerInterface {
}

@ -19,18 +19,11 @@ package com.arialyy.aria.core.scheduler;
* Created by Aria.Lao on 2019/6/26. * Created by Aria.Lao on 2019/6/26.
* m3u8切片事件回调类 * m3u8切片事件回调类
*/ */
public class M3U8PeerTaskListener implements M3U8PeerTaskListenerInterface, ISchedulerListener{ public interface M3U8PeerTaskListener extends TaskInternalListenerInterface {
@Override public void onPeerStart(final String m3u8Url, final String peerPath, final int peerIndex) { public void onPeerStart(final String m3u8Url, final String peerPath, final int peerIndex);
}
@Override public void onPeerComplete(final String m3u8Url, final String peerPath, final int peerIndex) { public void onPeerComplete(final String m3u8Url, final String peerPath, final int peerIndex);
}
@Override public void onPeerFail(final String m3u8Url, final String peerPath, final int peerIndex) { public void onPeerFail(final String m3u8Url, final String peerPath, final int peerIndex);
}
@Override public void setListener(Object obj) {
}
} }

@ -24,7 +24,8 @@ import com.arialyy.aria.core.task.UploadTask;
* Created by Aria.Lao on 2017/6/7. * Created by Aria.Lao on 2017/6/7.
* 普通任务事件{@link DownloadTask}{@link UploadTask}{@link DownloadGroupTask}回调类 * 普通任务事件{@link DownloadTask}{@link UploadTask}{@link DownloadGroupTask}回调类
*/ */
public interface NormalTaskListenerInterface<TASK extends ITask> extends DownloadTaskInternalListenerInterface { public interface NormalTaskListenerInterface<TASK extends ITask> extends
TaskInternalListenerInterface {
/** /**
* 队列已经满了继续创建任务将会回调该方法 * 队列已经满了继续创建任务将会回调该方法

@ -22,47 +22,22 @@ import com.arialyy.aria.core.task.ITask;
* Created by Aria.Lao on 2019/6/26. * Created by Aria.Lao on 2019/6/26.
* 子任务事件回调类 * 子任务事件回调类
*/ */
public class SubTaskListener<TASK extends ITask, SUB_ENTITY extends AbsNormalEntity> public interface SubTaskListener<TASK extends ITask, SUB_ENTITY extends AbsNormalEntity> extends
implements SubTaskListenerInterface<TASK, SUB_ENTITY>, ISchedulerListener { TaskInternalListenerInterface {
@Override public void onNoSupportBreakPoint(TASK task) { public void onNoSupportBreakPoint(TASK task);
} public void onSubTaskPre(TASK task, SUB_ENTITY subTask);
@Override public void onSubTaskPre(TASK task, SUB_ENTITY subTask) { public void onSubTaskStart(TASK task, SUB_ENTITY subTask);
} public void onSubTaskStop(TASK task, SUB_ENTITY subTask);
@Override public void onSubTaskStart(TASK task, SUB_ENTITY subTask) { public void onSubTaskCancel(TASK task, SUB_ENTITY subTask);
} public void onSubTaskComplete(TASK task, SUB_ENTITY subTask);
@Override public void onSubTaskStop(TASK task, SUB_ENTITY subTask) { public void onSubTaskFail(TASK task, SUB_ENTITY subTask, Exception e);
} public void onSubTaskRunning(TASK task, SUB_ENTITY subTask);
@Override public void onSubTaskCancel(TASK task, SUB_ENTITY subTask) {
}
@Override public void onSubTaskComplete(TASK task, SUB_ENTITY subTask) {
}
@Deprecated
public void onSubTaskFail(TASK task, SUB_ENTITY subTask) {
}
@Override public void onSubTaskFail(TASK task, SUB_ENTITY subTask, Exception e) {
}
@Override public void onSubTaskRunning(TASK task, SUB_ENTITY subTask) {
}
@Override public void setListener(Object obj) {
}
} }

@ -1,42 +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.scheduler;
import com.arialyy.aria.core.common.AbsNormalEntity;
import com.arialyy.aria.core.task.ITask;
/**
* Created by Aria.Lao on 2019/6/26.
* 子任务事件回调类
*/
public interface SubTaskListenerInterface<TASK extends ITask, SUB_ENTITY extends AbsNormalEntity> extends DownloadTaskInternalListenerInterface {
public void onNoSupportBreakPoint(TASK task);
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, Exception e);
public void onSubTaskRunning(TASK task, SUB_ENTITY subTask);
}

@ -0,0 +1,25 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.scheduler;
/**
* 直接实现监听器回调接口的基类不对外部直接开放仅作为内部监听器的父接口使用
*
* @author ChenFei(chenfei0928 @ gmail.com)
* @date 2020-07-07 15:18
*/
public interface TaskInternalListenerInterface {
}

@ -106,7 +106,7 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
} }
if (!hasProxyListener(listeners, taskEnum)) { if (!hasProxyListener(listeners, taskEnum)) {
if (obj instanceof DownloadTaskInternalListenerInterface) { if (obj instanceof TaskInternalListenerInterface) {
listeners.put(taskEnum, obj); listeners.put(taskEnum, obj);
return; return;
} }
@ -209,8 +209,8 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
if (listeners == null || listeners.isEmpty()) { if (listeners == null || listeners.isEmpty()) {
continue; continue;
} }
M3U8PeerTaskListenerInterface listener = M3U8PeerTaskListener listener =
(M3U8PeerTaskListenerInterface) listeners.get(TaskEnum.M3U8_PEER); (M3U8PeerTaskListener) listeners.get(TaskEnum.M3U8_PEER);
if (listener == null) { if (listener == null) {
continue; continue;
} }
@ -258,8 +258,8 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
if (listeners == null || listeners.isEmpty()) { if (listeners == null || listeners.isEmpty()) {
continue; continue;
} }
SubTaskListenerInterface<TASK, AbsNormalEntity> listener = SubTaskListener<TASK, AbsNormalEntity> listener =
(SubTaskListenerInterface<TASK, AbsNormalEntity>) listeners.get(TaskEnum.DOWNLOAD_GROUP_SUB); (SubTaskListener<TASK, AbsNormalEntity>) listeners.get(TaskEnum.DOWNLOAD_GROUP_SUB);
if (listener == null) { if (listener == null) {
continue; continue;
} }

@ -29,6 +29,7 @@ import com.arialyy.aria.core.event.EventMsgUtil;
import com.arialyy.aria.core.inf.AbsReceiver; import com.arialyy.aria.core.inf.AbsReceiver;
import com.arialyy.aria.core.inf.ReceiverType; import com.arialyy.aria.core.inf.ReceiverType;
import com.arialyy.aria.core.queue.UTaskQueue; import com.arialyy.aria.core.queue.UTaskQueue;
import com.arialyy.aria.core.scheduler.TaskInternalListenerInterface;
import com.arialyy.aria.core.scheduler.TaskSchedulers; import com.arialyy.aria.core.scheduler.TaskSchedulers;
import com.arialyy.aria.core.task.ITask; import com.arialyy.aria.core.task.ITask;
import com.arialyy.aria.core.upload.target.FtpBuilderTarget; import com.arialyy.aria.core.upload.target.FtpBuilderTarget;
@ -270,6 +271,13 @@ public class UploadReceiver extends AbsReceiver {
ALog.e(TAG, String.format("【%s】观察者为空", getTargetName())); ALog.e(TAG, String.format("【%s】观察者为空", getTargetName()));
return; return;
} }
if (obj instanceof TaskInternalListenerInterface){
if (obj instanceof UploadTaskListener){
TaskSchedulers.getInstance().register(obj, TaskEnum.UPLOAD);
}
return;
}
Set<Integer> set = ProxyHelper.getInstance().checkProxyType(obj.getClass()); Set<Integer> set = ProxyHelper.getInstance().checkProxyType(obj.getClass());
if (set != null && !set.isEmpty()) { if (set != null && !set.isEmpty()) {
for (Integer type : set) { for (Integer type : set) {

@ -1,3 +1,18 @@
/*
* 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.upload; package com.arialyy.aria.core.upload;
import com.arialyy.aria.core.scheduler.NormalTaskListenerInterface; import com.arialyy.aria.core.scheduler.NormalTaskListenerInterface;

@ -21,15 +21,15 @@ package com.arialyy.annotations;
*/ */
public enum TaskEnum { public enum TaskEnum {
DOWNLOAD("com.arialyy.aria.core.task", "DownloadTask", "$$DownloadListenerProxy", DOWNLOAD("com.arialyy.aria.core.task", "DownloadTask", "$$DownloadListenerProxy",
"NormalTaskListener"), "AptNormalTaskListener"),
DOWNLOAD_GROUP("com.arialyy.aria.core.task", "DownloadGroupTask", DOWNLOAD_GROUP("com.arialyy.aria.core.task", "DownloadGroupTask",
"$$DownloadGroupListenerProxy", "NormalTaskListener"), "$$DownloadGroupListenerProxy", "AptNormalTaskListener"),
DOWNLOAD_GROUP_SUB("com.arialyy.aria.core.task", "DownloadGroupTask", DOWNLOAD_GROUP_SUB("com.arialyy.aria.core.task", "DownloadGroupTask",
"$$DGSubListenerProxy", "SubTaskListener"), "$$DGSubListenerProxy", "AptSubTaskListener"),
UPLOAD("com.arialyy.aria.core.task", "UploadTask", "$$UploadListenerProxy", UPLOAD("com.arialyy.aria.core.task", "UploadTask", "$$UploadListenerProxy",
"NormalTaskListener"), "AptNormalTaskListener"),
M3U8_PEER("com.arialyy.aria.core.task", "DownloadTask", "$$M3U8PeerListenerProxy", M3U8_PEER("com.arialyy.aria.core.task", "DownloadTask", "$$M3U8PeerListenerProxy",
"M3U8PeerTaskListener"); "AptM3U8PeerTaskListener");
public String pkg, className, proxySuffix, proxySuperClass; public String pkg, className, proxySuffix, proxySuperClass;

@ -2,8 +2,11 @@
+ v_3.8.11 + v_3.8.11
- 修复一个正则表达式导致的文件名保存号异常问题 https://github.com/AriaLyy/Aria/issues/715 - 修复一个正则表达式导致的文件名保存号异常问题 https://github.com/AriaLyy/Aria/issues/715
- 修复一个匿名内部类中的内存溢出的问题 https://github.com/AriaLyy/Aria/issues/705 - 修复一个匿名内部类中的内存溢出的问题 https://github.com/AriaLyy/Aria/issues/705
- m3u8密钥下载地址转换器增加ts列表的url地址 https://github.com/AriaLyy/Aria/issues/718 - 修复同一个url地址的任务提示路径冲突的问题
- 现在http文件下载将使用HEAD请求获取文件大小,配置文件增加 <useHeadRequest value="false"/> - 修复m3u8任务地址错误时,无法删除实体的问题 https://github.com/AriaLyy/Aria/issues/712
- 增加m3u8密钥下载地址转换器增加ts列表的url地址 https://github.com/AriaLyy/Aria/issues/718
- 增加现在http文件下载将使用HEAD请求获取文件大小,配置文件增加 <useHeadRequest value="true"/>
- 增加允许不使用apt直接通过实现监听器来回调下载进度更新,该功能由[chenfei0928](https://github.com/chenfei0928)提交,感谢他的pr。如果注解不生效,只需要实现`DownloadListener`接口便可
+ v_3.8.10 (2020/6/26) + v_3.8.10 (2020/6/26)
- fix bug https://github.com/AriaLyy/Aria/issues/703 - fix bug https://github.com/AriaLyy/Aria/issues/703
- fix bug https://github.com/AriaLyy/Aria/issues/702 - fix bug https://github.com/AriaLyy/Aria/issues/702

@ -1,291 +1,172 @@
# Aria # Aria
![图标](https://github.com/AriaLyy/DownloadUtil/blob/master/app/src/main/res/mipmap-hdpi/ic_launcher.png)</br> ![图标](https://github.com/AriaLyy/DownloadUtil/blob/master/img/ic_launcher.png)</br>
## [ENGLISH DOC](https://github.com/AriaLyy/Aria/blob/master/ENGLISH_README.md)</br>
## [中文文档](https://aria.laoyuyu.me/aria_doc)
The Aria project originated from the need for file download management encountered in work. At that time, the pain of being downloaded was unhappy. Since then, a simple and easy-to-use, stable and efficient download framework has emerged. Aria has experienced 1.0 to 3.0 development. , It is getting closer and closer to the goal set at the beginning.
Aria has the following characteristics:
+ Simple and convenient
- Can be used in Activity, Service, Fragment, Dialog, popupWindow, Notification and other components
- Support HTTP\FTP resumable download, multi-task automatic scheduling
- Support multi-file package download, multi-file sharing the same progress (eg: video + cover + subtitles)
- Support downloading FTP folder
- Support HTTP form upload
- Support file FTP resumable upload
- Support FTPS resumable upload, [see](https://aria.laoyuyu.me/aria_doc/api/ftp_params.html#%E4%BA%8C%E3%80%81ftps)
- Support SFTP resumable upload, [sftp download](https://aria.laoyuyu.me/aria_doc/download/sftp_normal.html), [sftp upload](https://aria.laoyuyu.me/aria_doc/upload /sftp_normal.html)
+ Support https address download
- It is easy to set the CA certificate information in the configuration file
+ Support [Multi-threaded download in blocks](https://aria.laoyuyu.me/aria_doc/start/config.html), which can more effectively play the machine IO performance
+ Support 300, 301, 302 redirect download link download
+ Support file download of m3u8 and hls protocol [m3u8 download](https://aria.laoyuyu.me/aria_doc/download/m3u8.html)
+ Support m3u8 download support, [click to view details](https://aria.laoyuyu.me/aria_doc/download/m3u8_vod.html)
+ The download support file length increases dynamically, and the file download initialization will no longer occupy too much memory space, see [Dynamic Length Configuration](https://aria.laoyuyu.me/aria_doc/start/config.html#%E4% B8%8B%E8%BD%BD%E5%8A%A8%E6%80%81%E6%96%87%E4%BB%B6%E8%AF%B4%E6%98%8E)
## [中文文档](https://github.com/AriaLyy/Aria/blob/master/CHINESE_README.md) [How to use Aria?] (#use)
If you think Aria is helpful to you, your star and issues will be my greatest support. Of course, you are also very welcome to PR, [PR Method](https://www.zhihu.com/question/21682976/answer /79489643)`^_^`
Aria project is from the moment taht the work encountered in a file download management needs adn i was tortured at the time of the pain.</br> ## Example
Since then i have a idea which is to program a simple and easy to use,stable and efficient download framework. * Multitask download
Aria experienced 1.0 to 3.0 development, be more and more close to the original set by the target.
Aria has the following characteristics: ![Multitask download](https://github.com/AriaLyy/DownloadUtil/blob/master/img/download_img.gif)
+ simple and convenient
- can be used in Activity, Service, Fragment, Dialog, popupWindow, Notification and other components
- support the task of automatic scheduling, the user does not need to care about the state of the task switch logic
- [Through the Aria event, it is easy to get the download status of the current download task](#status)
- [a code plus can get the current download speed](#interface)
- [a code can be dynamically set the maximum number of downloads](#parameters)
- [code to achieve speed limit](#interface)
- [It is easy to modify the number of download threads by modifying the configuration file](https://github.com/AriaLyy/Aria/blob/master/app/src/main/assets/aria_config.xml)
- [priority to download a task](#interface)
+ Support https address download * Speed limit
- It is easy to set the CA certificate information in the configuration file
+ Support 300,301,302 redirect download link download ![网速下载限制](https://github.com/AriaLyy/DownloadUtil/blob/master/img/max_speed.gif)
+ Support upload operation
* Multi-file package download
<img src="https://github.com/AriaLyy/DownloadUtil/blob/master/img/group_task.gif" width="360" height="640"/>
* m3u8 download
How do we to use Aria? ![m3u8点播文件边下边看](https://github.com/AriaLyy/Aria/blob/master/img/m3u8VodDownload.gif)
* [download](#Using)
* [upload](#Upload) s ## Lib
[![license](http://img.shields.io/badge/license-Apache2.0-brightgreen.svg?style=flat)](https://github.com/AriaLyy/Aria/blob/master/LICENSE)
[![Core](https://img.shields.io/badge/Core-3.8.10-blue)](https://github.com/AriaLyy/Aria)
[![Compiler](https://img.shields.io/badge/Compiler-3.8.10-blue)](https://github.com/AriaLyy/Aria)
[![FtpComponent](https://img.shields.io/badge/FtpComponent-3.8.10-orange)](https://github.com/AriaLyy/Aria)
[![FtpComponent](https://img.shields.io/badge/SFtpComponent-3.8.10-orange)](https://github.com/AriaLyy/Aria)
[![M3U8Component](https://img.shields.io/badge/M3U8Component-3.8.10-orange)](https://github.com/AriaLyy/Aria)
If you feel that Aria is helpful to you, your star and issues will be the greatest support for me.`^_^`
## Download
[![Download](https://api.bintray.com/packages/arialyy/maven/AriaApi/images/download.svg)](https://bintray.com/arialyy/maven/AriaApi/_latestVersion)
[![Download](https://api.bintray.com/packages/arialyy/maven/AriaCompiler/images/download.svg)](https://bintray.com/arialyy/maven/AriaCompiler/_latestVersion)
```java ```java
compile 'com.arialyy.aria:aria-core:3.2.0' implementation 'com.arialyy.aria:core:3.8.10'
annotationProcessor 'com.arialyy.aria:aria-compiler:3.2.0' annotationProcessor 'com.arialyy.aria:compiler:3.8.10'
implementation 'com.arialyy.aria:ftpComponent:3.8.10' # If you need to use ftp, please add this component
implementation 'com.arialyy.aria:sftpComponent:3.8.10' # If you need to use sftp, please add this component
implementation 'com.arialyy.aria:m3u8Component:3.8.10' # If you need to use the m3u8 download function, please add this component
``` ```
## For example If you are using Kotlin, please use the official method provided by Kotlin to configure apt, [kotlin kapt official configuration portal](https://www.kotlincn.net/docs/reference/kapt.html)
![Multi-task download](https://github.com/AriaLyy/DownloadUtil/blob/master/img/download_img.gif)
![download speed limit](https://github.com/AriaLyy/DownloadUtil/blob/master/img/max_speed.gif) __⚠Note: When the version below 3.5.4 is upgraded, the [configuration file] needs to be updated(https://aria.laoyuyu.me/aria_doc/start/config.html)!!__
## performance __⚠Note: Version 3.8 and above have been adapted to AndroidX and support libraries can be used
![Performance display](https://github.com/AriaLyy/DownloadUtil/blob/master/img/performance.png)
*** ***
## Using ## Use
Since Aria involves the operation of files and networks, you need to add the following permissions to the manifest file. Because Aria involves file and network operations, you need to add the following permissions to the manifest file. If you want to use Aria in a system above 6.0, you need to dynamically apply for file system read and write permissions to the Android system, [How to use Android system permissions](https://developer.android.com/training/permissions/index.html?hl=zh-cn)
```xml ```xml
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
``` ```
## Use Aria to download ## Use Aria
* Add a task (do not download), when other download tasks are completed, will automatically download the waiting task ### Basic use
The example is a single-task download, only a very simple code is needed to realize the download function.
* Create task
```java ```java
Aria.download(this) long taskId = Aria.download(this)
.load(DOWNLOAD_URL) .load(DOWNLOAD_URL) //Read download address
.setDownloadPath(DOWNLOAD_PATH) //file save path .setFilePath(DOWNLOAD_PATH) //Set the full path where the file is saved
.add(); .create(); //Create and start download
``` ```
* Stop\Resume task
* download
```java ```java
Aria.download(this) Aria.download(this)
.load(DOWNLOAD_URL) //load download url .load(taskId) //task id
.setDownloadPath(DOWNLOAD_PATH) //file save path .stop(); // stop task
.start(); //start download //.resume(); // resume task
```
* Pause
```java
Aria.download(this).load(DOWNLOAD_URL).pause();
``` ```
* Resume download
```java ### Obtaining task status
Aria.download(this).load(DOWNLOAD_URL).resume(); Based on the consideration of decoupling, the download function of Aria is separated from the state acquisition, and the state acquisition will not be integrated into the chain code, but Aria provides another simpler and more flexible solution.
``` Through annotations, you can easily get all the status of the task.
* Cancel download
```java
Aria.download(this).load(DOWNLOAD_URL).cancel();
```
### status
If you want to read the download progress or download the information, then you need to create an event class and register the event class into the Aria manager in the onResume (Activity, Fragment) or constructor (Dialog, PopupWindow).
1. Register the object to Aria 1. Register the object to Aria
```java
`Aria.download(this).register();` or `Aria.upload(this).register();` protected void onCreate(Bundle savedInstanceState) {
```java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Aria.download(this).register(); Aria.download(this).register();
} }
```
2. Use`@Download` or `@Upload` to annotate your function<br>
**note:**
- Annotation is done by using `Apt`, so you do not need to worry that this will affect your machine's performance
- The annotated method**can not be modified by private**
- The annotated method**can have only one argument, and the parameter type must be either`DownloadTask` or `UploadTask`**
- Method name can be any string
3. In addition to using annotation methods in widget (Activity, Fragment, Dialog, Popupwindow), you can also use annotation functions in components such as Service, Notification, and so on.
```java
@Download.onPre(DOWNLOAD_URL)
protected void onPre(DownloadTask task) {}
@Download.onTaskStart
void taskStart(DownloadTask task) {}
@Download.onTaskRunning
protected void running(DownloadTask task) {}
@Download.onTaskResume
void taskResume(DownloadTask task) {}
@Download.onTaskStop
void taskStop(DownloadTask task) {}
@Download.onTaskCancel
void taskCancel(DownloadTask task) {}
@Download.onTaskFail
void taskFail(DownloadTask task) {}
@Download.onTaskComplete
void taskComplete(DownloadTask task) {}
@Download.onNoSupportBreakPoint
public void onNoSupportBreakPoint(DownloadTask task) {}
```
4. If you want to set up a listener for a single task, or for some specific task.<br>
**Adding a download address for a task in an annotation means that only the task triggers the annotated method.**
```java
@Download.onTaskRunning({
"https://test.xx.apk",
"http://test.xx2.apk"
}) void taskRunning(DownloadTask task) {
mAdapter.setProgress(task.getDownloadEntity());
}
```
In the above example,only the download address is`https://test.xx.apk` and `http://test.xx2.apk`will trigger the`taskRunning(DownloadTask task)`method。
### parameters
#### [Configuration file setting parameters](https://github.com/AriaLyy/Aria/blob/master/app/src/main/assets/aria_config.xml)
#### Set the parameters in the code
In addition to the file mode to modify the Aria parameter, the same, you can also modify the code in the Aria parameters</br>
Get the configuration file directly through`Aria.get(this).getDownloadConfig()`or`Aria.get(this).getUploadConfig()`</br>
and then modify the parameters:
```java
// 修改最大下载数,调用完成后,立即生效
// 如当前下载任务数是4,修改完成后,当前任务数会被Aria自动调度任务数
Aria.get(this).getDownloadConfig().setMaxTaskNum(3);
``` ```
### interface 2. Obtain task execution status through annotations
* Stop all tasks **Note: **
- Annotation back is implemented using Apt, so you don’t need to worry about this affecting the performance of your machine
```java - Annotated methods **cannot be modified by private**
Aria.download(this).stopAllTask(); - The annotated method ** can only have one parameter, and the parameter type must be `DownloadTask` or `UploadTask` or `DownloadGroupTask`**
``` - Method name can be any string
* Restore all stopped tasks
```java
Aria.download(this).resumeAllTask();
```
* Delete all tasks
```java ```java
Aria.download(this).removeAllTask(); //Process the status of the task execution here, such as the refresh of the progress bar
``` @Download.onTaskRunning protected void running(DownloadTask task) {
if(task.getKey().eques(url)){
* Maximum download speed limit ....
```java You can judge whether it is the callback of the specified task by url
//单位为 kb }
Aria.download(this).setMaxSpeed(speed); int p = task.getPercent(); //Task progress percentage
``` String speed = task.getConvertSpeed(); //Download speed after unit conversion, unit conversion needs to be opened in the configuration file
String speed1 = task.getSpeed(); //Original byte length speed
* Get download speed for current tasks<br>
Speed parameters a bit special,need to [download the event support](#status)
``` java
@Override public void onTaskRunning(DownloadTask task) {
//If you turn on the speed unit conversion configuration, you can get the download speed with units in the following ways, such as: 1 mb/s
String convertSpeed = task.getConvertSpeed();
//If you have your own unit format, you can get the original byte length by the following method
long speed = task.getSpeed();
} }
```
* Get the downloaded file size, the current progress percentage</br> @Download.onTaskComplete void taskComplete(DownloadTask task) {
Likewise, you can also get the downloaded file size in the DownloadTask object //Process the status of task completion here
```
@Override public void onTaskRunning(DownloadTask task) {
 //Get the file size
long fileSize = task.getFileSize();
//Get the file size after conversion
String fileSize1 = task.getConvertFileSize();
//The current percentage of progress
int percent = task.getPercent();
} }
``` ```
* Set the high priority task<br> ### [Document address](https://aria.laoyuyu.me/aria_doc/)
If you want to give priority to download a task, you can
``` java
Aria.download(this).load(DOWNLOAD_URL).setDownloadPath(PATH).setHighestPriority();
```
* Set the extension field<br>
Sometimes, you may want to store some of your own data when you download it</br>
**TIP**: If you have more data, or the data is more complex, you can first convert the data to JSON, and then save it to Aria's download entity
```java
Aria.download(this).load(DOWNLOAD_URL).setExtendField(str)
```
## Upload
* Add a task (add only, do not upload)
```java
Aria.upload(this)
.load(filePath) //file path
.setUploadUrl(uploadUrl) // upload the path
.setAttachment(fileKey) //The server reads the file's key
.add();
```
* Upload ### Version Log
+ v_3.8.10 (2020/6/26)
- fix bug https://github.com/AriaLyy/Aria/issues/703
- fix bug https://github.com/AriaLyy/Aria/issues/702
- fix bug https://github.com/AriaLyy/Aria/issues/695
```java [More Version Log](https://github.com/AriaLyy/Aria/blob/master/DEV_LOG.md)
Aria.upload(this)
.load(filePath) //file path
.setUploadUrl(uploadUrl) //upload the path
.setAttachment(fileKey) //The server reads the file's key
.start();
```
* cancel upload
```java ## Confusion configuration
Aria.upload(this).load(filePath).cancel();
```
## Confused configuration
``` ```
-dontwarn com.arialyy.aria.** -dontwarn com.arialyy.aria.**
-keep class com.arialyy.aria.**{*;} -keep class com.arialyy.aria.**{*;}
-keep class **$$DownloadListenerProxy{ *; } -keep class **$$DownloadListenerProxy{ *; }
-keep class **$$UploadListenerProxy{ *; } -keep class **$$UploadListenerProxy{ *; }
-keep class **$$DownloadGroupListenerProxy{ *; }
-keep class **$$DGSubListenerProxy{ *; }
-keepclasseswithmembernames class * { -keepclasseswithmembernames class * {
@Download.* <methods>; @Download.* <methods>;
@Upload.* <methods>; @Upload.* <methods>;
@DownloadGroup.* <methods>;
} }
``` ```
## others ## Other
Have any questions that can give me a message in the[issues](https://github.com/AriaLyy/Aria/issues)。 If you have any questions, you can leave me a feedback at [issues](https://github.com/AriaLyy/Aria/issues). </br>
Before submitting an issue, I hope you have checked [wiki](https://aria.laoyuyu.me/aria_doc/) or searched [issues](https://github.com/AriaLyy/Aria/issues). </br>
*** ## Donate
https://paypal.me/arialyy
## 后续版本开发规划 ***
* ~~http、scoket断点上传~~
* ~~实现上传队列调度功能~~
## Development log
+ v_3.1.9 Repair the stopAll queue without task when the problem of collapse, increase the function for a single task monitor
+ v_3.1.7 repair some files can not download the bug, increase the apt annotation method, the incident is more simple
+ v_3.1.6 When the task is canceled ontaskCancel callback twice
+ v_3.1.5 Optimize the code structure, increase the priority download task function.
+ v_3.1.4 Repair the fast switching, pause, and restore functions, the probability of re-download problems, add onPre () callback, onPre () used to request the interface before the implementation of interface UI update operation.
+ v_3.1.0 Add the Aria configuration file to optimize the code
+ v_3.0.3 Repair the pause after deleting the task, flashing the problem, add the api to delete the record
+ v_3.0.2 supports 30x redirect link download
+ v_3.0.0 add upload task support to fix some bugs that have been discovered
License License
------- -------

@ -47,7 +47,7 @@ public class DownloadConfig extends BaseTaskConfig implements Serializable {
/** /**
* 设置http下载获取文件大小是否使用Head请求true使用head请求false使用默认的get请求 * 设置http下载获取文件大小是否使用Head请求true使用head请求false使用默认的get请求
*/ */
boolean useHeadRequest; boolean useHeadRequest = false;
public boolean isUseHeadRequest() { public boolean isUseHeadRequest() {
return useHeadRequest; return useHeadRequest;

@ -157,7 +157,7 @@ public class XMLReader extends DefaultHandler {
setField("subReTryInterval", subReTryInterval, ConfigType.D_GROUP); setField("subReTryInterval", subReTryInterval, ConfigType.D_GROUP);
break; break;
case "useHeadRequest": // 是否使用head请求 case "useHeadRequest": // 是否使用head请求
boolean useHeadRequest = checkBoolean(value) ? Boolean.valueOf(value) : true; boolean useHeadRequest = checkBoolean(value) ? Boolean.valueOf(value) : false;
setField("useHeadRequest", useHeadRequest, ConfigType.DOWNLOAD); setField("useHeadRequest", useHeadRequest, ConfigType.DOWNLOAD);
break; break;
} }

@ -24,7 +24,7 @@ import java.util.List;
*/ */
public abstract class DbEntity { public abstract class DbEntity {
private static final Object LOCK = new Object(); private static final Object LOCK = new Object();
protected long rowID = -1; public long rowID = -1;
protected DbEntity() { protected DbEntity() {

@ -768,7 +768,7 @@ public class CommonUtil {
field = clazz.getField(name); field = clazz.getField(name);
} catch (NoSuchFieldException e1) { } catch (NoSuchFieldException e1) {
if (clazz.getSuperclass() == null) { if (clazz.getSuperclass() == null) {
return field; return null;
} else { } else {
field = getField(clazz.getSuperclass(), name); field = getField(clazz.getSuperclass(), name);
} }
@ -780,6 +780,32 @@ public class CommonUtil {
return field; return field;
} }
/**
* 获取类里面的指定对象如果该类没有则从父类查询
*/
public static Method getMethod(Class clazz, String methodName, Class<?>... params){
Method method = null;
try {
method = clazz.getDeclaredMethod(methodName, params);
} catch (NoSuchMethodException e) {
try {
method = clazz.getMethod(methodName, params);
} catch (NoSuchMethodException ex) {
if (clazz.getSuperclass() == null) {
return null;
} else {
method = getMethod(clazz.getSuperclass(), methodName, params);
}
}
}
if (method != null){
method.setAccessible(true);
}
return method;
}
/** /**
* 字符串转hashcode * 字符串转hashcode
*/ */

@ -34,14 +34,14 @@ public class DeleteDGRecord implements IDeleteRecord {
private static volatile DeleteDGRecord INSTANCE = null; private static volatile DeleteDGRecord INSTANCE = null;
private DeleteDGRecord(){ private DeleteDGRecord() {
} }
public static DeleteDGRecord getInstance() { public static DeleteDGRecord getInstance() {
if (INSTANCE == null){ if (INSTANCE == null) {
synchronized (DeleteDGRecord.class){ synchronized (DeleteDGRecord.class) {
if (INSTANCE == null){ if (INSTANCE == null) {
INSTANCE = new DeleteDGRecord(); INSTANCE = new DeleteDGRecord();
} }
} }
@ -108,9 +108,13 @@ public class DeleteDGRecord implements IDeleteRecord {
} }
} }
deleteEntity(needRemoveEntity, groupEntity.getGroupHash());
}
private void deleteEntity(boolean needRemoveEntity, String groupHash) {
if (needRemoveEntity) { if (needRemoveEntity) {
DbEntity.deleteData(DownloadEntity.class, "groupHash=?", groupEntity.getGroupHash()); DbEntity.deleteData(DownloadEntity.class, "groupHash=?", groupHash);
DbEntity.deleteData(DownloadGroupEntity.class, "groupHash=?", groupEntity.getGroupHash()); DbEntity.deleteData(DownloadGroupEntity.class, "groupHash=?", groupHash);
} }
} }

@ -92,9 +92,9 @@ public class DeleteDRecord implements IDeleteRecord {
TaskRecord record = DbDataHelper.getTaskRecord(entity.getFilePath(), entity.getTaskType()); TaskRecord record = DbDataHelper.getTaskRecord(entity.getFilePath(), entity.getTaskType());
if (record == null) { if (record == null) {
ALog.e(TAG, "删除下载记录失败,记录为空,filePath:" + entity.getFilePath()); ALog.e(TAG, "删除下载记录失败,记录为空,将删除实体记录,filePath:" + entity.getFilePath());
FileUtil.deleteFile(targetFile); FileUtil.deleteFile(targetFile);
DbEntity.deleteData(DownloadEntity.class, "downloadPath=?", filePath); deleteEntity(needRemoveEntity, filePath);
return; return;
} }
@ -111,6 +111,10 @@ public class DeleteDRecord implements IDeleteRecord {
} }
} }
deleteEntity(needRemoveEntity, filePath);
}
private void deleteEntity(boolean needRemoveEntity, String filePath){
if (needRemoveEntity) { if (needRemoveEntity) {
DbEntity.deleteData(DownloadEntity.class, "downloadPath=?", filePath); DbEntity.deleteData(DownloadEntity.class, "downloadPath=?", filePath);
} }

@ -76,12 +76,13 @@ public class DeleteM3u8Record implements IDeleteRecord {
} }
DownloadEntity entity = (DownloadEntity) absEntity; DownloadEntity entity = (DownloadEntity) absEntity;
TaskRecord record = DbDataHelper.getTaskRecord(entity.getFilePath(), entity.getTaskType()); final String filePath = entity.getFilePath();
TaskRecord record = DbDataHelper.getTaskRecord(filePath, entity.getTaskType());
if (record == null) { if (record == null) {
ALog.e(TAG, "删除下载记录失败,记录为空,filePath:" + entity.getFilePath()); ALog.e(TAG, "删除下载记录失败,记录为空,将删除实体记录,filePath:" + entity.getFilePath());
deleteEntity(needRemoveEntity, filePath);
return; return;
} }
final String filePath = entity.getFilePath();
// 删除下载的线程记录和任务记录 // 删除下载的线程记录和任务记录
DbEntity.deleteData(ThreadRecord.class, "taskKey=? AND threadType=?", filePath, DbEntity.deleteData(ThreadRecord.class, "taskKey=? AND threadType=?", filePath,
@ -95,6 +96,10 @@ public class DeleteM3u8Record implements IDeleteRecord {
FileUtil.deleteFile(filePath); FileUtil.deleteFile(filePath);
} }
deleteEntity(needRemoveEntity, filePath);
}
private void deleteEntity(boolean needRemoveEntity, String filePath){
if (needRemoveEntity) { if (needRemoveEntity) {
DbEntity.deleteData(DownloadEntity.class, "downloadPath=?", filePath); DbEntity.deleteData(DownloadEntity.class, "downloadPath=?", filePath);
} }

@ -88,8 +88,12 @@ public class DeleteURecord implements IDeleteRecord {
FileUtil.deleteFile(entity.getFilePath()); FileUtil.deleteFile(entity.getFilePath());
} }
deleteEntity(needRemoveEntity, entity.getFilePath());
}
private void deleteEntity(boolean needRemoveEntity, String filePath) {
if (needRemoveEntity) { if (needRemoveEntity) {
DbEntity.deleteData(UploadEntity.class, "filePath=?", entity.getFilePath()); DbEntity.deleteData(UploadEntity.class, "filePath=?", filePath);
} }
} }
} }

@ -194,13 +194,3 @@ License
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.

@ -27,11 +27,12 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".core.download.fragment.MultiFragmentActivity"/>
<activity android:name=".core.upload.SFtpUploadActivity" /> <activity android:name=".core.upload.SFtpUploadActivity" />
<activity android:name=".core.download.SFtpDownloadActivity" /> <activity android:name=".core.download.SFtpDownloadActivity" />
<activity android:name=".core.download.DownloadActivity" /> <activity android:name=".core.download.DownloadActivity" />
<activity android:name=".core.download.SingleTaskActivity" /> <activity android:name=".core.download.SingleTaskActivity" />
<activity android:name=".core.download.mutil.MultiTaskActivity" /> <activity android:name=".core.download.mutil.MultiTaskListActivity" />
<activity android:name=".core.download.fragment.FragmentActivity" /> <activity android:name=".core.download.fragment.FragmentActivity" />
<activity android:name=".core.download.mutil.MultiDownloadActivity" /> <activity android:name=".core.download.mutil.MultiDownloadActivity" />
<activity android:name=".core.download.HighestPriorityActivity" /> <activity android:name=".core.download.HighestPriorityActivity" />

@ -20,13 +20,12 @@
<!--普通下载任务--> <!--普通下载任务-->
<download> <download>
<!--设置http下载获取文件大小是否使用Head请求。true:使用head请求,false:使用默认的get请求。默认为false-->
<!--设置http下载获取文件大小是否使用Head请求。true:使用head请求,false:使用默认的get请求-->
<!--只适用于3.8.11以上的版本--> <!--只适用于3.8.11以上的版本-->
<useHeadRequest value="true"/> <useHeadRequest value="false"/>
<!--设置任务最大下载速度,0表示不限速,单位为:kb--> <!--设置任务最大下载速度,0表示不限速,单位为:kb-->
<maxSpeed value="128"/> <maxSpeed value="0"/>
<!-- <!--
多线程下载是否使用块下载模式,{@code true}使用,{@code false}不使用 多线程下载是否使用块下载模式,{@code true}使用,{@code false}不使用
@ -45,7 +44,7 @@
3、从3.4.1开始,如果线程数为1,文件初始化时将不再预占用对应长度的空间,下载多少byte,则占多大的空间; 3、从3.4.1开始,如果线程数为1,文件初始化时将不再预占用对应长度的空间,下载多少byte,则占多大的空间;
对于采用多线程的任务或旧任务,依然采用原来的文件空间占用方式; 对于采用多线程的任务或旧任务,依然采用原来的文件空间占用方式;
--> -->
<threadNum value="1"/> <threadNum value="3"/>
<!--设置下载队列最大任务数, 默认为2--> <!--设置下载队列最大任务数, 默认为2-->
<maxTaskNum value="1"/> <maxTaskNum value="1"/>

@ -28,7 +28,8 @@ import com.arialyy.simple.R;
import com.arialyy.simple.base.BaseActivity; import com.arialyy.simple.base.BaseActivity;
import com.arialyy.simple.base.adapter.RvItemClickSupport; import com.arialyy.simple.base.adapter.RvItemClickSupport;
import com.arialyy.simple.common.NormalToAdapter; import com.arialyy.simple.common.NormalToAdapter;
import com.arialyy.simple.core.download.mutil.MultiTaskActivity; import com.arialyy.simple.core.download.fragment.MultiFragmentActivity;
import com.arialyy.simple.core.download.mutil.MultiTaskListActivity;
import com.arialyy.simple.databinding.ActivityDownloadMeanBinding; import com.arialyy.simple.databinding.ActivityDownloadMeanBinding;
import com.arialyy.simple.modlue.CommonModule; import com.arialyy.simple.modlue.CommonModule;
import com.arialyy.simple.to.NormalTo; import com.arialyy.simple.to.NormalTo;
@ -76,7 +77,7 @@ public class DownloadActivity extends BaseActivity<ActivityDownloadMeanBinding>
break; break;
case 1: case 1:
module.startNextActivity(DownloadActivity.this, data.get(position), module.startNextActivity(DownloadActivity.this, data.get(position),
MultiTaskActivity.class); MultiTaskListActivity.class);
break; break;
case 2: case 2:
module.startNextActivity(DownloadActivity.this, data.get(position), module.startNextActivity(DownloadActivity.this, data.get(position),
@ -87,7 +88,9 @@ public class DownloadActivity extends BaseActivity<ActivityDownloadMeanBinding>
KotlinDownloadActivity.class); KotlinDownloadActivity.class);
break; break;
case 4: case 4:
// 服务中 // 多fragment
module.startNextActivity(DownloadActivity.this, data.get(position),
MultiFragmentActivity.class);
break; break;
case 5: case 5:
// 组件中使用 // 组件中使用

@ -34,9 +34,10 @@ import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.common.AbsEntity; import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.common.HttpOption; import com.arialyy.aria.core.common.HttpOption;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.inf.IEntity; import com.arialyy.aria.core.download.DownloadTaskListener;
import com.arialyy.aria.core.listener.ISchedulers; import com.arialyy.aria.core.listener.ISchedulers;
import com.arialyy.aria.core.processor.IHttpFileLenAdapter; import com.arialyy.aria.core.processor.IHttpFileLenAdapter;
import com.arialyy.aria.core.scheduler.NormalTaskListenerInterface;
import com.arialyy.aria.core.task.DownloadTask; import com.arialyy.aria.core.task.DownloadTask;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
@ -165,7 +166,7 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
} }
@Download.onWait @Download.onWait
void onWait(DownloadTask task) { public void onWait(DownloadTask task) {
if (task.getKey().equals(mUrl)) { if (task.getKey().equals(mUrl)) {
Log.d(TAG, "wait ==> " + task.getDownloadEntity().getFileName()); Log.d(TAG, "wait ==> " + task.getDownloadEntity().getFileName());
getBinding().pl.setInfo(task.getEntity()); getBinding().pl.setInfo(task.getEntity());
@ -173,14 +174,18 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
} }
@Download.onPre @Download.onPre
protected void onPre(DownloadTask task) { public void onPre(DownloadTask task) {
if (task.getKey().equals(mUrl)) { if (task.getKey().equals(mUrl)) {
getBinding().pl.setInfo(task.getEntity()); getBinding().pl.setInfo(task.getEntity());
} }
} }
//@Override public void onTaskPre(DownloadTask task) {
//
//}
@Download.onTaskStart @Download.onTaskStart
void taskStart(DownloadTask task) { public void onTaskStart(DownloadTask task) {
if (task.getKey().equals(mUrl)) { if (task.getKey().equals(mUrl)) {
getBinding().pl.setInfo(task.getEntity()); getBinding().pl.setInfo(task.getEntity());
ALog.d(TAG, "isComplete = " + task.isComplete() + ", state = " + task.getState()); ALog.d(TAG, "isComplete = " + task.isComplete() + ", state = " + task.getState());
@ -188,15 +193,19 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
} }
@Download.onTaskRunning @Download.onTaskRunning
protected void running(DownloadTask task) { public void onTaskRunning(DownloadTask task) {
if (task.getKey().equals(mUrl)) { if (task.getKey().equals(mUrl)) {
//ALog.d(TAG, "isRunning" + "; state = " + task.getEntity().getState()); //ALog.d(TAG, "isRunning" + "; state = " + task.getEntity().getState());
getBinding().pl.setInfo(task.getEntity()); getBinding().pl.setInfo(task.getEntity());
} }
} }
//@Override public void onNoSupportBreakPoint(DownloadTask task) {
//
//}
@Download.onTaskResume @Download.onTaskResume
void taskResume(DownloadTask task) { public void onTaskResume(DownloadTask task) {
if (task.getKey().equals(mUrl)) { if (task.getKey().equals(mUrl)) {
ALog.d(TAG, "resume"); ALog.d(TAG, "resume");
getBinding().pl.setInfo(task.getEntity()); getBinding().pl.setInfo(task.getEntity());
@ -204,7 +213,7 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
} }
@Download.onTaskStop @Download.onTaskStop
void taskStop(DownloadTask task) { public void onTaskStop(DownloadTask task) {
if (task.getKey().equals(mUrl)) { if (task.getKey().equals(mUrl)) {
ALog.d(TAG, "stop"); ALog.d(TAG, "stop");
getBinding().pl.setInfo(task.getEntity()); getBinding().pl.setInfo(task.getEntity());
@ -212,7 +221,7 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
} }
@Download.onTaskCancel @Download.onTaskCancel
void taskCancel(DownloadTask task) { public void onTaskCancel(DownloadTask task) {
if (task.getKey().equals(mUrl)) { if (task.getKey().equals(mUrl)) {
mTaskId = -1; mTaskId = -1;
Log.d(TAG, "cancel"); Log.d(TAG, "cancel");
@ -221,7 +230,7 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
} }
@Download.onTaskFail @Download.onTaskFail
void taskFail(DownloadTask task, Exception e) { public void onTaskFail(DownloadTask task, Exception e) {
ALog.d(TAG, "下载失败"); ALog.d(TAG, "下载失败");
Toast.makeText(SingleTaskActivity.this, getString(R.string.download_fail), Toast.LENGTH_SHORT) Toast.makeText(SingleTaskActivity.this, getString(R.string.download_fail), Toast.LENGTH_SHORT)
.show(); .show();
@ -231,7 +240,7 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
} }
@Download.onTaskComplete @Download.onTaskComplete
void taskComplete(DownloadTask task) { public void onTaskComplete(DownloadTask task) {
if (task.getKey().equals(mUrl)) { if (task.getKey().equals(mUrl)) {
Toast.makeText(SingleTaskActivity.this, getString(R.string.download_success), Toast.makeText(SingleTaskActivity.this, getString(R.string.download_success),
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();

@ -19,24 +19,20 @@ package com.arialyy.simple.core.download.fragment;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.view.View; import android.view.View;
import android.widget.Button;
import com.arialyy.annotations.Download; import com.arialyy.annotations.Download;
import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.task.DownloadTask; import com.arialyy.aria.core.task.DownloadTask;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.frame.core.AbsFragment; import com.arialyy.frame.core.AbsFragment;
import com.arialyy.simple.R; import com.arialyy.simple.R;
import com.arialyy.simple.databinding.FragmentDownloadBinding; import com.arialyy.simple.databinding.FragmentDownloadBinding;
import com.arialyy.simple.widget.ProgressLayout;
/** /**
* Created by lyy on 2017/1/4. * Created by lyy on 2017/1/4.
*/ */
public class DownloadFragment extends AbsFragment<FragmentDownloadBinding> public class DownloadFragment extends AbsFragment<FragmentDownloadBinding> {
implements View.OnClickListener {
Button mStart;
Button mCancel;
private long mTaskId = -1; private long mTaskId = -1;
private static final String DOWNLOAD_URL = private static final String DOWNLOAD_URL =
@ -44,82 +40,58 @@ public class DownloadFragment extends AbsFragment<FragmentDownloadBinding>
private static final String FILE_NAME = "王者军团"; private static final String FILE_NAME = "王者军团";
@Override protected void init(Bundle savedInstanceState) { @Override protected void init(Bundle savedInstanceState) {
mStart = mRootView.findViewById(R.id.start); Aria.download(this).register();
mCancel = mRootView.findViewById(R.id.cancel);
mStart.setOnClickListener(this);
mCancel.setOnClickListener(this);
DownloadEntity entity = Aria.download(this).getFirstDownloadEntity(DOWNLOAD_URL); DownloadEntity entity = Aria.download(this).getFirstDownloadEntity(DOWNLOAD_URL);
if (entity != null) { if (entity == null){
getBinding().setFileSize(CommonUtil.formatFileSize(entity.getFileSize())); entity = new DownloadEntity();
getBinding().setProgress(entity.getPercent()); entity.setUrl(DOWNLOAD_URL);
if (entity.getState() == IEntity.STATE_RUNNING) {
getBinding().setStateStr(getString(R.string.stop));
} else {
getBinding().setStateStr(getString(R.string.resume));
}
mTaskId = entity.getId();
} else {
getBinding().setStateStr(getString(R.string.start));
} }
getBinding().setUrl(DOWNLOAD_URL); getBinding().pl.setInfo(entity);
getBinding().setFileName(FILE_NAME); getBinding().pl.setBtListener(new ProgressLayout.OnProgressLayoutBtListener() {
Aria.download(this).register(); @Override public void create(View v, AbsEntity entity) {
} mTaskId = Aria.download(this)
.load(DOWNLOAD_URL)
.setFilePath(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
.getPath() + String.format("/%s.apk",
FILE_NAME))
.create();
}
public void onClick(View view) { @Override public void stop(View v, AbsEntity entity) {
switch (view.getId()) { Aria.download(this)
case R.id.start: .load(mTaskId)
if (mTaskId == -1) { .stop();
mTaskId = Aria.download(this) }
.load(DOWNLOAD_URL)
.setFilePath( @Override public void resume(View v, AbsEntity entity) {
Environment.getExternalStorageDirectory().getPath() + String.format("/%s.apk", Aria.download(this).load(mTaskId)
FILE_NAME)) //.updateUrl(mUrl)
.create(); .resume();
getBinding().setStateStr(getString(R.string.stop)); }
break;
} @Override public void cancel(View v, AbsEntity entity) {
if (Aria.download(this).load(mTaskId).isRunning()) { Aria.download(this).load(mTaskId).cancel(false);
Aria.download(this).load(mTaskId).stop();
getBinding().setStateStr(getString(R.string.resume));
} else {
Aria.download(this).load(mTaskId).resume();
getBinding().setStateStr(getString(R.string.stop));
}
break;
case R.id.cancel:
Aria.download(this).load(mTaskId).cancel();
getBinding().setStateStr(getString(R.string.start));
mTaskId = -1; mTaskId = -1;
break; }
} });
} }
@Download.onTaskPre public void onTaskPre(DownloadTask task) { @Download.onTaskPre public void onTaskPre(DownloadTask task) {
getBinding().setFileSize(task.getConvertFileSize()); getBinding().pl.setInfo(task.getEntity());
} }
@Download.onTaskStop public void onTaskStop(DownloadTask task) { @Download.onTaskStop public void onTaskStop(DownloadTask task) {
getBinding().setSpeed(""); getBinding().pl.setInfo(task.getEntity());
getBinding().setStateStr(getString(R.string.resume));
} }
@Download.onTaskCancel public void onTaskCancel(DownloadTask task) { @Download.onTaskCancel public void onTaskCancel(DownloadTask task) {
getBinding().setProgress(0); getBinding().pl.setInfo(task.getEntity());
getBinding().setSpeed("");
getBinding().setStateStr(getString(R.string.cancel));
} }
@Download.onTaskRunning public void onTaskRunning(DownloadTask task) { @Download.onTaskRunning public void onTaskRunning(DownloadTask task) {
long len = task.getFileSize(); long len = task.getFileSize();
if (len == 0) { getBinding().pl.setInfo(task.getEntity());
getBinding().setProgress(0);
} else {
getBinding().setProgress(task.getPercent());
}
getBinding().setSpeed(task.getConvertSpeed());
} }
@Override protected void onDelayLoad() { @Override protected void onDelayLoad() {

@ -0,0 +1,56 @@
package com.arialyy.simple.core.download.fragment
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter
import com.arialyy.simple.R
import com.arialyy.simple.base.BaseActivity
import com.arialyy.simple.databinding.ActivityMultiFragmentActivityBinding
class MultiFragmentActivity : BaseActivity<ActivityMultiFragmentActivityBinding>() {
private val urls = arrayListOf(
"http://cpsdown.muzhiwan.com/2020/07/23/com.suyou.xjhx.syad_5f195b471dff6.apk",
"http://60.174.135.183:88/sdkdown.muzhiwan.com/2020/01/13/com.supercell.clashroyale.ewan.mzw_5e1bc4eb4313e.apk",
"http://60.174.135.183:88/sdkdown.muzhiwan.com/openfile/2020/08/06/com.maoer.m282_5f2b79232a8b1.apk"
)
private val names = arrayListOf(
"星界幻想",
"皇室战争",
"无双帝国"
)
override fun setLayoutId(): Int {
return R.layout.activity_multi_fragment_activity
}
override fun init(savedInstanceState: Bundle?) {
super.init(savedInstanceState)
val fragmentList = arrayListOf<MultiItemFragment>()
urls.forEachIndexed { index, url ->
fragmentList.add(MultiItemFragment(url, names[index]))
}
binding.vpPage.adapter = PGAdapter(fragmentList, supportFragmentManager, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)
binding.tabLayout.setupWithViewPager(binding.vpPage)
binding.tabLayout.getTabAt(0)!!.text = "fm1"
binding.tabLayout.getTabAt(1)!!.text = "fm2"
binding.tabLayout.getTabAt(2)!!.text = "fm3"
}
private class PGAdapter(
val fragments: List<MultiItemFragment>,
fm: FragmentManager,
state: Int
) : FragmentPagerAdapter(fm, state) {
override fun getItem(position: Int): Fragment {
return fragments[position]
}
override fun getCount(): Int {
return fragments.size
}
}
}

@ -0,0 +1,124 @@
/*
* 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.core.download.fragment;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import com.arialyy.annotations.Download;
import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.task.DownloadTask;
import com.arialyy.frame.core.AbsFragment;
import com.arialyy.simple.R;
import com.arialyy.simple.databinding.FragmentDownloadBinding;
import com.arialyy.simple.widget.ProgressLayout;
/**
* Created by lyy on 2017/1/4.
*/
public class MultiItemFragment extends AbsFragment<FragmentDownloadBinding> {
private long mTaskId = -1;
private String DOWNLOAD_URL;
private String FILE_NAME;
public MultiItemFragment(String url, String fileName) {
DOWNLOAD_URL = url;
FILE_NAME = fileName;
}
@Override protected void init(Bundle savedInstanceState) {
Aria.download(this).register();
DownloadEntity entity = Aria.download(this).getFirstDownloadEntity(DOWNLOAD_URL);
if (entity == null) {
entity = new DownloadEntity();
entity.setUrl(DOWNLOAD_URL);
}
getBinding().pl.setInfo(entity);
getBinding().pl.setBtListener(new ProgressLayout.OnProgressLayoutBtListener() {
@Override public void create(View v, AbsEntity entity) {
mTaskId = Aria.download(this)
.load(DOWNLOAD_URL)
.setFilePath(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
.getPath() + String.format("/%s.apk",
FILE_NAME))
.create();
}
@Override public void stop(View v, AbsEntity entity) {
Aria.download(this)
.load(mTaskId)
.stop();
}
@Override public void resume(View v, AbsEntity entity) {
Aria.download(this).load(mTaskId)
//.updateUrl(mUrl)
.resume();
}
@Override public void cancel(View v, AbsEntity entity) {
Aria.download(this).load(mTaskId).cancel(false);
mTaskId = -1;
}
});
}
@Download.onTaskPre public void onTaskPre(DownloadTask task) {
if (!task.getKey().equals(DOWNLOAD_URL)){
return;
}
getBinding().pl.setInfo(task.getEntity());
}
@Download.onTaskStop public void onTaskStop(DownloadTask task) {
if (!task.getKey().equals(DOWNLOAD_URL)){
return;
}
getBinding().pl.setInfo(task.getEntity());
}
@Download.onTaskCancel public void onTaskCancel(DownloadTask task) {
if (!task.getKey().equals(DOWNLOAD_URL)){
return;
}
getBinding().pl.setInfo(task.getEntity());
}
@Download.onTaskRunning public void onTaskRunning(DownloadTask task) {
if (!task.getKey().equals(DOWNLOAD_URL)){
return;
}
long len = task.getFileSize();
getBinding().pl.setInfo(task.getEntity());
}
@Override protected void onDelayLoad() {
}
@Override protected int setLayoutId() {
return R.layout.fragment_download;
}
@Override protected void dataCallback(int result, Object obj) {
}
}

@ -31,6 +31,7 @@ import com.arialyy.annotations.Download;
import com.arialyy.annotations.M3U8; import com.arialyy.annotations.M3U8;
import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.common.AbsEntity; import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.common.HttpOption;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.M3U8Entity; import com.arialyy.aria.core.download.M3U8Entity;
import com.arialyy.aria.core.download.m3u8.M3U8VodOption; import com.arialyy.aria.core.download.m3u8.M3U8VodOption;
@ -309,7 +310,7 @@ public class M3U8VodDLoadActivity extends BaseActivity<ActivityM3u8VodBinding> {
//.merge(true) //.merge(true)
//.setVodTsUrlConvert(new VodTsUrlConverter()); //.setVodTsUrlConvert(new VodTsUrlConverter());
//.setMergeHandler(new TsMergeHandler()); //.setMergeHandler(new TsMergeHandler());
option.setUseDefConvert(false); option.setUseDefConvert(true);
option.setKeyUrlConverter(new KeyUrlConverter()); option.setKeyUrlConverter(new KeyUrlConverter());
option.setVodTsUrlConvert(new VodTsUrlConverter()); option.setVodTsUrlConvert(new VodTsUrlConverter());
option.setBandWidthUrlConverter(new BandWidthUrlConverter()); option.setBandWidthUrlConverter(new BandWidthUrlConverter());

@ -34,8 +34,7 @@ public class M3U8VodModule extends BaseViewModule {
// m3u8测试集合:http://www.voidcn.com/article/p-snaliarm-ct.html // m3u8测试集合:http://www.voidcn.com/article/p-snaliarm-ct.html
//private final String defUrl = "https://www.gaoya123.cn/2019/1557993797897.m3u8"; //private final String defUrl = "https://www.gaoya123.cn/2019/1557993797897.m3u8";
// 多码率地址: // 多码率地址:
//private final String defUrl = "http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"; private final String defUrl = "http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u811";
private final String defUrl = "http://mgjx.awu1k.cn:8000/parse/player.m3u8?target=eb2d3ca5198516269cf356463be86573";
//private final String defUrl = "http://youku.cdn7-okzy.com/20200123/16815_fbe419ed/index.m3u8"; //private final String defUrl = "http://youku.cdn7-okzy.com/20200123/16815_fbe419ed/index.m3u8";
//private final String defUrl = "https://cn7.kankia.com/hls/20200108/e1eaec074274c64fe46a3bdb5d2ba487/1578488360/index.m3u8"; //private final String defUrl = "https://cn7.kankia.com/hls/20200108/e1eaec074274c64fe46a3bdb5d2ba487/1578488360/index.m3u8";

@ -26,6 +26,7 @@ import com.arialyy.annotations.Download;
import com.arialyy.annotations.DownloadGroup; import com.arialyy.annotations.DownloadGroup;
import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.common.AbsEntity; import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.task.DownloadGroupTask; import com.arialyy.aria.core.task.DownloadGroupTask;
import com.arialyy.aria.core.task.DownloadTask; import com.arialyy.aria.core.task.DownloadTask;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
@ -100,6 +101,10 @@ public class MultiDownloadActivity extends BaseActivity<ActivityMultiDownloadBin
@Download.onTaskCancel void taskCancel(DownloadTask task) { @Download.onTaskCancel void taskCancel(DownloadTask task) {
mAdapter.updateState(task.getEntity()); mAdapter.updateState(task.getEntity());
List<DownloadEntity> tasks = Aria.download(this).getAllNotCompleteTask();
if (tasks != null){
ALog.d(TAG, "未完成的任务数:" + tasks.size());
}
} }
@Download.onTaskFail void taskFail(DownloadTask task) { @Download.onTaskFail void taskFail(DownloadTask task) {

@ -42,7 +42,7 @@ import java.util.List;
/** /**
* Created by Lyy on 2016/9/27. * Created by Lyy on 2016/9/27.
*/ */
public class MultiTaskActivity extends BaseActivity<ActivityMultiBinding> { public class MultiTaskListActivity extends BaseActivity<ActivityMultiBinding> {
RecyclerView mList; RecyclerView mList;
Toolbar mBar; Toolbar mBar;
private FileListAdapter mAdapter; private FileListAdapter mAdapter;

@ -99,7 +99,7 @@ public class ProgressLayout extends RelativeLayout implements View.OnClickListen
@Override public void onClick(View v) { @Override public void onClick(View v) {
if (listener == null) { if (listener == null) {
ALog.d(TAG, "没有设置OnProgressLayoutBtListener"); ALog.e(TAG, "没有设置OnProgressLayoutBtListener");
return; return;
} }
if (entity == null) { if (entity == null) {

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="fm1" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="fm2" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="fm3" />
</com.google.android.material.tabs.TabLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/vpPage"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</layout>

@ -1,60 +1,16 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" <layout xmlns:android="http://schemas.android.com/apk/res/android">
xmlns:bind="http://schemas.android.com/apk/res-auto"
>
<data>
<variable
name="fileSize"
type="String"
/>
<variable
name="speed"
type="String"
/>
<variable
name="progress"
type="int"
/>
<variable
name="stateStr"
type="String"
/>
<variable
name="file_name"
type="String"
/>
<variable
name="url"
type="String"
/>
</data>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical">
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{@string/file_name(file_name)}"
/>
<TextView <com.arialyy.simple.widget.ProgressLayout
android:layout_width="wrap_content" android:id="@+id/pl"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@{@string/url(url)}" android:layout_margin="16dp" />
/>
<include
layout="@layout/layout_content_single"
bind:fileSize="@{fileSize}"
bind:progress="@{progress}"
bind:speed="@{speed}"
bind:stateStr="@{stateStr}"
/>
</LinearLayout> </LinearLayout>
</layout> </layout>

@ -68,7 +68,7 @@
<item>多任务下载</item> <item>多任务下载</item>
<item>高优先级任务</item> <item>高优先级任务</item>
<item>kotlin</item> <item>kotlin</item>
<item>Service中使用</item> <item>多fragment</item>
<item>组件中使用</item> <item>组件中使用</item>
</string-array> </string-array>

@ -45,7 +45,7 @@ task clean(type: Delete) {
ext { ext {
versionCode = 390 versionCode = 390
versionName = '3.8.10' versionName = '3.8.11-beta'
userOrg = 'arialyy' userOrg = 'arialyy'
groupId = 'com.arialyy.aria' groupId = 'com.arialyy.aria'
publishVersion = versionName publishVersion = versionName

Loading…
Cancel
Save