queue, schedulers reconstruct

v4
laoyuyu 2 years ago
parent 0d814d6494
commit f2ef5927ca
  1. 2
      Aria/src/androidTest/java/com/arialyy/downloadutil/ApplicationTest.java
  2. 2
      Aria/src/main/java/com/arialyy/aria/core/AriaManager.java
  3. 7
      Aria/src/main/java/com/arialyy/aria/core/Dua.kt
  4. 23
      Aria/src/main/java/com/arialyy/aria/core/common/receiver/LifLifecycleReceiver.kt
  5. 91
      Aria/src/main/java/com/arialyy/aria/core/manager/LifecycleManager.kt
  6. 27
      Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java
  7. 4
      Aria/src/main/java/com/arialyy/aria/core/queue/DGroupTaskQueue.java
  8. 131
      Aria/src/main/java/com/arialyy/aria/core/queue/DTaskQueue.java
  9. 155
      Aria/src/main/java/com/arialyy/aria/core/queue/ITaskQueue.java
  10. 78
      Aria/src/main/java/com/arialyy/aria/core/queue/UTaskQueue.java
  11. 2
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/DGLoadExecutePool.java
  12. 2
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/DGLoadSharePool.java
  13. 3
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/DLoadExecutePool.java
  14. 2
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/DLoadSharePool.java
  15. 3
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/UploadExecutePool.java
  16. 2
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/UploadSharePool.java
  17. 1
      Aria/src/main/java/com/arialyy/aria/core/upload/target/UNormalConfigHandler.java
  18. 27
      HttpComponent/src/main/java/com/arialyy/aria/http/HttpBaseController.kt
  19. 20
      HttpComponent/src/main/java/com/arialyy/aria/http/HttpComponent.kt
  20. 3
      HttpComponent/src/main/java/com/arialyy/aria/http/HttpComponentLoader.kt
  21. 2
      HttpComponent/src/main/java/com/arialyy/aria/http/HttpOption.kt
  22. 52
      HttpComponent/src/main/java/com/arialyy/aria/http/HttpUtil.kt
  23. 95
      HttpComponent/src/main/java/com/arialyy/aria/http/download/HttpDStartController.kt
  24. 29
      HttpComponent/src/main/java/com/arialyy/aria/http/download/HttpDTaskOption.kt
  25. 27
      HttpComponent/src/main/java/com/arialyy/aria/http/download/HttpDownloadListener.kt
  26. 23
      HttpComponent/src/main/java/com/arialyy/aria/http/download/HttpDownloader.kt
  27. 1
      HttpComponent/src/main/resources/META-INF/services/com.arialyy.aria.core.inf.IComponentInit
  28. 1
      PublicComponent/build.gradle
  29. 15
      PublicComponent/src/main/java/com/arialyy/aria/core/DuaContext.kt
  30. 0
      PublicComponent/src/main/java/com/arialyy/aria/core/command/AbsCmd.java
  31. 0
      PublicComponent/src/main/java/com/arialyy/aria/core/command/AbsCmdFactory.java
  32. 0
      PublicComponent/src/main/java/com/arialyy/aria/core/command/AbsGroupCmd.java
  33. 0
      PublicComponent/src/main/java/com/arialyy/aria/core/command/AbsNormalCmd.java
  34. 0
      PublicComponent/src/main/java/com/arialyy/aria/core/command/AddCmd.java
  35. 0
      PublicComponent/src/main/java/com/arialyy/aria/core/command/CancelAllCmd.java
  36. 0
      PublicComponent/src/main/java/com/arialyy/aria/core/command/CancelCmd.java
  37. 0
      PublicComponent/src/main/java/com/arialyy/aria/core/command/CmdHelper.java
  38. 0
      PublicComponent/src/main/java/com/arialyy/aria/core/command/CommandManager.java
  39. 0
      PublicComponent/src/main/java/com/arialyy/aria/core/command/DGSubStartCmd.java
  40. 0
      PublicComponent/src/main/java/com/arialyy/aria/core/command/DGSubStopCmd.java
  41. 0
      PublicComponent/src/main/java/com/arialyy/aria/core/command/GroupCmdFactory.java
  42. 0
      PublicComponent/src/main/java/com/arialyy/aria/core/command/HighestPriorityCmd.java
  43. 0
      PublicComponent/src/main/java/com/arialyy/aria/core/command/ICmd.java
  44. 0
      PublicComponent/src/main/java/com/arialyy/aria/core/command/NormalCmdFactory.java
  45. 0
      PublicComponent/src/main/java/com/arialyy/aria/core/command/ReStartCmd.java
  46. 0
      PublicComponent/src/main/java/com/arialyy/aria/core/command/ResumeAllCmd.java
  47. 0
      PublicComponent/src/main/java/com/arialyy/aria/core/command/ResumeThread.java
  48. 2
      PublicComponent/src/main/java/com/arialyy/aria/core/command/StartCmd.java
  49. 0
      PublicComponent/src/main/java/com/arialyy/aria/core/command/StopAllCmd.java
  50. 0
      PublicComponent/src/main/java/com/arialyy/aria/core/command/StopCmd.java
  51. 5
      PublicComponent/src/main/java/com/arialyy/aria/core/config/BaseConfig.java
  52. 13
      PublicComponent/src/main/java/com/arialyy/aria/core/config/CommonConfig.kt
  53. 10
      PublicComponent/src/main/java/com/arialyy/aria/core/config/Configuration.java
  54. 29
      PublicComponent/src/main/java/com/arialyy/aria/core/download/DTaskOption.kt
  55. 2
      PublicComponent/src/main/java/com/arialyy/aria/core/inf/IBaseLoader.kt
  56. 27
      PublicComponent/src/main/java/com/arialyy/aria/core/inf/IComponentInit.kt
  57. 1
      PublicComponent/src/main/java/com/arialyy/aria/core/inf/IComponentLoader.kt
  58. 2
      PublicComponent/src/main/java/com/arialyy/aria/core/inf/IEntity.java
  59. 52
      PublicComponent/src/main/java/com/arialyy/aria/core/inf/IStartController.kt
  60. 5
      PublicComponent/src/main/java/com/arialyy/aria/core/inf/ITaskOption.java
  61. 88
      PublicComponent/src/main/java/com/arialyy/aria/core/inf/ITaskQueue.java
  62. 15
      PublicComponent/src/main/java/com/arialyy/aria/core/inf/TaskSchedulerType.java
  63. 3
      PublicComponent/src/main/java/com/arialyy/aria/core/listener/ISchedulers.java
  64. 76
      PublicComponent/src/main/java/com/arialyy/aria/core/listener/ITaskStatusListener.kt
  65. 53
      PublicComponent/src/main/java/com/arialyy/aria/core/manager/ThreadTaskManager.java
  66. 3
      PublicComponent/src/main/java/com/arialyy/aria/core/provider/DuaStartupProvider.kt
  67. 2
      PublicComponent/src/main/java/com/arialyy/aria/core/service/IService.kt
  68. 69
      PublicComponent/src/main/java/com/arialyy/aria/core/service/LifecycleManager.kt
  69. 51
      PublicComponent/src/main/java/com/arialyy/aria/core/service/ServiceManager.kt
  70. 203
      PublicComponent/src/main/java/com/arialyy/aria/core/task/AbsTask.java
  71. 71
      PublicComponent/src/main/java/com/arialyy/aria/core/task/DownloadTask.java
  72. 47
      PublicComponent/src/main/java/com/arialyy/aria/core/task/ITask.java
  73. 90
      PublicComponent/src/main/java/com/arialyy/aria/core/task/TaskState.kt
  74. 36
      PublicComponent/src/main/java/com/arialyy/aria/core/task/TaskStatePool.kt
  75. 4
      PublicComponent/src/main/java/com/arialyy/aria/orm/entity/DEntity.kt
  76. 83
      PublicComponent/src/main/java/com/arialyy/aria/util/CheckUtil.kt
  77. 1
      Queue/.gitignore
  78. 43
      Queue/build.gradle
  79. 0
      Queue/consumer-rules.pro
  80. 21
      Queue/proguard-rules.pro
  81. 24
      Queue/src/androidTest/java/com/arialyy/aria/queue/ExampleInstrumentedTest.kt
  82. 4
      Queue/src/main/AndroidManifest.xml
  83. 264
      Queue/src/main/java/com/arialyy/aria/queue/AbsTaskQueue.java
  84. 97
      Queue/src/main/java/com/arialyy/aria/queue/BaseCachePool.java
  85. 123
      Queue/src/main/java/com/arialyy/aria/queue/BaseExecutePool.java
  86. 53
      Queue/src/main/java/com/arialyy/aria/queue/DTaskQueue.java
  87. 41
      Queue/src/main/java/com/arialyy/aria/queue/IPool.java
  88. 15
      Queue/src/main/java/com/arialyy/aria/queue/QueueComponent.kt
  89. 53
      Queue/src/main/java/com/arialyy/aria/queue/UTaskQueue.java
  90. 2
      Queue/src/main/resources/META-INF/MANIFEST.MF
  91. 1
      Queue/src/main/resources/META-INF/services/com.arialyy.aria.core.inf.IComponentInit
  92. 17
      Queue/src/test/java/com/arialyy/aria/queue/ExampleUnitTest.kt
  93. 1
      Schedulers/.gitignore
  94. 43
      Schedulers/build.gradle
  95. 0
      Schedulers/consumer-rules.pro
  96. 21
      Schedulers/proguard-rules.pro
  97. 24
      Schedulers/src/androidTest/java/com/arialyy/aria/schedulers/ExampleInstrumentedTest.kt
  98. 4
      Schedulers/src/main/AndroidManifest.xml
  99. 2
      Schedulers/src/main/java/com/arialyy/aria/schedulers/AptM3U8PeerTaskListener.java
  100. 2
      Schedulers/src/main/java/com/arialyy/aria/schedulers/AptNormalTaskListener.java
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 AriaLyy(DownloadUtil)
* 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.

@ -16,11 +16,9 @@
package com.arialyy.aria.core;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import com.arialyy.aria.core.command.CommandManager;

@ -15,20 +15,21 @@
*/
package com.arialyy.aria.core
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle.Event
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import com.arialyy.aria.core.common.receiver.LifLifecycleReceiver
import com.arialyy.aria.core.config.Configuration
/**
* @Author laoyuyu
* @Description
* @Date 10:48 AM 2023/1/20
**/
@Deprecated("有问题,微软有dua的工程在github上")// 使用cof? exco?
object Dua {
fun with(lifecycle: LifecycleOwner): LifLifecycleReceiver {
return LifLifecycleReceiver(lifecycle)
}
fun getCommonConfig() = Configuration.getInstance().cCommonCfg
}

@ -17,9 +17,11 @@ package com.arialyy.aria.core.common.receiver
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.arialyy.aria.core.DuaContext
import com.arialyy.aria.core.inf.IComponentLoader
import com.arialyy.aria.core.inf.IDuaReceiver
import com.arialyy.aria.core.scheduler.TaskSchedulers
import com.arialyy.aria.schedulers.TaskSchedulers
import java.lang.reflect.InvocationHandler
import java.lang.reflect.Proxy
/**
@ -34,21 +36,30 @@ class LifLifecycleReceiver(val lifecycle: LifecycleOwner) : IDuaReceiver {
* @param clazz eg: HttpLoader, FtpLoader
*/
fun <T : IComponentLoader> setLoader(clazz: Class<T>): T {
val clazzProxy = Proxy.getProxyClass(
javaClass.classLoader,
*clazz.interfaces
)
val constructor = clazzProxy.getConstructor(InvocationHandler::class.java)
val loader = constructor.newInstance()
DuaContext.getLifeManager().loaderAssociationTarget(lifecycle, loader as IComponentLoader)
return Proxy.newProxyInstance(
javaClass.classLoader, arrayOf(IComponentLoader::class.java)
) { proxy, method, args ->
val result = method.invoke(proxy, args)
) { _, method, args ->
val result = method.invoke(loader, args)
if (method.name in IComponentLoader.proxyMethods) {
lifecycle.lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onCreate(owner: LifecycleOwner) {
super.onCreate(owner)
TaskSchedulers.getInstance()
.register(lifecycle, (proxy as IComponentLoader).getTaskEnum())
com.arialyy.aria.schedulers.TaskSchedulers.getInstance().register(lifecycle, loader.getTaskEnum())
}
override fun onDestroy(owner: LifecycleOwner) {
super.onDestroy(owner)
TaskSchedulers.getInstance().unRegister(lifecycle)
com.arialyy.aria.schedulers.TaskSchedulers.getInstance().unRegister(lifecycle)
DuaContext.getLifeManager().removeLoader(lifecycle)
DuaContext.getLifeManager().removeCustomListener(lifecycle)
}
})
}

@ -1,91 +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.manager
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import com.arialyy.annotations.TaskEnum
import com.arialyy.aria.core.common.ProxyHelper
import com.arialyy.aria.core.download.DownloadGroupTaskListener
import com.arialyy.aria.core.download.DownloadTaskListener
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.util.ALog
import timber.log.Timber
import java.util.Timer
/**
* @Author laoyuyu
* @Description
* @Date 10:55 AM 2023/1/20
**/
object LifecycleManager {
private fun register(obj: Any) {
if (obj is TaskInternalListenerInterface) {
ProxyHelper.getInstance().checkProxyType(obj.javaClass)
if (obj is DownloadTaskListener) {
TaskSchedulers.getInstance().register(obj, TaskEnum.DOWNLOAD)
}
if (obj is DownloadGroupTaskListener) {
TaskSchedulers.getInstance().register(obj, TaskEnum.DOWNLOAD_GROUP)
}
if (obj is M3U8PeerTaskListener) {
TaskSchedulers.getInstance().register(obj, TaskEnum.M3U8_PEER)
}
if (obj is SubTaskListener<*, *>) {
TaskSchedulers.getInstance().register(obj, TaskEnum.DOWNLOAD_GROUP_SUB)
}
return
}
val set: Set<Int> = ProxyHelper.getInstance().checkProxyType(obj.javaClass)
if (set.isNotEmpty()) {
for (type in set) {
when (type) {
ProxyHelper.PROXY_TYPE_DOWNLOAD -> {
TaskSchedulers.getInstance().register(obj, TaskEnum.DOWNLOAD)
}
ProxyHelper.PROXY_TYPE_DOWNLOAD_GROUP -> {
TaskSchedulers.getInstance().register(obj, TaskEnum.DOWNLOAD_GROUP)
}
ProxyHelper.PROXY_TYPE_M3U8_PEER -> {
TaskSchedulers.getInstance().register(obj, TaskEnum.M3U8_PEER)
}
ProxyHelper.PROXY_TYPE_DOWNLOAD_GROUP_SUB -> {
TaskSchedulers.getInstance().register(obj, TaskEnum.DOWNLOAD_GROUP_SUB)
}
}
}
return
}
Timber.e("没有Aria的注解方法,详情见:https://aria.laoyuyu.me/aria_doc/other/annotaion_invalid.html")
}
fun addObserver(lifecycle: Lifecycle) {
lifecycle.addObserver(DuaObserver(lifecycle))
}
private class DuaObserver(val obj: Lifecycle) : DefaultLifecycleObserver {
override fun onCreate(owner: LifecycleOwner) {
super.onCreate(owner)
register(obj)
}
}
}

@ -17,22 +17,19 @@
package com.arialyy.aria.core.queue;
import android.text.TextUtils;
import android.util.Log;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.ITaskQueue;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.manager.TaskWrapperManager;
import com.arialyy.aria.core.manager.ThreadTaskManager;
import com.arialyy.aria.core.queue.pool.BaseCachePool;
import com.arialyy.aria.core.queue.pool.BaseExecutePool;
import com.arialyy.aria.core.queue.pool.DGLoadSharePool;
import com.arialyy.aria.core.queue.pool.DLoadSharePool;
import com.arialyy.aria.core.queue.pool.UploadSharePool;
import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.core.task.DownloadGroupTask;
import com.arialyy.aria.core.task.DownloadTask;
import com.arialyy.aria.core.task.ITask;
import com.arialyy.aria.core.task.UploadTask;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import java.util.ArrayList;
@ -41,8 +38,8 @@ import java.util.List;
/**
* Created by lyy on 2017/2/23. 任务队列
*/
public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends AbsTaskWrapper>
implements ITaskQueue<TASK, TASK_WRAPPER> {
public abstract class AbsTaskQueue<TASK extends ITask>
implements ITaskQueue<TASK> {
final int TYPE_D_QUEUE = 1;
final int TYPE_DG_QUEUE = 2;
final int TYPE_U_QUEUE = 3;
@ -114,7 +111,7 @@ public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends Ab
ALog.w(TAG, "resume task fail, task is null");
return;
}
if (mExecutePool.taskExits(task.getKey())) {
if (mExecutePool.taskExist(task.getKey())) {
ALog.w(TAG, String.format("task【%s】running", task.getKey()));
return;
}
@ -133,7 +130,7 @@ public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends Ab
@Override public void stopAllTask() {
for (TASK task : mExecutePool.getAllTask()) {
if (task != null) {
int state = task.getState();
int state = task.getTaskState();
if (task.isRunning() || (state != IEntity.STATE_COMPLETE
&& state != IEntity.STATE_CANCEL)) {
task.stop(TaskSchedulerType.TYPE_STOP_NOT_NEXT);
@ -194,7 +191,7 @@ public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends Ab
}
@Override public void setMaxTaskNum(int maxNum) {
int oldMaxSize = getOldMaxNum();
int oldMaxSize = getOldMaxSize();
int diff = maxNum - oldMaxSize;
if (oldMaxSize == maxNum) {
ALog.w(TAG, "设置的下载任务数和配置文件的下载任务数一直,跳过");
@ -209,11 +206,11 @@ public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends Ab
}
}
}
mExecutePool.setMaxNum(maxNum);
mExecutePool.setPoolSize(maxNum);
if (diff >= 1) {
for (int i = 0; i < diff; i++) {
TASK nextTask = getNextTask();
if (nextTask != null && nextTask.getState() == IEntity.STATE_WAIT) {
if (nextTask != null && nextTask.getTaskState() == IEntity.STATE_WAIT) {
startTask(nextTask);
}
}
@ -261,7 +258,7 @@ public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends Ab
if (task == null) {
ALog.w(TAG, "create fail, task is null");
}
if (mExecutePool.taskExits(task.getKey())) {
if (mExecutePool.taskExist(task.getKey())) {
ALog.w(TAG, String.format("任务【%s】执行中", task.getKey()));
return;
}
@ -277,7 +274,7 @@ public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends Ab
ALog.w(TAG, "stop fail, task is null");
return;
}
int state = task.getState();
int state = task.getTaskState();
boolean canStop = false;
switch (state) {
case IEntity.STATE_WAIT:
@ -333,7 +330,7 @@ public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends Ab
return;
}
int state = task.getState();
int state = task.getTaskState();
switch (state) {
case IEntity.STATE_POST_PRE:
case IEntity.STATE_PRE:

@ -64,7 +64,7 @@ public class DGroupTaskQueue
@Override public DownloadGroupTask createTask(DGTaskWrapper wrapper) {
super.createTask(wrapper);
DownloadGroupTask task = null;
if (!mCachePool.taskExits(wrapper.getKey()) && !mExecutePool.taskExits(wrapper.getKey())) {
if (!mCachePool.taskExits(wrapper.getKey()) && !mExecutePool.taskExist(wrapper.getKey())) {
task = (DownloadGroupTask) TaskFactory.getInstance()
.createTask(wrapper, TaskSchedulers.getInstance());
addTask(task);
@ -74,7 +74,7 @@ public class DGroupTaskQueue
return task;
}
@Override public int getOldMaxNum() {
public int getOldMaxSize() {
return AriaConfig.getInstance().getDGConfig().oldMaxTaskNum;
}
}

@ -1,131 +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.queue;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.event.DMaxNumEvent;
import com.arialyy.aria.core.event.Event;
import com.arialyy.aria.core.event.EventMsgUtil;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.scheduler.TaskSchedulers;
import com.arialyy.aria.core.task.DownloadTask;
import com.arialyy.aria.util.ALog;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/**
* Created by lyy on 2016/8/17.
* 下载任务队列
*/
public class DTaskQueue extends AbsTaskQueue<DownloadTask, DTaskWrapper> {
private static final String TAG = "DownloadTaskQueue";
private static volatile DTaskQueue INSTANCE = null;
public static DTaskQueue getInstance() {
if (INSTANCE == null) {
synchronized (DTaskQueue.class) {
INSTANCE = new DTaskQueue();
EventMsgUtil.getDefault().register(INSTANCE);
}
}
return INSTANCE;
}
private DTaskQueue() {
}
@Override int getQueueType() {
return TYPE_D_QUEUE;
}
@Event
public void maxTaskNum(DMaxNumEvent event) {
setMaxTaskNum(event.maxNum);
}
@Override public int getOldMaxNum() {
return AriaConfig.getInstance().getDConfig().oldMaxTaskNum;
}
/**
* 设置任务为最高优先级任务
*/
public void setTaskHighestPriority(DownloadTask task) {
task.setHighestPriority(true);
//Map<String, DownloadTask> exeTasks = mExecutePool.getAllTask();
List<DownloadTask> exeTasks = mExecutePool.getAllTask();
if (exeTasks != null && !exeTasks.isEmpty()) {
for (DownloadTask temp : exeTasks) {
if (temp != null && temp.isRunning() && temp.isHighestPriorityTask() && !temp.getKey()
.equals(task.getKey())) {
ALog.e(TAG, "设置最高优先级任务失败,失败原因【任务中已经有最高优先级任务,请等待上一个最高优先级任务完成,或手动暂停该任务】");
task.setHighestPriority(false);
return;
}
}
int maxSize = AriaConfig.getInstance().getDConfig().getMaxTaskNum();
int currentSize = mExecutePool.size();
if (currentSize == 0 || currentSize < maxSize) {
startTask(task);
} else {
Set<DownloadTask> tempTasks = new LinkedHashSet<>();
for (int i = 0; i < maxSize; i++) {
DownloadTask oldTsk = mExecutePool.pollTask();
if (oldTsk != null && oldTsk.isRunning()) {
if (i == maxSize - 1) {
oldTsk.stop(TaskSchedulerType.TYPE_STOP_AND_WAIT);
mCachePool.putTaskToFirst(oldTsk);
break;
}
tempTasks.add(oldTsk);
}
}
startTask(task);
for (DownloadTask temp : tempTasks) {
mExecutePool.putTask(temp);
}
}
}
}
@Override public DownloadTask createTask(DTaskWrapper wrapper) {
super.createTask(wrapper);
DownloadTask task = null;
if (!mCachePool.taskExits(wrapper.getKey()) && !mExecutePool.taskExits(wrapper.getKey())) {
task = (DownloadTask) TaskFactory.getInstance()
.createTask(wrapper, TaskSchedulers.getInstance());
addTask(task);
} else {
ALog.w(TAG, "任务已存在");
}
return task;
}
@Override public void stopTask(DownloadTask task) {
task.setHighestPriority(false);
super.stopTask(task);
}
@Override public int getMaxTaskNum() {
return AriaConfig.getInstance().getDConfig().getMaxTaskNum();
}
}

@ -1,155 +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.queue;
import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.task.DownloadGroupTask;
import com.arialyy.aria.core.task.DownloadTask;
import com.arialyy.aria.core.task.ITask;
import com.arialyy.aria.core.task.UploadTask;
import com.arialyy.aria.core.upload.UTaskWrapper;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
/**
* Created by lyy on 2016/8/16. 任务功能接口
*/
public interface ITaskQueue<TASK extends ITask, TASK_WRAPPER extends AbsTaskWrapper> {
/**
* 通过key跑断任务是在存在
*
* @param key 下载链接或上传文件的路径
* @return {@code true} 任务存在
*/
boolean taskExists(String key);
/**
* 通过key判断任务是否正在执行
*
* @param key 下载链接或上传文件的路径
* @return {@code true} 任务正在运行
*/
boolean taskIsRunning(String key);
/**
* 恢复任务 如果执行队列任务未满则直接启动任务 如果执行队列已经满了则暂停执行队列队首任务并恢复指定任务
*
* @param task 需要恢复飞任务
*/
void resumeTask(TASK task);
/**
* 停止所有任务
*/
void stopAllTask();
/**
* 开始任务
*
* @param task {@link DownloadTask}{@link UploadTask}{@link DownloadGroupTask}
*/
void startTask(TASK task);
/**
* 开始任务
*
* @param action {@link TaskSchedulerType}
*/
void startTask(TASK task, int action);
/**
* 停止任务
*
* @param task {@link DownloadTask}{@link UploadTask}{@link DownloadGroupTask}
*/
void stopTask(TASK task);
/**
* 取消任务
*
* @param task {@link DownloadTask}{@link UploadTask}{@link DownloadGroupTask}
*/
void cancelTask(TASK task);
/**
* 取消任务
*
* @param action {@link TaskSchedulerType}
*/
void cancelTask(TASK task, int action);
/**
* 通过key从队列中删除任务
*
* @param key 如果是下载则为下载链接如果是上传为文件保存路径如果是下载任务组则为任务组名
*/
void removeTaskFormQueue(String key);
/**
* 重试下载
*
* @param task {@link DownloadTask}{@link UploadTask}{@link DownloadGroupTask}
*/
void reTryStart(TASK task);
/**
* 获取当前执行池中的任务数量
*/
int getCurrentExePoolNum();
/**
* 获取当前任务缓存池中的任务数量
*/
int getCurrentCachePoolNum();
/**
* 设置执行池可执行的最大任务数
*
* @param newMaxNum 最大任务数
*/
void setMaxTaskNum(int newMaxNum);
/**
* 获取执行池可执行的最大任务数
*/
int getMaxTaskNum();
/**
* 创建一个缓存任务创建时只是将新任务存储到缓存池
*
* @param wrapper 任务实体{@link DTaskWrapper}{@link UTaskWrapper}{@link DGTaskWrapper}
* @return {@link DownloadTask}{@link UploadTask}{@link DGTaskWrapper}
*/
TASK createTask(TASK_WRAPPER wrapper);
/**
* 通过工作实体缓存池或任务池搜索下载任务如果缓存池或任务池都没有任务则创建新任务
*
* @param key 如果是下载则为下载链接如果是上传为文件保存路径如果是下载任务组则为任务组名
* @return {@link DownloadTask}{@link UploadTask}{@link DownloadGroupTask}
*/
TASK getTask(String key);
/**
* 获取缓存池的下一个任务
*
* @return 下载任务 or null
*/
TASK getNextTask();
}

@ -1,78 +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.queue;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.event.Event;
import com.arialyy.aria.core.event.EventMsgUtil;
import com.arialyy.aria.core.event.UMaxNumEvent;
import com.arialyy.aria.core.scheduler.TaskSchedulers;
import com.arialyy.aria.core.upload.UTaskWrapper;
import com.arialyy.aria.core.task.UploadTask;
import com.arialyy.aria.util.ALog;
/**
* Created by lyy on 2017/2/27. 上传任务队列
*/
public class UTaskQueue extends AbsTaskQueue<UploadTask, UTaskWrapper> {
private static final String TAG = "UploadTaskQueue";
private static volatile UTaskQueue INSTANCE = null;
public static UTaskQueue getInstance() {
if (INSTANCE == null) {
synchronized (UTaskQueue.class) {
INSTANCE = new UTaskQueue();
EventMsgUtil.getDefault().register(INSTANCE);
}
}
return INSTANCE;
}
private UTaskQueue() {
}
@Event
public void maxTaskNum(UMaxNumEvent event){
setMaxTaskNum(event.maxNum);
}
@Override int getQueueType() {
return TYPE_U_QUEUE;
}
@Override public int getOldMaxNum() {
return AriaConfig.getInstance().getUConfig().oldMaxTaskNum;
}
@Override public int getMaxTaskNum() {
return AriaConfig.getInstance().getUConfig().getMaxTaskNum();
}
@Override public UploadTask createTask(UTaskWrapper wrapper) {
super.createTask(wrapper);
UploadTask task = null;
if (!mCachePool.taskExits(wrapper.getKey()) && !mExecutePool.taskExits(wrapper.getKey())) {
task = (UploadTask) TaskFactory.getInstance()
.createTask(wrapper, TaskSchedulers.getInstance());
addTask(task);
} else {
ALog.w(TAG, "任务已存在");
}
return task;
}
}

@ -27,7 +27,7 @@ import com.arialyy.aria.util.CommonUtil;
class DGLoadExecutePool<TASK extends AbsTask> extends DLoadExecutePool<TASK> {
private final String TAG = CommonUtil.getClassName(this);
@Override protected int getMaxSize() {
@Override protected int getPoolSize() {
return AriaConfig.getInstance().getDGConfig().getMaxTaskNum();
}
}

@ -15,6 +15,8 @@
*/
package com.arialyy.aria.core.queue.pool;
import com.arialyy.aria.core.queue.BaseCachePool;
/**
* Created by Aria.Lao on 2017/7/17.
* 下载任务池该池子为简单任务和任务组共用

@ -16,6 +16,7 @@
package com.arialyy.aria.core.queue.pool;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.queue.BaseExecutePool;
import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.util.ALog;
@ -26,7 +27,7 @@ import com.arialyy.aria.util.ALog;
class DLoadExecutePool<TASK extends AbsTask> extends BaseExecutePool<TASK> {
private final String TAG = "DownloadExecutePool";
@Override protected int getMaxSize() {
@Override protected int getPoolSize() {
return AriaConfig.getInstance().getDConfig().getMaxTaskNum();
}

@ -15,6 +15,8 @@
*/
package com.arialyy.aria.core.queue.pool;
import com.arialyy.aria.core.queue.BaseCachePool;
/**
* Created by Aria.Lao on 2017/7/17.
* 下载任务池该池子为简单任务和任务组共用

@ -16,13 +16,14 @@
package com.arialyy.aria.core.queue.pool;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.queue.BaseExecutePool;
import com.arialyy.aria.core.task.AbsTask;
/**
* Created by Aria.Lao on 2017/7/17.
*/
public class UploadExecutePool<TASK extends AbsTask> extends BaseExecutePool<TASK> {
@Override protected int getMaxSize() {
@Override protected int getPoolSize() {
return AriaConfig.getInstance().getUConfig().getMaxTaskNum();
}
}

@ -15,6 +15,8 @@
*/
package com.arialyy.aria.core.queue.pool;
import com.arialyy.aria.core.queue.BaseCachePool;
/**
* Created by Aria.Lao on 2017/7/17.
* 下载任务池该池子为简单任务和任务组共用

@ -17,7 +17,6 @@ package com.arialyy.aria.core.upload.target;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.common.AbsNormalTarget;
import com.arialyy.aria.core.common.ErrorCode;
import com.arialyy.aria.core.event.ErrorEvent;
import com.arialyy.aria.core.inf.AbsTarget;
import com.arialyy.aria.core.inf.IConfigHandler;

@ -0,0 +1,27 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.http
import com.arialyy.aria.http.download.HttpDownloader
/**
* @Author laoyuyu
* @Description
* @Date 12:40 PM 2023/1/22
**/
open class HttpBaseController(val target: Any) {
}

@ -0,0 +1,20 @@
package com.arialyy.aria.http
import android.content.Context
import com.arialyy.aria.core.DuaContext
import com.arialyy.aria.core.inf.IComponentInit
import com.arialyy.aria.queue.DTaskQueue
import com.arialyy.aria.queue.UTaskQueue
/**
* @Author laoyuyu
* @Description
* @Date 3:40 PM 2023/1/26
**/
class HttpComponent : IComponentInit {
override fun init(context: Context) {
DuaContext.getServiceManager().registerService(DuaContext.D_QUEUE, com.arialyy.aria.queue.DTaskQueue.getInstance())
DuaContext.getServiceManager().registerService(DuaContext.U_QUEUE, com.arialyy.aria.queue.UTaskQueue.getInstance())
}
}

@ -16,6 +16,7 @@
package com.arialyy.aria.http
import com.arialyy.annotations.TaskEnum
import com.arialyy.aria.core.DuaContext
import com.arialyy.aria.core.inf.IBaseLoader
import com.arialyy.aria.core.inf.IComponentLoader
import com.arialyy.aria.core.inf.IDownloader
@ -30,7 +31,7 @@ import kotlin.LazyThreadSafetyMode.SYNCHRONIZED
class HttpComponentLoader : IComponentLoader {
private val downloader by lazy(SYNCHRONIZED) {
HttpDownloader()
HttpDownloader(DuaContext.getLifeManager().getTargetByLoader(this)!!)
}
private lateinit var loader: IBaseLoader

@ -22,6 +22,6 @@ package com.arialyy.aria.http
**/
class HttpOption {
fun se
// fun se
}

@ -0,0 +1,52 @@
/*
* 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.http
import com.arialyy.aria.http.download.HttpDTaskOption
import com.arialyy.aria.util.CheckUtil
import timber.log.Timber
/**
* @Author laoyuyu
* @Description
* @Date 12:40 PM 2023/1/22
**/
internal object HttpUtil {
fun checkHttpDParams(option: HttpDTaskOption?): Boolean {
if (option == null) {
Timber.e("option is null")
return false
}
if (option.sourUrl.isNullOrEmpty()) {
Timber.e("url is null")
return false
}
if (!CheckUtil.checkUrl(option.sourUrl!!)) {
Timber.e("invalid url, ${option.sourUrl}")
return false
}
if (option.savePathUri == null) {
Timber.e("save path is null")
return false
}
if (!CheckUtil.checkUri(option.savePathUri)) {
Timber.e("invalid uri, ${option.savePathUri}")
return false
}
return true
}
}

@ -0,0 +1,95 @@
/*
* 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.http.download
import android.net.Uri
import com.arialyy.aria.core.DuaContext
import com.arialyy.aria.core.event.EventMsgUtil
import com.arialyy.aria.core.inf.IStartController
import com.arialyy.aria.core.task.DownloadTask
import com.arialyy.aria.http.HttpBaseController
import com.arialyy.aria.http.HttpOption
import com.arialyy.aria.http.HttpUtil
/**
* @Author laoyuyu
* @Description
* @Date 12:38 PM 2023/1/22
**/
class HttpDStartController(target: Any, val url: String) : HttpBaseController(target),
IStartController {
private var httpDTaskOption = HttpDTaskOption()
init {
httpDTaskOption.sourUrl = url
}
/**
* set http params, link Header
*/
fun setHttpOption(httpOption: HttpOption): HttpBaseController {
httpDTaskOption.httpOption = httpOption
return this
}
fun setListener(listener: HttpDownloadListener): HttpBaseController {
DuaContext.getLifeManager().addCustomListener(target, listener)
return this
}
fun setSavePath(savePath: Uri): HttpDStartController {
httpDTaskOption.savePathUri = savePath
return this
}
private fun createTask(): DownloadTask {
if (HttpUtil.checkHttpDParams(httpDTaskOption)) {
throw IllegalArgumentException("invalid params")
}
val task = DownloadTask()
}
override fun add(): Long {
if (!HttpUtil.checkHttpDParams(httpDTaskOption)) {
return -1
}
EventMsgUtil.getDefault().post()
TODO("Not yet implemented")
}
override fun create(): Long {
if (!HttpUtil.checkHttpDParams(httpDTaskOption)) {
return -1
}
TODO("Not yet implemented")
}
override fun resume(): Long {
if (!HttpUtil.checkHttpDParams(httpDTaskOption)) {
return -1
}
TODO("Not yet implemented")
}
override fun resume(newStart: Boolean): Long {
if (!HttpUtil.checkHttpDParams(httpDTaskOption)) {
return -1
}
TODO("Not yet implemented")
}
}

@ -0,0 +1,29 @@
/*
* 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.http.download
import com.arialyy.aria.core.download.DTaskOption
import com.arialyy.aria.http.HttpOption
/**
* @Author laoyuyu
* @Description
* @Date 12:47 PM 2023/1/22
**/
class HttpDTaskOption : DTaskOption() {
var httpOption: HttpOption? = null
}

@ -0,0 +1,27 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.http.download
import com.arialyy.aria.core.listener.ITaskStatusListener
import com.arialyy.aria.core.task.DownloadTask
/**
* @Author laoyuyu
* @Description
* @Date 12:24 PM 2023/1/22
**/
class HttpDownloadListener : ITaskStatusListener<DownloadTask> {
}

@ -18,36 +18,19 @@ package com.arialyy.aria.http.download
import com.arialyy.annotations.TaskEnum
import com.arialyy.annotations.TaskEnum.DOWNLOAD
import com.arialyy.aria.core.inf.IDownloader
import com.arialyy.aria.http.HttpOption
/**
* @Author laoyuyu
* @Description
* @Date 14:11 AM 2023/1/20
**/
internal class HttpDownloader : IDownloader {
private lateinit var uri: String
private lateinit var savePath: String
private var httpOption = HttpOption()
class HttpDownloader(val target: Any) : IDownloader {
override fun getTaskEnum(): TaskEnum {
return DOWNLOAD
}
fun setSourceUri(uri: String): HttpDownloader {
this.uri = uri
return this
fun load(url: String): HttpDStartController {
return HttpDStartController(target, url)
}
fun setSavePath(savePath: String): HttpDownloader {
this.savePath = savePath
return this
}
fun setHttpOption(httpOption: HttpOption): HttpDownloader {
this.httpOption = httpOption
return this
}
}

@ -36,6 +36,7 @@ dependencies {
implementation(libs.bundles.room)
implementation(libs.startup)
api(libs.timber)
api(libs.annotation)
implementation(libs.gson)
kapt libs.room.compiler
}

@ -16,6 +16,9 @@
package com.arialyy.aria.core
import android.annotation.SuppressLint
import android.content.Context
import com.arialyy.aria.core.service.LifecycleManager
import com.arialyy.aria.core.service.QueueManager
import com.arialyy.aria.core.service.ServiceManager
import kotlinx.coroutines.MainScope
@ -25,14 +28,22 @@ import kotlinx.coroutines.MainScope
* @Date 10:40 AM 2023/1/16
**/
@SuppressLint("StaticFieldLeak")
internal object DuaContext {
object DuaContext {
const val DB_SERVICE = "DB_SERVICE"
const val D_QUEUE = "D_QUEUE"
const val U_QUEUE = "U_QUEUE"
private val serviceArray = arrayOf(DB_SERVICE)
private val serviceArray = arrayOf(DB_SERVICE, D_QUEUE, U_QUEUE)
val duaScope = MainScope()
lateinit var context: Context
fun isService(serviceName: String) = serviceName in serviceArray
fun getServiceManager() = ServiceManager
fun getLifeManager() = LifecycleManager
fun getQueueManger() = QueueManager
}

@ -66,7 +66,7 @@ final public class StartCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
if (mod.equals(QueueMod.NOW.getTag())) {
startTask();
} else if (mod.equals(QueueMod.WAIT.getTag())) {
int state = task.getState();
int state = task.getTaskState();
if (mQueue.getCurrentExePoolNum() < maxTaskNum) {
if (state == IEntity.STATE_STOP
|| state == IEntity.STATE_FAIL

@ -13,6 +13,8 @@ abstract class BaseConfig implements Serializable {
static final int TYPE_APP = 3;
static final int TYPE_DGROUP = 4;
static final int TYPE_COMMON = 100;
/**
* 类型
*
@ -39,6 +41,9 @@ abstract class BaseConfig implements Serializable {
case TYPE_DGROUP:
path = Configuration.DGROUP_CONFIG_FILE;
break;
case TYPE_COMMON:
path = Configuration.COMMON_CONFIG_FILE;
break;
}
if (!TextUtils.isEmpty(path)) {
String tempPath = String.format("%s%s", basePath, path);

@ -0,0 +1,13 @@
package com.arialyy.aria.core.config
/**
* @Author laoyuyu
* @Description
* @Date 10:36 PM 2023/1/24
**/
class CommonConfig : BaseTaskConfig() {
override fun getType(): Int {
return TYPE_COMMON
}
}

@ -30,10 +30,12 @@ public final class Configuration {
static final String UPLOAD_CONFIG_FILE = "/Aria/AriaUpload.cfg";
static final String APP_CONFIG_FILE = "/Aria/AriaApp.cfg";
static final String DGROUP_CONFIG_FILE = "/Aria/AriaDGroup.cfg";
static final String COMMON_CONFIG_FILE = "/Aria/AriaCommon.cfg";
public DownloadConfig downloadCfg;
public UploadConfig uploadCfg;
public AppConfig appCfg;
public DGroupConfig dGroupCfg;
public CommonConfig cCommonCfg;
private Configuration() {
//删除老版本的配置文件
@ -43,6 +45,7 @@ public final class Configuration {
File newUCfg = new File(String.format("%s%s", basePath, UPLOAD_CONFIG_FILE));
File newACfg = new File(String.format("%s%s", basePath, APP_CONFIG_FILE));
File dgCfg = new File(String.format("%s%s", basePath, DGROUP_CONFIG_FILE));
File cCfg = new File(String.format("%s%s", basePath, COMMON_CONFIG_FILE));
// 加载下载配置
if (newDCfg.exists()) {
downloadCfg = (DownloadConfig) FileUtil.readObjFromFile(newDCfg.getPath());
@ -71,6 +74,13 @@ public final class Configuration {
if (dGroupCfg == null) {
dGroupCfg = new DGroupConfig();
}
// 通用配置
if (cCfg.exists()) {
cCommonCfg = (CommonConfig) FileUtil.readObjFromFile(dgCfg.getPath());
}
if (cCommonCfg == null) {
cCommonCfg = new CommonConfig();
}
}
public static Configuration getInstance() {

@ -0,0 +1,29 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.download
import android.net.Uri
import com.arialyy.aria.core.inf.ITaskOption
/**
* @Author laoyuyu
* @Description
* @Date 4:16 PM 2023/1/25
**/
open class DTaskOption : ITaskOption() {
var sourUrl: String? = null
var savePathUri: Uri? = null
}

@ -16,6 +16,7 @@
package com.arialyy.aria.core.inf
import com.arialyy.annotations.TaskEnum
import com.arialyy.aria.core.listener.ITaskStatusListener
/**
* @Author laoyuyu
@ -24,4 +25,5 @@ import com.arialyy.annotations.TaskEnum
**/
interface IBaseLoader {
fun getTaskEnum(): TaskEnum
}

@ -0,0 +1,27 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.inf
import android.content.Context
/**
* @Author laoyuyu
* @Description
* @Date 3:38 PM 2023/1/26
**/
interface IComponentInit {
fun init(context: Context)
}

@ -16,6 +16,7 @@
package com.arialyy.aria.core.inf
import com.arialyy.annotations.TaskEnum
import com.arialyy.aria.core.listener.ITaskStatusListener
/**
* @Author laoyuyu

@ -15,7 +15,7 @@
*/
package com.arialyy.aria.core.inf;
import com.arialyy.aria.orm.annotation.Ignore;
import androidx.room.Ignore;
/**
* Created by lyy on 2017/2/23.

@ -0,0 +1,52 @@
/*
* 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
/**
* @Author laoyuyu
* @Description
* @Date 12:32 PM 2023/1/22
**/
interface IStartController {
/**
* 添加任务
*
* @return 正常添加返回任务id否则返回-1
*/
fun add(): Long
/**
* 创建并开始任务
*
* @return 正常启动返回任务id否则返回-1
*/
fun create(): Long
/**
* 恢复任务
* @return 正常启动返回任务id否则返回-1
*/
fun resume(): Long
/**
* 正常来说当执行队列满时调用恢复任务接口只能将任务放到缓存队列中
* 如果希望调用恢复接口马上进入执行队列需要使用该方法
*
* @param newStart true 立即将任务恢复到执行队列中
* @return 正常启动返回任务id否则返回-1
*/
fun resume(newStart: Boolean): Long
}

@ -15,10 +15,13 @@
*/
package com.arialyy.aria.core.inf;
import com.arialyy.aria.core.listener.IEventListener;
/**
* Created by AriaL on 2017/6/29.
* 任务信息设置接口
*/
public interface ITaskOption {
public abstract class ITaskOption {
public IEventListener taskListener;
}

@ -0,0 +1,88 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.inf;
import com.arialyy.aria.core.service.IService;
import com.arialyy.aria.core.task.ITask;
/**
* Created by lyy on 2016/8/16. 任务功能接口
*/
public interface ITaskQueue<TASK extends ITask> extends IService {
/**
* @return {@code true} task exists
*/
boolean taskExists(int taskId);
/**
* @return {@code true} task is running
*/
boolean taskIsRunning(int taskId);
/**
* stop task
*/
void stopTask(TASK task);
/**
* stop all task
*/
void stopAllTask();
/**
* start a task
*
* @return TaskId is returned if the task is created successfully, and -1 is returned for failure.
*/
int startTask(TASK task);
/**
* remove task
*/
void removeTask(TASK task);
/**
* 重试
*/
void reTry(TASK task);
/**
* get cache queue size
*/
int getCacheSize();
/**
* get process queue size
*/
int getQueueSize();
/**
* modify process queue size
*/
void setQueueSize(int size);
/**
* get task by id
*/
TASK getTask(int taskId);
/**
* get next task
*/
boolean startNextTask();
}

@ -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.inf;
public interface TaskSchedulerType {

@ -19,13 +19,14 @@ package com.arialyy.aria.core.listener;
import android.os.Handler;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.service.IService;
import com.arialyy.aria.core.task.ITask;
import com.arialyy.aria.core.upload.UploadEntity;
/**
* Created by lyy on 2016/11/2. 调度器功能接口
*/
public interface ISchedulers extends Handler.Callback {
public interface ISchedulers extends Handler.Callback, IService {
String ARIA_TASK_INFO_ACTION = "ARIA_TASK_INFO_ACTION";
/**

@ -0,0 +1,76 @@
/*
* 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.listener
import com.arialyy.aria.core.task.ITask
/**
* @Author laoyuyu
* @Description
* @Date 11:43 AM 2023/1/22
**/
interface ITaskStatusListener<TASK : ITask> {
/**
* 队列已经满了继续创建任务将会回调该方法
*/
fun onWait(task: TASK) {}
/**
* 预处理有时有些地址链接比较慢这时可以先在这个地方出来一些界面上的UI如按钮的状态
* 在这个回调中任务是获取不到文件大小下载速度等参数
*/
fun onPre(task: TASK) {}
/**
* 任务预加载完成
*/
fun onTaskPre(task: TASK) {}
/**
* 任务恢复下载
*/
fun onTaskResume(task: TASK) {}
/**
* 任务开始
*/
fun onTaskStart(task: TASK) {}
/**
* 任务停止
*/
fun onTaskStop(task: TASK) {}
/**
* 任务取消
*/
fun onTaskCancel(task: TASK) {}
/**
* 任务失败
*/
fun onTaskFail(task: TASK, e: Exception?) {}
/**
* 任务完成
*/
fun onTaskComplete(task: TASK) {}
/**
* 任务执行中
*/
fun onTaskRunning(task: TASK) {}
}

@ -17,8 +17,8 @@
package com.arialyy.aria.core.manager;
import android.text.TextUtils;
import com.arialyy.aria.core.task.ITask;
import com.arialyy.aria.core.task.IThreadTask;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import java.util.HashSet;
@ -39,8 +39,8 @@ public class ThreadTaskManager {
private static volatile ThreadTaskManager INSTANCE = null;
private static final int CORE_POOL_NUM = 20;
private static final ReentrantLock LOCK = new ReentrantLock();
private ThreadPoolExecutor mExePool;
private Map<String, Set<FutureContainer>> mThreadTasks = new ConcurrentHashMap<>();
private final ThreadPoolExecutor mExePool;
private final Map<Integer, Set<FutureContainer>> mThreadTasks = new ConcurrentHashMap<>();
public static synchronized ThreadTaskManager getInstance() {
if (INSTANCE == null) {
@ -85,21 +85,20 @@ public class ThreadTaskManager {
/**
* 启动线程任务
*
* @param key 任务对应的key{@link AbsTaskWrapper#getKey()}
* @param taskId {@link ITask#getTaskId()}
* @param threadTask 线程任务{@link IThreadTask}
*/
public void startThread(String key, IThreadTask threadTask) {
public void startThread(Integer taskId, IThreadTask threadTask) {
try {
LOCK.tryLock(2, TimeUnit.SECONDS);
if (mExePool.isShutdown()) {
ALog.e(TAG, "线程池已经关闭");
return;
}
key = getKey(key);
Set<FutureContainer> temp = mThreadTasks.get(key);
Set<FutureContainer> temp = mThreadTasks.get(taskId);
if (temp == null) {
temp = new HashSet<>();
mThreadTasks.put(key, temp);
mThreadTasks.put(taskId, temp);
}
FutureContainer container = new FutureContainer();
container.threadTask = threadTask;
@ -115,27 +114,23 @@ public class ThreadTaskManager {
/**
* 任务是否在执行
*
* @param key 任务的key
* @return {@code true} 任务正在运行
*/
public boolean taskIsRunning(String key) {
return mThreadTasks.get(getKey(key)) != null;
public boolean taskIsRunning(Integer taskId) {
return mThreadTasks.get(taskId) != null;
}
/**
* 停止任务的所有线程
*
* @param key 任务对应的key{@link AbsTaskWrapper#getKey()}
*/
public void removeTaskThread(String key) {
public void removeTaskThread(Integer taskId) {
try {
LOCK.tryLock(2, TimeUnit.SECONDS);
if (mExePool.isShutdown()) {
ALog.e(TAG, "线程池已经关闭");
return;
}
key = getKey(key);
Set<FutureContainer> temp = mThreadTasks.get(key);
Set<FutureContainer> temp = mThreadTasks.get(taskId);
if (temp != null && temp.size() > 0) {
for (FutureContainer container : temp) {
if (container.future.isDone() || container.future.isCancelled()) {
@ -144,7 +139,7 @@ public class ThreadTaskManager {
container.threadTask.destroy();
}
temp.clear();
mThreadTasks.remove(key);
mThreadTasks.remove(taskId);
}
} catch (Exception e) {
e.printStackTrace();
@ -156,11 +151,10 @@ public class ThreadTaskManager {
/**
* 根据线程名删除任务的中的线程
*
* @param key 任务的key如果是组合任务则为组合任务的key
* @param threadName 线程名
* @return true 删除线程成功false 删除线程失败
*/
public boolean removeSingleTaskThread(String key, String threadName) {
public boolean removeSingleTaskThread(Integer taskId, String threadName) {
try {
LOCK.tryLock(2, TimeUnit.SECONDS);
if (mExePool.isShutdown()) {
@ -172,8 +166,7 @@ public class ThreadTaskManager {
return false;
}
key = getKey(key);
Set<FutureContainer> temp = mThreadTasks.get(key);
Set<FutureContainer> temp = mThreadTasks.get(taskId);
if (temp != null && temp.size() > 0) {
FutureContainer tempC = null;
for (FutureContainer container : temp) {
@ -199,10 +192,9 @@ public class ThreadTaskManager {
/**
* 删除单个线程任务
*
* @param key 任务的key
* @param task 线程任务
*/
public boolean removeSingleTaskThread(String key, IThreadTask task) {
public boolean removeSingleTaskThread(Integer taskId, IThreadTask task) {
try {
LOCK.tryLock(2, TimeUnit.SECONDS);
if (mExePool.isShutdown()) {
@ -213,8 +205,7 @@ public class ThreadTaskManager {
ALog.e(TAG, "线程任务为空");
return false;
}
key = getKey(key);
Set<FutureContainer> temp = mThreadTasks.get(key);
Set<FutureContainer> temp = mThreadTasks.get(taskId);
if (temp != null && temp.size() > 0) {
FutureContainer tempC = null;
for (FutureContainer container : temp) {
@ -266,17 +257,7 @@ public class ThreadTaskManager {
}
}
/**
* map中的key
*
* @param key 任务的key{@link AbsTaskWrapper#getKey()}
* @return 转换后的map中的key
*/
private String getKey(String key) {
return CommonUtil.getStrMd5(key);
}
private class FutureContainer {
private static class FutureContainer {
Future future;
IThreadTask threadTask;
}

@ -25,8 +25,9 @@ import timber.log.Timber.DebugTree
class DuaStartupProvider : Initializer<Unit> {
override fun create(context: Context) {
DuaContext.context = context
DuaContext.getServiceManager().let {
it.registerService(DuaContext.DB_SERVICE, context, DbService::class.java)
it.registerService(DuaContext.DB_SERVICE, DbService::class.java)
}
initLog()
}

@ -22,7 +22,7 @@ import android.content.Context
* @Description
* @Date 19:34 AM 2023/1/16
**/
internal interface IService {
interface IService {
fun init(context: Context)
}

@ -0,0 +1,69 @@
/*
* 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.service
import com.arialyy.aria.core.inf.IBaseLoader
import com.arialyy.aria.core.inf.IComponentLoader
import com.arialyy.aria.core.listener.ITaskStatusListener
import java.util.concurrent.ConcurrentHashMap
/**
* @Author laoyuyu
* @Description
* @Date 10:55 AM 2023/1/20
**/
object LifecycleManager {
private val listenerMap = ConcurrentHashMap<Any, MutableSet<ITaskStatusListener<*>>>()
private val loaderMap = ConcurrentHashMap<IComponentLoader, Any>()
fun getTargetByLoader(loader: IComponentLoader) = loaderMap[loader]
/**
* Associate the Loader with the Target
*/
fun loaderAssociationTarget(target: Any, loader: IComponentLoader) {
loaderMap[loader] = target
}
fun removeLoader(target: Any) {
val tempKey = mutableListOf<IComponentLoader>()
loaderMap.forEach {
if (it.value == target) {
tempKey.add(it.key)
}
}
tempKey.forEach {
loaderMap.remove(it)
}
}
/**
* Monitoring set by user, [IBaseLoader]
*/
fun <T : ITaskStatusListener<*>> addCustomListener(target: Any, listener: T) {
var listeners = listenerMap[target]
if (listeners == null) {
listeners = hashSetOf()
}
listeners.add(listener)
}
fun removeCustomListener(target: Any) {
listenerMap.remove(target)
}
}

@ -15,32 +15,42 @@
*/
package com.arialyy.aria.core.service
import android.content.Context
import com.arialyy.aria.core.DuaContext
import com.arialyy.aria.queue.ITaskQueue
import com.arialyy.aria.core.service.QueueManager.registerQueue
import com.arialyy.aria.core.task.DownloadTask
import com.arialyy.aria.core.task.UploadTask
import com.arialyy.aria.exception.AriaException
import timber.log.Timber
object ServiceManager {
private val serviceCache = hashMapOf<String, IService>()
private fun getServiceName(clazz: Class<*>) = clazz.name
/**
* register a service
* @param serviceName [DuaContext.DB_SERVICE]
*/
fun <T : IService> registerService(serviceName: String, context: Context, clazz: Class<T>) {
fun <T : IService> registerService(serviceName: String, clazz: Class<T>) {
if (!DuaContext.isService(serviceName)) {
throw AriaException("$serviceName Not a service.")
}
val sn = getServiceName(clazz)
val service = serviceCache[sn]
if (service == null) {
Timber.d("start register service: $sn")
val s = clazz.newInstance()
s.init(context)
serviceCache[serviceName] = s
Timber.d("start register service: $serviceName")
val s = clazz.newInstance()
s.init(DuaContext.context)
serviceCache[serviceName] = s
}
/**
* register a service
* @param serviceName [DuaContext.DB_SERVICE]
*/
fun registerService(serviceName: String, service: IService) {
if (!DuaContext.isService(serviceName)) {
throw AriaException("$serviceName Not a service.")
}
Timber.d("start register service: $serviceName")
service.init(DuaContext.context)
serviceCache[serviceName] = service
}
/**
@ -53,4 +63,23 @@ object ServiceManager {
return (serviceCache[DuaContext.DB_SERVICE]
?: throw AriaException("service not found: ${DuaContext.DB_SERVICE}")) as DbService
}
/**
* get queue service, if already [registerQueue] custom queue, return custom queue
*/
fun getDownloadQueue(): com.arialyy.aria.queue.ITaskQueue<DownloadTask> {
if (!DuaContext.isService(DuaContext.D_QUEUE)) {
throw AriaException("${DuaContext.D_QUEUE} not a queue.")
}
return (serviceCache[DuaContext.D_QUEUE]
?: throw AriaException("queue not found: ${DuaContext.D_QUEUE}")) as com.arialyy.aria.queue.ITaskQueue<DownloadTask>
}
fun getUploadQueue(): com.arialyy.aria.queue.ITaskQueue<UploadTask> {
if (!DuaContext.isService(DuaContext.U_QUEUE)) {
throw AriaException("${DuaContext.U_QUEUE} not a queue.")
}
return (serviceCache[DuaContext.U_QUEUE]
?: throw AriaException("queue not found: ${DuaContext.U_QUEUE}")) as com.arialyy.aria.queue.ITaskQueue<UploadTask>
}
}

@ -15,53 +15,48 @@
*/
package com.arialyy.aria.core.task;
import android.content.Context;
import android.os.Handler;
import android.text.TextUtils;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.ITaskOption;
import com.arialyy.aria.core.inf.IUtil;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.ComponentUtil;
import java.util.HashMap;
import java.util.Map;
import timber.log.Timber;
/**
* Created by AriaL on 2017/6/29.
*/
public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
implements ITask<TASK_WRAPPER> {
public abstract class AbsTask implements ITask {
public static final String ERROR_INFO_KEY = "ERROR_INFO_KEY";
protected String TAG = CommonUtil.getClassName(getClass());
/**
* 是否需要重试默认为false
*/
private boolean needRetry = true;
protected TASK_WRAPPER mTaskWrapper;
protected Handler mOutHandler;
protected Context mContext;
protected boolean isHeighestTask = false;
protected ITaskOption mTaskOption;
private boolean isCancel = false, isStop = false;
private IUtil mUtil;
/**
* 扩展信息
*/
private Map<String, Object> mExpand = new HashMap<>();
/**
* 该任务的调度类型
*/
private int mSchedulerType = TaskSchedulerType.TYPE_DEFAULT;
protected IEventListener mListener;
protected TaskState mTaskState = new TaskState();
private int taskId = -1;
private final Map<String, Object> mExpand = new HashMap<>();
protected AbsTask() {
protected AbsTask(ITaskOption taskOption) {
mTaskOption = taskOption;
taskId = TaskStatePool.INSTANCE.buildTaskId$PublicComponent_debug();
TaskStatePool.INSTANCE.putTaskState(getTaskId(), mTaskState);
}
public Handler getOutHandler() {
return mOutHandler;
@Override public void setState(int state) {
mTaskState.setState(state);
}
synchronized IUtil getUtil() {
@ -71,12 +66,20 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
return mUtil;
}
@Override public <T extends ITaskOption> T getTaskOption(Class<T> clazz) {
return (T) mTaskOption;
}
@Override public int getTaskId() {
return taskId;
}
/**
* 获取剩余时间单位s
* 如果是m3u8任务无法获取剩余时间m2u8任务如果需要获取剩余时间请设置文件长度{@link AbsEntity#setFileSize(long)}
*/
public int getTimeLeft() {
return getTaskWrapper().getEntity().getTimeLeft();
return mTaskState.getTimeLeft();
}
/**
@ -87,7 +90,7 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
* 时间 7 显示样式
*/
public String getConvertTimeLeft() {
return CommonUtil.formatTime(getTaskWrapper().getEntity().getTimeLeft());
return CommonUtil.formatTime(getTimeLeft());
}
/**
@ -95,42 +98,30 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
*/
public void putExpand(String key, Object obj) {
if (TextUtils.isEmpty(key)) {
ALog.e(TAG, "key 为空");
Timber.e("key 为空");
return;
} else if (obj == null) {
ALog.i(TAG, "扩展数据为空");
}
if (obj == null) {
Timber.w("扩展数据为空");
return;
}
mExpand.put(key, obj);
}
@Override public boolean isNeedRetry() {
return needRetry;
public Object getExpand(String key) {
return mExpand.get(key);
}
public void setNeedRetry(boolean needRetry) {
this.needRetry = needRetry;
public TaskState getTaskState() {
return mTaskState;
}
/**
* 最高优先级命令最高优先级命令有以下属性
* 1在下载队列中有且只有一个最高优先级任务
* 2最高优先级任务会一直存在直到用户手动暂停或任务完成
* 3任务调度器不会暂停最高优先级任务
* 4用户手动暂停或任务完成后第二次重新执行该任务该命令将失效
* 5如果下载队列中已经满了则会停止队尾的任务
* 6把任务设置为最高优先级任务后将自动执行任务不需要重新调用start()启动任务
*/
public void setHighestPriority(boolean isHighestPriority) {
isHeighestTask = isHighestPriority;
@Override public boolean isNeedRetry() {
return needRetry;
}
/**
* 读取扩展数据
*/
@Override
public Object getExpand(String key) {
return mExpand.get(key);
public void setNeedRetry(boolean needRetry) {
this.needRetry = needRetry;
}
/**
@ -139,14 +130,14 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
* @return {@code true} 已经完成{@code false} 未完成
*/
public boolean isComplete() {
return mTaskWrapper.getEntity().isComplete();
return mTaskState.isComplete();
}
/**
* 获取当前下载进度
*/
public long getCurrentProgress() {
return mTaskWrapper.getEntity().getCurrentProgress();
return mTaskState.getCurProgress();
}
/**
@ -155,29 +146,17 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
* @return 已经下载3mb的大小则返回{@code 3mb}
*/
public String getConvertCurrentProgress() {
if (mTaskWrapper.getEntity().getCurrentProgress() == 0) {
if (getCurrentProgress() == 0) {
return "0b";
}
return CommonUtil.formatFileSize(mTaskWrapper.getEntity().getCurrentProgress());
}
/**
* 转换单位后的文件长度
*
* @return 如果文件长度为0则返回0m否则返回转换后的长度1b1kb1mb1gb1tb
*/
public String getConvertFileSize() {
if (mTaskWrapper.getEntity().getFileSize() == 0) {
return "0mb";
}
return CommonUtil.formatFileSize(mTaskWrapper.getEntity().getFileSize());
return CommonUtil.formatFileSize(getCurrentProgress());
}
/**
* 获取文件大小
*/
public long getFileSize() {
return mTaskWrapper.getEntity().getFileSize();
return mTaskState.getFileSize();
}
/**
@ -186,62 +165,36 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
* @return 返回百分比进度如果文件长度为0返回0
*/
public int getPercent() {
return mTaskWrapper.getEntity().getPercent();
}
/**
* 任务当前状态
*
* @return {@link IEntity}
*/
public int getState() {
return mTaskWrapper.getState();
}
/**
* 获取保存的扩展字段
*
* @return 如果实体不存在则返回null否则返回扩展字段
*/
public String getExtendField() {
return mTaskWrapper.getEntity() == null ? null : mTaskWrapper.getEntity().getStr();
}
@Override public void start() {
start(TaskSchedulerType.TYPE_DEFAULT);
return mTaskState.getPercent();
}
@Override public void start(int type) {
mSchedulerType = type;
mUtil = getUtil();
if (mUtil == null) {
ALog.e(TAG, "任务工具创建失败");
Timber.e("util is null");
return;
}
if (type == TaskSchedulerType.TYPE_START_AND_RESET_STATE) {
if (getUtil().isRunning()) {
ALog.e(TAG, String.format("任务【%s】重启失败", getTaskName()));
Timber.e("task restart fail");
return;
}
mUtil.start();
ALog.d(TAG, String.format("任务【%s】重启成功", getTaskName()));
Timber.e("task restart success");
return;
}
if (getUtil().isRunning()) {
ALog.d(TAG, "任务正在下载");
} else {
getUtil().start();
Timber.d("task is running");
return;
}
}
@Override public void stop() {
stop(TaskSchedulerType.TYPE_DEFAULT);
getUtil().start();
}
@Override public void stop(int type) {
mUtil = getUtil();
if (mUtil == null) {
ALog.e(TAG, "任务工具创建失败");
Timber.e("util is null");
return;
}
isStop = true;
@ -249,14 +202,10 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
getUtil().stop();
}
@Override public void cancel() {
cancel(TaskSchedulerType.TYPE_DEFAULT);
}
@Override public void cancel(int type) {
mUtil = getUtil();
if (mUtil == null) {
ALog.e(TAG, "任务工具创建失败");
Timber.e("util is null");
return;
}
isCancel = true;
@ -302,52 +251,32 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
}
/**
* @return 返回原始byte速度需要你在配置文件中配置
* <pre>
* {@code
* <xml>
* <download>
* ...
* <convertSpeed value="false"/>
* </download>
*
* 或在代码中设置
* Aria.get(this).getDownloadConfig().setConvertSpeed(false);
* </xml>
* }
* </pre>
* 才能生效
* Bytes transferred in 1 second, if file size 0, return 0
* curSpeed, unit: byte/s
*/
public long getSpeed() {
return mTaskWrapper.getEntity().getSpeed();
return mTaskState.getSpeed();
}
/**
* @return 返回转换单位后的速度需要你在配置文件中配置转换完成后为1b/s1kb/s1mb/s1gb/s1tb/s
* you need set params in config
*
* @return Returns the converted speed:1b/s1kb/s1mb/s1gb/s1tb/s
* xml:
* <pre>
* {@code
* <xml>
* <download>
* ...
* <convertSpeed value="true"/>
* </download>
* `<xml>
* <download>
* ...
* <convertSpeed value="true"/>
* </download>
*
* code:
* Dua.getCommonConfig().setConvertSpeed(true);
* </xml>
*
* 或在代码中设置
* Aria.get(this).getDownloadConfig().setConvertSpeed(true);
* </xml>
* }
* </pre>
* 才能生效
*/
public String getConvertSpeed() {
return mTaskWrapper.getEntity().getConvertSpeed();
}
@Override public TASK_WRAPPER getTaskWrapper() {
return mTaskWrapper;
}
public boolean isHighestPriorityTask() {
return isHeighestTask;
return mTaskState.getConvertSpeed();
}
}

@ -16,84 +16,33 @@
package com.arialyy.aria.core.task;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.listener.ISchedulers;
import com.arialyy.aria.util.ComponentUtil;
import com.arialyy.aria.core.download.DTaskOption;
/**
* Created by lyy on 2016/8/11.
* 下载任务类
*/
public class DownloadTask extends AbsTask<DTaskWrapper> {
public class DownloadTask extends AbsTask {
private DownloadTask(DTaskWrapper taskWrapper, Handler outHandler) {
mTaskWrapper = taskWrapper;
mOutHandler = outHandler;
mContext = AriaConfig.getInstance().getAPP();
mListener =
ComponentUtil.getInstance().buildListener(taskWrapper.getRequestType(), this, mOutHandler);
private DownloadTask(DTaskOption taskOption) {
super(taskOption);
taskOption.taskListener.setParams(this, outHandler);
}
/**
* 获取文件保存路径
*/
public String getFilePath() {
return mTaskWrapper.getEntity().getFilePath();
public Uri getSavePath() {
return getTaskOption(DTaskOption.class).getSavePathUri();
}
public DownloadEntity getEntity() {
return mTaskWrapper.getEntity();
public String getSourceUrl() {
return getTaskOption(DTaskOption.class).getSourUrl();
}
/**
* 获取当前下载任务的下载地址
*
* @see DownloadTask#getKey()
*/
@Deprecated public String getDownloadUrl() {
return mTaskWrapper.getEntity().getUrl();
}
@Override public int getTaskType() {
return ITask.DOWNLOAD;
}
@Override public String getKey() {
return mTaskWrapper.getEntity().getKey();
}
public DownloadEntity getDownloadEntity() {
return mTaskWrapper.getEntity();
}
@Override public String getTaskName() {
return mTaskWrapper.getEntity().getFileName();
}
public static class Builder {
DTaskWrapper taskEntity;
Handler outHandler;
public Builder(DTaskWrapper taskEntity) {
this.taskEntity = taskEntity;
}
/**
* 设置自定义Handler处理下载状态时间
*
* @param schedulers {@link ISchedulers}
*/
public Builder setOutHandler(ISchedulers schedulers) {
outHandler = new Handler(Looper.getMainLooper(), schedulers);
return this;
}
public DownloadTask build() {
return new DownloadTask(taskEntity, outHandler);
}
}
}

@ -15,13 +15,13 @@
*/
package com.arialyy.aria.core.task;
import com.arialyy.aria.core.inf.ITaskOption;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
/**
* Created by lyy on 2017/2/13.
*/
public interface ITask<TASK_WRAPPER extends AbsTaskWrapper> {
public interface ITask {
/**
* 普通下载任务
@ -59,15 +59,12 @@ public interface ITask<TASK_WRAPPER extends AbsTaskWrapper> {
*/
int getTaskType();
/**
* 获取下载状态
*/
int getState();
void setState(int state);
/**
* 唯一标识符DownloadTask 为下载地址UploadTask 为文件路径
* 获取下载状态
*/
String getKey();
TaskState getTaskState();
/**
* 任务是否正在执行
@ -76,16 +73,6 @@ public interface ITask<TASK_WRAPPER extends AbsTaskWrapper> {
*/
boolean isRunning();
/**
* 获取信息实体
*/
TASK_WRAPPER getTaskWrapper();
/**
* 启动任务
*/
void start();
/**
* 启动任务
*
@ -93,11 +80,6 @@ public interface ITask<TASK_WRAPPER extends AbsTaskWrapper> {
*/
void start(int type);
/**
* 停止任务
*/
void stop();
/**
* 停止任务
*
@ -105,11 +87,6 @@ public interface ITask<TASK_WRAPPER extends AbsTaskWrapper> {
*/
void stop(int type);
/**
* 删除任务
*/
void cancel();
/**
* 停止任务
*
@ -117,11 +94,6 @@ public interface ITask<TASK_WRAPPER extends AbsTaskWrapper> {
*/
void cancel(int type);
/**
* 读取扩展数据
*/
Object getExpand(String key);
/**
* 任务是否停止了
*
@ -143,14 +115,13 @@ public interface ITask<TASK_WRAPPER extends AbsTaskWrapper> {
*/
boolean isNeedRetry();
/**
* 获取任务名也就是文件名
*/
String getTaskName();
/**
* 任务的调度类型
* {@link TaskSchedulerType}
*/
int getSchedulerType();
int getTaskId();
<T extends ITaskOption> T getTaskOption(Class<T> clazz);
}

@ -0,0 +1,90 @@
/*
* 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.task
import com.arialyy.aria.core.config.Configuration
import com.arialyy.aria.core.inf.IEntity
import com.arialyy.aria.util.CommonUtil
/**
* @Author laoyuyu
* @Description
* @Date 10:04 PM 2023/1/24
**/
class TaskState {
var state: Int = IEntity.STATE_WAIT
/**
* current task progress, unit: byte
*/
var curProgress: Long = 0
/**
* Bytes transferred in 1 second, if file size 0, return 0
* curSpeed, unit: byte/s
*/
var speed: Long = 0
get() {
return if (fileSize == 0L) 0 else field
}
set(value) {
if (value <= 0L) {
timeLeft = Int.MAX_VALUE
field = 0L
return
}
if (fileSize == 0L) {
timeLeft = Int.MAX_VALUE
}
timeLeft = ((fileSize - curProgress) / value).toInt()
field = value
}
var fileSize: Long = 0
/**
* task time left, unit: s
*/
var timeLeft: Int = Int.Companion.MAX_VALUE
fun getPercent() = ((curProgress * 100) / fileSize).toInt()
fun isComplete() = state == IEntity.STATE_COMPLETE
/**
* you need set params in config
* @return Returns the converted speed:1b/s1kb/s1mb/s1gb/s1tb/s
* xml:
* <pre>
* `<xml>
* <download>
* ...
* <convertSpeed value="true"/>
* </download>
*
* code:
* Dua.getCommonConfig().setConvertSpeed(true);
* </xml>
*
* </pre>
*/
fun getConvertSpeed(): String {
if (Configuration.getInstance().cCommonCfg.isConvertSpeed) {
return CommonUtil.formatFileSize((if (speed < 0L) 0L else speed.toDouble()) as Double) + "/s"
}
return "0b/s"
}
}

@ -0,0 +1,36 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.task
import java.util.concurrent.atomic.AtomicInteger
/**
* @Author laoyuyu
* @Description
* @Date 10:03 PM 2023/1/24
**/
object TaskStatePool {
private val stateMap = hashMapOf<Int, TaskState>()
private val taskCounter = AtomicInteger(1)
fun putTaskState(taskId: Int, state: TaskState) {
stateMap[taskId] = state
}
fun getTaskState(taskId: Int) = stateMap[taskId]
internal fun buildTaskId() = taskCounter.addAndGet(1)
}

@ -16,9 +16,9 @@
package com.arialyy.aria.orm.entity
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.Index
import androidx.room.PrimaryKey
import com.arialyy.aria.core.inf.IEntity
/**
* Download Entity
@ -47,4 +47,4 @@ data class DEntity(
val createTime: Long,
val updateTime: Long
)
) : IEntity

@ -0,0 +1,83 @@
/*
* 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.util
import android.database.Cursor
import android.net.Uri
import com.arialyy.aria.core.DuaContext
import timber.log.Timber
import java.io.InputStream
object CheckUtil {
val HTTP_REGEX =
Regex(
"(https?)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]",
RegexOption.IGNORE_CASE
)
/**
* check if url is correct
*/
fun checkUrl(url: String) = HTTP_REGEX.matches(url)
/**
* 1. Check if Uri is correct
* 2. Whether the file corresponding to Uri exists (may be deleted, or the system db has Uri related records, but the file is invalid or damaged)
*
* https://stackoverflow.com/questions/7645951/how-to-check-if-resource-pointed-by-uri-is-available
*/
fun checkUri(uri: Uri?): Boolean {
if (uri == null) return false
val resolver = DuaContext.context.contentResolver
//1. Check Uri
var cursor: Cursor? = null
val isUriExist: Boolean = try {
cursor = resolver.query(uri, null, null, null, null)
//cursor null: content Uri was invalid or some other error occurred
//cursor.moveToFirst() false: Uri was ok but no entry found.
(cursor != null && cursor.moveToFirst())
} catch (t: Throwable) {
Timber.e("1.Check Uri Error: ${t.message}")
false
} finally {
try {
cursor?.close()
} catch (t: Throwable) {
}
}
//2. Check File Exist
//如果系统 db 存有 Uri 相关记录, 但是文件失效或者损坏 (If the system db has Uri related records, but the file is invalid or damaged)
var ins: InputStream? = null
val isFileExist: Boolean = try {
ins = resolver.openInputStream(uri)
// file exists
true
} catch (t: Throwable) {
// File was not found eg: open failed: ENOENT (No such file or directory)
Timber.e("2. Check File Exist Error: ${t.message}")
false
} finally {
try {
ins?.close()
} catch (t: Throwable) {
}
}
return isUriExist && isFileExist
}
}

1
Queue/.gitignore vendored

@ -0,0 +1 @@
/build

@ -0,0 +1,43 @@
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
}
android {
compileSdkVersion libs.versions.compilesdk.get().toInteger()
buildToolsVersion libs.versions.buildToolsVersion.get()
namespace 'com.arialyy.aria.queue'
defaultConfig {
minSdkVersion libs.versions.minSdk.get().toInteger()
targetSdkVersion libs.versions.targetsdk.get().toInteger()
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError false
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(path: ':PublicComponent')
testImplementation(libs.junit)
androidTestImplementation(libs.bundles.android.test)
}
//apply from: 'bintray-release.gradle'
ext {
PUBLISH_ARTIFACT_ID = 'queue'
}
apply from: '../gradle/mavenCentral-release.gradle'

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

@ -0,0 +1,24 @@
package com.arialyy.aria.queue
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.arialyy.aria.queue.test", appContext.packageName)
}
}

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>

@ -0,0 +1,264 @@
/*
* 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.queue;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.ITaskQueue;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.manager.ThreadTaskManager;
import com.arialyy.aria.core.task.ITask;
import timber.log.Timber;
/**
* Created by lyy on 2017/2/23. 任务队列
*/
public abstract class AbsTaskQueue<TASK extends ITask> implements ITaskQueue<TASK> {
private final IPool<TASK> DEF_CACHE_POOL = new BaseCachePool<>();
private final IPool<TASK> DEF_EXE_POOL = new BaseExecutePool<>();
private int maxSize;
protected AbsTaskQueue() {
maxSize = getMaxTaskSize();
}
protected IPool<TASK> getCachePool() {
return DEF_CACHE_POOL;
}
protected IPool<TASK> getExePool() {
return DEF_EXE_POOL;
}
protected abstract int getMaxTaskSize();
@Override public boolean taskExists(int taskId) {
return getCachePool().taskExist(taskId) || getExePool().taskExist(taskId);
}
/**
* @return if cachePool or exePool has task, return true, otherwise false
*/
@Override public boolean taskIsRunning(int taskId) {
if (getCachePool().getTask(taskId) != null) {
return true;
}
TASK task = getExePool().getTask(taskId);
if (task == null && ThreadTaskManager.getInstance().taskIsRunning(taskId)) {
ThreadTaskManager.getInstance().removeTaskThread(taskId);
}
return task != null && task.isRunning() && taskExists(taskId);
}
@Override public int startTask(TASK task) {
if (task == null) {
Timber.e("task is null");
return -1;
}
if (getExePool().taskExist(task.getTaskId())) {
Timber.w("task running, taskId: %s", task.getTaskId());
return task.getTaskId();
}
Timber.i("start a task, taskId: %s", task.getTaskId());
if (getExePool().size() >= getMaxTaskSize()) {
Timber.i("exe queue is full, task into cache queue");
task.setState(IEntity.STATE_WAIT);
boolean b = getCachePool().putTask(task);
return b ? task.getTaskId() : -1;
}
boolean b = getExePool().putTask(task);
task.start(TaskSchedulerType.TYPE_DEFAULT);
return b ? task.getTaskId() : -1;
}
@Override public void removeTask(TASK task) {
if (task == null) {
Timber.e("task is null");
return;
}
if (getCachePool().taskExist(task.getTaskId())) {
Timber.i("cache pool has task, which will be removed from the cache pool");
getCachePool().removeTask(task.getTaskId());
}
if (getExePool().taskExist(task.getTaskId())) {
stopTask(task);
getExePool().removeTask(task.getTaskId());
}
}
/**
* 停止所有任务
*/
@Override public void stopAllTask() {
for (TASK task : getExePool().getAllTask()) {
if (task != null) {
int state = task.getTaskState().getState();
if (task.isRunning()
|| (state != IEntity.STATE_COMPLETE && state != IEntity.STATE_CANCEL)) {
task.stop(TaskSchedulerType.TYPE_STOP_NOT_NEXT);
}
}
}
for (TASK task : getCachePool().getAllTask()) {
if (task != null) {
task.stop(TaskSchedulerType.TYPE_STOP_NOT_NEXT);
}
}
ThreadTaskManager.getInstance().removeAllThreadTask();
getCachePool().clear();
}
/**
* 获取配置文件旧的最大任务数
*/
public abstract int getOldMaxSize();
@Override public void stopTask(TASK task) {
if (task == null) {
Timber.e("stop fail, task is null");
return;
}
int state = task.getTaskState().getState();
boolean canStop = false;
switch (state) {
case IEntity.STATE_WAIT:
getCachePool().removeTask(task.getTaskId());
canStop = true;
break;
case IEntity.STATE_POST_PRE:
case IEntity.STATE_PRE:
case IEntity.STATE_RUNNING:
getExePool().removeTask(task.getTaskId());
canStop = true;
break;
case IEntity.STATE_STOP:
case IEntity.STATE_OTHER:
case IEntity.STATE_FAIL:
Timber.w("stop task fail,it already topped, taskId: %d", task.getTaskId());
if (taskIsRunning(task.getTaskId())) {
getCachePool().removeTask(task.getTaskId());
getExePool().removeTask(task.getTaskId());
if (ThreadTaskManager.getInstance().taskIsRunning(task.getTaskId())) {
ThreadTaskManager.getInstance().removeTaskThread(task.getTaskId());
}
}
break;
case IEntity.STATE_CANCEL:
Timber.w("stop task fail, it already removed, taskId: %d", task.getTaskId());
break;
case IEntity.STATE_COMPLETE:
Timber.w("stop task fail, it already completed, taskId: %d", task.getTaskId());
break;
}
if (canStop) {
task.stop(TaskSchedulerType.TYPE_DEFAULT);
}
}
@Override public void reTry(TASK task) {
if (task == null) {
Timber.e("task is null");
return;
}
int state = task.getTaskState().getState();
switch (state) {
case IEntity.STATE_POST_PRE:
case IEntity.STATE_PRE:
case IEntity.STATE_RUNNING:
Timber.w("task is running, will restart task, taskId: %d", task.getTaskId());
task.stop(TaskSchedulerType.TYPE_STOP_NOT_NEXT);
task.start(TaskSchedulerType.TYPE_DEFAULT);
break;
case IEntity.STATE_WAIT:
case IEntity.STATE_STOP:
case IEntity.STATE_OTHER:
case IEntity.STATE_FAIL:
task.start(TaskSchedulerType.TYPE_DEFAULT);
break;
case IEntity.STATE_CANCEL:
Timber.e("retry task fail, it already removed, taskId: %d", task.getTaskId());
break;
case IEntity.STATE_COMPLETE:
Timber.e("retry task fail, it already completed, taskId: %d", task.getTaskId());
break;
}
}
@Override public int getCacheSize() {
return getCachePool().size();
}
@Override public int getQueueSize() {
return getExePool().size();
}
@Override public void setQueueSize(int size) {
int oldMaxSize = getOldMaxSize();
int diff = maxSize - oldMaxSize;
if (oldMaxSize == maxSize) {
Timber.w("There is no change in size");
return;
}
maxSize = size;
//设置的任务数小于配置任务数
if (diff <= -1 && getExePool().size() >= oldMaxSize) {
for (int i = 0, len = Math.abs(diff); i < len; i++) {
TASK eTask = getExePool().pollTask();
if (eTask != null) {
stopTask(eTask);
}
}
}
getExePool().setPoolSize(maxSize);
if (diff >= 1) {
for (int i = 0; i < diff; i++) {
startNextTask();
}
}
}
@Override public TASK getTask(int taskId) {
if (taskId < 1) {
Timber.e("invalid taskId: %d", taskId);
return null;
}
TASK ct = getCachePool().getTask(taskId);
if (ct != null) {
return ct;
}
TASK et = getExePool().getTask(taskId);
if (et != null) {
return et;
}
Timber.w("not found task, taskId: %d", taskId);
return null;
}
@Override public boolean startNextTask() {
TASK nextTask = getCachePool().pollTask();
if (nextTask != null && nextTask.getTaskState().getState() == IEntity.STATE_WAIT) {
return startTask(nextTask) != -1;
}
Timber.w("start next fail");
return false;
}
}

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 AriaLyy(DownloadUtil)
* 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.
@ -14,33 +14,33 @@
* limitations under the License.
*/
package com.arialyy.aria.core.queue.pool;
package com.arialyy.aria.queue;
import android.text.TextUtils;
import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.core.task.ITask;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.concurrent.LinkedBlockingDeque;
import timber.log.Timber;
/**
* Created by lyy on 2016/8/14. 任务缓存池所有下载任务最先缓存在这个池中
*/
public class BaseCachePool<TASK extends AbsTask> implements IPool<TASK> {
private final String TAG = CommonUtil.getClassName(this);
public class BaseCachePool<TASK extends ITask> implements IPool<TASK> {
private static final int MAX_NUM = Integer.MAX_VALUE; //最大下载任务数
private static final Object LOCK = new Object();
private Deque<TASK> mCacheQueue;
private int mSize;
BaseCachePool() {
mSize = getPoolSize();
mCacheQueue = new LinkedBlockingDeque<>(MAX_NUM);
}
/**
* 获取被缓存的任务
*/
@Override
public List<TASK> getAllTask() {
return new ArrayList<>(mCacheQueue);
}
@ -48,6 +48,7 @@ public class BaseCachePool<TASK extends AbsTask> implements IPool<TASK> {
/**
* 清除所有缓存的任务
*/
@Override
public void clear() {
mCacheQueue.clear();
}
@ -55,24 +56,39 @@ public class BaseCachePool<TASK extends AbsTask> implements IPool<TASK> {
/**
* 将任务放在队首
*/
public boolean putTaskToFirst(TASK task) {
return mCacheQueue.offerFirst(task);
public void putTaskToFirst(TASK task) {
mCacheQueue.offerFirst(task);
}
@Override public void setPoolSize(int newSize) {
synchronized (LOCK) {
Deque<TASK> temp = new LinkedBlockingDeque<>(newSize);
TASK task;
while ((task = mCacheQueue.poll()) != null) {
temp.offer(task);
}
mCacheQueue = temp;
mSize = newSize;
}
}
@Override public int getPoolSize() {
return MAX_NUM;
}
@Override public boolean putTask(TASK task) {
synchronized (LOCK) {
if (task == null) {
ALog.e(TAG, "任务不能为空!!");
Timber.e("task is null");
return false;
}
if (mCacheQueue.contains(task)) {
ALog.w(TAG, "任务【" + task.getTaskName() + "】进入缓存队列失败,原因:已经在缓存队列中");
Timber.e("put task fail, it is already in the queue, taskId: %d", task.getTaskId());
return false;
} else {
boolean s = mCacheQueue.offer(task);
ALog.d(TAG, "任务【" + task.getTaskName() + "】进入缓存队列" + (s ? "成功" : "失败"));
return s;
}
boolean s = mCacheQueue.offer(task);
Timber.e("put the task in the cache %s", (s ? "success" : "fail"));
return s;
}
}
@ -82,44 +98,35 @@ public class BaseCachePool<TASK extends AbsTask> implements IPool<TASK> {
}
}
@Override public TASK getTask(String key) {
synchronized (LOCK) {
if (TextUtils.isEmpty(key)) {
ALog.e(TAG, "key 为null");
return null;
}
for (TASK task : mCacheQueue) {
if (task.getKey().equals(key)) {
return task;
}
@Override public TASK getTask(int taskId) {
if (taskId <= 0) {
Timber.e("invalid taskId: %s", taskId);
return null;
}
for (TASK task : mCacheQueue) {
if (task.getTaskId() == taskId) {
return task;
}
}
Timber.w("not found task, taskId: %s", taskId);
return null;
}
@Override public boolean taskExits(String key) {
return getTask(key) != null;
}
@Override public boolean removeTask(TASK task) {
synchronized (LOCK) {
if (task == null) {
ALog.e(TAG, "任务不能为空");
return false;
} else {
return mCacheQueue.remove(task);
}
@Override public boolean taskExist(int taskId) {
if (taskId <= 0) {
Timber.e("invalid taskId: %s", taskId);
return false;
}
return getTask(taskId) != null;
}
@Override public boolean removeTask(String key) {
synchronized (LOCK) {
if (TextUtils.isEmpty(key)) {
ALog.e(TAG, "请传入有效的下载链接");
return false;
}
return mCacheQueue.remove(getTask(key));
@Override public boolean removeTask(int taskId) {
if (taskId <= 0) {
Timber.e("invalid taskId: %s", taskId);
return false;
}
return mCacheQueue.remove(getTask(taskId));
}
@Override public int size() {

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 AriaLyy(DownloadUtil)
* 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.
@ -14,44 +14,42 @@
* limitations under the License.
*/
package com.arialyy.aria.core.queue.pool;
package com.arialyy.aria.queue;
import android.text.TextUtils;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.task.ITask;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.concurrent.LinkedBlockingDeque;
import timber.log.Timber;
/**
* Created by lyy on 2016/8/15. 任务执行池所有当前下载任务都该任务池中默认下载大小为2
*/
public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
private final String TAG = CommonUtil.getClassName(this);
public class BaseExecutePool<TASK extends ITask> implements IPool<TASK> {
private static final int MAX_NUM = 2; //max task size
private static final Object LOCK = new Object();
Deque<TASK> mExecuteQueue;
int mSize;
private Deque<TASK> mExecuteQueue;
private int mSize;
BaseExecutePool() {
mSize = getMaxSize();
mSize = getPoolSize();
mExecuteQueue = new LinkedBlockingDeque<>(mSize);
}
/**
* 获取最大任务数配置
*
* @return {@link AriaManager#getDownloadConfig()} {@link AriaManager#getUploadConfig()}如果不设置默认返回2
* return max queue size
*/
protected int getMaxSize() {
return 2;
@Override
public int getPoolSize() {
return MAX_NUM;
}
/**
* 获取所有正在执行的任务
*/
@Override
public List<TASK> getAllTask() {
return new ArrayList<>(mExecuteQueue);
}
@ -59,39 +57,37 @@ public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
@Override public boolean putTask(TASK task) {
synchronized (LOCK) {
if (task == null) {
ALog.e(TAG, "任务不能为空!!");
Timber.e("task is null");
return false;
}
if (mExecuteQueue.contains(task)) {
ALog.e(TAG, "任务【" + task.getTaskName() + "】进入执行队列失败,原因:已经在执行队列中");
Timber.e("put task fail: %s is already in the queue", task.getTaskId());
return false;
} else {
if (mExecuteQueue.size() >= mSize) {
if (pollFirstTask()) {
return putNewTask(task);
}
} else {
return putNewTask(task);
}
}
if (mExecuteQueue.size() >= mSize && pollFirstTask()) {
return putNewTask(task);
}
return putNewTask(task);
}
return false;
}
/**
* 设置执行队列最大任务数
*
* @param maxNum 下载数
* update pool size
*/
public void setMaxNum(int maxNum) {
@Override
public void setPoolSize(int newSize) {
if (newSize < 1) {
Timber.e("update pool size fail, size less than 1");
return;
}
synchronized (LOCK) {
Deque<TASK> temp = new LinkedBlockingDeque<>(maxNum);
Deque<TASK> temp = new LinkedBlockingDeque<>(newSize);
TASK task;
while ((task = mExecuteQueue.poll()) != null) {
temp.offer(task);
}
mExecuteQueue = temp;
mSize = maxNum;
mSize = newSize;
}
}
@ -103,22 +99,22 @@ public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
boolean putNewTask(TASK newTask) {
synchronized (LOCK) {
boolean s = mExecuteQueue.offer(newTask);
ALog.d(TAG, "任务【" + newTask.getTaskName() + "】进入执行队列" + (s ? "成功" : "失败"));
Timber.d("offer %s into queue %s ", newTask.getTaskId(), (s ? "success" : "fail"));
return s;
}
}
/**
* 队列满时将移除下载队列中的第一个任务
* check pool, if pool size equal to max size, remove first task
*/
boolean pollFirstTask() {
synchronized (LOCK) {
TASK oldTask = mExecuteQueue.pollFirst();
if (oldTask == null) {
ALog.w(TAG, "移除任务失败,原因:任务为null");
Timber.w("poll task fail, task is null");
return false;
}
oldTask.stop();
oldTask.stop(TaskSchedulerType.TYPE_DEFAULT);
return true;
}
}
@ -129,49 +125,46 @@ public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
}
}
@Override public TASK getTask(String key) {
@Override public TASK getTask(int taskId) {
if (taskId < 0) {
Timber.e("invalid taskId");
return null;
}
synchronized (LOCK) {
if (TextUtils.isEmpty(key)) {
ALog.e(TAG, "key为null");
return null;
}
for (TASK task : mExecuteQueue) {
if (task.getKey().equals(key)) {
if (task.getTaskId() == taskId) {
return task;
}
}
return null;
}
Timber.w("not found task, taskId: %s", taskId);
return null;
}
@Override public boolean taskExits(String key) {
return getTask(key) != null;
@Override public boolean taskExist(int taskId) {
return getTask(taskId) != null;
}
@Override public boolean removeTask(TASK task) {
synchronized (LOCK) {
if (task == null) {
ALog.e(TAG, "任务不能为空");
return false;
} else {
return removeTask(task.getKey());
}
@Override public boolean removeTask(int taskId) {
if (taskId < 0) {
Timber.e("invalid taskId");
return false;
}
TASK task = getTask(taskId);
if (task == null) {
Timber.e("task not exist");
return false;
}
}
@Override public boolean removeTask(String key) {
synchronized (LOCK) {
if (TextUtils.isEmpty(key)) {
ALog.e(TAG, "key 为null");
return false;
}
return mExecuteQueue.remove(getTask(key));
return mExecuteQueue.remove(getTask(taskId));
}
}
@Override public int size() {
return mExecuteQueue.size();
}
@Override public void clear() {
Timber.i("exe queue does not support clear operation");
}
}

@ -0,0 +1,53 @@
/*
* 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.queue;
import android.content.Context;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.task.DownloadTask;
/**
* Created by lyy on 2016/8/17.
* 下载任务队列
*/
public class DTaskQueue extends AbsTaskQueue<DownloadTask> {
private static volatile DTaskQueue INSTANCE = null;
public static DTaskQueue getInstance() {
if (INSTANCE == null) {
synchronized (DTaskQueue.class) {
INSTANCE = new DTaskQueue();
}
}
return INSTANCE;
}
private DTaskQueue() {
}
@Override protected int getMaxTaskSize() {
return AriaConfig.getInstance().getDConfig().getMaxTaskNum();
}
@Override public int getOldMaxSize() {
return AriaConfig.getInstance().getDConfig().oldMaxTaskNum;
}
@Override public void init(@NonNull Context context) {
}
}

@ -14,22 +14,29 @@
* limitations under the License.
*/
package com.arialyy.aria.core.queue.pool;
package com.arialyy.aria.queue;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.core.task.ITask;
import java.util.List;
/**
* Created by lyy on 2016/8/14. 任务池
*/
interface IPool<T extends AbsTask> {
interface IPool<T extends ITask> {
List<T> getAllTask();
void setPoolSize(int newSize);
int getPoolSize();
/**
* 将下载任务添加到任务池中
*/
boolean putTask(T task);
/**
* 按照队列原则取出下载任务
* 按照队列原则取出任务
*
* @return 返回null或者下载任务
*/
@ -38,34 +45,21 @@ interface IPool<T extends AbsTask> {
/**
* 通过key获取任务当任务不为空时队列将删除该下载任务
*
* @param key {@link AbsEntity#getKey()}
* @return 返回null或者下载任务
*/
T getTask(String key);
T getTask(int taskId);
/**
* 任务是在存在
*
* @param key {@link AbsEntity#getKey()}
* @return {@code true} 任务存在
*/
boolean taskExits(String key);
boolean taskExist(int taskId);
/**
* 删除任务池中的下载任务
*
* @param task {@link AbsTask}
* @return true:移除成功
*/
boolean removeTask(T task);
/**
* 通过key除下载任务
*
* @param key 下载链接
* @return true:移除成功
*/
boolean removeTask(String key);
boolean removeTask(int taskId);
/**
* 池子大小
@ -73,4 +67,9 @@ interface IPool<T extends AbsTask> {
* @return 返回缓存池或者执行池大小
*/
int size();
/**
* remove all task
*/
void clear();
}

@ -0,0 +1,15 @@
package com.arialyy.aria.queue
import android.content.Context
import com.arialyy.aria.core.inf.IComponentInit
/**
* @Author laoyuyu
* @Description
* @Date 4:08 PM 2023/1/26
**/
class QueueComponent : IComponentInit {
override fun init(context: Context) {
}
}

@ -0,0 +1,53 @@
/*
* 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.queue;
import android.content.Context;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.task.UploadTask;
import org.jetbrains.annotations.NotNull;
/**
* Created by lyy on 2017/2/27. 上传任务队列
*/
public class UTaskQueue extends AbsTaskQueue<UploadTask> {
private static volatile UTaskQueue INSTANCE = null;
public static UTaskQueue getInstance() {
if (INSTANCE == null) {
synchronized (UTaskQueue.class) {
INSTANCE = new UTaskQueue();
}
}
return INSTANCE;
}
private UTaskQueue() {
}
@Override protected int getMaxTaskSize() {
return AriaConfig.getInstance().getUConfig().getMaxTaskNum();
}
@Override public int getOldMaxSize() {
return AriaConfig.getInstance().getUConfig().oldMaxTaskNum;
}
@Override public void init(@NotNull Context context) {
}
}

@ -0,0 +1,17 @@
package com.arialyy.aria.queue
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}

@ -0,0 +1 @@
/build

@ -0,0 +1,43 @@
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
}
android {
compileSdkVersion libs.versions.compilesdk.get().toInteger()
buildToolsVersion libs.versions.buildToolsVersion.get()
namespace 'com.arialyy.aria.schedulers'
defaultConfig {
minSdkVersion libs.versions.minSdk.get().toInteger()
targetSdkVersion libs.versions.targetsdk.get().toInteger()
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError false
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(path: ':PublicComponent')
testImplementation(libs.junit)
androidTestImplementation(libs.bundles.android.test)
}
//apply from: 'bintray-release.gradle'
ext {
PUBLISH_ARTIFACT_ID = 'schedulers'
}
apply from: '../gradle/mavenCentral-release.gradle'

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

@ -0,0 +1,24 @@
package com.arialyy.aria.schedulers
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.arialyy.aria.schedulers.test", appContext.packageName)
}
}

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.scheduler;
package com.arialyy.aria.schedulers;
/**
* Created by Aria.Lao on 2019/6/26.

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.scheduler;
package com.arialyy.aria.schedulers;
import com.arialyy.aria.core.task.DownloadGroupTask;
import com.arialyy.aria.core.task.DownloadTask;

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save