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