parent
3ac7b0f211
commit
5d0f59f7e9
@ -1,13 +0,0 @@ |
|||||||
package com.arialyy.aria.core.common |
|
||||||
|
|
||||||
import com.arialyy.aria.core.provider.IdbProvider |
|
||||||
|
|
||||||
/** |
|
||||||
* @Author laoyuyu |
|
||||||
* @Description |
|
||||||
* @Date 5:27 PM 2023/1/13 |
|
||||||
**/ |
|
||||||
class RoomProvider : IdbProvider { |
|
||||||
override fun initDb() { |
|
||||||
} |
|
||||||
} |
|
@ -1,79 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
package com.arialyy.aria.core.manager; |
|
||||||
|
|
||||||
import com.arialyy.aria.core.download.DGEntityWrapper; |
|
||||||
import com.arialyy.aria.core.download.DGTaskWrapper; |
|
||||||
import com.arialyy.aria.core.download.DownloadGroupEntity; |
|
||||||
import com.arialyy.aria.orm.DbEntity; |
|
||||||
import com.arialyy.aria.util.CommonUtil; |
|
||||||
import com.arialyy.aria.util.DbDataHelper; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by Aria.Lao on 2017/11/1. 组合任务wrapper |
|
||||||
*/ |
|
||||||
class DGTaskWrapperFactory implements IGroupWrapperFactory<DownloadGroupEntity, DGTaskWrapper> { |
|
||||||
private final String TAG = CommonUtil.getClassName(this); |
|
||||||
private static volatile DGTaskWrapperFactory INSTANCE = null; |
|
||||||
|
|
||||||
private DGTaskWrapperFactory() { |
|
||||||
} |
|
||||||
|
|
||||||
public static DGTaskWrapperFactory getInstance() { |
|
||||||
if (INSTANCE == null) { |
|
||||||
synchronized (DGTaskWrapperFactory.class) { |
|
||||||
INSTANCE = new DGTaskWrapperFactory(); |
|
||||||
} |
|
||||||
} |
|
||||||
return INSTANCE; |
|
||||||
} |
|
||||||
|
|
||||||
@Override public DGTaskWrapper getGroupWrapper(long taskId) { |
|
||||||
DGTaskWrapper wrapper; |
|
||||||
if (taskId == -1) { |
|
||||||
wrapper = new DGTaskWrapper(new DownloadGroupEntity()); |
|
||||||
} else { |
|
||||||
DownloadGroupEntity entity = getOrCreateHttpDGEntity(taskId); |
|
||||||
wrapper = new DGTaskWrapper(entity); |
|
||||||
if (entity.getSubEntities() != null && !entity.getSubEntities().isEmpty()) { |
|
||||||
wrapper.setSubTaskWrapper(DbDataHelper.createDGSubTaskWrapper(entity)); |
|
||||||
} |
|
||||||
} |
|
||||||
wrapper.setRequestType(wrapper.getEntity().getTaskType()); |
|
||||||
return wrapper; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 获取组合任务实体 如果数据库不存在该实体,则新创建一个新的任务组实体 |
|
||||||
*/ |
|
||||||
private DownloadGroupEntity getOrCreateHttpDGEntity(long taskId) { |
|
||||||
List<DGEntityWrapper> wrapper = |
|
||||||
DbEntity.findRelationData(DGEntityWrapper.class, "DownloadGroupEntity.rowid=?", |
|
||||||
String.valueOf(taskId)); |
|
||||||
|
|
||||||
DownloadGroupEntity groupEntity; |
|
||||||
if (wrapper != null && !wrapper.isEmpty()) { |
|
||||||
groupEntity = wrapper.get(0).groupEntity; |
|
||||||
if (groupEntity == null) { |
|
||||||
groupEntity = new DownloadGroupEntity(); |
|
||||||
} |
|
||||||
} else { |
|
||||||
groupEntity = new DownloadGroupEntity(); |
|
||||||
} |
|
||||||
return groupEntity; |
|
||||||
} |
|
||||||
} |
|
@ -1,109 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
package com.arialyy.aria.core.manager; |
|
||||||
|
|
||||||
import com.arialyy.aria.core.TaskRecord; |
|
||||||
import com.arialyy.aria.core.download.DTaskWrapper; |
|
||||||
import com.arialyy.aria.core.download.DownloadEntity; |
|
||||||
import com.arialyy.aria.core.inf.IEntity; |
|
||||||
import com.arialyy.aria.core.loader.IRecordHandler; |
|
||||||
import com.arialyy.aria.core.wrapper.ITaskWrapper; |
|
||||||
import java.io.File; |
|
||||||
|
|
||||||
/** |
|
||||||
* 创建下载任务wrapper Created by Aria.Lao on 2017/11/1. |
|
||||||
*/ |
|
||||||
class DTaskWrapperFactory implements INormalTEFactory<DownloadEntity, DTaskWrapper> { |
|
||||||
private final String TAG = "DTaskWrapperFactory"; |
|
||||||
private static volatile DTaskWrapperFactory INSTANCE = null; |
|
||||||
|
|
||||||
private DTaskWrapperFactory() { |
|
||||||
} |
|
||||||
|
|
||||||
public static DTaskWrapperFactory getInstance() { |
|
||||||
if (INSTANCE == null) { |
|
||||||
synchronized (DTaskWrapperFactory.class) { |
|
||||||
INSTANCE = new DTaskWrapperFactory(); |
|
||||||
} |
|
||||||
} |
|
||||||
return INSTANCE; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 通过下载地址创建任务实体 |
|
||||||
*/ |
|
||||||
@Override public DTaskWrapper create(long taskId) { |
|
||||||
DTaskWrapper wrapper; |
|
||||||
if (taskId == -1) { |
|
||||||
wrapper = new DTaskWrapper(new DownloadEntity()); |
|
||||||
} else { |
|
||||||
wrapper = new DTaskWrapper(getEntity(taskId)); |
|
||||||
} |
|
||||||
wrapper.setRequestType(wrapper.getEntity().getTaskType()); |
|
||||||
return wrapper; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 如果任务存在,但是下载实体不存在,则通过下载地址获取下载实体 |
|
||||||
*/ |
|
||||||
private DownloadEntity getEntity(long taskId) { |
|
||||||
DownloadEntity entity = |
|
||||||
DownloadEntity.findFirst(DownloadEntity.class, "rowid=? and isGroupChild='false'", |
|
||||||
String.valueOf(taskId)); |
|
||||||
|
|
||||||
if (entity == null) { |
|
||||||
entity = new DownloadEntity(); |
|
||||||
return entity; |
|
||||||
} |
|
||||||
File file = new File(entity.getFilePath()); |
|
||||||
|
|
||||||
if (!entity.isComplete()) { |
|
||||||
TaskRecord record = |
|
||||||
TaskRecord.findFirst(TaskRecord.class, "filePath=?", entity.getFilePath()); |
|
||||||
if (record == null) { |
|
||||||
resetEntity(entity); |
|
||||||
} else { |
|
||||||
if (record.isBlock) { |
|
||||||
int count = 0; |
|
||||||
for (int i = 0, len = record.threadNum; i < len; i++) { |
|
||||||
File temp = new File(String.format(IRecordHandler.SUB_PATH, record.filePath, i)); |
|
||||||
if (!temp.exists()) { |
|
||||||
count++; |
|
||||||
} |
|
||||||
} |
|
||||||
if (count == record.threadNum) { |
|
||||||
resetEntity(entity); |
|
||||||
} |
|
||||||
} else if (!file.exists() |
|
||||||
&& record.taskType != ITaskWrapper.M3U8_VOD) { // 非分块文件需要判断文件是否存在
|
|
||||||
resetEntity(entity); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return entity; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 初始化下载实体 |
|
||||||
*/ |
|
||||||
private void resetEntity(DownloadEntity entity) { |
|
||||||
entity.setPercent(0); |
|
||||||
entity.setCompleteTime(0); |
|
||||||
entity.setComplete(false); |
|
||||||
entity.setCurrentProgress(0); |
|
||||||
entity.setState(IEntity.STATE_WAIT); |
|
||||||
} |
|
||||||
} |
|
@ -1,84 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
package com.arialyy.aria.core.manager; |
|
||||||
|
|
||||||
import android.text.TextUtils; |
|
||||||
import com.arialyy.aria.core.command.GroupCmdFactory; |
|
||||||
import com.arialyy.aria.core.download.DGTaskWrapper; |
|
||||||
import com.arialyy.aria.core.event.EventMsgUtil; |
|
||||||
import com.arialyy.aria.util.ALog; |
|
||||||
import com.arialyy.aria.core.command.CmdHelper; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by lyy on 2017/9/4. |
|
||||||
* 子任务管理器 |
|
||||||
*/ |
|
||||||
public class SubTaskManager { |
|
||||||
private final String TAG = getClass().getSimpleName(); |
|
||||||
private DGTaskWrapper mEntity; |
|
||||||
|
|
||||||
public SubTaskManager(DGTaskWrapper entity) { |
|
||||||
mEntity = entity; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 启动任务组中的子任务 |
|
||||||
* |
|
||||||
* @param url 子任务下载地址 |
|
||||||
*/ |
|
||||||
public void startSubTask(String url) { |
|
||||||
if (checkUrl(url)) { |
|
||||||
EventMsgUtil.getDefault().post( |
|
||||||
CmdHelper.createGroupCmd(mEntity, GroupCmdFactory.SUB_TASK_START, url)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 停止任务组中的子任务 |
|
||||||
* |
|
||||||
* @param url 子任务下载地址 |
|
||||||
*/ |
|
||||||
public void stopSubTask(String url) { |
|
||||||
if (checkUrl(url)) { |
|
||||||
EventMsgUtil.getDefault().post( |
|
||||||
CmdHelper.createGroupCmd(mEntity, GroupCmdFactory.SUB_TASK_STOP, url)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 检查任务地址 |
|
||||||
* |
|
||||||
* @param url 子任务地址 |
|
||||||
* @return {@code false} 任务地址不合法 |
|
||||||
*/ |
|
||||||
private boolean checkUrl(String url) { |
|
||||||
if (TextUtils.isEmpty(url)) { |
|
||||||
ALog.e(TAG, "子任务地址不能为null"); |
|
||||||
return false; |
|
||||||
} |
|
||||||
List<String> urls = mEntity.getEntity().getUrls(); |
|
||||||
if (urls == null || urls.isEmpty()) { |
|
||||||
ALog.e(TAG, "任务组任务链接为null"); |
|
||||||
return false; |
|
||||||
} |
|
||||||
if (!urls.contains(url)) { |
|
||||||
ALog.e(TAG, "任务组中没有改Url【+ " + url + "】"); |
|
||||||
return false; |
|
||||||
} |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
@ -1,156 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
package com.arialyy.aria.core.manager; |
|
||||||
|
|
||||||
import android.util.LruCache; |
|
||||||
import com.arialyy.aria.core.download.DGTaskWrapper; |
|
||||||
import com.arialyy.aria.core.download.DTaskWrapper; |
|
||||||
import com.arialyy.aria.core.upload.UTaskWrapper; |
|
||||||
import com.arialyy.aria.core.wrapper.AbsTaskWrapper; |
|
||||||
import com.arialyy.aria.util.ALog; |
|
||||||
import com.arialyy.aria.util.CommonUtil; |
|
||||||
import java.util.concurrent.locks.Lock; |
|
||||||
import java.util.concurrent.locks.ReentrantLock; |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by Aria.Lao on 2017/11/1. 任务实体管理器 |
|
||||||
*/ |
|
||||||
public class TaskWrapperManager { |
|
||||||
private static final String TAG = "TaskWrapperManager"; |
|
||||||
private static volatile TaskWrapperManager INSTANCE = null; |
|
||||||
private LruCache<String, AbsTaskWrapper> cache = new LruCache<>(1024); |
|
||||||
private Lock lock; |
|
||||||
|
|
||||||
public static TaskWrapperManager getInstance() { |
|
||||||
if (INSTANCE == null) { |
|
||||||
synchronized (TaskWrapperManager.class) { |
|
||||||
if (INSTANCE == null) { |
|
||||||
INSTANCE = new TaskWrapperManager(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return INSTANCE; |
|
||||||
} |
|
||||||
|
|
||||||
private TaskWrapperManager() { |
|
||||||
lock = new ReentrantLock(); |
|
||||||
} |
|
||||||
|
|
||||||
private IGroupWrapperFactory chooseGroupFactory(Class clazz) { |
|
||||||
if (clazz == DGTaskWrapper.class) { |
|
||||||
return DGTaskWrapperFactory.getInstance(); |
|
||||||
} |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
private INormalTEFactory chooseNormalFactory(Class clazz) { |
|
||||||
if (clazz == DTaskWrapper.class) { |
|
||||||
return DTaskWrapperFactory.getInstance(); |
|
||||||
} else if (clazz == UTaskWrapper.class) { |
|
||||||
return UTaskWrapperFactory.getInstance(); |
|
||||||
} |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 获取普通任务的Wrapper |
|
||||||
* |
|
||||||
* @return 创建失败,返回null;成功返回{@link DTaskWrapper}或者{@link UTaskWrapper} |
|
||||||
*/ |
|
||||||
public <TW extends AbsTaskWrapper> TW getNormalTaskWrapper(Class<TW> clazz, long taskId) { |
|
||||||
final Lock lock = this.lock; |
|
||||||
lock.lock(); |
|
||||||
try { |
|
||||||
|
|
||||||
AbsTaskWrapper wrapper = cache.get(convertKey(clazz, taskId)); |
|
||||||
if (wrapper == null || wrapper.getClass() != clazz) { |
|
||||||
INormalTEFactory factory = chooseNormalFactory(clazz); |
|
||||||
if (factory == null) { |
|
||||||
ALog.e(TAG, "任务实体创建失败"); |
|
||||||
return null; |
|
||||||
} |
|
||||||
wrapper = factory.create(taskId); |
|
||||||
putTaskWrapper(wrapper); |
|
||||||
} |
|
||||||
return (TW) wrapper; |
|
||||||
} finally { |
|
||||||
lock.unlock(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 从缓存中获取HTTP任务组的任务实体,如果任务实体不存在,则创建任务实体 获取{} |
|
||||||
* |
|
||||||
* @param taskId 任务ID |
|
||||||
* @return 地址列表为null或创建实体失败,返回null;成功返回{@link DGTaskWrapper} |
|
||||||
*/ |
|
||||||
public <TW extends AbsTaskWrapper> TW getGroupWrapper(Class<TW> clazz, long taskId) { |
|
||||||
final Lock lock = this.lock; |
|
||||||
lock.lock(); |
|
||||||
try { |
|
||||||
AbsTaskWrapper tWrapper = cache.get(convertKey(clazz, taskId)); |
|
||||||
if (tWrapper == null || tWrapper.getClass() != clazz) { |
|
||||||
IGroupWrapperFactory factory = chooseGroupFactory(clazz); |
|
||||||
if (factory == null) { |
|
||||||
ALog.e(TAG, "任务实体创建失败"); |
|
||||||
return null; |
|
||||||
} |
|
||||||
tWrapper = factory.getGroupWrapper(taskId); |
|
||||||
putTaskWrapper(tWrapper); |
|
||||||
} |
|
||||||
return (TW) tWrapper; |
|
||||||
} finally { |
|
||||||
lock.unlock(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 更新任务Wrapper |
|
||||||
*/ |
|
||||||
public void putTaskWrapper(AbsTaskWrapper wrapper) { |
|
||||||
if (wrapper == null) { |
|
||||||
ALog.e(TAG, "任务实体添加失败"); |
|
||||||
return; |
|
||||||
} |
|
||||||
if (wrapper.getEntity() == null || wrapper.getEntity().getId() == -1) { |
|
||||||
return; |
|
||||||
} |
|
||||||
final Lock lock = this.lock; |
|
||||||
lock.lock(); |
|
||||||
try { |
|
||||||
cache.put(convertKey(wrapper.getClass(), wrapper.getEntity().getId()), wrapper); |
|
||||||
} finally { |
|
||||||
lock.unlock(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 通过key删除任务实体 当任务complete或删除记录时将删除缓存 |
|
||||||
*/ |
|
||||||
public void removeTaskWrapper(AbsTaskWrapper wrapper) { |
|
||||||
final Lock lock = this.lock; |
|
||||||
lock.lock(); |
|
||||||
try { |
|
||||||
cache.remove(convertKey(wrapper.getClass(), wrapper.getEntity().getId())); |
|
||||||
} finally { |
|
||||||
lock.unlock(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private String convertKey(Class clazz, long taskId) { |
|
||||||
return CommonUtil.keyToHashKey(clazz.getName() + taskId); |
|
||||||
} |
|
||||||
} |
|
@ -1,64 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
package com.arialyy.aria.core.manager; |
|
||||||
|
|
||||||
import com.arialyy.aria.core.upload.UTaskWrapper; |
|
||||||
import com.arialyy.aria.core.upload.UploadEntity; |
|
||||||
import com.arialyy.aria.util.ALog; |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by Aria.Lao on 2017/11/1. 任务实体工厂 |
|
||||||
*/ |
|
||||||
class UTaskWrapperFactory implements INormalTEFactory<UploadEntity, UTaskWrapper> { |
|
||||||
private static final String TAG = "UTaskWrapperFactory"; |
|
||||||
private static volatile UTaskWrapperFactory INSTANCE = null; |
|
||||||
|
|
||||||
private UTaskWrapperFactory() { |
|
||||||
} |
|
||||||
|
|
||||||
public static UTaskWrapperFactory getInstance() { |
|
||||||
if (INSTANCE == null) { |
|
||||||
synchronized (UTaskWrapperFactory.class) { |
|
||||||
INSTANCE = new UTaskWrapperFactory(); |
|
||||||
} |
|
||||||
} |
|
||||||
return INSTANCE; |
|
||||||
} |
|
||||||
|
|
||||||
@Override public UTaskWrapper create(long taskId) { |
|
||||||
UTaskWrapper wrapper; |
|
||||||
if (taskId == -1) { |
|
||||||
wrapper = new UTaskWrapper(new UploadEntity()); |
|
||||||
} else { |
|
||||||
wrapper = new UTaskWrapper(getUploadEntity(taskId)); |
|
||||||
} |
|
||||||
|
|
||||||
wrapper.setRequestType(wrapper.getEntity().getTaskType()); |
|
||||||
return wrapper; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 从数据中读取上传实体,如果数据库查不到,则新创建一个上传实体 |
|
||||||
*/ |
|
||||||
private UploadEntity getUploadEntity(long taskId) { |
|
||||||
UploadEntity entity = |
|
||||||
UploadEntity.findFirst(UploadEntity.class, "rowid=?", String.valueOf(taskId)); |
|
||||||
if (entity == null) { |
|
||||||
entity = new UploadEntity(); |
|
||||||
} |
|
||||||
return entity; |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,62 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
package com.arialyy.aria.http.download |
||||||
|
|
||||||
|
import com.arialyy.aria.core.DuaContext |
||||||
|
import com.arialyy.aria.core.task.ITaskInterceptor |
||||||
|
import com.arialyy.aria.core.task.TaskCachePool |
||||||
|
import com.arialyy.aria.core.task.TaskChain |
||||||
|
import com.arialyy.aria.core.task.TaskResp |
||||||
|
import com.arialyy.aria.http.HttpTaskOption |
||||||
|
import com.arialyy.aria.orm.entity.DEntity |
||||||
|
import timber.log.Timber |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author laoyuyu |
||||||
|
* @Description |
||||||
|
* @Date 8:31 PM 2023/3/6 |
||||||
|
**/ |
||||||
|
class HttpDCheckInterceptor : ITaskInterceptor { |
||||||
|
|
||||||
|
/** |
||||||
|
* find DEntity, if that not exist, create and save it |
||||||
|
*/ |
||||||
|
private suspend fun findDEntityBySavePath(option: HttpTaskOption): DEntity? { |
||||||
|
val savePath = option.savePathUri |
||||||
|
val dao = DuaContext.getServiceManager().getDbService().getDuaDb().getDEntityDao() |
||||||
|
val de = dao.getDEntityBySavePath(savePath.toString()) |
||||||
|
if (de != null) { |
||||||
|
return null |
||||||
|
} |
||||||
|
val newDe = DEntity( |
||||||
|
sourceUrl = option.sourUrl!!, |
||||||
|
savePath = savePath!!, |
||||||
|
) |
||||||
|
dao.insert(newDe) |
||||||
|
return newDe |
||||||
|
} |
||||||
|
|
||||||
|
override suspend fun interceptor(chain: TaskChain): TaskResp { |
||||||
|
val option = chain.getTask().getTaskOption(HttpTaskOption::class.java) |
||||||
|
val dEntity = findDEntityBySavePath(option) |
||||||
|
if (dEntity == null) { |
||||||
|
Timber.e("file already exists, ${option.savePathUri}") |
||||||
|
return TaskResp(TaskResp.CODE_INTERRUPT) |
||||||
|
} |
||||||
|
TaskCachePool.putEntity(chain.getTask().taskId, dEntity) |
||||||
|
return TaskResp(TaskResp.CODE_SUCCESS) |
||||||
|
} |
||||||
|
} |
@ -1,88 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
package com.arialyy.aria.http.download; |
|
||||||
|
|
||||||
import android.os.Looper; |
|
||||||
import com.arialyy.aria.core.common.AbsEntity; |
|
||||||
import com.arialyy.aria.core.common.CompleteInfo; |
|
||||||
import com.arialyy.aria.core.download.DTaskWrapper; |
|
||||||
import com.arialyy.aria.core.download.DownloadEntity; |
|
||||||
import com.arialyy.aria.core.group.AbsGroupLoader; |
|
||||||
import com.arialyy.aria.core.group.AbsSubDLoadAdapter; |
|
||||||
import com.arialyy.aria.core.listener.DownloadGroupListener; |
|
||||||
import com.arialyy.aria.core.loader.IInfoTask; |
|
||||||
import com.arialyy.aria.core.wrapper.AbsTaskWrapper; |
|
||||||
import com.arialyy.aria.exception.AriaException; |
|
||||||
import com.arialyy.aria.exception.AriaHTTPException; |
|
||||||
|
|
||||||
/** |
|
||||||
* http 组合任务加载器 |
|
||||||
*/ |
|
||||||
final class HttpDGLoader extends AbsGroupLoader { |
|
||||||
HttpDGLoader(AbsTaskWrapper groupWrapper, DownloadGroupListener listener) { |
|
||||||
super(groupWrapper, listener); |
|
||||||
} |
|
||||||
|
|
||||||
@Override protected void handlerTask(Looper looper) { |
|
||||||
if (isBreak()) { |
|
||||||
return; |
|
||||||
} |
|
||||||
mInfoTask.run(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected AbsSubDLoadAdapter createSubLoader(DTaskWrapper wrapper, boolean needGetFileInfo) { |
|
||||||
HttpSubDLoaderAdapter |
|
||||||
subUtil = new HttpSubDLoaderAdapter(getScheduler(), needGetFileInfo, getKey()); |
|
||||||
subUtil.setParams(wrapper, null); |
|
||||||
return subUtil; |
|
||||||
} |
|
||||||
|
|
||||||
private void startSub() { |
|
||||||
if (isBreak()) { |
|
||||||
return; |
|
||||||
} |
|
||||||
onPostStart(); |
|
||||||
for (DTaskWrapper wrapper : getWrapper().getSubTaskWrapper()) { |
|
||||||
DownloadEntity dEntity = wrapper.getEntity(); |
|
||||||
|
|
||||||
startSubLoader(createSubLoader(wrapper, dEntity.getFileSize() < 0)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override public void addComponent(IInfoTask infoTask) { |
|
||||||
mInfoTask = infoTask; |
|
||||||
mInfoTask.setCallback(new HttpDGInfoTask.DGInfoCallback() { |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onSubFail(DownloadEntity subEntity, AriaHTTPException e, boolean needRetry) { |
|
||||||
getState().countFailNum(subEntity.getKey()); |
|
||||||
} |
|
||||||
|
|
||||||
@Override public void onStop(long len) { |
|
||||||
getListener().onStop(len); |
|
||||||
} |
|
||||||
|
|
||||||
@Override public void onSucceed(String key, CompleteInfo info) { |
|
||||||
startSub(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override public void onFail(AbsEntity entity, AriaException e, boolean needRetry) { |
|
||||||
fail(e, needRetry); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,42 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
package com.arialyy.aria.http.download |
||||||
|
|
||||||
|
import com.arialyy.aria.core.processor.IHttpFileLenAdapter |
||||||
|
import com.arialyy.aria.http.IHttpTaskOptionAdapter |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author laoyuyu |
||||||
|
* @Description |
||||||
|
* @Date 2:03 PM 2023/3/6 |
||||||
|
**/ |
||||||
|
class HttpDOptionAdapter : IHttpTaskOptionAdapter { |
||||||
|
var fileSizeAdapter: IHttpFileLenAdapter? = null |
||||||
|
var isChunkTask = false |
||||||
|
|
||||||
|
/** |
||||||
|
* whether block is supported, true: supported |
||||||
|
*/ |
||||||
|
var isSupportResume = true |
||||||
|
|
||||||
|
/** |
||||||
|
* whether resume task is supported |
||||||
|
* 1. in download task, if file length not obtained, isSupportResume = false |
||||||
|
* 2. in upload task, if service not supported resume, isSupportResume = false |
||||||
|
*/ |
||||||
|
var isSupportBlock = true |
||||||
|
|
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
/* |
||||||
|
* 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.dua.group |
||||||
|
|
||||||
|
import com.arialyy.aria.core.task.ITaskInterceptor |
||||||
|
import com.arialyy.aria.core.task.TaskChain |
||||||
|
import com.arialyy.aria.core.task.TaskResp |
||||||
|
import com.arialyy.aria.util.CheckUtil |
||||||
|
import timber.log.Timber |
||||||
|
|
||||||
|
/** |
||||||
|
* 1. Check if the save path is valid |
||||||
|
* 2. Check all sub-task download addresses |
||||||
|
* @Author laoyuyu |
||||||
|
* @Description |
||||||
|
* @Date 8:56 PM 2023/3/6 |
||||||
|
**/ |
||||||
|
internal class HttpDGCheckInterceptor : ITaskInterceptor { |
||||||
|
|
||||||
|
override suspend fun interceptor(chain: TaskChain): TaskResp { |
||||||
|
// if (optionAdapter.subUrl.isEmpty()){ |
||||||
|
// Timber.e("sub-task list is empty") |
||||||
|
// return -1 |
||||||
|
// } |
||||||
|
// |
||||||
|
// optionAdapter.subUrl.forEach { |
||||||
|
// if (!CheckUtil.checkUrl(it)){ |
||||||
|
// Timber.e("invalid url: $it") |
||||||
|
// return -1 |
||||||
|
// } |
||||||
|
// } |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,40 @@ |
|||||||
|
/* |
||||||
|
* 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.dua.group |
||||||
|
|
||||||
|
import com.arialyy.annotations.TaskEnum |
||||||
|
import com.arialyy.aria.core.DuaContext |
||||||
|
import com.arialyy.aria.core.inf.IComponentLoader |
||||||
|
import com.arialyy.aria.core.inf.IDownloader |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author laoyuyu |
||||||
|
* @Description |
||||||
|
* @Date 7:51 AM 2023/3/6 |
||||||
|
**/ |
||||||
|
class HttpDGComponentLoader : IComponentLoader { |
||||||
|
private val downloader by lazy { |
||||||
|
HttpDGLoader(DuaContext.getLifeManager().getTargetByLoader(this)!!) |
||||||
|
} |
||||||
|
|
||||||
|
override fun <T : IDownloader> download(): T { |
||||||
|
return downloader as T |
||||||
|
} |
||||||
|
|
||||||
|
override fun getTaskEnum(): TaskEnum { |
||||||
|
return TaskEnum.DOWNLOAD_GROUP |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,83 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
package com.arialyy.dua.group |
||||||
|
|
||||||
|
import android.net.Uri |
||||||
|
import com.arialyy.aria.core.task.DownloadGroupTask |
||||||
|
import com.arialyy.aria.core.task.ITaskInterceptor |
||||||
|
import com.arialyy.aria.core.task.TaskCachePool |
||||||
|
import com.arialyy.aria.http.HttpBaseStartController |
||||||
|
import com.arialyy.aria.http.HttpOption |
||||||
|
import com.arialyy.aria.http.HttpUtil |
||||||
|
import com.arialyy.aria.util.FileUtils |
||||||
|
import timber.log.Timber |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author laoyuyu |
||||||
|
* @Description |
||||||
|
* @Date 7:47 PM 2023/3/6 |
||||||
|
**/ |
||||||
|
class HttpDGStartController(target: Any, val savePath: Uri) : HttpBaseStartController(target) { |
||||||
|
|
||||||
|
private val optionAdapter = HttpDGOptionAdapter() |
||||||
|
|
||||||
|
init { |
||||||
|
httpTaskOption.taskOptionAdapter = optionAdapter |
||||||
|
httpTaskOption.savePathUri = savePath |
||||||
|
} |
||||||
|
|
||||||
|
override fun setTaskInterceptor(taskInterceptor: ITaskInterceptor): HttpDGStartController { |
||||||
|
return super.setTaskInterceptor(taskInterceptor) as HttpDGStartController |
||||||
|
} |
||||||
|
|
||||||
|
override fun setThreadNum(threadNum: Int): HttpDGStartController { |
||||||
|
return super.setThreadNum(threadNum) as HttpDGStartController |
||||||
|
} |
||||||
|
|
||||||
|
override fun setHttpOption(httpOption: HttpOption): HttpDGStartController { |
||||||
|
return super.setHttpOption(httpOption) as HttpDGStartController |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* add sub task download uri |
||||||
|
*/ |
||||||
|
fun addSubUriResource(subUrlList: List<String>): HttpDGStartController { |
||||||
|
optionAdapter.subUrl.addAll(subUrlList) |
||||||
|
return this |
||||||
|
} |
||||||
|
|
||||||
|
private fun createTask(): DownloadGroupTask { |
||||||
|
if (HttpUtil.checkHttpDParams(httpTaskOption)) { |
||||||
|
throw IllegalArgumentException("invalid params") |
||||||
|
} |
||||||
|
val task = DownloadGroupTask(httpTaskOption) |
||||||
|
task.adapter = HttpDGroupAdapter() |
||||||
|
TaskCachePool.putTask(task) |
||||||
|
return task |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Start task |
||||||
|
* @return taskId |
||||||
|
*/ |
||||||
|
fun start(): Int { |
||||||
|
if (!FileUtils.uriEffective(savePath)) { |
||||||
|
Timber.e("invalid savePath: $savePath") |
||||||
|
return -1 |
||||||
|
} |
||||||
|
return createTask().taskId |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,84 @@ |
|||||||
|
/* |
||||||
|
* 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.dua.group |
||||||
|
|
||||||
|
import android.os.Looper |
||||||
|
import com.arialyy.aria.core.DuaContext |
||||||
|
import com.arialyy.aria.core.inf.ITaskManager |
||||||
|
import com.arialyy.aria.core.task.AbsTaskAdapter |
||||||
|
import com.arialyy.aria.core.task.DownloadGroupTask |
||||||
|
import com.arialyy.aria.core.task.TaskResp |
||||||
|
import com.arialyy.aria.exception.AriaException |
||||||
|
import com.arialyy.aria.http.HttpTaskOption |
||||||
|
import com.arialyy.aria.http.download.HttpBlockThreadInterceptor |
||||||
|
import com.arialyy.aria.http.download.HttpDCheckInterceptor |
||||||
|
import com.arialyy.aria.http.download.TimerInterceptor |
||||||
|
import kotlinx.coroutines.Dispatchers |
||||||
|
import kotlinx.coroutines.launch |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author laoyuyu |
||||||
|
* @Description |
||||||
|
* @Date 21:58 2023/2/20 |
||||||
|
**/ |
||||||
|
internal class HttpDGroupAdapter : AbsTaskAdapter() { |
||||||
|
|
||||||
|
init { |
||||||
|
getTask().getTaskOption(HttpTaskOption::class.java).eventListener = |
||||||
|
HttpDGEventListener(getTask() as DownloadGroupTask) |
||||||
|
} |
||||||
|
|
||||||
|
override fun getTaskManager(): ITaskManager { |
||||||
|
TODO("Not yet implemented") |
||||||
|
} |
||||||
|
|
||||||
|
override fun isRunning(): Boolean { |
||||||
|
TODO("Not yet implemented") |
||||||
|
} |
||||||
|
|
||||||
|
override fun cancel() { |
||||||
|
TODO("Not yet implemented") |
||||||
|
} |
||||||
|
|
||||||
|
override fun stop() { |
||||||
|
TODO("Not yet implemented") |
||||||
|
} |
||||||
|
|
||||||
|
override fun start() { |
||||||
|
getTask().getTaskOption(HttpTaskOption::class.java).taskInterceptor.let { |
||||||
|
if (it.isNotEmpty()) { |
||||||
|
addInterceptors(it) |
||||||
|
} |
||||||
|
} |
||||||
|
DuaContext.duaScope.launch(Dispatchers.IO) { |
||||||
|
Looper.prepare() |
||||||
|
blockManager?.setLooper() |
||||||
|
addCoreInterceptor(HttpDCheckInterceptor()) |
||||||
|
addCoreInterceptor(TimerInterceptor()) |
||||||
|
addCoreInterceptor(HttpBlockThreadInterceptor()) |
||||||
|
val resp = interceptor() |
||||||
|
if (resp == null || resp.code != TaskResp.CODE_SUCCESS) { |
||||||
|
getTask().getTaskOption(HttpTaskOption::class.java).eventListener.onFail( |
||||||
|
false, |
||||||
|
AriaException("start task fail, task interrupt, code: ${resp?.code ?: TaskResp.CODE_INTERRUPT}") |
||||||
|
) |
||||||
|
blockManager?.stop() |
||||||
|
return@launch |
||||||
|
} |
||||||
|
Looper.loop() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,78 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.arialyy.aria.core.inf |
||||||
|
|
||||||
|
import android.os.Handler |
||||||
|
|
||||||
|
/** |
||||||
|
* @Author laoyuyu |
||||||
|
* @Description |
||||||
|
* @Date 9:36 PM 2023/3/6 |
||||||
|
**/ |
||||||
|
interface ITaskManager { |
||||||
|
companion object { |
||||||
|
const val STATE_STOP = 0x01 |
||||||
|
const val STATE_FAIL = 0x02 |
||||||
|
const val STATE_CANCEL = 0x03 |
||||||
|
const val STATE_COMPLETE = 0x04 |
||||||
|
const val STATE_RUNNING = 0x05 |
||||||
|
const val STATE_UPDATE_PROGRESS = 0x06 |
||||||
|
const val STATE_PRE = 0x07 |
||||||
|
const val STATE_START = 0x08 |
||||||
|
const val DATA_RETRY = "DATA_RETRY" |
||||||
|
const val DATA_ERROR_INFO = "DATA_ERROR_INFO" |
||||||
|
const val DATA_THREAD_NAME = "DATA_THREAD_NAME" |
||||||
|
const val DATA_THREAD_LOCATION = "DATA_THREAD_LOCATION" |
||||||
|
const val DATA_ADD_LEN = "DATA_ADD_LEN" // 增加的长度 |
||||||
|
} |
||||||
|
|
||||||
|
fun setLooper() |
||||||
|
|
||||||
|
fun stop() |
||||||
|
|
||||||
|
/** |
||||||
|
* 任务是否已经完成 |
||||||
|
* |
||||||
|
* @return true 任务已完成 |
||||||
|
*/ |
||||||
|
fun isCompleted(): Boolean |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取当前任务进度 |
||||||
|
* |
||||||
|
* @return 任务当前进度 |
||||||
|
*/ |
||||||
|
fun getCurrentProgress(): Long |
||||||
|
|
||||||
|
fun isStopped(): Boolean |
||||||
|
|
||||||
|
fun isCanceled(): Boolean |
||||||
|
|
||||||
|
fun isRunning(): Boolean |
||||||
|
|
||||||
|
/** |
||||||
|
* 创建handler 回调 |
||||||
|
*/ |
||||||
|
fun getHandler(): Handler |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否有失败的快 |
||||||
|
* |
||||||
|
* @return true 有失败的快 |
||||||
|
*/ |
||||||
|
fun hasFailedTask(): Boolean |
||||||
|
} |
@ -1,155 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
package com.arialyy.aria.util; |
|
||||||
|
|
||||||
import com.arialyy.aria.core.TaskRecord; |
|
||||||
import com.arialyy.aria.core.ThreadRecord; |
|
||||||
import com.arialyy.aria.core.download.DGEntityWrapper; |
|
||||||
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.wrapper.ITaskWrapper; |
|
||||||
import com.arialyy.aria.orm.DbEntity; |
|
||||||
import java.io.File; |
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
/** |
|
||||||
* 数据库帮助类 |
|
||||||
*/ |
|
||||||
public class DbDataHelper { |
|
||||||
|
|
||||||
/** |
|
||||||
* 获取任务记录 |
|
||||||
* |
|
||||||
* @param filePath 文件地址 |
|
||||||
* @param taskType 任务类型{@link ITaskWrapper} |
|
||||||
* @return 没有记录返回null,有记录则返回任务记录 |
|
||||||
*/ |
|
||||||
public static TaskRecord getTaskRecord(String filePath, int taskType) { |
|
||||||
TaskRecord taskRecord = |
|
||||||
DbEntity.findFirst(TaskRecord.class, "filePath=? AND taskType=?", filePath, |
|
||||||
String.valueOf(taskType)); |
|
||||||
if (taskRecord != null) { |
|
||||||
taskRecord.threadRecords = |
|
||||||
DbEntity.findDatas(ThreadRecord.class, "taskKey=? AND threadType=?", filePath, |
|
||||||
String.valueOf(taskType)); |
|
||||||
} |
|
||||||
|
|
||||||
return taskRecord; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 获取组合任务实体、ftpDir任务实体 |
|
||||||
* |
|
||||||
* @param groupHash 组合任务Hash |
|
||||||
* @return 实体不存在,返回null |
|
||||||
*/ |
|
||||||
public static DownloadGroupEntity getDGEntityByHash(String groupHash) { |
|
||||||
List<DGEntityWrapper> wrapper = |
|
||||||
DbEntity.findRelationData(DGEntityWrapper.class, "DownloadGroupEntity.groupHash=?", |
|
||||||
groupHash); |
|
||||||
|
|
||||||
return wrapper == null || wrapper.size() == 0 ? null : wrapper.get(0).groupEntity; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 获取组合任务实体、ftpDir任务实体 |
|
||||||
* |
|
||||||
* @param dirPath 组合任务Hash |
|
||||||
* @return 实体不存在,返回null |
|
||||||
*/ |
|
||||||
public static DownloadGroupEntity getDGEntityByPath(String dirPath) { |
|
||||||
List<DGEntityWrapper> wrapper = |
|
||||||
DbEntity.findRelationData(DGEntityWrapper.class, "DownloadGroupEntity.dirPath=?", |
|
||||||
dirPath); |
|
||||||
|
|
||||||
return wrapper == null || wrapper.size() == 0 ? null : wrapper.get(0).groupEntity; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 获取组合任务实体、ftpDir任务实体 |
|
||||||
* |
|
||||||
* @param taskId 组合任务id |
|
||||||
* @return 实体不存在,返回null |
|
||||||
*/ |
|
||||||
public static DownloadGroupEntity getDGEntity(long taskId) { |
|
||||||
List<DGEntityWrapper> wrapper = |
|
||||||
DbEntity.findRelationData(DGEntityWrapper.class, "DownloadGroupEntity.rowid=?", |
|
||||||
String.valueOf(taskId)); |
|
||||||
|
|
||||||
return wrapper == null || wrapper.size() == 0 ? null : wrapper.get(0).groupEntity; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 创建HTTP子任务实体 |
|
||||||
*/ |
|
||||||
public static List<DownloadEntity> createHttpSubTask(String groupHash, List<String> urls) { |
|
||||||
List<DownloadEntity> list = new ArrayList<>(); |
|
||||||
for (int i = 0, len = urls.size(); i < len; i++) { |
|
||||||
String url = urls.get(i); |
|
||||||
DownloadEntity entity = new DownloadEntity(); |
|
||||||
entity.setUrl(url); |
|
||||||
entity.setFilePath(groupHash + "_" + i); |
|
||||||
int lastIndex = url.lastIndexOf(File.separator); |
|
||||||
//去除url末尾携带的的参数
|
|
||||||
int endIndex = url.lastIndexOf("?"); |
|
||||||
|
|
||||||
if(endIndex<0||endIndex<lastIndex)endIndex=url.length(); |
|
||||||
entity.setFileName(url.substring(lastIndex + 1,endIndex)); |
|
||||||
entity.setGroupHash(groupHash); |
|
||||||
entity.setGroupChild(true); |
|
||||||
list.add(entity); |
|
||||||
} |
|
||||||
return list; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 通过Ftp下载地址获取组合任务实体 |
|
||||||
* |
|
||||||
* @param ftpUrl ftp下载地址 |
|
||||||
*/ |
|
||||||
public static DownloadGroupEntity getOrCreateFtpDGEntity(String ftpUrl) { |
|
||||||
List<DGEntityWrapper> wrapper = |
|
||||||
DbEntity.findRelationData(DGEntityWrapper.class, "DownloadGroupEntity.groupHash=?", |
|
||||||
ftpUrl); |
|
||||||
DownloadGroupEntity groupEntity; |
|
||||||
if (wrapper != null && !wrapper.isEmpty()) { |
|
||||||
groupEntity = wrapper.get(0).groupEntity; |
|
||||||
if (groupEntity == null) { |
|
||||||
groupEntity = new DownloadGroupEntity(); |
|
||||||
} |
|
||||||
} else { |
|
||||||
groupEntity = new DownloadGroupEntity(); |
|
||||||
} |
|
||||||
groupEntity.setGroupHash(ftpUrl); |
|
||||||
return groupEntity; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 创建任务组子任务的任务实体 |
|
||||||
*/ |
|
||||||
public static List<DTaskWrapper> createDGSubTaskWrapper(DownloadGroupEntity dge) { |
|
||||||
List<DTaskWrapper> list = new ArrayList<>(); |
|
||||||
for (DownloadEntity entity : dge.getSubEntities()) { |
|
||||||
DTaskWrapper taskEntity = new DTaskWrapper(entity); |
|
||||||
taskEntity.setGroupHash(dge.getKey()); |
|
||||||
taskEntity.setGroupTask(true); |
|
||||||
list.add(taskEntity); |
|
||||||
} |
|
||||||
return list; |
|
||||||
} |
|
||||||
} |
|
@ -1,129 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
package com.arialyy.aria.util; |
|
||||||
|
|
||||||
import android.text.TextUtils; |
|
||||||
import com.arialyy.aria.core.TaskRecord; |
|
||||||
import com.arialyy.aria.core.ThreadRecord; |
|
||||||
import com.arialyy.aria.core.common.AbsEntity; |
|
||||||
import com.arialyy.aria.core.download.DownloadEntity; |
|
||||||
import com.arialyy.aria.core.download.DownloadGroupEntity; |
|
||||||
import com.arialyy.aria.core.loader.IRecordHandler; |
|
||||||
import com.arialyy.aria.core.wrapper.RecordWrapper; |
|
||||||
import com.arialyy.aria.orm.DbEntity; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
/** |
|
||||||
* 删除组合任务记录 |
|
||||||
*/ |
|
||||||
public class DeleteDGRecord implements IDeleteRecord { |
|
||||||
private String TAG = CommonUtil.getClassName(this); |
|
||||||
|
|
||||||
private static volatile DeleteDGRecord INSTANCE = null; |
|
||||||
|
|
||||||
private DeleteDGRecord() { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
public static DeleteDGRecord getInstance() { |
|
||||||
if (INSTANCE == null) { |
|
||||||
synchronized (DeleteDGRecord.class) { |
|
||||||
if (INSTANCE == null) { |
|
||||||
INSTANCE = new DeleteDGRecord(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return INSTANCE; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @param dirPath 组合任务保存路径 |
|
||||||
* @param needRemoveFile true,无论下载成功以否,都将删除下载下来的文件。false,只会删除下载任务没有完成的文件 |
|
||||||
* @param needRemoveEntity 是否需要删除实体,true 删除实体 |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
public void deleteRecord(String dirPath, boolean needRemoveFile, boolean needRemoveEntity) { |
|
||||||
if (TextUtils.isEmpty(dirPath)) { |
|
||||||
ALog.e(TAG, "删除下载任务组记录失败,组合任务路径为空"); |
|
||||||
return; |
|
||||||
} |
|
||||||
deleteRecord(DbDataHelper.getDGEntityByPath(dirPath), needRemoveFile, needRemoveEntity); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void deleteRecord(AbsEntity absEntity, boolean needRemoveFile, boolean needRemoveEntity) { |
|
||||||
if (absEntity == null) { |
|
||||||
ALog.e(TAG, "删除组合任务记录失败,组合任务实体为空"); |
|
||||||
return; |
|
||||||
} |
|
||||||
DownloadGroupEntity groupEntity = (DownloadGroupEntity) absEntity; |
|
||||||
|
|
||||||
List<RecordWrapper> records = |
|
||||||
DbEntity.findRelationData(RecordWrapper.class, "dGroupHash=?", groupEntity.getGroupHash()); |
|
||||||
|
|
||||||
// 删除子任务记录
|
|
||||||
if (records == null || records.isEmpty()) { |
|
||||||
ALog.w(TAG, "组任务记录已删除"); |
|
||||||
} else { |
|
||||||
for (RecordWrapper record : records) { |
|
||||||
if (record == null || record.taskRecord == null) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
// 删除分块文件
|
|
||||||
if (record.taskRecord.isBlock) { |
|
||||||
removeBlockFile(record.taskRecord); |
|
||||||
} |
|
||||||
DbEntity.deleteData(ThreadRecord.class, "taskKey=?", record.taskRecord.filePath); |
|
||||||
record.taskRecord.deleteData(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// 删除组合任务子任务的文件
|
|
||||||
List<DownloadEntity> subs = groupEntity.getSubEntities(); |
|
||||||
if (subs != null) { |
|
||||||
for (DownloadEntity sub : subs) { |
|
||||||
if (needRemoveFile || !groupEntity.isComplete()) { |
|
||||||
FileUtil.deleteFile(sub.getFilePath()); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// 删除文件夹
|
|
||||||
if (!TextUtils.isEmpty(groupEntity.getDirPath())) { |
|
||||||
if (needRemoveFile || !groupEntity.isComplete()) { |
|
||||||
FileUtil.deleteFile(groupEntity.getDirPath()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
deleteEntity(needRemoveEntity, groupEntity.getGroupHash()); |
|
||||||
} |
|
||||||
|
|
||||||
private void deleteEntity(boolean needRemoveEntity, String groupHash) { |
|
||||||
if (needRemoveEntity) { |
|
||||||
DbEntity.deleteData(DownloadEntity.class, "groupHash=?", groupHash); |
|
||||||
DbEntity.deleteData(DownloadGroupEntity.class, "groupHash=?", groupHash); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 删除多线程分块下载的分块文件 |
|
||||||
*/ |
|
||||||
private void removeBlockFile(TaskRecord record) { |
|
||||||
for (int i = 0, len = record.threadNum; i < len; i++) { |
|
||||||
FileUtil.deleteFile(String.format(IRecordHandler.SUB_PATH, record.filePath, i)); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,131 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
package com.arialyy.aria.util; |
|
||||||
|
|
||||||
import android.text.TextUtils; |
|
||||||
import com.arialyy.aria.core.TaskRecord; |
|
||||||
import com.arialyy.aria.core.ThreadRecord; |
|
||||||
import com.arialyy.aria.core.common.AbsEntity; |
|
||||||
import com.arialyy.aria.core.download.DownloadEntity; |
|
||||||
import com.arialyy.aria.core.loader.IRecordHandler; |
|
||||||
import com.arialyy.aria.core.wrapper.ITaskWrapper; |
|
||||||
import com.arialyy.aria.orm.DbEntity; |
|
||||||
import java.io.File; |
|
||||||
|
|
||||||
/** |
|
||||||
* 删除下载记录 |
|
||||||
*/ |
|
||||||
public class DeleteDRecord implements IDeleteRecord { |
|
||||||
private String TAG = CommonUtil.getClassName(this); |
|
||||||
private static volatile DeleteDRecord INSTANCE = null; |
|
||||||
|
|
||||||
private DeleteDRecord() { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
public static DeleteDRecord getInstance() { |
|
||||||
if (INSTANCE == null) { |
|
||||||
synchronized (DeleteDRecord.class) { |
|
||||||
if (INSTANCE == null) { |
|
||||||
INSTANCE = new DeleteDRecord(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return INSTANCE; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @param filePath 文件保存路径 |
|
||||||
* @param removeTarget true,无论下载成功以否,都将删除下载下来的文件。false,只会删除下载任务没有完成的文件 |
|
||||||
* @param needRemoveEntity 是否需要删除实体 |
|
||||||
*/ |
|
||||||
@Override public void deleteRecord(String filePath, boolean removeTarget, |
|
||||||
boolean needRemoveEntity) { |
|
||||||
if (TextUtils.isEmpty(filePath)) { |
|
||||||
throw new NullPointerException("删除记录失败,文件路径为空"); |
|
||||||
} |
|
||||||
if (!filePath.startsWith("/")) { |
|
||||||
throw new IllegalArgumentException(String.format("文件路径错误,filePath:%s", filePath)); |
|
||||||
} |
|
||||||
DownloadEntity entity = DbEntity.findFirst(DownloadEntity.class, "downloadPath=?", filePath); |
|
||||||
if (entity == null) { |
|
||||||
ALog.e(TAG, "删除下载记录失败,没有在数据库中找到对应的实体文件,filePath:" + filePath); |
|
||||||
return; |
|
||||||
} |
|
||||||
deleteRecord(entity, removeTarget, needRemoveEntity); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @param absEntity 记录关联的实体 |
|
||||||
* @param needRemoveFile true,无论下载成功以否,都将删除下载下来的文件。false,只会删除下载任务没有完成的文件 |
|
||||||
* @param needRemoveEntity 是否需要删除实体 |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
public void deleteRecord(AbsEntity absEntity, boolean needRemoveFile, boolean needRemoveEntity) { |
|
||||||
if (absEntity == null) { |
|
||||||
ALog.e(TAG, "删除下载记录失败,实体为空"); |
|
||||||
return; |
|
||||||
} |
|
||||||
DownloadEntity entity = (DownloadEntity) absEntity; |
|
||||||
final String filePath = entity.getFilePath(); |
|
||||||
File targetFile = new File(filePath); |
|
||||||
|
|
||||||
// 兼容以前版本
|
|
||||||
if (entity.getTaskType() == ITaskWrapper.M3U8_VOD |
|
||||||
|| entity.getTaskType() == ITaskWrapper.M3U8_LIVE) { |
|
||||||
DeleteM3u8Record.getInstance().deleteRecord(entity, needRemoveFile, needRemoveEntity); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
TaskRecord record = DbDataHelper.getTaskRecord(entity.getFilePath(), entity.getTaskType()); |
|
||||||
if (record == null) { |
|
||||||
ALog.e(TAG, "删除下载记录失败,记录为空,将删除实体记录,filePath:" + entity.getFilePath()); |
|
||||||
FileUtil.deleteFile(targetFile); |
|
||||||
deleteEntity(needRemoveEntity, filePath); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
// 删除下载的线程记录和任务记录
|
|
||||||
DbEntity.deleteData(ThreadRecord.class, "taskKey=? AND threadType=?", filePath, |
|
||||||
String.valueOf(entity.getTaskType())); |
|
||||||
DbEntity.deleteData(TaskRecord.class, "filePath=? AND taskType=?", filePath, |
|
||||||
String.valueOf(entity.getTaskType())); |
|
||||||
|
|
||||||
if (needRemoveFile || !entity.isComplete()) { |
|
||||||
FileUtil.deleteFile(targetFile); |
|
||||||
if (record.isBlock) { |
|
||||||
removeBlockFile(record); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
deleteEntity(needRemoveEntity, filePath); |
|
||||||
} |
|
||||||
|
|
||||||
private void deleteEntity(boolean needRemoveEntity, String filePath){ |
|
||||||
if (needRemoveEntity) { |
|
||||||
DbEntity.deleteData(DownloadEntity.class, "downloadPath=?", filePath); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 删除多线程分块下载的分块文件 |
|
||||||
*/ |
|
||||||
private void removeBlockFile(TaskRecord record) { |
|
||||||
for (int i = 0, len = record.threadNum; i < len; i++) { |
|
||||||
FileUtil.deleteFile(String.format(IRecordHandler.SUB_PATH, record.filePath, i)); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,151 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
package com.arialyy.aria.util; |
|
||||||
|
|
||||||
import android.text.TextUtils; |
|
||||||
import com.arialyy.aria.core.TaskRecord; |
|
||||||
import com.arialyy.aria.core.ThreadRecord; |
|
||||||
import com.arialyy.aria.core.common.AbsEntity; |
|
||||||
import com.arialyy.aria.core.download.DownloadEntity; |
|
||||||
import com.arialyy.aria.core.common.M3U8Entity; |
|
||||||
import com.arialyy.aria.orm.DbEntity; |
|
||||||
import java.io.File; |
|
||||||
|
|
||||||
/** |
|
||||||
* 删除m3u8记录 |
|
||||||
*/ |
|
||||||
public class DeleteM3u8Record implements IDeleteRecord { |
|
||||||
private String TAG = CommonUtil.getClassName(this); |
|
||||||
|
|
||||||
private static volatile DeleteM3u8Record INSTANCE = null; |
|
||||||
|
|
||||||
private DeleteM3u8Record() { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
public static DeleteM3u8Record getInstance() { |
|
||||||
if (INSTANCE == null) { |
|
||||||
synchronized (DeleteM3u8Record.class) { |
|
||||||
if (INSTANCE == null) { |
|
||||||
INSTANCE = new DeleteM3u8Record(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return INSTANCE; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @param filePath 文件保存路径 |
|
||||||
* @param removeTarget true,无论下载成功以否,都将删除下载下来的文件。false,只会删除下载任务没有完成的文件 |
|
||||||
* @param needRemoveEntity 是否需要删除实体 |
|
||||||
*/ |
|
||||||
@Override public void deleteRecord(String filePath, boolean removeTarget, |
|
||||||
boolean needRemoveEntity) { |
|
||||||
if (TextUtils.isEmpty(filePath)) { |
|
||||||
throw new NullPointerException("删除记录失败,文件路径为空"); |
|
||||||
} |
|
||||||
if (!filePath.startsWith("/")) { |
|
||||||
throw new IllegalArgumentException(String.format("文件路径错误,filePath:%s", filePath)); |
|
||||||
} |
|
||||||
DownloadEntity entity = DbEntity.findFirst(DownloadEntity.class, "downloadPath=?", filePath); |
|
||||||
if (entity == null) { |
|
||||||
ALog.e(TAG, "删除下载记录失败,没有在数据库中找到对应的实体文件,filePath:" + filePath); |
|
||||||
return; |
|
||||||
} |
|
||||||
deleteRecord(entity, removeTarget, needRemoveEntity); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void deleteRecord(AbsEntity absEntity, boolean needRemoveFile, boolean needRemoveEntity) { |
|
||||||
if (absEntity == null) { |
|
||||||
ALog.e(TAG, "删除下载记录失败,实体为空"); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
DownloadEntity entity = (DownloadEntity) absEntity; |
|
||||||
final String filePath = entity.getFilePath(); |
|
||||||
TaskRecord record = DbDataHelper.getTaskRecord(filePath, entity.getTaskType()); |
|
||||||
if (record == null) { |
|
||||||
ALog.e(TAG, "删除下载记录失败,记录为空,将删除实体记录,filePath:" + entity.getFilePath()); |
|
||||||
deleteEntity(entity.getTaskType(), needRemoveEntity, filePath); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
if (needRemoveFile || !entity.isComplete()) { |
|
||||||
removeTsCache(new File(filePath), record.bandWidth); |
|
||||||
FileUtil.deleteFile(filePath); |
|
||||||
} |
|
||||||
|
|
||||||
deleteEntity(entity.getTaskType(), needRemoveEntity, filePath); |
|
||||||
} |
|
||||||
|
|
||||||
private void deleteEntity(int taskType, boolean needRemoveEntity, String filePath){ |
|
||||||
// 删除下载的线程记录和任务记录
|
|
||||||
DbEntity.deleteData(ThreadRecord.class, "taskKey=? AND threadType=?", filePath, |
|
||||||
String.valueOf(taskType)); |
|
||||||
DbEntity.deleteData(TaskRecord.class, "filePath=? AND taskType=?", filePath, |
|
||||||
String.valueOf(taskType)); |
|
||||||
DbEntity.deleteData(M3U8Entity.class, "filePath=?", filePath); |
|
||||||
|
|
||||||
if (needRemoveEntity) { |
|
||||||
DbEntity.deleteData(DownloadEntity.class, "downloadPath=?", filePath); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 删除ts文件,和索引文件(如果有的话) |
|
||||||
*/ |
|
||||||
private static void removeTsCache(File targetFile, long bandWidth) { |
|
||||||
|
|
||||||
// 删除key
|
|
||||||
M3U8Entity entity = DbEntity.findFirst(M3U8Entity.class, "filePath=?", targetFile.getPath()); |
|
||||||
if (entity != null && !TextUtils.isEmpty(entity.keyPath)){ |
|
||||||
File keyFile = new File(entity.keyPath); |
|
||||||
FileUtil.deleteFile(keyFile); |
|
||||||
} |
|
||||||
|
|
||||||
// 删除ts
|
|
||||||
String cacheDir = null; |
|
||||||
if (!targetFile.isDirectory()) { |
|
||||||
cacheDir = |
|
||||||
String.format("%s/.%s_%s", targetFile.getParent(), targetFile.getName(), bandWidth); |
|
||||||
} |
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(cacheDir)) { |
|
||||||
File cacheDirF = new File(cacheDir); |
|
||||||
if (!cacheDirF.exists()) { |
|
||||||
return; |
|
||||||
} |
|
||||||
File[] files = cacheDirF.listFiles(); |
|
||||||
for (File f : files) { |
|
||||||
if (f.exists()) { |
|
||||||
f.delete(); |
|
||||||
} |
|
||||||
} |
|
||||||
File cDir = new File(cacheDir); |
|
||||||
if (cDir.exists()) { |
|
||||||
cDir.delete(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
File indexFile = new File(String.format("%s.index", targetFile.getPath())); |
|
||||||
|
|
||||||
if (indexFile.exists()) { |
|
||||||
indexFile.delete(); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
@ -1,99 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
package com.arialyy.aria.util; |
|
||||||
|
|
||||||
import android.text.TextUtils; |
|
||||||
import com.arialyy.aria.core.TaskRecord; |
|
||||||
import com.arialyy.aria.core.ThreadRecord; |
|
||||||
import com.arialyy.aria.core.common.AbsEntity; |
|
||||||
import com.arialyy.aria.core.upload.UploadEntity; |
|
||||||
import com.arialyy.aria.orm.DbEntity; |
|
||||||
|
|
||||||
/** |
|
||||||
* 删除上传记录 |
|
||||||
*/ |
|
||||||
public class DeleteURecord implements IDeleteRecord { |
|
||||||
private String TAG = CommonUtil.getClassName(this); |
|
||||||
|
|
||||||
private static volatile DeleteURecord INSTANCE = null; |
|
||||||
|
|
||||||
private DeleteURecord() { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
public static DeleteURecord getInstance() { |
|
||||||
if (INSTANCE == null) { |
|
||||||
synchronized (DeleteURecord.class) { |
|
||||||
if (INSTANCE == null) { |
|
||||||
INSTANCE = new DeleteURecord(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return INSTANCE; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 删除上传记录 |
|
||||||
* |
|
||||||
* @param filePath 上传文件的地址 |
|
||||||
* @param needRemoveFile 上传完成后是否需要删除本地文件。true,上传完成后删除本地文件 |
|
||||||
* @param needRemoveEntity 是否需要删除实体,true 删除实体 |
|
||||||
*/ |
|
||||||
@Override public void deleteRecord(String filePath, boolean needRemoveFile, |
|
||||||
boolean needRemoveEntity) { |
|
||||||
if (TextUtils.isEmpty(filePath)) { |
|
||||||
throw new NullPointerException("删除记录失败,文件路径为空"); |
|
||||||
} |
|
||||||
if (!filePath.startsWith("/")) { |
|
||||||
throw new IllegalArgumentException(String.format("文件路径错误,filePath:%s", filePath)); |
|
||||||
} |
|
||||||
|
|
||||||
UploadEntity entity = DbEntity.findFirst(UploadEntity.class, "filePath=?", filePath); |
|
||||||
if (entity == null) { |
|
||||||
ALog.e(TAG, "删除上传记录失败,没有在数据库中找到对应的实体文件,filePath:" + filePath); |
|
||||||
return; |
|
||||||
} |
|
||||||
deleteRecord(entity, needRemoveFile, needRemoveEntity); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void deleteRecord(AbsEntity absEntity, boolean needRemoveFile, boolean needRemoveEntity) { |
|
||||||
if (absEntity == null) { |
|
||||||
ALog.e(TAG, "删除上传记录失败,实体为空"); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
UploadEntity entity = (UploadEntity) absEntity; |
|
||||||
|
|
||||||
// 删除下载的线程记录和任务记录
|
|
||||||
DbEntity.deleteData(ThreadRecord.class, "taskKey=? AND threadType=?", entity.getFilePath(), |
|
||||||
String.valueOf(entity.getTaskType())); |
|
||||||
DbEntity.deleteData(TaskRecord.class, "filePath=? AND taskType=?", entity.getFilePath(), |
|
||||||
String.valueOf(entity.getTaskType())); |
|
||||||
|
|
||||||
if (needRemoveFile) { |
|
||||||
FileUtil.deleteFile(entity.getFilePath()); |
|
||||||
} |
|
||||||
|
|
||||||
deleteEntity(needRemoveEntity, entity.getFilePath()); |
|
||||||
} |
|
||||||
|
|
||||||
private void deleteEntity(boolean needRemoveEntity, String filePath) { |
|
||||||
if (needRemoveEntity) { |
|
||||||
DbEntity.deleteData(UploadEntity.class, "filePath=?", filePath); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue