Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3871d8f056 | ||
|
|
669aa6981c | ||
|
|
91daecd039 | ||
|
|
297cc99f2b | ||
|
|
f5f8e9b528 | ||
|
|
94c3e8bb58 | ||
|
|
ee5ee6e080 | ||
|
|
c4cc804c67 | ||
|
|
c9c00c38c6 | ||
|
|
846235a826 | ||
|
|
06dd6b35e0 | ||
|
|
944d69a1af | ||
|
|
1ee36e0bc1 | ||
|
|
0765ab67f7 | ||
|
|
1b54bfc4ac | ||
|
|
846e6c0720 | ||
|
|
5ad485890c | ||
|
|
012f94511b | ||
|
|
e41d2f8578 | ||
|
|
a6ecaadea4 | ||
|
|
c1b1cc1390 |
23
.github/ISSUE_TEMPLATE/Custom.md
vendored
23
.github/ISSUE_TEMPLATE/Custom.md
vendored
@@ -1,17 +1,26 @@
|
|||||||
---
|
---
|
||||||
name: 问题描述
|
name: 问题描述
|
||||||
about: 请详细描述你遇到的问题
|
about: 提交问题前,请先阅读文档和搜索issue
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Aria版本
|
<!-- 提交问题前,请先阅读文档和搜索相应问题的issue -->
|
||||||
|
|
||||||
|
## 版本
|
||||||
|
* 框架版本
|
||||||
|
|
||||||
|
* 系统版本
|
||||||
|
|
||||||
|
## 错误日志
|
||||||
|
<!-- 请提供详细的错误日志 -->
|
||||||
|
|
||||||
|
|
||||||
## 什么问题
|
## 重现步骤
|
||||||
|
<!-- 请提供明确的步骤 -->
|
||||||
|
1.
|
||||||
|
2.
|
||||||
|
3.
|
||||||
|
4.
|
||||||
|
|
||||||
|
|
||||||
## 如何复现此问题
|
|
||||||
|
|
||||||
|
|
||||||
## 控制台日志
|
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,6 @@ import android.app.Dialog;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Looper;
|
|
||||||
import android.widget.PopupWindow;
|
import android.widget.PopupWindow;
|
||||||
import com.arialyy.aria.core.command.CommandManager;
|
import com.arialyy.aria.core.command.CommandManager;
|
||||||
import com.arialyy.aria.core.common.QueueMod;
|
import com.arialyy.aria.core.common.QueueMod;
|
||||||
@@ -76,7 +74,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
*/
|
*/
|
||||||
private Map<String, List<String>> mSubClass = new ConcurrentHashMap<>();
|
private Map<String, List<String>> mSubClass = new ConcurrentHashMap<>();
|
||||||
private static Context APP;
|
private static Context APP;
|
||||||
private Handler mAriaHandler;
|
|
||||||
private DelegateWrapper mDbWrapper;
|
private DelegateWrapper mDbWrapper;
|
||||||
private AriaConfig mConfig;
|
private AriaConfig mConfig;
|
||||||
|
|
||||||
@@ -98,9 +95,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static AriaManager getInstance() {
|
public static AriaManager getInstance() {
|
||||||
if (INSTANCE == null) {
|
|
||||||
throw new NullPointerException("请使用AriaManager.init(context)初始化管理器");
|
|
||||||
}
|
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,13 +165,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Handler getAriaHandler() {
|
|
||||||
if (mAriaHandler == null) {
|
|
||||||
mAriaHandler = new Handler(Looper.getMainLooper());
|
|
||||||
}
|
|
||||||
return mAriaHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, AbsReceiver> getReceiver() {
|
public Map<String, AbsReceiver> getReceiver() {
|
||||||
return mReceivers;
|
return mReceivers;
|
||||||
}
|
}
|
||||||
@@ -295,7 +282,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
RecordUtil.delTaskRecord(key, IRecordHandler.TYPE_DOWNLOAD, removeFile, true);
|
RecordUtil.delTaskRecord(key, IRecordHandler.TYPE_DOWNLOAD, removeFile, true);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
RecordUtil.delGroupTaskRecord(key, removeFile);
|
RecordUtil.delGroupTaskRecordByHash(key, removeFile);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
RecordUtil.delTaskRecord(key, IRecordHandler.TYPE_UPLOAD);
|
RecordUtil.delTaskRecord(key, IRecordHandler.TYPE_UPLOAD);
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.arialyy.aria.core.command;
|
package com.arialyy.aria.core.command;
|
||||||
|
|
||||||
|
import com.arialyy.aria.core.task.ITask;
|
||||||
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,8 +26,7 @@ public abstract class AbsCmdFactory<TASK_ENTITY extends AbsTaskWrapper, CMD exte
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param entity 下载实体
|
* @param entity 下载实体
|
||||||
* @param taskType {@link ICmd#TASK_TYPE_DOWNLOAD}、{@link ICmd#TASK_TYPE_DOWNLOAD_GROUP}、{@link
|
* {@link ITask#DOWNLOAD}、{@link ITask#DOWNLOAD_GROUP}、{@link ITask#UPLOAD}
|
||||||
* ICmd#TASK_TYPE_UPLOAD}
|
|
||||||
*/
|
*/
|
||||||
public abstract CMD createCmd(TASK_ENTITY entity, int type, int taskType);
|
public abstract CMD createCmd(TASK_ENTITY entity, int type, int taskType);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,14 +157,6 @@ public abstract class AbsNormalCmd<T extends AbsTaskWrapper> extends AbsCmd<T> {
|
|||||||
mQueue.resumeTask(task);
|
mQueue.resumeTask(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 启动指定任务
|
|
||||||
*
|
|
||||||
* @param task 指定任务
|
|
||||||
*/
|
|
||||||
void startTask(AbsTask task) {
|
|
||||||
mQueue.startTask(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从队列中获取任务
|
* 从队列中获取任务
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public class CommandManager {
|
|||||||
EventMsgUtil.getDefault().register(this);
|
EventMsgUtil.getDefault().register(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CommandManager init() {
|
public static void init() {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
synchronized (CommandManager.class) {
|
synchronized (CommandManager.class) {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
@@ -38,7 +38,6 @@ public class CommandManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return instance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Event
|
@Event
|
||||||
@@ -51,9 +50,6 @@ public class CommandManager {
|
|||||||
|
|
||||||
@Event
|
@Event
|
||||||
public void start(StartCmd cmd) {
|
public void start(StartCmd cmd) {
|
||||||
if (CommonUtil.isFastDoubleClick()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cmd.executeCmd();
|
cmd.executeCmd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.arialyy.aria.core.command;
|
package com.arialyy.aria.core.command;
|
||||||
|
|
||||||
|
import com.arialyy.aria.core.AriaConfig;
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaManager;
|
||||||
import com.arialyy.aria.core.task.DownloadTask;
|
import com.arialyy.aria.core.task.DownloadTask;
|
||||||
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
||||||
@@ -41,7 +42,7 @@ final class HighestPriorityCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T>
|
|||||||
|
|
||||||
@Override public void executeCmd() {
|
@Override public void executeCmd() {
|
||||||
if (!canExeCmd) return;
|
if (!canExeCmd) return;
|
||||||
if (!NetUtils.isConnected(AriaManager.getInstance().getAPP())){
|
if (!NetUtils.isConnected(AriaConfig.getInstance().getAPP())){
|
||||||
ALog.e(TAG, "启动任务失败,网络未连接");
|
ALog.e(TAG, "启动任务失败,网络未连接");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.arialyy.aria.core.command;
|
package com.arialyy.aria.core.command;
|
||||||
|
|
||||||
|
import com.arialyy.aria.core.task.ITask;
|
||||||
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -83,8 +84,7 @@ public class NormalCmdFactory extends AbsCmdFactory<AbsTaskWrapper, AbsNormalCmd
|
|||||||
* @param entity 下载实体
|
* @param entity 下载实体
|
||||||
* @param type 命令类型{@link #TASK_CREATE}、{@link #TASK_START}、{@link #TASK_CANCEL}、{@link
|
* @param type 命令类型{@link #TASK_CREATE}、{@link #TASK_START}、{@link #TASK_CANCEL}、{@link
|
||||||
* #TASK_STOP}、{@link #TASK_HIGHEST_PRIORITY}、{@link #TASK_STOP_ALL}、{@link #TASK_RESUME_ALL}
|
* #TASK_STOP}、{@link #TASK_HIGHEST_PRIORITY}、{@link #TASK_STOP_ALL}、{@link #TASK_RESUME_ALL}
|
||||||
* @param taskType {@link ICmd#TASK_TYPE_DOWNLOAD}、{@link ICmd#TASK_TYPE_DOWNLOAD_GROUP}、{@link
|
* @param taskType {@link ITask#DOWNLOAD}、{@link ITask#DOWNLOAD_GROUP}、{@link ITask#UPLOAD}
|
||||||
* ICmd#TASK_TYPE_UPLOAD}
|
|
||||||
*/
|
*/
|
||||||
public AbsNormalCmd createCmd(AbsTaskWrapper entity, int type, int taskType) {
|
public AbsNormalCmd createCmd(AbsTaskWrapper entity, int type, int taskType) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|||||||
@@ -1,25 +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.command;
|
package com.arialyy.aria.core.command;
|
||||||
|
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaConfig;
|
||||||
import com.arialyy.aria.core.download.DGTaskWrapper;
|
|
||||||
import com.arialyy.aria.core.download.DTaskWrapper;
|
|
||||||
import com.arialyy.aria.core.download.DownloadEntity;
|
|
||||||
import com.arialyy.aria.core.download.DownloadGroupEntity;
|
|
||||||
import com.arialyy.aria.core.common.AbsEntity;
|
|
||||||
import com.arialyy.aria.core.task.AbsTask;
|
|
||||||
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
|
||||||
import com.arialyy.aria.core.inf.IEntity;
|
import com.arialyy.aria.core.inf.IEntity;
|
||||||
import com.arialyy.aria.core.manager.TaskWrapperManager;
|
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
||||||
import com.arialyy.aria.core.queue.DGroupTaskQueue;
|
|
||||||
import com.arialyy.aria.core.queue.DTaskQueue;
|
|
||||||
import com.arialyy.aria.core.queue.UTaskQueue;
|
|
||||||
import com.arialyy.aria.core.upload.UTaskWrapper;
|
|
||||||
import com.arialyy.aria.core.upload.UploadEntity;
|
|
||||||
import com.arialyy.aria.orm.DbEntity;
|
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
import com.arialyy.aria.util.NetUtils;
|
import com.arialyy.aria.util.NetUtils;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by AriaL on 2017/6/13.
|
* Created by AriaL on 2017/6/13.
|
||||||
@@ -30,105 +30,17 @@ import java.util.List;
|
|||||||
* 4.恢复下载的任务规则是,停止时间越晚的任务启动越早,按照DESC来进行排序
|
* 4.恢复下载的任务规则是,停止时间越晚的任务启动越早,按照DESC来进行排序
|
||||||
*/
|
*/
|
||||||
final class ResumeAllCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
|
final class ResumeAllCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
|
||||||
private List<AbsTaskWrapper> mWaitList = new ArrayList<>();
|
|
||||||
|
|
||||||
ResumeAllCmd(T entity, int taskType) {
|
ResumeAllCmd(T entity, int taskType) {
|
||||||
super(entity, taskType);
|
super(entity, taskType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void executeCmd() {
|
@Override public void executeCmd() {
|
||||||
if (!NetUtils.isConnected(AriaManager.getInstance().getAPP())) {
|
if (!NetUtils.isConnected(AriaConfig.getInstance().getAPP())) {
|
||||||
ALog.w(TAG, "恢复任务失败,网络未连接");
|
ALog.w(TAG, "恢复任务失败,网络未连接");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isDownloadCmd) {
|
new Thread(new ResumeThread(isDownloadCmd,
|
||||||
findTaskData(1);
|
String.format("state!=%s", IEntity.STATE_COMPLETE))).start();
|
||||||
findTaskData(2);
|
|
||||||
} else {
|
|
||||||
findTaskData(3);
|
|
||||||
}
|
|
||||||
resumeWaitTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查找数据库中的所有任务数据
|
|
||||||
*
|
|
||||||
* @param type {@code 1}单任务下载任务;{@code 2}任务组下载任务;{@code 3} 单任务上传任务
|
|
||||||
*/
|
|
||||||
private void findTaskData(int type) {
|
|
||||||
if (type == 1) {
|
|
||||||
List<DownloadEntity> entities =
|
|
||||||
DbEntity.findDatas(DownloadEntity.class,
|
|
||||||
"isGroupChild=? AND state!=? ORDER BY stopTime DESC", "false", "1");
|
|
||||||
if (entities != null && !entities.isEmpty()) {
|
|
||||||
for (DownloadEntity entity : entities) {
|
|
||||||
addResumeEntity(TaskWrapperManager.getInstance()
|
|
||||||
.getNormalTaskWrapper(DTaskWrapper.class, entity.getId()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (type == 2) {
|
|
||||||
List<DownloadGroupEntity> entities =
|
|
||||||
DbEntity.findDatas(DownloadGroupEntity.class, "state!=? ORDER BY stopTime DESC", "1");
|
|
||||||
if (entities != null && !entities.isEmpty()) {
|
|
||||||
for (DownloadGroupEntity entity : entities) {
|
|
||||||
addResumeEntity(
|
|
||||||
TaskWrapperManager.getInstance()
|
|
||||||
.getGroupWrapper(DGTaskWrapper.class, entity.getId()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (type == 3) {
|
|
||||||
List<UploadEntity> entities =
|
|
||||||
DbEntity.findDatas(UploadEntity.class, "state!=? ORDER BY stopTime DESC", "1");
|
|
||||||
if (entities != null && !entities.isEmpty()) {
|
|
||||||
for (UploadEntity entity : entities) {
|
|
||||||
addResumeEntity(TaskWrapperManager.getInstance()
|
|
||||||
.getNormalTaskWrapper(UTaskWrapper.class, entity.getId()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 添加恢复实体
|
|
||||||
*/
|
|
||||||
private void addResumeEntity(AbsTaskWrapper te) {
|
|
||||||
if (te == null || te.getEntity() == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!mQueue.taskExists(te.getKey())) {
|
|
||||||
mWaitList.add(te);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理等待状态的任务
|
|
||||||
*/
|
|
||||||
private void resumeWaitTask() {
|
|
||||||
int maxTaskNum = mQueue.getMaxTaskNum();
|
|
||||||
if (mWaitList == null || mWaitList.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<AbsEntity> resumeEntities = new ArrayList<>();
|
|
||||||
|
|
||||||
for (AbsTaskWrapper te : mWaitList) {
|
|
||||||
if (te instanceof DTaskWrapper) {
|
|
||||||
mQueue = DTaskQueue.getInstance();
|
|
||||||
} else if (te instanceof UTaskWrapper) {
|
|
||||||
mQueue = UTaskQueue.getInstance();
|
|
||||||
} else if (te instanceof DGTaskWrapper) {
|
|
||||||
mQueue = DGroupTaskQueue.getInstance();
|
|
||||||
}
|
|
||||||
if (mQueue.getCurrentExePoolNum() < maxTaskNum) {
|
|
||||||
startTask(createTask(te));
|
|
||||||
} else {
|
|
||||||
te.getEntity().setState(IEntity.STATE_WAIT);
|
|
||||||
AbsTask task = createTask(te);
|
|
||||||
sendWaitState(task);
|
|
||||||
resumeEntities.add(te.getEntity());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!resumeEntities.isEmpty()) {
|
|
||||||
DbEntity.updateManyData(resumeEntities);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,200 @@
|
|||||||
|
/*
|
||||||
|
* 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 android.text.TextUtils;
|
||||||
|
import com.arialyy.aria.core.common.AbsEntity;
|
||||||
|
import com.arialyy.aria.core.download.DGTaskWrapper;
|
||||||
|
import com.arialyy.aria.core.download.DTaskWrapper;
|
||||||
|
import com.arialyy.aria.core.download.DownloadEntity;
|
||||||
|
import com.arialyy.aria.core.download.DownloadGroupEntity;
|
||||||
|
import com.arialyy.aria.core.inf.IEntity;
|
||||||
|
import com.arialyy.aria.core.inf.IOptionConstant;
|
||||||
|
import com.arialyy.aria.core.listener.ISchedulers;
|
||||||
|
import com.arialyy.aria.core.manager.TaskWrapperManager;
|
||||||
|
import com.arialyy.aria.core.queue.AbsTaskQueue;
|
||||||
|
import com.arialyy.aria.core.queue.DGroupTaskQueue;
|
||||||
|
import com.arialyy.aria.core.queue.DTaskQueue;
|
||||||
|
import com.arialyy.aria.core.queue.UTaskQueue;
|
||||||
|
import com.arialyy.aria.core.task.AbsTask;
|
||||||
|
import com.arialyy.aria.core.upload.UTaskWrapper;
|
||||||
|
import com.arialyy.aria.core.upload.UploadEntity;
|
||||||
|
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
||||||
|
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
||||||
|
import com.arialyy.aria.orm.DbEntity;
|
||||||
|
import com.arialyy.aria.util.ALog;
|
||||||
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 恢复任务工具
|
||||||
|
*/
|
||||||
|
public class ResumeThread implements Runnable {
|
||||||
|
private String TAG = CommonUtil.getClassName(getClass());
|
||||||
|
private List<AbsTaskWrapper> mWaitList = new ArrayList<>();
|
||||||
|
private boolean isDownloadCmd;
|
||||||
|
private String sqlCondition;
|
||||||
|
|
||||||
|
ResumeThread(boolean isDownload, String sqlCondition) {
|
||||||
|
this.isDownloadCmd = isDownload;
|
||||||
|
this.sqlCondition = sqlCondition;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找数据库中的所有任务数据
|
||||||
|
*
|
||||||
|
* @param type {@code 1}单任务下载任务;{@code 2}任务组下载任务;{@code 3} 单任务上传任务
|
||||||
|
*/
|
||||||
|
private void findTaskData(int type) {
|
||||||
|
if (type == 1) {
|
||||||
|
List<DownloadEntity> entities =
|
||||||
|
DbEntity.findDatas(DownloadEntity.class,
|
||||||
|
String.format("NOT(isGroupChild) AND NOT(isComplete) AND %s ORDER BY stopTime DESC",
|
||||||
|
sqlCondition));
|
||||||
|
if (entities != null && !entities.isEmpty()) {
|
||||||
|
for (DownloadEntity entity : entities) {
|
||||||
|
addResumeEntity(TaskWrapperManager.getInstance()
|
||||||
|
.getNormalTaskWrapper(DTaskWrapper.class, entity.getId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (type == 2) {
|
||||||
|
List<DownloadGroupEntity> entities =
|
||||||
|
DbEntity.findDatas(DownloadGroupEntity.class,
|
||||||
|
String.format("NOT(isComplete) AND %s ORDER BY stopTime DESC",
|
||||||
|
sqlCondition));
|
||||||
|
if (entities != null && !entities.isEmpty()) {
|
||||||
|
for (DownloadGroupEntity entity : entities) {
|
||||||
|
addResumeEntity(
|
||||||
|
TaskWrapperManager.getInstance()
|
||||||
|
.getGroupWrapper(DGTaskWrapper.class, entity.getId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (type == 3) {
|
||||||
|
List<UploadEntity> entities =
|
||||||
|
DbEntity.findDatas(UploadEntity.class,
|
||||||
|
String.format("NOT(isComplete) AND %s ORDER BY stopTime DESC",
|
||||||
|
sqlCondition));
|
||||||
|
if (entities != null && !entities.isEmpty()) {
|
||||||
|
for (UploadEntity entity : entities) {
|
||||||
|
addResumeEntity(TaskWrapperManager.getInstance()
|
||||||
|
.getNormalTaskWrapper(UTaskWrapper.class, entity.getId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加恢复实体
|
||||||
|
*/
|
||||||
|
private void addResumeEntity(AbsTaskWrapper te) {
|
||||||
|
if (te == null || te.getEntity() == null || TextUtils.isEmpty(te.getKey())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mWaitList.add(te);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理等待状态的任务
|
||||||
|
*/
|
||||||
|
private void resumeWaitTask() {
|
||||||
|
|
||||||
|
if (mWaitList == null || mWaitList.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<AbsEntity> resumeEntities = new ArrayList<>();
|
||||||
|
|
||||||
|
for (AbsTaskWrapper wrapper : mWaitList) {
|
||||||
|
AbsTaskQueue queue = null;
|
||||||
|
if (wrapper instanceof DTaskWrapper) {
|
||||||
|
queue = DTaskQueue.getInstance();
|
||||||
|
} else if (wrapper instanceof UTaskWrapper) {
|
||||||
|
queue = UTaskQueue.getInstance();
|
||||||
|
} else if (wrapper instanceof DGTaskWrapper) {
|
||||||
|
queue = DGroupTaskQueue.getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queue == null) {
|
||||||
|
ALog.e(TAG, "任务类型错误");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wrapper.getEntity() == null || TextUtils.isEmpty(wrapper.getKey())) {
|
||||||
|
ALog.e(TAG, "任务实体为空或key为空");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbsTask task = queue.getTask(wrapper.getKey());
|
||||||
|
if (task != null) {
|
||||||
|
ALog.w(TAG, "任务已存在");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxTaskNum = queue.getMaxTaskNum();
|
||||||
|
task = queue.createTask(wrapper);
|
||||||
|
if (task == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleWrapper(wrapper);
|
||||||
|
|
||||||
|
if (queue.getCurrentExePoolNum() < maxTaskNum) {
|
||||||
|
queue.startTask(task);
|
||||||
|
} else {
|
||||||
|
wrapper.getEntity().setState(IEntity.STATE_WAIT);
|
||||||
|
sendWaitState(task);
|
||||||
|
resumeEntities.add(wrapper.getEntity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!resumeEntities.isEmpty()) {
|
||||||
|
DbEntity.updateManyData(resumeEntities);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理ftp的wrapper
|
||||||
|
*/
|
||||||
|
private void handleWrapper(AbsTaskWrapper wrapper) {
|
||||||
|
int requestType = wrapper.getRequestType();
|
||||||
|
if (requestType == ITaskWrapper.D_FTP
|
||||||
|
|| requestType == ITaskWrapper.U_FTP
|
||||||
|
|| requestType == ITaskWrapper.D_FTP_DIR) {
|
||||||
|
wrapper.getOptionParams()
|
||||||
|
.setParams(IOptionConstant.ftpUrlEntity,
|
||||||
|
CommonUtil.getFtpUrlInfo(wrapper.getEntity().getKey()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送等待状态
|
||||||
|
*/
|
||||||
|
private void sendWaitState(AbsTask task) {
|
||||||
|
if (task != null) {
|
||||||
|
task.getTaskWrapper().setState(IEntity.STATE_WAIT);
|
||||||
|
task.getOutHandler().obtainMessage(ISchedulers.WAIT, task).sendToTarget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void run() {
|
||||||
|
if (isDownloadCmd) {
|
||||||
|
findTaskData(1);
|
||||||
|
findTaskData(2);
|
||||||
|
} else {
|
||||||
|
findTaskData(3);
|
||||||
|
}
|
||||||
|
resumeWaitTask();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,52 +16,47 @@
|
|||||||
|
|
||||||
package com.arialyy.aria.core.command;
|
package com.arialyy.aria.core.command;
|
||||||
|
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaConfig;
|
||||||
import com.arialyy.aria.core.common.QueueMod;
|
import com.arialyy.aria.core.common.QueueMod;
|
||||||
import com.arialyy.aria.core.download.DGTaskWrapper;
|
import com.arialyy.aria.core.inf.IEntity;
|
||||||
import com.arialyy.aria.core.download.DTaskWrapper;
|
|
||||||
import com.arialyy.aria.core.download.DownloadEntity;
|
|
||||||
import com.arialyy.aria.core.download.DownloadGroupEntity;
|
|
||||||
import com.arialyy.aria.core.task.AbsTask;
|
import com.arialyy.aria.core.task.AbsTask;
|
||||||
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
||||||
import com.arialyy.aria.core.inf.IEntity;
|
|
||||||
import com.arialyy.aria.core.inf.IOptionConstant;
|
|
||||||
import com.arialyy.aria.core.manager.TaskWrapperManager;
|
|
||||||
import com.arialyy.aria.core.queue.DGroupTaskQueue;
|
|
||||||
import com.arialyy.aria.core.queue.DTaskQueue;
|
|
||||||
import com.arialyy.aria.core.queue.UTaskQueue;
|
|
||||||
import com.arialyy.aria.core.upload.UTaskWrapper;
|
|
||||||
import com.arialyy.aria.core.upload.UploadEntity;
|
|
||||||
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
|
||||||
import com.arialyy.aria.orm.DbEntity;
|
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
import com.arialyy.aria.util.CommonUtil;
|
|
||||||
import com.arialyy.aria.util.NetUtils;
|
import com.arialyy.aria.util.NetUtils;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by lyy on 2016/8/22. 开始命令 队列模型{@link QueueMod#NOW}、{@link QueueMod#WAIT}
|
* Created by lyy on 2016/8/22. 开始命令 队列模型{@link QueueMod#NOW}、{@link QueueMod#WAIT}
|
||||||
*/
|
*/
|
||||||
final class StartCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
|
final public class StartCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
|
||||||
|
|
||||||
|
private boolean newStart = false;
|
||||||
|
|
||||||
StartCmd(T entity, int taskType) {
|
StartCmd(T entity, int taskType) {
|
||||||
super(entity, taskType);
|
super(entity, taskType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 立即执行任务
|
||||||
|
*
|
||||||
|
* @param newStart true 立即执行任务,无论执行队列是否满了
|
||||||
|
*/
|
||||||
|
public void setNewStart(boolean newStart) {
|
||||||
|
this.newStart = newStart;
|
||||||
|
}
|
||||||
|
|
||||||
@Override public void executeCmd() {
|
@Override public void executeCmd() {
|
||||||
if (!canExeCmd) return;
|
if (!canExeCmd) return;
|
||||||
if (!NetUtils.isConnected(AriaManager.getInstance().getAPP())) {
|
if (!NetUtils.isConnected(AriaConfig.getInstance().getAPP())) {
|
||||||
ALog.e(TAG, "启动任务失败,网络未连接");
|
ALog.e(TAG, "启动任务失败,网络未连接");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String mod;
|
String mod;
|
||||||
int maxTaskNum = mQueue.getMaxTaskNum();
|
int maxTaskNum = mQueue.getMaxTaskNum();
|
||||||
AriaManager manager = AriaManager.getInstance();
|
AriaConfig config = AriaConfig.getInstance();
|
||||||
if (isDownloadCmd) {
|
if (isDownloadCmd) {
|
||||||
mod = manager.getDownloadConfig().getQueueMod();
|
mod = config.getDConfig().getQueueMod();
|
||||||
} else {
|
} else {
|
||||||
mod = manager.getUploadConfig().getQueueMod();
|
mod = config.getUConfig().getQueueMod();
|
||||||
}
|
}
|
||||||
|
|
||||||
AbsTask task = getTask();
|
AbsTask task = getTask();
|
||||||
@@ -87,7 +82,11 @@ final class StartCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
|
|||||||
startTask();
|
startTask();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sendWaitState(task);
|
if (newStart) {
|
||||||
|
startTask();
|
||||||
|
} else {
|
||||||
|
sendWaitState(task);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -107,75 +106,7 @@ final class StartCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
|
|||||||
* 当缓冲队列为null时,查找数据库中所有等待中的任务
|
* 当缓冲队列为null时,查找数据库中所有等待中的任务
|
||||||
*/
|
*/
|
||||||
private void findAllWaitTask() {
|
private void findAllWaitTask() {
|
||||||
new Thread(new WaitTaskThread()).start();
|
new Thread(
|
||||||
}
|
new ResumeThread(isDownloadCmd, String.format("state=%s", IEntity.STATE_WAIT))).start();
|
||||||
|
|
||||||
private class WaitTaskThread implements Runnable {
|
|
||||||
|
|
||||||
@Override public void run() {
|
|
||||||
if (isDownloadCmd) {
|
|
||||||
handleTask(findWaitData(1));
|
|
||||||
handleTask(findWaitData(2));
|
|
||||||
} else {
|
|
||||||
handleTask(findWaitData(3));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<AbsTaskWrapper> findWaitData(int type) {
|
|
||||||
List<AbsTaskWrapper> waitList = new ArrayList<>();
|
|
||||||
TaskWrapperManager tManager = TaskWrapperManager.getInstance();
|
|
||||||
if (type == 1) { // 普通下载任务
|
|
||||||
List<DownloadEntity> dEntities = DbEntity.findDatas(DownloadEntity.class,
|
|
||||||
"isGroupChild=? and state=?", "false", "3");
|
|
||||||
if (dEntities != null && !dEntities.isEmpty()) {
|
|
||||||
for (DownloadEntity e : dEntities) {
|
|
||||||
waitList.add(tManager.getNormalTaskWrapper(DTaskWrapper.class, e.getId()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (type == 2) { // 组合任务
|
|
||||||
List<DownloadGroupEntity> dEntities =
|
|
||||||
DbEntity.findDatas(DownloadGroupEntity.class, "state=?", "3");
|
|
||||||
if (dEntities != null && !dEntities.isEmpty()) {
|
|
||||||
for (DownloadGroupEntity e : dEntities) {
|
|
||||||
if (e.getTaskType() == ITaskWrapper.DG_HTTP) {
|
|
||||||
waitList.add(tManager.getGroupWrapper(DGTaskWrapper.class, e.getId()));
|
|
||||||
} else if (e.getTaskType() == ITaskWrapper.D_FTP_DIR) {
|
|
||||||
waitList.add(tManager.getGroupWrapper(DGTaskWrapper.class, e.getId()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (type == 3) { //普通上传任务
|
|
||||||
List<UploadEntity> dEntities = DbEntity.findDatas(UploadEntity.class, "state=?", "3");
|
|
||||||
|
|
||||||
if (dEntities != null && !dEntities.isEmpty()) {
|
|
||||||
for (UploadEntity e : dEntities) {
|
|
||||||
waitList.add(tManager.getNormalTaskWrapper(UTaskWrapper.class, e.getId()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return waitList;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleTask(List<AbsTaskWrapper> waitList) {
|
|
||||||
for (AbsTaskWrapper wrapper : waitList) {
|
|
||||||
if (wrapper.getEntity() == null) continue;
|
|
||||||
AbsTask task = getTask(wrapper.getKey());
|
|
||||||
if (task != null) continue;
|
|
||||||
if (wrapper instanceof DTaskWrapper) {
|
|
||||||
if (wrapper.getRequestType() == ITaskWrapper.D_FTP
|
|
||||||
|| wrapper.getRequestType() == ITaskWrapper.U_FTP) {
|
|
||||||
wrapper.getOptionParams()
|
|
||||||
.setParams(IOptionConstant.ftpUrlEntity,
|
|
||||||
CommonUtil.getFtpUrlInfo(wrapper.getEntity().getKey()));
|
|
||||||
}
|
|
||||||
mQueue = DTaskQueue.getInstance();
|
|
||||||
} else if (wrapper instanceof UTaskWrapper) {
|
|
||||||
mQueue = UTaskQueue.getInstance();
|
|
||||||
} else if (wrapper instanceof DGTaskWrapper) {
|
|
||||||
mQueue = DGroupTaskQueue.getInstance();
|
|
||||||
}
|
|
||||||
createTask(wrapper);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15,12 +15,12 @@
|
|||||||
*/
|
*/
|
||||||
package com.arialyy.aria.core.common;
|
package com.arialyy.aria.core.common;
|
||||||
|
|
||||||
import com.arialyy.aria.core.common.controller.IStartFeature;
|
|
||||||
import com.arialyy.aria.core.common.controller.BuilderController;
|
import com.arialyy.aria.core.common.controller.BuilderController;
|
||||||
|
import com.arialyy.aria.core.common.controller.IStartFeature;
|
||||||
import com.arialyy.aria.core.inf.AbsTarget;
|
import com.arialyy.aria.core.inf.AbsTarget;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理第一次下载
|
* 处理第一次创建的任务
|
||||||
*/
|
*/
|
||||||
public abstract class AbsBuilderTarget<TARGET extends AbsBuilderTarget> extends AbsTarget<TARGET>
|
public abstract class AbsBuilderTarget<TARGET extends AbsBuilderTarget> extends AbsTarget<TARGET>
|
||||||
implements IStartFeature {
|
implements IStartFeature {
|
||||||
@@ -34,6 +34,23 @@ public abstract class AbsBuilderTarget<TARGET extends AbsBuilderTarget> extends
|
|||||||
return mStartController;
|
return mStartController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否忽略权限检查
|
||||||
|
*/
|
||||||
|
public TARGET ignoreCheckPermissions() {
|
||||||
|
getController().ignoreCheckPermissions();
|
||||||
|
return (TARGET) this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 忽略文件占用,不管文件路径是否被其它任务占用,都执行上传\下载任务
|
||||||
|
* 需要注意的是:如果文件被其它任务占用,并且还调用了该方法,将自动删除占用了该文件路径的任务
|
||||||
|
*/
|
||||||
|
public TARGET ignoreFilePathOccupy() {
|
||||||
|
getController().ignoreFilePathOccupy();
|
||||||
|
return (TARGET) this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加任务
|
* 添加任务
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -31,6 +31,14 @@ import com.arialyy.aria.util.RecordUtil;
|
|||||||
public abstract class AbsNormalTarget<TARGET extends AbsNormalTarget> extends AbsTarget<TARGET>
|
public abstract class AbsNormalTarget<TARGET extends AbsNormalTarget> extends AbsTarget<TARGET>
|
||||||
implements INormalFeature {
|
implements INormalFeature {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否忽略权限检查
|
||||||
|
*/
|
||||||
|
public TARGET ignoreCheckPermissions() {
|
||||||
|
getController().ignoreCheckPermissions();
|
||||||
|
return (TARGET) this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任务是否在执行
|
* 任务是否在执行
|
||||||
*
|
*
|
||||||
@@ -150,7 +158,17 @@ public abstract class AbsNormalTarget<TARGET extends AbsNormalTarget> extends Ab
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void resume() {
|
public void resume() {
|
||||||
getController().resume();
|
resume(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 正常来说,当执行队列满时,调用恢复任务接口,只能将任务放到缓存队列中。
|
||||||
|
* 如果希望调用恢复接口,马上进入执行队列,需要使用该方法
|
||||||
|
*
|
||||||
|
* @param newStart true 立即将任务恢复到执行队列中
|
||||||
|
*/
|
||||||
|
@Override public void resume(boolean newStart) {
|
||||||
|
getController().resume(newStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import com.arialyy.aria.core.command.NormalCmdFactory;
|
|||||||
import com.arialyy.aria.core.event.EventMsgUtil;
|
import com.arialyy.aria.core.event.EventMsgUtil;
|
||||||
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
||||||
import com.arialyy.aria.core.command.CmdHelper;
|
import com.arialyy.aria.core.command.CmdHelper;
|
||||||
|
import com.arialyy.aria.util.ALog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建任务时使用的控制器
|
* 创建任务时使用的控制器
|
||||||
|
|||||||
@@ -19,21 +19,21 @@ import android.Manifest;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaConfig;
|
||||||
|
import com.arialyy.aria.core.common.AbsEntity;
|
||||||
import com.arialyy.aria.core.download.CheckDEntityUtil;
|
import com.arialyy.aria.core.download.CheckDEntityUtil;
|
||||||
import com.arialyy.aria.core.download.CheckDGEntityUtil;
|
import com.arialyy.aria.core.download.CheckDGEntityUtil;
|
||||||
import com.arialyy.aria.core.download.CheckFtpDirEntityUtil;
|
import com.arialyy.aria.core.download.CheckFtpDirEntityUtil;
|
||||||
import com.arialyy.aria.core.download.DGTaskWrapper;
|
import com.arialyy.aria.core.download.DGTaskWrapper;
|
||||||
import com.arialyy.aria.core.download.DTaskWrapper;
|
import com.arialyy.aria.core.download.DTaskWrapper;
|
||||||
import com.arialyy.aria.core.common.AbsEntity;
|
|
||||||
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
|
||||||
import com.arialyy.aria.core.inf.ICheckEntityUtil;
|
import com.arialyy.aria.core.inf.ICheckEntityUtil;
|
||||||
import com.arialyy.aria.core.task.ITask;
|
|
||||||
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
|
||||||
import com.arialyy.aria.core.listener.ISchedulers;
|
import com.arialyy.aria.core.listener.ISchedulers;
|
||||||
import com.arialyy.aria.core.scheduler.TaskSchedulers;
|
import com.arialyy.aria.core.scheduler.TaskSchedulers;
|
||||||
|
import com.arialyy.aria.core.task.ITask;
|
||||||
import com.arialyy.aria.core.upload.CheckUEntityUtil;
|
import com.arialyy.aria.core.upload.CheckUEntityUtil;
|
||||||
import com.arialyy.aria.core.upload.UTaskWrapper;
|
import com.arialyy.aria.core.upload.UTaskWrapper;
|
||||||
|
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
||||||
|
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
import com.arialyy.aria.util.CommonUtil;
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
@@ -46,6 +46,10 @@ public abstract class FeatureController {
|
|||||||
private final String TAG;
|
private final String TAG;
|
||||||
|
|
||||||
private AbsTaskWrapper mTaskWrapper;
|
private AbsTaskWrapper mTaskWrapper;
|
||||||
|
/**
|
||||||
|
* 是否忽略权限检查 true 忽略权限检查
|
||||||
|
*/
|
||||||
|
private boolean ignoreCheckPermissions = false;
|
||||||
|
|
||||||
FeatureController(AbsTaskWrapper wrapper) {
|
FeatureController(AbsTaskWrapper wrapper) {
|
||||||
mTaskWrapper = wrapper;
|
mTaskWrapper = wrapper;
|
||||||
@@ -87,6 +91,20 @@ public abstract class FeatureController {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否忽略权限检查
|
||||||
|
*/
|
||||||
|
public void ignoreCheckPermissions() {
|
||||||
|
this.ignoreCheckPermissions = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 强制执行任务,不管文件路径是否被占用
|
||||||
|
*/
|
||||||
|
public void ignoreFilePathOccupy() {
|
||||||
|
mTaskWrapper.setIgnoreFilePathOccupy(true);
|
||||||
|
}
|
||||||
|
|
||||||
protected AbsTaskWrapper getTaskWrapper() {
|
protected AbsTaskWrapper getTaskWrapper() {
|
||||||
return mTaskWrapper;
|
return mTaskWrapper;
|
||||||
}
|
}
|
||||||
@@ -111,7 +129,7 @@ public abstract class FeatureController {
|
|||||||
* 如果检查实体失败,将错误回调
|
* 如果检查实体失败,将错误回调
|
||||||
*/
|
*/
|
||||||
boolean checkConfig() {
|
boolean checkConfig() {
|
||||||
if (!checkPermission()) {
|
if (!ignoreCheckPermissions && !checkPermission()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
boolean b = checkEntity();
|
boolean b = checkEntity();
|
||||||
@@ -134,21 +152,21 @@ public abstract class FeatureController {
|
|||||||
*/
|
*/
|
||||||
private boolean checkPermission() {
|
private boolean checkPermission() {
|
||||||
|
|
||||||
if (AriaManager.getInstance()
|
if (AriaConfig.getInstance()
|
||||||
.getAPP()
|
.getAPP()
|
||||||
.checkCallingOrSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
.checkCallingOrSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
!= PackageManager.PERMISSION_GRANTED) {
|
!= PackageManager.PERMISSION_GRANTED) {
|
||||||
ALog.e(TAG, "启动失败,缺少权限:Manifest.permission.WRITE_EXTERNAL_STORAGE");
|
ALog.e(TAG, "启动失败,缺少权限:Manifest.permission.WRITE_EXTERNAL_STORAGE");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (AriaManager.getInstance()
|
if (AriaConfig.getInstance()
|
||||||
.getAPP()
|
.getAPP()
|
||||||
.checkCallingOrSelfPermission(Manifest.permission.INTERNET)
|
.checkCallingOrSelfPermission(Manifest.permission.INTERNET)
|
||||||
!= PackageManager.PERMISSION_GRANTED) {
|
!= PackageManager.PERMISSION_GRANTED) {
|
||||||
ALog.e(TAG, "启动失败,缺少权限:Manifest.permission.INTERNET");
|
ALog.e(TAG, "启动失败,缺少权限:Manifest.permission.INTERNET");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (AriaManager.getInstance()
|
if (AriaConfig.getInstance()
|
||||||
.getAPP()
|
.getAPP()
|
||||||
.checkCallingOrSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
|
.checkCallingOrSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||||
!= PackageManager.PERMISSION_GRANTED) {
|
!= PackageManager.PERMISSION_GRANTED) {
|
||||||
|
|||||||
@@ -30,6 +30,14 @@ public interface INormalFeature {
|
|||||||
*/
|
*/
|
||||||
void resume();
|
void resume();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 正常来说,当执行队列满时,调用恢复任务接口,只能将任务放到缓存队列中。
|
||||||
|
* 如果希望调用恢复接口,马上进入执行队列,需要使用该方法
|
||||||
|
*
|
||||||
|
* @param newStart true 立即将任务恢复到执行队列中
|
||||||
|
*/
|
||||||
|
void resume(boolean newStart);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除任务
|
* 删除任务
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -16,11 +16,12 @@
|
|||||||
package com.arialyy.aria.core.common.controller;
|
package com.arialyy.aria.core.common.controller;
|
||||||
|
|
||||||
import com.arialyy.aria.core.command.CancelCmd;
|
import com.arialyy.aria.core.command.CancelCmd;
|
||||||
|
import com.arialyy.aria.core.command.CmdHelper;
|
||||||
import com.arialyy.aria.core.command.NormalCmdFactory;
|
import com.arialyy.aria.core.command.NormalCmdFactory;
|
||||||
|
import com.arialyy.aria.core.command.StartCmd;
|
||||||
import com.arialyy.aria.core.event.EventMsgUtil;
|
import com.arialyy.aria.core.event.EventMsgUtil;
|
||||||
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
import com.arialyy.aria.core.command.CmdHelper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 启动控制器
|
* 启动控制器
|
||||||
@@ -49,10 +50,23 @@ public final class NormalController extends FeatureController implements INormal
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void resume() {
|
public void resume() {
|
||||||
|
resume(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 正常来说,当执行队列满时,调用恢复任务接口,只能将任务放到缓存队列中。
|
||||||
|
* 如果希望调用恢复接口,马上进入执行队列,需要使用该方法
|
||||||
|
*
|
||||||
|
* @param newStart true 立即将任务恢复到执行队列中
|
||||||
|
*/
|
||||||
|
@Override public void resume(boolean newStart) {
|
||||||
if (checkConfig()) {
|
if (checkConfig()) {
|
||||||
|
StartCmd cmd =
|
||||||
|
(StartCmd) CmdHelper.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_START,
|
||||||
|
checkTaskType());
|
||||||
|
cmd.setNewStart(newStart);
|
||||||
EventMsgUtil.getDefault()
|
EventMsgUtil.getDefault()
|
||||||
.post(CmdHelper.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_START,
|
.post(cmd);
|
||||||
checkTaskType()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,16 +16,14 @@
|
|||||||
package com.arialyy.aria.core.download;
|
package com.arialyy.aria.core.download;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import com.arialyy.aria.core.common.ErrorCode;
|
|
||||||
import com.arialyy.aria.core.inf.ICheckEntityUtil;
|
import com.arialyy.aria.core.inf.ICheckEntityUtil;
|
||||||
import com.arialyy.aria.core.inf.IOptionConstant;
|
import com.arialyy.aria.core.inf.IOptionConstant;
|
||||||
import com.arialyy.aria.core.inf.IRecordHandler;
|
|
||||||
import com.arialyy.aria.core.inf.ITargetHandler;
|
import com.arialyy.aria.core.inf.ITargetHandler;
|
||||||
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
||||||
import com.arialyy.aria.orm.DbEntity;
|
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
import com.arialyy.aria.util.CheckUtil;
|
import com.arialyy.aria.util.CheckUtil;
|
||||||
import com.arialyy.aria.util.CommonUtil;
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
|
import com.arialyy.aria.util.FileUtil;
|
||||||
import com.arialyy.aria.util.RecordUtil;
|
import com.arialyy.aria.util.RecordUtil;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
@@ -68,23 +66,18 @@ public class CheckDEntityUtil implements ICheckEntityUtil {
|
|||||||
File file = new File(mWrapper.getTempFilePath());
|
File file = new File(mWrapper.getTempFilePath());
|
||||||
Object bw = mWrapper.getM3U8Params().getParam(IOptionConstant.bandWidth);
|
Object bw = mWrapper.getM3U8Params().getParam(IOptionConstant.bandWidth);
|
||||||
int bandWidth = bw == null ? 0 : (int) bw;
|
int bandWidth = bw == null ? 0 : (int) bw;
|
||||||
// 缓存文件夹格式:问文件夹/.文件名_码率
|
String cacheDir = FileUtil.getTsCacheDir(file.getPath(), bandWidth);
|
||||||
String cacheDir = String.format("%s/.%s_%s", file.getParent(), file.getName(), bandWidth);
|
|
||||||
|
|
||||||
mWrapper.getM3U8Params().setParams(IOptionConstant.cacheDir, cacheDir);
|
mWrapper.getM3U8Params().setParams(IOptionConstant.cacheDir, cacheDir);
|
||||||
M3U8Entity m3U8Entity = mEntity.getM3U8Entity();
|
M3U8Entity m3U8Entity = mEntity.getM3U8Entity();
|
||||||
|
|
||||||
Object temp = mWrapper.getM3U8Params().getParam(IOptionConstant.generateIndexFileTemp);
|
|
||||||
boolean generateIndexFileTemp = temp != null && (boolean) temp;
|
|
||||||
if (m3U8Entity == null) {
|
if (m3U8Entity == null) {
|
||||||
m3U8Entity = new M3U8Entity();
|
m3U8Entity = new M3U8Entity();
|
||||||
m3U8Entity.setFilePath(mEntity.getFilePath());
|
m3U8Entity.setFilePath(mEntity.getFilePath());
|
||||||
m3U8Entity.setPeerIndex(0);
|
m3U8Entity.setPeerIndex(0);
|
||||||
m3U8Entity.setCacheDir(cacheDir);
|
m3U8Entity.setCacheDir(cacheDir);
|
||||||
m3U8Entity.setGenerateIndexFile(generateIndexFileTemp);
|
|
||||||
m3U8Entity.insert();
|
m3U8Entity.insert();
|
||||||
} else {
|
} else {
|
||||||
m3U8Entity.setGenerateIndexFile(generateIndexFileTemp);
|
|
||||||
m3U8Entity.update();
|
m3U8Entity.update();
|
||||||
}
|
}
|
||||||
if (mWrapper.getRequestType() == ITaskWrapper.M3U8_VOD) {
|
if (mWrapper.getRequestType() == ITaskWrapper.M3U8_VOD) {
|
||||||
@@ -141,14 +134,8 @@ public class CheckDEntityUtil implements ICheckEntityUtil {
|
|||||||
//设置文件保存路径,如果新文件路径和旧文件路径不同,则修改路径
|
//设置文件保存路径,如果新文件路径和旧文件路径不同,则修改路径
|
||||||
if (!filePath.equals(mEntity.getFilePath())) {
|
if (!filePath.equals(mEntity.getFilePath())) {
|
||||||
// 检查路径冲突
|
// 检查路径冲突
|
||||||
if (DbEntity.checkDataExist(DownloadEntity.class, "downloadPath=?", filePath)) {
|
if (!CheckUtil.checkDPathConflicts(mWrapper.isIgnoreFilePathOccupy(), filePath)) {
|
||||||
if (!mWrapper.isForceDownload()) {
|
return false;
|
||||||
ALog.e(TAG, String.format("下载失败,保存路径【%s】已经被其它任务占用,请设置其它保存路径", filePath));
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
ALog.w(TAG, String.format("保存路径【%s】已经被其它任务占用,当前任务将覆盖该路径的文件", filePath));
|
|
||||||
RecordUtil.delTaskRecord(filePath, IRecordHandler.TYPE_DOWNLOAD);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
File newFile = new File(filePath);
|
File newFile = new File(filePath);
|
||||||
|
|||||||
@@ -16,12 +16,12 @@
|
|||||||
package com.arialyy.aria.core.download;
|
package com.arialyy.aria.core.download;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import com.arialyy.aria.core.common.ErrorCode;
|
|
||||||
import com.arialyy.aria.core.common.RequestEnum;
|
import com.arialyy.aria.core.common.RequestEnum;
|
||||||
import com.arialyy.aria.core.inf.ICheckEntityUtil;
|
import com.arialyy.aria.core.inf.ICheckEntityUtil;
|
||||||
import com.arialyy.aria.core.inf.IOptionConstant;
|
import com.arialyy.aria.core.inf.IOptionConstant;
|
||||||
import com.arialyy.aria.orm.DbEntity;
|
import com.arialyy.aria.orm.DbEntity;
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
|
import com.arialyy.aria.util.CheckUtil;
|
||||||
import com.arialyy.aria.util.CommonUtil;
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
import com.arialyy.aria.util.RecordUtil;
|
import com.arialyy.aria.util.RecordUtil;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -70,10 +70,9 @@ public class CheckDGEntityUtil implements ICheckEntityUtil {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mEntity.getDirPath() == null || !mEntity.getDirPath().equals(mWrapper.getDirPathTemp()))
|
// 检查路径冲突
|
||||||
&& DbEntity.checkDataExist(DownloadGroupEntity.class, "dirPath=?",
|
if (mWrapper.isNewTask() && !CheckUtil.checkDGPathConflicts(mWrapper.isIgnoreFilePathOccupy(),
|
||||||
mWrapper.getDirPathTemp())) {
|
mWrapper.getDirPathTemp())) {
|
||||||
ALog.e(TAG, String.format("文件夹路径【%s】已被其它任务占用,请重新设置文件夹路径", mWrapper.getDirPathTemp()));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,9 +169,8 @@ public class CheckDGEntityUtil implements ICheckEntityUtil {
|
|||||||
if (!newName.equals(entity.getFileName())) {
|
if (!newName.equals(entity.getFileName())) {
|
||||||
String oldPath = mEntity.getDirPath() + "/" + entity.getFileName();
|
String oldPath = mEntity.getDirPath() + "/" + entity.getFileName();
|
||||||
String newPath = mEntity.getDirPath() + "/" + newName;
|
String newPath = mEntity.getDirPath() + "/" + newName;
|
||||||
if (DbEntity.checkDataExist(DownloadEntity.class, "downloadPath=? or isComplete='true'",
|
if (DbEntity.checkDataExist(DownloadEntity.class, "downloadPath=?", newPath)) {
|
||||||
newPath)) {
|
ALog.w(TAG, String.format("更新文件名失败,路径【%s】被其它任务占用", newPath));
|
||||||
ALog.w(TAG, String.format("更新文件名失败,路径【%s】已存在或文件已下载", newPath));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.arialyy.aria.core.download;
|
|||||||
import androidx.annotation.CheckResult;
|
import androidx.annotation.CheckResult;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import com.arialyy.annotations.TaskEnum;
|
import com.arialyy.annotations.TaskEnum;
|
||||||
|
import com.arialyy.aria.core.AriaConfig;
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaManager;
|
||||||
import com.arialyy.aria.core.command.CancelAllCmd;
|
import com.arialyy.aria.core.command.CancelAllCmd;
|
||||||
import com.arialyy.aria.core.command.CmdHelper;
|
import com.arialyy.aria.core.command.CmdHelper;
|
||||||
@@ -64,7 +65,7 @@ public class DownloadReceiver extends AbsReceiver {
|
|||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public DownloadReceiver setMaxSpeed(int maxSpeed) {
|
public DownloadReceiver setMaxSpeed(int maxSpeed) {
|
||||||
AriaManager.getInstance().getDownloadConfig().setMaxSpeed(maxSpeed);
|
AriaConfig.getInstance().getDConfig().setMaxSpeed(maxSpeed);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,10 +288,10 @@ public class DownloadReceiver extends AbsReceiver {
|
|||||||
* @return 如果实体不存在,返回null
|
* @return 如果实体不存在,返回null
|
||||||
*/
|
*/
|
||||||
public DownloadGroupEntity getGroupEntity(List<String> urls) {
|
public DownloadGroupEntity getGroupEntity(List<String> urls) {
|
||||||
if (CheckUtil.checkDownloadUrlsIsEmpty(urls)){
|
if (CheckUtil.checkDownloadUrlsIsEmpty(urls)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return DbDataHelper.getDGEntity(CommonUtil.getMd5Code(urls));
|
return DbDataHelper.getDGEntityByHash(CommonUtil.getMd5Code(urls));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -303,7 +304,7 @@ public class DownloadReceiver extends AbsReceiver {
|
|||||||
if (!CheckUtil.checkUrl(url)) {
|
if (!CheckUtil.checkUrl(url)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return DbDataHelper.getDGEntity(url);
|
return DbDataHelper.getDGEntityByHash(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ package com.arialyy.aria.core.download.m3u8;
|
|||||||
|
|
||||||
import com.arialyy.aria.core.common.BaseOption;
|
import com.arialyy.aria.core.common.BaseOption;
|
||||||
import com.arialyy.aria.core.processor.IBandWidthUrlConverter;
|
import com.arialyy.aria.core.processor.IBandWidthUrlConverter;
|
||||||
|
import com.arialyy.aria.core.processor.IKeyUrlConverter;
|
||||||
import com.arialyy.aria.core.processor.ITsMergeHandler;
|
import com.arialyy.aria.core.processor.ITsMergeHandler;
|
||||||
import com.arialyy.aria.core.processor.IVodTsUrlConverter;
|
|
||||||
import com.arialyy.aria.util.CheckUtil;
|
import com.arialyy.aria.util.CheckUtil;
|
||||||
import com.arialyy.aria.util.ComponentUtil;
|
import com.arialyy.aria.util.ComponentUtil;
|
||||||
|
|
||||||
@@ -27,11 +27,12 @@ import com.arialyy.aria.util.ComponentUtil;
|
|||||||
*/
|
*/
|
||||||
public class M3U8Option<OP extends M3U8Option> extends BaseOption {
|
public class M3U8Option<OP extends M3U8Option> extends BaseOption {
|
||||||
|
|
||||||
private boolean generateIndexFileTemp = false;
|
private boolean generateIndexFile = false;
|
||||||
private boolean mergeFile = false;
|
private boolean mergeFile = true;
|
||||||
private int bandWidth;
|
private int bandWidth;
|
||||||
private ITsMergeHandler mergeHandler;
|
private ITsMergeHandler mergeHandler;
|
||||||
private IBandWidthUrlConverter bandWidthUrlConverter;
|
private IBandWidthUrlConverter bandWidthUrlConverter;
|
||||||
|
private IKeyUrlConverter keyUrlConverter;
|
||||||
|
|
||||||
M3U8Option() {
|
M3U8Option() {
|
||||||
super();
|
super();
|
||||||
@@ -41,9 +42,10 @@ public class M3U8Option<OP extends M3U8Option> extends BaseOption {
|
|||||||
/**
|
/**
|
||||||
* 生成m3u8索引文件
|
* 生成m3u8索引文件
|
||||||
* 注意:创建索引文件,{@link #merge(boolean)}方法设置与否都不再合并文件
|
* 注意:创建索引文件,{@link #merge(boolean)}方法设置与否都不再合并文件
|
||||||
|
* 如果是直播文件下载,创建索引文件的操作将导致只能同时下载一个切片!!
|
||||||
*/
|
*/
|
||||||
public OP generateIndexFile() {
|
public OP generateIndexFile() {
|
||||||
this.generateIndexFileTemp = true;
|
this.generateIndexFile = true;
|
||||||
return (OP) this;
|
return (OP) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,4 +90,15 @@ public class M3U8Option<OP extends M3U8Option> extends BaseOption {
|
|||||||
this.bandWidthUrlConverter = bandWidthUrlConverter;
|
this.bandWidthUrlConverter = bandWidthUrlConverter;
|
||||||
return (OP) this;
|
return (OP) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* M3U8 密钥url转换器,对于某些服务器,密钥的下载地址是被加密的,因此需要使用该方法将被加密的密钥解密成可被识别的http地址
|
||||||
|
*
|
||||||
|
* @param keyUrlConverter {@link IKeyUrlConverter}
|
||||||
|
*/
|
||||||
|
public OP setKeyUrlConverter(IKeyUrlConverter keyUrlConverter) {
|
||||||
|
CheckUtil.checkMemberClass(keyUrlConverter.getClass());
|
||||||
|
this.keyUrlConverter = keyUrlConverter;
|
||||||
|
return (OP) this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ class DNormalConfigHandler<TARGET extends AbsTarget> implements IConfigHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setForceDownload(boolean forceDownload) {
|
void setForceDownload(boolean forceDownload) {
|
||||||
getWrapper().setForceDownload(forceDownload);
|
getWrapper().setIgnoreFilePathOccupy(forceDownload);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setUrl(String url) {
|
void setUrl(String url) {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ public class FtpBuilderTarget extends AbsBuilderTarget<FtpBuilderTarget> {
|
|||||||
mConfigHandler = new DNormalConfigHandler<>(this, -1);
|
mConfigHandler = new DNormalConfigHandler<>(this, -1);
|
||||||
mConfigHandler.setUrl(url);
|
mConfigHandler.setUrl(url);
|
||||||
getTaskWrapper().setRequestType(ITaskWrapper.D_FTP);
|
getTaskWrapper().setRequestType(ITaskWrapper.D_FTP);
|
||||||
|
getTaskWrapper().setNewTask(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -70,7 +71,9 @@ public class FtpBuilderTarget extends AbsBuilderTarget<FtpBuilderTarget> {
|
|||||||
*
|
*
|
||||||
* @param filePath 路径必须为文件路径,不能为文件夹路径
|
* @param filePath 路径必须为文件路径,不能为文件夹路径
|
||||||
* @param forceDownload {@code true}强制下载,不考虑文件路径是否被占用
|
* @param forceDownload {@code true}强制下载,不考虑文件路径是否被占用
|
||||||
|
* @deprecated 使用 {@link #ignoreFilePathOccupy()}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
|
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
|
||||||
public FtpBuilderTarget setFilePath(@NonNull String filePath, boolean forceDownload) {
|
public FtpBuilderTarget setFilePath(@NonNull String filePath, boolean forceDownload) {
|
||||||
mConfigHandler.setTempFilePath(filePath);
|
mConfigHandler.setTempFilePath(filePath);
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public class FtpDirBuilderTarget extends AbsBuilderTarget<FtpDirBuilderTarget> {
|
|||||||
this.url = url;
|
this.url = url;
|
||||||
mConfigHandler = new FtpDirConfigHandler<>(this, -1);
|
mConfigHandler = new FtpDirConfigHandler<>(this, -1);
|
||||||
getEntity().setGroupHash(url);
|
getEntity().setGroupHash(url);
|
||||||
|
getTaskWrapper().setNewTask(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ public class FtpDirNormalTarget extends AbsNormalTarget<FtpDirNormalTarget> {
|
|||||||
|
|
||||||
FtpDirNormalTarget(long taskId) {
|
FtpDirNormalTarget(long taskId) {
|
||||||
mConfigHandler = new FtpDirConfigHandler<>(this, taskId);
|
mConfigHandler = new FtpDirConfigHandler<>(this, taskId);
|
||||||
|
getTaskWrapper().setNewTask(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean isRunning() {
|
@Override public boolean isRunning() {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ public class FtpNormalTarget extends AbsNormalTarget<FtpNormalTarget> {
|
|||||||
FtpNormalTarget(long taskId) {
|
FtpNormalTarget(long taskId) {
|
||||||
mConfigHandler = new DNormalConfigHandler<>(this, taskId);
|
mConfigHandler = new DNormalConfigHandler<>(this, taskId);
|
||||||
getTaskWrapper().setRequestType(ITaskWrapper.D_FTP);
|
getTaskWrapper().setRequestType(ITaskWrapper.D_FTP);
|
||||||
|
getTaskWrapper().setNewTask(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -34,8 +34,9 @@ public class GroupBuilderTarget extends AbsBuilderTarget<GroupBuilderTarget> {
|
|||||||
|
|
||||||
GroupBuilderTarget(List<String> urls) {
|
GroupBuilderTarget(List<String> urls) {
|
||||||
mConfigHandler = new HttpGroupConfigHandler<>(this, -1);
|
mConfigHandler = new HttpGroupConfigHandler<>(this, -1);
|
||||||
getTaskWrapper().setRequestType(ITaskWrapper.DG_HTTP);
|
|
||||||
mConfigHandler.setGroupUrl(urls);
|
mConfigHandler.setGroupUrl(urls);
|
||||||
|
getTaskWrapper().setRequestType(ITaskWrapper.DG_HTTP);
|
||||||
|
getTaskWrapper().setNewTask(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ public class GroupNormalTarget extends AbsNormalTarget<GroupNormalTarget> {
|
|||||||
GroupNormalTarget(long taskId) {
|
GroupNormalTarget(long taskId) {
|
||||||
mConfigHandler = new HttpGroupConfigHandler<>(this, taskId);
|
mConfigHandler = new HttpGroupConfigHandler<>(this, taskId);
|
||||||
getTaskWrapper().setRequestType(ITaskWrapper.DG_HTTP);
|
getTaskWrapper().setRequestType(ITaskWrapper.DG_HTTP);
|
||||||
|
getTaskWrapper().setNewTask(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -22,12 +22,9 @@ import com.arialyy.aria.core.common.HttpOption;
|
|||||||
import com.arialyy.aria.core.download.DTaskWrapper;
|
import com.arialyy.aria.core.download.DTaskWrapper;
|
||||||
import com.arialyy.aria.core.download.m3u8.M3U8LiveOption;
|
import com.arialyy.aria.core.download.m3u8.M3U8LiveOption;
|
||||||
import com.arialyy.aria.core.download.m3u8.M3U8VodOption;
|
import com.arialyy.aria.core.download.m3u8.M3U8VodOption;
|
||||||
import com.arialyy.aria.core.inf.IOptionConstant;
|
|
||||||
import com.arialyy.aria.core.inf.Suggest;
|
import com.arialyy.aria.core.inf.Suggest;
|
||||||
import com.arialyy.aria.core.processor.IHttpFileLenAdapter;
|
|
||||||
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
||||||
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
||||||
import com.arialyy.aria.util.CheckUtil;
|
|
||||||
|
|
||||||
public class HttpBuilderTarget extends AbsBuilderTarget<HttpBuilderTarget> {
|
public class HttpBuilderTarget extends AbsBuilderTarget<HttpBuilderTarget> {
|
||||||
|
|
||||||
@@ -35,13 +32,14 @@ public class HttpBuilderTarget extends AbsBuilderTarget<HttpBuilderTarget> {
|
|||||||
|
|
||||||
HttpBuilderTarget(String url) {
|
HttpBuilderTarget(String url) {
|
||||||
mConfigHandler = new DNormalConfigHandler<>(this, -1);
|
mConfigHandler = new DNormalConfigHandler<>(this, -1);
|
||||||
getTaskWrapper().setRequestType(ITaskWrapper.D_HTTP);
|
|
||||||
mConfigHandler.setUrl(url);
|
mConfigHandler.setUrl(url);
|
||||||
|
getTaskWrapper().setRequestType(ITaskWrapper.D_HTTP);
|
||||||
|
getTaskWrapper().setNewTask(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
|
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
|
||||||
public HttpBuilderTarget m3u8VodOption(M3U8VodOption m3U8VodOption) {
|
public HttpBuilderTarget m3u8VodOption(M3U8VodOption m3U8VodOption) {
|
||||||
if (m3U8VodOption == null){
|
if (m3U8VodOption == null) {
|
||||||
throw new NullPointerException("m3u8任务设置为空");
|
throw new NullPointerException("m3u8任务设置为空");
|
||||||
}
|
}
|
||||||
getTaskWrapper().setRequestType(AbsTaskWrapper.M3U8_VOD);
|
getTaskWrapper().setRequestType(AbsTaskWrapper.M3U8_VOD);
|
||||||
@@ -52,7 +50,7 @@ public class HttpBuilderTarget extends AbsBuilderTarget<HttpBuilderTarget> {
|
|||||||
|
|
||||||
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
|
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
|
||||||
public HttpBuilderTarget m3u8LiveOption(M3U8LiveOption m3U8LiveOption) {
|
public HttpBuilderTarget m3u8LiveOption(M3U8LiveOption m3U8LiveOption) {
|
||||||
if (m3U8LiveOption == null){
|
if (m3U8LiveOption == null) {
|
||||||
throw new NullPointerException("m3u8任务设置为空");
|
throw new NullPointerException("m3u8任务设置为空");
|
||||||
}
|
}
|
||||||
getTaskWrapper().setRequestType(AbsTaskWrapper.M3U8_LIVE);
|
getTaskWrapper().setRequestType(AbsTaskWrapper.M3U8_LIVE);
|
||||||
@@ -92,7 +90,9 @@ public class HttpBuilderTarget extends AbsBuilderTarget<HttpBuilderTarget> {
|
|||||||
*
|
*
|
||||||
* @param filePath 路径必须为文件路径,不能为文件夹路径
|
* @param filePath 路径必须为文件路径,不能为文件夹路径
|
||||||
* @param forceDownload {@code true}强制下载,不考虑文件路径是否被占用
|
* @param forceDownload {@code true}强制下载,不考虑文件路径是否被占用
|
||||||
|
* @deprecated 使用 {@link #ignoreFilePathOccupy()}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
|
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
|
||||||
public HttpBuilderTarget setFilePath(@NonNull String filePath, boolean forceDownload) {
|
public HttpBuilderTarget setFilePath(@NonNull String filePath, boolean forceDownload) {
|
||||||
mConfigHandler.setTempFilePath(filePath);
|
mConfigHandler.setTempFilePath(filePath);
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public class HttpNormalTarget extends AbsNormalTarget<HttpNormalTarget> {
|
|||||||
HttpNormalTarget(long taskId) {
|
HttpNormalTarget(long taskId) {
|
||||||
mConfigHandler = new DNormalConfigHandler<>(this, taskId);
|
mConfigHandler = new DNormalConfigHandler<>(this, taskId);
|
||||||
getTaskWrapper().setRequestType(getTaskWrapper().getEntity().getTaskType());
|
getTaskWrapper().setRequestType(getTaskWrapper().getEntity().getTaskType());
|
||||||
|
getTaskWrapper().setNewTask(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
|
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ public class M3U8NormalTarget extends AbsNormalTarget<M3U8NormalTarget> {
|
|||||||
|
|
||||||
M3U8NormalTarget(DTaskWrapper wrapper) {
|
M3U8NormalTarget(DTaskWrapper wrapper) {
|
||||||
setTaskWrapper(wrapper);
|
setTaskWrapper(wrapper);
|
||||||
|
getTaskWrapper().setNewTask(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ public class TcpBuilderTarget extends AbsBuilderTarget<TcpBuilderTarget> {
|
|||||||
TcpBuilderTarget(String ip, int port) {
|
TcpBuilderTarget(String ip, int port) {
|
||||||
mConfigHandler = new DNormalConfigHandler<>(this, -1);
|
mConfigHandler = new DNormalConfigHandler<>(this, -1);
|
||||||
getTaskWrapper().setRequestType(ITaskWrapper.D_TCP);
|
getTaskWrapper().setRequestType(ITaskWrapper.D_TCP);
|
||||||
|
getTaskWrapper().setNewTask(true);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
///**
|
///**
|
||||||
@@ -56,18 +57,4 @@ public class TcpBuilderTarget extends AbsBuilderTarget<TcpBuilderTarget> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置文件存储路径,如果需要修改新的文件名,修改路径便可。
|
|
||||||
* 如:原文件路径 /mnt/sdcard/test.zip
|
|
||||||
* 如果需要将test.zip改为game.zip,只需要重新设置文件路径为:/mnt/sdcard/game.zip
|
|
||||||
*
|
|
||||||
* @param filePath 路径必须为文件路径,不能为文件夹路径
|
|
||||||
* @param forceDownload {@code true}强制下载,不考虑文件路径是否被占用
|
|
||||||
*/
|
|
||||||
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
|
|
||||||
public TcpBuilderTarget setFilePath(@NonNull String filePath, boolean forceDownload) {
|
|
||||||
mConfigHandler.setTempFilePath(filePath);
|
|
||||||
mConfigHandler.setForceDownload(forceDownload);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,14 +42,17 @@ class DGTaskWrapperFactory implements IGroupWrapperFactory<DownloadGroupEntity,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public DGTaskWrapper getGroupWrapper(long taskId) {
|
@Override public DGTaskWrapper getGroupWrapper(long taskId) {
|
||||||
|
DGTaskWrapper wrapper;
|
||||||
if (taskId == -1) {
|
if (taskId == -1) {
|
||||||
return new DGTaskWrapper(new DownloadGroupEntity());
|
wrapper = new DGTaskWrapper(new DownloadGroupEntity());
|
||||||
}
|
}else {
|
||||||
DownloadGroupEntity entity = getOrCreateHttpDGEntity(taskId);
|
DownloadGroupEntity entity = getOrCreateHttpDGEntity(taskId);
|
||||||
DGTaskWrapper wrapper = new DGTaskWrapper(entity);
|
wrapper = new DGTaskWrapper(entity);
|
||||||
if (entity.getSubEntities() != null && !entity.getSubEntities().isEmpty()) {
|
if (entity.getSubEntities() != null && !entity.getSubEntities().isEmpty()) {
|
||||||
wrapper.setSubTaskWrapper(DbDataHelper.createDGSubTaskWrapper(entity));
|
wrapper.setSubTaskWrapper(DbDataHelper.createDGSubTaskWrapper(entity));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
wrapper.setRequestType(wrapper.getEntity().getTaskType());
|
||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,11 +45,14 @@ class DTaskWrapperFactory implements INormalTEFactory<DownloadEntity, DTaskWrapp
|
|||||||
* 通过下载地址创建任务实体
|
* 通过下载地址创建任务实体
|
||||||
*/
|
*/
|
||||||
@Override public DTaskWrapper create(long taskId) {
|
@Override public DTaskWrapper create(long taskId) {
|
||||||
|
DTaskWrapper wrapper;
|
||||||
if (taskId == -1) {
|
if (taskId == -1) {
|
||||||
return new DTaskWrapper(new DownloadEntity());
|
wrapper = new DTaskWrapper(new DownloadEntity());
|
||||||
|
} else {
|
||||||
|
wrapper = new DTaskWrapper(getEntity(taskId));
|
||||||
}
|
}
|
||||||
|
wrapper.setRequestType(wrapper.getEntity().getTaskType());
|
||||||
return new DTaskWrapper(getEntity(taskId));
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package com.arialyy.aria.core.manager;
|
|||||||
|
|
||||||
import com.arialyy.aria.core.upload.UTaskWrapper;
|
import com.arialyy.aria.core.upload.UTaskWrapper;
|
||||||
import com.arialyy.aria.core.upload.UploadEntity;
|
import com.arialyy.aria.core.upload.UploadEntity;
|
||||||
|
import com.arialyy.aria.util.ALog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Aria.Lao on 2017/11/1. 任务实体工厂
|
* Created by Aria.Lao on 2017/11/1. 任务实体工厂
|
||||||
@@ -38,10 +39,15 @@ class UTaskWrapperFactory implements INormalTEFactory<UploadEntity, UTaskWrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public UTaskWrapper create(long taskId) {
|
@Override public UTaskWrapper create(long taskId) {
|
||||||
|
UTaskWrapper wrapper;
|
||||||
if (taskId == -1) {
|
if (taskId == -1) {
|
||||||
return new UTaskWrapper(new UploadEntity());
|
wrapper = new UTaskWrapper(new UploadEntity());
|
||||||
|
} else {
|
||||||
|
wrapper = new UTaskWrapper(getUploadEntity(taskId));
|
||||||
}
|
}
|
||||||
return new UTaskWrapper(getUploadEntity(taskId));
|
|
||||||
|
wrapper.setRequestType(wrapper.getEntity().getTaskType());
|
||||||
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,13 +16,13 @@
|
|||||||
|
|
||||||
package com.arialyy.aria.core.queue;
|
package com.arialyy.aria.core.queue;
|
||||||
|
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaConfig;
|
||||||
import com.arialyy.aria.core.download.DGTaskWrapper;
|
import com.arialyy.aria.core.download.DGTaskWrapper;
|
||||||
import com.arialyy.aria.core.task.DownloadGroupTask;
|
|
||||||
import com.arialyy.aria.core.event.DGMaxNumEvent;
|
import com.arialyy.aria.core.event.DGMaxNumEvent;
|
||||||
import com.arialyy.aria.core.event.Event;
|
import com.arialyy.aria.core.event.Event;
|
||||||
import com.arialyy.aria.core.event.EventMsgUtil;
|
import com.arialyy.aria.core.event.EventMsgUtil;
|
||||||
import com.arialyy.aria.core.scheduler.TaskSchedulers;
|
import com.arialyy.aria.core.scheduler.TaskSchedulers;
|
||||||
|
import com.arialyy.aria.core.task.DownloadGroupTask;
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -57,7 +57,7 @@ public class DGroupTaskQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public int getMaxTaskNum() {
|
@Override public int getMaxTaskNum() {
|
||||||
return AriaManager.getInstance().getDGroupConfig().getMaxTaskNum();
|
return AriaConfig.getInstance().getDConfig().getMaxTaskNum();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public DownloadGroupTask createTask(DGTaskWrapper wrapper) {
|
@Override public DownloadGroupTask createTask(DGTaskWrapper wrapper) {
|
||||||
@@ -74,6 +74,6 @@ public class DGroupTaskQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public int getOldMaxNum() {
|
@Override public int getOldMaxNum() {
|
||||||
return AriaManager.getInstance().getDGroupConfig().oldMaxTaskNum;
|
return AriaConfig.getInstance().getDGConfig().oldMaxTaskNum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,14 +16,14 @@
|
|||||||
|
|
||||||
package com.arialyy.aria.core.queue;
|
package com.arialyy.aria.core.queue;
|
||||||
|
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaConfig;
|
||||||
import com.arialyy.aria.core.download.DTaskWrapper;
|
import com.arialyy.aria.core.download.DTaskWrapper;
|
||||||
import com.arialyy.aria.core.task.DownloadTask;
|
|
||||||
import com.arialyy.aria.core.event.DMaxNumEvent;
|
import com.arialyy.aria.core.event.DMaxNumEvent;
|
||||||
import com.arialyy.aria.core.event.Event;
|
import com.arialyy.aria.core.event.Event;
|
||||||
import com.arialyy.aria.core.event.EventMsgUtil;
|
import com.arialyy.aria.core.event.EventMsgUtil;
|
||||||
import com.arialyy.aria.core.inf.TaskSchedulerType;
|
import com.arialyy.aria.core.inf.TaskSchedulerType;
|
||||||
import com.arialyy.aria.core.scheduler.TaskSchedulers;
|
import com.arialyy.aria.core.scheduler.TaskSchedulers;
|
||||||
|
import com.arialyy.aria.core.task.DownloadTask;
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -60,7 +60,7 @@ public class DTaskQueue extends AbsTaskQueue<DownloadTask, DTaskWrapper> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public int getOldMaxNum() {
|
@Override public int getOldMaxNum() {
|
||||||
return AriaManager.getInstance().getDownloadConfig().oldMaxTaskNum;
|
return AriaConfig.getInstance().getDConfig().oldMaxTaskNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,7 +81,7 @@ public class DTaskQueue extends AbsTaskQueue<DownloadTask, DTaskWrapper> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int maxSize = AriaManager.getInstance().getDownloadConfig().getMaxTaskNum();
|
int maxSize = AriaConfig.getInstance().getDConfig().getMaxTaskNum();
|
||||||
int currentSize = mExecutePool.size();
|
int currentSize = mExecutePool.size();
|
||||||
if (currentSize == 0 || currentSize < maxSize) {
|
if (currentSize == 0 || currentSize < maxSize) {
|
||||||
startTask(task);
|
startTask(task);
|
||||||
@@ -126,6 +126,6 @@ public class DTaskQueue extends AbsTaskQueue<DownloadTask, DTaskWrapper> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public int getMaxTaskNum() {
|
@Override public int getMaxTaskNum() {
|
||||||
return AriaManager.getInstance().getDownloadConfig().getMaxTaskNum();
|
return AriaConfig.getInstance().getDConfig().getMaxTaskNum();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.arialyy.aria.core.queue;
|
package com.arialyy.aria.core.queue;
|
||||||
|
|
||||||
|
import com.arialyy.aria.core.AriaConfig;
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaManager;
|
||||||
import com.arialyy.aria.core.event.Event;
|
import com.arialyy.aria.core.event.Event;
|
||||||
import com.arialyy.aria.core.event.EventMsgUtil;
|
import com.arialyy.aria.core.event.EventMsgUtil;
|
||||||
@@ -55,11 +56,11 @@ public class UTaskQueue extends AbsTaskQueue<UploadTask, UTaskWrapper> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public int getOldMaxNum() {
|
@Override public int getOldMaxNum() {
|
||||||
return AriaManager.getInstance().getUploadConfig().oldMaxTaskNum;
|
return AriaConfig.getInstance().getUConfig().oldMaxTaskNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public int getMaxTaskNum() {
|
@Override public int getMaxTaskNum() {
|
||||||
return AriaManager.getInstance().getUploadConfig().getMaxTaskNum();
|
return AriaConfig.getInstance().getUConfig().getMaxTaskNum();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public UploadTask createTask(UTaskWrapper wrapper) {
|
@Override public UploadTask createTask(UTaskWrapper wrapper) {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.arialyy.aria.core.queue.pool;
|
package com.arialyy.aria.core.queue.pool;
|
||||||
|
|
||||||
|
import com.arialyy.aria.core.AriaConfig;
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaManager;
|
||||||
import com.arialyy.aria.core.task.AbsTask;
|
import com.arialyy.aria.core.task.AbsTask;
|
||||||
|
|
||||||
@@ -26,6 +27,6 @@ class DGLoadExecutePool<TASK extends AbsTask> extends DLoadExecutePool<TASK> {
|
|||||||
private final String TAG = "DGLoadExecutePool";
|
private final String TAG = "DGLoadExecutePool";
|
||||||
|
|
||||||
@Override protected int getMaxSize() {
|
@Override protected int getMaxSize() {
|
||||||
return AriaManager.getInstance().getDGroupConfig().getMaxTaskNum();
|
return AriaConfig.getInstance().getDGConfig().getMaxTaskNum();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.arialyy.aria.core.queue.pool;
|
package com.arialyy.aria.core.queue.pool;
|
||||||
|
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaConfig;
|
||||||
import com.arialyy.aria.core.task.AbsTask;
|
import com.arialyy.aria.core.task.AbsTask;
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
import com.arialyy.aria.util.CommonUtil;
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
@@ -30,7 +30,7 @@ class DLoadExecutePool<TASK extends AbsTask> extends BaseExecutePool<TASK> {
|
|||||||
private final String TAG = "DownloadExecutePool";
|
private final String TAG = "DownloadExecutePool";
|
||||||
|
|
||||||
@Override protected int getMaxSize() {
|
@Override protected int getMaxSize() {
|
||||||
return AriaManager.getInstance().getDownloadConfig().getMaxTaskNum();
|
return AriaConfig.getInstance().getDConfig().getMaxTaskNum();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean putTask(TASK task) {
|
@Override public boolean putTask(TASK task) {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.arialyy.aria.core.queue.pool;
|
package com.arialyy.aria.core.queue.pool;
|
||||||
|
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaConfig;
|
||||||
import com.arialyy.aria.core.task.AbsTask;
|
import com.arialyy.aria.core.task.AbsTask;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -23,6 +23,6 @@ import com.arialyy.aria.core.task.AbsTask;
|
|||||||
*/
|
*/
|
||||||
public class UploadExecutePool<TASK extends AbsTask> extends BaseExecutePool<TASK> {
|
public class UploadExecutePool<TASK extends AbsTask> extends BaseExecutePool<TASK> {
|
||||||
@Override protected int getMaxSize() {
|
@Override protected int getMaxSize() {
|
||||||
return AriaManager.getInstance().getUploadConfig().getMaxTaskNum();
|
return AriaConfig.getInstance().getUConfig().getMaxTaskNum();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,11 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package com.arialyy.aria.core.scheduler;
|
package com.arialyy.aria.core.scheduler;
|
||||||
|
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaConfig;
|
||||||
import com.arialyy.aria.core.common.AbsEntity;
|
import com.arialyy.aria.core.common.AbsEntity;
|
||||||
import com.arialyy.aria.core.task.ITask;
|
|
||||||
import com.arialyy.aria.core.manager.TaskWrapperManager;
|
import com.arialyy.aria.core.manager.TaskWrapperManager;
|
||||||
import com.arialyy.aria.core.queue.ITaskQueue;
|
import com.arialyy.aria.core.queue.ITaskQueue;
|
||||||
|
import com.arialyy.aria.core.task.ITask;
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
import com.arialyy.aria.util.CommonUtil;
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -42,7 +42,6 @@ class FailureTaskHandler<TASK extends ITask> {
|
|||||||
private TaskSchedulers mSchedulers;
|
private TaskSchedulers mSchedulers;
|
||||||
private final ReentrantLock LOCK = new ReentrantLock();
|
private final ReentrantLock LOCK = new ReentrantLock();
|
||||||
private Condition mCondition = LOCK.newCondition();
|
private Condition mCondition = LOCK.newCondition();
|
||||||
private AriaManager mAriaManager;
|
|
||||||
|
|
||||||
static FailureTaskHandler init(TaskSchedulers schedulers) {
|
static FailureTaskHandler init(TaskSchedulers schedulers) {
|
||||||
if (INSTANCE == null) {
|
if (INSTANCE == null) {
|
||||||
@@ -57,7 +56,6 @@ class FailureTaskHandler<TASK extends ITask> {
|
|||||||
|
|
||||||
private FailureTaskHandler(TaskSchedulers schedulers) {
|
private FailureTaskHandler(TaskSchedulers schedulers) {
|
||||||
mSchedulers = schedulers;
|
mSchedulers = schedulers;
|
||||||
mAriaManager = AriaManager.getInstance();
|
|
||||||
new Thread(new Runnable() {
|
new Thread(new Runnable() {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -82,35 +80,46 @@ class FailureTaskHandler<TASK extends ITask> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void retryTask(final TASK task) {
|
private void retryTask(final TASK task) {
|
||||||
long interval = task.getTaskWrapper().getConfig().getReTryInterval();
|
|
||||||
final int num = task.getTaskWrapper().getConfig().getReTryNum();
|
|
||||||
final ITaskQueue queue = mSchedulers.getQueue(task.getTaskType());
|
final ITaskQueue queue = mSchedulers.getQueue(task.getTaskType());
|
||||||
mAriaManager.getAriaHandler().postDelayed(new Runnable() {
|
if (task.isNeedRetry()){
|
||||||
@Override public void run() {
|
long interval = task.getTaskWrapper().getConfig().getReTryInterval();
|
||||||
AbsEntity entity = task.getTaskWrapper().getEntity();
|
final int num = task.getTaskWrapper().getConfig().getReTryNum();
|
||||||
if (entity.getFailNum() <= num) {
|
AriaConfig.getInstance().getAriaHandler().postDelayed(new Runnable() {
|
||||||
ALog.d(TAG, String.format("任务【%s】开始重试", task.getTaskName()));
|
@Override public void run() {
|
||||||
queue.reTryStart(task);
|
AbsEntity entity = task.getTaskWrapper().getEntity();
|
||||||
} else {
|
if (entity.getFailNum() <= num) {
|
||||||
queue.removeTaskFormQueue(task.getKey());
|
ALog.d(TAG, String.format("任务【%s】开始重试", task.getTaskName()));
|
||||||
mSchedulers.startNextTask(queue, task.getSchedulerType());
|
queue.reTryStart(task);
|
||||||
TaskWrapperManager.getInstance().removeTaskWrapper(task.getTaskWrapper());
|
} else {
|
||||||
}
|
queue.removeTaskFormQueue(task.getKey());
|
||||||
mExeQueue.remove(task);
|
mSchedulers.startNextTask(queue, task.getSchedulerType());
|
||||||
int index = mHashList.indexOf(task.hashCode());
|
TaskWrapperManager.getInstance().removeTaskWrapper(task.getTaskWrapper());
|
||||||
if (index != -1) {
|
|
||||||
mHashList.remove(index);
|
|
||||||
}
|
|
||||||
if (LOCK.isLocked()) {
|
|
||||||
try {
|
|
||||||
LOCK.lock();
|
|
||||||
mCondition.signalAll();
|
|
||||||
} finally {
|
|
||||||
LOCK.unlock();
|
|
||||||
}
|
}
|
||||||
|
next(task);
|
||||||
}
|
}
|
||||||
|
}, interval);
|
||||||
|
}else {
|
||||||
|
queue.removeTaskFormQueue(task.getKey());
|
||||||
|
mSchedulers.startNextTask(queue, task.getSchedulerType());
|
||||||
|
TaskWrapperManager.getInstance().removeTaskWrapper(task.getTaskWrapper());
|
||||||
|
next(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void next(TASK task){
|
||||||
|
mExeQueue.remove(task);
|
||||||
|
int index = mHashList.indexOf(task.hashCode());
|
||||||
|
if (index != -1) {
|
||||||
|
mHashList.remove(index);
|
||||||
|
}
|
||||||
|
if (LOCK.isLocked()) {
|
||||||
|
try {
|
||||||
|
LOCK.lock();
|
||||||
|
mCondition.signalAll();
|
||||||
|
} finally {
|
||||||
|
LOCK.unlock();
|
||||||
}
|
}
|
||||||
}, interval);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void offer(TASK task) {
|
void offer(TASK task) {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import android.content.Intent;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import com.arialyy.annotations.TaskEnum;
|
import com.arialyy.annotations.TaskEnum;
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaConfig;
|
||||||
import com.arialyy.aria.core.common.AbsEntity;
|
import com.arialyy.aria.core.common.AbsEntity;
|
||||||
import com.arialyy.aria.core.common.AbsNormalEntity;
|
import com.arialyy.aria.core.common.AbsNormalEntity;
|
||||||
import com.arialyy.aria.core.group.GroupSendParams;
|
import com.arialyy.aria.core.group.GroupSendParams;
|
||||||
@@ -53,10 +53,10 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
|
|||||||
private static FailureTaskHandler mFailureTaskHandler;
|
private static FailureTaskHandler mFailureTaskHandler;
|
||||||
|
|
||||||
private Map<String, Map<TaskEnum, ISchedulerListener>> mObservers = new ConcurrentHashMap<>();
|
private Map<String, Map<TaskEnum, ISchedulerListener>> mObservers = new ConcurrentHashMap<>();
|
||||||
private AriaManager mAriaManager;
|
private AriaConfig mAriaConfig;
|
||||||
|
|
||||||
private TaskSchedulers() {
|
private TaskSchedulers() {
|
||||||
mAriaManager = AriaManager.getInstance();
|
mAriaConfig = AriaConfig.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TaskSchedulers getInstance() {
|
public static TaskSchedulers getInstance() {
|
||||||
@@ -230,11 +230,11 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean canSend = mAriaManager.getAppConfig().isUseBroadcast();
|
boolean canSend = mAriaConfig.getAConfig().isUseBroadcast();
|
||||||
if (canSend) {
|
if (canSend) {
|
||||||
Intent intent = new Intent(ISchedulers.ARIA_TASK_INFO_ACTION);
|
Intent intent = new Intent(ISchedulers.ARIA_TASK_INFO_ACTION);
|
||||||
intent.putExtras(data);
|
intent.putExtras(data);
|
||||||
mAriaManager.getAPP().sendBroadcast(intent);
|
mAriaConfig.getAPP().sendBroadcast(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -284,9 +284,9 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean canSend = mAriaManager.getAppConfig().isUseBroadcast();
|
boolean canSend = mAriaConfig.getAConfig().isUseBroadcast();
|
||||||
if (canSend) {
|
if (canSend) {
|
||||||
mAriaManager.getAPP().sendBroadcast(
|
mAriaConfig.getAPP().sendBroadcast(
|
||||||
createData(msg.what, ITask.DOWNLOAD_GROUP_SUB, params.entity));
|
createData(msg.what, ITask.DOWNLOAD_GROUP_SUB, params.entity));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,13 +353,13 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
|
|||||||
startNextTask(getQueue(taskType), TaskSchedulerType.TYPE_DEFAULT);
|
startNextTask(getQueue(taskType), TaskSchedulerType.TYPE_DEFAULT);
|
||||||
|
|
||||||
// 发送广播
|
// 发送广播
|
||||||
boolean canSend = mAriaManager.getAppConfig().isUseBroadcast();
|
boolean canSend = mAriaConfig.getAConfig().isUseBroadcast();
|
||||||
if (canSend) {
|
if (canSend) {
|
||||||
Intent intent = new Intent(ISchedulers.ARIA_TASK_INFO_ACTION);
|
Intent intent = new Intent(ISchedulers.ARIA_TASK_INFO_ACTION);
|
||||||
Bundle b = new Bundle();
|
Bundle b = new Bundle();
|
||||||
b.putInt(ISchedulers.TASK_TYPE, taskType);
|
b.putInt(ISchedulers.TASK_TYPE, taskType);
|
||||||
b.putInt(ISchedulers.TASK_STATE, ISchedulers.FAIL);
|
b.putInt(ISchedulers.TASK_STATE, ISchedulers.FAIL);
|
||||||
mAriaManager.getAPP().sendBroadcast(intent);
|
mAriaConfig.getAPP().sendBroadcast(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理回调
|
// 处理回调
|
||||||
@@ -470,16 +470,16 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
|
|||||||
* 发送普通任务的广播
|
* 发送普通任务的广播
|
||||||
*/
|
*/
|
||||||
private void sendNormalBroadcast(int state, TASK task) {
|
private void sendNormalBroadcast(int state, TASK task) {
|
||||||
boolean canSend = mAriaManager.getAppConfig().isUseBroadcast();
|
boolean canSend = mAriaConfig.getAConfig().isUseBroadcast();
|
||||||
if (!canSend) {
|
if (!canSend) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int type = task.getTaskType();
|
int type = task.getTaskType();
|
||||||
if (type == ITask.DOWNLOAD || type == ITask.DOWNLOAD_GROUP) {
|
if (type == ITask.DOWNLOAD || type == ITask.DOWNLOAD_GROUP) {
|
||||||
mAriaManager.getAPP().sendBroadcast(
|
mAriaConfig.getAPP().sendBroadcast(
|
||||||
createData(state, type, task.getTaskWrapper().getEntity()));
|
createData(state, type, task.getTaskWrapper().getEntity()));
|
||||||
} else if (type == ITask.UPLOAD) {
|
} else if (type == ITask.UPLOAD) {
|
||||||
mAriaManager.getAPP().sendBroadcast(
|
mAriaConfig.getAPP().sendBroadcast(
|
||||||
createData(state, type, task.getTaskWrapper().getEntity()));
|
createData(state, type, task.getTaskWrapper().getEntity()));
|
||||||
} else {
|
} else {
|
||||||
ALog.w(TAG, "发送广播失败,没有对应的任务");
|
ALog.w(TAG, "发送广播失败,没有对应的任务");
|
||||||
@@ -519,9 +519,9 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int num = task.getTaskWrapper().getConfig().getReTryNum();
|
int num = task.getTaskWrapper().getConfig().getReTryNum();
|
||||||
boolean isNotNetRetry = mAriaManager.getAppConfig().isNotNetRetry();
|
boolean isNotNetRetry = mAriaConfig.getAConfig().isNotNetRetry();
|
||||||
|
|
||||||
if ((!NetUtils.isConnected(mAriaManager.getAPP()) && !isNotNetRetry)
|
if ((!NetUtils.isConnected(mAriaConfig.getAPP()) && !isNotNetRetry)
|
||||||
|| task.getTaskWrapper().getEntity().getFailNum() > num) {
|
|| task.getTaskWrapper().getEntity().getFailNum() > num) {
|
||||||
queue.removeTaskFormQueue(task.getKey());
|
queue.removeTaskFormQueue(task.getKey());
|
||||||
startNextTask(queue, task.getSchedulerType());
|
startNextTask(queue, task.getSchedulerType());
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
package com.arialyy.aria.core.upload;
|
package com.arialyy.aria.core.upload;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import com.arialyy.aria.core.common.ErrorCode;
|
|
||||||
import com.arialyy.aria.core.inf.ICheckEntityUtil;
|
import com.arialyy.aria.core.inf.ICheckEntityUtil;
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
import com.arialyy.aria.util.CheckUtil;
|
import com.arialyy.aria.util.CheckUtil;
|
||||||
@@ -59,6 +58,11 @@ public class CheckUEntityUtil implements ICheckEntityUtil {
|
|||||||
ALog.e(TAG, "上传失败,文件路径【" + filePath + "】不合法");
|
ALog.e(TAG, "上传失败,文件路径【" + filePath + "】不合法");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// 任务是新任务,并且路径冲突就不会继续执行
|
||||||
|
if (mWrapper.isNewTask() && !CheckUtil.checkUPathConflicts(
|
||||||
|
mWrapper.isIgnoreFilePathOccupy(), filePath)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
File file = new File(mEntity.getFilePath());
|
File file = new File(mEntity.getFilePath());
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
@@ -69,6 +73,7 @@ public class CheckUEntityUtil implements ICheckEntityUtil {
|
|||||||
ALog.e(TAG, "上传失败,文件【" + filePath + "】不能是文件夹");
|
ALog.e(TAG, "上传失败,文件【" + filePath + "】不能是文件夹");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import android.text.TextUtils;
|
|||||||
import androidx.annotation.CheckResult;
|
import androidx.annotation.CheckResult;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import com.arialyy.annotations.TaskEnum;
|
import com.arialyy.annotations.TaskEnum;
|
||||||
|
import com.arialyy.aria.core.AriaConfig;
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaManager;
|
||||||
import com.arialyy.aria.core.command.CancelAllCmd;
|
import com.arialyy.aria.core.command.CancelAllCmd;
|
||||||
import com.arialyy.aria.core.command.CmdHelper;
|
import com.arialyy.aria.core.command.CmdHelper;
|
||||||
@@ -58,7 +59,7 @@ public class UploadReceiver extends AbsReceiver {
|
|||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public UploadReceiver setMaxSpeed(int maxSpeed) {
|
public UploadReceiver setMaxSpeed(int maxSpeed) {
|
||||||
AriaManager.getInstance().getUploadConfig().setMaxSpeed(maxSpeed);
|
AriaConfig.getInstance().getUConfig().setMaxSpeed(maxSpeed);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ import androidx.annotation.CheckResult;
|
|||||||
import com.arialyy.aria.core.common.AbsBuilderTarget;
|
import com.arialyy.aria.core.common.AbsBuilderTarget;
|
||||||
import com.arialyy.aria.core.common.FtpOption;
|
import com.arialyy.aria.core.common.FtpOption;
|
||||||
import com.arialyy.aria.core.inf.Suggest;
|
import com.arialyy.aria.core.inf.Suggest;
|
||||||
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
import com.arialyy.aria.core.upload.UTaskWrapper;
|
||||||
|
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
||||||
import com.arialyy.aria.util.CommonUtil;
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,7 +34,8 @@ public class FtpBuilderTarget extends AbsBuilderTarget<FtpBuilderTarget> {
|
|||||||
FtpBuilderTarget(String filePath) {
|
FtpBuilderTarget(String filePath) {
|
||||||
mConfigHandler = new UNormalConfigHandler<>(this, -1);
|
mConfigHandler = new UNormalConfigHandler<>(this, -1);
|
||||||
mConfigHandler.setFilePath(filePath);
|
mConfigHandler.setFilePath(filePath);
|
||||||
getTaskWrapper().setRequestType(AbsTaskWrapper.U_FTP);
|
getTaskWrapper().setRequestType(ITaskWrapper.U_FTP);
|
||||||
|
getTaskWrapper().setNewTask(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,6 +50,17 @@ public class FtpBuilderTarget extends AbsBuilderTarget<FtpBuilderTarget> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如果文件路径被其它任务占用,删除其它任务
|
||||||
|
*
|
||||||
|
* @deprecated 使用 {@link #ignoreFilePathOccupy()}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public FtpBuilderTarget forceUpload() {
|
||||||
|
getTaskWrapper().setIgnoreFilePathOccupy(true);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置登陆、字符串编码、ftps等参数
|
* 设置登陆、字符串编码、ftps等参数
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import com.arialyy.aria.core.common.AbsNormalTarget;
|
|||||||
import com.arialyy.aria.core.common.FtpOption;
|
import com.arialyy.aria.core.common.FtpOption;
|
||||||
import com.arialyy.aria.core.inf.Suggest;
|
import com.arialyy.aria.core.inf.Suggest;
|
||||||
import com.arialyy.aria.core.upload.UploadEntity;
|
import com.arialyy.aria.core.upload.UploadEntity;
|
||||||
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
||||||
import com.arialyy.aria.util.CommonUtil;
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,7 +32,8 @@ public class FtpNormalTarget extends AbsNormalTarget<FtpNormalTarget> {
|
|||||||
|
|
||||||
FtpNormalTarget(long taskId) {
|
FtpNormalTarget(long taskId) {
|
||||||
mConfigHandler = new UNormalConfigHandler<>(this, taskId);
|
mConfigHandler = new UNormalConfigHandler<>(this, taskId);
|
||||||
getTaskWrapper().setRequestType(AbsTaskWrapper.U_FTP);
|
getTaskWrapper().setRequestType(ITaskWrapper.U_FTP);
|
||||||
|
getTaskWrapper().setNewTask(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -29,12 +29,12 @@ public class HttpBuilderTarget extends AbsBuilderTarget<HttpBuilderTarget> {
|
|||||||
private UNormalConfigHandler<HttpBuilderTarget> mConfigHandler;
|
private UNormalConfigHandler<HttpBuilderTarget> mConfigHandler;
|
||||||
|
|
||||||
HttpBuilderTarget(String filePath) {
|
HttpBuilderTarget(String filePath) {
|
||||||
|
|
||||||
mConfigHandler = new UNormalConfigHandler<>(this, -1);
|
mConfigHandler = new UNormalConfigHandler<>(this, -1);
|
||||||
mConfigHandler.setFilePath(filePath);
|
mConfigHandler.setFilePath(filePath);
|
||||||
//http暂时不支持断点上传
|
//http暂时不支持断点上传
|
||||||
getTaskWrapper().setSupportBP(false);
|
getTaskWrapper().setSupportBP(false);
|
||||||
getTaskWrapper().setRequestType(AbsTaskWrapper.U_HTTP);
|
getTaskWrapper().setRequestType(AbsTaskWrapper.U_HTTP);
|
||||||
|
getTaskWrapper().setNewTask(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,4 +60,15 @@ public class HttpBuilderTarget extends AbsBuilderTarget<HttpBuilderTarget> {
|
|||||||
getTaskWrapper().getOptionParams().setParams(option);
|
getTaskWrapper().getOptionParams().setParams(option);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如果文件路径被其它任务占用,删除其它任务
|
||||||
|
*
|
||||||
|
* @deprecated 使用 {@link #ignoreFilePathOccupy()}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public HttpBuilderTarget forceUpload() {
|
||||||
|
getTaskWrapper().setIgnoreFilePathOccupy(true);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ public class HttpNormalTarget extends AbsNormalTarget<HttpNormalTarget> {
|
|||||||
mConfigHandler = new UNormalConfigHandler<>(this, taskId);
|
mConfigHandler = new UNormalConfigHandler<>(this, taskId);
|
||||||
getTaskWrapper().setSupportBP(false);
|
getTaskWrapper().setSupportBP(false);
|
||||||
getTaskWrapper().setRequestType(AbsTaskWrapper.U_HTTP);
|
getTaskWrapper().setRequestType(AbsTaskWrapper.U_HTTP);
|
||||||
|
getTaskWrapper().setNewTask(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
39
DEV_LOG.md
39
DEV_LOG.md
@@ -1,6 +1,41 @@
|
|||||||
## 开发日志
|
## 开发日志
|
||||||
+ v_3.7.4
|
+ v_3.7.10 (2019/12/3)
|
||||||
|
- fix bug https://github.com/AriaLyy/Aria/issues/543#issuecomment-559733124
|
||||||
|
- fix bug https://github.com/AriaLyy/Aria/issues/542
|
||||||
|
- fix bug https://github.com/AriaLyy/Aria/issues/547
|
||||||
|
- 修复下载失败时,中断重试无效的问题
|
||||||
|
- 增加忽略权限检查的api,`ignoreCheckPermissions()`
|
||||||
|
- 增加通用的的忽略文件路径被占用的api,`isIgnoreFilePathOccupy()`
|
||||||
|
+ v_3.7.9 (2019/11/28)
|
||||||
|
- fix bug https://github.com/AriaLyy/Aria/issues/537
|
||||||
|
+ v_3.7.8 (2019/11/28)
|
||||||
|
- fix bug https://github.com/AriaLyy/Aria/issues/526
|
||||||
|
- fix bug https://github.com/AriaLyy/Aria/issues/533
|
||||||
|
- fix bug https://github.com/AriaLyy/Aria/issues/535
|
||||||
|
- 修复ftp无法完成下载的问题
|
||||||
|
- 修复一个非分块模式下,调用`updateUrl(newUrl)`后无法恢复下载的问题
|
||||||
|
- 增加立即恢复任务的接口,正常来说,当执行队列满时,调用恢复任务接口,只能将任务放到缓存队列中。如果希望调用恢复接口,马上进入执行队列,需要调用`resume(true)`这个重载方法。
|
||||||
|
- 增加M3U8加密密钥的下载地址转换器 https://github.com/AriaLyy/Aria/issues/522
|
||||||
|
+ v_3.7.7 (2019/11/20)
|
||||||
|
- 修复ftp无法完成下载的问题
|
||||||
|
- 修复一个http下载崩溃的问题
|
||||||
|
+ v_3.7.6 (2019/11/19)
|
||||||
|
- fix bug https://github.com/AriaLyy/Aria/issues/505
|
||||||
|
- fix bug https://github.com/AriaLyy/Aria/issues/516
|
||||||
|
- fix bug https://github.com/AriaLyy/Aria/issues/515
|
||||||
|
- 增加强制上传的api`forceUpload()`
|
||||||
|
- 修复for循环上传文件出现的问题
|
||||||
|
- 移除创建任务的500ms间隔限制
|
||||||
|
- 修复多线程读写时可能出现的`database is locked`的问题
|
||||||
|
+ v_3.7.5 (2019/11/10)
|
||||||
|
- fix bug https://github.com/AriaLyy/Aria/issues/500
|
||||||
|
- fix bug https://github.com/AriaLyy/Aria/issues/508
|
||||||
|
- fix bug https://github.com/AriaLyy/Aria/issues/503
|
||||||
|
- 修复m3u8创建索引不成功的问题
|
||||||
|
+ v_3.7.4 (2019/11/2)
|
||||||
- 修复一个class被莫名改变的问题
|
- 修复一个class被莫名改变的问题
|
||||||
|
- 修复非分块模式下导致的一个下载失败问题
|
||||||
|
- fix bug https://github.com/AriaLyy/Aria/issues/493
|
||||||
+ v_3.7.3 (2019/10/31)
|
+ v_3.7.3 (2019/10/31)
|
||||||
- fix bug https://github.com/AriaLyy/Aria/issues/495
|
- fix bug https://github.com/AriaLyy/Aria/issues/495
|
||||||
- fix bug https://github.com/AriaLyy/Aria/issues/496
|
- fix bug https://github.com/AriaLyy/Aria/issues/496
|
||||||
@@ -15,7 +50,7 @@
|
|||||||
- fix bug https://github.com/AriaLyy/Aria/issues/482
|
- fix bug https://github.com/AriaLyy/Aria/issues/482
|
||||||
- fix bug https://github.com/AriaLyy/Aria/issues/473
|
- fix bug https://github.com/AriaLyy/Aria/issues/473
|
||||||
- 移除隐藏api的反射 https://github.com/AriaLyy/Aria/issues/456
|
- 移除隐藏api的反射 https://github.com/AriaLyy/Aria/issues/456
|
||||||
- 新增ftp免证书登陆功能h ttps://github.com/AriaLyy/Aria/issues/455
|
- 新增ftp免证书登陆功能 https://github.com/AriaLyy/Aria/issues/455
|
||||||
- 适配androidX
|
- 适配androidX
|
||||||
- 修复组合任务,恢复下载,会出现进度显示为0的问题
|
- 修复组合任务,恢复下载,会出现进度显示为0的问题
|
||||||
- m3u8点播下载新增创建ts索引功能
|
- m3u8点播下载新增创建ts索引功能
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ dependencies {
|
|||||||
|
|
||||||
implementation "androidx.appcompat:appcompat:${rootProject.ext.XAppcompatVersion}"
|
implementation "androidx.appcompat:appcompat:${rootProject.ext.XAppcompatVersion}"
|
||||||
|
|
||||||
// implementation project(path: ':AriaFtpPlug')
|
|
||||||
implementation project(path: ':PublicComponent')
|
implementation project(path: ':PublicComponent')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ import javax.net.ssl.SSLContext;
|
|||||||
public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER extends AbsTaskWrapper<ENTITY>>
|
public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER extends AbsTaskWrapper<ENTITY>>
|
||||||
implements Runnable {
|
implements Runnable {
|
||||||
|
|
||||||
private final String TAG = "AbsFtpInfoThread";
|
private final String TAG = CommonUtil.getClassName(getClass());
|
||||||
protected ENTITY mEntity;
|
protected ENTITY mEntity;
|
||||||
protected TASK_WRAPPER mTaskWrapper;
|
protected TASK_WRAPPER mTaskWrapper;
|
||||||
protected FtpTaskOption mTaskOption;
|
protected FtpTaskOption mTaskOption;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import com.arialyy.aria.core.download.DownloadGroupEntity;
|
|||||||
import com.arialyy.aria.core.inf.OnFileInfoCallback;
|
import com.arialyy.aria.core.inf.OnFileInfoCallback;
|
||||||
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
||||||
import com.arialyy.aria.exception.BaseException;
|
import com.arialyy.aria.exception.BaseException;
|
||||||
|
import com.arialyy.aria.util.CheckUtil;
|
||||||
import com.arialyy.aria.util.CommonUtil;
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
import com.arialyy.aria.util.RecordUtil;
|
import com.arialyy.aria.util.RecordUtil;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
@@ -72,6 +73,9 @@ public class FtpDirInfoThread extends AbsFtpInfoThread<DownloadGroupEntity, DGTa
|
|||||||
entity.setGroupChild(true);
|
entity.setGroupChild(true);
|
||||||
entity.setConvertFileSize(CommonUtil.formatFileSize(ftpFile.getSize()));
|
entity.setConvertFileSize(CommonUtil.formatFileSize(ftpFile.getSize()));
|
||||||
entity.setFileSize(ftpFile.getSize());
|
entity.setFileSize(ftpFile.getSize());
|
||||||
|
|
||||||
|
//if(CheckUtil.checkDPathConflicts(mTaskWrapper.is))
|
||||||
|
|
||||||
entity.insert();
|
entity.insert();
|
||||||
|
|
||||||
DTaskWrapper subWrapper = new DTaskWrapper(entity);
|
DTaskWrapper subWrapper = new DTaskWrapper(entity);
|
||||||
|
|||||||
@@ -21,9 +21,8 @@ import com.arialyy.aria.core.common.AbsRecordHandlerAdapter;
|
|||||||
import com.arialyy.aria.core.common.RecordHelper;
|
import com.arialyy.aria.core.common.RecordHelper;
|
||||||
import com.arialyy.aria.core.config.Configuration;
|
import com.arialyy.aria.core.config.Configuration;
|
||||||
import com.arialyy.aria.core.download.DownloadEntity;
|
import com.arialyy.aria.core.download.DownloadEntity;
|
||||||
import com.arialyy.aria.core.common.AbsNormalEntity;
|
|
||||||
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
|
||||||
import com.arialyy.aria.core.inf.IRecordHandler;
|
import com.arialyy.aria.core.inf.IRecordHandler;
|
||||||
|
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
||||||
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
||||||
import com.arialyy.aria.util.RecordUtil;
|
import com.arialyy.aria.util.RecordUtil;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -40,8 +39,12 @@ public class FtpRecordAdapter extends AbsRecordHandlerAdapter {
|
|||||||
|
|
||||||
@Override public void handlerTaskRecord(TaskRecord record) {
|
@Override public void handlerTaskRecord(TaskRecord record) {
|
||||||
RecordHelper helper = new RecordHelper(getWrapper(), record);
|
RecordHelper helper = new RecordHelper(getWrapper(), record);
|
||||||
if (record.isBlock) {
|
if (getWrapper().isSupportBP()) {
|
||||||
helper.handleBlockRecord();
|
if (record.isBlock) {
|
||||||
|
helper.handleBlockRecord();
|
||||||
|
} else {
|
||||||
|
helper.handleMultiRecord();
|
||||||
|
}
|
||||||
} else if (record.threadNum == 1) {
|
} else if (record.threadNum == 1) {
|
||||||
helper.handleSingleThreadRecord();
|
helper.handleSingleThreadRecord();
|
||||||
}
|
}
|
||||||
@@ -74,9 +77,7 @@ public class FtpRecordAdapter extends AbsRecordHandlerAdapter {
|
|||||||
|
|
||||||
int requestType = getWrapper().getRequestType();
|
int requestType = getWrapper().getRequestType();
|
||||||
if (requestType == ITaskWrapper.D_FTP || requestType == ITaskWrapper.D_FTP_DIR) {
|
if (requestType == ITaskWrapper.D_FTP || requestType == ITaskWrapper.D_FTP_DIR) {
|
||||||
record.isBlock = threadNum > 1 && Configuration.getInstance().downloadCfg.isUseBlock();
|
record.isBlock = Configuration.getInstance().downloadCfg.isUseBlock();
|
||||||
// 线程数为1,或者使用了分块,则认为是使用动态长度文件
|
|
||||||
record.isOpenDynamicFile = threadNum == 1 || record.isBlock;
|
|
||||||
} else {
|
} else {
|
||||||
record.isBlock = false;
|
record.isBlock = false;
|
||||||
}
|
}
|
||||||
@@ -104,6 +105,4 @@ public class FtpRecordAdapter extends AbsRecordHandlerAdapter {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,32 +16,33 @@
|
|||||||
package com.arialyy.aria.ftp.download;
|
package com.arialyy.aria.ftp.download;
|
||||||
|
|
||||||
import com.arialyy.aria.core.TaskRecord;
|
import com.arialyy.aria.core.TaskRecord;
|
||||||
import com.arialyy.aria.core.task.AbsNormalLoaderAdapter;
|
|
||||||
import com.arialyy.aria.core.common.RecordHandler;
|
import com.arialyy.aria.core.common.RecordHandler;
|
||||||
import com.arialyy.aria.core.common.SubThreadConfig;
|
import com.arialyy.aria.core.common.SubThreadConfig;
|
||||||
|
import com.arialyy.aria.core.inf.IRecordHandler;
|
||||||
|
import com.arialyy.aria.core.task.AbsNormalLoaderAdapter;
|
||||||
|
import com.arialyy.aria.core.task.IThreadTask;
|
||||||
import com.arialyy.aria.core.task.ThreadTask;
|
import com.arialyy.aria.core.task.ThreadTask;
|
||||||
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
||||||
import com.arialyy.aria.core.inf.IRecordHandler;
|
|
||||||
import com.arialyy.aria.core.task.IThreadTask;
|
|
||||||
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
||||||
import com.arialyy.aria.ftp.FtpRecordAdapter;
|
import com.arialyy.aria.ftp.FtpRecordAdapter;
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
|
import com.arialyy.aria.util.FileUtil;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author lyy
|
* @Author lyy
|
||||||
* @Date 2019-09-19
|
* @Date 2019-09-19
|
||||||
*/
|
*/
|
||||||
final class FtpDLoaderAdapter extends AbsNormalLoaderAdapter {
|
public class FtpDLoaderAdapter extends AbsNormalLoaderAdapter {
|
||||||
|
|
||||||
FtpDLoaderAdapter(ITaskWrapper wrapper) {
|
public FtpDLoaderAdapter(ITaskWrapper wrapper) {
|
||||||
super(wrapper);
|
super(wrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean handleNewTask(TaskRecord record, int totalThreadNum) {
|
@Override public boolean handleNewTask(TaskRecord record, int totalThreadNum) {
|
||||||
if (!record.isBlock) {
|
if (!record.isBlock) {
|
||||||
if (getTempFile().exists()) {
|
if (getTempFile().exists()) {
|
||||||
getTempFile().delete();
|
FileUtil.deleteFile(getTempFile());
|
||||||
}
|
}
|
||||||
//CommonUtil.createFile(mTempFile.getPath());
|
//CommonUtil.createFile(mTempFile.getPath());
|
||||||
} else {
|
} else {
|
||||||
@@ -50,7 +51,7 @@ final class FtpDLoaderAdapter extends AbsNormalLoaderAdapter {
|
|||||||
new File(String.format(IRecordHandler.SUB_PATH, getTempFile().getPath(), i));
|
new File(String.format(IRecordHandler.SUB_PATH, getTempFile().getPath(), i));
|
||||||
if (blockFile.exists()) {
|
if (blockFile.exists()) {
|
||||||
ALog.d(TAG, String.format("分块【%s】已经存在,将删除该分块", i));
|
ALog.d(TAG, String.format("分块【%s】已经存在,将删除该分块", i));
|
||||||
blockFile.delete();
|
FileUtil.deleteFile(blockFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ final class FtpDThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getThreadConfig().isOpenDynamicFile) {
|
if (getThreadConfig().isBlock) {
|
||||||
readDynamicFile(is);
|
readDynamicFile(is);
|
||||||
} else {
|
} else {
|
||||||
readNormal(is);
|
readNormal(is);
|
||||||
|
|||||||
@@ -85,13 +85,14 @@ public class FtpDirDLoaderUtil extends AbsGroupUtil {
|
|||||||
* @param needCloneInfo 第一次下载,信息已经在{@link FtpDirInfoThread}中clone了
|
* @param needCloneInfo 第一次下载,信息已经在{@link FtpDirInfoThread}中clone了
|
||||||
*/
|
*/
|
||||||
private void startDownload(boolean needCloneInfo) {
|
private void startDownload(boolean needCloneInfo) {
|
||||||
|
// ftp需要获取完成只任务信息才更新只任务数量
|
||||||
|
getState().setSubSize(getWrapper().getSubTaskWrapper().size());
|
||||||
try {
|
try {
|
||||||
LOCK.lock();
|
LOCK.lock();
|
||||||
condition.signalAll();
|
condition.signalAll();
|
||||||
} finally {
|
} finally {
|
||||||
LOCK.unlock();
|
LOCK.unlock();
|
||||||
}
|
}
|
||||||
initState();
|
|
||||||
for (DTaskWrapper wrapper : getWrapper().getSubTaskWrapper()) {
|
for (DTaskWrapper wrapper : getWrapper().getSubTaskWrapper()) {
|
||||||
if (needCloneInfo) {
|
if (needCloneInfo) {
|
||||||
cloneInfo(wrapper);
|
cloneInfo(wrapper);
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ class FtpUFileInfoThread extends AbsFtpInfoThread<UploadEntity, UTaskWrapper> {
|
|||||||
@Override protected boolean onInterceptor(FTPClient client, FTPFile[] ftpFiles) {
|
@Override protected boolean onInterceptor(FTPClient client, FTPFile[] ftpFiles) {
|
||||||
// 旧任务将不做处理,否则断点续传上传将失效
|
// 旧任务将不做处理,否则断点续传上传将失效
|
||||||
if (!mTaskWrapper.isNewTask()) {
|
if (!mTaskWrapper.isNewTask()) {
|
||||||
|
ALog.d(TAG, "任务是旧任务,忽略该拦截器");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ import java.io.UnsupportedEncodingException;
|
|||||||
* Created by Aria.Lao on 2017/7/28. D_FTP 单线程上传任务,需要FTP 服务器给用户打开append和write的权限
|
* Created by Aria.Lao on 2017/7/28. D_FTP 单线程上传任务,需要FTP 服务器给用户打开append和write的权限
|
||||||
*/
|
*/
|
||||||
class FtpUThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
|
class FtpUThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
|
||||||
private final String TAG = "FtpThreadTask";
|
|
||||||
private String dir, remotePath;
|
private String dir, remotePath;
|
||||||
|
|
||||||
FtpUThreadTaskAdapter(SubThreadConfig config) {
|
FtpUThreadTaskAdapter(SubThreadConfig config) {
|
||||||
@@ -66,7 +65,8 @@ class FtpUThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
file =
|
file =
|
||||||
new BufferedRandomAccessFile(getThreadConfig().tempFile, "rwd", getTaskConfig().getBuffSize());
|
new BufferedRandomAccessFile(getThreadConfig().tempFile, "rwd",
|
||||||
|
getTaskConfig().getBuffSize());
|
||||||
if (getThreadRecord().startLocation != 0) {
|
if (getThreadRecord().startLocation != 0) {
|
||||||
//file.skipBytes((int) getThreadConfig().START_LOCATION);
|
//file.skipBytes((int) getThreadConfig().START_LOCATION);
|
||||||
file.seek(getThreadRecord().startLocation);
|
file.seek(getThreadRecord().startLocation);
|
||||||
@@ -103,10 +103,8 @@ class FtpUThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
|
|||||||
private void initPath() throws UnsupportedEncodingException {
|
private void initPath() throws UnsupportedEncodingException {
|
||||||
dir = CommonUtil.convertFtpChar(charSet, mTaskOption.getUrlEntity().remotePath);
|
dir = CommonUtil.convertFtpChar(charSet, mTaskOption.getUrlEntity().remotePath);
|
||||||
|
|
||||||
String fileName =
|
String fileName = TextUtils.isEmpty(mTaskOption.getNewFileName()) ? getEntity().getFileName()
|
||||||
TextUtils.isEmpty(mTaskOption.getNewFileName()) ? CommonUtil.convertFtpChar(charSet,
|
: mTaskOption.getNewFileName();
|
||||||
getEntity().getFileName())
|
|
||||||
: CommonUtil.convertFtpChar(charSet, mTaskOption.getNewFileName());
|
|
||||||
|
|
||||||
remotePath =
|
remotePath =
|
||||||
CommonUtil.convertFtpChar(charSet,
|
CommonUtil.convertFtpChar(charSet,
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
<resources>
|
|
||||||
<string name="app_name">AriaFtpComponent</string>
|
|
||||||
</resources>
|
|
||||||
@@ -38,15 +38,19 @@ public class HttpRecordAdapter extends AbsRecordHandlerAdapter {
|
|||||||
|
|
||||||
@Override public void onPre() {
|
@Override public void onPre() {
|
||||||
super.onPre();
|
super.onPre();
|
||||||
if (getWrapper().getRequestType() == ITaskWrapper.U_HTTP){
|
if (getWrapper().getRequestType() == ITaskWrapper.U_HTTP) {
|
||||||
RecordUtil.delTaskRecord(getEntity().getFilePath(), IRecordHandler.TYPE_UPLOAD);
|
RecordUtil.delTaskRecord(getEntity().getFilePath(), IRecordHandler.TYPE_UPLOAD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void handlerTaskRecord(TaskRecord record) {
|
@Override public void handlerTaskRecord(TaskRecord record) {
|
||||||
RecordHelper helper = new RecordHelper(getWrapper(), record);
|
RecordHelper helper = new RecordHelper(getWrapper(), record);
|
||||||
if (record.isBlock) {
|
if (getWrapper().isSupportBP()) {
|
||||||
helper.handleBlockRecord();
|
if (record.isBlock) {
|
||||||
|
helper.handleBlockRecord();
|
||||||
|
} else {
|
||||||
|
helper.handleMultiRecord();
|
||||||
|
}
|
||||||
} else if (!getWrapper().isSupportBP()) {
|
} else if (!getWrapper().isSupportBP()) {
|
||||||
helper.handleNoSupportBPRecord();
|
helper.handleNoSupportBPRecord();
|
||||||
} else {
|
} else {
|
||||||
@@ -81,10 +85,9 @@ public class HttpRecordAdapter extends AbsRecordHandlerAdapter {
|
|||||||
record.threadNum = threadNum;
|
record.threadNum = threadNum;
|
||||||
|
|
||||||
int requestType = getWrapper().getRequestType();
|
int requestType = getWrapper().getRequestType();
|
||||||
if (requestType == ITaskWrapper.D_FTP || requestType == ITaskWrapper.D_FTP_DIR) {
|
if (requestType == ITaskWrapper.D_FTP || requestType == ITaskWrapper.D_FTP_DIR
|
||||||
record.isBlock = threadNum > 1 && Configuration.getInstance().downloadCfg.isUseBlock();
|
|| requestType == ITaskWrapper.D_HTTP || requestType == ITaskWrapper.DG_HTTP) {
|
||||||
// 线程数为1,或者使用了分块,则认为是使用动态长度文件
|
record.isBlock = Configuration.getInstance().downloadCfg.isUseBlock();
|
||||||
record.isOpenDynamicFile = threadNum == 1 || record.isBlock;
|
|
||||||
} else {
|
} else {
|
||||||
record.isBlock = false;
|
record.isBlock = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ public class DGroupLoaderUtil extends AbsGroupUtil {
|
|||||||
|
|
||||||
@Override protected boolean onStart() {
|
@Override protected boolean onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
initState();
|
getState().setSubSize(getWrapper().getSubTaskWrapper().size());
|
||||||
if (getState().getCompleteNum() == getState().getSubSize()) {
|
if (getState().getCompleteNum() == getState().getSubSize()) {
|
||||||
mListener.onComplete();
|
mListener.onComplete();
|
||||||
} else {
|
} else {
|
||||||
@@ -91,6 +91,7 @@ public class DGroupLoaderUtil extends AbsGroupUtil {
|
|||||||
return getLenComplete;
|
return getLenComplete;
|
||||||
} else {
|
} else {
|
||||||
for (DTaskWrapper wrapper : getWrapper().getSubTaskWrapper()) {
|
for (DTaskWrapper wrapper : getWrapper().getSubTaskWrapper()) {
|
||||||
|
cloneHeader(wrapper);
|
||||||
if (wrapper.getState() != IEntity.STATE_COMPLETE) {
|
if (wrapper.getState() != IEntity.STATE_COMPLETE) {
|
||||||
startSubLoader(createSubLoader(wrapper, true));
|
startSubLoader(createSubLoader(wrapper, true));
|
||||||
}
|
}
|
||||||
@@ -179,7 +180,7 @@ public class DGroupLoaderUtil extends AbsGroupUtil {
|
|||||||
*/
|
*/
|
||||||
private void cloneHeader(DTaskWrapper taskWrapper) {
|
private void cloneHeader(DTaskWrapper taskWrapper) {
|
||||||
HttpTaskOption groupOption = (HttpTaskOption) getWrapper().getTaskOption();
|
HttpTaskOption groupOption = (HttpTaskOption) getWrapper().getTaskOption();
|
||||||
HttpTaskOption subOption = (HttpTaskOption) taskWrapper.getTaskOption();
|
HttpTaskOption subOption = new HttpTaskOption();
|
||||||
|
|
||||||
// 设置属性
|
// 设置属性
|
||||||
subOption.setFileLenAdapter(groupOption.getFileLenAdapter());
|
subOption.setFileLenAdapter(groupOption.getFileLenAdapter());
|
||||||
@@ -187,5 +188,6 @@ public class DGroupLoaderUtil extends AbsGroupUtil {
|
|||||||
subOption.setHeaders(groupOption.getHeaders());
|
subOption.setHeaders(groupOption.getHeaders());
|
||||||
subOption.setProxy(groupOption.getProxy());
|
subOption.setProxy(groupOption.getProxy());
|
||||||
subOption.setParams(groupOption.getParams());
|
subOption.setParams(groupOption.getParams());
|
||||||
|
taskWrapper.setTaskOption(subOption);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,6 +28,7 @@ import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
|||||||
import com.arialyy.aria.http.HttpRecordAdapter;
|
import com.arialyy.aria.http.HttpRecordAdapter;
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
||||||
|
import com.arialyy.aria.util.FileUtil;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@@ -43,16 +44,15 @@ final class HttpDLoaderAdapter extends AbsNormalLoaderAdapter {
|
|||||||
@Override public boolean handleNewTask(TaskRecord record, int totalThreadNum) {
|
@Override public boolean handleNewTask(TaskRecord record, int totalThreadNum) {
|
||||||
if (!record.isBlock) {
|
if (!record.isBlock) {
|
||||||
if (getTempFile().exists()) {
|
if (getTempFile().exists()) {
|
||||||
getTempFile().delete();
|
FileUtil.deleteFile(getTempFile());
|
||||||
}
|
}
|
||||||
//CommonUtil.createFile(mTempFile.getPath());
|
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < totalThreadNum; i++) {
|
for (int i = 0; i < totalThreadNum; i++) {
|
||||||
File blockFile =
|
File blockFile =
|
||||||
new File(String.format(IRecordHandler.SUB_PATH, getTempFile().getPath(), i));
|
new File(String.format(IRecordHandler.SUB_PATH, getTempFile().getPath(), i));
|
||||||
if (blockFile.exists()) {
|
if (blockFile.exists()) {
|
||||||
ALog.d(TAG, String.format("分块【%s】已经存在,将删除该分块", i));
|
ALog.d(TAG, String.format("分块【%s】已经存在,将删除该分块", i));
|
||||||
blockFile.delete();
|
FileUtil.deleteFile(blockFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,15 +15,16 @@
|
|||||||
*/
|
*/
|
||||||
package com.arialyy.aria.http.download;
|
package com.arialyy.aria.http.download;
|
||||||
|
|
||||||
|
import com.arialyy.aria.core.common.RequestEnum;
|
||||||
import com.arialyy.aria.core.common.SubThreadConfig;
|
import com.arialyy.aria.core.common.SubThreadConfig;
|
||||||
import com.arialyy.aria.core.download.DTaskWrapper;
|
import com.arialyy.aria.core.download.DTaskWrapper;
|
||||||
import com.arialyy.aria.exception.AriaIOException;
|
import com.arialyy.aria.exception.AriaIOException;
|
||||||
import com.arialyy.aria.exception.TaskException;
|
import com.arialyy.aria.exception.TaskException;
|
||||||
import com.arialyy.aria.http.BaseHttpThreadTaskAdapter;
|
import com.arialyy.aria.http.BaseHttpThreadTaskAdapter;
|
||||||
import com.arialyy.aria.http.ConnectionHelp;
|
import com.arialyy.aria.http.ConnectionHelp;
|
||||||
import com.arialyy.aria.core.common.RequestEnum;
|
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
||||||
|
import com.arialyy.aria.util.FileUtil;
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -103,7 +104,7 @@ final class HttpDThreadTaskAdapter extends BaseHttpThreadTaskAdapter {
|
|||||||
is = new BufferedInputStream(ConnectionHelp.convertInputStream(conn));
|
is = new BufferedInputStream(ConnectionHelp.convertInputStream(conn));
|
||||||
if (mTaskOption.isChunked()) {
|
if (mTaskOption.isChunked()) {
|
||||||
readChunked(is);
|
readChunked(is);
|
||||||
} else if (getThreadConfig().isOpenDynamicFile) {
|
} else if (getThreadConfig().isBlock) {
|
||||||
readDynamicFile(is);
|
readDynamicFile(is);
|
||||||
} else {
|
} else {
|
||||||
//创建可设置位置的文件
|
//创建可设置位置的文件
|
||||||
@@ -123,6 +124,10 @@ final class HttpDThreadTaskAdapter extends BaseHttpThreadTaskAdapter {
|
|||||||
fail(new TaskException(TAG,
|
fail(new TaskException(TAG,
|
||||||
String.format("任务【%s】下载失败,filePath: %s, url: %s", getFileName(),
|
String.format("任务【%s】下载失败,filePath: %s, url: %s", getFileName(),
|
||||||
getEntity().getFilePath(), getEntity().getUrl()), e), true);
|
getEntity().getFilePath(), getEntity().getUrl()), e), true);
|
||||||
|
} catch (ArrayIndexOutOfBoundsException e) {
|
||||||
|
fail(new TaskException(TAG,
|
||||||
|
String.format("任务【%s】下载失败,filePath: %s, url: %s", getFileName(),
|
||||||
|
getEntity().getFilePath(), getEntity().getUrl()), e), false);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail(new TaskException(TAG,
|
fail(new TaskException(TAG,
|
||||||
String.format("任务【%s】下载失败,filePath: %s, url: %s", getFileName(),
|
String.format("任务【%s】下载失败,filePath: %s, url: %s", getFileName(),
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
<resources>
|
|
||||||
<string name="app_name">HttpComponent</string>
|
|
||||||
</resources>
|
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.arialyy.aria.m3u8;
|
package com.arialyy.aria.m3u8;
|
||||||
|
|
||||||
|
import android.text.TextUtils;
|
||||||
import com.arialyy.aria.core.common.RecordHandler;
|
import com.arialyy.aria.core.common.RecordHandler;
|
||||||
import com.arialyy.aria.core.download.DTaskWrapper;
|
import com.arialyy.aria.core.download.DTaskWrapper;
|
||||||
import com.arialyy.aria.core.download.DownloadEntity;
|
import com.arialyy.aria.core.download.DownloadEntity;
|
||||||
@@ -59,6 +60,9 @@ public abstract class BaseM3U8Loader extends AbsLoader {
|
|||||||
|
|
||||||
protected String getCacheDir() {
|
protected String getCacheDir() {
|
||||||
String cacheDir = mM3U8Option.getCacheDir();
|
String cacheDir = mM3U8Option.getCacheDir();
|
||||||
|
if (TextUtils.isEmpty(cacheDir)) {
|
||||||
|
cacheDir = FileUtil.getTsCacheDir(getEntity().getFilePath(), mM3U8Option.getBandWidth());
|
||||||
|
}
|
||||||
if (!new File(cacheDir).exists()) {
|
if (!new File(cacheDir).exists()) {
|
||||||
FileUtil.createDir(cacheDir);
|
FileUtil.createDir(cacheDir);
|
||||||
}
|
}
|
||||||
@@ -68,8 +72,9 @@ public abstract class BaseM3U8Loader extends AbsLoader {
|
|||||||
/**
|
/**
|
||||||
* 创建索引文件
|
* 创建索引文件
|
||||||
*/
|
*/
|
||||||
protected boolean generateIndexFile() {
|
public boolean generateIndexFile(boolean isLive) {
|
||||||
File tempFile = new File(M3U8InfoThread.M3U8_INDEX_FORMAT, getEntity().getFilePath());
|
File tempFile =
|
||||||
|
new File(String.format(M3U8InfoThread.M3U8_INDEX_FORMAT, getEntity().getFilePath()));
|
||||||
if (!tempFile.exists()) {
|
if (!tempFile.exists()) {
|
||||||
ALog.e(TAG, "源索引文件不存在");
|
ALog.e(TAG, "源索引文件不存在");
|
||||||
return false;
|
return false;
|
||||||
@@ -85,21 +90,29 @@ public abstract class BaseM3U8Loader extends AbsLoader {
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
while ((line = reader.readLine()) != null) {
|
while ((line = reader.readLine()) != null) {
|
||||||
byte[] bytes;
|
byte[] bytes;
|
||||||
if (line.startsWith("EXTINF")) {
|
if (line.startsWith("#EXTINF")) {
|
||||||
|
fos.write(line.concat("\r\n").getBytes(Charset.forName("UTF-8")));
|
||||||
String tsPath = getTsFilePath(cacheDir, mRecord.threadRecords.get(i).threadId);
|
String tsPath = getTsFilePath(cacheDir, mRecord.threadRecords.get(i).threadId);
|
||||||
bytes = tsPath.concat("\r\n").getBytes(Charset.forName("UTF-8"));
|
bytes = tsPath.concat("\r\n").getBytes(Charset.forName("UTF-8"));
|
||||||
|
reader.readLine(); // 继续读一行,避免写入源索引文件的切片地址
|
||||||
i++;
|
i++;
|
||||||
} else if (line.startsWith("EXT-X-KEY")) {
|
} else if (line.startsWith("#EXT-X-KEY")) {
|
||||||
M3U8Entity m3U8Entity = getEntity().getM3U8Entity();
|
M3U8Entity m3U8Entity = getEntity().getM3U8Entity();
|
||||||
String keyInfo = String.format("#EXT-X-KEY:METHOD=%s,URI=%s,IV=%s\r\n", m3U8Entity.method,
|
String keyInfo = String.format("#EXT-X-KEY:METHOD=%s,URI=%s,IV=%s\r\n", m3U8Entity.method,
|
||||||
m3U8Entity.keyPath, m3U8Entity.iv);
|
m3U8Entity.keyPath, m3U8Entity.iv);
|
||||||
bytes = keyInfo.getBytes(Charset.forName("UTF-8"));
|
bytes = keyInfo.getBytes(Charset.forName("UTF-8"));
|
||||||
} else {
|
} else {
|
||||||
bytes = line.getBytes(Charset.forName("UTF-8"));
|
bytes = line.concat("\r\n").getBytes(Charset.forName("UTF-8"));
|
||||||
}
|
}
|
||||||
fos.write(bytes, 0, bytes.length);
|
fos.write(bytes, 0, bytes.length);
|
||||||
}
|
}
|
||||||
|
// 直播的索引文件需要在结束的时候才写入结束标志
|
||||||
|
if (isLive) {
|
||||||
|
fos.write("#EXT-X-ENDLIST".concat("\r\n").getBytes(Charset.forName("UTF-8")));
|
||||||
|
}
|
||||||
|
|
||||||
fos.flush();
|
fos.flush();
|
||||||
|
return true;
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|||||||
@@ -24,8 +24,9 @@ import com.arialyy.aria.core.common.CompleteInfo;
|
|||||||
import com.arialyy.aria.core.download.DTaskWrapper;
|
import com.arialyy.aria.core.download.DTaskWrapper;
|
||||||
import com.arialyy.aria.core.download.DownloadEntity;
|
import com.arialyy.aria.core.download.DownloadEntity;
|
||||||
import com.arialyy.aria.core.download.M3U8Entity;
|
import com.arialyy.aria.core.download.M3U8Entity;
|
||||||
import com.arialyy.aria.core.processor.IBandWidthUrlConverter;
|
|
||||||
import com.arialyy.aria.core.inf.OnFileInfoCallback;
|
import com.arialyy.aria.core.inf.OnFileInfoCallback;
|
||||||
|
import com.arialyy.aria.core.processor.IBandWidthUrlConverter;
|
||||||
|
import com.arialyy.aria.core.processor.IKeyUrlConverter;
|
||||||
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
||||||
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
||||||
import com.arialyy.aria.exception.M3U8Exception;
|
import com.arialyy.aria.exception.M3U8Exception;
|
||||||
@@ -39,7 +40,6 @@ import com.arialyy.aria.util.FileUtil;
|
|||||||
import com.arialyy.aria.util.Regular;
|
import com.arialyy.aria.util.Regular;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@@ -55,6 +55,7 @@ import java.util.regex.Pattern;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析url中获取到到m3u8文件信息
|
* 解析url中获取到到m3u8文件信息
|
||||||
|
* 协议地址:https://tools.ietf.org/html/rfc8216
|
||||||
* https://www.cnblogs.com/renhui/p/10351870.html
|
* https://www.cnblogs.com/renhui/p/10351870.html
|
||||||
* https://blog.csdn.net/Guofengpu/article/details/54922865
|
* https://blog.csdn.net/Guofengpu/article/details/54922865
|
||||||
*/
|
*/
|
||||||
@@ -72,13 +73,9 @@ final public class M3U8InfoThread implements Runnable {
|
|||||||
* 是否停止获取切片信息,{@code true}停止获取切片信息
|
* 是否停止获取切片信息,{@code true}停止获取切片信息
|
||||||
*/
|
*/
|
||||||
private boolean isStop = false;
|
private boolean isStop = false;
|
||||||
/**
|
|
||||||
* m3u8文件信息
|
|
||||||
*/
|
|
||||||
private List<String> mInfos = new ArrayList<>();
|
|
||||||
|
|
||||||
public interface OnGetLivePeerCallback {
|
public interface OnGetLivePeerCallback {
|
||||||
void onGetPeer(String url);
|
void onGetPeer(String url, String extInf);
|
||||||
}
|
}
|
||||||
|
|
||||||
public M3U8InfoThread(DTaskWrapper taskWrapper, OnFileInfoCallback callback) {
|
public M3U8InfoThread(DTaskWrapper taskWrapper, OnFileInfoCallback callback) {
|
||||||
@@ -122,38 +119,51 @@ final public class M3U8InfoThread implements Runnable {
|
|||||||
}
|
}
|
||||||
List<String> extInf = new ArrayList<>();
|
List<String> extInf = new ArrayList<>();
|
||||||
boolean isLive = mTaskWrapper.getRequestType() == ITaskWrapper.M3U8_LIVE;
|
boolean isLive = mTaskWrapper.getRequestType() == ITaskWrapper.M3U8_LIVE;
|
||||||
boolean isGenerateIndexFile = mTaskWrapper.getEntity().getM3U8Entity().isGenerateIndexFile();
|
boolean isGenerateIndexFile =
|
||||||
|
((M3U8TaskOption) mTaskWrapper.getM3u8Option()).isGenerateIndexFile();
|
||||||
|
// 写入索引信息的流
|
||||||
|
FileOutputStream fos = null;
|
||||||
if (isGenerateIndexFile) {
|
if (isGenerateIndexFile) {
|
||||||
mInfos.add(line);
|
String indexPath = String.format(M3U8_INDEX_FORMAT, mEntity.getFilePath());
|
||||||
|
File indexFile = new File(indexPath);
|
||||||
|
if (!indexFile.exists()) {
|
||||||
|
FileUtil.createFile(indexPath);
|
||||||
|
} else {
|
||||||
|
//FileUtil.deleteFile(indexPath);
|
||||||
|
}
|
||||||
|
fos = new FileOutputStream(indexFile);
|
||||||
|
ALog.d(TAG, line);
|
||||||
|
addIndexInfo(isGenerateIndexFile, fos, line);
|
||||||
}
|
}
|
||||||
while ((line = reader.readLine()) != null) {
|
while ((line = reader.readLine()) != null) {
|
||||||
if (isStop) {
|
if (isStop) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isGenerateIndexFile) {
|
|
||||||
mInfos.add(line);
|
|
||||||
}
|
|
||||||
if (line.startsWith("#EXT-X-ENDLIST")) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ALog.d(TAG, line);
|
ALog.d(TAG, line);
|
||||||
if (line.startsWith("#EXTINF")) {
|
if (line.startsWith("#EXT-X-ENDLIST")) {
|
||||||
String info = reader.readLine();
|
// 点播文件的下载写入结束标志,直播文件的下载在停止时才写入结束标志
|
||||||
mInfos.add(info);
|
addIndexInfo(isGenerateIndexFile && !isLive, fos, line);
|
||||||
|
break;
|
||||||
|
} else if (line.startsWith("#EXTINF")) {
|
||||||
|
String url = reader.readLine();
|
||||||
if (isLive) {
|
if (isLive) {
|
||||||
if (onGetPeerCallback != null) {
|
if (onGetPeerCallback != null) {
|
||||||
onGetPeerCallback.onGetPeer(info);
|
onGetPeerCallback.onGetPeer(url, line);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
extInf.add(info);
|
extInf.add(url);
|
||||||
}
|
}
|
||||||
|
ALog.d(TAG, url);
|
||||||
|
addIndexInfo(isGenerateIndexFile && !isLive, fos, line);
|
||||||
|
addIndexInfo(isGenerateIndexFile && !isLive, fos, url);
|
||||||
} else if (line.startsWith("#EXT-X-STREAM-INF")) {
|
} else if (line.startsWith("#EXT-X-STREAM-INF")) {
|
||||||
|
addIndexInfo(isGenerateIndexFile, fos, line);
|
||||||
int setBand = mM3U8Option.getBandWidth();
|
int setBand = mM3U8Option.getBandWidth();
|
||||||
int bandWidth = getBandWidth(line);
|
int bandWidth = getBandWidth(line);
|
||||||
// 多码率的m3u8配置文件,清空信息
|
// 多码率的m3u8配置文件,清空信息
|
||||||
if (isGenerateIndexFile && mInfos != null) {
|
//if (isGenerateIndexFile && mInfos != null) {
|
||||||
mInfos.clear();
|
// mInfos.clear();
|
||||||
}
|
//}
|
||||||
if (setBand == 0) {
|
if (setBand == 0) {
|
||||||
handleBandWidth(conn, reader.readLine());
|
handleBandWidth(conn, reader.readLine());
|
||||||
} else if (bandWidth == setBand) {
|
} else if (bandWidth == setBand) {
|
||||||
@@ -162,8 +172,11 @@ final public class M3U8InfoThread implements Runnable {
|
|||||||
failDownload(String.format("【%s】码率不存在", bandWidth), false);
|
failDownload(String.format("【%s】码率不存在", bandWidth), false);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if (line.startsWith("EXT-X-KEY")) {
|
} else if (line.startsWith("#EXT-X-KEY")) {
|
||||||
|
addIndexInfo(isGenerateIndexFile, fos, line);
|
||||||
getKeyInfo(line);
|
getKeyInfo(line);
|
||||||
|
} else {
|
||||||
|
addIndexInfo(isGenerateIndexFile, fos, line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,8 +190,11 @@ final public class M3U8InfoThread implements Runnable {
|
|||||||
}
|
}
|
||||||
CompleteInfo info = new CompleteInfo();
|
CompleteInfo info = new CompleteInfo();
|
||||||
info.obj = extInf;
|
info.obj = extInf;
|
||||||
generateIndexFile();
|
|
||||||
onFileInfoCallback.onComplete(mEntity.getKey(), info);
|
onFileInfoCallback.onComplete(mEntity.getKey(), info);
|
||||||
|
if (fos != null) {
|
||||||
|
fos.close();
|
||||||
|
}
|
||||||
} else if (code == HttpURLConnection.HTTP_MOVED_TEMP
|
} else if (code == HttpURLConnection.HTTP_MOVED_TEMP
|
||||||
|| code == HttpURLConnection.HTTP_MOVED_PERM
|
|| code == HttpURLConnection.HTTP_MOVED_PERM
|
||||||
|| code == HttpURLConnection.HTTP_SEE_OTHER
|
|| code == HttpURLConnection.HTTP_SEE_OTHER
|
||||||
@@ -193,40 +209,19 @@ final public class M3U8InfoThread implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建索引文件
|
* 添加切片信息到索引文件中
|
||||||
|
* 直播下载的索引只记录头部信息,不记录EXTINF中的信息,该信息在onGetPeer的方法中添加。
|
||||||
|
* 点播下载记录所有信息
|
||||||
|
*
|
||||||
|
* @param write true 将信息写入文件
|
||||||
|
* @param info 切片信息
|
||||||
*/
|
*/
|
||||||
private void generateIndexFile() {
|
private void addIndexInfo(boolean write, FileOutputStream fos, String info)
|
||||||
if (mTaskWrapper.getEntity().getM3U8Entity().isGenerateIndexFile()) {
|
throws IOException {
|
||||||
|
if (!write) {
|
||||||
String indexPath = String.format(M3U8_INDEX_FORMAT, mEntity.getFilePath());
|
return;
|
||||||
File indexFile = new File(indexPath);
|
|
||||||
if (indexFile.exists()) {
|
|
||||||
FileUtil.deleteFile(indexPath);
|
|
||||||
}
|
|
||||||
FileUtil.createFile(indexPath);
|
|
||||||
|
|
||||||
FileOutputStream fos = null;
|
|
||||||
try {
|
|
||||||
fos = new FileOutputStream(indexFile);
|
|
||||||
for (String str : mInfos) {
|
|
||||||
byte[] by = str.concat("\r\n").getBytes(Charset.forName("UTF-8"));
|
|
||||||
fos.write(by, 0, by.length);
|
|
||||||
}
|
|
||||||
fos.flush();
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
if (fos != null) {
|
|
||||||
try {
|
|
||||||
fos.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
fos.write(info.concat("\r\n").getBytes(Charset.forName("UTF-8")));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -355,11 +350,22 @@ final public class M3U8InfoThread implements Runnable {
|
|||||||
File keyF = new File(info.keyPath);
|
File keyF = new File(info.keyPath);
|
||||||
if (!keyF.exists()) {
|
if (!keyF.exists()) {
|
||||||
ALog.d(TAG, "密钥不存在,下载密钥");
|
ALog.d(TAG, "密钥不存在,下载密钥");
|
||||||
FileUtil.createFile(keyF.getPath());
|
FileUtil.createFile(keyF);
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
URL url = ConnectionHelp.handleUrl(info.keyUrl, mHttpOption);
|
|
||||||
|
IKeyUrlConverter keyUrlConverter = mM3U8Option.getKeyUrlConverter();
|
||||||
|
String keyUrl = info.keyUrl;
|
||||||
|
if (keyUrlConverter != null) {
|
||||||
|
keyUrl = keyUrlConverter.convert(keyUrl);
|
||||||
|
}
|
||||||
|
if (TextUtils.isEmpty(keyUrl)){
|
||||||
|
ALog.e(TAG, "m3u8密钥key url 为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
URL url = ConnectionHelp.handleUrl(keyUrl, mHttpOption);
|
||||||
conn = ConnectionHelp.handleConnection(url, mHttpOption);
|
conn = ConnectionHelp.handleConnection(url, mHttpOption);
|
||||||
ConnectionHelp.setConnectParam(mHttpOption, conn);
|
ConnectionHelp.setConnectParam(mHttpOption, conn);
|
||||||
conn.setConnectTimeout(mConnectTimeOut);
|
conn.setConnectTimeout(mConnectTimeOut);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import com.arialyy.aria.core.download.M3U8Entity;
|
|||||||
import com.arialyy.aria.core.inf.IRecordHandler;
|
import com.arialyy.aria.core.inf.IRecordHandler;
|
||||||
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
|
import com.arialyy.aria.util.FileUtil;
|
||||||
import com.arialyy.aria.util.RecordUtil;
|
import com.arialyy.aria.util.RecordUtil;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -42,7 +43,7 @@ public class M3U8RecordAdapter extends AbsRecordHandlerAdapter {
|
|||||||
|
|
||||||
@Override public void onPre() {
|
@Override public void onPre() {
|
||||||
super.onPre();
|
super.onPre();
|
||||||
if (getWrapper().getRequestType() == ITaskWrapper.M3U8_LIVE){
|
if (getWrapper().getRequestType() == ITaskWrapper.M3U8_LIVE) {
|
||||||
RecordUtil.delTaskRecord(getEntity().getFilePath(), IRecordHandler.TYPE_DOWNLOAD);
|
RecordUtil.delTaskRecord(getEntity().getFilePath(), IRecordHandler.TYPE_DOWNLOAD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,18 +55,22 @@ public class M3U8RecordAdapter extends AbsRecordHandlerAdapter {
|
|||||||
String cacheDir = mOption.getCacheDir();
|
String cacheDir = mOption.getCacheDir();
|
||||||
long currentProgress = 0;
|
long currentProgress = 0;
|
||||||
int completeNum = 0;
|
int completeNum = 0;
|
||||||
|
File targetFile = new File(mTaskRecord.filePath);
|
||||||
|
if (!targetFile.exists()) {
|
||||||
|
FileUtil.createFile(targetFile);
|
||||||
|
}
|
||||||
|
|
||||||
M3U8Entity m3U8Entity = ((DownloadEntity) getEntity()).getM3U8Entity();
|
M3U8Entity m3U8Entity = ((DownloadEntity) getEntity()).getM3U8Entity();
|
||||||
// 重新下载所有切片
|
// 重新下载所有切片
|
||||||
boolean reDownload =
|
boolean reDownload =
|
||||||
(m3U8Entity.getPeerNum() <= 0 || (m3U8Entity.isGenerateIndexFile() && !new File(
|
(m3U8Entity.getPeerNum() <= 0 || (mOption.isGenerateIndexFile() && !new File(
|
||||||
String.format(M3U8InfoThread.M3U8_INDEX_FORMAT, getEntity().getFilePath())).exists()));
|
String.format(M3U8InfoThread.M3U8_INDEX_FORMAT, getEntity().getFilePath())).exists()));
|
||||||
|
|
||||||
for (ThreadRecord record : mTaskRecord.threadRecords) {
|
for (ThreadRecord record : mTaskRecord.threadRecords) {
|
||||||
File temp = new File(BaseM3U8Loader.getTsFilePath(cacheDir, record.threadId));
|
File temp = new File(BaseM3U8Loader.getTsFilePath(cacheDir, record.threadId));
|
||||||
if (!record.isComplete || reDownload) {
|
if (!record.isComplete || reDownload) {
|
||||||
if (temp.exists()) {
|
if (temp.exists()) {
|
||||||
temp.delete();
|
FileUtil.deleteFile(temp);
|
||||||
}
|
}
|
||||||
record.startLocation = 0;
|
record.startLocation = 0;
|
||||||
//ALog.d(TAG, String.format("分片【%s】未完成,将重新下载该分片", record.threadId));
|
//ALog.d(TAG, String.format("分片【%s】未完成,将重新下载该分片", record.threadId));
|
||||||
@@ -112,23 +117,22 @@ public class M3U8RecordAdapter extends AbsRecordHandlerAdapter {
|
|||||||
record.filePath = getEntity().getFilePath();
|
record.filePath = getEntity().getFilePath();
|
||||||
record.threadRecords = new ArrayList<>();
|
record.threadRecords = new ArrayList<>();
|
||||||
record.threadNum = threadNum;
|
record.threadNum = threadNum;
|
||||||
|
record.isBlock = true;
|
||||||
|
|
||||||
int requestType = getWrapper().getRequestType();
|
int requestType = getWrapper().getRequestType();
|
||||||
if (requestType == ITaskWrapper.M3U8_VOD) {
|
if (requestType == ITaskWrapper.M3U8_VOD) {
|
||||||
record.taskType = TaskRecord.TYPE_M3U8_VOD;
|
record.taskType = TaskRecord.TYPE_M3U8_VOD;
|
||||||
record.isOpenDynamicFile = true;
|
|
||||||
record.bandWidth = mOption.getBandWidth();
|
|
||||||
} else if (requestType == ITaskWrapper.M3U8_LIVE) {
|
} else if (requestType == ITaskWrapper.M3U8_LIVE) {
|
||||||
record.taskType = TaskRecord.TYPE_M3U8_LIVE;
|
record.taskType = TaskRecord.TYPE_M3U8_LIVE;
|
||||||
record.isOpenDynamicFile = true;
|
|
||||||
record.bandWidth = mOption.getBandWidth();
|
|
||||||
}
|
}
|
||||||
|
record.bandWidth = mOption.getBandWidth();
|
||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public int initTaskThreadNum() {
|
@Override public int initTaskThreadNum() {
|
||||||
if (getWrapper().getRequestType() == ITaskWrapper.M3U8_VOD) {
|
if (getWrapper().getRequestType() == ITaskWrapper.M3U8_VOD) {
|
||||||
return mOption.getUrls().size();
|
return
|
||||||
|
mOption.getUrls() == null || mOption.getUrls().isEmpty() ? 1 : mOption.getUrls().size();
|
||||||
}
|
}
|
||||||
if (getWrapper().getRequestType() == ITaskWrapper.M3U8_LIVE) {
|
if (getWrapper().getRequestType() == ITaskWrapper.M3U8_LIVE) {
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package com.arialyy.aria.m3u8;
|
|||||||
|
|
||||||
import com.arialyy.aria.core.inf.ITaskOption;
|
import com.arialyy.aria.core.inf.ITaskOption;
|
||||||
import com.arialyy.aria.core.processor.IBandWidthUrlConverter;
|
import com.arialyy.aria.core.processor.IBandWidthUrlConverter;
|
||||||
|
import com.arialyy.aria.core.processor.IKeyUrlConverter;
|
||||||
import com.arialyy.aria.core.processor.ILiveTsUrlConverter;
|
import com.arialyy.aria.core.processor.ILiveTsUrlConverter;
|
||||||
import com.arialyy.aria.core.processor.ITsMergeHandler;
|
import com.arialyy.aria.core.processor.ITsMergeHandler;
|
||||||
import com.arialyy.aria.core.processor.IVodTsUrlConverter;
|
import com.arialyy.aria.core.processor.IVodTsUrlConverter;
|
||||||
@@ -101,14 +102,27 @@ public class M3U8TaskOption implements ITaskOption {
|
|||||||
/**
|
/**
|
||||||
* 生成索引占位字段
|
* 生成索引占位字段
|
||||||
*/
|
*/
|
||||||
private boolean generateIndexFileTemp = false;
|
private boolean generateIndexFile = false;
|
||||||
|
|
||||||
public boolean isGenerateIndexFileTemp() {
|
/**
|
||||||
return generateIndexFileTemp;
|
* 加密密钥的解密处理器
|
||||||
|
*/
|
||||||
|
private SoftReference<IKeyUrlConverter> keyUrlConverter;
|
||||||
|
|
||||||
|
public IKeyUrlConverter getKeyUrlConverter() {
|
||||||
|
return keyUrlConverter == null ? null : keyUrlConverter.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGenerateIndexFileTemp(boolean generateIndexFileTemp) {
|
public void setKeyUrlConverter(IKeyUrlConverter keyUrlConverter) {
|
||||||
this.generateIndexFileTemp = generateIndexFileTemp;
|
this.keyUrlConverter = new SoftReference<>(keyUrlConverter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isGenerateIndexFile() {
|
||||||
|
return generateIndexFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGenerateIndexFile(boolean generateIndexFile) {
|
||||||
|
this.generateIndexFile = generateIndexFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getJumpIndex() {
|
public int getJumpIndex() {
|
||||||
|
|||||||
@@ -89,10 +89,18 @@ public class M3U8ThreadTaskAdapter extends AbsThreadTaskAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int code = conn.getResponseCode();
|
||||||
|
if (code != HttpURLConnection.HTTP_OK) {
|
||||||
|
fail(new TaskException(TAG,
|
||||||
|
String.format("连接错误,http错误码:%s,url:%s", code, getThreadConfig().url)),
|
||||||
|
false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
is = new BufferedInputStream(ConnectionHelp.convertInputStream(conn));
|
is = new BufferedInputStream(ConnectionHelp.convertInputStream(conn));
|
||||||
if (mHttpTaskOption.isChunked()) {
|
if (mHttpTaskOption.isChunked()) {
|
||||||
readChunked(is);
|
readChunked(is);
|
||||||
} else if (getThreadConfig().isOpenDynamicFile) {
|
} else if (getThreadConfig().isBlock) {
|
||||||
readDynamicFile(is);
|
readDynamicFile(is);
|
||||||
}
|
}
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
|
|||||||
@@ -24,17 +24,22 @@ import com.arialyy.aria.core.common.SubThreadConfig;
|
|||||||
import com.arialyy.aria.core.download.DTaskWrapper;
|
import com.arialyy.aria.core.download.DTaskWrapper;
|
||||||
import com.arialyy.aria.core.inf.IThreadState;
|
import com.arialyy.aria.core.inf.IThreadState;
|
||||||
import com.arialyy.aria.core.listener.IEventListener;
|
import com.arialyy.aria.core.listener.IEventListener;
|
||||||
|
import com.arialyy.aria.core.listener.ISchedulers;
|
||||||
import com.arialyy.aria.core.manager.ThreadTaskManager;
|
import com.arialyy.aria.core.manager.ThreadTaskManager;
|
||||||
|
import com.arialyy.aria.core.processor.ITsMergeHandler;
|
||||||
import com.arialyy.aria.core.task.ThreadTask;
|
import com.arialyy.aria.core.task.ThreadTask;
|
||||||
import com.arialyy.aria.m3u8.BaseM3U8Loader;
|
import com.arialyy.aria.m3u8.BaseM3U8Loader;
|
||||||
import com.arialyy.aria.core.processor.ITsMergeHandler;
|
|
||||||
import com.arialyy.aria.m3u8.IdGenerator;
|
import com.arialyy.aria.m3u8.IdGenerator;
|
||||||
import com.arialyy.aria.m3u8.M3U8Listener;
|
import com.arialyy.aria.m3u8.M3U8Listener;
|
||||||
|
import com.arialyy.aria.m3u8.M3U8TaskOption;
|
||||||
import com.arialyy.aria.m3u8.M3U8ThreadTaskAdapter;
|
import com.arialyy.aria.m3u8.M3U8ThreadTaskAdapter;
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
import com.arialyy.aria.util.FileUtil;
|
import com.arialyy.aria.util.FileUtil;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.FilenameFilter;
|
import java.io.FilenameFilter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
@@ -42,6 +47,8 @@ import java.util.concurrent.LinkedBlockingQueue;
|
|||||||
import java.util.concurrent.locks.Condition;
|
import java.util.concurrent.locks.Condition;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
import static com.arialyy.aria.m3u8.M3U8InfoThread.M3U8_INDEX_FORMAT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* M3U8点播文件下载器
|
* M3U8点播文件下载器
|
||||||
*/
|
*/
|
||||||
@@ -49,15 +56,21 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
|
|||||||
/**
|
/**
|
||||||
* 最大执行数
|
* 最大执行数
|
||||||
*/
|
*/
|
||||||
private static final int EXEC_MAX_NUM = 4;
|
private static int EXEC_MAX_NUM = 4;
|
||||||
private Handler mStateHandler;
|
private Handler mStateHandler;
|
||||||
private ArrayBlockingQueue<Long> mFlagQueue = new ArrayBlockingQueue<>(EXEC_MAX_NUM);
|
private ArrayBlockingQueue<Long> mFlagQueue = new ArrayBlockingQueue<>(EXEC_MAX_NUM);
|
||||||
private ReentrantLock LOCK = new ReentrantLock();
|
private ReentrantLock LOCK = new ReentrantLock();
|
||||||
private Condition mCondition = LOCK.newCondition();
|
private Condition mCondition = LOCK.newCondition();
|
||||||
private LinkedBlockingQueue<String> mPeerQueue = new LinkedBlockingQueue<>();
|
private LinkedBlockingQueue<ExtInfo> mPeerQueue = new LinkedBlockingQueue<>();
|
||||||
|
private ExtInfo mCurExtInfo;
|
||||||
|
private FileOutputStream mIndexFos;
|
||||||
|
|
||||||
M3U8LiveLoader(M3U8Listener listener, DTaskWrapper wrapper) {
|
M3U8LiveLoader(M3U8Listener listener, DTaskWrapper wrapper) {
|
||||||
super(listener, wrapper);
|
super(listener, wrapper);
|
||||||
|
if (((M3U8TaskOption) wrapper.getM3u8Option()).isGenerateIndexFile()) {
|
||||||
|
ALog.i(TAG, "直播文件下载,创建索引文件的操作将导致只能同时下载一个切片");
|
||||||
|
EXEC_MAX_NUM = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected IThreadState createStateManager(Looper looper) {
|
@Override protected IThreadState createStateManager(Looper looper) {
|
||||||
@@ -66,8 +79,8 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
|
|||||||
return manager;
|
return manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
void offerPeer(String peerUrl) {
|
void offerPeer(ExtInfo extInfo) {
|
||||||
mPeerQueue.offer(peerUrl);
|
mPeerQueue.offer(extInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected void handleTask() {
|
@Override protected void handleTask() {
|
||||||
@@ -80,13 +93,14 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
|
|||||||
try {
|
try {
|
||||||
LOCK.lock();
|
LOCK.lock();
|
||||||
while (mFlagQueue.size() < EXEC_MAX_NUM) {
|
while (mFlagQueue.size() < EXEC_MAX_NUM) {
|
||||||
String url = mPeerQueue.poll();
|
ExtInfo extInfo = mPeerQueue.poll();
|
||||||
if (url == null) {
|
if (extInfo == null) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ThreadTask task = createThreadTask(cacheDir, index, url);
|
mCurExtInfo = extInfo;
|
||||||
|
ThreadTask task = createThreadTask(cacheDir, index, extInfo.url);
|
||||||
getTaskList().put(index, task);
|
getTaskList().put(index, task);
|
||||||
mFlagQueue.offer(startThreadTask(task));
|
mFlagQueue.offer(startThreadTask(task, task.getConfig().peerIndex));
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
if (mFlagQueue.size() > 0) {
|
if (mFlagQueue.size() > 0) {
|
||||||
@@ -106,11 +120,15 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
|
|||||||
return mTempFile.length();
|
return mTempFile.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyLock() {
|
private void notifyLock(boolean success, int peerId) {
|
||||||
try {
|
try {
|
||||||
LOCK.lock();
|
LOCK.lock();
|
||||||
long id = mFlagQueue.take();
|
long id = mFlagQueue.take();
|
||||||
ALog.d(TAG, String.format("线程【%s】完成", id));
|
if (success) {
|
||||||
|
ALog.d(TAG, String.format("切片【%s】下载成功", peerId));
|
||||||
|
} else {
|
||||||
|
ALog.e(TAG, String.format("切片【%s】下载失败", peerId));
|
||||||
|
}
|
||||||
mCondition.signalAll();
|
mCondition.signalAll();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@@ -119,13 +137,27 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override protected void onPostStop() {
|
||||||
|
super.onPostStop();
|
||||||
|
if (mIndexFos != null) {
|
||||||
|
try {
|
||||||
|
mIndexFos.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 启动线程任务
|
* 启动线程任务
|
||||||
*
|
*
|
||||||
* @return 线程唯一id标志
|
* @return 线程唯一id标志
|
||||||
*/
|
*/
|
||||||
private long startThreadTask(ThreadTask task) {
|
private long startThreadTask(ThreadTask task, int indexId) {
|
||||||
ThreadTaskManager.getInstance().startThread(mTaskWrapper.getKey(), task);
|
ThreadTaskManager.getInstance().startThread(mTaskWrapper.getKey(), task);
|
||||||
|
((M3U8Listener) mListener).onPeerStart(mTaskWrapper.getKey(),
|
||||||
|
task.getConfig().tempFile.getPath(),
|
||||||
|
indexId);
|
||||||
return IdGenerator.getInstance().nextId();
|
return IdGenerator.getInstance().nextId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,18 +171,19 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
|
|||||||
record.tsUrl = tsUrl;
|
record.tsUrl = tsUrl;
|
||||||
record.threadType = TaskRecord.TYPE_M3U8_LIVE;
|
record.threadType = TaskRecord.TYPE_M3U8_LIVE;
|
||||||
record.threadId = indexId;
|
record.threadId = indexId;
|
||||||
|
mRecord.threadRecords.add(record);
|
||||||
|
|
||||||
SubThreadConfig config = new SubThreadConfig();
|
SubThreadConfig config = new SubThreadConfig();
|
||||||
config.url = tsUrl;
|
config.url = tsUrl;
|
||||||
config.tempFile = new File(getTsFilePath(cacheDir, indexId));
|
config.tempFile = new File(getTsFilePath(cacheDir, indexId));
|
||||||
config.isBlock = mRecord.isBlock;
|
config.isBlock = mRecord.isBlock;
|
||||||
config.isOpenDynamicFile = mRecord.isOpenDynamicFile;
|
|
||||||
config.taskWrapper = mTaskWrapper;
|
config.taskWrapper = mTaskWrapper;
|
||||||
config.record = record;
|
config.record = record;
|
||||||
config.stateHandler = mStateHandler;
|
config.stateHandler = mStateHandler;
|
||||||
|
config.peerIndex = indexId;
|
||||||
|
|
||||||
if (!config.tempFile.exists()) {
|
if (!config.tempFile.exists()) {
|
||||||
FileUtil.createFile(config.tempFile.getPath());
|
FileUtil.createFile(config.tempFile);
|
||||||
}
|
}
|
||||||
ThreadTask threadTask = new ThreadTask(config);
|
ThreadTask threadTask = new ThreadTask(config);
|
||||||
M3U8ThreadTaskAdapter adapter = new M3U8ThreadTaskAdapter(config);
|
M3U8ThreadTaskAdapter adapter = new M3U8ThreadTaskAdapter(config);
|
||||||
@@ -163,10 +196,7 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
|
|||||||
*
|
*
|
||||||
* @return {@code true} 合并成功,{@code false}合并失败
|
* @return {@code true} 合并成功,{@code false}合并失败
|
||||||
*/
|
*/
|
||||||
public boolean mergeFile() {
|
boolean mergeFile() {
|
||||||
if (getEntity().getM3U8Entity().isGenerateIndexFile()) {
|
|
||||||
return generateIndexFile();
|
|
||||||
}
|
|
||||||
ITsMergeHandler mergeHandler = mM3U8Option.getMergeHandler();
|
ITsMergeHandler mergeHandler = mM3U8Option.getMergeHandler();
|
||||||
String cacheDir = getCacheDir();
|
String cacheDir = getCacheDir();
|
||||||
List<String> partPath = new ArrayList<>();
|
List<String> partPath = new ArrayList<>();
|
||||||
@@ -213,7 +243,7 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
|
|||||||
/**
|
/**
|
||||||
* 任务状态回调
|
* 任务状态回调
|
||||||
*/
|
*/
|
||||||
private IEventListener mListener;
|
private M3U8Listener mListener;
|
||||||
private long mProgress; //当前总进度
|
private long mProgress; //当前总进度
|
||||||
private Looper mLooper;
|
private Looper mLooper;
|
||||||
|
|
||||||
@@ -222,7 +252,7 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
|
|||||||
*/
|
*/
|
||||||
LiveStateManager(Looper looper, IEventListener listener) {
|
LiveStateManager(Looper looper, IEventListener listener) {
|
||||||
mLooper = looper;
|
mLooper = looper;
|
||||||
mListener = listener;
|
mListener = (M3U8Listener) listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -234,6 +264,7 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean handleMessage(Message msg) {
|
@Override public boolean handleMessage(Message msg) {
|
||||||
|
int peerIndex = msg.getData().getInt(ISchedulers.DATA_M3U8_PEER_INDEX);
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
case STATE_STOP:
|
case STATE_STOP:
|
||||||
if (isBreak()) {
|
if (isBreak()) {
|
||||||
@@ -248,15 +279,46 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case STATE_COMPLETE:
|
case STATE_COMPLETE:
|
||||||
notifyLock();
|
notifyLock(true, peerIndex);
|
||||||
|
if (mM3U8Option.isGenerateIndexFile() && !isBreak()) {
|
||||||
|
addExtInf(mCurExtInfo.url, mCurExtInfo.extInf);
|
||||||
|
}
|
||||||
|
mListener.onPeerComplete(mTaskWrapper.getKey(),
|
||||||
|
msg.getData().getString(ISchedulers.DATA_M3U8_PEER_PATH), peerIndex);
|
||||||
break;
|
break;
|
||||||
case STATE_RUNNING:
|
case STATE_RUNNING:
|
||||||
mProgress += (long) msg.obj;
|
mProgress += (long) msg.obj;
|
||||||
break;
|
break;
|
||||||
|
case STATE_FAIL:
|
||||||
|
notifyLock(false, peerIndex);
|
||||||
|
mListener.onPeerFail(mTaskWrapper.getKey(),
|
||||||
|
msg.getData().getString(ISchedulers.DATA_M3U8_PEER_PATH), peerIndex);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 给索引文件添加extInfo信息
|
||||||
|
*/
|
||||||
|
private void addExtInf(String url, String extInf) {
|
||||||
|
File indexFile =
|
||||||
|
new File(String.format(M3U8_INDEX_FORMAT, getEntity().getFilePath()));
|
||||||
|
if (!indexFile.exists()) {
|
||||||
|
ALog.e(TAG, String.format("索引文件【%s】不存在,添加peer的extInf失败", indexFile.getPath()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (mIndexFos == null) {
|
||||||
|
mIndexFos = new FileOutputStream(indexFile, true);
|
||||||
|
}
|
||||||
|
mIndexFos.write(extInf.concat("\r\n").getBytes(Charset.forName("UTF-8")));
|
||||||
|
mIndexFos.write(url.concat("\r\n").getBytes(Charset.forName("UTF-8")));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override public boolean isFail() {
|
@Override public boolean isFail() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -269,4 +331,14 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
|
|||||||
return mProgress;
|
return mProgress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class ExtInfo {
|
||||||
|
String url;
|
||||||
|
String extInf;
|
||||||
|
|
||||||
|
ExtInfo(String url, String extInf) {
|
||||||
|
this.url = url;
|
||||||
|
this.extInf = extInf;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import com.arialyy.aria.core.processor.ILiveTsUrlConverter;
|
|||||||
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
||||||
import com.arialyy.aria.exception.BaseException;
|
import com.arialyy.aria.exception.BaseException;
|
||||||
import com.arialyy.aria.exception.M3U8Exception;
|
import com.arialyy.aria.exception.M3U8Exception;
|
||||||
|
import com.arialyy.aria.exception.TaskException;
|
||||||
import com.arialyy.aria.http.HttpTaskOption;
|
import com.arialyy.aria.http.HttpTaskOption;
|
||||||
import com.arialyy.aria.m3u8.M3U8InfoThread;
|
import com.arialyy.aria.m3u8.M3U8InfoThread;
|
||||||
import com.arialyy.aria.m3u8.M3U8Listener;
|
import com.arialyy.aria.m3u8.M3U8Listener;
|
||||||
@@ -87,7 +88,7 @@ public class M3U8LiveUtil extends AbsNormalLoaderUtil {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
infoThread.setOnGetPeerCallback(new M3U8InfoThread.OnGetLivePeerCallback() {
|
infoThread.setOnGetPeerCallback(new M3U8InfoThread.OnGetLivePeerCallback() {
|
||||||
@Override public void onGetPeer(String url) {
|
@Override public void onGetPeer(String url, String extInf) {
|
||||||
if (mPeerUrls.contains(url)) {
|
if (mPeerUrls.contains(url)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -104,7 +105,7 @@ public class M3U8LiveUtil extends AbsNormalLoaderUtil {
|
|||||||
fail(new M3U8Exception(TAG, String.format("ts地址错误,url:%s", url)), false);
|
fail(new M3U8Exception(TAG, String.format("ts地址错误,url:%s", url)), false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
getLoader().offerPeer(url);
|
getLoader().offerPeer(new M3U8LiveLoader.ExtInfo(url, extInf));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return infoThread;
|
return infoThread;
|
||||||
@@ -129,7 +130,13 @@ public class M3U8LiveUtil extends AbsNormalLoaderUtil {
|
|||||||
if (mInfoThread != null) {
|
if (mInfoThread != null) {
|
||||||
mInfoThread.setStop(true);
|
mInfoThread.setStop(true);
|
||||||
closeTimer();
|
closeTimer();
|
||||||
if (mM3U8Option.isMergeFile()) {
|
if (((M3U8TaskOption) getTaskWrapper().getM3u8Option()).isGenerateIndexFile()) {
|
||||||
|
if (getLoader().generateIndexFile(true)) {
|
||||||
|
getListener().onComplete();
|
||||||
|
} else {
|
||||||
|
getListener().onFail(false, new TaskException(TAG, "创建索引文件失败"));
|
||||||
|
}
|
||||||
|
} else if (mM3U8Option.isMergeFile()) {
|
||||||
if (getLoader().mergeFile()) {
|
if (getLoader().mergeFile()) {
|
||||||
getListener().onComplete();
|
getListener().onComplete();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -31,14 +31,16 @@ import com.arialyy.aria.core.inf.IThreadState;
|
|||||||
import com.arialyy.aria.core.listener.IEventListener;
|
import com.arialyy.aria.core.listener.IEventListener;
|
||||||
import com.arialyy.aria.core.listener.ISchedulers;
|
import com.arialyy.aria.core.listener.ISchedulers;
|
||||||
import com.arialyy.aria.core.manager.ThreadTaskManager;
|
import com.arialyy.aria.core.manager.ThreadTaskManager;
|
||||||
|
import com.arialyy.aria.core.processor.ITsMergeHandler;
|
||||||
import com.arialyy.aria.core.task.ThreadTask;
|
import com.arialyy.aria.core.task.ThreadTask;
|
||||||
import com.arialyy.aria.exception.BaseException;
|
import com.arialyy.aria.exception.BaseException;
|
||||||
|
import com.arialyy.aria.exception.TaskException;
|
||||||
import com.arialyy.aria.m3u8.BaseM3U8Loader;
|
import com.arialyy.aria.m3u8.BaseM3U8Loader;
|
||||||
import com.arialyy.aria.core.processor.ITsMergeHandler;
|
|
||||||
import com.arialyy.aria.m3u8.M3U8Listener;
|
import com.arialyy.aria.m3u8.M3U8Listener;
|
||||||
import com.arialyy.aria.m3u8.M3U8TaskOption;
|
import com.arialyy.aria.m3u8.M3U8TaskOption;
|
||||||
import com.arialyy.aria.m3u8.M3U8ThreadTaskAdapter;
|
import com.arialyy.aria.m3u8.M3U8ThreadTaskAdapter;
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
import com.arialyy.aria.util.FileUtil;
|
import com.arialyy.aria.util.FileUtil;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -219,6 +221,12 @@ public class M3U8VodLoader extends BaseM3U8Loader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mManager.updateStateCount();
|
mManager.updateStateCount();
|
||||||
|
if (mCompleteNum <= 0){
|
||||||
|
mListener.onStart(0);
|
||||||
|
}else {
|
||||||
|
int percent = mCompleteNum * 100 / mRecord.threadRecords.size();
|
||||||
|
mListener.onResume(percent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -428,13 +436,12 @@ public class M3U8VodLoader extends BaseM3U8Loader {
|
|||||||
config.url = record.tsUrl;
|
config.url = record.tsUrl;
|
||||||
config.tempFile = new File(BaseM3U8Loader.getTsFilePath(cacheDir, record.threadId));
|
config.tempFile = new File(BaseM3U8Loader.getTsFilePath(cacheDir, record.threadId));
|
||||||
config.isBlock = mRecord.isBlock;
|
config.isBlock = mRecord.isBlock;
|
||||||
config.isOpenDynamicFile = mRecord.isOpenDynamicFile;
|
|
||||||
config.taskWrapper = mTaskWrapper;
|
config.taskWrapper = mTaskWrapper;
|
||||||
config.record = record;
|
config.record = record;
|
||||||
config.stateHandler = mStateHandler;
|
config.stateHandler = mStateHandler;
|
||||||
config.peerIndex = index;
|
config.peerIndex = index;
|
||||||
if (!config.tempFile.exists()) {
|
if (!config.tempFile.exists()) {
|
||||||
FileUtil.createFile(config.tempFile.getPath());
|
FileUtil.createFile(config.tempFile);
|
||||||
}
|
}
|
||||||
ThreadTask threadTask = new ThreadTask(config);
|
ThreadTask threadTask = new ThreadTask(config);
|
||||||
M3U8ThreadTaskAdapter adapter = new M3U8ThreadTaskAdapter(config);
|
M3U8ThreadTaskAdapter adapter = new M3U8ThreadTaskAdapter(config);
|
||||||
@@ -446,7 +453,7 @@ public class M3U8VodLoader extends BaseM3U8Loader {
|
|||||||
* M3U8线程状态管理
|
* M3U8线程状态管理
|
||||||
*/
|
*/
|
||||||
private class VodStateManager implements IThreadState {
|
private class VodStateManager implements IThreadState {
|
||||||
private final String TAG = "M3U8ThreadStateManager";
|
private final String TAG = CommonUtil.getClassName(VodStateManager.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任务状态回调
|
* 任务状态回调
|
||||||
@@ -456,7 +463,8 @@ public class M3U8VodLoader extends BaseM3U8Loader {
|
|||||||
private int cancelNum = 0; // 已经取消的线程的数
|
private int cancelNum = 0; // 已经取消的线程的数
|
||||||
private int stopNum = 0; // 已经停止的线程数
|
private int stopNum = 0; // 已经停止的线程数
|
||||||
private int failNum = 0; // 失败的线程数
|
private int failNum = 0; // 失败的线程数
|
||||||
private long progress; //当前总进度
|
private long percent; //当前总进度,百分比进度
|
||||||
|
private long progress;
|
||||||
private TaskRecord taskRecord; // 任务记录
|
private TaskRecord taskRecord; // 任务记录
|
||||||
private Looper looper;
|
private Looper looper;
|
||||||
|
|
||||||
@@ -473,6 +481,7 @@ public class M3U8VodLoader extends BaseM3U8Loader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
|
progress = getEntity().getCurrentProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateStateCount() {
|
private void updateStateCount() {
|
||||||
@@ -559,7 +568,14 @@ public class M3U8VodLoader extends BaseM3U8Loader {
|
|||||||
"startThreadNum = %s, stopNum = %s, cancelNum = %s, failNum = %s, completeNum = %s, flagQueueSize = %s",
|
"startThreadNum = %s, stopNum = %s, cancelNum = %s, failNum = %s, completeNum = %s, flagQueueSize = %s",
|
||||||
startThreadNum, stopNum, cancelNum, failNum, mCompleteNum, mFlagQueue.size()));
|
startThreadNum, stopNum, cancelNum, failNum, mCompleteNum, mFlagQueue.size()));
|
||||||
ALog.d(TAG, String.format("vod任务【%s】完成", mTempFile.getName()));
|
ALog.d(TAG, String.format("vod任务【%s】完成", mTempFile.getName()));
|
||||||
if (mM3U8Option.isMergeFile()) {
|
|
||||||
|
if (mM3U8Option.isGenerateIndexFile()) {
|
||||||
|
if (generateIndexFile(false)){
|
||||||
|
listener.onComplete();
|
||||||
|
}else {
|
||||||
|
listener.onFail(false, new TaskException(TAG, "创建索引文件失败"));
|
||||||
|
}
|
||||||
|
} else if (mM3U8Option.isMergeFile()) {
|
||||||
if (mergeFile()) {
|
if (mergeFile()) {
|
||||||
listener.onComplete();
|
listener.onComplete();
|
||||||
} else {
|
} else {
|
||||||
@@ -596,6 +612,7 @@ public class M3U8VodLoader extends BaseM3U8Loader {
|
|||||||
int percent = completeNum * 100 / taskRecord.threadRecords.size();
|
int percent = completeNum * 100 / taskRecord.threadRecords.size();
|
||||||
getEntity().setPercent(percent);
|
getEntity().setPercent(percent);
|
||||||
getEntity().update();
|
getEntity().update();
|
||||||
|
this.percent = percent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean isFail() {
|
@Override public boolean isFail() {
|
||||||
@@ -625,9 +642,6 @@ public class M3U8VodLoader extends BaseM3U8Loader {
|
|||||||
* @return {@code true} 合并成功,{@code false}合并失败
|
* @return {@code true} 合并成功,{@code false}合并失败
|
||||||
*/
|
*/
|
||||||
private boolean mergeFile() {
|
private boolean mergeFile() {
|
||||||
if (getEntity().getM3U8Entity().isGenerateIndexFile()) {
|
|
||||||
return generateIndexFile();
|
|
||||||
}
|
|
||||||
ITsMergeHandler mergeHandler = mM3U8Option.getMergeHandler();
|
ITsMergeHandler mergeHandler = mM3U8Option.getMergeHandler();
|
||||||
String cacheDir = getCacheDir();
|
String cacheDir = getCacheDir();
|
||||||
List<String> partPath = new ArrayList<>();
|
List<String> partPath = new ArrayList<>();
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
<resources>
|
|
||||||
<string name="app_name">M3U8Component</string>
|
|
||||||
</resources>
|
|
||||||
@@ -23,6 +23,8 @@ import android.net.Network;
|
|||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
import android.net.NetworkRequest;
|
import android.net.NetworkRequest;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
import com.arialyy.aria.core.config.AppConfig;
|
import com.arialyy.aria.core.config.AppConfig;
|
||||||
import com.arialyy.aria.core.config.Configuration;
|
import com.arialyy.aria.core.config.Configuration;
|
||||||
import com.arialyy.aria.core.config.DGroupConfig;
|
import com.arialyy.aria.core.config.DGroupConfig;
|
||||||
@@ -56,6 +58,7 @@ public class AriaConfig {
|
|||||||
* 是否已经联网,true 已经联网
|
* 是否已经联网,true 已经联网
|
||||||
*/
|
*/
|
||||||
private static boolean isConnectedNet = true;
|
private static boolean isConnectedNet = true;
|
||||||
|
private Handler mAriaHandler;
|
||||||
|
|
||||||
private AriaConfig(Context context) {
|
private AriaConfig(Context context) {
|
||||||
APP = context.getApplicationContext();
|
APP = context.getApplicationContext();
|
||||||
@@ -105,6 +108,13 @@ public class AriaConfig {
|
|||||||
return mDGConfig;
|
return mDGConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized Handler getAriaHandler() {
|
||||||
|
if (mAriaHandler == null) {
|
||||||
|
mAriaHandler = new Handler(Looper.getMainLooper());
|
||||||
|
}
|
||||||
|
return mAriaHandler;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册网络监听,只有配置了检查网络{@link AppConfig#isNetCheck()}才会注册事件
|
* 注册网络监听,只有配置了检查网络{@link AppConfig#isNetCheck()}才会注册事件
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import com.arialyy.aria.core.processor.FtpInterceptHandler;
|
|||||||
import com.arialyy.aria.core.processor.IBandWidthUrlConverter;
|
import com.arialyy.aria.core.processor.IBandWidthUrlConverter;
|
||||||
import com.arialyy.aria.core.processor.IFtpUploadInterceptor;
|
import com.arialyy.aria.core.processor.IFtpUploadInterceptor;
|
||||||
import com.arialyy.aria.core.processor.IHttpFileLenAdapter;
|
import com.arialyy.aria.core.processor.IHttpFileLenAdapter;
|
||||||
|
import com.arialyy.aria.core.processor.IKeyUrlConverter;
|
||||||
import com.arialyy.aria.core.processor.ILiveTsUrlConverter;
|
import com.arialyy.aria.core.processor.ILiveTsUrlConverter;
|
||||||
import com.arialyy.aria.core.processor.ITsMergeHandler;
|
import com.arialyy.aria.core.processor.ITsMergeHandler;
|
||||||
import com.arialyy.aria.core.processor.IVodTsUrlConverter;
|
import com.arialyy.aria.core.processor.IVodTsUrlConverter;
|
||||||
@@ -61,6 +62,7 @@ public class TaskOptionParams {
|
|||||||
PROCESSORES.add(ILiveTsUrlConverter.class);
|
PROCESSORES.add(ILiveTsUrlConverter.class);
|
||||||
PROCESSORES.add(ITsMergeHandler.class);
|
PROCESSORES.add(ITsMergeHandler.class);
|
||||||
PROCESSORES.add(IVodTsUrlConverter.class);
|
PROCESSORES.add(IVodTsUrlConverter.class);
|
||||||
|
PROCESSORES.add(IKeyUrlConverter.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -78,12 +78,6 @@ public class TaskRecord extends DbEntity {
|
|||||||
*/
|
*/
|
||||||
public boolean isBlock = false;
|
public boolean isBlock = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否是使用虚拟文件下载的
|
|
||||||
* {@code true}是,{@code false}不是
|
|
||||||
*/
|
|
||||||
public boolean isOpenDynamicFile = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 线程类型
|
* 线程类型
|
||||||
* {@link #TYPE_HTTP_FTP}、{@link #TYPE_M3U8_VOD}
|
* {@link #TYPE_HTTP_FTP}、{@link #TYPE_M3U8_VOD}
|
||||||
|
|||||||
@@ -86,8 +86,8 @@ public class RecordHandler implements IRecordHandler {
|
|||||||
mTaskRecord.threadNum = mAdapter.initTaskThreadNum();
|
mTaskRecord.threadNum = mAdapter.initTaskThreadNum();
|
||||||
initRecord(false);
|
initRecord(false);
|
||||||
}
|
}
|
||||||
mAdapter.handlerTaskRecord(mTaskRecord);
|
|
||||||
}
|
}
|
||||||
|
mAdapter.handlerTaskRecord(mTaskRecord);
|
||||||
}
|
}
|
||||||
saveRecord();
|
saveRecord();
|
||||||
return mTaskRecord;
|
return mTaskRecord;
|
||||||
@@ -125,7 +125,6 @@ public class RecordHandler implements IRecordHandler {
|
|||||||
}
|
}
|
||||||
mTaskWrapper.setNewTask(false);
|
mTaskWrapper.setNewTask(false);
|
||||||
mTaskRecord = mAdapter.createTaskRecord(threadNum);
|
mTaskRecord = mAdapter.createTaskRecord(threadNum);
|
||||||
mTaskRecord.isOpenDynamicFile = false;
|
|
||||||
mTaskRecord.isBlock = false;
|
mTaskRecord.isBlock = false;
|
||||||
File tempFile = new File(getFilePath());
|
File tempFile = new File(getFilePath());
|
||||||
for (int i = 0; i < threadNum; i++) {
|
for (int i = 0; i < threadNum; i++) {
|
||||||
@@ -145,7 +144,7 @@ public class RecordHandler implements IRecordHandler {
|
|||||||
}
|
}
|
||||||
mTaskRecord.threadRecords.add(tRecord);
|
mTaskRecord.threadRecords.add(tRecord);
|
||||||
}
|
}
|
||||||
mConfigFile.delete();
|
FileUtil.deleteFile(mConfigFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,10 @@ import com.arialyy.aria.core.ThreadRecord;
|
|||||||
import com.arialyy.aria.core.inf.IRecordHandler;
|
import com.arialyy.aria.core.inf.IRecordHandler;
|
||||||
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
|
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
||||||
|
import com.arialyy.aria.util.FileUtil;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任务记录帮助类,用于处理统一的逻辑
|
* 任务记录帮助类,用于处理统一的逻辑
|
||||||
@@ -39,6 +42,45 @@ public class RecordHelper {
|
|||||||
mTaskRecord = record;
|
mTaskRecord = record;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理非分块的,多线程任务
|
||||||
|
*/
|
||||||
|
public void handleMultiRecord() {
|
||||||
|
// 默认线程分块长度
|
||||||
|
long blockSize = mWrapper.getEntity().getFileSize() / mTaskRecord.threadRecords.size();
|
||||||
|
File temp = new File(mTaskRecord.filePath);
|
||||||
|
boolean fileExists = false;
|
||||||
|
if (!temp.exists()) {
|
||||||
|
BufferedRandomAccessFile tempFile;
|
||||||
|
try {
|
||||||
|
tempFile = new BufferedRandomAccessFile(temp, "rw");
|
||||||
|
tempFile.setLength(mWrapper.getEntity().getFileSize());
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
fileExists = true;
|
||||||
|
}
|
||||||
|
// 处理文件被删除的情况
|
||||||
|
if (!fileExists) {
|
||||||
|
ALog.w(TAG, String.format("文件【%s】被删除,重新分配线程区间", mTaskRecord.filePath));
|
||||||
|
for (int i = 0; i < mTaskRecord.threadNum; i++) {
|
||||||
|
long startL = i * blockSize, endL = (i + 1) * blockSize;
|
||||||
|
ThreadRecord tr = mTaskRecord.threadRecords.get(i);
|
||||||
|
tr.startLocation = startL;
|
||||||
|
tr.isComplete = false;
|
||||||
|
|
||||||
|
//最后一个线程的结束位置即为文件的总长度
|
||||||
|
if (tr.threadId == (mTaskRecord.threadNum - 1)) {
|
||||||
|
endL = mWrapper.getEntity().getFileSize();
|
||||||
|
}
|
||||||
|
tr.endLocation = endL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mWrapper.setNewTask(false);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理分块任务的记录,分块文件(blockFileLen)长度必须需要小于等于线程区间(threadRectLen)的长度
|
* 处理分块任务的记录,分块文件(blockFileLen)长度必须需要小于等于线程区间(threadRectLen)的长度
|
||||||
*/
|
*/
|
||||||
@@ -104,10 +146,10 @@ public class RecordHelper {
|
|||||||
tr.startLocation = 0;
|
tr.startLocation = 0;
|
||||||
tr.isComplete = false;
|
tr.isComplete = false;
|
||||||
tr.endLocation = mWrapper.getEntity().getFileSize();
|
tr.endLocation = mWrapper.getEntity().getFileSize();
|
||||||
} else if (mTaskRecord.isOpenDynamicFile) {
|
} else if (mTaskRecord.isBlock) {
|
||||||
if (file.length() > mWrapper.getEntity().getFileSize()) {
|
if (file.length() > mWrapper.getEntity().getFileSize()) {
|
||||||
ALog.i(TAG, String.format("文件【%s】错误,任务重新开始", file.getPath()));
|
ALog.i(TAG, String.format("文件【%s】错误,任务重新开始", file.getPath()));
|
||||||
file.delete();
|
FileUtil.deleteFile(file);
|
||||||
tr.startLocation = 0;
|
tr.startLocation = 0;
|
||||||
tr.isComplete = false;
|
tr.isComplete = false;
|
||||||
tr.endLocation = mWrapper.getEntity().getFileSize();
|
tr.endLocation = mWrapper.getEntity().getFileSize();
|
||||||
|
|||||||
@@ -35,8 +35,6 @@ public class SubThreadConfig {
|
|||||||
public ThreadRecord record;
|
public ThreadRecord record;
|
||||||
// 状态处理器
|
// 状态处理器
|
||||||
public Handler stateHandler;
|
public Handler stateHandler;
|
||||||
// 动态文件
|
|
||||||
public boolean isOpenDynamicFile;
|
|
||||||
// m3u8切片索引
|
// m3u8切片索引
|
||||||
public int peerIndex;
|
public int peerIndex;
|
||||||
}
|
}
|
||||||
@@ -54,11 +54,6 @@ public class DTaskWrapper extends AbsTaskWrapper<DownloadEntity> {
|
|||||||
*/
|
*/
|
||||||
private String mTempFilePath;
|
private String mTempFilePath;
|
||||||
|
|
||||||
/**
|
|
||||||
* {@code true}强制下载,不考虑文件路径是否被占用
|
|
||||||
*/
|
|
||||||
private boolean forceDownload = false;
|
|
||||||
|
|
||||||
public DTaskWrapper(DownloadEntity entity) {
|
public DTaskWrapper(DownloadEntity entity) {
|
||||||
super(entity);
|
super(entity);
|
||||||
}
|
}
|
||||||
@@ -124,12 +119,4 @@ public class DTaskWrapper extends AbsTaskWrapper<DownloadEntity> {
|
|||||||
public void setTempFilePath(String mTempFilePath) {
|
public void setTempFilePath(String mTempFilePath) {
|
||||||
this.mTempFilePath = mTempFilePath;
|
this.mTempFilePath = mTempFilePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isForceDownload() {
|
|
||||||
return forceDownload;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setForceDownload(boolean forceDownload) {
|
|
||||||
this.forceDownload = forceDownload;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
package com.arialyy.aria.core.download;
|
package com.arialyy.aria.core.download;
|
||||||
|
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
|
import android.text.TextUtils;
|
||||||
import com.arialyy.aria.core.common.AbsGroupEntity;
|
import com.arialyy.aria.core.common.AbsGroupEntity;
|
||||||
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
||||||
import com.arialyy.aria.orm.annotation.Ignore;
|
import com.arialyy.aria.orm.annotation.Ignore;
|
||||||
@@ -48,7 +49,12 @@ public class DownloadGroupEntity extends AbsGroupEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public int getTaskType() {
|
@Override public int getTaskType() {
|
||||||
return getKey().startsWith("ftp") ? ITaskWrapper.D_FTP_DIR : ITaskWrapper.DG_HTTP;
|
if (getSubEntities() == null || getSubEntities().isEmpty() || TextUtils.isEmpty(
|
||||||
|
getSubEntities().get(0).getUrl())) {
|
||||||
|
return ITaskWrapper.ERROR;
|
||||||
|
}
|
||||||
|
return getSubEntities().get(0).getUrl().startsWith("ftp") ? ITaskWrapper.D_FTP_DIR
|
||||||
|
: ITaskWrapper.DG_HTTP;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DownloadGroupEntity() {
|
public DownloadGroupEntity() {
|
||||||
|
|||||||
@@ -58,11 +58,6 @@ public class M3U8Entity extends DbEntity implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
private String cacheDir;
|
private String cacheDir;
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成索引
|
|
||||||
*/
|
|
||||||
private boolean generateIndexFile;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加密key保存地址
|
* 加密key保存地址
|
||||||
*/
|
*/
|
||||||
@@ -115,14 +110,6 @@ public class M3U8Entity extends DbEntity implements Parcelable {
|
|||||||
this.iv = iv;
|
this.iv = iv;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isGenerateIndexFile() {
|
|
||||||
return generateIndexFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGenerateIndexFile(boolean generateIndexFile) {
|
|
||||||
this.generateIndexFile = generateIndexFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLive() {
|
public boolean isLive() {
|
||||||
return isLive;
|
return isLive;
|
||||||
}
|
}
|
||||||
@@ -248,7 +235,6 @@ public class M3U8Entity extends DbEntity implements Parcelable {
|
|||||||
dest.writeInt(this.peerNum);
|
dest.writeInt(this.peerNum);
|
||||||
dest.writeByte(this.isLive ? (byte) 1 : (byte) 0);
|
dest.writeByte(this.isLive ? (byte) 1 : (byte) 0);
|
||||||
dest.writeString(this.cacheDir);
|
dest.writeString(this.cacheDir);
|
||||||
dest.writeByte(this.generateIndexFile ? (byte) 1 : (byte) 0);
|
|
||||||
dest.writeString(this.keyPath);
|
dest.writeString(this.keyPath);
|
||||||
dest.writeString(this.keyUrl);
|
dest.writeString(this.keyUrl);
|
||||||
dest.writeString(this.method);
|
dest.writeString(this.method);
|
||||||
@@ -261,7 +247,6 @@ public class M3U8Entity extends DbEntity implements Parcelable {
|
|||||||
this.peerNum = in.readInt();
|
this.peerNum = in.readInt();
|
||||||
this.isLive = in.readByte() != 0;
|
this.isLive = in.readByte() != 0;
|
||||||
this.cacheDir = in.readString();
|
this.cacheDir = in.readString();
|
||||||
this.generateIndexFile = in.readByte() != 0;
|
|
||||||
this.keyPath = in.readString();
|
this.keyPath = in.readString();
|
||||||
this.keyUrl = in.readString();
|
this.keyUrl = in.readString();
|
||||||
this.method = in.readString();
|
this.method = in.readString();
|
||||||
|
|||||||
@@ -80,9 +80,8 @@ public abstract class AbsGroupUtil implements IUtil, Runnable {
|
|||||||
/**
|
/**
|
||||||
* 初始化组合任务状态
|
* 初始化组合任务状态
|
||||||
*/
|
*/
|
||||||
protected void initState() {
|
private void initState() {
|
||||||
mState = new GroupRunState(getWrapper().getKey(), mListener,
|
mState = new GroupRunState(getWrapper().getKey(), mListener, mSubQueue);
|
||||||
mGTWrapper.getSubTaskWrapper().size(), mSubQueue);
|
|
||||||
for (DTaskWrapper wrapper : mGTWrapper.getSubTaskWrapper()) {
|
for (DTaskWrapper wrapper : mGTWrapper.getSubTaskWrapper()) {
|
||||||
if (wrapper.getEntity().getState() == IEntity.STATE_COMPLETE) {
|
if (wrapper.getEntity().getState() == IEntity.STATE_COMPLETE) {
|
||||||
mState.updateCompleteNum();
|
mState.updateCompleteNum();
|
||||||
|
|||||||
@@ -112,30 +112,4 @@ public abstract class AbsSubDLoadUtil implements IUtil {
|
|||||||
mSchedulers.obtainMessage(ISchedulers.STOP, this).sendToTarget();
|
mSchedulers.obtainMessage(ISchedulers.STOP, this).sendToTarget();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//@Override public void start() {
|
|
||||||
// if (mWrapper.getRequestType() == ITaskWrapper.D_HTTP) {
|
|
||||||
// if (needGetInfo) {
|
|
||||||
// new Thread(new HttpFileInfoThread(mWrapper, new OnFileInfoCallback() {
|
|
||||||
//
|
|
||||||
// @Override public void onComplete(String url, CompleteInfo info) {
|
|
||||||
// mDLoader = new Downloader(mListener, mWrapper);
|
|
||||||
// mDLoader.start();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) {
|
|
||||||
// mSchedulers.obtainMessage(ISchedulers.FAIL, SubDLoadUtil.this).sendToTarget();
|
|
||||||
// }
|
|
||||||
// })).start();
|
|
||||||
// } else {
|
|
||||||
// mDLoader = new Downloader(mListener, mWrapper);
|
|
||||||
// mDLoader.start();
|
|
||||||
// }
|
|
||||||
// } else if (mWrapper.getRequestType() == ITaskWrapper.D_FTP) {
|
|
||||||
// mDLoader = new Downloader(mListener, mWrapper);
|
|
||||||
// mDLoader.start();
|
|
||||||
// } else {
|
|
||||||
// ALog.w(TAG, String.format("不识别的类型,requestType:%s", mWrapper.getRequestType()));
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,14 +72,16 @@ public class GroupRunState {
|
|||||||
|
|
||||||
private String mGroupHash;
|
private String mGroupHash;
|
||||||
|
|
||||||
GroupRunState(String groupHash, IDGroupListener listener, int subSize,
|
GroupRunState(String groupHash, IDGroupListener listener, SimpleSubQueue queue) {
|
||||||
SimpleSubQueue queue) {
|
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
this.queue = queue;
|
this.queue = queue;
|
||||||
mSubSize = subSize;
|
|
||||||
mGroupHash = groupHash;
|
mGroupHash = groupHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSubSize(int subSize){
|
||||||
|
mSubSize = subSize;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 组合任务是否正在自行
|
* 组合任务是否正在自行
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -142,7 +142,6 @@ public class NormalLoader extends AbsLoader {
|
|||||||
String.format(IRecordHandler.SUB_PATH, mTempFile.getPath(), record.threadId))
|
String.format(IRecordHandler.SUB_PATH, mTempFile.getPath(), record.threadId))
|
||||||
: mTempFile;
|
: mTempFile;
|
||||||
config.isBlock = mRecord.isBlock;
|
config.isBlock = mRecord.isBlock;
|
||||||
config.isOpenDynamicFile = mRecord.isOpenDynamicFile;
|
|
||||||
config.startThreadNum = startNum;
|
config.startThreadNum = startNum;
|
||||||
config.taskWrapper = mTaskWrapper;
|
config.taskWrapper = mTaskWrapper;
|
||||||
config.record = record;
|
config.record = record;
|
||||||
@@ -200,8 +199,7 @@ public class NormalLoader extends AbsLoader {
|
|||||||
ALog.d(TAG, String.format("进度修正,当前进度:%s", currentProgress));
|
ALog.d(TAG, String.format("进度修正,当前进度:%s", currentProgress));
|
||||||
getEntity().setCurrentProgress(currentProgress);
|
getEntity().setCurrentProgress(currentProgress);
|
||||||
}
|
}
|
||||||
mStateHandler.obtainMessage(IThreadState.STATE_UPDATE_PROGRESS, currentProgress)
|
mStateManager.updateProgress(currentProgress);
|
||||||
.sendToTarget();
|
|
||||||
startThreadTask();
|
startThreadTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ import android.os.Bundle;
|
|||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import com.arialyy.aria.core.TaskRecord;
|
import com.arialyy.aria.core.TaskRecord;
|
||||||
import com.arialyy.aria.core.listener.IEventListener;
|
|
||||||
import com.arialyy.aria.core.inf.IRecordHandler;
|
import com.arialyy.aria.core.inf.IRecordHandler;
|
||||||
import com.arialyy.aria.core.inf.IThreadState;
|
import com.arialyy.aria.core.inf.IThreadState;
|
||||||
|
import com.arialyy.aria.core.listener.IEventListener;
|
||||||
import com.arialyy.aria.exception.BaseException;
|
import com.arialyy.aria.exception.BaseException;
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
import com.arialyy.aria.util.FileUtil;
|
import com.arialyy.aria.util.FileUtil;
|
||||||
@@ -59,6 +59,13 @@ public class ThreadStateManager implements IThreadState {
|
|||||||
mListener = listener;
|
mListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 不要使用handle更新启动线程的进度,因为有延迟
|
||||||
|
*/
|
||||||
|
void updateProgress(long curProgress) {
|
||||||
|
mProgress = curProgress;
|
||||||
|
}
|
||||||
|
|
||||||
@Override public boolean handleMessage(Message msg) {
|
@Override public boolean handleMessage(Message msg) {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
case STATE_STOP:
|
case STATE_STOP:
|
||||||
@@ -77,7 +84,7 @@ public class ThreadStateManager implements IThreadState {
|
|||||||
mFailNum++;
|
mFailNum++;
|
||||||
if (isFail()) {
|
if (isFail()) {
|
||||||
Bundle b = msg.getData();
|
Bundle b = msg.getData();
|
||||||
mListener.onFail(b.getBoolean(KEY_RETRY, true),
|
mListener.onFail(b.getBoolean(KEY_RETRY, false),
|
||||||
(BaseException) b.getSerializable(KEY_ERROR_INFO));
|
(BaseException) b.getSerializable(KEY_ERROR_INFO));
|
||||||
quitLooper();
|
quitLooper();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* 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.processor;
|
||||||
|
|
||||||
|
import com.arialyy.aria.core.inf.IEventHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* M3U8 密钥下载地址处理器,可用于解密被加密的密钥的下载地址
|
||||||
|
*/
|
||||||
|
public interface IKeyUrlConverter extends IEventHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将被加密的密钥下载地址转换为可使用的http下载地址
|
||||||
|
*
|
||||||
|
* @param keyUrl 加密的url地址
|
||||||
|
* @return 可正常访问的http地址
|
||||||
|
*/
|
||||||
|
String convert(String keyUrl);
|
||||||
|
}
|
||||||
@@ -22,7 +22,7 @@ import com.arialyy.aria.util.CommonUtil;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 但文件任务适配器
|
* 单文件任务适配器
|
||||||
*
|
*
|
||||||
* @Author lyy
|
* @Author lyy
|
||||||
* @Date 2019-09-19
|
* @Date 2019-09-19
|
||||||
|
|||||||
@@ -34,10 +34,6 @@ public abstract class AbsThreadTaskAdapter implements IThreadTaskAdapter {
|
|||||||
* 速度限制工具
|
* 速度限制工具
|
||||||
*/
|
*/
|
||||||
protected BandwidthLimiter mSpeedBandUtil;
|
protected BandwidthLimiter mSpeedBandUtil;
|
||||||
/**
|
|
||||||
* 当前线程的下去区间的进度
|
|
||||||
*/
|
|
||||||
private long mRangeProgress;
|
|
||||||
private ThreadRecord mThreadRecord;
|
private ThreadRecord mThreadRecord;
|
||||||
private IThreadTaskObserver mObserver;
|
private IThreadTaskObserver mObserver;
|
||||||
private AbsTaskWrapper mWrapper;
|
private AbsTaskWrapper mWrapper;
|
||||||
@@ -48,7 +44,6 @@ public abstract class AbsThreadTaskAdapter implements IThreadTaskAdapter {
|
|||||||
mThreadRecord = config.record;
|
mThreadRecord = config.record;
|
||||||
mWrapper = config.taskWrapper;
|
mWrapper = config.taskWrapper;
|
||||||
mThreadConfig = config;
|
mThreadConfig = config;
|
||||||
mRangeProgress = mThreadRecord.startLocation;
|
|
||||||
if (getTaskConfig().getMaxSpeed() > 0) {
|
if (getTaskConfig().getMaxSpeed() > 0) {
|
||||||
mSpeedBandUtil = new BandwidthLimiter(getTaskConfig().getMaxSpeed(), config.startThreadNum);
|
mSpeedBandUtil = new BandwidthLimiter(getTaskConfig().getMaxSpeed(), config.startThreadNum);
|
||||||
}
|
}
|
||||||
@@ -68,7 +63,7 @@ public abstract class AbsThreadTaskAdapter implements IThreadTaskAdapter {
|
|||||||
* 当前线程的下去区间的进度
|
* 当前线程的下去区间的进度
|
||||||
*/
|
*/
|
||||||
protected long getRangeProgress() {
|
protected long getRangeProgress() {
|
||||||
return mRangeProgress;
|
return mObserver.getThreadProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ThreadRecord getThreadRecord() {
|
protected ThreadRecord getThreadRecord() {
|
||||||
@@ -97,7 +92,7 @@ public abstract class AbsThreadTaskAdapter implements IThreadTaskAdapter {
|
|||||||
return mThreadConfig;
|
return mThreadConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void setThreadStateObserver(IThreadTaskObserver observer) {
|
@Override public void attach(IThreadTaskObserver observer) {
|
||||||
mObserver = observer;
|
mObserver = observer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public interface IThreadTaskAdapter {
|
|||||||
void setMaxSpeed(int speed);
|
void setMaxSpeed(int speed);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置线程任务状态观察者
|
* 注册观察者
|
||||||
*/
|
*/
|
||||||
void setThreadStateObserver(IThreadTaskObserver observer);
|
void attach(IThreadTaskObserver observer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,4 +53,9 @@ public interface IThreadTaskObserver {
|
|||||||
* @param len 新增的长度
|
* @param len 新增的长度
|
||||||
*/
|
*/
|
||||||
void updateProgress(long len);
|
void updateProgress(long len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取线程当前进度
|
||||||
|
*/
|
||||||
|
long getThreadProgress();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
|||||||
import com.arialyy.aria.exception.BaseException;
|
import com.arialyy.aria.exception.BaseException;
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
||||||
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
import com.arialyy.aria.util.ErrorHelp;
|
import com.arialyy.aria.util.ErrorHelp;
|
||||||
import com.arialyy.aria.util.FileUtil;
|
import com.arialyy.aria.util.FileUtil;
|
||||||
import com.arialyy.aria.util.NetUtils;
|
import com.arialyy.aria.util.NetUtils;
|
||||||
@@ -49,7 +50,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
|
|||||||
* 线程重试次数
|
* 线程重试次数
|
||||||
*/
|
*/
|
||||||
private final int RETRY_NUM = 2;
|
private final int RETRY_NUM = 2;
|
||||||
private final String TAG = "AbsThreadTask";
|
private final String TAG = CommonUtil.getClassName(getClass());
|
||||||
private IEntity mEntity;
|
private IEntity mEntity;
|
||||||
protected AbsTaskWrapper mTaskWrapper;
|
protected AbsTaskWrapper mTaskWrapper;
|
||||||
private int mFailTimes = 0;
|
private int mFailTimes = 0;
|
||||||
@@ -94,7 +95,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
|
|||||||
*/
|
*/
|
||||||
public void setAdapter(IThreadTaskAdapter adapter) {
|
public void setAdapter(IThreadTaskAdapter adapter) {
|
||||||
mAdapter = adapter;
|
mAdapter = adapter;
|
||||||
mAdapter.setThreadStateObserver(this);
|
mAdapter.attach(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -317,6 +318,11 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getThreadProgress() {
|
||||||
|
return mRangeProgress;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 取消任务
|
* 取消任务
|
||||||
*/
|
*/
|
||||||
@@ -335,7 +341,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
|
|||||||
*/
|
*/
|
||||||
protected void fail(final long subCurrentLocation, BaseException ex, boolean needRetry) {
|
protected void fail(final long subCurrentLocation, BaseException ex, boolean needRetry) {
|
||||||
if (ex != null) {
|
if (ex != null) {
|
||||||
ALog.e(TAG, ALog.getExceptionString(ex));
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
if (mTaskWrapper.getRequestType() == ITaskWrapper.M3U8_VOD) {
|
if (mTaskWrapper.getRequestType() == ITaskWrapper.M3U8_VOD) {
|
||||||
writeConfig(false, 0);
|
writeConfig(false, 0);
|
||||||
@@ -347,7 +353,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
|
|||||||
} else {
|
} else {
|
||||||
ALog.e(TAG, String.format("任务【%s】执行失败", getFileName()));
|
ALog.e(TAG, String.format("任务【%s】执行失败", getFileName()));
|
||||||
ErrorHelp.saveError(TAG, "", ALog.getExceptionString(ex));
|
ErrorHelp.saveError(TAG, "", ALog.getExceptionString(ex));
|
||||||
sendFailMsg(null);
|
sendFailMsg(null, needRetry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -359,7 +365,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
|
|||||||
boolean isConnected = NetUtils.isConnected(AriaConfig.getInstance().getAPP());
|
boolean isConnected = NetUtils.isConnected(AriaConfig.getInstance().getAPP());
|
||||||
if (!isConnected && !isNotNetRetry) {
|
if (!isConnected && !isNotNetRetry) {
|
||||||
ALog.w(TAG, String.format("ts切片【%s】重试失败,网络未连接", getFileName()));
|
ALog.w(TAG, String.format("ts切片【%s】重试失败,网络未连接", getFileName()));
|
||||||
sendFailMsg(null);
|
sendFailMsg(null, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mFailTimes < RETRY_NUM && needRetry && (NetUtils.isConnected(
|
if (mFailTimes < RETRY_NUM && needRetry && (NetUtils.isConnected(
|
||||||
@@ -367,11 +373,11 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
|
|||||||
|| isNotNetRetry) && !isBreak()) {
|
|| isNotNetRetry) && !isBreak()) {
|
||||||
ALog.w(TAG, String.format("ts切片【%s】正在重试", getFileName()));
|
ALog.w(TAG, String.format("ts切片【%s】正在重试", getFileName()));
|
||||||
mFailTimes++;
|
mFailTimes++;
|
||||||
mConfig.tempFile.delete();
|
FileUtil.deleteFile(mConfig.tempFile);
|
||||||
FileUtil.createFile(mConfig.tempFile.getPath());
|
FileUtil.createFile(mConfig.tempFile);
|
||||||
ThreadTaskManager.getInstance().retryThread(this);
|
ThreadTaskManager.getInstance().retryThread(this);
|
||||||
} else {
|
} else {
|
||||||
sendFailMsg(null);
|
sendFailMsg(null, needRetry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,7 +389,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
|
|||||||
private void retryBlockTask(boolean needRetry) {
|
private void retryBlockTask(boolean needRetry) {
|
||||||
if (!NetUtils.isConnected(AriaConfig.getInstance().getAPP()) && !isNotNetRetry) {
|
if (!NetUtils.isConnected(AriaConfig.getInstance().getAPP()) && !isNotNetRetry) {
|
||||||
ALog.w(TAG, String.format("分块【%s】重试失败,网络未连接", getFileName()));
|
ALog.w(TAG, String.format("分块【%s】重试失败,网络未连接", getFileName()));
|
||||||
sendFailMsg(null);
|
sendFailMsg(null, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mFailTimes < RETRY_NUM && needRetry && (NetUtils.isConnected(
|
if (mFailTimes < RETRY_NUM && needRetry && (NetUtils.isConnected(
|
||||||
@@ -394,7 +400,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
|
|||||||
handleBlockRecord();
|
handleBlockRecord();
|
||||||
ThreadTaskManager.getInstance().retryThread(this);
|
ThreadTaskManager.getInstance().retryThread(this);
|
||||||
} else {
|
} else {
|
||||||
sendFailMsg(null);
|
sendFailMsg(null, needRetry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,13 +448,14 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
|
|||||||
/**
|
/**
|
||||||
* 发送失败信息
|
* 发送失败信息
|
||||||
*/
|
*/
|
||||||
private void sendFailMsg(@Nullable BaseException e) {
|
private void sendFailMsg(@Nullable BaseException e,boolean needRetry) {
|
||||||
|
Bundle b = new Bundle();
|
||||||
|
b.putBoolean(IThreadState.KEY_RETRY, needRetry);
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
Bundle b = new Bundle();
|
|
||||||
b.putSerializable(IThreadState.KEY_ERROR_INFO, e);
|
b.putSerializable(IThreadState.KEY_ERROR_INFO, e);
|
||||||
updateState(IThreadState.STATE_FAIL, b);
|
updateState(IThreadState.STATE_FAIL, b);
|
||||||
} else {
|
} else {
|
||||||
updateState(IThreadState.STATE_FAIL, null);
|
updateState(IThreadState.STATE_FAIL, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -462,8 +469,6 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
|
|||||||
if (mRecord != null) {
|
if (mRecord != null) {
|
||||||
mRecord.isComplete = isComplete;
|
mRecord.isComplete = isComplete;
|
||||||
if (mConfig.isBlock) {
|
if (mConfig.isBlock) {
|
||||||
mRecord.startLocation = record;
|
|
||||||
} else if (mConfig.isOpenDynamicFile) {
|
|
||||||
mRecord.startLocation = mConfig.tempFile.length();
|
mRecord.startLocation = mConfig.tempFile.length();
|
||||||
} else {
|
} else {
|
||||||
if (0 < record && record < mRecord.endLocation) {
|
if (0 < record && record < mRecord.endLocation) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package com.arialyy.aria.core.upload;
|
|||||||
|
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.text.TextUtils;
|
||||||
import com.arialyy.aria.core.common.AbsNormalEntity;
|
import com.arialyy.aria.core.common.AbsNormalEntity;
|
||||||
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
import com.arialyy.aria.core.wrapper.ITaskWrapper;
|
||||||
import com.arialyy.aria.orm.annotation.Primary;
|
import com.arialyy.aria.orm.annotation.Primary;
|
||||||
@@ -58,7 +59,10 @@ public class UploadEntity extends AbsNormalEntity implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public int getTaskType() {
|
@Override public int getTaskType() {
|
||||||
return getUrl().startsWith("ftp") ? ITaskWrapper.D_FTP : ITaskWrapper.D_HTTP;
|
if (TextUtils.isEmpty(getUrl())){
|
||||||
|
return ITaskWrapper.ERROR;
|
||||||
|
}
|
||||||
|
return getUrl().startsWith("ftp") ? ITaskWrapper.U_FTP : ITaskWrapper.U_HTTP;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UploadEntity() {
|
public UploadEntity() {
|
||||||
|
|||||||
@@ -84,6 +84,19 @@ public abstract class AbsTaskWrapper<ENTITY extends AbsEntity>
|
|||||||
*/
|
*/
|
||||||
private TaskOptionParams optionParams = new TaskOptionParams();
|
private TaskOptionParams optionParams = new TaskOptionParams();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code true}强制下载\上传,不考虑文件路径是否被占用
|
||||||
|
*/
|
||||||
|
private boolean ignoreFilePathOccupy = false;
|
||||||
|
|
||||||
|
public boolean isIgnoreFilePathOccupy() {
|
||||||
|
return ignoreFilePathOccupy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIgnoreFilePathOccupy(boolean ignoreFilePathOccupy) {
|
||||||
|
this.ignoreFilePathOccupy = ignoreFilePathOccupy;
|
||||||
|
}
|
||||||
|
|
||||||
public void setTaskOption(ITaskOption option) {
|
public void setTaskOption(ITaskOption option) {
|
||||||
this.taskOption = option;
|
this.taskOption = option;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,9 +32,9 @@ import java.util.Map;
|
|||||||
class DBConfig {
|
class DBConfig {
|
||||||
/*adb pull /mnt/sdcard/Android/data/com.arialyy.simple/files/DB/AriaLyyDb d:/db*/
|
/*adb pull /mnt/sdcard/Android/data/com.arialyy.simple/files/DB/AriaLyyDb d:/db*/
|
||||||
static boolean DEBUG = false;
|
static boolean DEBUG = false;
|
||||||
static Map<String, Class> mapping = new LinkedHashMap<>();
|
static Map<String, Class<? extends DbEntity>> mapping = new LinkedHashMap<>();
|
||||||
static String DB_NAME;
|
static String DB_NAME;
|
||||||
static int VERSION = 55;
|
static int VERSION = 56;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否将数据库保存在Sd卡,{@code true} 是
|
* 是否将数据库保存在Sd卡,{@code true} 是
|
||||||
@@ -51,8 +51,8 @@ class DBConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
mapping.put("DownloadGroupEntity", DownloadGroupEntity.class);
|
|
||||||
mapping.put("DownloadEntity", DownloadEntity.class);
|
mapping.put("DownloadEntity", DownloadEntity.class);
|
||||||
|
mapping.put("DownloadGroupEntity", DownloadGroupEntity.class);
|
||||||
mapping.put("UploadEntity", UploadEntity.class);
|
mapping.put("UploadEntity", UploadEntity.class);
|
||||||
mapping.put("ThreadRecord", ThreadRecord.class);
|
mapping.put("ThreadRecord", ThreadRecord.class);
|
||||||
mapping.put("TaskRecord", TaskRecord.class);
|
mapping.put("TaskRecord", TaskRecord.class);
|
||||||
|
|||||||
@@ -221,4 +221,22 @@ class DelegateCommon extends AbsDelegate {
|
|||||||
db.execSQL(str);
|
db.execSQL(str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过class 获取该class的表字段
|
||||||
|
*
|
||||||
|
* @return 表字段列表
|
||||||
|
*/
|
||||||
|
List<String> getColumns(Class<? extends DbEntity> clazz) {
|
||||||
|
List<String> columns = new ArrayList<>();
|
||||||
|
List<Field> fields = CommonUtil.getAllFields(clazz);
|
||||||
|
for (Field field : fields) {
|
||||||
|
field.setAccessible(true);
|
||||||
|
if (SqlUtil.isIgnore(field)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
columns.add(field.getName());
|
||||||
|
}
|
||||||
|
return columns;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,9 +76,6 @@ final class SqlHelper extends SQLiteOpenHelper {
|
|||||||
// 需要使用如下语句:
|
// 需要使用如下语句:
|
||||||
db.execSQL("PRAGMA foreign_keys=ON;");
|
db.execSQL("PRAGMA foreign_keys=ON;");
|
||||||
}
|
}
|
||||||
if (DBConfig.DEBUG) {
|
|
||||||
db.enableWriteAheadLogging();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onCreate(SQLiteDatabase db) {
|
@Override public void onCreate(SQLiteDatabase db) {
|
||||||
@@ -103,14 +100,14 @@ final class SqlHelper extends SQLiteOpenHelper {
|
|||||||
} else if (oldVersion < 53) {
|
} else if (oldVersion < 53) {
|
||||||
handle366Update(db);
|
handle366Update(db);
|
||||||
} else {
|
} else {
|
||||||
handleDbUpdate(db, null, null);
|
handleDbUpdate(db, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
@Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
if (oldVersion > newVersion) {
|
if (oldVersion > newVersion) {
|
||||||
handleDbUpdate(db, null, null);
|
handleDbUpdate(db, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,6 +136,7 @@ final class SqlHelper extends SQLiteOpenHelper {
|
|||||||
SQLiteDatabase.CREATE_IF_NECESSARY);
|
SQLiteDatabase.CREATE_IF_NECESSARY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
db.enableWriteAheadLogging();
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,10 +145,8 @@ final class SqlHelper extends SQLiteOpenHelper {
|
|||||||
*
|
*
|
||||||
* @param modifyColumns 需要修改的表字段的映射,key为表名,
|
* @param modifyColumns 需要修改的表字段的映射,key为表名,
|
||||||
* value{@code Map<String, String>}中的Map的key为老字段名称,value为该老字段对应的新字段名称
|
* value{@code Map<String, String>}中的Map的key为老字段名称,value为该老字段对应的新字段名称
|
||||||
* @param delColumns 需要删除的表字段,key为表名,value{@code List<String>}为需要删除的字段列表
|
|
||||||
*/
|
*/
|
||||||
private void handleDbUpdate(SQLiteDatabase db, Map<String, Map<String, String>> modifyColumns,
|
private void handleDbUpdate(SQLiteDatabase db, Map<String, Map<String, String>> modifyColumns) {
|
||||||
Map<String, List<String>> delColumns) {
|
|
||||||
if (db == null) {
|
if (db == null) {
|
||||||
ALog.e("SqlHelper", "db 为 null");
|
ALog.e("SqlHelper", "db 为 null");
|
||||||
return;
|
return;
|
||||||
@@ -163,7 +159,7 @@ final class SqlHelper extends SQLiteOpenHelper {
|
|||||||
db.beginTransaction();
|
db.beginTransaction();
|
||||||
Set<String> tables = DBConfig.mapping.keySet();
|
Set<String> tables = DBConfig.mapping.keySet();
|
||||||
for (String tableName : tables) {
|
for (String tableName : tables) {
|
||||||
Class clazz = DBConfig.mapping.get(tableName);
|
Class<? extends DbEntity> clazz = DBConfig.mapping.get(tableName);
|
||||||
if (mDelegate.tableExists(db, clazz)) {
|
if (mDelegate.tableExists(db, clazz)) {
|
||||||
//修改表名为中介表名
|
//修改表名为中介表名
|
||||||
String alertSql = String.format("ALTER TABLE %s RENAME TO %s_temp", tableName, tableName);
|
String alertSql = String.format("ALTER TABLE %s RENAME TO %s_temp", tableName, tableName);
|
||||||
@@ -180,46 +176,57 @@ final class SqlHelper extends SQLiteOpenHelper {
|
|||||||
|
|
||||||
// 复制数据
|
// 复制数据
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
// 获取旧表的所有字段名称
|
|
||||||
Cursor columnC =
|
Cursor columnC =
|
||||||
db.rawQuery(String.format("PRAGMA table_info(%s_temp)", tableName), null);
|
db.rawQuery(String.format("PRAGMA table_info(%s_temp)", tableName), null);
|
||||||
StringBuilder params = new StringBuilder();
|
|
||||||
|
// 获取新表的所有字段名称
|
||||||
|
List<String> newTabColumns = mDelegate.getColumns(clazz);
|
||||||
|
// 获取旧表的所有字段名称
|
||||||
|
List<String> oldTabColumns = new ArrayList<>();
|
||||||
|
|
||||||
while (columnC.moveToNext()) {
|
while (columnC.moveToNext()) {
|
||||||
String columnName = columnC.getString(columnC.getColumnIndex("name"));
|
String columnName = columnC.getString(columnC.getColumnIndex("name"));
|
||||||
if (delColumns != null && delColumns.get(tableName) != null) {
|
oldTabColumns.add(columnName);
|
||||||
List<String> delColumn = delColumns.get(tableName);
|
|
||||||
if (delColumn != null && !delColumn.isEmpty()) {
|
|
||||||
if (delColumn.contains(columnName)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
params.append(columnName).append(",");
|
|
||||||
}
|
}
|
||||||
columnC.close();
|
columnC.close();
|
||||||
|
|
||||||
|
// 旧表需要删除的字段,删除旧表有而新表没的字段
|
||||||
|
List<String> diffTab = getDiffColumn(newTabColumns, oldTabColumns);
|
||||||
|
StringBuilder params = new StringBuilder();
|
||||||
|
|
||||||
|
// 需要修改的列名映射表
|
||||||
|
Map<String, String> modifyMap = null;
|
||||||
|
if (modifyColumns != null) {
|
||||||
|
modifyMap = modifyColumns.get(tableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String column : oldTabColumns) {
|
||||||
|
if (!diffTab.isEmpty() && diffTab.contains(column)
|
||||||
|
&& (modifyMap != null && !modifyMap.containsKey(column))) { // 如果旧表字段有修改,忽略这个删除
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
params.append(column).append(",");
|
||||||
|
}
|
||||||
|
|
||||||
String oldParamStr = params.toString();
|
String oldParamStr = params.toString();
|
||||||
oldParamStr = oldParamStr.substring(0, oldParamStr.length() - 1);
|
oldParamStr = oldParamStr.substring(0, oldParamStr.length() - 1);
|
||||||
String newParamStr = oldParamStr;
|
String newParamStr = oldParamStr;
|
||||||
// 处理字段名称改变
|
// 处理字段名称改变
|
||||||
if (modifyColumns != null) {
|
if (modifyMap != null && !modifyMap.isEmpty()) {
|
||||||
Map<String, String> columnMap = modifyColumns.get(tableName);
|
Set<String> keys = modifyMap.keySet();
|
||||||
if (columnMap != null && !columnMap.isEmpty()) {
|
for (String key : keys) {
|
||||||
Set<String> keys = columnMap.keySet();
|
if (newParamStr.contains(key)) {
|
||||||
for (String key : keys) {
|
newParamStr = newParamStr.replace(key, modifyMap.get(key));
|
||||||
if (newParamStr.contains(key)) {
|
|
||||||
newParamStr = newParamStr.replace(key, columnMap.get(key));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//恢复数据
|
//恢复数据
|
||||||
String insertSql =
|
String insertSql =
|
||||||
String.format("INSERT INTO %s (%s) SELECT %s FROM %s_temp", tableName, newParamStr,
|
String.format("INSERT INTO %s (%s) SELECT %s FROM %s_temp", tableName, newParamStr,
|
||||||
oldParamStr, tableName);
|
oldParamStr, tableName);
|
||||||
ALog.d(TAG, "insertSql = " + insertSql);
|
ALog.d(TAG, "insertSql = " + insertSql);
|
||||||
|
|
||||||
db.execSQL(insertSql);
|
db.execSQL(insertSql);
|
||||||
}
|
}
|
||||||
//删除中介表
|
//删除中介表
|
||||||
@@ -236,6 +243,19 @@ final class SqlHelper extends SQLiteOpenHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取新表差值(需要删除的字段):旧表有而新表没的字段
|
||||||
|
*
|
||||||
|
* @param newTab 新表字段
|
||||||
|
* @param oldTab 旧表字段
|
||||||
|
* @return 旧表有而新表没的字段
|
||||||
|
*/
|
||||||
|
private List<String> getDiffColumn(List<String> newTab, List<String> oldTab) {
|
||||||
|
List<String> temp = new ArrayList<>(oldTab); // 拷贝旧表字段
|
||||||
|
temp.removeAll(newTab);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除重复的repeat数据
|
* 删除重复的repeat数据
|
||||||
*/
|
*/
|
||||||
@@ -258,7 +278,7 @@ final class SqlHelper extends SQLiteOpenHelper {
|
|||||||
modifyMap.put("ThreadRecord", threadRecordModify);
|
modifyMap.put("ThreadRecord", threadRecordModify);
|
||||||
|
|
||||||
// 执行升级操作
|
// 执行升级操作
|
||||||
handleDbUpdate(db, modifyMap, null);
|
handleDbUpdate(db, modifyMap);
|
||||||
delRepeatThreadRecord(db);
|
delRepeatThreadRecord(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,7 +295,7 @@ final class SqlHelper extends SQLiteOpenHelper {
|
|||||||
modifyMap.put("ThreadRecord", threadRecordModify);
|
modifyMap.put("ThreadRecord", threadRecordModify);
|
||||||
|
|
||||||
// 执行升级操作
|
// 执行升级操作
|
||||||
handleDbUpdate(db, modifyMap, null);
|
handleDbUpdate(db, modifyMap);
|
||||||
delRepeatThreadRecord(db);
|
delRepeatThreadRecord(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,7 +329,7 @@ final class SqlHelper extends SQLiteOpenHelper {
|
|||||||
modifyMap.put("ThreadRecord", threadRecordModify);
|
modifyMap.put("ThreadRecord", threadRecordModify);
|
||||||
|
|
||||||
// 执行升级操作
|
// 执行升级操作
|
||||||
handleDbUpdate(db, modifyMap, null);
|
handleDbUpdate(db, modifyMap);
|
||||||
delRepeatThreadRecord(db);
|
delRepeatThreadRecord(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,15 +382,6 @@ final class SqlHelper extends SQLiteOpenHelper {
|
|||||||
dGEntityModifyMap.put("groupName", "groupHash");
|
dGEntityModifyMap.put("groupName", "groupHash");
|
||||||
modifyMap.put("DownloadGroupEntity", dGEntityModifyMap);
|
modifyMap.put("DownloadGroupEntity", dGEntityModifyMap);
|
||||||
|
|
||||||
// 删除字段
|
handleDbUpdate(db, modifyMap);
|
||||||
Map<String, List<String>> delColumnMap = new HashMap<>();
|
|
||||||
List<String> dEntityDel = new ArrayList<>();
|
|
||||||
dEntityDel.add("taskKey");
|
|
||||||
delColumnMap.put("DownloadEntity", dEntityDel);
|
|
||||||
List<String> dgEntityDel = new ArrayList<>();
|
|
||||||
dgEntityDel.add("subtask");
|
|
||||||
delColumnMap.put("DownloadGroupEntity", dgEntityDel);
|
|
||||||
|
|
||||||
handleDbUpdate(db, modifyMap, delColumnMap);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,6 +17,11 @@
|
|||||||
package com.arialyy.aria.util;
|
package com.arialyy.aria.util;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import com.arialyy.aria.core.download.DownloadEntity;
|
||||||
|
import com.arialyy.aria.core.download.DownloadGroupEntity;
|
||||||
|
import com.arialyy.aria.core.inf.IRecordHandler;
|
||||||
|
import com.arialyy.aria.core.upload.UploadEntity;
|
||||||
|
import com.arialyy.aria.orm.DbEntity;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -27,6 +32,69 @@ import java.util.List;
|
|||||||
public class CheckUtil {
|
public class CheckUtil {
|
||||||
private static final String TAG = "CheckUtil";
|
private static final String TAG = "CheckUtil";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查和处理下载任务的路径冲突
|
||||||
|
*
|
||||||
|
* @param isForceDownload true,如果路径冲突,将删除其它任务的记录的
|
||||||
|
* @param filePath 文件保存路径
|
||||||
|
* @return false 任务不再执行,true 任务继续执行
|
||||||
|
*/
|
||||||
|
public static boolean checkDPathConflicts(boolean isForceDownload, String filePath) {
|
||||||
|
if (DbEntity.checkDataExist(DownloadEntity.class, "downloadPath=?", filePath)) {
|
||||||
|
if (!isForceDownload) {
|
||||||
|
ALog.e(TAG, String.format("下载失败,保存路径【%s】已经被其它任务占用,请设置其它保存路径", filePath));
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
ALog.w(TAG, String.format("保存路径【%s】已经被其它任务占用,当前任务将覆盖该路径的文件", filePath));
|
||||||
|
RecordUtil.delTaskRecord(filePath, IRecordHandler.TYPE_DOWNLOAD);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查和处理上传任务的路径冲突
|
||||||
|
*
|
||||||
|
* @param isForceUpload true,如果路径冲突,将删除其它任务的记录的
|
||||||
|
* @param filePath 文件保存路径
|
||||||
|
* @return false 任务不再执行,true 任务继续执行
|
||||||
|
*/
|
||||||
|
public static boolean checkUPathConflicts(boolean isForceUpload, String filePath) {
|
||||||
|
if (DbEntity.checkDataExist(UploadEntity.class, "filePath=?", filePath)) {
|
||||||
|
if (!isForceUpload) {
|
||||||
|
ALog.e(TAG, String.format("上传失败,文件路径【%s】已经被其它任务占用,请设置其它文件路径", filePath));
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
ALog.w(TAG, String.format("文件路径【%s】已经被其它任务占用,当前任务将覆盖该路径的文件", filePath));
|
||||||
|
RecordUtil.delTaskRecord(filePath, IRecordHandler.TYPE_UPLOAD);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查和处理组合任务的路径冲突
|
||||||
|
*
|
||||||
|
* @param isForceDownload true,如果路径冲突,将删除其它任务的记录的
|
||||||
|
* @param dirPath 文件保存路径
|
||||||
|
* @return false 任务不再执行,true 任务继续执行
|
||||||
|
*/
|
||||||
|
public static boolean checkDGPathConflicts(boolean isForceDownload, String dirPath) {
|
||||||
|
if (DbEntity.checkDataExist(DownloadGroupEntity.class, "dirPath=?", dirPath)) {
|
||||||
|
if (!isForceDownload) {
|
||||||
|
ALog.e(TAG, String.format("下载失败,文件夹路径【%s】已经被其它任务占用,请设置其它文件路径", dirPath));
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
ALog.w(TAG, String.format("文件夹路径【%s】已经被其它任务占用,当前任务将覆盖该路径", dirPath));
|
||||||
|
RecordUtil.delGroupTaskRecordByPath(dirPath, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查成员类是否是静态和public
|
* 检查成员类是否是静态和public
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -71,15 +71,15 @@ public class CommonUtil {
|
|||||||
ALog.e(TAG, "sql语句表达式不能为null");
|
ALog.e(TAG, "sql语句表达式不能为null");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (expression.length == 1) {
|
//if (expression.length == 1) {
|
||||||
ALog.e(TAG, String.format("表达式需要写入参数,参数信息:%s", Arrays.toString(expression)));
|
// ALog.e(TAG, String.format("表达式需要写入参数,参数信息:%s", Arrays.toString(expression)));
|
||||||
return false;
|
// return false;
|
||||||
}
|
//}
|
||||||
String where = expression[0];
|
String where = expression[0];
|
||||||
if (!where.contains("?")) {
|
//if (!where.contains("?")) {
|
||||||
ALog.e(TAG, String.format("请在where语句的'='后编写?,参数信息:%s", Arrays.toString(expression)));
|
// ALog.e(TAG, String.format("请在where语句的'='后编写?,参数信息:%s", Arrays.toString(expression)));
|
||||||
return false;
|
// return false;
|
||||||
}
|
//}
|
||||||
Pattern pattern = Pattern.compile("\\?");
|
Pattern pattern = Pattern.compile("\\?");
|
||||||
Matcher matcher = pattern.matcher(where);
|
Matcher matcher = pattern.matcher(where);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user