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