修复任务记录删除失败的问题
优化网络连接状态获取的逻辑 修复配置文件的某些配置失效的问题 新增m3u8切片状态注解`@M3U8.onPeerStart`,`@M3U8.onPeerComplete`,`@M3U8.onPeerFail` 新增动态指定m3u8协议视频的下载功能(边下边播)
This commit is contained in:
34
.github/ISSUE_TEMPLATE/Custom.md
vendored
34
.github/ISSUE_TEMPLATE/Custom.md
vendored
@@ -1,17 +1,17 @@
|
||||
---
|
||||
name: 问题描述
|
||||
about: 描述你遇到的问题或bug
|
||||
|
||||
---
|
||||
|
||||
## Aria版本
|
||||
|
||||
|
||||
## 什么问题
|
||||
|
||||
|
||||
## 如何复现此问题
|
||||
|
||||
|
||||
## 控制台日志
|
||||
|
||||
---
|
||||
name: 问题描述
|
||||
about: 请详细描述你遇到的问题
|
||||
|
||||
---
|
||||
|
||||
## Aria版本
|
||||
|
||||
|
||||
## 什么问题
|
||||
|
||||
|
||||
## 如何复现此问题
|
||||
|
||||
|
||||
## 控制台日志
|
||||
|
||||
|
||||
@@ -24,26 +24,23 @@ import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.NetworkRequest;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.widget.PopupWindow;
|
||||
import com.arialyy.aria.BuildConfig;
|
||||
import com.arialyy.aria.core.command.ICmd;
|
||||
import com.arialyy.aria.core.command.CommandManager;
|
||||
import com.arialyy.aria.core.common.QueueMod;
|
||||
import com.arialyy.aria.core.common.RecordHandler;
|
||||
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.DownloadConfig;
|
||||
import com.arialyy.aria.core.config.UploadConfig;
|
||||
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.DownloadGroupEntity;
|
||||
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 {
|
||||
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 UPLOAD_TEMP_DIR = "/Aria/temp/upload/";
|
||||
/**
|
||||
@@ -90,7 +87,6 @@ import org.xml.sax.SAXException;
|
||||
*/
|
||||
private Map<String, List<String>> mSubClass = new ConcurrentHashMap<>();
|
||||
public static Context APP;
|
||||
private List<ICmd> mCommands = new ArrayList<>();
|
||||
private DownloadConfig mDConfig;
|
||||
private UploadConfig mUConfig;
|
||||
private AppConfig mAConfig;
|
||||
@@ -110,7 +106,9 @@ import org.xml.sax.SAXException;
|
||||
public static AriaManager getInstance(Context context) {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (LOCK) {
|
||||
INSTANCE = new AriaManager(context);
|
||||
if (INSTANCE == null) {
|
||||
INSTANCE = new AriaManager(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
return INSTANCE;
|
||||
@@ -182,6 +180,7 @@ import org.xml.sax.SAXException;
|
||||
Thread.setDefaultUncaughtExceptionHandler(new AriaCrashHandler());
|
||||
}
|
||||
mAConfig.setLogLevel(mAConfig.getLogLevel());
|
||||
CommandManager.init();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -291,34 +290,6 @@ import org.xml.sax.SAXException;
|
||||
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
|
||||
* 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.inf.AbsGroupTask;
|
||||
import com.arialyy.aria.core.inf.AbsTask;
|
||||
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.util.ALog;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
@@ -14,17 +14,13 @@
|
||||
* 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.DTaskWrapper;
|
||||
import com.arialyy.aria.core.inf.AbsEntity;
|
||||
import com.arialyy.aria.core.inf.AbsTask;
|
||||
import com.arialyy.aria.core.inf.AbsTaskWrapper;
|
||||
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.DownloadTaskQueue;
|
||||
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) {
|
||||
AbsTask tempTask = getTask(taskEntity.getEntity());
|
||||
void removeTask(AbsTaskWrapper wrapper) {
|
||||
AbsTask tempTask = getTask(wrapper.getKey());
|
||||
if (tempTask == null) {
|
||||
tempTask = createTask(taskEntity);
|
||||
tempTask = createTask(wrapper);
|
||||
}
|
||||
mQueue.cancelTask(tempTask);
|
||||
}
|
||||
@@ -143,7 +139,7 @@ public abstract class AbsNormalCmd<T extends AbsTaskWrapper> extends AbsCmd<T> {
|
||||
*/
|
||||
void startTask() {
|
||||
AbsTask task = getTask();
|
||||
if (task == null){
|
||||
if (task == null) {
|
||||
task = createTask();
|
||||
}
|
||||
mQueue.startTask(task);
|
||||
@@ -154,7 +150,7 @@ public abstract class AbsNormalCmd<T extends AbsTaskWrapper> extends AbsCmd<T> {
|
||||
*/
|
||||
void resumeTask() {
|
||||
AbsTask task = getTask();
|
||||
if (task == null){
|
||||
if (task == null) {
|
||||
task = createTask();
|
||||
}
|
||||
mQueue.resumeTask(task);
|
||||
@@ -183,8 +179,8 @@ public abstract class AbsNormalCmd<T extends AbsTaskWrapper> extends AbsCmd<T> {
|
||||
*
|
||||
* @return 执行任务
|
||||
*/
|
||||
AbsTask getTask(AbsEntity entity) {
|
||||
return mQueue.getTask(entity.getKey());
|
||||
AbsTask getTask(String key) {
|
||||
return mQueue.getTask(key);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,11 +195,11 @@ public abstract class AbsNormalCmd<T extends AbsTaskWrapper> extends AbsCmd<T> {
|
||||
/**
|
||||
* 创建指定实体的任务
|
||||
*
|
||||
* @param taskEntity 特定的任务实体
|
||||
* @param wrapper 特定的任务实体
|
||||
* @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.
|
||||
*/
|
||||
|
||||
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.AbsTaskWrapper;
|
||||
@@ -25,7 +25,7 @@ import com.arialyy.aria.util.ALog;
|
||||
* 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) {
|
||||
super(entity, taskType);
|
||||
@@ -14,7 +14,7 @@
|
||||
* 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.DTaskWrapper;
|
||||
@@ -35,7 +35,7 @@ import java.util.List;
|
||||
* 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}
|
||||
* 如果文件已经下载完成,只删除下载记录
|
||||
@@ -64,7 +64,8 @@ public class CancelAllCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
|
||||
DbEntity.findDatas(DownloadEntity.class, "isGroupChild=?", "false");
|
||||
if (entities != null && !entities.isEmpty()) {
|
||||
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()) {
|
||||
for (DownloadGroupEntity entity : entities) {
|
||||
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");
|
||||
if (entities != null && !entities.isEmpty()) {
|
||||
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) {
|
||||
if (te == null){
|
||||
if (te == null) {
|
||||
ALog.w(TAG, "取消任务失败,任务为空");
|
||||
return;
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* 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.AbsTaskWrapper;
|
||||
@@ -23,7 +23,7 @@ import com.arialyy.aria.core.inf.AbsTaskWrapper;
|
||||
* 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}
|
||||
* 如果文件已经下载完成,只删除下载记录
|
||||
@@ -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
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.command.group;
|
||||
package com.arialyy.aria.core.command;
|
||||
|
||||
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> {
|
||||
GroupStartCmd(T wrapper) {
|
||||
final class DGSubStartCmd<T extends AbsGroupTaskWrapper> extends AbsGroupCmd<T> {
|
||||
DGSubStartCmd(T wrapper) {
|
||||
super(wrapper);
|
||||
}
|
||||
|
||||
@@ -13,16 +13,16 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.command.group;
|
||||
package com.arialyy.aria.core.command;
|
||||
|
||||
import com.arialyy.aria.core.inf.AbsGroupTaskWrapper;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/6/29.
|
||||
* 停止任务组的命令
|
||||
* 停止任务组子任务的命令
|
||||
*/
|
||||
class GroupStopCmd<T extends AbsGroupTaskWrapper> extends AbsGroupCmd<T> {
|
||||
GroupStopCmd(T entity) {
|
||||
final class DGSubStopCmd<T extends AbsGroupTaskWrapper> extends AbsGroupCmd<T> {
|
||||
DGSubStopCmd(T entity) {
|
||||
super(entity);
|
||||
}
|
||||
|
||||
@@ -13,10 +13,8 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* 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;
|
||||
|
||||
/**
|
||||
@@ -40,7 +38,7 @@ public class GroupCmdFactory {
|
||||
|
||||
public static GroupCmdFactory getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (GroupCmdFactory.class) {
|
||||
INSTANCE = new GroupCmdFactory();
|
||||
}
|
||||
}
|
||||
@@ -58,10 +56,10 @@ public class GroupCmdFactory {
|
||||
AbsGroupCmd cmd = null;
|
||||
switch (type) {
|
||||
case SUB_TASK_START:
|
||||
cmd = new GroupStartCmd<>(wrapper);
|
||||
cmd = new DGSubStartCmd<>(wrapper);
|
||||
break;
|
||||
case SUB_TASK_STOP:
|
||||
cmd = new GroupStopCmd<>(wrapper);
|
||||
cmd = new DGSubStopCmd<>(wrapper);
|
||||
break;
|
||||
}
|
||||
if (cmd != null) {
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* 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.download.DownloadTask;
|
||||
@@ -14,11 +14,8 @@
|
||||
* 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;
|
||||
|
||||
/**
|
||||
@@ -75,7 +72,7 @@ public class NormalCmdFactory extends AbsCmdFactory<AbsTaskWrapper, AbsNormalCmd
|
||||
|
||||
public static NormalCmdFactory getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (NormalCmdFactory.class) {
|
||||
INSTANCE = new NormalCmdFactory();
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* 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.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) {
|
||||
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.download.DGTaskWrapper;
|
||||
@@ -14,7 +14,7 @@
|
||||
* 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.common.QueueMod;
|
||||
@@ -41,7 +41,7 @@ import java.util.List;
|
||||
/**
|
||||
* 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) {
|
||||
super(entity, taskType);
|
||||
@@ -90,8 +90,7 @@ class StartCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
|
||||
}
|
||||
} else {
|
||||
//任务没执行并且执行队列中没有该任务,才认为任务没有运行中
|
||||
if (!task.isRunning() && !mQueue.taskIsRunning(task.getKey()) && !mQueue.taskExists(
|
||||
task.getKey())) {
|
||||
if (!mQueue.taskIsRunning(task.getKey())) {
|
||||
resumeTask();
|
||||
} else {
|
||||
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) {
|
||||
for (AbsTaskWrapper te : waitList) {
|
||||
if (te.getEntity() == null) continue;
|
||||
AbsTask task = getTask(te.getEntity());
|
||||
AbsTask task = getTask(te.getKey());
|
||||
if (task != null) continue;
|
||||
if (te instanceof DTaskWrapper) {
|
||||
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;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* 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.AbsTaskWrapper;
|
||||
@@ -25,7 +25,7 @@ import com.arialyy.aria.util.ALog;
|
||||
* 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) {
|
||||
super(entity, taskType);
|
||||
@@ -36,7 +36,6 @@ class StopCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
|
||||
AbsTask task = getTask();
|
||||
if (task == null) {
|
||||
if (mTaskWrapper.getEntity().getState() == IEntity.STATE_RUNNING) {
|
||||
createTask();
|
||||
stopTask();
|
||||
} else {
|
||||
ALog.w(TAG, "停止命令执行失败,【调度器中没有该任务】");
|
||||
@@ -49,6 +49,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
|
||||
protected TaskRecord mRecord;
|
||||
private IThreadState mStateManager;
|
||||
private boolean isCancel = false, isStop = false;
|
||||
private boolean isRuning = false;
|
||||
|
||||
protected AbsFileer(IEventListener listener, TASK_WRAPPER wrapper) {
|
||||
mListener = listener;
|
||||
@@ -64,11 +65,6 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
|
||||
*/
|
||||
protected abstract void handleTask();
|
||||
|
||||
/**
|
||||
* 设置最大下载速度
|
||||
*/
|
||||
protected abstract void setMaxSpeed(int maxSpeed);
|
||||
|
||||
public String getKey() {
|
||||
return mTaskWrapper.getKey();
|
||||
}
|
||||
@@ -101,14 +97,15 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
|
||||
if (isBreak()) {
|
||||
return;
|
||||
}
|
||||
isRuning = true;
|
||||
resetState();
|
||||
mRecord = new RecordHandler(mTaskWrapper).getRecord();
|
||||
Looper.prepare();
|
||||
Looper looper = Looper.myLooper();
|
||||
mStateManager = getStateManager(looper);
|
||||
onPostPre();
|
||||
startTimer();
|
||||
handleTask();
|
||||
startTimer();
|
||||
Looper.loop();
|
||||
}
|
||||
|
||||
@@ -137,18 +134,24 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
|
||||
* 启动进度获取定时器
|
||||
*/
|
||||
private synchronized void startTimer() {
|
||||
if (isBreak()) {
|
||||
return;
|
||||
}
|
||||
ALog.d(TAG, "启动定时器");
|
||||
mTimer = new ScheduledThreadPoolExecutor(1);
|
||||
mTimer.scheduleWithFixedDelay(new Runnable() {
|
||||
@Override public void run() {
|
||||
if (mStateManager.isComplete()
|
||||
|| mStateManager.isStop()
|
||||
|| mStateManager.isCancel()
|
||||
|| mStateManager.isFail()
|
||||
|| !isRunning()
|
||||
|| isBreak()) {
|
||||
ALog.d(TAG, "isComplete = " + mStateManager.isComplete()
|
||||
+ "; isFail = " + mStateManager.isFail()
|
||||
+ "; isRunning = " + isRunning()
|
||||
+ "; isBreak = " + isBreak());
|
||||
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
|
||||
closeTimer();
|
||||
onDestroy();
|
||||
} else if (mStateManager.getCurrentProgress() >= 0) {
|
||||
mListener.onProgress(mStateManager.getCurrentProgress());
|
||||
}
|
||||
@@ -157,12 +160,16 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
|
||||
}
|
||||
|
||||
public synchronized void closeTimer() {
|
||||
ALog.d(TAG, "关闭定时器");
|
||||
ALog.i(TAG, "关闭定时器");
|
||||
if (mTimer != null && !mTimer.isShutdown()) {
|
||||
mTimer.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
isRuning = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置定时器更新间隔
|
||||
*
|
||||
@@ -184,13 +191,13 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
|
||||
* 获取当前任务位置
|
||||
*/
|
||||
public long getCurrentLocation() {
|
||||
return mStateManager.getCurrentProgress();
|
||||
return isRuning ? mStateManager.getCurrentProgress() : mEntity.getCurrentProgress();
|
||||
}
|
||||
|
||||
public synchronized boolean isRunning() {
|
||||
boolean b = ThreadTaskManager.getInstance().taskIsRunning(mTaskWrapper.getKey());
|
||||
//ALog.d(TAG, "isRunning = " + b);
|
||||
return b;
|
||||
return b && isRuning;
|
||||
}
|
||||
|
||||
final public synchronized void cancel() {
|
||||
@@ -209,6 +216,8 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
|
||||
}
|
||||
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
|
||||
onPostCancel();
|
||||
onDestroy();
|
||||
mListener.onCancel();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,7 +241,6 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
|
||||
closeTimer();
|
||||
isStop = true;
|
||||
onStop();
|
||||
if (mStateManager.isComplete()) return;
|
||||
for (int i = 0; i < mTask.size(); i++) {
|
||||
AbsThreadTask task = mTask.valueAt(i);
|
||||
if (task != null && !task.isThreadComplete()) {
|
||||
@@ -241,6 +249,8 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
|
||||
}
|
||||
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
|
||||
onPostStop();
|
||||
onDestroy();
|
||||
mListener.onStop(getCurrentLocation());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -283,7 +293,8 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
|
||||
*/
|
||||
public boolean isBreak() {
|
||||
if (isCancel || isStop) {
|
||||
closeTimer();
|
||||
//closeTimer();
|
||||
ALog.d(TAG, "isCancel = " + isCancel + ", isStop = " + isStop);
|
||||
ALog.d(TAG, String.format("任务【%s】已停止或取消了", mEntity.getFileName()));
|
||||
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.ITaskWrapper;
|
||||
import com.arialyy.aria.core.manager.ThreadTaskManager;
|
||||
import com.arialyy.aria.core.scheduler.ISchedulers;
|
||||
import com.arialyy.aria.exception.BaseException;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
||||
@@ -66,7 +67,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
private boolean taskBreak = false; //任务跳出
|
||||
protected BandwidthLimiter mSpeedBandUtil; //速度限制工具
|
||||
protected AriaManager mAridManager;
|
||||
private boolean isInterrupted = false;
|
||||
private boolean isDestroy = false;
|
||||
protected boolean isCancel = false, isStop = false;
|
||||
protected ThreadRecord mRecord;
|
||||
private Handler mStateHandler;
|
||||
@@ -103,17 +104,22 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
return mConfig.tempFile.getName();
|
||||
}
|
||||
|
||||
protected SubThreadConfig<TASK_WRAPPER> getConfig() {
|
||||
public SubThreadConfig<TASK_WRAPPER> getConfig() {
|
||||
return mConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置线程是否中断
|
||||
*
|
||||
* @param isInterrupted {@code true} 中断
|
||||
*/
|
||||
public void setInterrupted(boolean isInterrupted) {
|
||||
this.isInterrupted = isInterrupted;
|
||||
public void destroy() {
|
||||
this.isDestroy = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 线程执行完成
|
||||
*/
|
||||
protected void onThreadComplete() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,7 +128,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
* @return {@code true}存活
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
||||
public void setMaxSpeed(int speed) {
|
||||
if (mSpeedBandUtil != null) {
|
||||
mSpeedBandUtil.setMaxRate(speed);
|
||||
@@ -197,13 +204,28 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
Message msg = mStateHandler.obtainMessage();
|
||||
msg.what = state;
|
||||
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) {
|
||||
msg.setData(bundle);
|
||||
}
|
||||
Thread loopThread = mStateHandler.getLooper().getThread();
|
||||
if (!loopThread.isAlive() || loopThread.isInterrupted()) {
|
||||
return;
|
||||
}
|
||||
msg.sendToTarget();
|
||||
}
|
||||
|
||||
public boolean isInterrupted() {
|
||||
public boolean isDestroy() {
|
||||
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} 不是中断
|
||||
*/
|
||||
@@ -285,7 +310,8 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
// return;
|
||||
//}
|
||||
mChildCurrentLocation += len;
|
||||
if (!mStateHandler.getLooper().getThread().isAlive()) {
|
||||
Thread loopThread = mStateHandler.getLooper().getThread();
|
||||
if (!loopThread.isAlive() || loopThread.isInterrupted()) {
|
||||
return;
|
||||
}
|
||||
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 {
|
||||
isInterrupted = false;
|
||||
isDestroy = false;
|
||||
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
|
||||
TrafficStats.setThreadStatsTag(UUID.randomUUID().toString().hashCode());
|
||||
return this;
|
||||
|
||||
@@ -160,9 +160,11 @@ public abstract class BaseListener<ENTITY extends AbsEntity, TASK_WRAPPER extend
|
||||
if (mEntity instanceof DownloadGroupEntity) {
|
||||
RecordUtil.delGroupTaskRecord((DownloadGroupEntity) mEntity, false, false);
|
||||
} 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) {
|
||||
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_ERROR_INFO = "KEY_ERROR_INFO";
|
||||
|
||||
/**
|
||||
* 任务是否已经停止
|
||||
*
|
||||
* @return true 任务已停止
|
||||
*/
|
||||
boolean isStop();
|
||||
|
||||
/**
|
||||
* 任务是否已经失败
|
||||
*
|
||||
@@ -51,13 +44,6 @@ public interface IThreadState extends Handler.Callback {
|
||||
*/
|
||||
boolean isComplete();
|
||||
|
||||
/**
|
||||
* 任务是否已经取消
|
||||
*
|
||||
* @return true 任务已取消
|
||||
*/
|
||||
boolean isCancel();
|
||||
|
||||
/**
|
||||
* 获取当前任务进度
|
||||
*
|
||||
|
||||
@@ -65,11 +65,4 @@ public interface IUtil {
|
||||
* 开始
|
||||
*/
|
||||
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.Looper;
|
||||
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.AbsTaskWrapper;
|
||||
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) {
|
||||
super(listener, wrapper);
|
||||
EventMsgUtil.getDefault().register(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,8 +57,7 @@ public abstract class NormalFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
*
|
||||
* @param maxSpeed 单位为:kb
|
||||
*/
|
||||
@Override
|
||||
public void setMaxSpeed(int maxSpeed) {
|
||||
protected void setMaxSpeed(int maxSpeed) {
|
||||
for (int i = 0; i < getTaskList().size(); i++) {
|
||||
AbsThreadTask task = getTaskList().valueAt(i);
|
||||
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() {
|
||||
super.onPostPre();
|
||||
mTotalThreadNum = mRecord.threadNum;
|
||||
|
||||
@@ -15,13 +15,8 @@
|
||||
*/
|
||||
package com.arialyy.aria.core.common;
|
||||
|
||||
import android.os.Build;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import com.arialyy.annotations.TaskEnum;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
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_SUB = 0x03;
|
||||
/**
|
||||
* 普通上传任务类型
|
||||
*/
|
||||
public static int PROXY_TYPE_UPLOAD = 0x04;
|
||||
public Set<String> downloadCounter = new HashSet<>(), uploadCounter = new HashSet<>(),
|
||||
downloadGroupCounter = new HashSet<>(), downloadGroupSubCounter = new HashSet<>();
|
||||
public static int PROXY_TYPE_UPLOAD = 0x03;
|
||||
/**
|
||||
* 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 static volatile ProxyHelper INSTANCE = null;
|
||||
private boolean canLoadClass = false;
|
||||
|
||||
private ProxyHelper() {
|
||||
//init();
|
||||
}
|
||||
|
||||
public static ProxyHelper getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (ProxyHelper.class) {
|
||||
INSTANCE = new ProxyHelper();
|
||||
}
|
||||
}
|
||||
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<>();
|
||||
try {
|
||||
if (getClass().getClassLoader().loadClass(className.concat("$$DownloadGroupListenerProxy"))
|
||||
if (getClass().getClassLoader()
|
||||
.loadClass(className.concat(TaskEnum.DOWNLOAD_GROUP.proxySuffix))
|
||||
!= null) {
|
||||
result.add(PROXY_TYPE_DOWNLOAD_GROUP);
|
||||
}
|
||||
@@ -115,7 +85,7 @@ public class ProxyHelper {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
if (getClass().getClassLoader().loadClass(className.concat("$$DownloadListenerProxy"))
|
||||
if (getClass().getClassLoader().loadClass(className.concat(TaskEnum.DOWNLOAD.proxySuffix))
|
||||
!= null) {
|
||||
result.add(PROXY_TYPE_DOWNLOAD);
|
||||
}
|
||||
@@ -124,7 +94,7 @@ public class ProxyHelper {
|
||||
}
|
||||
|
||||
try {
|
||||
if (getClass().getClassLoader().loadClass(className.concat("$$UploadListenerProxy"))
|
||||
if (getClass().getClassLoader().loadClass(className.concat(TaskEnum.UPLOAD.proxySuffix))
|
||||
!= null) {
|
||||
result.add(PROXY_TYPE_UPLOAD);
|
||||
}
|
||||
@@ -132,47 +102,28 @@ public class ProxyHelper {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
if (getClass().getClassLoader().loadClass(className.concat(TaskEnum.M3U8_PEER.proxySuffix))
|
||||
!= null) {
|
||||
result.add(PROXY_TYPE_M3U8_PEER);
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
if (getClass().getClassLoader()
|
||||
.loadClass(className.concat(TaskEnum.DOWNLOAD_GROUP_SUB.proxySuffix))
|
||||
!= null) {
|
||||
result.add(PROXY_TYPE_DOWNLOAD_GROUP_SUB);
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
|
||||
if (!result.isEmpty()) {
|
||||
mProxyCache.put(clazz.getName(), result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private void count(String className) {
|
||||
try {
|
||||
Class clazz = Class.forName(className);
|
||||
Method download = clazz.getMethod("getDownloadCounter");
|
||||
Method downloadGroup = clazz.getMethod("getDownloadGroupCounter");
|
||||
Method downloadGroupSub = clazz.getMethod("getDownloadGroupSubCounter");
|
||||
Method upload = clazz.getMethod("getUploadCounter");
|
||||
Object object = clazz.newInstance();
|
||||
Object dc = download.invoke(object);
|
||||
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) {
|
||||
e.printStackTrace();
|
||||
} catch (InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,4 +36,6 @@ public class SubThreadConfig<TASK_WRAPPER extends AbsTaskWrapper> {
|
||||
public Handler stateHandler;
|
||||
// 动态文件
|
||||
public boolean isOpenDynamicFile;
|
||||
// m3u8切片索引
|
||||
public int peerIndex;
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
package com.arialyy.aria.core.common;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import com.arialyy.aria.core.inf.IEventListener;
|
||||
@@ -62,15 +61,12 @@ public class ThreadStateManager implements IThreadState {
|
||||
case STATE_STOP:
|
||||
mStopNum++;
|
||||
if (isStop()) {
|
||||
mListener.onStop(mProgress);
|
||||
quitLooper();
|
||||
}
|
||||
break;
|
||||
case STATE_CANCEL:
|
||||
mCancelNum++;
|
||||
if (isCancel()) {
|
||||
ALog.d(TAG, "icCancel");
|
||||
mListener.onCancel();
|
||||
quitLooper();
|
||||
}
|
||||
break;
|
||||
@@ -133,7 +129,6 @@ public class ThreadStateManager implements IThreadState {
|
||||
/**
|
||||
* 所有子线程是否都已经停止
|
||||
*/
|
||||
@Override
|
||||
public boolean isStop() {
|
||||
//ALog.d(TAG,
|
||||
// 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() {
|
||||
//ALog.d(TAG, String.format("isCancel; stopNum: %s, cancelNum: %s, failNum: %s, completeNum: %s",
|
||||
// mStopNum,
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.arialyy.aria.core.common.ftp;
|
||||
|
||||
import com.arialyy.aria.core.FtpUrlEntity;
|
||||
import com.arialyy.aria.core.inf.ITaskConfig;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.Proxy;
|
||||
|
||||
/**
|
||||
@@ -39,7 +40,7 @@ public class FtpTaskConfig implements ITaskConfig {
|
||||
/**
|
||||
* 上传拦截器
|
||||
*/
|
||||
private IFtpUploadInterceptor uploadInterceptor;
|
||||
private WeakReference<IFtpUploadInterceptor> uploadInterceptor;
|
||||
|
||||
/**
|
||||
* 上传到服务器文件的新文件名{@link FtpInterceptHandler#getNewFileName()}
|
||||
@@ -55,11 +56,11 @@ public class FtpTaskConfig implements ITaskConfig {
|
||||
}
|
||||
|
||||
public IFtpUploadInterceptor getUploadInterceptor() {
|
||||
return uploadInterceptor;
|
||||
return uploadInterceptor.get();
|
||||
}
|
||||
|
||||
public void setUploadInterceptor(IFtpUploadInterceptor uploadInterceptor) {
|
||||
this.uploadInterceptor = uploadInterceptor;
|
||||
this.uploadInterceptor = new WeakReference<>(uploadInterceptor);
|
||||
}
|
||||
|
||||
public FtpUrlEntity getUrlEntity() {
|
||||
|
||||
@@ -41,7 +41,7 @@ import java.util.List;
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public class IFtpUploadInterceptor {
|
||||
public interface IFtpUploadInterceptor {
|
||||
|
||||
/**
|
||||
* 处理拦截事件
|
||||
@@ -49,7 +49,5 @@ public class IFtpUploadInterceptor {
|
||||
* @param entity 上传信息实体
|
||||
* @param fileList ftp服务器端remotePath下的文件列表
|
||||
*/
|
||||
public FtpInterceptHandler onIntercept(UploadEntity entity, List<String> fileList) {
|
||||
return null;
|
||||
}
|
||||
FtpInterceptHandler onIntercept(UploadEntity entity, List<String> fileList);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.arialyy.aria.core.common.http;
|
||||
import com.arialyy.aria.core.common.RequestEnum;
|
||||
import com.arialyy.aria.core.inf.IHttpFileLenAdapter;
|
||||
import com.arialyy.aria.core.inf.ITaskConfig;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.CookieManager;
|
||||
import java.net.Proxy;
|
||||
import java.util.HashMap;
|
||||
@@ -82,17 +83,17 @@ public class HttpTaskConfig implements ITaskConfig {
|
||||
*/
|
||||
private Map<String, String> formFields = new HashMap<>();
|
||||
|
||||
private IHttpFileLenAdapter fileLenAdapter;
|
||||
private WeakReference<IHttpFileLenAdapter> fileLenAdapter;
|
||||
|
||||
public IHttpFileLenAdapter getFileLenAdapter() {
|
||||
return fileLenAdapter;
|
||||
return fileLenAdapter.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果是匿名内部类,完成后需要将adapter设置为空,否则会出现内存泄漏
|
||||
*/
|
||||
public void setFileLenAdapter(IHttpFileLenAdapter fileLenAdapter) {
|
||||
this.fileLenAdapter = fileLenAdapter;
|
||||
this.fileLenAdapter = new WeakReference<>(fileLenAdapter);
|
||||
}
|
||||
|
||||
public Map<String, String> getFormFields() {
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
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 java.io.Serializable;
|
||||
|
||||
@@ -50,7 +52,7 @@ public class DGroupConfig extends BaseTaskConfig implements Serializable {
|
||||
|
||||
@Override public DGroupConfig setMaxSpeed(int maxSpeed) {
|
||||
super.setMaxSpeed(maxSpeed);
|
||||
DownloadGroupTaskQueue.getInstance().setMaxSpeed(maxSpeed);
|
||||
EventMsgUtil.getDefault().post(new SpeedEvent(maxSpeed));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
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 java.io.Serializable;
|
||||
|
||||
@@ -47,7 +49,7 @@ public class DownloadConfig extends BaseTaskConfig implements Serializable {
|
||||
|
||||
@Override public DownloadConfig setMaxSpeed(int maxSpeed) {
|
||||
super.setMaxSpeed(maxSpeed);
|
||||
DownloadTaskQueue.getInstance().setMaxSpeed(maxSpeed);
|
||||
EventMsgUtil.getDefault().post(new SpeedEvent(maxSpeed));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
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 java.io.Serializable;
|
||||
|
||||
@@ -28,7 +30,7 @@ public class UploadConfig extends BaseTaskConfig implements Serializable {
|
||||
|
||||
@Override public UploadConfig setMaxSpeed(int maxSpeed) {
|
||||
super.setMaxSpeed(maxSpeed);
|
||||
UploadTaskQueue.getInstance().setMaxSpeed(maxSpeed);
|
||||
EventMsgUtil.getDefault().post(new SpeedEvent(maxSpeed));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
package com.arialyy.aria.core.download;
|
||||
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
||||
import com.arialyy.aria.core.command.NormalCmdFactory;
|
||||
import com.arialyy.aria.core.event.EventMsgUtil;
|
||||
import com.arialyy.aria.core.inf.AbsTarget;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
|
||||
@@ -43,11 +43,9 @@ abstract class AbsDTarget<TARGET extends AbsDTarget> extends AbsTarget<TARGET> {
|
||||
*/
|
||||
public void setHighestPriority() {
|
||||
if (checkConfig()) {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(
|
||||
CommonUtil.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_HIGHEST_PRIORITY,
|
||||
checkTaskType()))
|
||||
.exe();
|
||||
EventMsgUtil.getDefault()
|
||||
.post(CommonUtil.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_HIGHEST_PRIORITY,
|
||||
checkTaskType()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@ package com.arialyy.aria.core.download;
|
||||
|
||||
import android.text.TextUtils;
|
||||
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.ITargetHandler;
|
||||
import com.arialyy.aria.core.inf.ITaskWrapper;
|
||||
import com.arialyy.aria.core.manager.TaskWrapperManager;
|
||||
import com.arialyy.aria.core.queue.DownloadTaskQueue;
|
||||
@@ -93,8 +93,7 @@ class DNormalConfigHandler<TARGET extends AbsDTarget> implements IConfigHandler
|
||||
}
|
||||
|
||||
@Override public boolean isRunning() {
|
||||
DownloadTask task = DownloadTaskQueue.getInstance().getTask(mEntity.getKey());
|
||||
return task != null && task.isRunning();
|
||||
return DownloadTaskQueue.getInstance().taskIsRunning(mEntity.getKey());
|
||||
}
|
||||
|
||||
@Override public boolean checkEntity() {
|
||||
@@ -113,9 +112,10 @@ class DNormalConfigHandler<TARGET extends AbsDTarget> implements IConfigHandler
|
||||
File file = new File(mTempFilePath);
|
||||
DTaskWrapper wrapper = (DTaskWrapper) mTarget.getTaskWrapper();
|
||||
// 缓存文件夹格式:问文件夹/.文件名_码率
|
||||
wrapper.asM3U8()
|
||||
.setCacheDir(String.format("%s/.%s_%s", file.getParent(), file.getName(),
|
||||
wrapper.asM3U8().getBandWidth()));
|
||||
String cacheDir = String.format("%s/.%s_%s", file.getParent(), file.getName(),
|
||||
wrapper.asM3U8().getBandWidth());
|
||||
wrapper.asM3U8().setCacheDir(cacheDir);
|
||||
mEntity.getM3U8Entity().setCacheDir(cacheDir);
|
||||
if (wrapper.getRequestType() == ITaskWrapper.M3U8_VOD) {
|
||||
if (mEntity.getFileSize() == 0) {
|
||||
ALog.w(TAG,
|
||||
|
||||
@@ -18,16 +18,16 @@ package com.arialyy.aria.core.download;
|
||||
import android.support.annotation.CheckResult;
|
||||
import android.support.annotation.NonNull;
|
||||
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.command.CancelAllCmd;
|
||||
import com.arialyy.aria.core.command.ICmd;
|
||||
import com.arialyy.aria.core.command.normal.CancelAllCmd;
|
||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
||||
import com.arialyy.aria.core.command.NormalCmdFactory;
|
||||
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.AbsReceiver;
|
||||
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.DownloadSchedulers;
|
||||
import com.arialyy.aria.orm.DbEntity;
|
||||
@@ -173,9 +173,13 @@ public class DownloadReceiver extends AbsReceiver {
|
||||
if (set != null && !set.isEmpty()) {
|
||||
for (Integer type : set) {
|
||||
if (type == ProxyHelper.PROXY_TYPE_DOWNLOAD) {
|
||||
DownloadSchedulers.getInstance().register(obj);
|
||||
DownloadSchedulers.getInstance().register(obj, TaskEnum.DOWNLOAD);
|
||||
} 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 {
|
||||
@@ -417,11 +421,9 @@ public class DownloadReceiver extends AbsReceiver {
|
||||
* 停止所有正在下载的任务,并清空等待队列。
|
||||
*/
|
||||
public void stopAllTask() {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(NormalCmdFactory.getInstance()
|
||||
.createCmd(new DTaskWrapper(null), NormalCmdFactory.TASK_STOP_ALL,
|
||||
ICmd.TASK_TYPE_DOWNLOAD))
|
||||
.exe();
|
||||
EventMsgUtil.getDefault().post(NormalCmdFactory.getInstance()
|
||||
.createCmd(new DTaskWrapper(null), NormalCmdFactory.TASK_STOP_ALL,
|
||||
ICmd.TASK_TYPE_DOWNLOAD));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -430,11 +432,9 @@ public class DownloadReceiver extends AbsReceiver {
|
||||
* 2.如果队列执行队列已经满了,则将所有任务添加到等待队列中
|
||||
*/
|
||||
public void resumeAllTask() {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(NormalCmdFactory.getInstance()
|
||||
.createCmd(new DTaskWrapper(null), NormalCmdFactory.TASK_RESUME_ALL,
|
||||
ICmd.TASK_TYPE_DOWNLOAD))
|
||||
.exe();
|
||||
EventMsgUtil.getDefault().post(NormalCmdFactory.getInstance()
|
||||
.createCmd(new DTaskWrapper(null), NormalCmdFactory.TASK_RESUME_ALL,
|
||||
ICmd.TASK_TYPE_DOWNLOAD));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -449,7 +449,8 @@ public class DownloadReceiver extends AbsReceiver {
|
||||
(CancelAllCmd) CommonUtil.createNormalCmd(new DTaskWrapper(null),
|
||||
NormalCmdFactory.TASK_CANCEL_ALL, ICmd.TASK_TYPE_DOWNLOAD);
|
||||
cancelCmd.removeFile = removeFile;
|
||||
ariaManager.setCmd(cancelCmd).exe();
|
||||
EventMsgUtil.getDefault().post(cancelCmd);
|
||||
|
||||
Set<String> keys = ariaManager.getReceiver().keySet();
|
||||
for (String key : keys) {
|
||||
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.M3U8VodUtil;
|
||||
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.ITaskWrapper;
|
||||
import com.arialyy.aria.core.scheduler.ISchedulers;
|
||||
@@ -39,7 +40,12 @@ public class DownloadTask extends AbsNormalTask<DTaskWrapper> {
|
||||
mTaskWrapper = taskWrapper;
|
||||
mOutHandler = outHandler;
|
||||
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() {
|
||||
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) {
|
||||
return new M3U8LiveUtil(mTaskWrapper, (IDownloadListener) mListener);
|
||||
return new M3U8LiveUtil(mTaskWrapper, (M3U8Listener) mListener);
|
||||
} else {
|
||||
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.download.DownloadEntity;
|
||||
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.IDownloadListener;
|
||||
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() {
|
||||
super.onPostPre();
|
||||
((IDownloadListener) mListener).onPostPre(mEntity.getFileSize());
|
||||
|
||||
@@ -111,6 +111,8 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
onThreadComplete();
|
||||
}
|
||||
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) {
|
||||
List<String> sLength = headers.get("Content-Length");
|
||||
|
||||
@@ -141,6 +141,8 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
onThreadComplete();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -97,15 +97,12 @@ public class SimpleDownloadUtil implements IUtil {
|
||||
new Thread(createInfoThread()).start();
|
||||
}
|
||||
|
||||
@Override public void setMaxSpeed(int speed) {
|
||||
mDownloader.setMaxSpeed(speed);
|
||||
}
|
||||
|
||||
private void failDownload(BaseException e, boolean needRetry) {
|
||||
if (isStop || isCancel) {
|
||||
return;
|
||||
}
|
||||
mListener.onFail(needRetry, e);
|
||||
mDownloader.onDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,12 +19,11 @@ import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import com.arialyy.aria.core.common.IUtil;
|
||||
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.DTaskWrapper;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
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() {
|
||||
if (mTimer != null && !mTimer.isShutdown()) {
|
||||
mTimer.shutdown();
|
||||
|
||||
@@ -127,10 +127,4 @@ class SubDownloadLoader implements IUtil {
|
||||
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() {
|
||||
return 2000;
|
||||
return 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,7 @@ package com.arialyy.aria.core.download.m3u8;
|
||||
* M3U8 bandWidth 码率url转换器,对于某些服务器,返回的ts地址可以是相对地址,也可能是处理过的,
|
||||
* 对于这种情况,你需要使用url转换器将地址转换为可正常访问的http地址
|
||||
*/
|
||||
public class IBandWidthUrlConverter {
|
||||
public interface IBandWidthUrlConverter {
|
||||
|
||||
/**
|
||||
* 转换码率地址为可用的http地址,对于某些服务器,返回的切片信息有可能是相对地址,也可能是处理过的,
|
||||
@@ -28,7 +28,5 @@ public class IBandWidthUrlConverter {
|
||||
* @param bandWidthUrl 原始码率地址
|
||||
* @return 可正常访问的http地址
|
||||
*/
|
||||
public String convert(String bandWidthUrl) {
|
||||
return null;
|
||||
}
|
||||
String convert(String bandWidthUrl);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ package com.arialyy.aria.core.download.m3u8;
|
||||
* M3U8 直播下载,ts url转换器,对于某些服务器,返回的ts地址可以是相对地址,也可能是处理过的
|
||||
* 对于这种情况,你需要使用url转换器将地址转换为可正常访问的http地址
|
||||
*/
|
||||
public class ILiveTsUrlConverter {
|
||||
public interface ILiveTsUrlConverter {
|
||||
|
||||
/**
|
||||
* 处理#EXTINF信息,对于某些服务器,返回的切片信息有可能是相对地址,因此,你需要自行转换为可下载http连接
|
||||
@@ -28,7 +28,5 @@ public class ILiveTsUrlConverter {
|
||||
* @param tsUrl ts文件下载地址
|
||||
* @return 转换后的http地址
|
||||
*/
|
||||
public String convert(String m3u8Url, String tsUrl) {
|
||||
return null;
|
||||
}
|
||||
public String convert(String m3u8Url, String tsUrl);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.util.List;
|
||||
/**
|
||||
* Ts文件合并处理,如果你希望使用自行处理ts文件的合并,你可以实现该接口
|
||||
*/
|
||||
public class ITsMergeHandler {
|
||||
public interface ITsMergeHandler {
|
||||
|
||||
/**
|
||||
* 合并ts文件
|
||||
@@ -30,7 +30,5 @@ public class ITsMergeHandler {
|
||||
* @param tsPath ts文件列表
|
||||
* @return {@code true} 合并成功
|
||||
*/
|
||||
public boolean merge(@Nullable M3U8KeyInfo keyInfo, List<String> tsPath) {
|
||||
return false;
|
||||
}
|
||||
boolean merge(@Nullable M3U8KeyInfo keyInfo, List<String> tsPath);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.util.List;
|
||||
* M3U8 点播文件下载,ts url转换器,对于某些服务器,返回的ts地址可以是相对地址,也可能是处理过的
|
||||
* 对于这种情况,你需要使用url转换器将地址转换为可正常访问的http地址
|
||||
*/
|
||||
public class IVodTsUrlConverter {
|
||||
public interface IVodTsUrlConverter {
|
||||
|
||||
/**
|
||||
* 处理#EXTINF信息,对于某些服务器,返回的切片信息有可能是相对地址,因此,你需要自行转换为可下载http连接
|
||||
@@ -30,7 +30,5 @@ public class IVodTsUrlConverter {
|
||||
* @param tsUrls ts文件下载地址列表
|
||||
* @return 根据切片信息转换后的http连接列表,如果你的切片信息是可以直接下载的http连接,直接返回extInf便可
|
||||
*/
|
||||
public List<String> convert(String m3u8Url, List<String> tsUrls) {
|
||||
return null;
|
||||
}
|
||||
List<String> convert(String m3u8Url, List<String> tsUrls);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,16 @@ package com.arialyy.aria.core.download.m3u8;
|
||||
|
||||
import android.os.Parcel;
|
||||
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.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实体信息
|
||||
@@ -44,10 +53,85 @@ public class M3U8Entity extends DbEntity implements Parcelable {
|
||||
*/
|
||||
private boolean isLive;
|
||||
|
||||
/**
|
||||
* 缓存目录
|
||||
*/
|
||||
private String cacheDir;
|
||||
|
||||
public boolean 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) {
|
||||
isLive = live;
|
||||
}
|
||||
@@ -88,6 +172,7 @@ public class M3U8Entity extends DbEntity implements Parcelable {
|
||||
dest.writeInt(this.peerIndex);
|
||||
dest.writeInt(this.peerNum);
|
||||
dest.writeByte(this.isLive ? (byte) 1 : (byte) 0);
|
||||
dest.writeString(this.cacheDir);
|
||||
}
|
||||
|
||||
protected M3U8Entity(Parcel in) {
|
||||
@@ -95,6 +180,7 @@ public class M3U8Entity extends DbEntity implements Parcelable {
|
||||
this.peerIndex = in.readInt();
|
||||
this.peerNum = in.readInt();
|
||||
this.isLive = in.readByte() != 0;
|
||||
this.cacheDir = in.readString();
|
||||
}
|
||||
|
||||
public static final Creator<M3U8Entity> CREATOR = new Creator<M3U8Entity>() {
|
||||
@@ -106,4 +192,14 @@ public class M3U8Entity extends DbEntity implements Parcelable {
|
||||
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();
|
||||
handleConnect(conn);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
failDownload(e.getMessage(), false);
|
||||
} finally {
|
||||
if (conn != null) {
|
||||
conn.disconnect();
|
||||
@@ -147,7 +147,7 @@ final class M3U8InfoThread implements Runnable {
|
||||
failDownload(String.format("获取M3U8下载地址列表失败,url: %s", mEntity.getUrl()), false);
|
||||
return;
|
||||
}
|
||||
if (!isLive && mEntity.getM3U8Entity().getPeerNum() != 0) {
|
||||
if (!isLive && mEntity.getM3U8Entity().getPeerNum() == 0) {
|
||||
mEntity.getM3U8Entity().setPeerNum(extInf.size());
|
||||
mEntity.getM3U8Entity().update();
|
||||
}
|
||||
@@ -257,6 +257,8 @@ final class M3U8InfoThread implements Runnable {
|
||||
failDownload(String.format("码率转换器转换后的url地址无效,转换后的url:%s", bandWidthM3u8Url), false);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
ALog.d(TAG, "没有设置码率转换器");
|
||||
}
|
||||
mTaskWrapper.asM3U8().setBandWidthUrl(bandWidthM3u8Url);
|
||||
ALog.d(TAG, String.format("新码率url:%s", bandWidthM3u8Url));
|
||||
|
||||
@@ -99,10 +99,6 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
|
||||
}).start();
|
||||
}
|
||||
|
||||
@Override protected void setMaxSpeed(int maxSpeed) {
|
||||
// TODO: 2019-06-06 暂不支持
|
||||
}
|
||||
|
||||
private void notifyLock() {
|
||||
try {
|
||||
LOCK.lock();
|
||||
@@ -227,16 +223,14 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
|
||||
@Override public boolean handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case STATE_STOP:
|
||||
if (isStop()) {
|
||||
if (isBreak()) {
|
||||
ALog.d(TAG, "任务停止");
|
||||
mListener.onStop(mProgress);
|
||||
quitLooper();
|
||||
}
|
||||
break;
|
||||
case STATE_CANCEL:
|
||||
if (isCancel()) {
|
||||
if (isBreak()) {
|
||||
ALog.d(TAG, "任务取消");
|
||||
mListener.onCancel();
|
||||
quitLooper();
|
||||
}
|
||||
break;
|
||||
@@ -250,10 +244,6 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override public boolean isStop() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override public boolean isFail() {
|
||||
return false;
|
||||
}
|
||||
@@ -262,10 +252,6 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override public boolean isCancel() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override public long getCurrentProgress() {
|
||||
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;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -30,7 +31,7 @@ public class M3U8TaskConfig {
|
||||
/**
|
||||
* #EXTINF 标签信息处理器
|
||||
*/
|
||||
private IVodTsUrlConverter vodUrlConverter;
|
||||
private WeakReference<IVodTsUrlConverter> vodUrlConverter;
|
||||
|
||||
/**
|
||||
* 缓存目录
|
||||
@@ -45,7 +46,7 @@ public class M3U8TaskConfig {
|
||||
/**
|
||||
* 合并处理器
|
||||
*/
|
||||
private ITsMergeHandler mergeHandler;
|
||||
private WeakReference<ITsMergeHandler> mergeHandler;
|
||||
|
||||
/**
|
||||
* 已完成的ts分片数量
|
||||
@@ -65,7 +66,7 @@ public class M3U8TaskConfig {
|
||||
/**
|
||||
* 码率url转换器
|
||||
*/
|
||||
private IBandWidthUrlConverter bandWidthUrlConverter;
|
||||
private WeakReference<IBandWidthUrlConverter> bandWidthUrlConverter;
|
||||
|
||||
/**
|
||||
* 码率地址
|
||||
@@ -80,7 +81,7 @@ public class M3U8TaskConfig {
|
||||
/**
|
||||
* 直播下载,ts url转换器
|
||||
*/
|
||||
private ILiveTsUrlConverter liveTsUrlConverter;
|
||||
private WeakReference<ILiveTsUrlConverter> liveTsUrlConverter;
|
||||
|
||||
/**
|
||||
* 直播的m3u8文件更新间隔
|
||||
@@ -92,6 +93,19 @@ public class M3U8TaskConfig {
|
||||
*/
|
||||
private int maxTsQueueNum = 4;
|
||||
|
||||
/**
|
||||
* 指定的索引位置
|
||||
*/
|
||||
private int jumpIndex;
|
||||
|
||||
public int getJumpIndex() {
|
||||
return jumpIndex;
|
||||
}
|
||||
|
||||
public void setJumpIndex(int jumpIndex) {
|
||||
this.jumpIndex = jumpIndex;
|
||||
}
|
||||
|
||||
public int getMaxTsQueueNum() {
|
||||
return maxTsQueueNum;
|
||||
}
|
||||
@@ -109,12 +123,11 @@ public class M3U8TaskConfig {
|
||||
}
|
||||
|
||||
public ILiveTsUrlConverter getLiveTsUrlConverter() {
|
||||
return liveTsUrlConverter;
|
||||
return liveTsUrlConverter.get();
|
||||
}
|
||||
|
||||
public void setLiveTsUrlConverter(
|
||||
ILiveTsUrlConverter liveTsUrlConverter) {
|
||||
this.liveTsUrlConverter = liveTsUrlConverter;
|
||||
public void setLiveTsUrlConverter(ILiveTsUrlConverter liveTsUrlConverter) {
|
||||
this.liveTsUrlConverter = new WeakReference<>(liveTsUrlConverter);
|
||||
}
|
||||
|
||||
public M3U8KeyInfo getKeyInfo() {
|
||||
@@ -134,12 +147,11 @@ public class M3U8TaskConfig {
|
||||
}
|
||||
|
||||
public IBandWidthUrlConverter getBandWidthUrlConverter() {
|
||||
return bandWidthUrlConverter;
|
||||
return bandWidthUrlConverter.get();
|
||||
}
|
||||
|
||||
public void setBandWidthUrlConverter(
|
||||
IBandWidthUrlConverter bandWidthUrlConverter) {
|
||||
this.bandWidthUrlConverter = bandWidthUrlConverter;
|
||||
public void setBandWidthUrlConverter(IBandWidthUrlConverter bandWidthUrlConverter) {
|
||||
this.bandWidthUrlConverter = new WeakReference<>(bandWidthUrlConverter);
|
||||
}
|
||||
|
||||
public int getBandWidth() {
|
||||
@@ -175,19 +187,19 @@ public class M3U8TaskConfig {
|
||||
}
|
||||
|
||||
public ITsMergeHandler getMergeHandler() {
|
||||
return mergeHandler;
|
||||
return mergeHandler.get();
|
||||
}
|
||||
|
||||
public void setMergeHandler(ITsMergeHandler mergeHandler) {
|
||||
this.mergeHandler = mergeHandler;
|
||||
this.mergeHandler = new WeakReference<>(mergeHandler);
|
||||
}
|
||||
|
||||
public IVodTsUrlConverter getVodUrlConverter() {
|
||||
return vodUrlConverter;
|
||||
return vodUrlConverter.get();
|
||||
}
|
||||
|
||||
public void setVodUrlConverter(IVodTsUrlConverter vodUrlConverter) {
|
||||
this.vodUrlConverter = vodUrlConverter;
|
||||
this.vodUrlConverter = new WeakReference<>(vodUrlConverter);
|
||||
}
|
||||
|
||||
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.TaskException;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -40,7 +39,6 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -48,7 +46,7 @@ import java.util.Set;
|
||||
* Created by lyy on 2017/1/18. 下载线程
|
||||
*/
|
||||
final class M3U8ThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
private final String TAG = "HttpThreadTask";
|
||||
private final String TAG = "M3U8ThreadTask";
|
||||
|
||||
M3U8ThreadTask(SubThreadConfig<DTaskWrapper> config) {
|
||||
super(config);
|
||||
@@ -75,9 +73,6 @@ final class M3U8ThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
conn.setChunkedStreamingMode(0);
|
||||
}
|
||||
conn.connect();
|
||||
//Map<String, List<String>> header = conn.getHeaderFields();
|
||||
//int code = conn.getResponseCode();
|
||||
//String msg = conn.getResponseMessage();
|
||||
// 传递参数
|
||||
if (taskDelegate.getRequestEnum() == RequestEnum.POST) {
|
||||
Map<String, String> params = taskDelegate.getParams();
|
||||
@@ -125,6 +120,7 @@ final class M3U8ThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
onThreadComplete();
|
||||
}
|
||||
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.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.AbsTaskWrapper;
|
||||
import com.arialyy.aria.core.queue.DownloadTaskQueue;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
|
||||
/**
|
||||
@@ -60,4 +63,48 @@ public class M3U8VodDelegate<TARGET extends AbsTarget> extends BaseDelegate<TARG
|
||||
mTaskWrapper.asM3U8().setMaxTsQueueNum(num);
|
||||
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.Looper;
|
||||
import android.os.Message;
|
||||
import android.util.SparseArray;
|
||||
import com.arialyy.aria.core.common.AbsThreadTask;
|
||||
import com.arialyy.aria.core.common.IThreadState;
|
||||
import com.arialyy.aria.core.common.SubThreadConfig;
|
||||
import com.arialyy.aria.core.common.TaskRecord;
|
||||
import com.arialyy.aria.core.common.ThreadRecord;
|
||||
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.manager.ThreadTaskManager;
|
||||
import com.arialyy.aria.core.scheduler.ISchedulers;
|
||||
import com.arialyy.aria.exception.BaseException;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import com.arialyy.aria.util.FileUtil;
|
||||
import com.arialyy.aria.util.IdGenerator;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
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.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 ArrayBlockingQueue<Long> mFlagQueue;
|
||||
private VodStateManager mManager;
|
||||
private ArrayBlockingQueue<TempFlag> mFlagQueue;
|
||||
private ArrayBlockingQueue<PeerIndexEvent> mJumpQueue;
|
||||
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);
|
||||
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) {
|
||||
@@ -64,55 +90,299 @@ public class M3U8VodLoader extends BaseM3U8Loader {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
new Thread(new Runnable() {
|
||||
@Override protected void onPostPre() {
|
||||
super.onPostPre();
|
||||
initData();
|
||||
}
|
||||
|
||||
@Override public boolean isBreak() {
|
||||
return super.isBreak() || isDestroy;
|
||||
}
|
||||
|
||||
@Override protected void handleTask() {
|
||||
Thread th = new Thread(new Runnable() {
|
||||
@Override public void run() {
|
||||
int index = 0;
|
||||
String cacheDir = getCacheDir();
|
||||
while (!isBreak()) {
|
||||
try {
|
||||
LOCK.lock();
|
||||
while (mFlagQueue.size() < EXEC_MAX_NUM) {
|
||||
if (index == mRecord.threadRecords.size()) {
|
||||
break;
|
||||
}
|
||||
ThreadRecord tr = mRecord.threadRecords.get(index);
|
||||
index++;
|
||||
if (tr.isComplete) {
|
||||
continue;
|
||||
}
|
||||
|
||||
M3U8ThreadTask task = createThreadTask(cacheDir, tr);
|
||||
getTaskList().put(tr.threadId, task);
|
||||
mEntity.getM3U8Entity().setPeerIndex(index);
|
||||
mFlagQueue.offer(startThreadTask(task, index));
|
||||
}
|
||||
if (mFlagQueue.size() > 0) {
|
||||
mCondition.await();
|
||||
JUMP_LOCK.lock();
|
||||
if (isJump) {
|
||||
mJumpCondition.await(5, TimeUnit.SECONDS);
|
||||
isJump = false;
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
JUMP_LOCK.unlock();
|
||||
}
|
||||
|
||||
try {
|
||||
LOCK.lock();
|
||||
while (mFlagQueue.size() < EXEC_MAX_NUM && !isBreak()) {
|
||||
if (mCompleteNum == mRecord.threadRecords.size()) {
|
||||
break;
|
||||
}
|
||||
|
||||
ThreadRecord tr = getThreadRecord();
|
||||
if (tr == null || tr.isComplete) {
|
||||
ALog.d(TAG, "记录为空或记录已完成");
|
||||
break;
|
||||
}
|
||||
addTaskToQueue(tr);
|
||||
}
|
||||
if (mFlagQueue.size() > 0) {
|
||||
mWaitCondition.await();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
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 {
|
||||
LOCK.lock();
|
||||
long id = mFlagQueue.take();
|
||||
ALog.d(TAG, String.format("线程【%s】完成", id));
|
||||
mCondition.signalAll();
|
||||
} catch (InterruptedException e) {
|
||||
if (isComplete) {
|
||||
TempFlag flag = mFlagQueue.poll(1, TimeUnit.SECONDS);
|
||||
if (flag != null) {
|
||||
ALog.d(TAG, String.format("切片【%s】完成", flag.threadId));
|
||||
}
|
||||
}
|
||||
mWaitCondition.signalAll();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
LOCK.unlock();
|
||||
@@ -124,15 +394,24 @@ public class M3U8VodLoader extends BaseM3U8Loader {
|
||||
*
|
||||
* @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);
|
||||
return peerIndex;
|
||||
getListener().onPeerStart(mTaskWrapper.getKey(), task.getConfig().tempFile.getPath(),
|
||||
peerIndex);
|
||||
TempFlag flag = new TempFlag();
|
||||
flag.threadTask = task;
|
||||
flag.threadId = peerIndex;
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置config
|
||||
*/
|
||||
private M3U8ThreadTask createThreadTask(String cacheDir, ThreadRecord record) {
|
||||
private M3U8ThreadTask createThreadTask(String cacheDir, ThreadRecord record, int index) {
|
||||
SubThreadConfig<DTaskWrapper> config = new SubThreadConfig<>();
|
||||
config.url = record.tsUrl;
|
||||
config.tempFile = new File(getTsFilePath(cacheDir, record.threadId));
|
||||
@@ -141,6 +420,7 @@ public class M3U8VodLoader extends BaseM3U8Loader {
|
||||
config.taskWrapper = mTaskWrapper;
|
||||
config.record = record;
|
||||
config.stateHandler = mStateHandler;
|
||||
config.peerIndex = index;
|
||||
if (!config.tempFile.exists()) {
|
||||
CommonUtil.createFile(config.tempFile.getPath());
|
||||
}
|
||||
@@ -156,29 +436,34 @@ public class M3U8VodLoader extends BaseM3U8Loader {
|
||||
/**
|
||||
* 任务状态回调
|
||||
*/
|
||||
private IEventListener mListener;
|
||||
private int mStartThreadNum; // 启动的线程总数
|
||||
private int mCancelNum = 0; // 已经取消的线程的数
|
||||
private int mStopNum = 0; // 已经停止的线程数
|
||||
private int mFailNum = 0; // 失败的线程数
|
||||
private int mCompleteNum = 0; // 完成的线程数
|
||||
private long mProgress; //当前总进度
|
||||
private TaskRecord mTaskRecord; // 任务记录
|
||||
private Looper mLooper;
|
||||
private IEventListener listener;
|
||||
private int startThreadNum; // 启动的线程总数
|
||||
private int cancelNum = 0; // 已经取消的线程的数
|
||||
private int stopNum = 0; // 已经停止的线程数
|
||||
private int failNum = 0; // 失败的线程数
|
||||
private long progress; //当前总进度
|
||||
private TaskRecord taskRecord; // 任务记录
|
||||
private Looper looper;
|
||||
|
||||
/**
|
||||
* @param taskRecord 任务记录
|
||||
* @param listener 任务事件
|
||||
*/
|
||||
VodStateManager(Looper looper, TaskRecord taskRecord, IEventListener listener) {
|
||||
mLooper = looper;
|
||||
mTaskRecord = taskRecord;
|
||||
this.looper = looper;
|
||||
this.taskRecord = taskRecord;
|
||||
for (ThreadRecord record : taskRecord.threadRecords) {
|
||||
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() {
|
||||
ALog.d(TAG, "quitLooper");
|
||||
mLooper.quit();
|
||||
looper.quit();
|
||||
}
|
||||
|
||||
@Override public boolean handleMessage(Message msg) {
|
||||
int peerIndex = msg.getData().getInt(ISchedulers.DATA_M3U8_PEER_INDEX);
|
||||
switch (msg.what) {
|
||||
case STATE_STOP:
|
||||
mStopNum++;
|
||||
ThreadTaskManager.getInstance().removeSingleTaskThread(mTaskWrapper.getKey(),
|
||||
(AbsThreadTask) msg.obj);
|
||||
if (isStop()) {
|
||||
stopNum++;
|
||||
removeSignThread((AbsThreadTask) msg.obj);
|
||||
// 处理跳转位置后,恢复任务
|
||||
if (isJump && (stopNum == mCurrentFlagSize || mCurrentFlagSize == 0) && !isBreak()) {
|
||||
resumeTask();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isBreak()) {
|
||||
ALog.d(TAG, String.format("vod任务【%s】停止", mTempFile.getName()));
|
||||
mListener.onStop(mProgress);
|
||||
quitLooper();
|
||||
}
|
||||
break;
|
||||
case STATE_CANCEL:
|
||||
mCancelNum++;
|
||||
ThreadTaskManager.getInstance().removeSingleTaskThread(mTaskWrapper.getKey(),
|
||||
(AbsThreadTask) msg.obj);
|
||||
if (isCancel()) {
|
||||
cancelNum++;
|
||||
removeSignThread((AbsThreadTask) msg.obj);
|
||||
|
||||
if (isBreak()) {
|
||||
ALog.d(TAG, String.format("vod任务【%s】取消", mTempFile.getName()));
|
||||
mListener.onCancel();
|
||||
quitLooper();
|
||||
}
|
||||
break;
|
||||
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()) {
|
||||
ALog.d(TAG, String.format("vod任务【%s】失败", mTempFile.getName()));
|
||||
Bundle b = msg.getData();
|
||||
mListener.onFail(b.getBoolean(KEY_RETRY, true),
|
||||
listener.onFail(b.getBoolean(KEY_RETRY, true),
|
||||
(BaseException) b.getSerializable(KEY_ERROR_INFO));
|
||||
quitLooper();
|
||||
}
|
||||
break;
|
||||
case STATE_COMPLETE:
|
||||
if (isBreak()) {
|
||||
quitLooper();
|
||||
}
|
||||
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();
|
||||
notifyLock();
|
||||
if (!isJump) {
|
||||
notifyWaitLock(true);
|
||||
}
|
||||
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 (mergeFile()) {
|
||||
mListener.onComplete();
|
||||
listener.onComplete();
|
||||
} else {
|
||||
mListener.onFail(false, null);
|
||||
listener.onFail(false, null);
|
||||
}
|
||||
} else {
|
||||
mListener.onComplete();
|
||||
listener.onComplete();
|
||||
}
|
||||
quitLooper();
|
||||
}
|
||||
break;
|
||||
case STATE_RUNNING:
|
||||
mProgress += (long) msg.obj;
|
||||
progress += (long) msg.obj;
|
||||
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();
|
||||
completeNum++;
|
||||
mTaskWrapper.asM3U8().setCompleteNum(completeNum);
|
||||
int percent = completeNum * 100 / mTaskRecord.threadRecords.size();
|
||||
int percent = completeNum * 100 / taskRecord.threadRecords.size();
|
||||
mEntity.setPercent(percent);
|
||||
mEntity.update();
|
||||
}
|
||||
|
||||
@Override public boolean isStop() {
|
||||
printInfo("isStop");
|
||||
return mStopNum == mFlagQueue.size();
|
||||
}
|
||||
|
||||
@Override public boolean isFail() {
|
||||
printInfo("isFail");
|
||||
return mFailNum == mFlagQueue.size();
|
||||
return failNum != 0 && failNum == mFlagQueue.size() && !isJump;
|
||||
}
|
||||
|
||||
@Override public boolean isComplete() {
|
||||
printInfo("isComplete");
|
||||
return mStartThreadNum == mCompleteNum;
|
||||
}
|
||||
|
||||
@Override public boolean isCancel() {
|
||||
printInfo("isCancel");
|
||||
return mCancelNum == mFlagQueue.size();
|
||||
return mCompleteNum == taskRecord.threadRecords.size() && !isJump;
|
||||
}
|
||||
|
||||
@Override public long getCurrentProgress() {
|
||||
return mProgress;
|
||||
return progress;
|
||||
}
|
||||
|
||||
private void printInfo(String tag) {
|
||||
if (false) {
|
||||
ALog.d(tag, String.format(
|
||||
"startThreadNum = %s, stopNum = %s, cancelNum = %s, failNum = %s, completeNum = %s",
|
||||
mStartThreadNum, mStopNum, mCancelNum, mFailNum, mCompleteNum));
|
||||
"startThreadNum = %s, stopNum = %s, cancelNum = %s, failNum = %s, completeNum = %s, flagQueueSize = %s",
|
||||
startThreadNum, stopNum, cancelNum, failNum, mCompleteNum, mFlagQueue.size()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,19 +613,19 @@ public class M3U8VodLoader extends BaseM3U8Loader {
|
||||
ITsMergeHandler mergeHandler = mTaskWrapper.asM3U8().getMergeHandler();
|
||||
String cacheDir = getCacheDir();
|
||||
List<String> partPath = new ArrayList<>();
|
||||
for (ThreadRecord tr : mTaskRecord.threadRecords) {
|
||||
for (ThreadRecord tr : taskRecord.threadRecords) {
|
||||
partPath.add(getTsFilePath(cacheDir, tr.threadId));
|
||||
}
|
||||
boolean isSuccess;
|
||||
if (mergeHandler != null) {
|
||||
isSuccess = mergeHandler.merge(mTaskWrapper.asM3U8().getKeyInfo(), partPath);
|
||||
} else {
|
||||
isSuccess = FileUtil.mergeFile(mTaskRecord.filePath, partPath);
|
||||
isSuccess = FileUtil.mergeFile(taskRecord.filePath, partPath);
|
||||
}
|
||||
if (isSuccess) {
|
||||
// 合并成功,删除缓存文件
|
||||
for (String pp : partPath) {
|
||||
File f = new File(pp);
|
||||
File[] files = new File(cacheDir).listFiles();
|
||||
for (File f : files) {
|
||||
if (f.exists()) {
|
||||
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.OnFileInfoCallback;
|
||||
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.IDownloadListener;
|
||||
import com.arialyy.aria.exception.BaseException;
|
||||
import com.arialyy.aria.exception.M3U8Exception;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -40,12 +41,12 @@ public class M3U8VodUtil implements IUtil {
|
||||
private final String TAG = "M3U8DownloadUtil";
|
||||
|
||||
private DTaskWrapper mWrapper;
|
||||
private IDownloadListener mListener;
|
||||
private M3U8Listener mListener;
|
||||
private boolean isStop = false, isCancel = false;
|
||||
private List<String> mUrls = new ArrayList<>();
|
||||
private M3U8VodLoader mLoader;
|
||||
|
||||
public M3U8VodUtil(DTaskWrapper wrapper, IDownloadListener listener) {
|
||||
public M3U8VodUtil(DTaskWrapper wrapper, M3U8Listener listener) {
|
||||
mWrapper = wrapper;
|
||||
mListener = listener;
|
||||
mLoader = new M3U8VodLoader(mListener, mWrapper);
|
||||
@@ -85,10 +86,6 @@ public class M3U8VodUtil implements IUtil {
|
||||
getVodInfo();
|
||||
}
|
||||
|
||||
@Override public void setMaxSpeed(int speed) {
|
||||
mLoader.setMaxSpeed(speed);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取点播文件信息
|
||||
*/
|
||||
@@ -114,7 +111,13 @@ public class M3U8VodUtil implements IUtil {
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
@@ -129,5 +132,6 @@ public class M3U8VodUtil implements IUtil {
|
||||
return;
|
||||
}
|
||||
mListener.onFail(needRetry, e);
|
||||
mLoader.onDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
30
Aria/src/main/java/com/arialyy/aria/core/event/Event.java
Normal file
30
Aria/src/main/java/com/arialyy/aria/core/event/Event.java
Normal file
@@ -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
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.scheduler;
|
||||
|
||||
import com.arialyy.aria.core.inf.ITask;
|
||||
package com.arialyy.aria.core.event;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2017/4/5.
|
||||
* 事件消息信息
|
||||
*/
|
||||
public interface IDownloadSchedulerListener<TASK extends ITask> extends ISchedulerListener<TASK> {
|
||||
class EventMethodInfo {
|
||||
|
||||
/**
|
||||
* 支持断点的回调
|
||||
* 被{@link Event}注解的事件方法
|
||||
*/
|
||||
public void onNoSupportBreakPoint(TASK task);
|
||||
String methodName;
|
||||
|
||||
/**
|
||||
* 该方法对应的参数类型
|
||||
*/
|
||||
Class<?> param;
|
||||
}
|
||||
153
Aria/src/main/java/com/arialyy/aria/core/event/EventMsgUtil.java
Normal file
153
Aria/src/main/java/com/arialyy/aria/core/event/EventMsgUtil.java
Normal file
@@ -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.support.annotation.CheckResult;
|
||||
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.normal.CancelCmd;
|
||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
||||
import com.arialyy.aria.core.command.normal.ReStartCmd;
|
||||
import com.arialyy.aria.core.command.NormalCmdFactory;
|
||||
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.DownloadGroupEntity;
|
||||
import com.arialyy.aria.core.event.EventMsgUtil;
|
||||
import com.arialyy.aria.core.manager.TaskWrapperManager;
|
||||
import com.arialyy.aria.core.scheduler.DownloadGroupSchedulers;
|
||||
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.CommonUtil;
|
||||
import com.arialyy.aria.util.RecordUtil;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/7/3.
|
||||
@@ -81,7 +78,8 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
|
||||
if (mEntity instanceof AbsNormalEntity) {
|
||||
RecordUtil.delTaskRecord((AbsNormalEntity) mEntity, mTaskWrapper.isRemoveFile());
|
||||
} else if (mEntity instanceof DownloadGroupEntity) {
|
||||
RecordUtil.delGroupTaskRecord(((DownloadGroupEntity) mEntity), mTaskWrapper.isRemoveFile(), true);
|
||||
RecordUtil.delGroupTaskRecord(((DownloadGroupEntity) mEntity), mTaskWrapper.isRemoveFile(),
|
||||
true);
|
||||
}
|
||||
TaskWrapperManager.getInstance().removeTaskWrapper(mEntity.getKey());
|
||||
}
|
||||
@@ -272,10 +270,9 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
|
||||
*/
|
||||
@Override public void add() {
|
||||
if (checkConfig()) {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(CommonUtil.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_CREATE,
|
||||
checkTaskType()))
|
||||
.exe();
|
||||
EventMsgUtil.getDefault()
|
||||
.post(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_CREATE,
|
||||
checkTaskType()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,11 +281,9 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
|
||||
*/
|
||||
@Override public void start() {
|
||||
if (checkConfig()) {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(
|
||||
CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START,
|
||||
checkTaskType()))
|
||||
.exe();
|
||||
EventMsgUtil.getDefault()
|
||||
.post(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START,
|
||||
checkTaskType()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,17 +293,14 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
|
||||
* @see #stop()
|
||||
*/
|
||||
@Deprecated public void pause() {
|
||||
if (checkConfig()) {
|
||||
stop();
|
||||
}
|
||||
stop();
|
||||
}
|
||||
|
||||
@Override public void stop() {
|
||||
if (checkConfig()) {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(
|
||||
CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_STOP, checkTaskType()))
|
||||
.exe();
|
||||
EventMsgUtil.getDefault()
|
||||
.post(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_STOP,
|
||||
checkTaskType()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,11 +309,9 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
|
||||
*/
|
||||
@Override public void resume() {
|
||||
if (checkConfig()) {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(
|
||||
CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START,
|
||||
checkTaskType()))
|
||||
.exe();
|
||||
EventMsgUtil.getDefault()
|
||||
.post(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START,
|
||||
checkTaskType()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,10 +320,9 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
|
||||
*/
|
||||
@Override public void cancel() {
|
||||
if (checkConfig()) {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_CANCEL,
|
||||
checkTaskType()))
|
||||
.exe();
|
||||
EventMsgUtil.getDefault()
|
||||
.post(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_CANCEL,
|
||||
checkTaskType()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,12 +331,11 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
|
||||
*/
|
||||
@Override public void reTry() {
|
||||
if (checkConfig()) {
|
||||
List<ICmd> cmds = new ArrayList<>();
|
||||
int taskType = checkTaskType();
|
||||
cmds.add(
|
||||
CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_STOP, taskType));
|
||||
cmds.add(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START, taskType));
|
||||
AriaManager.getInstance(AriaManager.APP).setCmds(cmds).exe();
|
||||
EventMsgUtil.getDefault()
|
||||
.post(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_STOP, taskType));
|
||||
EventMsgUtil.getDefault()
|
||||
.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,
|
||||
checkTaskType());
|
||||
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() {
|
||||
if (checkConfig()) {
|
||||
ReStartCmd cmd =
|
||||
(ReStartCmd) CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_RESTART,
|
||||
checkTaskType());
|
||||
AriaManager.getInstance(AriaManager.APP).setCmd(cmd).exe();
|
||||
EventMsgUtil.getDefault()
|
||||
.post(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_RESTART,
|
||||
checkTaskType()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -100,17 +100,6 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
|
||||
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) {
|
||||
isStop = true;
|
||||
mSchedulerType = type;
|
||||
if (getUtil().isRunning()) {
|
||||
getUtil().stop();
|
||||
} else {
|
||||
ALog.d(TAG, "下载任务未执行");
|
||||
mListener.onStop(mTaskWrapper.getEntity().getCurrentProgress());
|
||||
}
|
||||
getUtil().stop();
|
||||
}
|
||||
|
||||
@Override public void cancel() {
|
||||
@@ -230,11 +214,7 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
|
||||
@Override public void cancel(@TaskSchedulerType int type) {
|
||||
isCancel = true;
|
||||
mSchedulerType = type;
|
||||
if (!getUtil().isRunning()) {
|
||||
mListener.onCancel();
|
||||
} else {
|
||||
getUtil().cancel();
|
||||
}
|
||||
getUtil().cancel();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,7 +23,7 @@ import java.util.Map;
|
||||
/**
|
||||
* Http文件长度适配器
|
||||
*/
|
||||
public class IHttpFileLenAdapter implements Serializable {
|
||||
public interface IHttpFileLenAdapter extends Serializable {
|
||||
long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
@@ -32,7 +32,5 @@ public class IHttpFileLenAdapter implements Serializable {
|
||||
* @param headers header参数{@link URLConnection#getHeaderFields()}
|
||||
* @return 文件长度
|
||||
*/
|
||||
public long handleFileLen(Map<String, List<String>> headers) {
|
||||
return 0;
|
||||
}
|
||||
long handleFileLen(Map<String, List<String>> headers);
|
||||
}
|
||||
|
||||
@@ -41,10 +41,14 @@ public interface ITask<TASK_WRAPPER extends AbsTaskWrapper> {
|
||||
* 组合任务的子任务
|
||||
*/
|
||||
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.setGroupChild(false);
|
||||
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()) {
|
||||
TaskRecord record =
|
||||
@@ -91,7 +91,7 @@ class DTaskWrapperFactory implements INormalTEFactory<DownloadEntity, DTaskWrapp
|
||||
if (count == record.threadNum) {
|
||||
resetEntity(entity);
|
||||
}
|
||||
} else if (!file.exists()) { // 非分块文件需要判断文件是否存在
|
||||
} else if (!file.exists() && record.taskType != TaskRecord.TYPE_M3U8_VOD) { // 非分块文件需要判断文件是否存在
|
||||
resetEntity(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
package com.arialyy.aria.core.manager;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.command.group.GroupCmdFactory;
|
||||
import com.arialyy.aria.core.command.GroupCmdFactory;
|
||||
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.CommonUtil;
|
||||
import java.util.List;
|
||||
@@ -44,10 +44,9 @@ public class SubTaskManager {
|
||||
*/
|
||||
public void startSubTask(String url) {
|
||||
if (checkUrl(url)) {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(
|
||||
CommonUtil.createGroupCmd(mTargetName, mEntity, GroupCmdFactory.SUB_TASK_START, url))
|
||||
.exe();
|
||||
EventMsgUtil.getDefault()
|
||||
.post(
|
||||
CommonUtil.createGroupCmd(mTargetName, mEntity, GroupCmdFactory.SUB_TASK_START, url));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,10 +57,9 @@ public class SubTaskManager {
|
||||
*/
|
||||
public void stopSubTask(String url) {
|
||||
if (checkUrl(url)) {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(
|
||||
CommonUtil.createGroupCmd(mTargetName, mEntity, GroupCmdFactory.SUB_TASK_STOP, url))
|
||||
.exe();
|
||||
EventMsgUtil.getDefault()
|
||||
.post(
|
||||
CommonUtil.createGroupCmd(mTargetName, mEntity, GroupCmdFactory.SUB_TASK_STOP, url));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ import com.arialyy.aria.core.inf.AbsTask;
|
||||
import com.arialyy.aria.core.inf.AbsTaskWrapper;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -112,7 +111,7 @@ public class ThreadTaskManager {
|
||||
if (container.future.isDone() || container.future.isCancelled()) {
|
||||
continue;
|
||||
}
|
||||
container.threadTask.setInterrupted(true);
|
||||
container.threadTask.destroy();
|
||||
}
|
||||
temp.clear();
|
||||
}
|
||||
@@ -130,16 +129,16 @@ public class ThreadTaskManager {
|
||||
* @param key 任务的key
|
||||
* @param task 线程任务
|
||||
*/
|
||||
public void removeSingleTaskThread(String key, AbsThreadTask task) {
|
||||
public boolean removeSingleTaskThread(String key, AbsThreadTask task) {
|
||||
try {
|
||||
LOCK.tryLock(2, TimeUnit.SECONDS);
|
||||
if (mExePool.isShutdown()) {
|
||||
ALog.e(TAG, "线程池已经关闭");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if (task == null) {
|
||||
ALog.e(TAG, "线程任务为空");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
key = getKey(key);
|
||||
Set<FutureContainer> temp = mThreadTasks.get(key);
|
||||
@@ -152,8 +151,9 @@ public class ThreadTaskManager {
|
||||
}
|
||||
}
|
||||
if (tempC != null) {
|
||||
task.setInterrupted(true);
|
||||
task.destroy();
|
||||
temp.remove(tempC);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@@ -161,6 +161,7 @@ public class ThreadTaskManager {
|
||||
} finally {
|
||||
LOCK.unlock();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,7 +177,7 @@ public class ThreadTaskManager {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (task == null || task.isInterrupted()) {
|
||||
if (task == null || task.isDestroy()) {
|
||||
ALog.e(TAG, "线程为空或线程已经中断");
|
||||
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.TaskSchedulerType;
|
||||
import com.arialyy.aria.core.manager.TaskWrapperManager;
|
||||
import com.arialyy.aria.core.manager.ThreadTaskManager;
|
||||
import com.arialyy.aria.core.queue.pool.BaseCachePool;
|
||||
import com.arialyy.aria.core.queue.pool.BaseExecutePool;
|
||||
import com.arialyy.aria.core.queue.pool.DownloadSharePool;
|
||||
import com.arialyy.aria.core.queue.pool.UploadSharePool;
|
||||
import com.arialyy.aria.core.upload.UploadTask;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
@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 需要恢复的任务
|
||||
*/
|
||||
@Override public void resumeTask(TASK task) {
|
||||
if (task == null){
|
||||
if (task == null) {
|
||||
ALog.w(TAG, "resume task fail, task is null");
|
||||
return;
|
||||
}
|
||||
@@ -109,18 +112,6 @@ public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends Ab
|
||||
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}
|
||||
*/
|
||||
void addTask(TASK task) {
|
||||
if (task == null){
|
||||
if (task == null) {
|
||||
ALog.w(TAG, "add task fail, task is null");
|
||||
return;
|
||||
}
|
||||
@@ -218,7 +209,7 @@ public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends Ab
|
||||
}
|
||||
|
||||
@Override public void startTask(TASK task) {
|
||||
if (task == null){
|
||||
if (task == null) {
|
||||
ALog.w(TAG, "start fail, task is null");
|
||||
}
|
||||
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_FAIL:
|
||||
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;
|
||||
case IEntity.STATE_CANCEL:
|
||||
ALog.w(TAG, String.format("停止任务【%s】失败,原因:任务已删除", task.getTaskName()));
|
||||
|
||||
@@ -33,7 +33,7 @@ public class DownloadGroupTaskQueue
|
||||
|
||||
public static DownloadGroupTaskQueue getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (DownloadGroupTaskQueue.class) {
|
||||
INSTANCE = new DownloadGroupTaskQueue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ public class DownloadTaskQueue extends AbsTaskQueue<DownloadTask, DTaskWrapper>
|
||||
|
||||
public static DownloadTaskQueue getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (DownloadTaskQueue.class) {
|
||||
INSTANCE = new DownloadTaskQueue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
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.DTaskWrapper;
|
||||
import com.arialyy.aria.core.download.DownloadGroupTask;
|
||||
@@ -43,7 +42,7 @@ class TaskFactory {
|
||||
|
||||
public static TaskFactory getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (TaskFactory.class) {
|
||||
INSTANCE = new TaskFactory();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public class UploadTaskQueue extends AbsTaskQueue<UploadTask, UTaskWrapper> {
|
||||
|
||||
public static UploadTaskQueue getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (UploadTaskQueue.class) {
|
||||
INSTANCE = new UploadTaskQueue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.arialyy.aria.core.queue.pool;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.inf.AbsTask;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
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 int MAX_NUM = Integer.MAX_VALUE; //最大下载任务数
|
||||
private static final long TIME_OUT = 1000;
|
||||
private static final Object LOCK = new Object();
|
||||
private Map<String, TASK> mCacheMap;
|
||||
private LinkedBlockingQueue<TASK> mCacheQueue;
|
||||
|
||||
@@ -82,7 +82,7 @@ public class BaseCachePool<TASK extends AbsTask> implements IPool<TASK> {
|
||||
}
|
||||
|
||||
@Override public boolean putTask(TASK task) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (LOCK) {
|
||||
if (task == null) {
|
||||
ALog.e(TAG, "任务不能为空!!");
|
||||
return false;
|
||||
@@ -103,7 +103,7 @@ public class BaseCachePool<TASK extends AbsTask> implements IPool<TASK> {
|
||||
}
|
||||
|
||||
@Override public TASK pollTask() {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (LOCK) {
|
||||
try {
|
||||
TASK task;
|
||||
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) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (LOCK) {
|
||||
if (TextUtils.isEmpty(key)) {
|
||||
ALog.e(TAG, "key 为null");
|
||||
return null;
|
||||
@@ -134,7 +134,7 @@ public class BaseCachePool<TASK extends AbsTask> implements IPool<TASK> {
|
||||
}
|
||||
|
||||
@Override public boolean removeTask(TASK task) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (LOCK) {
|
||||
if (task == null) {
|
||||
ALog.e(TAG, "任务不能为空");
|
||||
return false;
|
||||
@@ -147,7 +147,7 @@ public class BaseCachePool<TASK extends AbsTask> implements IPool<TASK> {
|
||||
}
|
||||
|
||||
@Override public boolean removeTask(String key) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (LOCK) {
|
||||
if (TextUtils.isEmpty(key)) {
|
||||
ALog.e(TAG, "请传入有效的下载链接");
|
||||
return false;
|
||||
|
||||
@@ -31,6 +31,7 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
|
||||
private final String TAG = "BaseExecutePool";
|
||||
private static final Object LOCK = new Object();
|
||||
final long TIME_OUT = 1000;
|
||||
ArrayBlockingQueue<TASK> mExecuteQueue;
|
||||
Map<String, TASK> mExecuteMap;
|
||||
@@ -59,7 +60,7 @@ public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
|
||||
}
|
||||
|
||||
@Override public boolean putTask(TASK task) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (LOCK) {
|
||||
if (task == null) {
|
||||
ALog.e(TAG, "任务不能为空!!");
|
||||
return false;
|
||||
@@ -86,7 +87,7 @@ public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
|
||||
* @param maxNum 下载数
|
||||
*/
|
||||
public void setMaxNum(int maxNum) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (LOCK) {
|
||||
try {
|
||||
ArrayBlockingQueue<TASK> temp = new ArrayBlockingQueue<>(maxNum);
|
||||
TASK task;
|
||||
@@ -107,7 +108,7 @@ public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
|
||||
* @param newTask 新任务
|
||||
*/
|
||||
boolean putNewTask(TASK newTask) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (LOCK) {
|
||||
String url = newTask.getKey();
|
||||
boolean s = mExecuteQueue.offer(newTask);
|
||||
ALog.d(TAG, "任务【" + newTask.getTaskName() + "】进入执行队列" + (s ? "成功" : "失败"));
|
||||
@@ -122,7 +123,7 @@ public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
|
||||
* 队列满时,将移除下载队列中的第一个任务
|
||||
*/
|
||||
boolean pollFirstTask() {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (LOCK) {
|
||||
try {
|
||||
TASK oldTask = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS);
|
||||
if (oldTask == null) {
|
||||
@@ -141,7 +142,7 @@ public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
|
||||
}
|
||||
|
||||
@Override public TASK pollTask() {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (LOCK) {
|
||||
try {
|
||||
TASK task;
|
||||
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) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (LOCK) {
|
||||
if (TextUtils.isEmpty(key)) {
|
||||
ALog.e(TAG, "key 为null");
|
||||
return null;
|
||||
@@ -172,7 +173,7 @@ public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
|
||||
}
|
||||
|
||||
@Override public boolean removeTask(TASK task) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (LOCK) {
|
||||
if (task == null) {
|
||||
ALog.e(TAG, "任务不能为空");
|
||||
return false;
|
||||
@@ -183,7 +184,7 @@ public class BaseExecutePool<TASK extends AbsTask> implements IPool<TASK> {
|
||||
}
|
||||
|
||||
@Override public boolean removeTask(String key) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (LOCK) {
|
||||
if (TextUtils.isEmpty(key)) {
|
||||
ALog.e(TAG, "key 为null");
|
||||
return false;
|
||||
|
||||
@@ -34,7 +34,7 @@ class DownloadExecutePool<TASK extends AbsTask> extends BaseExecutePool<TASK> {
|
||||
}
|
||||
|
||||
@Override public boolean putTask(TASK task) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (DownloadExecutePool.class) {
|
||||
if (task == null) {
|
||||
ALog.e(TAG, "任务不能为空!!");
|
||||
return false;
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package com.arialyy.aria.core.queue.pool;
|
||||
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
|
||||
/**
|
||||
* Created by Aria.Lao on 2017/7/17.
|
||||
* 下载任务池,该池子为简单任务和任务组共用
|
||||
@@ -34,7 +32,7 @@ public class DownloadSharePool {
|
||||
|
||||
public static DownloadSharePool getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (DownloadSharePool.class) {
|
||||
INSTANCE = new DownloadSharePool();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package com.arialyy.aria.core.queue.pool;
|
||||
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
|
||||
/**
|
||||
* Created by Aria.Lao on 2017/7/17.
|
||||
* 下载任务池,该池子为简单任务和任务组共用
|
||||
@@ -34,7 +32,7 @@ public class UploadSharePool {
|
||||
|
||||
public static UploadSharePool getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (UploadSharePool.class) {
|
||||
INSTANCE = new UploadSharePool();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ package com.arialyy.aria.core.scheduler;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.Message;
|
||||
import com.arialyy.annotations.TaskEnum;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.download.DownloadGroupTask;
|
||||
import com.arialyy.aria.core.download.DownloadTask;
|
||||
@@ -51,14 +51,7 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends IT
|
||||
|
||||
protected QUEUE mQueue;
|
||||
|
||||
private Map<String, AbsSchedulerListener<TASK, AbsNormalEntity>> mObservers =
|
||||
new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 设置代理类后缀名
|
||||
*/
|
||||
abstract String getProxySuffix();
|
||||
|
||||
private Map<String, Map<TaskEnum, ISchedulerListener>> mObservers = new ConcurrentHashMap<>();
|
||||
private AriaManager manager;
|
||||
|
||||
AbsSchedulers() {
|
||||
@@ -69,21 +62,39 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends IT
|
||||
* 将当前类注册到Aria
|
||||
*
|
||||
* @param obj 观察者类
|
||||
* @param taskEnum 任务类型 {@link TaskEnum}
|
||||
*/
|
||||
public void register(Object obj) {
|
||||
public void register(Object obj, TaskEnum taskEnum) {
|
||||
String targetName = obj.getClass().getName();
|
||||
AbsSchedulerListener<TASK, AbsNormalEntity> listener = mObservers.get(getKey(obj));
|
||||
if (listener == null) {
|
||||
listener = createListener(targetName);
|
||||
Map<TaskEnum, ISchedulerListener> listeners = mObservers.get(getKey(obj));
|
||||
|
||||
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) {
|
||||
listener.setListener(obj);
|
||||
mObservers.put(getKey(obj), listener);
|
||||
listeners.put(taskEnum, listener);
|
||||
} 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))) {
|
||||
return;
|
||||
}
|
||||
for (Iterator<Map.Entry<String, AbsSchedulerListener<TASK, AbsNormalEntity>>> iter =
|
||||
for (Iterator<Map.Entry<String, Map<TaskEnum, ISchedulerListener>>> iter =
|
||||
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))) {
|
||||
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) {
|
||||
AbsSchedulerListener<TASK, AbsNormalEntity> listener = null;
|
||||
private ISchedulerListener createListener(String proxyClassName) {
|
||||
ISchedulerListener listener = null;
|
||||
try {
|
||||
Class clazz = Class.forName(targetName + getProxySuffix());
|
||||
listener = (AbsSchedulerListener<TASK, AbsNormalEntity>) clazz.newInstance();
|
||||
Class clazz = Class.forName(proxyClassName);
|
||||
listener = (ISchedulerListener) clazz.newInstance();
|
||||
} catch (ClassNotFoundException e) {
|
||||
ALog.e(TAG, targetName + ",没有Aria的Download或Upload注解方法");
|
||||
ALog.e(TAG, e.getMessage());
|
||||
} catch (InstantiationException e) {
|
||||
ALog.e(TAG, e.getMessage());
|
||||
} catch (IllegalAccessException e) {
|
||||
@@ -131,6 +143,10 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends IT
|
||||
return handleSubEvent(msg);
|
||||
}
|
||||
|
||||
if (msg.arg1 == IS_M3U8_PEER) {
|
||||
return handlePeerEvent(msg);
|
||||
}
|
||||
|
||||
TASK task = (TASK) msg.obj;
|
||||
if (task == null) {
|
||||
ALog.e(TAG, "请传入下载任务");
|
||||
@@ -140,6 +156,54 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends IT
|
||||
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) {
|
||||
Set<String> keys = mObservers.keySet();
|
||||
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) {
|
||||
case SUB_PRE:
|
||||
listener.onSubTaskPre((TASK) params.groupTask, params.entity);
|
||||
@@ -228,7 +300,7 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends IT
|
||||
}
|
||||
}
|
||||
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 状态
|
||||
*/
|
||||
private void callback(int state, TASK task) {
|
||||
private void normalTaskCallback(int state, TASK task) {
|
||||
sendNormalBroadcast(state, task);
|
||||
if (mObservers.size() > 0) {
|
||||
Set<String> keys = mObservers.keySet();
|
||||
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,
|
||||
AbsSchedulerListener<TASK, AbsNormalEntity> listener) {
|
||||
private void normalTaskCallback(int state, TASK task, NormalTaskListener<TASK> listener) {
|
||||
if (listener != null) {
|
||||
if (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()) {
|
||||
mQueue.removeTaskFormQueue(task.getKey());
|
||||
startNextTask(task);
|
||||
callback(FAIL, task);
|
||||
normalTaskCallback(FAIL, task);
|
||||
return;
|
||||
}
|
||||
long interval = task.getTaskWrapper().getConfig().getReTryInterval();
|
||||
@@ -354,7 +441,7 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends IT
|
||||
mQueue.removeTaskFormQueue(task.getKey());
|
||||
startNextTask(task);
|
||||
TaskWrapperManager.getInstance().removeTaskWrapper(task.getKey());
|
||||
callback(FAIL, task);
|
||||
normalTaskCallback(FAIL, task);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
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.DownloadGroupTask;
|
||||
import com.arialyy.aria.core.queue.DownloadGroupTaskQueue;
|
||||
@@ -36,14 +35,10 @@ public class DownloadGroupSchedulers extends
|
||||
|
||||
public static DownloadGroupSchedulers getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (DownloadGroupSchedulers.class) {
|
||||
INSTANCE = new DownloadGroupSchedulers();
|
||||
}
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override String getProxySuffix() {
|
||||
return "$$DownloadGroupListenerProxy";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,9 @@
|
||||
|
||||
package com.arialyy.aria.core.scheduler;
|
||||
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
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.queue.DownloadTaskQueue;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2016/8/16.
|
||||
@@ -38,14 +37,10 @@ public class DownloadSchedulers
|
||||
|
||||
public static DownloadSchedulers getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (DownloadSchedulers.class) {
|
||||
INSTANCE = new DownloadSchedulers();
|
||||
}
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override String getProxySuffix() {
|
||||
return "$$DownloadListenerProxy";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,69 +15,10 @@
|
||||
*/
|
||||
package com.arialyy.aria.core.scheduler;
|
||||
|
||||
import com.arialyy.aria.core.inf.ITask;
|
||||
|
||||
/**
|
||||
* 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 onTaskRunning(TASK task);
|
||||
void setListener(Object obj);
|
||||
}
|
||||
@@ -19,7 +19,6 @@ package com.arialyy.aria.core.scheduler;
|
||||
import android.os.Handler;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
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.upload.UploadEntity;
|
||||
|
||||
@@ -64,10 +63,28 @@ public interface ISchedulers extends Handler.Callback {
|
||||
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;
|
||||
|
||||
/**
|
||||
* m3u8切片任务标志
|
||||
*/
|
||||
int IS_M3U8_PEER = 0xd2;
|
||||
|
||||
/**
|
||||
* 任务不支持断点
|
||||
*/
|
||||
@@ -148,4 +165,17 @@ public interface ISchedulers extends Handler.Callback {
|
||||
* 组合任务子任务完成
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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>
|
||||
implements ISchedulerListener<TASK> {
|
||||
|
||||
@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 class SubTaskListener<TASK extends ITask, SUB_ENTITY extends AbsNormalEntity>
|
||||
implements ISchedulerListener {
|
||||
|
||||
public void onNoSupportBreakPoint(TASK task) {
|
||||
|
||||
}
|
||||
|
||||
public void setListener(Object obj) {
|
||||
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void setListener(Object obj) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.arialyy.aria.core.scheduler;
|
||||
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.queue.UploadTaskQueue;
|
||||
import com.arialyy.aria.core.upload.UTaskWrapper;
|
||||
import com.arialyy.aria.core.upload.UploadTask;
|
||||
@@ -35,15 +34,11 @@ public class UploadSchedulers extends AbsSchedulers<UTaskWrapper, UploadTask, Up
|
||||
|
||||
public static UploadSchedulers getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
synchronized (UploadSchedulers.class) {
|
||||
INSTANCE = new UploadSchedulers();
|
||||
}
|
||||
}
|
||||
|
||||
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.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import com.arialyy.annotations.TaskEnum;
|
||||
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.normal.CancelAllCmd;
|
||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
||||
import com.arialyy.aria.core.command.NormalCmdFactory;
|
||||
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.ReceiverType;
|
||||
import com.arialyy.aria.core.scheduler.UploadSchedulers;
|
||||
@@ -164,11 +166,9 @@ public class UploadReceiver extends AbsReceiver {
|
||||
* 停止所有正在下载的任务,并清空等待队列。
|
||||
*/
|
||||
public void stopAllTask() {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(NormalCmdFactory.getInstance()
|
||||
.createCmd(new UTaskWrapper(null), NormalCmdFactory.TASK_STOP_ALL,
|
||||
ICmd.TASK_TYPE_UPLOAD))
|
||||
.exe();
|
||||
EventMsgUtil.getDefault().post(NormalCmdFactory.getInstance()
|
||||
.createCmd(new UTaskWrapper(null), NormalCmdFactory.TASK_STOP_ALL,
|
||||
ICmd.TASK_TYPE_UPLOAD));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,7 +183,8 @@ public class UploadReceiver extends AbsReceiver {
|
||||
(CancelAllCmd) CommonUtil.createNormalCmd(new UTaskWrapper(null),
|
||||
NormalCmdFactory.TASK_CANCEL_ALL, ICmd.TASK_TYPE_UPLOAD);
|
||||
cancelCmd.removeFile = removeFile;
|
||||
am.setCmd(cancelCmd).exe();
|
||||
|
||||
EventMsgUtil.getDefault().post(cancelCmd);
|
||||
Set<String> keys = am.getReceiver().keySet();
|
||||
for (String key : keys) {
|
||||
am.getReceiver().remove(key);
|
||||
@@ -207,7 +208,7 @@ public class UploadReceiver extends AbsReceiver {
|
||||
if (set != null && !set.isEmpty()) {
|
||||
for (Integer type : set) {
|
||||
if (type == ProxyHelper.PROXY_TYPE_UPLOAD) {
|
||||
UploadSchedulers.getInstance().register(obj);
|
||||
UploadSchedulers.getInstance().register(obj, TaskEnum.UPLOAD);
|
||||
}
|
||||
}
|
||||
} 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.FtpTaskConfig;
|
||||
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.UploadEntity;
|
||||
import com.arialyy.aria.exception.AriaIOException;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
||||
@@ -107,6 +107,7 @@ class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UTaskWrapper> {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
onThreadComplete();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -102,6 +102,8 @@ class HttpThreadTask extends AbsThreadTask<UploadEntity, UTaskWrapper> {
|
||||
fail(new TaskException(TAG,
|
||||
String.format("上传失败,filePath: %s, url: %s", getEntity().getFilePath(),
|
||||
getEntity().getUrl()), e));
|
||||
} finally {
|
||||
onThreadComplete();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ public class SimpleUploadUtil implements IUtil, Runnable {
|
||||
}
|
||||
|
||||
@Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) {
|
||||
mListener.onFail(needRetry, e);
|
||||
failUpload(e, needRetry);
|
||||
}
|
||||
});
|
||||
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() {
|
||||
return mTaskWrapper.getKey();
|
||||
}
|
||||
@@ -108,8 +116,4 @@ public class SimpleUploadUtil implements IUtil, Runnable {
|
||||
}
|
||||
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.NormalFileer;
|
||||
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.IUploadListener;
|
||||
import com.arialyy.aria.core.upload.UTaskWrapper;
|
||||
@@ -51,4 +53,9 @@ class Uploader extends NormalFileer<UploadEntity, UTaskWrapper> {
|
||||
}
|
||||
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.DGTaskWrapper;
|
||||
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.UTaskWrapper;
|
||||
import java.util.HashMap;
|
||||
@@ -37,7 +38,7 @@ class DBConfig {
|
||||
static boolean DEBUG = false;
|
||||
static Map<String, Class> mapping = new LinkedHashMap<>();
|
||||
static String DB_NAME;
|
||||
static int VERSION = 49;
|
||||
static int VERSION = 51;
|
||||
|
||||
/**
|
||||
* 是否将数据库保存在Sd卡,{@code true} 是
|
||||
@@ -59,5 +60,6 @@ class DBConfig {
|
||||
mapping.put("UploadEntity", UploadEntity.class);
|
||||
mapping.put("ThreadRecord", ThreadRecord.class);
|
||||
mapping.put("TaskRecord", TaskRecord.class);
|
||||
mapping.put("M3U8Entity", M3U8Entity.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
handle314AriaUpdate(db);
|
||||
} else if (oldVersion < 45) {
|
||||
handle360AriaUpdate(db);
|
||||
} else if (oldVersion < 49) {
|
||||
} else if (oldVersion < 51) {
|
||||
handle365Update(db);
|
||||
} else {
|
||||
handleDbUpdate(db, null, null);
|
||||
@@ -223,6 +223,8 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
}
|
||||
//删除中介表
|
||||
mDelegate.dropTable(db, tableName + "_temp");
|
||||
}else {
|
||||
mDelegate.createTable(db, clazz);
|
||||
}
|
||||
}
|
||||
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
|
||||
* 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
|
||||
* "c(f)" contains unflushed writes not reflected in "disk(f)". The flush
|
||||
* 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 com.arialyy.aria.core.AriaManager;
|
||||
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.group.AbsGroupCmd;
|
||||
import com.arialyy.aria.core.command.group.GroupCmdFactory;
|
||||
import com.arialyy.aria.core.command.normal.AbsNormalCmd;
|
||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
||||
import com.arialyy.aria.core.command.NormalCmdFactory;
|
||||
import com.arialyy.aria.core.inf.AbsGroupTaskWrapper;
|
||||
import com.arialyy.aria.core.inf.AbsTaskWrapper;
|
||||
import dalvik.system.DexFile;
|
||||
@@ -70,6 +70,22 @@ import java.util.regex.Pattern;
|
||||
public class CommonUtil {
|
||||
private static final String TAG = "CommonUtil";
|
||||
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编码
|
||||
@@ -83,8 +99,6 @@ public class CommonUtil {
|
||||
return new String(str.getBytes(charSet), SERVER_CHARSET);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
*
|
||||
@@ -968,7 +982,7 @@ public class CommonUtil {
|
||||
}
|
||||
try {
|
||||
if (file.createNewFile()) {
|
||||
ALog.d(TAG, "创建文件成功:" + file.getAbsolutePath());
|
||||
//ALog.d(TAG, "创建文件成功:" + file.getAbsolutePath());
|
||||
return true;
|
||||
}
|
||||
} 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.download.DownloadEntity;
|
||||
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.AbsNormalEntity;
|
||||
import com.arialyy.aria.core.upload.UploadEntity;
|
||||
import com.arialyy.aria.orm.DbEntity;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -154,7 +152,7 @@ public class RecordUtil {
|
||||
if (!targetFile.isDirectory()) {
|
||||
cacheDir = targetFile.getParent() + "/." + targetFile.getName();
|
||||
}
|
||||
removeTsCache(record, cacheDir);
|
||||
removeTsCache(cacheDir);
|
||||
} else if (record.isBlock) { // 删除分块文件
|
||||
removeBlockFile(record);
|
||||
}
|
||||
@@ -216,7 +214,7 @@ public class RecordUtil {
|
||||
cacheDir = String.format("%s/.%s_%s", targetFile.getParent(), targetFile.getName(),
|
||||
record.bandWidth);
|
||||
}
|
||||
removeTsCache(record, cacheDir);
|
||||
removeTsCache(cacheDir);
|
||||
} else if (record.isBlock) { // 删除分块文件
|
||||
removeBlockFile(record);
|
||||
}
|
||||
@@ -289,15 +287,12 @@ public class RecordUtil {
|
||||
/**
|
||||
* 删除ts文件
|
||||
*/
|
||||
private static void removeTsCache(TaskRecord record, String cacheDir) {
|
||||
private static void removeTsCache(String cacheDir) {
|
||||
|
||||
if (!TextUtils.isEmpty(cacheDir)) {
|
||||
List<String> partPath = new ArrayList<>();
|
||||
for (ThreadRecord tr : record.threadRecords) {
|
||||
partPath.add(BaseM3U8Loader.getTsFilePath(cacheDir, tr.threadId));
|
||||
}
|
||||
for (String pp : partPath) {
|
||||
File f = new File(pp);
|
||||
|
||||
File[] files = new File(cacheDir).listFiles();
|
||||
for (File f : files) {
|
||||
if (f.exists()) {
|
||||
f.delete();
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user