修复任务记录删除失败的问题

优化网络连接状态获取的逻辑
修复配置文件的某些配置失效的问题
新增m3u8切片状态注解`@M3U8.onPeerStart`,`@M3U8.onPeerComplete`,`@M3U8.onPeerFail`
新增动态指定m3u8协议视频的下载功能(边下边播)
v3.6.6
laoyuyu 5 years ago
parent 060b1f138e
commit b0818537f2
  1. 2
      .github/ISSUE_TEMPLATE/Custom.md
  2. 43
      Aria/src/main/java/com/arialyy/aria/core/AriaManager.java
  3. 5
      Aria/src/main/java/com/arialyy/aria/core/command/AbsGroupCmd.java
  4. 26
      Aria/src/main/java/com/arialyy/aria/core/command/AbsNormalCmd.java
  5. 4
      Aria/src/main/java/com/arialyy/aria/core/command/AddCmd.java
  6. 15
      Aria/src/main/java/com/arialyy/aria/core/command/CancelAllCmd.java
  7. 4
      Aria/src/main/java/com/arialyy/aria/core/command/CancelCmd.java
  8. 131
      Aria/src/main/java/com/arialyy/aria/core/command/CommandManager.java
  9. 9
      Aria/src/main/java/com/arialyy/aria/core/command/DGSubStartCmd.java
  10. 8
      Aria/src/main/java/com/arialyy/aria/core/command/DGSubStopCmd.java
  11. 10
      Aria/src/main/java/com/arialyy/aria/core/command/GroupCmdFactory.java
  12. 2
      Aria/src/main/java/com/arialyy/aria/core/command/HighestPriorityCmd.java
  13. 7
      Aria/src/main/java/com/arialyy/aria/core/command/NormalCmdFactory.java
  14. 4
      Aria/src/main/java/com/arialyy/aria/core/command/ReStartCmd.java
  15. 2
      Aria/src/main/java/com/arialyy/aria/core/command/ResumeAllCmd.java
  16. 9
      Aria/src/main/java/com/arialyy/aria/core/command/StartCmd.java
  17. 2
      Aria/src/main/java/com/arialyy/aria/core/command/StopAllCmd.java
  18. 5
      Aria/src/main/java/com/arialyy/aria/core/command/StopCmd.java
  19. 37
      Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java
  20. 48
      Aria/src/main/java/com/arialyy/aria/core/common/AbsThreadTask.java
  21. 6
      Aria/src/main/java/com/arialyy/aria/core/common/BaseListener.java
  22. 14
      Aria/src/main/java/com/arialyy/aria/core/common/IThreadState.java
  23. 7
      Aria/src/main/java/com/arialyy/aria/core/common/IUtil.java
  24. 12
      Aria/src/main/java/com/arialyy/aria/core/common/NormalFileer.java
  25. 113
      Aria/src/main/java/com/arialyy/aria/core/common/ProxyHelper.java
  26. 2
      Aria/src/main/java/com/arialyy/aria/core/common/SubThreadConfig.java
  27. 6
      Aria/src/main/java/com/arialyy/aria/core/common/ThreadStateManager.java
  28. 7
      Aria/src/main/java/com/arialyy/aria/core/common/ftp/FtpTaskConfig.java
  29. 6
      Aria/src/main/java/com/arialyy/aria/core/common/ftp/IFtpUploadInterceptor.java
  30. 7
      Aria/src/main/java/com/arialyy/aria/core/common/http/HttpTaskConfig.java
  31. 4
      Aria/src/main/java/com/arialyy/aria/core/config/DGroupConfig.java
  32. 4
      Aria/src/main/java/com/arialyy/aria/core/config/DownloadConfig.java
  33. 4
      Aria/src/main/java/com/arialyy/aria/core/config/UploadConfig.java
  34. 12
      Aria/src/main/java/com/arialyy/aria/core/download/AbsDTarget.java
  35. 12
      Aria/src/main/java/com/arialyy/aria/core/download/DNormalConfigHandler.java
  36. 35
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java
  37. 12
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadTask.java
  38. 75
      Aria/src/main/java/com/arialyy/aria/core/download/M3U8Listener.java
  39. 7
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/Downloader.java
  40. 2
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpThreadTask.java
  41. 2
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpFileInfoThread.java
  42. 2
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java
  43. 5
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/SimpleDownloadUtil.java
  44. 13
      Aria/src/main/java/com/arialyy/aria/core/download/group/AbsGroupUtil.java
  45. 6
      Aria/src/main/java/com/arialyy/aria/core/download/group/SubDownloadLoader.java
  46. 2
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/BaseM3U8Loader.java
  47. 6
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/IBandWidthUrlConverter.java
  48. 6
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/ILiveTsUrlConverter.java
  49. 6
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/ITsMergeHandler.java
  50. 6
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/IVodTsUrlConverter.java
  51. 96
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8Entity.java
  52. 6
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8InfoThread.java
  53. 18
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8LiveLoader.java
  54. 4
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8LiveUtil.java
  55. 44
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8TaskConfig.java
  56. 8
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8ThreadTask.java
  57. 47
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8VodDelegate.java
  58. 496
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8VodLoader.java
  59. 20
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8VodUtil.java
  60. 30
      Aria/src/main/java/com/arialyy/aria/core/event/Event.java
  61. 17
      Aria/src/main/java/com/arialyy/aria/core/event/EventMethodInfo.java
  62. 153
      Aria/src/main/java/com/arialyy/aria/core/event/EventMsgUtil.java
  63. 27
      Aria/src/main/java/com/arialyy/aria/core/event/PeerIndexEvent.java
  64. 25
      Aria/src/main/java/com/arialyy/aria/core/event/SpeedEvent.java
  65. 73
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java
  66. 24
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsTask.java
  67. 6
      Aria/src/main/java/com/arialyy/aria/core/inf/IHttpFileLenAdapter.java
  68. 6
      Aria/src/main/java/com/arialyy/aria/core/inf/ITask.java
  69. 6
      Aria/src/main/java/com/arialyy/aria/core/manager/DTaskWrapperFactory.java
  70. 18
      Aria/src/main/java/com/arialyy/aria/core/manager/SubTaskManager.java
  71. 15
      Aria/src/main/java/com/arialyy/aria/core/manager/ThreadTaskManager.java
  72. 33
      Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java
  73. 2
      Aria/src/main/java/com/arialyy/aria/core/queue/DownloadGroupTaskQueue.java
  74. 2
      Aria/src/main/java/com/arialyy/aria/core/queue/DownloadTaskQueue.java
  75. 3
      Aria/src/main/java/com/arialyy/aria/core/queue/TaskFactory.java
  76. 2
      Aria/src/main/java/com/arialyy/aria/core/queue/UploadTaskQueue.java
  77. 12
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/BaseCachePool.java
  78. 17
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/BaseExecutePool.java
  79. 2
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/DownloadExecutePool.java
  80. 4
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/DownloadSharePool.java
  81. 4
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/UploadSharePool.java
  82. 149
      Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java
  83. 7
      Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadGroupSchedulers.java
  84. 9
      Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadSchedulers.java
  85. 63
      Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulerListener.java
  86. 34
      Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulers.java
  87. 36
      Aria/src/main/java/com/arialyy/aria/core/scheduler/M3U8PeerTaskListener.java
  88. 116
      Aria/src/main/java/com/arialyy/aria/core/scheduler/NormalTaskListener.java
  89. 59
      Aria/src/main/java/com/arialyy/aria/core/scheduler/SubTaskListener.java
  90. 7
      Aria/src/main/java/com/arialyy/aria/core/scheduler/UploadSchedulers.java
  91. 19
      Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java
  92. 3
      Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpThreadTask.java
  93. 2
      Aria/src/main/java/com/arialyy/aria/core/upload/uploader/HttpThreadTask.java
  94. 14
      Aria/src/main/java/com/arialyy/aria/core/upload/uploader/SimpleUploadUtil.java
  95. 7
      Aria/src/main/java/com/arialyy/aria/core/upload/uploader/Uploader.java
  96. 4
      Aria/src/main/java/com/arialyy/aria/orm/DBConfig.java
  97. 4
      Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java
  98. 2
      Aria/src/main/java/com/arialyy/aria/util/BufferedRandomAccessFile.java
  99. 28
      Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java
  100. 17
      Aria/src/main/java/com/arialyy/aria/util/RecordUtil.java
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,6 +1,6 @@
--- ---
name: 问题描述 name: 问题描述
about: 描述你遇到的问题或bug about: 请详细描述你遇到的问题
--- ---

@ -24,26 +24,23 @@ import android.content.Context;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.Network; import android.net.Network;
import android.net.NetworkCapabilities; import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkRequest; import android.net.NetworkRequest;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.support.annotation.RequiresApi;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.widget.PopupWindow; import android.widget.PopupWindow;
import com.arialyy.aria.BuildConfig; import com.arialyy.aria.core.command.CommandManager;
import com.arialyy.aria.core.command.ICmd;
import com.arialyy.aria.core.common.QueueMod; import com.arialyy.aria.core.common.QueueMod;
import com.arialyy.aria.core.common.RecordHandler; import com.arialyy.aria.core.common.RecordHandler;
import com.arialyy.aria.core.config.AppConfig; import com.arialyy.aria.core.config.AppConfig;
import com.arialyy.aria.core.config.Configuration;
import com.arialyy.aria.core.config.DGroupConfig; import com.arialyy.aria.core.config.DGroupConfig;
import com.arialyy.aria.core.config.DownloadConfig; import com.arialyy.aria.core.config.DownloadConfig;
import com.arialyy.aria.core.config.UploadConfig; import com.arialyy.aria.core.config.UploadConfig;
import com.arialyy.aria.core.config.XMLReader; import com.arialyy.aria.core.config.XMLReader;
import com.arialyy.aria.core.config.Configuration;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity; import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.download.DownloadReceiver; import com.arialyy.aria.core.download.DownloadReceiver;
@ -75,7 +72,7 @@ import org.xml.sax.SAXException;
*/ */
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public class AriaManager { @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public class AriaManager {
private static final String TAG = "AriaManager"; private static final String TAG = "AriaManager";
public static final Object LOCK = new Object(); private static final Object LOCK = new Object();
public static final String DOWNLOAD_TEMP_DIR = "/Aria/temp/download/"; public static final String DOWNLOAD_TEMP_DIR = "/Aria/temp/download/";
public static final String UPLOAD_TEMP_DIR = "/Aria/temp/upload/"; public static final String UPLOAD_TEMP_DIR = "/Aria/temp/upload/";
/** /**
@ -90,7 +87,6 @@ import org.xml.sax.SAXException;
*/ */
private Map<String, List<String>> mSubClass = new ConcurrentHashMap<>(); private Map<String, List<String>> mSubClass = new ConcurrentHashMap<>();
public static Context APP; public static Context APP;
private List<ICmd> mCommands = new ArrayList<>();
private DownloadConfig mDConfig; private DownloadConfig mDConfig;
private UploadConfig mUConfig; private UploadConfig mUConfig;
private AppConfig mAConfig; private AppConfig mAConfig;
@ -110,7 +106,9 @@ import org.xml.sax.SAXException;
public static AriaManager getInstance(Context context) { public static AriaManager getInstance(Context context) {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (LOCK) { synchronized (LOCK) {
INSTANCE = new AriaManager(context); if (INSTANCE == null) {
INSTANCE = new AriaManager(context);
}
} }
} }
return INSTANCE; return INSTANCE;
@ -182,6 +180,7 @@ import org.xml.sax.SAXException;
Thread.setDefaultUncaughtExceptionHandler(new AriaCrashHandler()); Thread.setDefaultUncaughtExceptionHandler(new AriaCrashHandler());
} }
mAConfig.setLogLevel(mAConfig.getLogLevel()); mAConfig.setLogLevel(mAConfig.getLogLevel());
CommandManager.init();
} }
/** /**
@ -291,34 +290,6 @@ import org.xml.sax.SAXException;
return mDGConfig; return mDGConfig;
} }
/**
* 设置命令
*/
public AriaManager setCmd(ICmd command) {
mCommands.add(command);
return this;
}
/**
* 设置一组命令
*/
public <T extends ICmd> AriaManager setCmds(List<T> commands) {
if (commands != null && commands.size() > 0) {
mCommands.addAll(commands);
}
return this;
}
/**
* 执行所有设置的命令
*/
public synchronized void exe() {
for (ICmd command : mCommands) {
command.executeCmd();
}
mCommands.clear();
}
/** /**
* 处理下载操作 * 处理下载操作
*/ */

@ -13,13 +13,12 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.command.group; package com.arialyy.aria.core.command;
import com.arialyy.aria.core.command.AbsCmd;
import com.arialyy.aria.core.download.DGTaskWrapper; import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.inf.AbsGroupTask; import com.arialyy.aria.core.inf.AbsGroupTask;
import com.arialyy.aria.core.inf.AbsTask;
import com.arialyy.aria.core.inf.AbsGroupTaskWrapper; import com.arialyy.aria.core.inf.AbsGroupTaskWrapper;
import com.arialyy.aria.core.inf.AbsTask;
import com.arialyy.aria.core.queue.DownloadGroupTaskQueue; import com.arialyy.aria.core.queue.DownloadGroupTaskQueue;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;

@ -14,17 +14,13 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.command.normal; package com.arialyy.aria.core.command;
import com.arialyy.aria.core.command.AbsCmd;
import com.arialyy.aria.core.command.ICmd;
import com.arialyy.aria.core.download.DGTaskWrapper; import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.inf.AbsEntity;
import com.arialyy.aria.core.inf.AbsTask; import com.arialyy.aria.core.inf.AbsTask;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;
import com.arialyy.aria.core.inf.IEntity; import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.manager.TaskWrapperManager;
import com.arialyy.aria.core.queue.DownloadGroupTaskQueue; import com.arialyy.aria.core.queue.DownloadGroupTaskQueue;
import com.arialyy.aria.core.queue.DownloadTaskQueue; import com.arialyy.aria.core.queue.DownloadTaskQueue;
import com.arialyy.aria.core.queue.UploadTaskQueue; import com.arialyy.aria.core.queue.UploadTaskQueue;
@ -130,10 +126,10 @@ public abstract class AbsNormalCmd<T extends AbsTaskWrapper> extends AbsCmd<T> {
/** /**
* 删除任务 * 删除任务
*/ */
void removeTask(AbsTaskWrapper taskEntity) { void removeTask(AbsTaskWrapper wrapper) {
AbsTask tempTask = getTask(taskEntity.getEntity()); AbsTask tempTask = getTask(wrapper.getKey());
if (tempTask == null) { if (tempTask == null) {
tempTask = createTask(taskEntity); tempTask = createTask(wrapper);
} }
mQueue.cancelTask(tempTask); mQueue.cancelTask(tempTask);
} }
@ -143,7 +139,7 @@ public abstract class AbsNormalCmd<T extends AbsTaskWrapper> extends AbsCmd<T> {
*/ */
void startTask() { void startTask() {
AbsTask task = getTask(); AbsTask task = getTask();
if (task == null){ if (task == null) {
task = createTask(); task = createTask();
} }
mQueue.startTask(task); mQueue.startTask(task);
@ -154,7 +150,7 @@ public abstract class AbsNormalCmd<T extends AbsTaskWrapper> extends AbsCmd<T> {
*/ */
void resumeTask() { void resumeTask() {
AbsTask task = getTask(); AbsTask task = getTask();
if (task == null){ if (task == null) {
task = createTask(); task = createTask();
} }
mQueue.resumeTask(task); mQueue.resumeTask(task);
@ -183,8 +179,8 @@ public abstract class AbsNormalCmd<T extends AbsTaskWrapper> extends AbsCmd<T> {
* *
* @return 执行任务 * @return 执行任务
*/ */
AbsTask getTask(AbsEntity entity) { AbsTask getTask(String key) {
return mQueue.getTask(entity.getKey()); return mQueue.getTask(key);
} }
/** /**
@ -199,11 +195,11 @@ public abstract class AbsNormalCmd<T extends AbsTaskWrapper> extends AbsCmd<T> {
/** /**
* 创建指定实体的任务 * 创建指定实体的任务
* *
* @param taskEntity 特定的任务实体 * @param wrapper 特定的任务实体
* @return 创建的任务 * @return 创建的任务
*/ */
AbsTask createTask(AbsTaskWrapper taskEntity) { AbsTask createTask(AbsTaskWrapper wrapper) {
return mQueue.createTask(taskEntity); return mQueue.createTask(wrapper);
} }
} }

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.command.normal; package com.arialyy.aria.core.command;
import com.arialyy.aria.core.inf.AbsTask; import com.arialyy.aria.core.inf.AbsTask;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;
@ -25,7 +25,7 @@ import com.arialyy.aria.util.ALog;
* Created by lyy on 2016/8/22. * Created by lyy on 2016/8/22.
* 添加任务的命令 * 添加任务的命令
*/ */
class AddCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> { final class AddCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
AddCmd(T entity, int taskType) { AddCmd(T entity, int taskType) {
super(entity, taskType); super(entity, taskType);

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.command.normal; package com.arialyy.aria.core.command;
import com.arialyy.aria.core.download.DGTaskWrapper; import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper;
@ -35,7 +35,7 @@ import java.util.List;
* Created by AriaL on 2017/6/27. * Created by AriaL on 2017/6/27.
* 删除所有任务并且删除所有回掉 * 删除所有任务并且删除所有回掉
*/ */
public class CancelAllCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> { final public class CancelAllCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
/** /**
* removeFile {@code true} 删除已经下载完成的任务不仅删除下载记录还会删除已经下载完成的文件{@code false} * removeFile {@code true} 删除已经下载完成的任务不仅删除下载记录还会删除已经下载完成的文件{@code false}
* 如果文件已经下载完成只删除下载记录 * 如果文件已经下载完成只删除下载记录
@ -64,7 +64,8 @@ public class CancelAllCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
DbEntity.findDatas(DownloadEntity.class, "isGroupChild=?", "false"); DbEntity.findDatas(DownloadEntity.class, "isGroupChild=?", "false");
if (entities != null && !entities.isEmpty()) { if (entities != null && !entities.isEmpty()) {
for (DownloadEntity entity : entities) { for (DownloadEntity entity : entities) {
remove(TaskWrapperManager.getInstance().getHttpTaskWrapper(DTaskWrapper.class, entity.getKey())); remove(TaskWrapperManager.getInstance()
.getHttpTaskWrapper(DTaskWrapper.class, entity.getKey()));
} }
} }
} }
@ -78,7 +79,8 @@ public class CancelAllCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
if (entities != null && !entities.isEmpty()) { if (entities != null && !entities.isEmpty()) {
for (DownloadGroupEntity entity : entities) { for (DownloadGroupEntity entity : entities) {
remove( remove(
TaskWrapperManager.getInstance().getDGTaskWrapper(DGTaskWrapper.class, entity.getUrls())); TaskWrapperManager.getInstance()
.getDGTaskWrapper(DGTaskWrapper.class, entity.getUrls()));
} }
} }
} }
@ -91,13 +93,14 @@ public class CancelAllCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
DbEntity.findDatas(UploadEntity.class, "isGroupChild=?", "false"); DbEntity.findDatas(UploadEntity.class, "isGroupChild=?", "false");
if (entities != null && !entities.isEmpty()) { if (entities != null && !entities.isEmpty()) {
for (UploadEntity entity : entities) { for (UploadEntity entity : entities) {
remove(TaskWrapperManager.getInstance().getHttpTaskWrapper(UTaskWrapper.class, entity.getKey())); remove(TaskWrapperManager.getInstance()
.getHttpTaskWrapper(UTaskWrapper.class, entity.getKey()));
} }
} }
} }
private void remove(AbsTaskWrapper te) { private void remove(AbsTaskWrapper te) {
if (te == null){ if (te == null) {
ALog.w(TAG, "取消任务失败,任务为空"); ALog.w(TAG, "取消任务失败,任务为空");
return; return;
} }

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.command.normal; package com.arialyy.aria.core.command;
import com.arialyy.aria.core.inf.AbsTask; import com.arialyy.aria.core.inf.AbsTask;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;
@ -23,7 +23,7 @@ import com.arialyy.aria.core.inf.AbsTaskWrapper;
* Created by lyy on 2016/9/20. * Created by lyy on 2016/9/20.
* 取消命令 * 取消命令
*/ */
public class CancelCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> { final public class CancelCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
/** /**
* removeFile {@code true} 删除已经下载完成的任务不仅删除下载记录还会删除已经下载完成的文件{@code false} * removeFile {@code true} 删除已经下载完成的任务不仅删除下载记录还会删除已经下载完成的文件{@code false}
* 如果文件已经下载完成只删除下载记录 * 如果文件已经下载完成只删除下载记录

@ -0,0 +1,131 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.command;
import com.arialyy.aria.core.event.Event;
import com.arialyy.aria.core.event.EventMsgUtil;
import com.arialyy.aria.util.CommonUtil;
/**
* 命令处理器
*/
public class CommandManager {
private static CommandManager instance;
private CommandManager() {
EventMsgUtil.getDefault().register(this);
}
public static CommandManager init() {
if (instance == null) {
synchronized (CommandManager.class) {
if (instance == null) {
instance = new CommandManager();
}
}
}
return instance;
}
@Event
public void add(AddCmd cmd) {
if (CommonUtil.isFastDoubleClick()){
return;
}
cmd.executeCmd();
}
@Event
public void start(StartCmd cmd) {
if (CommonUtil.isFastDoubleClick()){
return;
}
cmd.executeCmd();
}
@Event
public void stop(StopCmd cmd) {
if (CommonUtil.isFastDoubleClick()){
return;
}
cmd.executeCmd();
}
@Event
public void cancel(CancelCmd cmd) {
if (CommonUtil.isFastDoubleClick()){
return;
}
cmd.executeCmd();
}
@Event
public void stopAll(StopAllCmd cmd) {
if (CommonUtil.isFastDoubleClick()){
return;
}
cmd.executeCmd();
}
@Event
public void cancelAll(CancelAllCmd cmd) {
if (CommonUtil.isFastDoubleClick()){
return;
}
cmd.executeCmd();
}
@Event
public void reStart(ReStartCmd cmd) {
if (CommonUtil.isFastDoubleClick()){
return;
}
cmd.executeCmd();
}
@Event
public void highestPriority(HighestPriorityCmd cmd) {
if (CommonUtil.isFastDoubleClick()){
return;
}
cmd.executeCmd();
}
@Event
public void resumeAll(ResumeAllCmd cmd) {
if (CommonUtil.isFastDoubleClick()){
return;
}
cmd.executeCmd();
}
@Event
public void subStart(DGSubStartCmd cmd) {
if (CommonUtil.isFastDoubleClick()){
return;
}
cmd.executeCmd();
}
@Event
public void subStop(DGSubStopCmd cmd) {
if (CommonUtil.isFastDoubleClick()){
return;
}
cmd.executeCmd();
}
}

@ -13,15 +13,16 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.command.group; package com.arialyy.aria.core.command;
import com.arialyy.aria.core.inf.AbsGroupTaskWrapper; import com.arialyy.aria.core.inf.AbsGroupTaskWrapper;
/** /**
* Created by AriaL on 2017/6/29. 任务组开始命令该命令负责处理任务组子任务的开始\恢复等工作 * Created by AriaL on 2017/6/29.
* 任务组开始命令该命令负责处理任务组子任务的开始\恢复等工作
*/ */
class GroupStartCmd<T extends AbsGroupTaskWrapper> extends AbsGroupCmd<T> { final class DGSubStartCmd<T extends AbsGroupTaskWrapper> extends AbsGroupCmd<T> {
GroupStartCmd(T wrapper) { DGSubStartCmd(T wrapper) {
super(wrapper); super(wrapper);
} }

@ -13,16 +13,16 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.command.group; package com.arialyy.aria.core.command;
import com.arialyy.aria.core.inf.AbsGroupTaskWrapper; import com.arialyy.aria.core.inf.AbsGroupTaskWrapper;
/** /**
* Created by AriaL on 2017/6/29. * Created by AriaL on 2017/6/29.
* 停止任务组的命令 * 停止任务组子任务的命令
*/ */
class GroupStopCmd<T extends AbsGroupTaskWrapper> extends AbsGroupCmd<T> { final class DGSubStopCmd<T extends AbsGroupTaskWrapper> extends AbsGroupCmd<T> {
GroupStopCmd(T entity) { DGSubStopCmd(T entity) {
super(entity); super(entity);
} }

@ -13,10 +13,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.command.group; package com.arialyy.aria.core.command;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.inf.AbsGroupTaskWrapper; import com.arialyy.aria.core.inf.AbsGroupTaskWrapper;
/** /**
@ -40,7 +38,7 @@ public class GroupCmdFactory {
public static GroupCmdFactory getInstance() { public static GroupCmdFactory getInstance() {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (AriaManager.LOCK) { synchronized (GroupCmdFactory.class) {
INSTANCE = new GroupCmdFactory(); INSTANCE = new GroupCmdFactory();
} }
} }
@ -58,10 +56,10 @@ public class GroupCmdFactory {
AbsGroupCmd cmd = null; AbsGroupCmd cmd = null;
switch (type) { switch (type) {
case SUB_TASK_START: case SUB_TASK_START:
cmd = new GroupStartCmd<>(wrapper); cmd = new DGSubStartCmd<>(wrapper);
break; break;
case SUB_TASK_STOP: case SUB_TASK_STOP:
cmd = new GroupStopCmd<>(wrapper); cmd = new DGSubStopCmd<>(wrapper);
break; break;
} }
if (cmd != null) { if (cmd != null) {

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.command.normal; package com.arialyy.aria.core.command;
import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.download.DownloadTask; import com.arialyy.aria.core.download.DownloadTask;

@ -14,11 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.command.normal; package com.arialyy.aria.core.command;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.command.AbsCmdFactory;
import com.arialyy.aria.core.command.ICmd;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;
/** /**
@ -75,7 +72,7 @@ public class NormalCmdFactory extends AbsCmdFactory<AbsTaskWrapper, AbsNormalCmd
public static NormalCmdFactory getInstance() { public static NormalCmdFactory getInstance() {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (AriaManager.LOCK) { synchronized (NormalCmdFactory.class) {
INSTANCE = new NormalCmdFactory(); INSTANCE = new NormalCmdFactory();
} }
} }

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.command.normal; package com.arialyy.aria.core.command;
import com.arialyy.aria.core.inf.AbsTask; import com.arialyy.aria.core.inf.AbsTask;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;
@ -22,7 +22,7 @@ import com.arialyy.aria.core.inf.TaskSchedulerType;
/** /**
* 重新开始任务命令 * 重新开始任务命令
*/ */
public class ReStartCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> { final class ReStartCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
ReStartCmd(T entity, int taskType) { ReStartCmd(T entity, int taskType) {
super(entity, taskType); super(entity, taskType);

@ -1,4 +1,4 @@
package com.arialyy.aria.core.command.normal; package com.arialyy.aria.core.command;
import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.download.DGTaskWrapper; import com.arialyy.aria.core.download.DGTaskWrapper;

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.command.normal; package com.arialyy.aria.core.command;
import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.common.QueueMod; import com.arialyy.aria.core.common.QueueMod;
@ -41,7 +41,7 @@ import java.util.List;
/** /**
* Created by lyy on 2016/8/22. 开始命令 队列模型{@link QueueMod#NOW}{@link QueueMod#WAIT} * Created by lyy on 2016/8/22. 开始命令 队列模型{@link QueueMod#NOW}{@link QueueMod#WAIT}
*/ */
class StartCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> { final class StartCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
StartCmd(T entity, int taskType) { StartCmd(T entity, int taskType) {
super(entity, taskType); super(entity, taskType);
@ -90,8 +90,7 @@ class StartCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
} }
} else { } else {
//任务没执行并且执行队列中没有该任务,才认为任务没有运行中 //任务没执行并且执行队列中没有该任务,才认为任务没有运行中
if (!task.isRunning() && !mQueue.taskIsRunning(task.getKey()) && !mQueue.taskExists( if (!mQueue.taskIsRunning(task.getKey())) {
task.getKey())) {
resumeTask(); resumeTask();
} else { } else {
ALog.w(TAG, String.format("任务【%s】已经在运行", task.getTaskName())); ALog.w(TAG, String.format("任务【%s】已经在运行", task.getTaskName()));
@ -166,7 +165,7 @@ class StartCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
private void handleTask(List<AbsTaskWrapper> waitList) { private void handleTask(List<AbsTaskWrapper> waitList) {
for (AbsTaskWrapper te : waitList) { for (AbsTaskWrapper te : waitList) {
if (te.getEntity() == null) continue; if (te.getEntity() == null) continue;
AbsTask task = getTask(te.getEntity()); AbsTask task = getTask(te.getKey());
if (task != null) continue; if (task != null) continue;
if (te instanceof DTaskWrapper) { if (te instanceof DTaskWrapper) {
if (te.getRequestType() == AbsTaskWrapper.D_FTP if (te.getRequestType() == AbsTaskWrapper.D_FTP

@ -1,4 +1,4 @@
package com.arialyy.aria.core.command.normal; package com.arialyy.aria.core.command;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.command.normal; package com.arialyy.aria.core.command;
import com.arialyy.aria.core.inf.AbsTask; import com.arialyy.aria.core.inf.AbsTask;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;
@ -25,7 +25,7 @@ import com.arialyy.aria.util.ALog;
* Created by lyy on 2016/9/20. * Created by lyy on 2016/9/20.
* 停止命令 * 停止命令
*/ */
class StopCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> { final class StopCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
StopCmd(T entity, int taskType) { StopCmd(T entity, int taskType) {
super(entity, taskType); super(entity, taskType);
@ -36,7 +36,6 @@ class StopCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
AbsTask task = getTask(); AbsTask task = getTask();
if (task == null) { if (task == null) {
if (mTaskWrapper.getEntity().getState() == IEntity.STATE_RUNNING) { if (mTaskWrapper.getEntity().getState() == IEntity.STATE_RUNNING) {
createTask();
stopTask(); stopTask();
} else { } else {
ALog.w(TAG, "停止命令执行失败,【调度器中没有该任务】"); ALog.w(TAG, "停止命令执行失败,【调度器中没有该任务】");

@ -49,6 +49,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
protected TaskRecord mRecord; protected TaskRecord mRecord;
private IThreadState mStateManager; private IThreadState mStateManager;
private boolean isCancel = false, isStop = false; private boolean isCancel = false, isStop = false;
private boolean isRuning = false;
protected AbsFileer(IEventListener listener, TASK_WRAPPER wrapper) { protected AbsFileer(IEventListener listener, TASK_WRAPPER wrapper) {
mListener = listener; mListener = listener;
@ -64,11 +65,6 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
*/ */
protected abstract void handleTask(); protected abstract void handleTask();
/**
* 设置最大下载速度
*/
protected abstract void setMaxSpeed(int maxSpeed);
public String getKey() { public String getKey() {
return mTaskWrapper.getKey(); return mTaskWrapper.getKey();
} }
@ -101,14 +97,15 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
if (isBreak()) { if (isBreak()) {
return; return;
} }
isRuning = true;
resetState(); resetState();
mRecord = new RecordHandler(mTaskWrapper).getRecord(); mRecord = new RecordHandler(mTaskWrapper).getRecord();
Looper.prepare(); Looper.prepare();
Looper looper = Looper.myLooper(); Looper looper = Looper.myLooper();
mStateManager = getStateManager(looper); mStateManager = getStateManager(looper);
onPostPre(); onPostPre();
startTimer();
handleTask(); handleTask();
startTimer();
Looper.loop(); Looper.loop();
} }
@ -137,18 +134,24 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
* 启动进度获取定时器 * 启动进度获取定时器
*/ */
private synchronized void startTimer() { private synchronized void startTimer() {
if (isBreak()) {
return;
}
ALog.d(TAG, "启动定时器"); ALog.d(TAG, "启动定时器");
mTimer = new ScheduledThreadPoolExecutor(1); mTimer = new ScheduledThreadPoolExecutor(1);
mTimer.scheduleWithFixedDelay(new Runnable() { mTimer.scheduleWithFixedDelay(new Runnable() {
@Override public void run() { @Override public void run() {
if (mStateManager.isComplete() if (mStateManager.isComplete()
|| mStateManager.isStop()
|| mStateManager.isCancel()
|| mStateManager.isFail() || mStateManager.isFail()
|| !isRunning() || !isRunning()
|| isBreak()) { || isBreak()) {
ALog.d(TAG, "isComplete = " + mStateManager.isComplete()
+ "; isFail = " + mStateManager.isFail()
+ "; isRunning = " + isRunning()
+ "; isBreak = " + isBreak());
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey()); ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
closeTimer(); closeTimer();
onDestroy();
} else if (mStateManager.getCurrentProgress() >= 0) { } else if (mStateManager.getCurrentProgress() >= 0) {
mListener.onProgress(mStateManager.getCurrentProgress()); mListener.onProgress(mStateManager.getCurrentProgress());
} }
@ -157,12 +160,16 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
} }
public synchronized void closeTimer() { public synchronized void closeTimer() {
ALog.d(TAG, "关闭定时器"); ALog.i(TAG, "关闭定时器");
if (mTimer != null && !mTimer.isShutdown()) { if (mTimer != null && !mTimer.isShutdown()) {
mTimer.shutdown(); mTimer.shutdown();
} }
} }
public void onDestroy() {
isRuning = false;
}
/** /**
* 设置定时器更新间隔 * 设置定时器更新间隔
* *
@ -184,13 +191,13 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
* 获取当前任务位置 * 获取当前任务位置
*/ */
public long getCurrentLocation() { public long getCurrentLocation() {
return mStateManager.getCurrentProgress(); return isRuning ? mStateManager.getCurrentProgress() : mEntity.getCurrentProgress();
} }
public synchronized boolean isRunning() { public synchronized boolean isRunning() {
boolean b = ThreadTaskManager.getInstance().taskIsRunning(mTaskWrapper.getKey()); boolean b = ThreadTaskManager.getInstance().taskIsRunning(mTaskWrapper.getKey());
//ALog.d(TAG, "isRunning = " + b); //ALog.d(TAG, "isRunning = " + b);
return b; return b && isRuning;
} }
final public synchronized void cancel() { final public synchronized void cancel() {
@ -209,6 +216,8 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
} }
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey()); ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
onPostCancel(); onPostCancel();
onDestroy();
mListener.onCancel();
} }
/** /**
@ -232,7 +241,6 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
closeTimer(); closeTimer();
isStop = true; isStop = true;
onStop(); onStop();
if (mStateManager.isComplete()) return;
for (int i = 0; i < mTask.size(); i++) { for (int i = 0; i < mTask.size(); i++) {
AbsThreadTask task = mTask.valueAt(i); AbsThreadTask task = mTask.valueAt(i);
if (task != null && !task.isThreadComplete()) { if (task != null && !task.isThreadComplete()) {
@ -241,6 +249,8 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
} }
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey()); ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
onPostStop(); onPostStop();
onDestroy();
mListener.onStop(getCurrentLocation());
} }
/** /**
@ -283,7 +293,8 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
*/ */
public boolean isBreak() { public boolean isBreak() {
if (isCancel || isStop) { if (isCancel || isStop) {
closeTimer(); //closeTimer();
ALog.d(TAG, "isCancel = " + isCancel + ", isStop = " + isStop);
ALog.d(TAG, String.format("任务【%s】已停止或取消了", mEntity.getFileName())); ALog.d(TAG, String.format("任务【%s】已停止或取消了", mEntity.getFileName()));
return true; return true;
} }

@ -30,6 +30,7 @@ import com.arialyy.aria.core.inf.AbsNormalEntity;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;
import com.arialyy.aria.core.inf.ITaskWrapper; import com.arialyy.aria.core.inf.ITaskWrapper;
import com.arialyy.aria.core.manager.ThreadTaskManager; import com.arialyy.aria.core.manager.ThreadTaskManager;
import com.arialyy.aria.core.scheduler.ISchedulers;
import com.arialyy.aria.exception.BaseException; import com.arialyy.aria.exception.BaseException;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.BufferedRandomAccessFile; import com.arialyy.aria.util.BufferedRandomAccessFile;
@ -66,7 +67,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
private boolean taskBreak = false; //任务跳出 private boolean taskBreak = false; //任务跳出
protected BandwidthLimiter mSpeedBandUtil; //速度限制工具 protected BandwidthLimiter mSpeedBandUtil; //速度限制工具
protected AriaManager mAridManager; protected AriaManager mAridManager;
private boolean isInterrupted = false; private boolean isDestroy = false;
protected boolean isCancel = false, isStop = false; protected boolean isCancel = false, isStop = false;
protected ThreadRecord mRecord; protected ThreadRecord mRecord;
private Handler mStateHandler; private Handler mStateHandler;
@ -103,17 +104,22 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
return mConfig.tempFile.getName(); return mConfig.tempFile.getName();
} }
protected SubThreadConfig<TASK_WRAPPER> getConfig() { public SubThreadConfig<TASK_WRAPPER> getConfig() {
return mConfig; return mConfig;
} }
/** /**
* 设置线程是否中断 * 设置线程是否中断
*
* @param isInterrupted {@code true} 中断
*/ */
public void setInterrupted(boolean isInterrupted) { public void destroy() {
this.isInterrupted = isInterrupted; this.isDestroy = true;
}
/**
* 线程执行完成
*/
protected void onThreadComplete() {
} }
/** /**
@ -122,7 +128,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
* @return {@code true}存活 * @return {@code true}存活
*/ */
protected boolean isLive() { protected boolean isLive() {
return !Thread.currentThread().isInterrupted() && !isInterrupted; return !Thread.currentThread().isInterrupted() && !isDestroy;
} }
/** /**
@ -165,6 +171,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
* *
* @param speed 单位为kb * @param speed 单位为kb
*/ */
public void setMaxSpeed(int speed) { public void setMaxSpeed(int speed) {
if (mSpeedBandUtil != null) { if (mSpeedBandUtil != null) {
mSpeedBandUtil.setMaxRate(speed); mSpeedBandUtil.setMaxRate(speed);
@ -197,13 +204,28 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
Message msg = mStateHandler.obtainMessage(); Message msg = mStateHandler.obtainMessage();
msg.what = state; msg.what = state;
msg.obj = this; msg.obj = this;
if ((state == IThreadState.STATE_COMPLETE || state == IThreadState.STATE_FAIL)
&& (mTaskWrapper.getRequestType() == AbsTaskWrapper.M3U8_VOD
|| mTaskWrapper.getRequestType() == AbsTaskWrapper.M3U8_LIVE)) {
if (bundle == null) {
bundle = new Bundle();
}
bundle.putString(ISchedulers.DATA_M3U8_URL, getConfig().url);
bundle.putString(ISchedulers.DATA_M3U8_PEER_PATH, getConfig().tempFile.getPath());
bundle.putInt(ISchedulers.DATA_M3U8_PEER_INDEX, getConfig().peerIndex);
}
if (bundle != null) { if (bundle != null) {
msg.setData(bundle); msg.setData(bundle);
} }
Thread loopThread = mStateHandler.getLooper().getThread();
if (!loopThread.isAlive() || loopThread.isInterrupted()) {
return;
}
msg.sendToTarget(); msg.sendToTarget();
} }
public boolean isInterrupted() { public boolean isDestroy() {
return Thread.currentThread().isInterrupted(); return Thread.currentThread().isInterrupted();
} }
@ -215,7 +237,10 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
} }
/** /**
* 任务是否中断中断条件 1任务取消 2任务停止 3手动中断 {@link #taskBreak} * 任务是否中断中断条件
* 1任务取消
* 2任务停止
* 3手动中断 {@link #taskBreak}
* *
* @return {@code true} 中断{@code false} 不是中断 * @return {@code true} 中断{@code false} 不是中断
*/ */
@ -285,7 +310,8 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
// return; // return;
//} //}
mChildCurrentLocation += len; mChildCurrentLocation += len;
if (!mStateHandler.getLooper().getThread().isAlive()) { Thread loopThread = mStateHandler.getLooper().getThread();
if (!loopThread.isAlive() || loopThread.isInterrupted()) {
return; return;
} }
mStateHandler.obtainMessage(IThreadState.STATE_RUNNING, len).sendToTarget(); mStateHandler.obtainMessage(IThreadState.STATE_RUNNING, len).sendToTarget();
@ -471,7 +497,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
} }
@Override public AbsThreadTask call() throws Exception { @Override public AbsThreadTask call() throws Exception {
isInterrupted = false; isDestroy = false;
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
TrafficStats.setThreadStatsTag(UUID.randomUUID().toString().hashCode()); TrafficStats.setThreadStatsTag(UUID.randomUUID().toString().hashCode());
return this; return this;

@ -160,9 +160,11 @@ public abstract class BaseListener<ENTITY extends AbsEntity, TASK_WRAPPER extend
if (mEntity instanceof DownloadGroupEntity) { if (mEntity instanceof DownloadGroupEntity) {
RecordUtil.delGroupTaskRecord((DownloadGroupEntity) mEntity, false, false); RecordUtil.delGroupTaskRecord((DownloadGroupEntity) mEntity, false, false);
} else if (mEntity instanceof DownloadEntity) { } else if (mEntity instanceof DownloadEntity) {
RecordUtil.delTaskRecord(((DownloadEntity) mEntity).getFilePath(), RecordHandler.TYPE_DOWNLOAD, false, false); RecordUtil.delTaskRecord(((DownloadEntity) mEntity).getFilePath(),
RecordHandler.TYPE_DOWNLOAD, false, false);
} else if (mEntity instanceof UploadEntity) { } else if (mEntity instanceof UploadEntity) {
RecordUtil.delTaskRecord(((UploadEntity) mEntity).getFilePath(), RecordHandler.TYPE_UPLOAD, false, false); RecordUtil.delTaskRecord(((UploadEntity) mEntity).getFilePath(), RecordHandler.TYPE_UPLOAD,
false, false);
} }
} }

@ -30,13 +30,6 @@ public interface IThreadState extends Handler.Callback {
String KEY_RETRY = "KEY_RETRY"; String KEY_RETRY = "KEY_RETRY";
String KEY_ERROR_INFO = "KEY_ERROR_INFO"; String KEY_ERROR_INFO = "KEY_ERROR_INFO";
/**
* 任务是否已经停止
*
* @return true 任务已停止
*/
boolean isStop();
/** /**
* 任务是否已经失败 * 任务是否已经失败
* *
@ -51,13 +44,6 @@ public interface IThreadState extends Handler.Callback {
*/ */
boolean isComplete(); boolean isComplete();
/**
* 任务是否已经取消
*
* @return true 任务已取消
*/
boolean isCancel();
/** /**
* 获取当前任务进度 * 获取当前任务进度
* *

@ -65,11 +65,4 @@ public interface IUtil {
* 开始 * 开始
*/ */
void start(); void start();
/**
* 设置最大下载/上传速度
*
* @param speed 单位kb
*/
void setMaxSpeed(int speed);
} }

@ -18,6 +18,9 @@ package com.arialyy.aria.core.common;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import com.arialyy.aria.core.download.BaseDListener; import com.arialyy.aria.core.download.BaseDListener;
import com.arialyy.aria.core.event.Event;
import com.arialyy.aria.core.event.EventMsgUtil;
import com.arialyy.aria.core.event.SpeedEvent;
import com.arialyy.aria.core.inf.AbsNormalEntity; import com.arialyy.aria.core.inf.AbsNormalEntity;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;
import com.arialyy.aria.core.inf.IEventListener; import com.arialyy.aria.core.inf.IEventListener;
@ -34,6 +37,7 @@ public abstract class NormalFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER
protected NormalFileer(IEventListener listener, TASK_WRAPPER wrapper) { protected NormalFileer(IEventListener listener, TASK_WRAPPER wrapper) {
super(listener, wrapper); super(listener, wrapper);
EventMsgUtil.getDefault().register(this);
} }
/** /**
@ -53,8 +57,7 @@ public abstract class NormalFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER
* *
* @param maxSpeed 单位为kb * @param maxSpeed 单位为kb
*/ */
@Override protected void setMaxSpeed(int maxSpeed) {
public void setMaxSpeed(int maxSpeed) {
for (int i = 0; i < getTaskList().size(); i++) { for (int i = 0; i < getTaskList().size(); i++) {
AbsThreadTask task = getTaskList().valueAt(i); AbsThreadTask task = getTaskList().valueAt(i);
if (task != null && mStartThreadNum > 0) { if (task != null && mStartThreadNum > 0) {
@ -63,6 +66,11 @@ public abstract class NormalFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER
} }
} }
@Override public void onDestroy() {
super.onDestroy();
EventMsgUtil.getDefault().unRegister(this);
}
@Override protected void onPostPre() { @Override protected void onPostPre() {
super.onPostPre(); super.onPostPre();
mTotalThreadNum = mRecord.threadNum; mTotalThreadNum = mRecord.threadNum;

@ -15,13 +15,8 @@
*/ */
package com.arialyy.aria.core.common; package com.arialyy.aria.core.common;
import android.os.Build; import com.arialyy.annotations.TaskEnum;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.util.CommonUtil;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -39,60 +34,34 @@ public class ProxyHelper {
* 组合下载任务类型 * 组合下载任务类型
*/ */
public static int PROXY_TYPE_DOWNLOAD_GROUP = 0x02; public static int PROXY_TYPE_DOWNLOAD_GROUP = 0x02;
///**
// * 组合任务子任务类型
// */
//public static int PROXY_TYPE_DOWNLOAD_GROUP_SUB = 0x03;
/** /**
* 普通上传任务类型 * 普通上传任务类型
*/ */
public static int PROXY_TYPE_UPLOAD = 0x04; public static int PROXY_TYPE_UPLOAD = 0x03;
public Set<String> downloadCounter = new HashSet<>(), uploadCounter = new HashSet<>(), /**
downloadGroupCounter = new HashSet<>(), downloadGroupSubCounter = new HashSet<>(); * m3u8 peer
*/
public static int PROXY_TYPE_M3U8_PEER = 0x04;
/**
* 组合任务子任务类型
*/
public static int PROXY_TYPE_DOWNLOAD_GROUP_SUB = 0x05;
public Map<String, Set<Integer>> mProxyCache = new ConcurrentHashMap<>(); public Map<String, Set<Integer>> mProxyCache = new ConcurrentHashMap<>();
public static volatile ProxyHelper INSTANCE = null; public static volatile ProxyHelper INSTANCE = null;
private boolean canLoadClass = false;
private ProxyHelper() { private ProxyHelper() {
//init();
} }
public static ProxyHelper getInstance() { public static ProxyHelper getInstance() {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (AriaManager.LOCK) { synchronized (ProxyHelper.class) {
INSTANCE = new ProxyHelper(); INSTANCE = new ProxyHelper();
} }
} }
return INSTANCE; return INSTANCE;
} }
/**
* @since 3.4.6 版本开始已经在ElementHandler中关闭了ProxyClassCounter对象的生成
*/
@Deprecated
private void init() {
List<String> classes = CommonUtil.getPkgClassNames(AriaManager.APP,
"com.arialyy.aria.ProxyClassCounter");
canLoadClass = classes != null
&& !classes.isEmpty()
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
if (canLoadClass) {
for (String className : classes) {
count(className);
}
}
}
/**
* 是否能读取到代理计数文件
*
* @return {@code true} 可以读取{@code false} 不能读取
*/
public boolean isCanLoadCountClass() {
return canLoadClass;
}
/** /**
* 检查观察者对象的代理文件类型 * 检查观察者对象的代理文件类型
* *
@ -107,7 +76,8 @@ public class ProxyHelper {
} }
result = new HashSet<>(); result = new HashSet<>();
try { try {
if (getClass().getClassLoader().loadClass(className.concat("$$DownloadGroupListenerProxy")) if (getClass().getClassLoader()
.loadClass(className.concat(TaskEnum.DOWNLOAD_GROUP.proxySuffix))
!= null) { != null) {
result.add(PROXY_TYPE_DOWNLOAD_GROUP); result.add(PROXY_TYPE_DOWNLOAD_GROUP);
} }
@ -115,7 +85,7 @@ public class ProxyHelper {
//e.printStackTrace(); //e.printStackTrace();
} }
try { try {
if (getClass().getClassLoader().loadClass(className.concat("$$DownloadListenerProxy")) if (getClass().getClassLoader().loadClass(className.concat(TaskEnum.DOWNLOAD.proxySuffix))
!= null) { != null) {
result.add(PROXY_TYPE_DOWNLOAD); result.add(PROXY_TYPE_DOWNLOAD);
} }
@ -124,7 +94,7 @@ public class ProxyHelper {
} }
try { try {
if (getClass().getClassLoader().loadClass(className.concat("$$UploadListenerProxy")) if (getClass().getClassLoader().loadClass(className.concat(TaskEnum.UPLOAD.proxySuffix))
!= null) { != null) {
result.add(PROXY_TYPE_UPLOAD); result.add(PROXY_TYPE_UPLOAD);
} }
@ -132,47 +102,28 @@ public class ProxyHelper {
//e.printStackTrace(); //e.printStackTrace();
} }
if (!result.isEmpty()) { try {
mProxyCache.put(clazz.getName(), result); if (getClass().getClassLoader().loadClass(className.concat(TaskEnum.M3U8_PEER.proxySuffix))
!= null) {
result.add(PROXY_TYPE_M3U8_PEER);
}
} catch (ClassNotFoundException e) {
//e.printStackTrace();
} }
return result;
}
@Deprecated
private void count(String className) {
try { try {
Class clazz = Class.forName(className); if (getClass().getClassLoader()
Method download = clazz.getMethod("getDownloadCounter"); .loadClass(className.concat(TaskEnum.DOWNLOAD_GROUP_SUB.proxySuffix))
Method downloadGroup = clazz.getMethod("getDownloadGroupCounter"); != null) {
Method downloadGroupSub = clazz.getMethod("getDownloadGroupSubCounter"); result.add(PROXY_TYPE_DOWNLOAD_GROUP_SUB);
Method upload = clazz.getMethod("getUploadCounter");
Object object = clazz.newInstance();
Object dc = download.invoke(object);
if (dc != null) {
downloadCounter.addAll((Set<String>) dc);
}
Object dgc = downloadGroup.invoke(object);
if (dgc != null) {
downloadGroupCounter.addAll((Set<String>) dgc);
}
Object dgsc = downloadGroupSub.invoke(object);
if (dgsc != null) {
downloadGroupSubCounter.addAll((Set<String>) dgsc);
}
Object uc = upload.invoke(object);
if (uc != null) {
uploadCounter.addAll((Set<String>) uc);
} }
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
e.printStackTrace(); //e.printStackTrace();
} catch (InstantiationException e) { }
e.printStackTrace();
} catch (IllegalAccessException e) { if (!result.isEmpty()) {
e.printStackTrace(); mProxyCache.put(clazz.getName(), result);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} }
return result;
} }
} }

@ -36,4 +36,6 @@ public class SubThreadConfig<TASK_WRAPPER extends AbsTaskWrapper> {
public Handler stateHandler; public Handler stateHandler;
// 动态文件 // 动态文件
public boolean isOpenDynamicFile; public boolean isOpenDynamicFile;
// m3u8切片索引
public int peerIndex;
} }

@ -16,7 +16,6 @@
package com.arialyy.aria.core.common; package com.arialyy.aria.core.common;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.Message; import android.os.Message;
import com.arialyy.aria.core.inf.IEventListener; import com.arialyy.aria.core.inf.IEventListener;
@ -62,15 +61,12 @@ public class ThreadStateManager implements IThreadState {
case STATE_STOP: case STATE_STOP:
mStopNum++; mStopNum++;
if (isStop()) { if (isStop()) {
mListener.onStop(mProgress);
quitLooper(); quitLooper();
} }
break; break;
case STATE_CANCEL: case STATE_CANCEL:
mCancelNum++; mCancelNum++;
if (isCancel()) { if (isCancel()) {
ALog.d(TAG, "icCancel");
mListener.onCancel();
quitLooper(); quitLooper();
} }
break; break;
@ -133,7 +129,6 @@ public class ThreadStateManager implements IThreadState {
/** /**
* 所有子线程是否都已经停止 * 所有子线程是否都已经停止
*/ */
@Override
public boolean isStop() { public boolean isStop() {
//ALog.d(TAG, //ALog.d(TAG,
// String.format("isStop; stopNum: %s, cancelNum: %s, failNum: %s, completeNum: %s", mStopNum, // String.format("isStop; stopNum: %s, cancelNum: %s, failNum: %s, completeNum: %s", mStopNum,
@ -168,7 +163,6 @@ public class ThreadStateManager implements IThreadState {
/** /**
* 所有子线程是否都已经取消 * 所有子线程是否都已经取消
*/ */
@Override
public boolean isCancel() { public boolean isCancel() {
//ALog.d(TAG, String.format("isCancel; stopNum: %s, cancelNum: %s, failNum: %s, completeNum: %s", //ALog.d(TAG, String.format("isCancel; stopNum: %s, cancelNum: %s, failNum: %s, completeNum: %s",
// mStopNum, // mStopNum,

@ -17,6 +17,7 @@ package com.arialyy.aria.core.common.ftp;
import com.arialyy.aria.core.FtpUrlEntity; import com.arialyy.aria.core.FtpUrlEntity;
import com.arialyy.aria.core.inf.ITaskConfig; import com.arialyy.aria.core.inf.ITaskConfig;
import java.lang.ref.WeakReference;
import java.net.Proxy; import java.net.Proxy;
/** /**
@ -39,7 +40,7 @@ public class FtpTaskConfig implements ITaskConfig {
/** /**
* 上传拦截器 * 上传拦截器
*/ */
private IFtpUploadInterceptor uploadInterceptor; private WeakReference<IFtpUploadInterceptor> uploadInterceptor;
/** /**
* 上传到服务器文件的新文件名{@link FtpInterceptHandler#getNewFileName()} * 上传到服务器文件的新文件名{@link FtpInterceptHandler#getNewFileName()}
@ -55,11 +56,11 @@ public class FtpTaskConfig implements ITaskConfig {
} }
public IFtpUploadInterceptor getUploadInterceptor() { public IFtpUploadInterceptor getUploadInterceptor() {
return uploadInterceptor; return uploadInterceptor.get();
} }
public void setUploadInterceptor(IFtpUploadInterceptor uploadInterceptor) { public void setUploadInterceptor(IFtpUploadInterceptor uploadInterceptor) {
this.uploadInterceptor = uploadInterceptor; this.uploadInterceptor = new WeakReference<>(uploadInterceptor);
} }
public FtpUrlEntity getUrlEntity() { public FtpUrlEntity getUrlEntity() {

@ -41,7 +41,7 @@ import java.util.List;
* *
* </pre> * </pre>
*/ */
public class IFtpUploadInterceptor { public interface IFtpUploadInterceptor {
/** /**
* 处理拦截事件 * 处理拦截事件
@ -49,7 +49,5 @@ public class IFtpUploadInterceptor {
* @param entity 上传信息实体 * @param entity 上传信息实体
* @param fileList ftp服务器端remotePath下的文件列表 * @param fileList ftp服务器端remotePath下的文件列表
*/ */
public FtpInterceptHandler onIntercept(UploadEntity entity, List<String> fileList) { FtpInterceptHandler onIntercept(UploadEntity entity, List<String> fileList);
return null;
}
} }

@ -19,6 +19,7 @@ package com.arialyy.aria.core.common.http;
import com.arialyy.aria.core.common.RequestEnum; import com.arialyy.aria.core.common.RequestEnum;
import com.arialyy.aria.core.inf.IHttpFileLenAdapter; import com.arialyy.aria.core.inf.IHttpFileLenAdapter;
import com.arialyy.aria.core.inf.ITaskConfig; import com.arialyy.aria.core.inf.ITaskConfig;
import java.lang.ref.WeakReference;
import java.net.CookieManager; import java.net.CookieManager;
import java.net.Proxy; import java.net.Proxy;
import java.util.HashMap; import java.util.HashMap;
@ -82,17 +83,17 @@ public class HttpTaskConfig implements ITaskConfig {
*/ */
private Map<String, String> formFields = new HashMap<>(); private Map<String, String> formFields = new HashMap<>();
private IHttpFileLenAdapter fileLenAdapter; private WeakReference<IHttpFileLenAdapter> fileLenAdapter;
public IHttpFileLenAdapter getFileLenAdapter() { public IHttpFileLenAdapter getFileLenAdapter() {
return fileLenAdapter; return fileLenAdapter.get();
} }
/** /**
* 如果是匿名内部类完成后需要将adapter设置为空否则会出现内存泄漏 * 如果是匿名内部类完成后需要将adapter设置为空否则会出现内存泄漏
*/ */
public void setFileLenAdapter(IHttpFileLenAdapter fileLenAdapter) { public void setFileLenAdapter(IHttpFileLenAdapter fileLenAdapter) {
this.fileLenAdapter = fileLenAdapter; this.fileLenAdapter = new WeakReference<>(fileLenAdapter);
} }
public Map<String, String> getFormFields() { public Map<String, String> getFormFields() {

@ -15,6 +15,8 @@
*/ */
package com.arialyy.aria.core.config; package com.arialyy.aria.core.config;
import com.arialyy.aria.core.event.EventMsgUtil;
import com.arialyy.aria.core.event.SpeedEvent;
import com.arialyy.aria.core.queue.DownloadGroupTaskQueue; import com.arialyy.aria.core.queue.DownloadGroupTaskQueue;
import java.io.Serializable; import java.io.Serializable;
@ -50,7 +52,7 @@ public class DGroupConfig extends BaseTaskConfig implements Serializable {
@Override public DGroupConfig setMaxSpeed(int maxSpeed) { @Override public DGroupConfig setMaxSpeed(int maxSpeed) {
super.setMaxSpeed(maxSpeed); super.setMaxSpeed(maxSpeed);
DownloadGroupTaskQueue.getInstance().setMaxSpeed(maxSpeed); EventMsgUtil.getDefault().post(new SpeedEvent(maxSpeed));
return this; return this;
} }

@ -15,6 +15,8 @@
*/ */
package com.arialyy.aria.core.config; package com.arialyy.aria.core.config;
import com.arialyy.aria.core.event.EventMsgUtil;
import com.arialyy.aria.core.event.SpeedEvent;
import com.arialyy.aria.core.queue.DownloadTaskQueue; import com.arialyy.aria.core.queue.DownloadTaskQueue;
import java.io.Serializable; import java.io.Serializable;
@ -47,7 +49,7 @@ public class DownloadConfig extends BaseTaskConfig implements Serializable {
@Override public DownloadConfig setMaxSpeed(int maxSpeed) { @Override public DownloadConfig setMaxSpeed(int maxSpeed) {
super.setMaxSpeed(maxSpeed); super.setMaxSpeed(maxSpeed);
DownloadTaskQueue.getInstance().setMaxSpeed(maxSpeed); EventMsgUtil.getDefault().post(new SpeedEvent(maxSpeed));
return this; return this;
} }

@ -15,6 +15,8 @@
*/ */
package com.arialyy.aria.core.config; package com.arialyy.aria.core.config;
import com.arialyy.aria.core.event.EventMsgUtil;
import com.arialyy.aria.core.event.SpeedEvent;
import com.arialyy.aria.core.queue.UploadTaskQueue; import com.arialyy.aria.core.queue.UploadTaskQueue;
import java.io.Serializable; import java.io.Serializable;
@ -28,7 +30,7 @@ public class UploadConfig extends BaseTaskConfig implements Serializable {
@Override public UploadConfig setMaxSpeed(int maxSpeed) { @Override public UploadConfig setMaxSpeed(int maxSpeed) {
super.setMaxSpeed(maxSpeed); super.setMaxSpeed(maxSpeed);
UploadTaskQueue.getInstance().setMaxSpeed(maxSpeed); EventMsgUtil.getDefault().post(new SpeedEvent(maxSpeed));
return this; return this;
} }

@ -15,8 +15,8 @@
*/ */
package com.arialyy.aria.core.download; package com.arialyy.aria.core.download;
import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.command.NormalCmdFactory;
import com.arialyy.aria.core.command.normal.NormalCmdFactory; import com.arialyy.aria.core.event.EventMsgUtil;
import com.arialyy.aria.core.inf.AbsTarget; import com.arialyy.aria.core.inf.AbsTarget;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
@ -43,11 +43,9 @@ abstract class AbsDTarget<TARGET extends AbsDTarget> extends AbsTarget<TARGET> {
*/ */
public void setHighestPriority() { public void setHighestPriority() {
if (checkConfig()) { if (checkConfig()) {
AriaManager.getInstance(AriaManager.APP) EventMsgUtil.getDefault()
.setCmd( .post(CommonUtil.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_HIGHEST_PRIORITY,
CommonUtil.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_HIGHEST_PRIORITY, checkTaskType()));
checkTaskType()))
.exe();
} }
} }

@ -17,8 +17,8 @@ package com.arialyy.aria.core.download;
import android.text.TextUtils; import android.text.TextUtils;
import com.arialyy.aria.core.common.RecordHandler; import com.arialyy.aria.core.common.RecordHandler;
import com.arialyy.aria.core.inf.ITargetHandler;
import com.arialyy.aria.core.inf.IConfigHandler; import com.arialyy.aria.core.inf.IConfigHandler;
import com.arialyy.aria.core.inf.ITargetHandler;
import com.arialyy.aria.core.inf.ITaskWrapper; import com.arialyy.aria.core.inf.ITaskWrapper;
import com.arialyy.aria.core.manager.TaskWrapperManager; import com.arialyy.aria.core.manager.TaskWrapperManager;
import com.arialyy.aria.core.queue.DownloadTaskQueue; import com.arialyy.aria.core.queue.DownloadTaskQueue;
@ -93,8 +93,7 @@ class DNormalConfigHandler<TARGET extends AbsDTarget> implements IConfigHandler
} }
@Override public boolean isRunning() { @Override public boolean isRunning() {
DownloadTask task = DownloadTaskQueue.getInstance().getTask(mEntity.getKey()); return DownloadTaskQueue.getInstance().taskIsRunning(mEntity.getKey());
return task != null && task.isRunning();
} }
@Override public boolean checkEntity() { @Override public boolean checkEntity() {
@ -113,9 +112,10 @@ class DNormalConfigHandler<TARGET extends AbsDTarget> implements IConfigHandler
File file = new File(mTempFilePath); File file = new File(mTempFilePath);
DTaskWrapper wrapper = (DTaskWrapper) mTarget.getTaskWrapper(); DTaskWrapper wrapper = (DTaskWrapper) mTarget.getTaskWrapper();
// 缓存文件夹格式:问文件夹/.文件名_码率 // 缓存文件夹格式:问文件夹/.文件名_码率
wrapper.asM3U8() String cacheDir = String.format("%s/.%s_%s", file.getParent(), file.getName(),
.setCacheDir(String.format("%s/.%s_%s", file.getParent(), file.getName(), wrapper.asM3U8().getBandWidth());
wrapper.asM3U8().getBandWidth())); wrapper.asM3U8().setCacheDir(cacheDir);
mEntity.getM3U8Entity().setCacheDir(cacheDir);
if (wrapper.getRequestType() == ITaskWrapper.M3U8_VOD) { if (wrapper.getRequestType() == ITaskWrapper.M3U8_VOD) {
if (mEntity.getFileSize() == 0) { if (mEntity.getFileSize() == 0) {
ALog.w(TAG, ALog.w(TAG,

@ -18,16 +18,16 @@ package com.arialyy.aria.core.download;
import android.support.annotation.CheckResult; import android.support.annotation.CheckResult;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.text.TextUtils; import android.text.TextUtils;
import com.arialyy.annotations.DownloadGroup; import com.arialyy.annotations.TaskEnum;
import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.command.CancelAllCmd;
import com.arialyy.aria.core.command.ICmd; import com.arialyy.aria.core.command.ICmd;
import com.arialyy.aria.core.command.normal.CancelAllCmd; import com.arialyy.aria.core.command.NormalCmdFactory;
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
import com.arialyy.aria.core.common.ProxyHelper; import com.arialyy.aria.core.common.ProxyHelper;
import com.arialyy.aria.core.event.EventMsgUtil;
import com.arialyy.aria.core.inf.AbsEntity; import com.arialyy.aria.core.inf.AbsEntity;
import com.arialyy.aria.core.inf.AbsReceiver; import com.arialyy.aria.core.inf.AbsReceiver;
import com.arialyy.aria.core.inf.ReceiverType; import com.arialyy.aria.core.inf.ReceiverType;
import com.arialyy.aria.core.manager.TaskWrapperManager;
import com.arialyy.aria.core.scheduler.DownloadGroupSchedulers; import com.arialyy.aria.core.scheduler.DownloadGroupSchedulers;
import com.arialyy.aria.core.scheduler.DownloadSchedulers; import com.arialyy.aria.core.scheduler.DownloadSchedulers;
import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.orm.DbEntity;
@ -173,9 +173,13 @@ public class DownloadReceiver extends AbsReceiver {
if (set != null && !set.isEmpty()) { if (set != null && !set.isEmpty()) {
for (Integer type : set) { for (Integer type : set) {
if (type == ProxyHelper.PROXY_TYPE_DOWNLOAD) { if (type == ProxyHelper.PROXY_TYPE_DOWNLOAD) {
DownloadSchedulers.getInstance().register(obj); DownloadSchedulers.getInstance().register(obj, TaskEnum.DOWNLOAD);
} else if (type == ProxyHelper.PROXY_TYPE_DOWNLOAD_GROUP) { } else if (type == ProxyHelper.PROXY_TYPE_DOWNLOAD_GROUP) {
DownloadGroupSchedulers.getInstance().register(obj); DownloadGroupSchedulers.getInstance().register(obj, TaskEnum.DOWNLOAD_GROUP);
} else if (type == ProxyHelper.PROXY_TYPE_M3U8_PEER) {
DownloadSchedulers.getInstance().register(obj, TaskEnum.M3U8_PEER);
} else if (type == ProxyHelper.PROXY_TYPE_DOWNLOAD_GROUP_SUB) {
DownloadGroupSchedulers.getInstance().register(obj, TaskEnum.DOWNLOAD_GROUP_SUB);
} }
} }
} else { } else {
@ -417,11 +421,9 @@ public class DownloadReceiver extends AbsReceiver {
* 停止所有正在下载的任务并清空等待队列 * 停止所有正在下载的任务并清空等待队列
*/ */
public void stopAllTask() { public void stopAllTask() {
AriaManager.getInstance(AriaManager.APP) EventMsgUtil.getDefault().post(NormalCmdFactory.getInstance()
.setCmd(NormalCmdFactory.getInstance() .createCmd(new DTaskWrapper(null), NormalCmdFactory.TASK_STOP_ALL,
.createCmd(new DTaskWrapper(null), NormalCmdFactory.TASK_STOP_ALL, ICmd.TASK_TYPE_DOWNLOAD));
ICmd.TASK_TYPE_DOWNLOAD))
.exe();
} }
/** /**
@ -430,11 +432,9 @@ public class DownloadReceiver extends AbsReceiver {
* 2.如果队列执行队列已经满了则将所有任务添加到等待队列中 * 2.如果队列执行队列已经满了则将所有任务添加到等待队列中
*/ */
public void resumeAllTask() { public void resumeAllTask() {
AriaManager.getInstance(AriaManager.APP) EventMsgUtil.getDefault().post(NormalCmdFactory.getInstance()
.setCmd(NormalCmdFactory.getInstance() .createCmd(new DTaskWrapper(null), NormalCmdFactory.TASK_RESUME_ALL,
.createCmd(new DTaskWrapper(null), NormalCmdFactory.TASK_RESUME_ALL, ICmd.TASK_TYPE_DOWNLOAD));
ICmd.TASK_TYPE_DOWNLOAD))
.exe();
} }
/** /**
@ -449,7 +449,8 @@ public class DownloadReceiver extends AbsReceiver {
(CancelAllCmd) CommonUtil.createNormalCmd(new DTaskWrapper(null), (CancelAllCmd) CommonUtil.createNormalCmd(new DTaskWrapper(null),
NormalCmdFactory.TASK_CANCEL_ALL, ICmd.TASK_TYPE_DOWNLOAD); NormalCmdFactory.TASK_CANCEL_ALL, ICmd.TASK_TYPE_DOWNLOAD);
cancelCmd.removeFile = removeFile; cancelCmd.removeFile = removeFile;
ariaManager.setCmd(cancelCmd).exe(); EventMsgUtil.getDefault().post(cancelCmd);
Set<String> keys = ariaManager.getReceiver().keySet(); Set<String> keys = ariaManager.getReceiver().keySet();
for (String key : keys) { for (String key : keys) {
ariaManager.getReceiver().remove(key); ariaManager.getReceiver().remove(key);

@ -24,6 +24,7 @@ import com.arialyy.aria.core.download.downloader.SimpleDownloadUtil;
import com.arialyy.aria.core.download.m3u8.M3U8LiveUtil; import com.arialyy.aria.core.download.m3u8.M3U8LiveUtil;
import com.arialyy.aria.core.download.m3u8.M3U8VodUtil; import com.arialyy.aria.core.download.m3u8.M3U8VodUtil;
import com.arialyy.aria.core.inf.AbsNormalTask; import com.arialyy.aria.core.inf.AbsNormalTask;
import com.arialyy.aria.core.inf.AbsTaskWrapper;
import com.arialyy.aria.core.inf.IDownloadListener; import com.arialyy.aria.core.inf.IDownloadListener;
import com.arialyy.aria.core.inf.ITaskWrapper; import com.arialyy.aria.core.inf.ITaskWrapper;
import com.arialyy.aria.core.scheduler.ISchedulers; import com.arialyy.aria.core.scheduler.ISchedulers;
@ -39,7 +40,12 @@ public class DownloadTask extends AbsNormalTask<DTaskWrapper> {
mTaskWrapper = taskWrapper; mTaskWrapper = taskWrapper;
mOutHandler = outHandler; mOutHandler = outHandler;
mContext = AriaManager.APP; mContext = AriaManager.APP;
mListener = new BaseDListener(this, mOutHandler); if (taskWrapper.getRequestType() == AbsTaskWrapper.M3U8_VOD
|| taskWrapper.getRequestType() == AbsTaskWrapper.M3U8_LIVE) {
mListener = new M3U8Listener(this, mOutHandler);
} else {
mListener = new BaseDListener(this, mOutHandler);
}
} }
/** /**
@ -90,9 +96,9 @@ public class DownloadTask extends AbsNormalTask<DTaskWrapper> {
@Override protected synchronized IUtil createUtil() { @Override protected synchronized IUtil createUtil() {
if (mTaskWrapper.getRequestType() == ITaskWrapper.M3U8_VOD) { if (mTaskWrapper.getRequestType() == ITaskWrapper.M3U8_VOD) {
return new M3U8VodUtil(mTaskWrapper, (IDownloadListener) mListener); return new M3U8VodUtil(mTaskWrapper, (M3U8Listener) mListener);
} else if (mTaskWrapper.getRequestType() == ITaskWrapper.M3U8_LIVE) { } else if (mTaskWrapper.getRequestType() == ITaskWrapper.M3U8_LIVE) {
return new M3U8LiveUtil(mTaskWrapper, (IDownloadListener) mListener); return new M3U8LiveUtil(mTaskWrapper, (M3U8Listener) mListener);
} else { } else {
return new SimpleDownloadUtil(mTaskWrapper, (IDownloadListener) mListener); return new SimpleDownloadUtil(mTaskWrapper, (IDownloadListener) mListener);
} }

@ -0,0 +1,75 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.download;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import com.arialyy.aria.core.inf.IDownloadListener;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.scheduler.ISchedulers;
import com.arialyy.aria.util.CommonUtil;
/**
* 下载监听类
*/
public class M3U8Listener extends BaseDListener implements IDownloadListener {
M3U8Listener(DownloadTask task, Handler outHandler) {
super(task, outHandler);
}
@Override
public void onPostPre(long fileSize) {
mEntity.setFileSize(fileSize);
mEntity.setConvertFileSize(CommonUtil.formatFileSize(fileSize));
saveData(IEntity.STATE_POST_PRE, -1);
sendInState2Target(ISchedulers.POST_PRE);
}
/**
* 切片开始下载
*/
public void onPeerStart(String m3u8Url, String peerPath, int peerIndex) {
sendPeerStateToTarget(ISchedulers.M3U8_PEER_START, m3u8Url, peerPath, peerIndex);
}
/**
* 切片下载完成
*/
public void onPeerComplete(String m3u8Url, String peerPath, int peerIndex) {
sendPeerStateToTarget(ISchedulers.M3U8_PEER_COMPLETE, m3u8Url, peerPath, peerIndex);
}
/**
* 切片下载失败
*/
public void onPeerFail(String m3u8Url, String peerPath, int peerIndex) {
sendPeerStateToTarget(ISchedulers.M3U8_PEER_FAIL, m3u8Url, peerPath, peerIndex);
}
private void sendPeerStateToTarget(int state, String m3u8Url, String peerPath, int peerIndex) {
Bundle bundle = new Bundle();
bundle.putString(ISchedulers.DATA_M3U8_URL, m3u8Url);
bundle.putString(ISchedulers.DATA_M3U8_PEER_PATH, peerPath);
bundle.putInt(ISchedulers.DATA_M3U8_PEER_INDEX, peerIndex);
Message msg = outHandler.get().obtainMessage();
msg.setData(bundle);
msg.what = state;
msg.arg1 = ISchedulers.IS_M3U8_PEER;
msg.sendToTarget();
}
}

@ -21,6 +21,8 @@ import com.arialyy.aria.core.common.RecordHandler;
import com.arialyy.aria.core.common.SubThreadConfig; import com.arialyy.aria.core.common.SubThreadConfig;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.event.Event;
import com.arialyy.aria.core.event.SpeedEvent;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;
import com.arialyy.aria.core.inf.IDownloadListener; import com.arialyy.aria.core.inf.IDownloadListener;
import com.arialyy.aria.exception.BaseException; import com.arialyy.aria.exception.BaseException;
@ -95,6 +97,11 @@ public class Downloader extends NormalFileer<DownloadEntity, DTaskWrapper> {
} }
} }
@Event
public void setMaxSpeed(SpeedEvent event) {
setMaxSpeed(event.speed);
}
@Override protected void onPostPre() { @Override protected void onPostPre() {
super.onPostPre(); super.onPostPre();
((IDownloadListener) mListener).onPostPre(mEntity.getFileSize()); ((IDownloadListener) mListener).onPostPre(mEntity.getFileSize());

@ -111,6 +111,8 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DTaskWrapper> {
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
onThreadComplete();
} }
return this; return this;
} }

@ -331,7 +331,7 @@ public class HttpFileInfoThread implements Runnable {
} }
} }
private static class FileLenAdapter extends IHttpFileLenAdapter { private static class FileLenAdapter implements IHttpFileLenAdapter {
@Override public long handleFileLen(Map<String, List<String>> headers) { @Override public long handleFileLen(Map<String, List<String>> headers) {
List<String> sLength = headers.get("Content-Length"); List<String> sLength = headers.get("Content-Length");

@ -141,6 +141,8 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
onThreadComplete();
} }
return this; return this;
} }

@ -97,15 +97,12 @@ public class SimpleDownloadUtil implements IUtil {
new Thread(createInfoThread()).start(); new Thread(createInfoThread()).start();
} }
@Override public void setMaxSpeed(int speed) {
mDownloader.setMaxSpeed(speed);
}
private void failDownload(BaseException e, boolean needRetry) { private void failDownload(BaseException e, boolean needRetry) {
if (isStop || isCancel) { if (isStop || isCancel) {
return; return;
} }
mListener.onFail(needRetry, e); mListener.onFail(needRetry, e);
mDownloader.onDestroy();
} }
/** /**

@ -19,12 +19,11 @@ import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import com.arialyy.aria.core.common.IUtil; import com.arialyy.aria.core.common.IUtil;
import com.arialyy.aria.core.config.Configuration; import com.arialyy.aria.core.config.Configuration;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DGTaskWrapper; import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.inf.IEntity; import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -220,16 +219,6 @@ public abstract class AbsGroupUtil implements IUtil, Runnable {
} }
@Override public void setMaxSpeed(int speed) {
Set<String> keys = mSubQueue.getExec().keySet();
for (String key : keys) {
SubDownloadLoader dt = mSubQueue.getExec().get(key);
if (dt != null) {
dt.setMaxSpeed(speed);
}
}
}
synchronized void closeTimer() { synchronized void closeTimer() {
if (mTimer != null && !mTimer.isShutdown()) { if (mTimer != null && !mTimer.isShutdown()) {
mTimer.shutdown(); mTimer.shutdown();

@ -127,10 +127,4 @@ class SubDownloadLoader implements IUtil {
ALog.w(TAG, String.format("不识别的类型,requestType:%s", mWrapper.getRequestType())); ALog.w(TAG, String.format("不识别的类型,requestType:%s", mWrapper.getRequestType()));
} }
} }
@Override public void setMaxSpeed(int speed) {
if (mDownloader != null) {
mDownloader.setMaxSpeed(speed);
}
}
} }

@ -30,7 +30,7 @@ public abstract class BaseM3U8Loader extends AbsFileer<DownloadEntity, DTaskWrap
} }
@Override protected long delayTimer() { @Override protected long delayTimer() {
return 2000; return 1000;
} }
/** /**

@ -19,7 +19,7 @@ package com.arialyy.aria.core.download.m3u8;
* M3U8 bandWidth 码率url转换器对于某些服务器返回的ts地址可以是相对地址也可能是处理过的 * M3U8 bandWidth 码率url转换器对于某些服务器返回的ts地址可以是相对地址也可能是处理过的
* 对于这种情况你需要使用url转换器将地址转换为可正常访问的http地址 * 对于这种情况你需要使用url转换器将地址转换为可正常访问的http地址
*/ */
public class IBandWidthUrlConverter { public interface IBandWidthUrlConverter {
/** /**
* 转换码率地址为可用的http地址对于某些服务器返回的切片信息有可能是相对地址也可能是处理过的 * 转换码率地址为可用的http地址对于某些服务器返回的切片信息有可能是相对地址也可能是处理过的
@ -28,7 +28,5 @@ public class IBandWidthUrlConverter {
* @param bandWidthUrl 原始码率地址 * @param bandWidthUrl 原始码率地址
* @return 可正常访问的http地址 * @return 可正常访问的http地址
*/ */
public String convert(String bandWidthUrl) { String convert(String bandWidthUrl);
return null;
}
} }

@ -19,7 +19,7 @@ package com.arialyy.aria.core.download.m3u8;
* M3U8 直播下载ts url转换器对于某些服务器返回的ts地址可以是相对地址也可能是处理过的 * M3U8 直播下载ts url转换器对于某些服务器返回的ts地址可以是相对地址也可能是处理过的
* 对于这种情况你需要使用url转换器将地址转换为可正常访问的http地址 * 对于这种情况你需要使用url转换器将地址转换为可正常访问的http地址
*/ */
public class ILiveTsUrlConverter { public interface ILiveTsUrlConverter {
/** /**
* 处理#EXTINF信息对于某些服务器返回的切片信息有可能是相对地址因此你需要自行转换为可下载http连接 * 处理#EXTINF信息对于某些服务器返回的切片信息有可能是相对地址因此你需要自行转换为可下载http连接
@ -28,7 +28,5 @@ public class ILiveTsUrlConverter {
* @param tsUrl ts文件下载地址 * @param tsUrl ts文件下载地址
* @return 转换后的http地址 * @return 转换后的http地址
*/ */
public String convert(String m3u8Url, String tsUrl) { public String convert(String m3u8Url, String tsUrl);
return null;
}
} }

@ -21,7 +21,7 @@ import java.util.List;
/** /**
* Ts文件合并处理如果你希望使用自行处理ts文件的合并你可以实现该接口 * Ts文件合并处理如果你希望使用自行处理ts文件的合并你可以实现该接口
*/ */
public class ITsMergeHandler { public interface ITsMergeHandler {
/** /**
* 合并ts文件 * 合并ts文件
@ -30,7 +30,5 @@ public class ITsMergeHandler {
* @param tsPath ts文件列表 * @param tsPath ts文件列表
* @return {@code true} 合并成功 * @return {@code true} 合并成功
*/ */
public boolean merge(@Nullable M3U8KeyInfo keyInfo, List<String> tsPath) { boolean merge(@Nullable M3U8KeyInfo keyInfo, List<String> tsPath);
return false;
}
} }

@ -21,7 +21,7 @@ import java.util.List;
* M3U8 点播文件下载ts url转换器对于某些服务器返回的ts地址可以是相对地址也可能是处理过的 * M3U8 点播文件下载ts url转换器对于某些服务器返回的ts地址可以是相对地址也可能是处理过的
* 对于这种情况你需要使用url转换器将地址转换为可正常访问的http地址 * 对于这种情况你需要使用url转换器将地址转换为可正常访问的http地址
*/ */
public class IVodTsUrlConverter { public interface IVodTsUrlConverter {
/** /**
* 处理#EXTINF信息对于某些服务器返回的切片信息有可能是相对地址因此你需要自行转换为可下载http连接 * 处理#EXTINF信息对于某些服务器返回的切片信息有可能是相对地址因此你需要自行转换为可下载http连接
@ -30,7 +30,5 @@ public class IVodTsUrlConverter {
* @param tsUrls ts文件下载地址列表 * @param tsUrls ts文件下载地址列表
* @return 根据切片信息转换后的http连接列表如果你的切片信息是可以直接下载的http连接直接返回extInf便可 * @return 根据切片信息转换后的http连接列表如果你的切片信息是可以直接下载的http连接直接返回extInf便可
*/ */
public List<String> convert(String m3u8Url, List<String> tsUrls) { List<String> convert(String m3u8Url, List<String> tsUrls);
return null;
}
} }

@ -17,7 +17,16 @@ package com.arialyy.aria.core.download.m3u8;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import android.text.TextUtils;
import com.arialyy.aria.core.common.TaskRecord;
import com.arialyy.aria.core.common.ThreadRecord;
import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.DbDataHelper;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.List;
/** /**
* M3U8实体信息 * M3U8实体信息
@ -44,10 +53,85 @@ public class M3U8Entity extends DbEntity implements Parcelable {
*/ */
private boolean isLive; private boolean isLive;
/**
* 缓存目录
*/
private String cacheDir;
public boolean isLive() { public boolean isLive() {
return isLive; return isLive;
} }
/**
* 获取m3u8切片
* 如果任务未完成则返回所有已下载完成的切片
* 如果任务已完成如果你设置{@link M3U8Delegate#merge(boolean)}合并分块的请求返回null如果没有设置该请求则返回所有已下载完成的切片
*/
public List<PeerInfo> getCompletedPeer() {
if (TextUtils.isEmpty(getCacheDir())) {
ALog.w("M3U8Entity", "任务未下载,获取切片失败");
return null;
}
List<PeerInfo> peers = new ArrayList<>();
TaskRecord taskRecord = DbDataHelper.getTaskRecord(filePath);
File cacheDir = new File(getCacheDir());
if ((taskRecord == null
|| taskRecord.threadRecords == null
|| taskRecord.threadRecords.isEmpty())
&& !cacheDir.exists()) {
return null;
}
// 处理任务完成的情况
if (taskRecord == null
|| taskRecord.threadRecords == null
|| taskRecord.threadRecords.isEmpty()
&& cacheDir.exists()) {
String[] files = cacheDir.list(new FilenameFilter() {
@Override public boolean accept(File dir, String name) {
return name.endsWith(".ts");
}
});
for (String fileName : files) {
PeerInfo peerInfo =
new PeerInfo(Integer.parseInt(fileName.substring(0, fileName.lastIndexOf(".ts"))),
getCacheDir().concat("/").concat(fileName));
peers.add(peerInfo);
}
return peers;
}
// 任务未完成的情况
if (taskRecord.threadRecords != null
&& !taskRecord.threadRecords.isEmpty()
&& cacheDir.exists()) {
for (ThreadRecord tr : taskRecord.threadRecords) {
if (!tr.isComplete) {
continue;
}
String peerPath = String.format("%s/%s.ts", cacheDir, tr.threadId);
if (new File(peerPath).exists()) {
PeerInfo peerInfo = new PeerInfo(tr.threadId, peerPath);
peers.add(peerInfo);
}
}
return peers;
}
return null;
}
public String getCacheDir() {
return cacheDir;
}
public void setCacheDir(String cacheDir) {
this.cacheDir = cacheDir;
}
public void setLive(boolean live) { public void setLive(boolean live) {
isLive = live; isLive = live;
} }
@ -88,6 +172,7 @@ public class M3U8Entity extends DbEntity implements Parcelable {
dest.writeInt(this.peerIndex); dest.writeInt(this.peerIndex);
dest.writeInt(this.peerNum); dest.writeInt(this.peerNum);
dest.writeByte(this.isLive ? (byte) 1 : (byte) 0); dest.writeByte(this.isLive ? (byte) 1 : (byte) 0);
dest.writeString(this.cacheDir);
} }
protected M3U8Entity(Parcel in) { protected M3U8Entity(Parcel in) {
@ -95,6 +180,7 @@ public class M3U8Entity extends DbEntity implements Parcelable {
this.peerIndex = in.readInt(); this.peerIndex = in.readInt();
this.peerNum = in.readInt(); this.peerNum = in.readInt();
this.isLive = in.readByte() != 0; this.isLive = in.readByte() != 0;
this.cacheDir = in.readString();
} }
public static final Creator<M3U8Entity> CREATOR = new Creator<M3U8Entity>() { public static final Creator<M3U8Entity> CREATOR = new Creator<M3U8Entity>() {
@ -106,4 +192,14 @@ public class M3U8Entity extends DbEntity implements Parcelable {
return new M3U8Entity[size]; return new M3U8Entity[size];
} }
}; };
public static class PeerInfo {
public PeerInfo(int peerId, String peerPath) {
this.peerId = peerId;
this.peerPath = peerPath;
}
public int peerId;
public String peerPath;
}
} }

@ -91,7 +91,7 @@ final class M3U8InfoThread implements Runnable {
conn.connect(); conn.connect();
handleConnect(conn); handleConnect(conn);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); failDownload(e.getMessage(), false);
} finally { } finally {
if (conn != null) { if (conn != null) {
conn.disconnect(); conn.disconnect();
@ -147,7 +147,7 @@ final class M3U8InfoThread implements Runnable {
failDownload(String.format("获取M3U8下载地址列表失败,url: %s", mEntity.getUrl()), false); failDownload(String.format("获取M3U8下载地址列表失败,url: %s", mEntity.getUrl()), false);
return; return;
} }
if (!isLive && mEntity.getM3U8Entity().getPeerNum() != 0) { if (!isLive && mEntity.getM3U8Entity().getPeerNum() == 0) {
mEntity.getM3U8Entity().setPeerNum(extInf.size()); mEntity.getM3U8Entity().setPeerNum(extInf.size());
mEntity.getM3U8Entity().update(); mEntity.getM3U8Entity().update();
} }
@ -257,6 +257,8 @@ final class M3U8InfoThread implements Runnable {
failDownload(String.format("码率转换器转换后的url地址无效,转换后的url:%s", bandWidthM3u8Url), false); failDownload(String.format("码率转换器转换后的url地址无效,转换后的url:%s", bandWidthM3u8Url), false);
return; return;
} }
} else {
ALog.d(TAG, "没有设置码率转换器");
} }
mTaskWrapper.asM3U8().setBandWidthUrl(bandWidthM3u8Url); mTaskWrapper.asM3U8().setBandWidthUrl(bandWidthM3u8Url);
ALog.d(TAG, String.format("新码率url:%s", bandWidthM3u8Url)); ALog.d(TAG, String.format("新码率url:%s", bandWidthM3u8Url));

@ -99,10 +99,6 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
}).start(); }).start();
} }
@Override protected void setMaxSpeed(int maxSpeed) {
// TODO: 2019-06-06 暂不支持
}
private void notifyLock() { private void notifyLock() {
try { try {
LOCK.lock(); LOCK.lock();
@ -227,16 +223,14 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
@Override public boolean handleMessage(Message msg) { @Override public boolean handleMessage(Message msg) {
switch (msg.what) { switch (msg.what) {
case STATE_STOP: case STATE_STOP:
if (isStop()) { if (isBreak()) {
ALog.d(TAG, "任务停止"); ALog.d(TAG, "任务停止");
mListener.onStop(mProgress);
quitLooper(); quitLooper();
} }
break; break;
case STATE_CANCEL: case STATE_CANCEL:
if (isCancel()) { if (isBreak()) {
ALog.d(TAG, "任务取消"); ALog.d(TAG, "任务取消");
mListener.onCancel();
quitLooper(); quitLooper();
} }
break; break;
@ -250,10 +244,6 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
return false; return false;
} }
@Override public boolean isStop() {
return false;
}
@Override public boolean isFail() { @Override public boolean isFail() {
return false; return false;
} }
@ -262,10 +252,6 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
return false; return false;
} }
@Override public boolean isCancel() {
return false;
}
@Override public long getCurrentProgress() { @Override public long getCurrentProgress() {
return mProgress; return mProgress;
} }

@ -129,10 +129,6 @@ public class M3U8LiveUtil implements IUtil {
} }
} }
@Override public void setMaxSpeed(int speed) {
mLoader.setMaxSpeed(speed);
}
/** /**
* 获取直播文件信息 * 获取直播文件信息
*/ */

@ -15,6 +15,7 @@
*/ */
package com.arialyy.aria.core.download.m3u8; package com.arialyy.aria.core.download.m3u8;
import java.lang.ref.WeakReference;
import java.util.List; import java.util.List;
/** /**
@ -30,7 +31,7 @@ public class M3U8TaskConfig {
/** /**
* #EXTINF 标签信息处理器 * #EXTINF 标签信息处理器
*/ */
private IVodTsUrlConverter vodUrlConverter; private WeakReference<IVodTsUrlConverter> vodUrlConverter;
/** /**
* 缓存目录 * 缓存目录
@ -45,7 +46,7 @@ public class M3U8TaskConfig {
/** /**
* 合并处理器 * 合并处理器
*/ */
private ITsMergeHandler mergeHandler; private WeakReference<ITsMergeHandler> mergeHandler;
/** /**
* 已完成的ts分片数量 * 已完成的ts分片数量
@ -65,7 +66,7 @@ public class M3U8TaskConfig {
/** /**
* 码率url转换器 * 码率url转换器
*/ */
private IBandWidthUrlConverter bandWidthUrlConverter; private WeakReference<IBandWidthUrlConverter> bandWidthUrlConverter;
/** /**
* 码率地址 * 码率地址
@ -80,7 +81,7 @@ public class M3U8TaskConfig {
/** /**
* 直播下载ts url转换器 * 直播下载ts url转换器
*/ */
private ILiveTsUrlConverter liveTsUrlConverter; private WeakReference<ILiveTsUrlConverter> liveTsUrlConverter;
/** /**
* 直播的m3u8文件更新间隔 * 直播的m3u8文件更新间隔
@ -92,6 +93,19 @@ public class M3U8TaskConfig {
*/ */
private int maxTsQueueNum = 4; private int maxTsQueueNum = 4;
/**
* 指定的索引位置
*/
private int jumpIndex;
public int getJumpIndex() {
return jumpIndex;
}
public void setJumpIndex(int jumpIndex) {
this.jumpIndex = jumpIndex;
}
public int getMaxTsQueueNum() { public int getMaxTsQueueNum() {
return maxTsQueueNum; return maxTsQueueNum;
} }
@ -109,12 +123,11 @@ public class M3U8TaskConfig {
} }
public ILiveTsUrlConverter getLiveTsUrlConverter() { public ILiveTsUrlConverter getLiveTsUrlConverter() {
return liveTsUrlConverter; return liveTsUrlConverter.get();
} }
public void setLiveTsUrlConverter( public void setLiveTsUrlConverter(ILiveTsUrlConverter liveTsUrlConverter) {
ILiveTsUrlConverter liveTsUrlConverter) { this.liveTsUrlConverter = new WeakReference<>(liveTsUrlConverter);
this.liveTsUrlConverter = liveTsUrlConverter;
} }
public M3U8KeyInfo getKeyInfo() { public M3U8KeyInfo getKeyInfo() {
@ -134,12 +147,11 @@ public class M3U8TaskConfig {
} }
public IBandWidthUrlConverter getBandWidthUrlConverter() { public IBandWidthUrlConverter getBandWidthUrlConverter() {
return bandWidthUrlConverter; return bandWidthUrlConverter.get();
} }
public void setBandWidthUrlConverter( public void setBandWidthUrlConverter(IBandWidthUrlConverter bandWidthUrlConverter) {
IBandWidthUrlConverter bandWidthUrlConverter) { this.bandWidthUrlConverter = new WeakReference<>(bandWidthUrlConverter);
this.bandWidthUrlConverter = bandWidthUrlConverter;
} }
public int getBandWidth() { public int getBandWidth() {
@ -175,19 +187,19 @@ public class M3U8TaskConfig {
} }
public ITsMergeHandler getMergeHandler() { public ITsMergeHandler getMergeHandler() {
return mergeHandler; return mergeHandler.get();
} }
public void setMergeHandler(ITsMergeHandler mergeHandler) { public void setMergeHandler(ITsMergeHandler mergeHandler) {
this.mergeHandler = mergeHandler; this.mergeHandler = new WeakReference<>(mergeHandler);
} }
public IVodTsUrlConverter getVodUrlConverter() { public IVodTsUrlConverter getVodUrlConverter() {
return vodUrlConverter; return vodUrlConverter.get();
} }
public void setVodUrlConverter(IVodTsUrlConverter vodUrlConverter) { public void setVodUrlConverter(IVodTsUrlConverter vodUrlConverter) {
this.vodUrlConverter = vodUrlConverter; this.vodUrlConverter = new WeakReference<>(vodUrlConverter);
} }
public List<String> getUrls() { public List<String> getUrls() {

@ -26,7 +26,6 @@ import com.arialyy.aria.core.download.downloader.ConnectionHelp;
import com.arialyy.aria.exception.AriaIOException; import com.arialyy.aria.exception.AriaIOException;
import com.arialyy.aria.exception.TaskException; import com.arialyy.aria.exception.TaskException;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.BufferedRandomAccessFile;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
@ -40,7 +39,6 @@ import java.nio.ByteBuffer;
import java.nio.channels.Channels; import java.nio.channels.Channels;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel; import java.nio.channels.ReadableByteChannel;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -48,7 +46,7 @@ import java.util.Set;
* Created by lyy on 2017/1/18. 下载线程 * Created by lyy on 2017/1/18. 下载线程
*/ */
final class M3U8ThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> { final class M3U8ThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
private final String TAG = "HttpThreadTask"; private final String TAG = "M3U8ThreadTask";
M3U8ThreadTask(SubThreadConfig<DTaskWrapper> config) { M3U8ThreadTask(SubThreadConfig<DTaskWrapper> config) {
super(config); super(config);
@ -75,9 +73,6 @@ final class M3U8ThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
conn.setChunkedStreamingMode(0); conn.setChunkedStreamingMode(0);
} }
conn.connect(); conn.connect();
//Map<String, List<String>> header = conn.getHeaderFields();
//int code = conn.getResponseCode();
//String msg = conn.getResponseMessage();
// 传递参数 // 传递参数
if (taskDelegate.getRequestEnum() == RequestEnum.POST) { if (taskDelegate.getRequestEnum() == RequestEnum.POST) {
Map<String, String> params = taskDelegate.getParams(); Map<String, String> params = taskDelegate.getParams();
@ -125,6 +120,7 @@ final class M3U8ThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
onThreadComplete();
} }
return this; return this;
} }

@ -17,8 +17,11 @@ package com.arialyy.aria.core.download.m3u8;
import com.arialyy.aria.core.common.BaseDelegate; import com.arialyy.aria.core.common.BaseDelegate;
import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.event.EventMsgUtil;
import com.arialyy.aria.core.event.PeerIndexEvent;
import com.arialyy.aria.core.inf.AbsTarget; import com.arialyy.aria.core.inf.AbsTarget;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;
import com.arialyy.aria.core.queue.DownloadTaskQueue;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
/** /**
@ -60,4 +63,48 @@ public class M3U8VodDelegate<TARGET extends AbsTarget> extends BaseDelegate<TARG
mTaskWrapper.asM3U8().setMaxTsQueueNum(num); mTaskWrapper.asM3U8().setMaxTsQueueNum(num);
return this; return this;
} }
/**
* 启动任务时初始化索引位置
*
* 优先下载指定索引后的切片
* 如果指定的切片索引大于切片总数则此操作无效
* 如果指定的切片索引小于当前正在下载的切片索引并且指定索引和当前索引区间内有未下载的切片则优先下载该区间的切片否则此操作无效
* 如果指定索引后的切片已经全部下载完成但是索引前有未下载的切片间会自动下载未下载的切片
*
* @param index 指定的切片位置
*/
public M3U8VodDelegate setPeerIndex(int index) {
if (index < 1) {
ALog.e(TAG, "切片索引不能小于1");
return this;
}
mTaskWrapper.asM3U8().setJumpIndex(index);
return this;
}
/**
* 任务执行中跳转索引位置
* 优先下载指定索引后的切片
* 如果指定的切片索引大于切片总数则此操作无效
* 如果指定的切片索引小于当前正在下载的切片索引并且指定索引和当前索引区间内有未下载的切片则优先下载该区间的切片否则此操作无效
* 如果指定索引后的切片已经全部下载完成但是索引前有未下载的切片间会自动下载未下载的切片
*
* @param index 指定的切片位置
*/
public void jumPeerIndex(int index) {
if (index < 1) {
ALog.e(TAG, "切片索引不能小于1");
return;
}
if (!DownloadTaskQueue.getInstance().taskIsRunning(mTaskWrapper.getKey())) {
ALog.e(TAG,
String.format("任务【%s】没有运行,如果你希望在启动任务时初始化索引位置,请调用setPeerIndex(xxx)",
mTaskWrapper.getKey()));
return;
}
EventMsgUtil.getDefault().post(new PeerIndexEvent(index));
}
} }

@ -19,23 +19,31 @@ import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.util.SparseArray;
import com.arialyy.aria.core.common.AbsThreadTask; import com.arialyy.aria.core.common.AbsThreadTask;
import com.arialyy.aria.core.common.IThreadState; import com.arialyy.aria.core.common.IThreadState;
import com.arialyy.aria.core.common.SubThreadConfig; import com.arialyy.aria.core.common.SubThreadConfig;
import com.arialyy.aria.core.common.TaskRecord; import com.arialyy.aria.core.common.TaskRecord;
import com.arialyy.aria.core.common.ThreadRecord; import com.arialyy.aria.core.common.ThreadRecord;
import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.M3U8Listener;
import com.arialyy.aria.core.event.Event;
import com.arialyy.aria.core.event.EventMsgUtil;
import com.arialyy.aria.core.event.PeerIndexEvent;
import com.arialyy.aria.core.inf.IEventListener; import com.arialyy.aria.core.inf.IEventListener;
import com.arialyy.aria.core.manager.ThreadTaskManager; import com.arialyy.aria.core.manager.ThreadTaskManager;
import com.arialyy.aria.core.scheduler.ISchedulers;
import com.arialyy.aria.exception.BaseException; import com.arialyy.aria.exception.BaseException;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.FileUtil; import com.arialyy.aria.util.FileUtil;
import com.arialyy.aria.util.IdGenerator;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
@ -46,16 +54,34 @@ public class M3U8VodLoader extends BaseM3U8Loader {
/** /**
* 最大执行数 * 最大执行数
*/ */
private static final int EXEC_MAX_NUM = 4; private int EXEC_MAX_NUM;
private Handler mStateHandler; private Handler mStateHandler;
private ArrayBlockingQueue<Long> mFlagQueue; private ArrayBlockingQueue<TempFlag> mFlagQueue;
private VodStateManager mManager; private ArrayBlockingQueue<PeerIndexEvent> mJumpQueue;
private ReentrantLock LOCK = new ReentrantLock(); private ReentrantLock LOCK = new ReentrantLock();
private Condition mCondition = LOCK.newCondition(); private ReentrantLock EVENT_LOCK = new ReentrantLock();
private ReentrantLock JUMP_LOCK = new ReentrantLock();
private Condition mWaitCondition = LOCK.newCondition();
private Condition mEventQueueCondition = EVENT_LOCK.newCondition();
private Condition mJumpCondition = JUMP_LOCK.newCondition();
private SparseArray<ThreadRecord> mBeforePeer = new SparseArray<>();
private SparseArray<ThreadRecord> mAfterPeer = new SparseArray<>();
private VodStateManager mManager;
private PeerIndexEvent mCurrentEvent;
private String mCacheDir;
private int aIndex = 0, bIndex = 0;
private int mCurrentFlagSize;
private boolean isJump = false, isDestroy = false;
private int mCompleteNum = 0;
private ExecutorService mJumpThreadPool;
private Thread jumpThread = null;
M3U8VodLoader(IEventListener listener, DTaskWrapper wrapper) { M3U8VodLoader(M3U8Listener listener, DTaskWrapper wrapper) {
super(listener, wrapper); super(listener, wrapper);
mFlagQueue = new ArrayBlockingQueue<>(wrapper.asM3U8().getMaxTsQueueNum()); mFlagQueue = new ArrayBlockingQueue<>(wrapper.asM3U8().getMaxTsQueueNum());
EXEC_MAX_NUM = wrapper.asM3U8().getMaxTsQueueNum();
mJumpQueue = new ArrayBlockingQueue<>(10);
EventMsgUtil.getDefault().register(this);
} }
@Override protected IThreadState getStateManager(Looper looper) { @Override protected IThreadState getStateManager(Looper looper) {
@ -64,55 +90,299 @@ public class M3U8VodLoader extends BaseM3U8Loader {
return mManager; return mManager;
} }
@Override protected void handleTask() { @Override public void onDestroy() {
super.onDestroy();
isDestroy = true;
EventMsgUtil.getDefault().unRegister(this);
if (mJumpThreadPool != null && !mJumpThreadPool.isShutdown()) {
mJumpThreadPool.shutdown();
}
}
@Override protected void onPostPre() {
super.onPostPre();
initData();
}
@Override public boolean isBreak() {
return super.isBreak() || isDestroy;
}
new Thread(new Runnable() { @Override protected void handleTask() {
Thread th = new Thread(new Runnable() {
@Override public void run() { @Override public void run() {
int index = 0;
String cacheDir = getCacheDir();
while (!isBreak()) { while (!isBreak()) {
try {
JUMP_LOCK.lock();
if (isJump) {
mJumpCondition.await(5, TimeUnit.SECONDS);
isJump = false;
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
JUMP_LOCK.unlock();
}
try { try {
LOCK.lock(); LOCK.lock();
while (mFlagQueue.size() < EXEC_MAX_NUM) { while (mFlagQueue.size() < EXEC_MAX_NUM && !isBreak()) {
if (index == mRecord.threadRecords.size()) { if (mCompleteNum == mRecord.threadRecords.size()) {
break; break;
} }
ThreadRecord tr = mRecord.threadRecords.get(index);
index++;
if (tr.isComplete) {
continue;
}
M3U8ThreadTask task = createThreadTask(cacheDir, tr); ThreadRecord tr = getThreadRecord();
getTaskList().put(tr.threadId, task); if (tr == null || tr.isComplete) {
mEntity.getM3U8Entity().setPeerIndex(index); ALog.d(TAG, "记录为空或记录已完成");
mFlagQueue.offer(startThreadTask(task, index)); break;
}
addTaskToQueue(tr);
} }
if (mFlagQueue.size() > 0) { if (mFlagQueue.size() > 0) {
mCondition.await(); mWaitCondition.await();
} }
} catch (InterruptedException e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} finally { } finally {
LOCK.unlock(); LOCK.unlock();
} }
} }
} }
}).start(); });
th.start();
} }
@Override protected void setMaxSpeed(int maxSpeed) { /**
// TODO: 2019-06-05 暂不支持 * 获取线程记录
*/
private ThreadRecord getThreadRecord() {
ThreadRecord tr = null;
try {
// 优先下载peer指针之后的数据
if (bIndex == 0 && aIndex < mAfterPeer.size()) {
//ALog.d(TAG, String.format("afterArray size:%s, index:%s", mAfterPeer.size(), aIndex));
tr = mAfterPeer.valueAt(aIndex);
aIndex++;
}
// 如果指针之后的数组没有切片了,则重新初始化指针位置,并获取指针之前的数组获取切片进行下载
if (mBeforePeer.size() > 0 && (tr == null || bIndex != 0) && bIndex < mBeforePeer.size()) {
tr = mBeforePeer.valueAt(bIndex);
bIndex++;
}
} catch (Exception e) {
e.printStackTrace();
}
return tr;
} }
private void notifyLock() { /**
* 启动线程任务
*/
private void addTaskToQueue(ThreadRecord tr) throws InterruptedException {
M3U8ThreadTask task = createThreadTask(mCacheDir, tr, tr.threadId);
getTaskList().put(tr.threadId, task);
mEntity.getM3U8Entity().setPeerIndex(tr.threadId);
TempFlag flag = startThreadTask(task, tr.threadId);
if (flag != null) {
mFlagQueue.put(flag);
}
}
/**
* 初始化数据
*/
private void initData() {
mCacheDir = getCacheDir();
if (mTaskWrapper.asM3U8().getJumpIndex() != 0) {
mCurrentEvent = new PeerIndexEvent(mTaskWrapper.asM3U8().getJumpIndex());
resumeTask();
return;
}
// 设置需要下载的切片
mCompleteNum = 0;
for (ThreadRecord tr : mRecord.threadRecords) {
if (!tr.isComplete) {
mAfterPeer.put(tr.threadId, tr);
} else {
mCompleteNum++;
}
}
mManager.updateStateCount();
}
/**
* 每隔几秒钟检查jump队列取最新的事件处理
*/
private synchronized void startJumpThread() {
jumpThread = new Thread(new Runnable() {
@Override public void run() {
try {
PeerIndexEvent event;
while (!isBreak()) {
try {
EVENT_LOCK.lock();
PeerIndexEvent temp = null;
// 取最新的事件
while ((event = mJumpQueue.poll(1, TimeUnit.SECONDS)) != null) {
temp = event;
}
if (temp != null) {
handleJump(temp);
}
mEventQueueCondition.await();
} finally {
EVENT_LOCK.unlock();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
jumpThread.start();
}
/**
* 处理跳转
*/
private void handleJump(PeerIndexEvent event) {
if (isBreak()) {
ALog.e(TAG, "任务已停止,处理跳转失败");
return;
}
mCurrentEvent = event;
if (mRecord == null || mRecord.threadRecords == null) {
ALog.e(TAG, "跳到指定位置失败,记录为空");
return;
}
if (event.peerIndex >= mRecord.threadRecords.size()) {
ALog.e(TAG,
String.format("切片索引设置错误,切片最大索引为:%s,当前设置的索引为:%s", mRecord.threadRecords.size(),
event.peerIndex));
return;
}
ALog.i(TAG, String.format("将优先下载索引【%s】之后的切片", event.peerIndex));
isJump = true;
notifyWaitLock(false);
mCurrentFlagSize = mFlagQueue.size();
// 停止所有正在执行的线程任务
try {
TempFlag flag;
while ((flag = mFlagQueue.poll()) != null) {
flag.threadTask.stop();
}
} catch (Exception e) {
e.printStackTrace();
}
ALog.d(TAG, "完成停止队列中的切片任务");
}
/**
* 下载指定索引后面的切片
* 如果指定的切片索引大于切片总数则此操作无效
* 如果指定的切片索引小于当前正在下载的切片索引并且指定索引和当前索引区间内有未下载的切片则优先下载该区间的切片否则此操作无效
* 如果指定索引后的切片已经全部下载完成但是索引前有未下载的切片间会自动下载未下载的切片
*/
@Event
public synchronized void jumpPeer(PeerIndexEvent event) {
if (isBreak()) {
ALog.e(TAG, "任务已停止,发送跳转事件失败");
return;
}
if (jumpThread == null) {
mJumpThreadPool = Executors.newSingleThreadExecutor();
startJumpThread();
}
mJumpQueue.offer(event);
mJumpThreadPool.submit(new Runnable() {
@Override public void run() {
try {
Thread.sleep(1000);
notifyJumpQueue();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private void notifyJumpQueue() {
try {
EVENT_LOCK.lock();
mEventQueueCondition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
EVENT_LOCK.unlock();
}
}
/**
* 重指定位置恢复任务
*/
private synchronized void resumeTask() {
if (isBreak()) {
ALog.e(TAG, "任务已停止,恢复任务失败");
return;
}
if (mJumpQueue.size() > 0) {
ALog.d(TAG, "有新定位,取消上一次操作");
notifyJumpQueue();
return;
}
ALog.d(TAG, "恢复切片任务");
// 重新初始化需要下载的分片
mBeforePeer.clear();
mAfterPeer.clear();
mFlagQueue.clear();
aIndex = 0;
bIndex = 0;
mCompleteNum = 0;
for (ThreadRecord tr : mRecord.threadRecords) {
if (tr.isComplete) {
mCompleteNum++;
continue;
}
if (tr.threadId < mCurrentEvent.peerIndex) {
mBeforePeer.put(tr.threadId, tr);
} else {
mAfterPeer.put(tr.threadId, tr);
}
}
ALog.i(TAG,
String.format("beforeSize = %s, afterSize = %s, mCompleteNum = %s", mBeforePeer.size(),
mAfterPeer.size(), mCompleteNum));
ALog.i(TAG, String.format("完成处理数据的操作,将优先下载【%s】之后的切片", mCurrentEvent.peerIndex));
mManager.updateStateCount();
try {
JUMP_LOCK.lock();
mJumpCondition.signalAll();
} finally {
JUMP_LOCK.unlock();
}
}
private M3U8Listener getListener() {
return (M3U8Listener) mListener;
}
private void notifyWaitLock(boolean isComplete) {
try { try {
LOCK.lock(); LOCK.lock();
long id = mFlagQueue.take(); if (isComplete) {
ALog.d(TAG, String.format("线程【%s】完成", id)); TempFlag flag = mFlagQueue.poll(1, TimeUnit.SECONDS);
mCondition.signalAll(); if (flag != null) {
} catch (InterruptedException e) { ALog.d(TAG, String.format("切片【%s】完成", flag.threadId));
}
}
mWaitCondition.signalAll();
} catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} finally { } finally {
LOCK.unlock(); LOCK.unlock();
@ -124,15 +394,24 @@ public class M3U8VodLoader extends BaseM3U8Loader {
* *
* @return 线程唯一id标志 * @return 线程唯一id标志
*/ */
private long startThreadTask(M3U8ThreadTask task, int peerIndex) { private TempFlag startThreadTask(M3U8ThreadTask task, int peerIndex) {
if (isBreak()) {
ALog.w(TAG, "任务已停止,启动线程任务失败");
return null;
}
ThreadTaskManager.getInstance().startThread(mTaskWrapper.getKey(), task); ThreadTaskManager.getInstance().startThread(mTaskWrapper.getKey(), task);
return peerIndex; getListener().onPeerStart(mTaskWrapper.getKey(), task.getConfig().tempFile.getPath(),
peerIndex);
TempFlag flag = new TempFlag();
flag.threadTask = task;
flag.threadId = peerIndex;
return flag;
} }
/** /**
* 配置config * 配置config
*/ */
private M3U8ThreadTask createThreadTask(String cacheDir, ThreadRecord record) { private M3U8ThreadTask createThreadTask(String cacheDir, ThreadRecord record, int index) {
SubThreadConfig<DTaskWrapper> config = new SubThreadConfig<>(); SubThreadConfig<DTaskWrapper> config = new SubThreadConfig<>();
config.url = record.tsUrl; config.url = record.tsUrl;
config.tempFile = new File(getTsFilePath(cacheDir, record.threadId)); config.tempFile = new File(getTsFilePath(cacheDir, record.threadId));
@ -141,6 +420,7 @@ public class M3U8VodLoader extends BaseM3U8Loader {
config.taskWrapper = mTaskWrapper; config.taskWrapper = mTaskWrapper;
config.record = record; config.record = record;
config.stateHandler = mStateHandler; config.stateHandler = mStateHandler;
config.peerIndex = index;
if (!config.tempFile.exists()) { if (!config.tempFile.exists()) {
CommonUtil.createFile(config.tempFile.getPath()); CommonUtil.createFile(config.tempFile.getPath());
} }
@ -156,29 +436,34 @@ public class M3U8VodLoader extends BaseM3U8Loader {
/** /**
* 任务状态回调 * 任务状态回调
*/ */
private IEventListener mListener; private IEventListener listener;
private int mStartThreadNum; // 启动的线程总数 private int startThreadNum; // 启动的线程总数
private int mCancelNum = 0; // 已经取消的线程的数 private int cancelNum = 0; // 已经取消的线程的数
private int mStopNum = 0; // 已经停止的线程数 private int stopNum = 0; // 已经停止的线程数
private int mFailNum = 0; // 失败的线程数 private int failNum = 0; // 失败的线程数
private int mCompleteNum = 0; // 完成的线程数 private long progress; //当前总进度
private long mProgress; //当前总进度 private TaskRecord taskRecord; // 任务记录
private TaskRecord mTaskRecord; // 任务记录 private Looper looper;
private Looper mLooper;
/** /**
* @param taskRecord 任务记录 * @param taskRecord 任务记录
* @param listener 任务事件 * @param listener 任务事件
*/ */
VodStateManager(Looper looper, TaskRecord taskRecord, IEventListener listener) { VodStateManager(Looper looper, TaskRecord taskRecord, IEventListener listener) {
mLooper = looper; this.looper = looper;
mTaskRecord = taskRecord; this.taskRecord = taskRecord;
for (ThreadRecord record : taskRecord.threadRecords) { for (ThreadRecord record : taskRecord.threadRecords) {
if (!record.isComplete) { if (!record.isComplete) {
mStartThreadNum++; startThreadNum++;
} }
} }
mListener = listener; this.listener = listener;
}
private void updateStateCount() {
cancelNum = 0;
stopNum = 0;
failNum = 0;
} }
/** /**
@ -186,65 +471,104 @@ public class M3U8VodLoader extends BaseM3U8Loader {
*/ */
private void quitLooper() { private void quitLooper() {
ALog.d(TAG, "quitLooper"); ALog.d(TAG, "quitLooper");
mLooper.quit(); looper.quit();
} }
@Override public boolean handleMessage(Message msg) { @Override public boolean handleMessage(Message msg) {
int peerIndex = msg.getData().getInt(ISchedulers.DATA_M3U8_PEER_INDEX);
switch (msg.what) { switch (msg.what) {
case STATE_STOP: case STATE_STOP:
mStopNum++; stopNum++;
ThreadTaskManager.getInstance().removeSingleTaskThread(mTaskWrapper.getKey(), removeSignThread((AbsThreadTask) msg.obj);
(AbsThreadTask) msg.obj); // 处理跳转位置后,恢复任务
if (isStop()) { if (isJump && (stopNum == mCurrentFlagSize || mCurrentFlagSize == 0) && !isBreak()) {
resumeTask();
return true;
}
if (isBreak()) {
ALog.d(TAG, String.format("vod任务【%s】停止", mTempFile.getName())); ALog.d(TAG, String.format("vod任务【%s】停止", mTempFile.getName()));
mListener.onStop(mProgress);
quitLooper(); quitLooper();
} }
break; break;
case STATE_CANCEL: case STATE_CANCEL:
mCancelNum++; cancelNum++;
ThreadTaskManager.getInstance().removeSingleTaskThread(mTaskWrapper.getKey(), removeSignThread((AbsThreadTask) msg.obj);
(AbsThreadTask) msg.obj);
if (isCancel()) { if (isBreak()) {
ALog.d(TAG, String.format("vod任务【%s】取消", mTempFile.getName())); ALog.d(TAG, String.format("vod任务【%s】取消", mTempFile.getName()));
mListener.onCancel();
quitLooper(); quitLooper();
} }
break; break;
case STATE_FAIL: case STATE_FAIL:
mFailNum++; failNum++;
for (ThreadRecord tr : mRecord.threadRecords) {
if (tr.threadId == peerIndex) {
mBeforePeer.put(peerIndex, tr);
break;
}
}
getListener().onPeerFail(mTaskWrapper.getKey(),
msg.getData().getString(ISchedulers.DATA_M3U8_PEER_PATH), peerIndex);
if (isFail()) { if (isFail()) {
ALog.d(TAG, String.format("vod任务【%s】失败", mTempFile.getName())); ALog.d(TAG, String.format("vod任务【%s】失败", mTempFile.getName()));
Bundle b = msg.getData(); Bundle b = msg.getData();
mListener.onFail(b.getBoolean(KEY_RETRY, true), listener.onFail(b.getBoolean(KEY_RETRY, true),
(BaseException) b.getSerializable(KEY_ERROR_INFO)); (BaseException) b.getSerializable(KEY_ERROR_INFO));
quitLooper(); quitLooper();
} }
break; break;
case STATE_COMPLETE: case STATE_COMPLETE:
if (isBreak()) {
quitLooper();
}
mCompleteNum++; mCompleteNum++;
ThreadTaskManager.getInstance().removeSingleTaskThread(mTaskWrapper.getKey(), // 正在切换位置时,切片完成,队列大小减小
(AbsThreadTask) msg.obj); if (isJump) {
mCurrentFlagSize--;
if (mCurrentFlagSize < 0) {
mCurrentFlagSize = 0;
}
}
removeSignThread((AbsThreadTask) msg.obj);
getListener().onPeerComplete(mTaskWrapper.getKey(),
msg.getData().getString(ISchedulers.DATA_M3U8_PEER_PATH), peerIndex);
handlerPercent(); handlerPercent();
notifyLock(); if (!isJump) {
notifyWaitLock(true);
}
if (isComplete()) { if (isComplete()) {
ALog.d(TAG, String.format(
"startThreadNum = %s, stopNum = %s, cancelNum = %s, failNum = %s, completeNum = %s, flagQueueSize = %s",
startThreadNum, stopNum, cancelNum, failNum, mCompleteNum, mFlagQueue.size()));
ALog.d(TAG, String.format("vod任务【%s】完成", mTempFile.getName()));
if (mTaskWrapper.asM3U8().isMergeFile()) { if (mTaskWrapper.asM3U8().isMergeFile()) {
if (mergeFile()) { if (mergeFile()) {
mListener.onComplete(); listener.onComplete();
} else { } else {
mListener.onFail(false, null); listener.onFail(false, null);
} }
} else { } else {
mListener.onComplete(); listener.onComplete();
} }
quitLooper(); quitLooper();
} }
break; break;
case STATE_RUNNING: case STATE_RUNNING:
mProgress += (long) msg.obj; progress += (long) msg.obj;
break; break;
} }
return false; return true;
}
private void removeSignThread(AbsThreadTask threadTask) {
int index = getTaskList().indexOfValue(threadTask);
if (index != -1) {
getTaskList().removeAt(index);
}
ThreadTaskManager.getInstance().removeSingleTaskThread(mTaskWrapper.getKey(), threadTask);
} }
/** /**
@ -254,40 +578,29 @@ public class M3U8VodLoader extends BaseM3U8Loader {
int completeNum = mTaskWrapper.asM3U8().getCompleteNum(); int completeNum = mTaskWrapper.asM3U8().getCompleteNum();
completeNum++; completeNum++;
mTaskWrapper.asM3U8().setCompleteNum(completeNum); mTaskWrapper.asM3U8().setCompleteNum(completeNum);
int percent = completeNum * 100 / mTaskRecord.threadRecords.size(); int percent = completeNum * 100 / taskRecord.threadRecords.size();
mEntity.setPercent(percent); mEntity.setPercent(percent);
mEntity.update(); mEntity.update();
} }
@Override public boolean isStop() {
printInfo("isStop");
return mStopNum == mFlagQueue.size();
}
@Override public boolean isFail() { @Override public boolean isFail() {
printInfo("isFail"); printInfo("isFail");
return mFailNum == mFlagQueue.size(); return failNum != 0 && failNum == mFlagQueue.size() && !isJump;
} }
@Override public boolean isComplete() { @Override public boolean isComplete() {
printInfo("isComplete"); return mCompleteNum == taskRecord.threadRecords.size() && !isJump;
return mStartThreadNum == mCompleteNum;
}
@Override public boolean isCancel() {
printInfo("isCancel");
return mCancelNum == mFlagQueue.size();
} }
@Override public long getCurrentProgress() { @Override public long getCurrentProgress() {
return mProgress; return progress;
} }
private void printInfo(String tag) { private void printInfo(String tag) {
if (false) { if (false) {
ALog.d(tag, String.format( ALog.d(tag, String.format(
"startThreadNum = %s, stopNum = %s, cancelNum = %s, failNum = %s, completeNum = %s", "startThreadNum = %s, stopNum = %s, cancelNum = %s, failNum = %s, completeNum = %s, flagQueueSize = %s",
mStartThreadNum, mStopNum, mCancelNum, mFailNum, mCompleteNum)); startThreadNum, stopNum, cancelNum, failNum, mCompleteNum, mFlagQueue.size()));
} }
} }
@ -300,19 +613,19 @@ public class M3U8VodLoader extends BaseM3U8Loader {
ITsMergeHandler mergeHandler = mTaskWrapper.asM3U8().getMergeHandler(); ITsMergeHandler mergeHandler = mTaskWrapper.asM3U8().getMergeHandler();
String cacheDir = getCacheDir(); String cacheDir = getCacheDir();
List<String> partPath = new ArrayList<>(); List<String> partPath = new ArrayList<>();
for (ThreadRecord tr : mTaskRecord.threadRecords) { for (ThreadRecord tr : taskRecord.threadRecords) {
partPath.add(getTsFilePath(cacheDir, tr.threadId)); partPath.add(getTsFilePath(cacheDir, tr.threadId));
} }
boolean isSuccess; boolean isSuccess;
if (mergeHandler != null) { if (mergeHandler != null) {
isSuccess = mergeHandler.merge(mTaskWrapper.asM3U8().getKeyInfo(), partPath); isSuccess = mergeHandler.merge(mTaskWrapper.asM3U8().getKeyInfo(), partPath);
} else { } else {
isSuccess = FileUtil.mergeFile(mTaskRecord.filePath, partPath); isSuccess = FileUtil.mergeFile(taskRecord.filePath, partPath);
} }
if (isSuccess) { if (isSuccess) {
// 合并成功,删除缓存文件 // 合并成功,删除缓存文件
for (String pp : partPath) { File[] files = new File(cacheDir).listFiles();
File f = new File(pp); for (File f : files) {
if (f.exists()) { if (f.exists()) {
f.delete(); f.delete();
} }
@ -328,4 +641,9 @@ public class M3U8VodLoader extends BaseM3U8Loader {
} }
} }
} }
private static class TempFlag {
AbsThreadTask threadTask;
int threadId;
}
} }

@ -20,10 +20,11 @@ import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.core.common.IUtil; import com.arialyy.aria.core.common.IUtil;
import com.arialyy.aria.core.common.OnFileInfoCallback; import com.arialyy.aria.core.common.OnFileInfoCallback;
import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.M3U8Listener;
import com.arialyy.aria.core.inf.AbsEntity; import com.arialyy.aria.core.inf.AbsEntity;
import com.arialyy.aria.core.inf.IDownloadListener;
import com.arialyy.aria.exception.BaseException; import com.arialyy.aria.exception.BaseException;
import com.arialyy.aria.exception.M3U8Exception; import com.arialyy.aria.exception.M3U8Exception;
import com.arialyy.aria.util.ALog;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -40,12 +41,12 @@ public class M3U8VodUtil implements IUtil {
private final String TAG = "M3U8DownloadUtil"; private final String TAG = "M3U8DownloadUtil";
private DTaskWrapper mWrapper; private DTaskWrapper mWrapper;
private IDownloadListener mListener; private M3U8Listener mListener;
private boolean isStop = false, isCancel = false; private boolean isStop = false, isCancel = false;
private List<String> mUrls = new ArrayList<>(); private List<String> mUrls = new ArrayList<>();
private M3U8VodLoader mLoader; private M3U8VodLoader mLoader;
public M3U8VodUtil(DTaskWrapper wrapper, IDownloadListener listener) { public M3U8VodUtil(DTaskWrapper wrapper, M3U8Listener listener) {
mWrapper = wrapper; mWrapper = wrapper;
mListener = listener; mListener = listener;
mLoader = new M3U8VodLoader(mListener, mWrapper); mLoader = new M3U8VodLoader(mListener, mWrapper);
@ -85,10 +86,6 @@ public class M3U8VodUtil implements IUtil {
getVodInfo(); getVodInfo();
} }
@Override public void setMaxSpeed(int speed) {
mLoader.setMaxSpeed(speed);
}
/** /**
* 获取点播文件信息 * 获取点播文件信息
*/ */
@ -114,7 +111,13 @@ public class M3U8VodUtil implements IUtil {
return; return;
} }
mWrapper.asM3U8().setUrls(mUrls); mWrapper.asM3U8().setUrls(mUrls);
mLoader.start(); if (isStop) {
mListener.onStop(mWrapper.getEntity().getCurrentProgress());
} else if (isCancel) {
mListener.onCancel();
} else {
mLoader.start();
}
} }
@Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) { @Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) {
@ -129,5 +132,6 @@ public class M3U8VodUtil implements IUtil {
return; return;
} }
mListener.onFail(needRetry, e); mListener.onFail(needRetry, e);
mLoader.onDestroy();
} }
} }

@ -0,0 +1,30 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.event;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 注解需要接收消息的方法方法中只能有一个参数
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Event {
//Class value();
}

@ -13,17 +13,20 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.scheduler; package com.arialyy.aria.core.event;
import com.arialyy.aria.core.inf.ITask;
/** /**
* Created by lyy on 2017/4/5. * 事件消息信息
*/ */
public interface IDownloadSchedulerListener<TASK extends ITask> extends ISchedulerListener<TASK> { class EventMethodInfo {
/**
* {@link Event}注解的事件方法
*/
String methodName;
/** /**
* 支持断点的回调 * 该方法对应的参数类型
*/ */
public void onNoSupportBreakPoint(TASK task); Class<?> param;
} }

@ -0,0 +1,153 @@
/*
* 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.event;
import com.arialyy.aria.util.ALog;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* 消息发送工具
*/
public class EventMsgUtil {
private static final String TAG = "EventUtil";
private static EventMsgUtil defaultInstance;
private Map<Object, List<EventMethodInfo>> mEventMethods =
new ConcurrentHashMap<>();
private ArrayBlockingQueue<Object> mEventQueue = new ArrayBlockingQueue<>(10);
private ExecutorService mPool = Executors.newFixedThreadPool(10);
private EventMsgUtil() {
ExecutorService pool = Executors.newSingleThreadExecutor();
pool.execute(new Runnable() {
@Override public void run() {
while (true) {
try {
Object info = mEventQueue.take();
sendEvent(info);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
}
private void sendEvent(final Object param) {
mPool.submit(new Runnable() {
@Override public void run() {
Set<Object> keys = mEventMethods.keySet();
for (Object key : keys) {
List<EventMethodInfo> list = mEventMethods.get(key);
if (list != null && !list.isEmpty()) {
for (EventMethodInfo info : list) {
try {
if (info.param == param.getClass()) {
Method method = key.getClass().getDeclaredMethod(info.methodName, info.param);
method.setAccessible(true);
method.invoke(key, param);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
});
}
public static EventMsgUtil getDefault() {
if (defaultInstance == null) {
synchronized (EventMsgUtil.class) {
if (defaultInstance == null) {
defaultInstance = new EventMsgUtil();
}
}
}
return defaultInstance;
}
/**
* 注册事件
*/
public void register(Object obj) {
Method[] methods = obj.getClass().getDeclaredMethods();
for (Method method : methods) {
method.setAccessible(true);
if (method.getAnnotation(Event.class) == null) {
continue;
}
Class<?>[] clazz = method.getParameterTypes();
if (clazz.length == 0 || clazz.length > 1) {
ALog.e(TAG,
String.format("%s.%s参数数量为0或参数数量大于1", obj.getClass().getName(), method.getName()));
continue;
}
int modifier = method.getModifiers();
if (Modifier.isStatic(modifier) || Modifier.isAbstract(modifier) || Modifier.isFinal(
modifier)) {
ALog.e(TAG, "注册的方法不能使用final、static、abstract修饰");
continue;
}
EventMethodInfo methodInfo = new EventMethodInfo();
methodInfo.methodName = method.getName();
methodInfo.param = clazz[0];
List<EventMethodInfo> list = mEventMethods.get(obj);
if (list == null) {
list = new ArrayList<>();
mEventMethods.put(obj, list);
}
list.add(methodInfo);
}
}
public void unRegister(Object obj) {
for (Iterator<Map.Entry<Object, List<EventMethodInfo>>> iter =
mEventMethods.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry<Object, List<EventMethodInfo>> entry = iter.next();
if (entry.getKey().equals(obj)) {
entry.getValue().clear();
iter.remove();
}
}
}
/**
* 发送事件接收消息的方法需要使用{@link Event}注解
*/
public void post(Object param) {
synchronized (EventMsgUtil.class) {
try {
mEventQueue.offer(param, 2, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

@ -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.event;
public class PeerIndexEvent {
public int peerIndex;
public long createTime;
public PeerIndexEvent(int peerIndex) {
this.peerIndex = peerIndex;
createTime = System.currentTimeMillis();
}
}

@ -0,0 +1,25 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.event;
public class SpeedEvent {
public int speed;
public SpeedEvent(int speed) {
this.speed = speed;
}
}

@ -19,14 +19,13 @@ import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.support.annotation.CheckResult; import android.support.annotation.CheckResult;
import android.text.TextUtils; import android.text.TextUtils;
import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.command.CancelCmd;
import com.arialyy.aria.core.command.ICmd; import com.arialyy.aria.core.command.ICmd;
import com.arialyy.aria.core.command.normal.CancelCmd; import com.arialyy.aria.core.command.NormalCmdFactory;
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
import com.arialyy.aria.core.command.normal.ReStartCmd;
import com.arialyy.aria.core.download.DGTaskWrapper; import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.event.EventMsgUtil;
import com.arialyy.aria.core.manager.TaskWrapperManager; import com.arialyy.aria.core.manager.TaskWrapperManager;
import com.arialyy.aria.core.scheduler.DownloadGroupSchedulers; import com.arialyy.aria.core.scheduler.DownloadGroupSchedulers;
import com.arialyy.aria.core.scheduler.DownloadSchedulers; import com.arialyy.aria.core.scheduler.DownloadSchedulers;
@ -36,8 +35,6 @@ import com.arialyy.aria.core.upload.UTaskWrapper;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.RecordUtil; import com.arialyy.aria.util.RecordUtil;
import java.util.ArrayList;
import java.util.List;
/** /**
* Created by AriaL on 2017/7/3. * Created by AriaL on 2017/7/3.
@ -81,7 +78,8 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
if (mEntity instanceof AbsNormalEntity) { if (mEntity instanceof AbsNormalEntity) {
RecordUtil.delTaskRecord((AbsNormalEntity) mEntity, mTaskWrapper.isRemoveFile()); RecordUtil.delTaskRecord((AbsNormalEntity) mEntity, mTaskWrapper.isRemoveFile());
} else if (mEntity instanceof DownloadGroupEntity) { } else if (mEntity instanceof DownloadGroupEntity) {
RecordUtil.delGroupTaskRecord(((DownloadGroupEntity) mEntity), mTaskWrapper.isRemoveFile(), true); RecordUtil.delGroupTaskRecord(((DownloadGroupEntity) mEntity), mTaskWrapper.isRemoveFile(),
true);
} }
TaskWrapperManager.getInstance().removeTaskWrapper(mEntity.getKey()); TaskWrapperManager.getInstance().removeTaskWrapper(mEntity.getKey());
} }
@ -272,10 +270,9 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
*/ */
@Override public void add() { @Override public void add() {
if (checkConfig()) { if (checkConfig()) {
AriaManager.getInstance(AriaManager.APP) EventMsgUtil.getDefault()
.setCmd(CommonUtil.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_CREATE, .post(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_CREATE,
checkTaskType())) checkTaskType()));
.exe();
} }
} }
@ -284,11 +281,9 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
*/ */
@Override public void start() { @Override public void start() {
if (checkConfig()) { if (checkConfig()) {
AriaManager.getInstance(AriaManager.APP) EventMsgUtil.getDefault()
.setCmd( .post(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START,
CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START, checkTaskType()));
checkTaskType()))
.exe();
} }
} }
@ -298,17 +293,14 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
* @see #stop() * @see #stop()
*/ */
@Deprecated public void pause() { @Deprecated public void pause() {
if (checkConfig()) { stop();
stop();
}
} }
@Override public void stop() { @Override public void stop() {
if (checkConfig()) { if (checkConfig()) {
AriaManager.getInstance(AriaManager.APP) EventMsgUtil.getDefault()
.setCmd( .post(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_STOP,
CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_STOP, checkTaskType())) checkTaskType()));
.exe();
} }
} }
@ -317,11 +309,9 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
*/ */
@Override public void resume() { @Override public void resume() {
if (checkConfig()) { if (checkConfig()) {
AriaManager.getInstance(AriaManager.APP) EventMsgUtil.getDefault()
.setCmd( .post(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START,
CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START, checkTaskType()));
checkTaskType()))
.exe();
} }
} }
@ -330,10 +320,9 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
*/ */
@Override public void cancel() { @Override public void cancel() {
if (checkConfig()) { if (checkConfig()) {
AriaManager.getInstance(AriaManager.APP) EventMsgUtil.getDefault()
.setCmd(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_CANCEL, .post(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_CANCEL,
checkTaskType())) checkTaskType()));
.exe();
} }
} }
@ -342,12 +331,11 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
*/ */
@Override public void reTry() { @Override public void reTry() {
if (checkConfig()) { if (checkConfig()) {
List<ICmd> cmds = new ArrayList<>();
int taskType = checkTaskType(); int taskType = checkTaskType();
cmds.add( EventMsgUtil.getDefault()
CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_STOP, taskType)); .post(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_STOP, taskType));
cmds.add(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START, taskType)); EventMsgUtil.getDefault()
AriaManager.getInstance(AriaManager.APP).setCmds(cmds).exe(); .post(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START, taskType));
} }
} }
@ -363,7 +351,7 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
(CancelCmd) CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_CANCEL, (CancelCmd) CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_CANCEL,
checkTaskType()); checkTaskType());
cancelCmd.removeFile = removeFile; cancelCmd.removeFile = removeFile;
AriaManager.getInstance(AriaManager.APP).setCmd(cancelCmd).exe(); EventMsgUtil.getDefault().post(cancelCmd);
} }
} }
@ -372,10 +360,9 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
*/ */
@Override public void reStart() { @Override public void reStart() {
if (checkConfig()) { if (checkConfig()) {
ReStartCmd cmd = EventMsgUtil.getDefault()
(ReStartCmd) CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_RESTART, .post(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_RESTART,
checkTaskType()); checkTaskType()));
AriaManager.getInstance(AriaManager.APP).setCmd(cmd).exe();
} }
} }

@ -100,17 +100,6 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
return mExpand.get(key); return mExpand.get(key);
} }
/**
* 设置最大下载/上传速度
*
* @param speed 单位为kb
*/
public void setMaxSpeed(int speed) {
if (getUtil() != null) {
getUtil().setMaxSpeed(speed);
}
}
/** /**
* 任务是否完成 * 任务是否完成
* *
@ -215,12 +204,7 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
@Override public void stop(@TaskSchedulerType int type) { @Override public void stop(@TaskSchedulerType int type) {
isStop = true; isStop = true;
mSchedulerType = type; mSchedulerType = type;
if (getUtil().isRunning()) { getUtil().stop();
getUtil().stop();
} else {
ALog.d(TAG, "下载任务未执行");
mListener.onStop(mTaskWrapper.getEntity().getCurrentProgress());
}
} }
@Override public void cancel() { @Override public void cancel() {
@ -230,11 +214,7 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
@Override public void cancel(@TaskSchedulerType int type) { @Override public void cancel(@TaskSchedulerType int type) {
isCancel = true; isCancel = true;
mSchedulerType = type; mSchedulerType = type;
if (!getUtil().isRunning()) { getUtil().cancel();
mListener.onCancel();
} else {
getUtil().cancel();
}
} }
/** /**

@ -23,7 +23,7 @@ import java.util.Map;
/** /**
* Http文件长度适配器 * Http文件长度适配器
*/ */
public class IHttpFileLenAdapter implements Serializable { public interface IHttpFileLenAdapter extends Serializable {
long serialVersionUID = 1L; long serialVersionUID = 1L;
/** /**
@ -32,7 +32,5 @@ public class IHttpFileLenAdapter implements Serializable {
* @param headers header参数{@link URLConnection#getHeaderFields()} * @param headers header参数{@link URLConnection#getHeaderFields()}
* @return 文件长度 * @return 文件长度
*/ */
public long handleFileLen(Map<String, List<String>> headers) { long handleFileLen(Map<String, List<String>> headers);
return 0;
}
} }

@ -41,10 +41,14 @@ public interface ITask<TASK_WRAPPER extends AbsTaskWrapper> {
* 组合任务的子任务 * 组合任务的子任务
*/ */
int DOWNLOAD_GROUP_SUB = 4; int DOWNLOAD_GROUP_SUB = 4;
/**
* 切片任务
*/
int M3U8_PEER = 5;
/** /**
* 填充的 * 填充的
*/ */
int TEMP = 5; int TEMP = 6;
/** /**
* 未知 * 未知
*/ */

@ -70,9 +70,9 @@ class DTaskWrapperFactory implements INormalTEFactory<DownloadEntity, DTaskWrapp
entity.setUrl(downloadUrl); entity.setUrl(downloadUrl);
entity.setGroupChild(false); entity.setGroupChild(false);
entity.setGroupHash(null); entity.setGroupHash(null);
entity.setDownloadPath(UUID.randomUUID().toString().replace("-", "")); //设置临时路径 entity.setFilePath(UUID.randomUUID().toString().replace("-", "")); //设置临时路径
} }
File file = new File(entity.getDownloadPath()); File file = new File(entity.getFilePath());
if (!entity.isComplete()) { if (!entity.isComplete()) {
TaskRecord record = TaskRecord record =
@ -91,7 +91,7 @@ class DTaskWrapperFactory implements INormalTEFactory<DownloadEntity, DTaskWrapp
if (count == record.threadNum) { if (count == record.threadNum) {
resetEntity(entity); resetEntity(entity);
} }
} else if (!file.exists()) { // 非分块文件需要判断文件是否存在 } else if (!file.exists() && record.taskType != TaskRecord.TYPE_M3U8_VOD) { // 非分块文件需要判断文件是否存在
resetEntity(entity); resetEntity(entity);
} }
} }

@ -16,9 +16,9 @@
package com.arialyy.aria.core.manager; package com.arialyy.aria.core.manager;
import android.text.TextUtils; import android.text.TextUtils;
import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.command.GroupCmdFactory;
import com.arialyy.aria.core.command.group.GroupCmdFactory;
import com.arialyy.aria.core.download.DGTaskWrapper; import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.event.EventMsgUtil;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import java.util.List; import java.util.List;
@ -44,10 +44,9 @@ public class SubTaskManager {
*/ */
public void startSubTask(String url) { public void startSubTask(String url) {
if (checkUrl(url)) { if (checkUrl(url)) {
AriaManager.getInstance(AriaManager.APP) EventMsgUtil.getDefault()
.setCmd( .post(
CommonUtil.createGroupCmd(mTargetName, mEntity, GroupCmdFactory.SUB_TASK_START, url)) CommonUtil.createGroupCmd(mTargetName, mEntity, GroupCmdFactory.SUB_TASK_START, url));
.exe();
} }
} }
@ -58,10 +57,9 @@ public class SubTaskManager {
*/ */
public void stopSubTask(String url) { public void stopSubTask(String url) {
if (checkUrl(url)) { if (checkUrl(url)) {
AriaManager.getInstance(AriaManager.APP) EventMsgUtil.getDefault()
.setCmd( .post(
CommonUtil.createGroupCmd(mTargetName, mEntity, GroupCmdFactory.SUB_TASK_STOP, url)) CommonUtil.createGroupCmd(mTargetName, mEntity, GroupCmdFactory.SUB_TASK_STOP, url));
.exe();
} }
} }

@ -21,7 +21,6 @@ import com.arialyy.aria.core.inf.AbsTask;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -112,7 +111,7 @@ public class ThreadTaskManager {
if (container.future.isDone() || container.future.isCancelled()) { if (container.future.isDone() || container.future.isCancelled()) {
continue; continue;
} }
container.threadTask.setInterrupted(true); container.threadTask.destroy();
} }
temp.clear(); temp.clear();
} }
@ -130,16 +129,16 @@ public class ThreadTaskManager {
* @param key 任务的key * @param key 任务的key
* @param task 线程任务 * @param task 线程任务
*/ */
public void removeSingleTaskThread(String key, AbsThreadTask task) { public boolean removeSingleTaskThread(String key, AbsThreadTask task) {
try { try {
LOCK.tryLock(2, TimeUnit.SECONDS); LOCK.tryLock(2, TimeUnit.SECONDS);
if (mExePool.isShutdown()) { if (mExePool.isShutdown()) {
ALog.e(TAG, "线程池已经关闭"); ALog.e(TAG, "线程池已经关闭");
return; return false;
} }
if (task == null) { if (task == null) {
ALog.e(TAG, "线程任务为空"); ALog.e(TAG, "线程任务为空");
return; return false;
} }
key = getKey(key); key = getKey(key);
Set<FutureContainer> temp = mThreadTasks.get(key); Set<FutureContainer> temp = mThreadTasks.get(key);
@ -152,8 +151,9 @@ public class ThreadTaskManager {
} }
} }
if (tempC != null) { if (tempC != null) {
task.setInterrupted(true); task.destroy();
temp.remove(tempC); temp.remove(tempC);
return true;
} }
} }
} catch (Exception e) { } catch (Exception e) {
@ -161,6 +161,7 @@ public class ThreadTaskManager {
} finally { } finally {
LOCK.unlock(); LOCK.unlock();
} }
return false;
} }
/** /**
@ -176,7 +177,7 @@ public class ThreadTaskManager {
return; return;
} }
try { try {
if (task == null || task.isInterrupted()) { if (task == null || task.isDestroy()) {
ALog.e(TAG, "线程为空或线程已经中断"); ALog.e(TAG, "线程为空或线程已经中断");
return; return;
} }

@ -23,14 +23,13 @@ import com.arialyy.aria.core.inf.AbsTaskWrapper;
import com.arialyy.aria.core.inf.IEntity; import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.TaskSchedulerType; import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.manager.TaskWrapperManager; 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.BaseCachePool;
import com.arialyy.aria.core.queue.pool.BaseExecutePool; import com.arialyy.aria.core.queue.pool.BaseExecutePool;
import com.arialyy.aria.core.queue.pool.DownloadSharePool; import com.arialyy.aria.core.queue.pool.DownloadSharePool;
import com.arialyy.aria.core.queue.pool.UploadSharePool; import com.arialyy.aria.core.queue.pool.UploadSharePool;
import com.arialyy.aria.core.upload.UploadTask; import com.arialyy.aria.core.upload.UploadTask;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import java.util.Map;
import java.util.Set;
/** /**
* Created by lyy on 2017/2/23. 任务队列 * Created by lyy on 2017/2/23. 任务队列
@ -62,7 +61,11 @@ public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends Ab
abstract int getQueueType(); abstract int getQueueType();
@Override public boolean taskIsRunning(String key) { @Override public boolean taskIsRunning(String key) {
return mExecutePool.getTask(key) != null; TASK task = mExecutePool.getTask(key);
if (task == null && ThreadTaskManager.getInstance().taskIsRunning(key)) {
ThreadTaskManager.getInstance().removeTaskThread(key);
}
return task != null && task.isRunning() && taskExists(key);
} }
/** /**
@ -71,7 +74,7 @@ public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends Ab
* @param task 需要恢复的任务 * @param task 需要恢复的任务
*/ */
@Override public void resumeTask(TASK task) { @Override public void resumeTask(TASK task) {
if (task == null){ if (task == null) {
ALog.w(TAG, "resume task fail, task is null"); ALog.w(TAG, "resume task fail, task is null");
return; return;
} }
@ -109,18 +112,6 @@ public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends Ab
mCachePool.clear(); mCachePool.clear();
} }
/**
* 最大下载速度
*/
public void setMaxSpeed(int maxSpeed) {
Map<String, TASK> tasks = mExecutePool.getAllTask();
Set<String> keys = tasks.keySet();
for (String key : keys) {
TASK task = tasks.get(key);
task.setMaxSpeed(maxSpeed);
}
}
/** /**
* 获取配置文件旧的最大任务数 * 获取配置文件旧的最大任务数
*/ */
@ -208,7 +199,7 @@ public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends Ab
* @param task {@link DownloadTask}{@link UploadTask}{@link DownloadGroupTask} * @param task {@link DownloadTask}{@link UploadTask}{@link DownloadGroupTask}
*/ */
void addTask(TASK task) { void addTask(TASK task) {
if (task == null){ if (task == null) {
ALog.w(TAG, "add task fail, task is null"); ALog.w(TAG, "add task fail, task is null");
return; return;
} }
@ -218,7 +209,7 @@ public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends Ab
} }
@Override public void startTask(TASK task) { @Override public void startTask(TASK task) {
if (task == null){ if (task == null) {
ALog.w(TAG, "start fail, task is null"); ALog.w(TAG, "start fail, task is null");
} }
if (mExecutePool.taskExits(task.getKey())) { if (mExecutePool.taskExits(task.getKey())) {
@ -253,6 +244,12 @@ public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends Ab
case IEntity.STATE_OTHER: case IEntity.STATE_OTHER:
case IEntity.STATE_FAIL: case IEntity.STATE_FAIL:
ALog.w(TAG, String.format("停止任务【%s】失败,原因:已停止", task.getTaskName())); ALog.w(TAG, String.format("停止任务【%s】失败,原因:已停止", task.getTaskName()));
if (taskIsRunning(task.getKey())) {
removeTaskFormQueue(task.getKey());
if (ThreadTaskManager.getInstance().taskIsRunning(task.getKey())) {
ThreadTaskManager.getInstance().removeTaskThread(task.getKey());
}
}
break; break;
case IEntity.STATE_CANCEL: case IEntity.STATE_CANCEL:
ALog.w(TAG, String.format("停止任务【%s】失败,原因:任务已删除", task.getTaskName())); ALog.w(TAG, String.format("停止任务【%s】失败,原因:任务已删除", task.getTaskName()));

@ -33,7 +33,7 @@ public class DownloadGroupTaskQueue
public static DownloadGroupTaskQueue getInstance() { public static DownloadGroupTaskQueue getInstance() {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (AriaManager.LOCK) { synchronized (DownloadGroupTaskQueue.class) {
INSTANCE = new DownloadGroupTaskQueue(); INSTANCE = new DownloadGroupTaskQueue();
} }
} }

@ -36,7 +36,7 @@ public class DownloadTaskQueue extends AbsTaskQueue<DownloadTask, DTaskWrapper>
public static DownloadTaskQueue getInstance() { public static DownloadTaskQueue getInstance() {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (AriaManager.LOCK) { synchronized (DownloadTaskQueue.class) {
INSTANCE = new DownloadTaskQueue(); INSTANCE = new DownloadTaskQueue();
} }
} }

@ -16,7 +16,6 @@
package com.arialyy.aria.core.queue; package com.arialyy.aria.core.queue;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.download.DGTaskWrapper; import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadGroupTask; import com.arialyy.aria.core.download.DownloadGroupTask;
@ -43,7 +42,7 @@ class TaskFactory {
public static TaskFactory getInstance() { public static TaskFactory getInstance() {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (AriaManager.LOCK) { synchronized (TaskFactory.class) {
INSTANCE = new TaskFactory(); INSTANCE = new TaskFactory();
} }
} }

@ -31,7 +31,7 @@ public class UploadTaskQueue extends AbsTaskQueue<UploadTask, UTaskWrapper> {
public static UploadTaskQueue getInstance() { public static UploadTaskQueue getInstance() {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (AriaManager.LOCK) { synchronized (UploadTaskQueue.class) {
INSTANCE = new UploadTaskQueue(); INSTANCE = new UploadTaskQueue();
} }
} }

@ -17,7 +17,6 @@
package com.arialyy.aria.core.queue.pool; package com.arialyy.aria.core.queue.pool;
import android.text.TextUtils; import android.text.TextUtils;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.inf.AbsTask; import com.arialyy.aria.core.inf.AbsTask;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
@ -35,6 +34,7 @@ public class BaseCachePool<TASK extends AbsTask> implements IPool<TASK> {
private static final String TAG = "BaseCachePool"; private static final String TAG = "BaseCachePool";
private static final int MAX_NUM = Integer.MAX_VALUE; //最大下载任务数 private static final int MAX_NUM = Integer.MAX_VALUE; //最大下载任务数
private static final long TIME_OUT = 1000; private static final long TIME_OUT = 1000;
private static final Object LOCK = new Object();
private Map<String, TASK> mCacheMap; private Map<String, TASK> mCacheMap;
private LinkedBlockingQueue<TASK> mCacheQueue; private LinkedBlockingQueue<TASK> mCacheQueue;
@ -82,7 +82,7 @@ public class BaseCachePool<TASK extends AbsTask> implements IPool<TASK> {
} }
@Override public boolean putTask(TASK task) { @Override public boolean putTask(TASK task) {
synchronized (AriaManager.LOCK) { synchronized (LOCK) {
if (task == null) { if (task == null) {
ALog.e(TAG, "任务不能为空!!"); ALog.e(TAG, "任务不能为空!!");
return false; return false;
@ -103,7 +103,7 @@ public class BaseCachePool<TASK extends AbsTask> implements IPool<TASK> {
} }
@Override public TASK pollTask() { @Override public TASK pollTask() {
synchronized (AriaManager.LOCK) { synchronized (LOCK) {
try { try {
TASK task; TASK task;
task = mCacheQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS); task = mCacheQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS);
@ -120,7 +120,7 @@ public class BaseCachePool<TASK extends AbsTask> implements IPool<TASK> {
} }
@Override public TASK getTask(String key) { @Override public TASK getTask(String key) {
synchronized (AriaManager.LOCK) { synchronized (LOCK) {
if (TextUtils.isEmpty(key)) { if (TextUtils.isEmpty(key)) {
ALog.e(TAG, "key 为null"); ALog.e(TAG, "key 为null");
return null; return null;
@ -134,7 +134,7 @@ public class BaseCachePool<TASK extends AbsTask> implements IPool<TASK> {
} }
@Override public boolean removeTask(TASK task) { @Override public boolean removeTask(TASK task) {
synchronized (AriaManager.LOCK) { synchronized (LOCK) {
if (task == null) { if (task == null) {
ALog.e(TAG, "任务不能为空"); ALog.e(TAG, "任务不能为空");
return false; return false;
@ -147,7 +147,7 @@ public class BaseCachePool<TASK extends AbsTask> implements IPool<TASK> {
} }
@Override public boolean removeTask(String key) { @Override public boolean removeTask(String key) {
synchronized (AriaManager.LOCK) { synchronized (LOCK) {
if (TextUtils.isEmpty(key)) { if (TextUtils.isEmpty(key)) {
ALog.e(TAG, "请传入有效的下载链接"); ALog.e(TAG, "请传入有效的下载链接");
return false; return false;

@ -31,6 +31,7 @@ import java.util.concurrent.TimeUnit;
*/ */
public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> { public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
private final String TAG = "BaseExecutePool"; private final String TAG = "BaseExecutePool";
private static final Object LOCK = new Object();
final long TIME_OUT = 1000; final long TIME_OUT = 1000;
ArrayBlockingQueue<TASK> mExecuteQueue; ArrayBlockingQueue<TASK> mExecuteQueue;
Map<String, TASK> mExecuteMap; Map<String, TASK> mExecuteMap;
@ -59,7 +60,7 @@ public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
} }
@Override public boolean putTask(TASK task) { @Override public boolean putTask(TASK task) {
synchronized (AriaManager.LOCK) { synchronized (LOCK) {
if (task == null) { if (task == null) {
ALog.e(TAG, "任务不能为空!!"); ALog.e(TAG, "任务不能为空!!");
return false; return false;
@ -86,7 +87,7 @@ public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
* @param maxNum 下载数 * @param maxNum 下载数
*/ */
public void setMaxNum(int maxNum) { public void setMaxNum(int maxNum) {
synchronized (AriaManager.LOCK) { synchronized (LOCK) {
try { try {
ArrayBlockingQueue<TASK> temp = new ArrayBlockingQueue<>(maxNum); ArrayBlockingQueue<TASK> temp = new ArrayBlockingQueue<>(maxNum);
TASK task; TASK task;
@ -107,7 +108,7 @@ public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
* @param newTask 新任务 * @param newTask 新任务
*/ */
boolean putNewTask(TASK newTask) { boolean putNewTask(TASK newTask) {
synchronized (AriaManager.LOCK) { synchronized (LOCK) {
String url = newTask.getKey(); String url = newTask.getKey();
boolean s = mExecuteQueue.offer(newTask); boolean s = mExecuteQueue.offer(newTask);
ALog.d(TAG, "任务【" + newTask.getTaskName() + "】进入执行队列" + (s ? "成功" : "失败")); ALog.d(TAG, "任务【" + newTask.getTaskName() + "】进入执行队列" + (s ? "成功" : "失败"));
@ -122,7 +123,7 @@ public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
* 队列满时将移除下载队列中的第一个任务 * 队列满时将移除下载队列中的第一个任务
*/ */
boolean pollFirstTask() { boolean pollFirstTask() {
synchronized (AriaManager.LOCK) { synchronized (LOCK) {
try { try {
TASK oldTask = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS); TASK oldTask = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS);
if (oldTask == null) { if (oldTask == null) {
@ -141,7 +142,7 @@ public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
} }
@Override public TASK pollTask() { @Override public TASK pollTask() {
synchronized (AriaManager.LOCK) { synchronized (LOCK) {
try { try {
TASK task; TASK task;
task = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS); task = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS);
@ -158,7 +159,7 @@ public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
} }
@Override public TASK getTask(String key) { @Override public TASK getTask(String key) {
synchronized (AriaManager.LOCK) { synchronized (LOCK) {
if (TextUtils.isEmpty(key)) { if (TextUtils.isEmpty(key)) {
ALog.e(TAG, "key 为null"); ALog.e(TAG, "key 为null");
return null; return null;
@ -172,7 +173,7 @@ public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
} }
@Override public boolean removeTask(TASK task) { @Override public boolean removeTask(TASK task) {
synchronized (AriaManager.LOCK) { synchronized (LOCK) {
if (task == null) { if (task == null) {
ALog.e(TAG, "任务不能为空"); ALog.e(TAG, "任务不能为空");
return false; return false;
@ -183,7 +184,7 @@ public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
} }
@Override public boolean removeTask(String key) { @Override public boolean removeTask(String key) {
synchronized (AriaManager.LOCK) { synchronized (LOCK) {
if (TextUtils.isEmpty(key)) { if (TextUtils.isEmpty(key)) {
ALog.e(TAG, "key 为null"); ALog.e(TAG, "key 为null");
return false; return false;

@ -34,7 +34,7 @@ class DownloadExecutePool<TASK extends AbsTask> extends BaseExecutePool<TASK> {
} }
@Override public boolean putTask(TASK task) { @Override public boolean putTask(TASK task) {
synchronized (AriaManager.LOCK) { synchronized (DownloadExecutePool.class) {
if (task == null) { if (task == null) {
ALog.e(TAG, "任务不能为空!!"); ALog.e(TAG, "任务不能为空!!");
return false; return false;

@ -15,8 +15,6 @@
*/ */
package com.arialyy.aria.core.queue.pool; package com.arialyy.aria.core.queue.pool;
import com.arialyy.aria.core.AriaManager;
/** /**
* Created by Aria.Lao on 2017/7/17. * Created by Aria.Lao on 2017/7/17.
* 下载任务池该池子为简单任务和任务组共用 * 下载任务池该池子为简单任务和任务组共用
@ -34,7 +32,7 @@ public class DownloadSharePool {
public static DownloadSharePool getInstance() { public static DownloadSharePool getInstance() {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (AriaManager.LOCK) { synchronized (DownloadSharePool.class) {
INSTANCE = new DownloadSharePool(); INSTANCE = new DownloadSharePool();
} }
} }

@ -15,8 +15,6 @@
*/ */
package com.arialyy.aria.core.queue.pool; package com.arialyy.aria.core.queue.pool;
import com.arialyy.aria.core.AriaManager;
/** /**
* Created by Aria.Lao on 2017/7/17. * Created by Aria.Lao on 2017/7/17.
* 下载任务池该池子为简单任务和任务组共用 * 下载任务池该池子为简单任务和任务组共用
@ -34,7 +32,7 @@ public class UploadSharePool {
public static UploadSharePool getInstance() { public static UploadSharePool getInstance() {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (AriaManager.LOCK) { synchronized (UploadSharePool.class) {
INSTANCE = new UploadSharePool(); INSTANCE = new UploadSharePool();
} }
} }

@ -17,8 +17,8 @@ package com.arialyy.aria.core.scheduler;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Message; import android.os.Message;
import com.arialyy.annotations.TaskEnum;
import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.download.DownloadGroupTask; import com.arialyy.aria.core.download.DownloadGroupTask;
import com.arialyy.aria.core.download.DownloadTask; import com.arialyy.aria.core.download.DownloadTask;
@ -51,14 +51,7 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends IT
protected QUEUE mQueue; protected QUEUE mQueue;
private Map<String, AbsSchedulerListener<TASK, AbsNormalEntity>> mObservers = private Map<String, Map<TaskEnum, ISchedulerListener>> mObservers = new ConcurrentHashMap<>();
new ConcurrentHashMap<>();
/**
* 设置代理类后缀名
*/
abstract String getProxySuffix();
private AriaManager manager; private AriaManager manager;
AbsSchedulers() { AbsSchedulers() {
@ -69,21 +62,39 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends IT
* 将当前类注册到Aria * 将当前类注册到Aria
* *
* @param obj 观察者类 * @param obj 观察者类
* @param taskEnum 任务类型 {@link TaskEnum}
*/ */
public void register(Object obj) { public void register(Object obj, TaskEnum taskEnum) {
String targetName = obj.getClass().getName(); String targetName = obj.getClass().getName();
AbsSchedulerListener<TASK, AbsNormalEntity> listener = mObservers.get(getKey(obj)); Map<TaskEnum, ISchedulerListener> listeners = mObservers.get(getKey(obj));
if (listener == null) {
listener = createListener(targetName); if (listeners == null) {
listeners = new ConcurrentHashMap<>();
mObservers.put(getKey(obj), listeners);
}
String proxyClassName = targetName + taskEnum.proxySuffix;
if (!hasProxyListener(listeners, taskEnum)) {
ISchedulerListener listener = createListener(proxyClassName);
if (listener != null) { if (listener != null) {
listener.setListener(obj); listener.setListener(obj);
mObservers.put(getKey(obj), listener); listeners.put(taskEnum, listener);
} else { } else {
ALog.e(TAG, "注册错误,没有【" + targetName + "】观察者"); ALog.e(TAG, "注册错误,没有【" + proxyClassName + "】观察者");
} }
} }
} }
/**
* 检查当前类是否已经注册了对应的代理
*
* @param taskEnum 代理类类型
* @return true已注册代理类false没有注册代理类
*/
private boolean hasProxyListener(Map<TaskEnum, ISchedulerListener> listeners, TaskEnum taskEnum) {
return !listeners.isEmpty() && listeners.get(taskEnum) != null;
}
/** /**
* 移除注册 * 移除注册
* *
@ -93,9 +104,10 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends IT
if (!mObservers.containsKey(getKey(obj))) { if (!mObservers.containsKey(getKey(obj))) {
return; return;
} }
for (Iterator<Map.Entry<String, AbsSchedulerListener<TASK, AbsNormalEntity>>> iter = for (Iterator<Map.Entry<String, Map<TaskEnum, ISchedulerListener>>> iter =
mObservers.entrySet().iterator(); iter.hasNext(); ) { mObservers.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry<String, AbsSchedulerListener<TASK, AbsNormalEntity>> entry = iter.next(); Map.Entry<String, Map<TaskEnum, ISchedulerListener>> entry = iter.next();
if (entry.getKey().equals(getKey(obj))) { if (entry.getKey().equals(getKey(obj))) {
iter.remove(); iter.remove();
} }
@ -109,15 +121,15 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends IT
/** /**
* 创建代理类 * 创建代理类
* *
* @param targetName 通过观察者创建对应的Aria事件代理 * @param proxyClassName 代理类类名
*/ */
private AbsSchedulerListener<TASK, AbsNormalEntity> createListener(String targetName) { private ISchedulerListener createListener(String proxyClassName) {
AbsSchedulerListener<TASK, AbsNormalEntity> listener = null; ISchedulerListener listener = null;
try { try {
Class clazz = Class.forName(targetName + getProxySuffix()); Class clazz = Class.forName(proxyClassName);
listener = (AbsSchedulerListener<TASK, AbsNormalEntity>) clazz.newInstance(); listener = (ISchedulerListener) clazz.newInstance();
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
ALog.e(TAG, targetName + ",没有Aria的Download或Upload注解方法"); ALog.e(TAG, e.getMessage());
} catch (InstantiationException e) { } catch (InstantiationException e) {
ALog.e(TAG, e.getMessage()); ALog.e(TAG, e.getMessage());
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
@ -131,6 +143,10 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends IT
return handleSubEvent(msg); return handleSubEvent(msg);
} }
if (msg.arg1 == IS_M3U8_PEER) {
return handlePeerEvent(msg);
}
TASK task = (TASK) msg.obj; TASK task = (TASK) msg.obj;
if (task == null) { if (task == null) {
ALog.e(TAG, "请传入下载任务"); ALog.e(TAG, "请传入下载任务");
@ -140,6 +156,54 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends IT
return true; return true;
} }
/**
* 处理m3u8切片任务事件
*/
private boolean handlePeerEvent(Message msg) {
Bundle data = msg.getData();
if (mObservers.size() > 0) {
Set<String> keys = mObservers.keySet();
for (String key : keys) {
Map<TaskEnum, ISchedulerListener> listeners = mObservers.get(key);
if (listeners == null || listeners.isEmpty()) {
continue;
}
M3U8PeerTaskListener listener =
(M3U8PeerTaskListener) listeners.get(TaskEnum.M3U8_PEER);
if (listener == null) {
continue;
}
switch (msg.what) {
case M3U8_PEER_START:
listener.onPeerStart(data.getString(DATA_M3U8_URL),
data.getString(DATA_M3U8_PEER_PATH),
data.getInt(DATA_M3U8_PEER_INDEX));
break;
case M3U8_PEER_COMPLETE:
listener.onPeerComplete(data.getString(DATA_M3U8_URL),
data.getString(DATA_M3U8_PEER_PATH),
data.getInt(DATA_M3U8_PEER_INDEX));
break;
case M3U8_PEER_FAIL:
listener.onPeerFail(data.getString(DATA_M3U8_URL),
data.getString(DATA_M3U8_PEER_PATH),
data.getInt(DATA_M3U8_PEER_INDEX));
break;
}
}
}
boolean canSend = manager.getAppConfig().isUseBroadcast();
if (canSend) {
Intent intent = new Intent(ISchedulers.ARIA_TASK_INFO_ACTION);
intent.putExtras(data);
AriaManager.APP.sendBroadcast(intent);
}
return true;
}
/** /**
* 处理任务组子任务事件 * 处理任务组子任务事件
*/ */
@ -148,7 +212,15 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends IT
if (mObservers.size() > 0) { if (mObservers.size() > 0) {
Set<String> keys = mObservers.keySet(); Set<String> keys = mObservers.keySet();
for (String key : keys) { for (String key : keys) {
AbsSchedulerListener<TASK, AbsNormalEntity> listener = mObservers.get(key); Map<TaskEnum, ISchedulerListener> listeners = mObservers.get(key);
if (listeners == null || listeners.isEmpty()) {
continue;
}
SubTaskListener<TASK, AbsNormalEntity> listener =
(SubTaskListener<TASK, AbsNormalEntity>) listeners.get(TaskEnum.DOWNLOAD_GROUP_SUB);
if (listener == null) {
continue;
}
switch (msg.what) { switch (msg.what) {
case SUB_PRE: case SUB_PRE:
listener.onSubTaskPre((TASK) params.groupTask, params.entity); listener.onSubTaskPre((TASK) params.groupTask, params.entity);
@ -228,7 +300,7 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends IT
} }
} }
if (what != FAIL) { if (what != FAIL) {
callback(what, task); normalTaskCallback(what, task);
} }
} }
@ -237,18 +309,33 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends IT
* *
* @param state 状态 * @param state 状态
*/ */
private void callback(int state, TASK task) { private void normalTaskCallback(int state, TASK task) {
sendNormalBroadcast(state, task); sendNormalBroadcast(state, task);
if (mObservers.size() > 0) { if (mObservers.size() > 0) {
Set<String> keys = mObservers.keySet(); Set<String> keys = mObservers.keySet();
for (String key : keys) { for (String key : keys) {
callback(state, task, mObservers.get(key)); Map<TaskEnum, ISchedulerListener> listeners = mObservers.get(key);
if (listeners == null || listeners.isEmpty()) {
continue;
}
NormalTaskListener<TASK> listener = null;
if (mObservers.get(key) != null) {
if (task instanceof DownloadTask) {
listener = (NormalTaskListener<TASK>) listeners.get(TaskEnum.DOWNLOAD);
} else if (task instanceof DownloadGroupTask) {
listener = (NormalTaskListener<TASK>) listeners.get(TaskEnum.DOWNLOAD_GROUP);
} else if (task instanceof UploadTask) {
listener = (NormalTaskListener<TASK>) listeners.get(TaskEnum.UPLOAD);
}
}
if (listener != null) {
normalTaskCallback(state, task, listener);
}
} }
} }
} }
private void callback(int state, TASK task, private void normalTaskCallback(int state, TASK task, NormalTaskListener<TASK> listener) {
AbsSchedulerListener<TASK, AbsNormalEntity> listener) {
if (listener != null) { if (listener != null) {
if (task == null) { if (task == null) {
ALog.e(TAG, "TASK 为null,回调失败"); ALog.e(TAG, "TASK 为null,回调失败");
@ -341,7 +428,7 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends IT
if (!task.isNeedRetry() || task.isStop() || task.isCancel()) { if (!task.isNeedRetry() || task.isStop() || task.isCancel()) {
mQueue.removeTaskFormQueue(task.getKey()); mQueue.removeTaskFormQueue(task.getKey());
startNextTask(task); startNextTask(task);
callback(FAIL, task); normalTaskCallback(FAIL, task);
return; return;
} }
long interval = task.getTaskWrapper().getConfig().getReTryInterval(); long interval = task.getTaskWrapper().getConfig().getReTryInterval();
@ -354,7 +441,7 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends IT
mQueue.removeTaskFormQueue(task.getKey()); mQueue.removeTaskFormQueue(task.getKey());
startNextTask(task); startNextTask(task);
TaskWrapperManager.getInstance().removeTaskWrapper(task.getKey()); TaskWrapperManager.getInstance().removeTaskWrapper(task.getKey());
callback(FAIL, task); normalTaskCallback(FAIL, task);
return; return;
} }

@ -15,7 +15,6 @@
*/ */
package com.arialyy.aria.core.scheduler; package com.arialyy.aria.core.scheduler;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.download.DGTaskWrapper; import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.download.DownloadGroupTask; import com.arialyy.aria.core.download.DownloadGroupTask;
import com.arialyy.aria.core.queue.DownloadGroupTaskQueue; import com.arialyy.aria.core.queue.DownloadGroupTaskQueue;
@ -36,14 +35,10 @@ public class DownloadGroupSchedulers extends
public static DownloadGroupSchedulers getInstance() { public static DownloadGroupSchedulers getInstance() {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (AriaManager.LOCK) { synchronized (DownloadGroupSchedulers.class) {
INSTANCE = new DownloadGroupSchedulers(); INSTANCE = new DownloadGroupSchedulers();
} }
} }
return INSTANCE; return INSTANCE;
} }
@Override String getProxySuffix() {
return "$$DownloadGroupListenerProxy";
}
} }

@ -16,10 +16,9 @@
package com.arialyy.aria.core.scheduler; package com.arialyy.aria.core.scheduler;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.queue.DownloadTaskQueue;
import com.arialyy.aria.core.download.DownloadTask; import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.core.queue.DownloadTaskQueue;
/** /**
* Created by lyy on 2016/8/16. * Created by lyy on 2016/8/16.
@ -38,14 +37,10 @@ public class DownloadSchedulers
public static DownloadSchedulers getInstance() { public static DownloadSchedulers getInstance() {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (AriaManager.LOCK) { synchronized (DownloadSchedulers.class) {
INSTANCE = new DownloadSchedulers(); INSTANCE = new DownloadSchedulers();
} }
} }
return INSTANCE; return INSTANCE;
} }
@Override String getProxySuffix() {
return "$$DownloadListenerProxy";
}
} }

@ -15,69 +15,10 @@
*/ */
package com.arialyy.aria.core.scheduler; package com.arialyy.aria.core.scheduler;
import com.arialyy.aria.core.inf.ITask;
/** /**
* Target处理任务监听 * Target处理任务监听
*/ */
public interface ISchedulerListener<TASK extends ITask> { public interface ISchedulerListener {
/**
* 队列已经满了继续创建任务将会回调该方法
*/
void onWait(TASK task);
/**
* 预处理有时有些地址链接比较慢这时可以先在这个地方出来一些界面上的UI如按钮的状态
* 在这个回调中任务是获取不到文件大小下载速度等参数
*/
void onPre(TASK task);
/**
* 任务预加载完成
*/
void onTaskPre(TASK task);
/**
* 任务恢复下载
*/
void onTaskResume(TASK task);
/**
* 任务开始
*/
void onTaskStart(TASK task);
/**
* 任务停止
*/
void onTaskStop(TASK task);
/**
* 任务取消
*/
void onTaskCancel(TASK task);
/**
* 任务失败
*
* @deprecated {@link #onTaskFail(ITask, Exception)}
*/
@Deprecated
void onTaskFail(TASK task);
/**
* 任务失败
*/
void onTaskFail(TASK task, Exception e);
/**
* 任务完成
*/
void onTaskComplete(TASK task);
/** void setListener(Object obj);
* 任务执行中
*/
void onTaskRunning(TASK task);
} }

@ -19,7 +19,6 @@ package com.arialyy.aria.core.scheduler;
import android.os.Handler; import android.os.Handler;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity; import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.inf.AbsTask;
import com.arialyy.aria.core.inf.ITask; import com.arialyy.aria.core.inf.ITask;
import com.arialyy.aria.core.upload.UploadEntity; import com.arialyy.aria.core.upload.UploadEntity;
@ -64,10 +63,28 @@ public interface ISchedulers extends Handler.Callback {
String TASK_PERCENT = "ARIA_TASK_PERCENT"; String TASK_PERCENT = "ARIA_TASK_PERCENT";
/** /**
* 为组合任务任务 * M3U8地址
*/
String DATA_M3U8_URL = "DATA_M3U8_URL";
/**
* 当前下载完成的切片地址
*/
String DATA_M3U8_PEER_PATH = "DATA_M3U8_PEER_PATH";
/**
* 当前下载完成的切片索引
*/
String DATA_M3U8_PEER_INDEX = "DATA_M3U8_PEER_INDEX";
/**
* 组合任务任务标志
*/ */
int IS_SUB_TASK = 0xd1; int IS_SUB_TASK = 0xd1;
/**
* m3u8切片任务标志
*/
int IS_M3U8_PEER = 0xd2;
/** /**
* 任务不支持断点 * 任务不支持断点
*/ */
@ -148,4 +165,17 @@ public interface ISchedulers extends Handler.Callback {
* 组合任务子任务完成 * 组合任务子任务完成
*/ */
int SUB_COMPLETE = 0xa7; int SUB_COMPLETE = 0xa7;
/**
* M3U8切片开始下载
*/
int M3U8_PEER_START = 0xb1;
/**
* M3U8切片下载完成
*/
int M3U8_PEER_COMPLETE = 0xb2;
/**
* M3U8切片下载失败
*/
int M3U8_PEER_FAIL = 0xb3;
} }

@ -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.scheduler;
/**
* Created by Aria.Lao on 2019/6/26.
* m3u8切片事件回调类
*/
public class M3U8PeerTaskListener implements ISchedulerListener {
public void onPeerStart(final String m3u8Url, final String peerPath, final int peerIndex) {
}
public void onPeerComplete(final String m3u8Url, final String peerPath, final int peerIndex) {
}
public void onPeerFail(final String m3u8Url, final String peerPath, final int peerIndex) {
}
@Override public void setListener(Object obj) {
}
}

@ -0,0 +1,116 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.scheduler;
import com.arialyy.aria.core.download.DownloadGroupTask;
import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.core.inf.ITask;
import com.arialyy.aria.core.upload.UploadTask;
/**
* Created by Aria.Lao on 2017/6/7.
* 普通任务事件{@link DownloadTask}{@link UploadTask}{@link DownloadGroupTask}回调类
*/
public class NormalTaskListener<TASK extends ITask> implements ISchedulerListener {
/**
* 队列已经满了继续创建任务将会回调该方法
*/
public void onWait(TASK task) {
}
/**
* 预处理有时有些地址链接比较慢这时可以先在这个地方出来一些界面上的UI如按钮的状态
* 在这个回调中任务是获取不到文件大小下载速度等参数
*/
public void onPre(TASK task) {
}
/**
* 任务预加载完成
*/
public void onTaskPre(TASK task) {
}
/**
* 任务恢复下载
*/
public void onTaskResume(TASK task) {
}
/**
* 任务开始
*/
public void onTaskStart(TASK task) {
}
/**
* 任务停止
*/
public void onTaskStop(TASK task) {
}
/**
* 任务取消
*/
public void onTaskCancel(TASK task) {
}
/**
* 任务失败
*
* @deprecated {@link #onTaskFail(ITask, Exception)}
*/
public void onTaskFail(TASK task) {
}
/**
* 任务失败
*/
public void onTaskFail(TASK task, Exception e) {
}
/**
* 任务完成
*/
public void onTaskComplete(TASK task) {
}
/**
* 任务执行中
*/
public void onTaskRunning(TASK task) {
}
public void onNoSupportBreakPoint(TASK task) {
}
@Override public void setListener(Object obj) {
}
}

@ -19,63 +19,16 @@ import com.arialyy.aria.core.inf.AbsNormalEntity;
import com.arialyy.aria.core.inf.ITask; import com.arialyy.aria.core.inf.ITask;
/** /**
* Created by Aria.Lao on 2017/6/7. * Created by Aria.Lao on 2019/6/26.
* 子任务事件回调类
*/ */
public class AbsSchedulerListener<TASK extends ITask, SUB_ENTITY extends AbsNormalEntity> public class SubTaskListener<TASK extends ITask, SUB_ENTITY extends AbsNormalEntity>
implements ISchedulerListener<TASK> { implements ISchedulerListener {
@Override public void onWait(TASK task) {
}
@Override public void onPre(TASK task) {
}
@Override public void onTaskPre(TASK task) {
}
@Override public void onTaskResume(TASK task) {
}
@Override public void onTaskStart(TASK task) {
}
@Override public void onTaskStop(TASK task) {
}
@Override public void onTaskCancel(TASK task) {
}
@Override public void onTaskFail(TASK task) {
}
@Override public void onTaskFail(TASK task, Exception e) {
}
@Override public void onTaskComplete(TASK task) {
}
@Override public void onTaskRunning(TASK task) {
}
public void onNoSupportBreakPoint(TASK task) { public void onNoSupportBreakPoint(TASK task) {
} }
public void setListener(Object obj) {
}
public void onSubTaskPre(TASK task, SUB_ENTITY subTask) { public void onSubTaskPre(TASK task, SUB_ENTITY subTask) {
} }
@ -108,4 +61,8 @@ public class AbsSchedulerListener<TASK extends ITask, SUB_ENTITY extends AbsNorm
public void onSubTaskRunning(TASK task, SUB_ENTITY subTask) { public void onSubTaskRunning(TASK task, SUB_ENTITY subTask) {
} }
@Override public void setListener(Object obj) {
}
} }

@ -15,7 +15,6 @@
*/ */
package com.arialyy.aria.core.scheduler; package com.arialyy.aria.core.scheduler;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.queue.UploadTaskQueue; import com.arialyy.aria.core.queue.UploadTaskQueue;
import com.arialyy.aria.core.upload.UTaskWrapper; import com.arialyy.aria.core.upload.UTaskWrapper;
import com.arialyy.aria.core.upload.UploadTask; import com.arialyy.aria.core.upload.UploadTask;
@ -35,15 +34,11 @@ public class UploadSchedulers extends AbsSchedulers<UTaskWrapper, UploadTask, Up
public static UploadSchedulers getInstance() { public static UploadSchedulers getInstance() {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (AriaManager.LOCK) { synchronized (UploadSchedulers.class) {
INSTANCE = new UploadSchedulers(); INSTANCE = new UploadSchedulers();
} }
} }
return INSTANCE; return INSTANCE;
} }
@Override String getProxySuffix() {
return "$$UploadListenerProxy";
}
} }

@ -18,11 +18,13 @@ package com.arialyy.aria.core.upload;
import android.support.annotation.CheckResult; import android.support.annotation.CheckResult;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.text.TextUtils; import android.text.TextUtils;
import com.arialyy.annotations.TaskEnum;
import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.command.CancelAllCmd;
import com.arialyy.aria.core.command.ICmd; import com.arialyy.aria.core.command.ICmd;
import com.arialyy.aria.core.command.normal.CancelAllCmd; import com.arialyy.aria.core.command.NormalCmdFactory;
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
import com.arialyy.aria.core.common.ProxyHelper; import com.arialyy.aria.core.common.ProxyHelper;
import com.arialyy.aria.core.event.EventMsgUtil;
import com.arialyy.aria.core.inf.AbsReceiver; import com.arialyy.aria.core.inf.AbsReceiver;
import com.arialyy.aria.core.inf.ReceiverType; import com.arialyy.aria.core.inf.ReceiverType;
import com.arialyy.aria.core.scheduler.UploadSchedulers; import com.arialyy.aria.core.scheduler.UploadSchedulers;
@ -164,11 +166,9 @@ public class UploadReceiver extends AbsReceiver {
* 停止所有正在下载的任务并清空等待队列 * 停止所有正在下载的任务并清空等待队列
*/ */
public void stopAllTask() { public void stopAllTask() {
AriaManager.getInstance(AriaManager.APP) EventMsgUtil.getDefault().post(NormalCmdFactory.getInstance()
.setCmd(NormalCmdFactory.getInstance() .createCmd(new UTaskWrapper(null), NormalCmdFactory.TASK_STOP_ALL,
.createCmd(new UTaskWrapper(null), NormalCmdFactory.TASK_STOP_ALL, ICmd.TASK_TYPE_UPLOAD));
ICmd.TASK_TYPE_UPLOAD))
.exe();
} }
/** /**
@ -183,7 +183,8 @@ public class UploadReceiver extends AbsReceiver {
(CancelAllCmd) CommonUtil.createNormalCmd(new UTaskWrapper(null), (CancelAllCmd) CommonUtil.createNormalCmd(new UTaskWrapper(null),
NormalCmdFactory.TASK_CANCEL_ALL, ICmd.TASK_TYPE_UPLOAD); NormalCmdFactory.TASK_CANCEL_ALL, ICmd.TASK_TYPE_UPLOAD);
cancelCmd.removeFile = removeFile; cancelCmd.removeFile = removeFile;
am.setCmd(cancelCmd).exe();
EventMsgUtil.getDefault().post(cancelCmd);
Set<String> keys = am.getReceiver().keySet(); Set<String> keys = am.getReceiver().keySet();
for (String key : keys) { for (String key : keys) {
am.getReceiver().remove(key); am.getReceiver().remove(key);
@ -207,7 +208,7 @@ public class UploadReceiver extends AbsReceiver {
if (set != null && !set.isEmpty()) { if (set != null && !set.isEmpty()) {
for (Integer type : set) { for (Integer type : set) {
if (type == ProxyHelper.PROXY_TYPE_UPLOAD) { if (type == ProxyHelper.PROXY_TYPE_UPLOAD) {
UploadSchedulers.getInstance().register(obj); UploadSchedulers.getInstance().register(obj, TaskEnum.UPLOAD);
} }
} }
} else { } else {

@ -23,8 +23,8 @@ import com.arialyy.aria.core.common.SubThreadConfig;
import com.arialyy.aria.core.common.ftp.AbsFtpThreadTask; import com.arialyy.aria.core.common.ftp.AbsFtpThreadTask;
import com.arialyy.aria.core.common.ftp.FtpTaskConfig; import com.arialyy.aria.core.common.ftp.FtpTaskConfig;
import com.arialyy.aria.core.config.UploadConfig; import com.arialyy.aria.core.config.UploadConfig;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.upload.UTaskWrapper; import com.arialyy.aria.core.upload.UTaskWrapper;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.exception.AriaIOException; import com.arialyy.aria.exception.AriaIOException;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.BufferedRandomAccessFile; import com.arialyy.aria.util.BufferedRandomAccessFile;
@ -107,6 +107,7 @@ class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UTaskWrapper> {
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
onThreadComplete();
} }
return this; return this;
} }

@ -102,6 +102,8 @@ class HttpThreadTask extends AbsThreadTask<UploadEntity, UTaskWrapper> {
fail(new TaskException(TAG, fail(new TaskException(TAG,
String.format("上传失败,filePath: %s, url: %s", getEntity().getFilePath(), String.format("上传失败,filePath: %s, url: %s", getEntity().getFilePath(),
getEntity().getUrl()), e)); getEntity().getUrl()), e));
} finally {
onThreadComplete();
} }
return this; return this;
} }

@ -65,7 +65,7 @@ public class SimpleUploadUtil implements IUtil, Runnable {
} }
@Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) { @Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) {
mListener.onFail(needRetry, e); failUpload(e, needRetry);
} }
}); });
new Thread(infoThread).start(); new Thread(infoThread).start();
@ -76,6 +76,14 @@ public class SimpleUploadUtil implements IUtil, Runnable {
} }
} }
private void failUpload(BaseException e, boolean needRetry) {
if (isStop || isCancel) {
return;
}
mListener.onFail(needRetry, e);
mUploader.onDestroy();
}
@Override public String getKey() { @Override public String getKey() {
return mTaskWrapper.getKey(); return mTaskWrapper.getKey();
} }
@ -108,8 +116,4 @@ public class SimpleUploadUtil implements IUtil, Runnable {
} }
new Thread(this).start(); new Thread(this).start();
} }
@Override public void setMaxSpeed(int speed) {
mUploader.setMaxSpeed(speed);
}
} }

@ -19,6 +19,8 @@ import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.common.AbsThreadTask; import com.arialyy.aria.core.common.AbsThreadTask;
import com.arialyy.aria.core.common.NormalFileer; import com.arialyy.aria.core.common.NormalFileer;
import com.arialyy.aria.core.common.SubThreadConfig; import com.arialyy.aria.core.common.SubThreadConfig;
import com.arialyy.aria.core.event.Event;
import com.arialyy.aria.core.event.SpeedEvent;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;
import com.arialyy.aria.core.inf.IUploadListener; import com.arialyy.aria.core.inf.IUploadListener;
import com.arialyy.aria.core.upload.UTaskWrapper; import com.arialyy.aria.core.upload.UTaskWrapper;
@ -51,4 +53,9 @@ class Uploader extends NormalFileer<UploadEntity, UTaskWrapper> {
} }
return null; return null;
} }
@Event
public void setMaxSpeed(SpeedEvent event) {
setMaxSpeed(event.speed);
}
} }

@ -22,6 +22,7 @@ import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity; import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.download.DGTaskWrapper; import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.m3u8.M3U8Entity;
import com.arialyy.aria.core.upload.UploadEntity; import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.upload.UTaskWrapper; import com.arialyy.aria.core.upload.UTaskWrapper;
import java.util.HashMap; import java.util.HashMap;
@ -37,7 +38,7 @@ class DBConfig {
static boolean DEBUG = false; static boolean DEBUG = false;
static Map<String, Class> mapping = new LinkedHashMap<>(); static Map<String, Class> mapping = new LinkedHashMap<>();
static String DB_NAME; static String DB_NAME;
static int VERSION = 49; static int VERSION = 51;
/** /**
* 是否将数据库保存在Sd卡{@code true} * 是否将数据库保存在Sd卡{@code true}
@ -59,5 +60,6 @@ class DBConfig {
mapping.put("UploadEntity", UploadEntity.class); mapping.put("UploadEntity", UploadEntity.class);
mapping.put("ThreadRecord", ThreadRecord.class); mapping.put("ThreadRecord", ThreadRecord.class);
mapping.put("TaskRecord", TaskRecord.class); mapping.put("TaskRecord", TaskRecord.class);
mapping.put("M3U8Entity", M3U8Entity.class);
} }
} }

@ -98,7 +98,7 @@ final class SqlHelper extends SQLiteOpenHelper {
handle314AriaUpdate(db); handle314AriaUpdate(db);
} else if (oldVersion < 45) { } else if (oldVersion < 45) {
handle360AriaUpdate(db); handle360AriaUpdate(db);
} else if (oldVersion < 49) { } else if (oldVersion < 51) {
handle365Update(db); handle365Update(db);
} else { } else {
handleDbUpdate(db, null, null); handleDbUpdate(db, null, null);
@ -223,6 +223,8 @@ final class SqlHelper extends SQLiteOpenHelper {
} }
//删除中介表 //删除中介表
mDelegate.dropTable(db, tableName + "_temp"); mDelegate.dropTable(db, tableName + "_temp");
}else {
mDelegate.createTable(db, clazz);
} }
} }
db.setTransactionSuccessful(); db.setTransactionSuccessful();

@ -64,7 +64,7 @@ public final class BufferedRandomAccessFile extends RandomAccessFile {
* c(f) the abstract contents of the file disk(f) the contents of f's * c(f) the abstract contents of the file disk(f) the contents of f's
* backing disk file closed(f) true iff the file is closed * backing disk file closed(f) true iff the file is closed
* *
* "curr(f)" is an index in the closed interval [0, len(f)]. "c(f)" is a * "curr(f)" is an peerIndex in the closed interval [0, len(f)]. "c(f)" is a
* character sequence of length "len(f)". "c(f)" and "disk(f)" may differ if * character sequence of length "len(f)". "c(f)" and "disk(f)" may differ if
* "c(f)" contains unflushed writes not reflected in "disk(f)". The flush * "c(f)" contains unflushed writes not reflected in "disk(f)". The flush
* operation has the effect of making "disk(f)" identical to "c(f)". * operation has the effect of making "disk(f)" identical to "c(f)".

@ -26,11 +26,11 @@ import android.text.TextUtils;
import android.util.Base64; import android.util.Base64;
import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.FtpUrlEntity; import com.arialyy.aria.core.FtpUrlEntity;
import com.arialyy.aria.core.command.AbsGroupCmd;
import com.arialyy.aria.core.command.AbsNormalCmd;
import com.arialyy.aria.core.command.GroupCmdFactory;
import com.arialyy.aria.core.command.ICmd; import com.arialyy.aria.core.command.ICmd;
import com.arialyy.aria.core.command.group.AbsGroupCmd; import com.arialyy.aria.core.command.NormalCmdFactory;
import com.arialyy.aria.core.command.group.GroupCmdFactory;
import com.arialyy.aria.core.command.normal.AbsNormalCmd;
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
import com.arialyy.aria.core.inf.AbsGroupTaskWrapper; import com.arialyy.aria.core.inf.AbsGroupTaskWrapper;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;
import dalvik.system.DexFile; import dalvik.system.DexFile;
@ -70,6 +70,22 @@ import java.util.regex.Pattern;
public class CommonUtil { public class CommonUtil {
private static final String TAG = "CommonUtil"; private static final String TAG = "CommonUtil";
public static final String SERVER_CHARSET = "ISO-8859-1"; public static final String SERVER_CHARSET = "ISO-8859-1";
private static long lastClickTime;
/**
* 是否是快速点击500ms内快速点击无效
*
* @return true 快速点击
*/
public static boolean isFastDoubleClick() {
long time = System.currentTimeMillis();
long timeD = time - lastClickTime;
if (0 < timeD && timeD < 500) {
return true;
}
lastClickTime = time;
return false;
}
/** /**
* 将字符串转换为Ftp服务器默认的ISO-8859-1编码 * 将字符串转换为Ftp服务器默认的ISO-8859-1编码
@ -83,8 +99,6 @@ public class CommonUtil {
return new String(str.getBytes(charSet), SERVER_CHARSET); return new String(str.getBytes(charSet), SERVER_CHARSET);
} }
/** /**
* 删除文件 * 删除文件
* *
@ -968,7 +982,7 @@ public class CommonUtil {
} }
try { try {
if (file.createNewFile()) { if (file.createNewFile()) {
ALog.d(TAG, "创建文件成功:" + file.getAbsolutePath()); //ALog.d(TAG, "创建文件成功:" + file.getAbsolutePath());
return true; return true;
} }
} catch (IOException e) { } catch (IOException e) {

@ -22,13 +22,11 @@ import com.arialyy.aria.core.common.TaskRecord;
import com.arialyy.aria.core.common.ThreadRecord; import com.arialyy.aria.core.common.ThreadRecord;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity; import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.download.m3u8.BaseM3U8Loader;
import com.arialyy.aria.core.inf.AbsEntity; import com.arialyy.aria.core.inf.AbsEntity;
import com.arialyy.aria.core.inf.AbsNormalEntity; import com.arialyy.aria.core.inf.AbsNormalEntity;
import com.arialyy.aria.core.upload.UploadEntity; import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.orm.DbEntity;
import java.io.File; import java.io.File;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
@ -154,7 +152,7 @@ public class RecordUtil {
if (!targetFile.isDirectory()) { if (!targetFile.isDirectory()) {
cacheDir = targetFile.getParent() + "/." + targetFile.getName(); cacheDir = targetFile.getParent() + "/." + targetFile.getName();
} }
removeTsCache(record, cacheDir); removeTsCache(cacheDir);
} else if (record.isBlock) { // 删除分块文件 } else if (record.isBlock) { // 删除分块文件
removeBlockFile(record); removeBlockFile(record);
} }
@ -216,7 +214,7 @@ public class RecordUtil {
cacheDir = String.format("%s/.%s_%s", targetFile.getParent(), targetFile.getName(), cacheDir = String.format("%s/.%s_%s", targetFile.getParent(), targetFile.getName(),
record.bandWidth); record.bandWidth);
} }
removeTsCache(record, cacheDir); removeTsCache(cacheDir);
} else if (record.isBlock) { // 删除分块文件 } else if (record.isBlock) { // 删除分块文件
removeBlockFile(record); removeBlockFile(record);
} }
@ -289,15 +287,12 @@ public class RecordUtil {
/** /**
* 删除ts文件 * 删除ts文件
*/ */
private static void removeTsCache(TaskRecord record, String cacheDir) { private static void removeTsCache(String cacheDir) {
if (!TextUtils.isEmpty(cacheDir)) { if (!TextUtils.isEmpty(cacheDir)) {
List<String> partPath = new ArrayList<>();
for (ThreadRecord tr : record.threadRecords) { File[] files = new File(cacheDir).listFiles();
partPath.add(BaseM3U8Loader.getTsFilePath(cacheDir, tr.threadId)); for (File f : files) {
}
for (String pp : partPath) {
File f = new File(pp);
if (f.exists()) { if (f.exists()) {
f.delete(); f.delete();
} }

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

Loading…
Cancel
Save