This commit is contained in:
laoyuyu
2020-04-18 11:30:55 +08:00
parent 0476c3a941
commit 1f2ac36580
45 changed files with 733 additions and 430 deletions

View File

@@ -144,20 +144,20 @@ public class AriaConfig {
@Override public void onLost(Network network) {
super.onLost(network);
isConnectedNet = false;
ALog.d(TAG, "onLost");
isConnectedNet = isNetworkAvailable();
ALog.d(TAG, "onLost, isConnectNet = " + isConnectedNet);
}
@Override public void onAvailable(Network network) {
super.onAvailable(network);
ALog.d(TAG, "onAvailable");
isConnectedNet = true;
ALog.d(TAG, "onAvailable, isConnectNet = true");
}
});
}
}
public boolean isNetworkAvailable() {
private boolean isNetworkAvailable() {
// 获取手机所有连接管理对象包括对wi-fi,net等连接的管理
ConnectivityManager connectivityManager =
(ConnectivityManager) getAPP().getSystemService(Context.CONNECTIVITY_SERVICE);

View File

@@ -75,9 +75,13 @@ public class DownloadEntity extends AbsNormalEntity implements Parcelable {
}
/**
* 如果是30x则是30x后的地址
* 设置进来的地址,如果需要获取真实的下载地址,请使用{@link #getRealUrl()}
*/
@Override public String getKey() {
return getUrl();
}
public String getRealUrl(){
return isRedirect() ? getRedirectUrl() : getUrl();
}

View File

@@ -23,6 +23,7 @@ import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.DeleteDRecord;
import com.arialyy.aria.util.RecordUtil;
/**
@@ -55,11 +56,15 @@ public class BaseDListener extends BaseListener<DownloadEntity, DTaskWrapper, Ab
if (sType == TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY) {
mEntity.setComplete(false);
mEntity.setState(IEntity.STATE_WAIT);
RecordUtil.delTaskRecord(mEntity.getFilePath(), IRecordHandler.TYPE_DOWNLOAD,
mTaskWrapper.isRemoveFile(), false);
DeleteDRecord.getInstance().deleteRecord(mEntity, mTaskWrapper.isRemoveFile(), false);
//RecordUtil.delTaskRecord(mEntity.getFilePath(), IRecordHandler.TYPE_DOWNLOAD,
// mTaskWrapper.isRemoveFile(), false);
} else {
RecordUtil.delTaskRecord(mEntity.getFilePath(), IRecordHandler.TYPE_DOWNLOAD,
mTaskWrapper.isRemoveFile(), true);
//RecordUtil.delTaskRecord(mEntity.getFilePath(), IRecordHandler.TYPE_DOWNLOAD,
// mTaskWrapper.isRemoveFile(), true);
DeleteDRecord.getInstance().deleteRecord(mEntity, mTaskWrapper.isRemoveFile(), true);
}
}
}

View File

@@ -180,7 +180,6 @@ public abstract class BaseListener<ENTITY extends AbsEntity, TASK_WRAPPER extend
protected void saveData(int state, long location) {
mEntity.setState(state);
mEntity.setComplete(false);
if (state == IEntity.STATE_CANCEL) {
handleCancel();

View File

@@ -17,12 +17,11 @@ package com.arialyy.aria.core.listener;
import android.os.Handler;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.core.upload.UTaskWrapper;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.util.RecordUtil;
import com.arialyy.aria.util.DeleteURecord;
/**
* 下载监听类
@@ -39,11 +38,9 @@ public class BaseUListener extends BaseListener<UploadEntity, UTaskWrapper, AbsT
if (sType == TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY) {
mEntity.setComplete(false);
mEntity.setState(IEntity.STATE_WAIT);
RecordUtil.delTaskRecord(mEntity.getFilePath(), IRecordHandler.TYPE_UPLOAD,
mTaskWrapper.isRemoveFile(), false);
DeleteURecord.getInstance().deleteRecord(mEntity, mTaskWrapper.isRemoveFile(), false);
} else {
RecordUtil.delTaskRecord(mEntity.getFilePath(), IRecordHandler.TYPE_UPLOAD,
mTaskWrapper.isRemoveFile(), true);
DeleteURecord.getInstance().deleteRecord(mEntity, mTaskWrapper.isRemoveFile(), true);
}
}
}

View File

@@ -27,8 +27,8 @@ import com.arialyy.aria.core.task.DownloadGroupTask;
import com.arialyy.aria.exception.AriaException;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.DeleteDGRecord;
import com.arialyy.aria.util.ErrorHelp;
import com.arialyy.aria.util.RecordUtil;
import static com.arialyy.aria.core.task.AbsTask.ERROR_INFO_KEY;
@@ -87,7 +87,7 @@ public class DownloadGroupListener
handleSubSpeed(subEntity, 0);
saveSubState(IEntity.STATE_FAIL, subEntity);
saveCurrentLocation();
mSeedEntity.groupTask.putExpand(ERROR_INFO_KEY,e);
mSeedEntity.groupTask.putExpand(ERROR_INFO_KEY, e);
sendInState2Target(ISchedulers.SUB_FAIL, subEntity);
if (e != null) {
e.printStackTrace();
@@ -197,9 +197,9 @@ public class DownloadGroupListener
if (sType == TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY) {
mEntity.setComplete(false);
mEntity.setState(IEntity.STATE_WAIT);
RecordUtil.delGroupTaskRecord(mEntity, mTaskWrapper.isRemoveFile(), false);
DeleteDGRecord.getInstance().deleteRecord(mEntity, mTaskWrapper.isRemoveFile(), false);
} else {
RecordUtil.delGroupTaskRecord(mEntity, mTaskWrapper.isRemoveFile(), true);
DeleteDGRecord.getInstance().deleteRecord(mEntity, mTaskWrapper.isRemoveFile(), true);
}
}
}

View File

@@ -16,6 +16,7 @@
package com.arialyy.aria.core.loader;
import android.os.Looper;
import android.util.Log;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.inf.IThreadStateManager;
import com.arialyy.aria.core.listener.IEventListener;
@@ -154,33 +155,43 @@ public abstract class AbsNormalLoader<T extends AbsTaskWrapper> implements ILoad
if (isBreak()) {
return;
}
ALog.d(TAG, "启动定时器");
mTimer = new ScheduledThreadPoolExecutor(1);
mTimer.scheduleWithFixedDelay(new Runnable() {
@Override public void run() {
// 线程池中是不抛异常的没有日志很难定位问题需要手动try-catch
try {
if (mStateManager == null) {
ALog.e(TAG, "stateManager is null");
} else if (mStateManager.isComplete()
|| mStateManager.isFail()
|| !isRunning()
|| isBreak()) {
//ALog.d(TAG, "isComplete = " + mStateManager.isComplete()
// + "; isFail = " + mStateManager.isFail()
// + "; isRunning = " + isRunning()
// + "; isBreak = " + isBreak());
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
closeTimer();
onDestroy();
} else if (mStateManager.getCurrentProgress() >= 0) {
mListener.onProgress(mStateManager.getCurrentProgress());
ALog.d(TAG, String.format("启动定时器delayTimer = %s, updateInterval = %s", delayTimer(),
mUpdateInterval));
closeTimer();
try {
mTimer = new ScheduledThreadPoolExecutor(1);
mTimer.scheduleWithFixedDelay(new Runnable() {
@Override public void run() {
// 线程池中是不抛异常的没有日志很难定位问题需要手动try-catch
try {
if (mStateManager == null) {
ALog.e(TAG, "stateManager is null");
} else if (mStateManager.isComplete()
|| mStateManager.isFail()
|| !isRunning()
|| isBreak()) {
//ALog.d(TAG, "isComplete = " + mStateManager.isComplete()
// + "; isFail = " + mStateManager.isFail()
// + "; isRunning = " + isRunning()
// + "; isBreak = " + isBreak());
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
closeTimer();
onDestroy();
} else if (mStateManager.getCurrentProgress() >= 0) {
Log.d(TAG, "running...");
mListener.onProgress(mStateManager.getCurrentProgress());
} else {
Log.d(TAG, "未知状态");
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}, delayTimer(), mUpdateInterval, TimeUnit.MILLISECONDS);
}, delayTimer(), mUpdateInterval, TimeUnit.MILLISECONDS);
} catch (Exception e) {
ALog.e(TAG, "启动定时器失败");
e.printStackTrace();
}
}
private synchronized void closeTimer() {

View File

@@ -25,12 +25,14 @@ import com.arialyy.aria.core.inf.IThreadStateManager;
import com.arialyy.aria.core.listener.IDLoadListener;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.manager.ThreadTaskManager;
import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.core.task.IThreadTask;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.exception.AriaException;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.FileUtil;
import java.io.File;
import java.util.List;
/**
* 单文件
@@ -130,6 +132,8 @@ public class NormalLoader<T extends AbsTaskWrapper> extends AbsNormalLoader<T> {
ThreadTaskManager.getInstance().startThread(mTaskWrapper.getKey(), threadTask);
}
List<IThreadTask> list = getTaskList();
// 启动定时器
startTimer();
}

View File

@@ -63,7 +63,7 @@ public class DownloadTask extends AbsTask<DTaskWrapper> {
}
@Override public String getKey() {
return mTaskWrapper.getEntity().getUrl();
return mTaskWrapper.getEntity().getKey();
}
public DownloadEntity getDownloadEntity() {

View File

@@ -20,6 +20,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Process;
import android.util.Log;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.common.AbsEntity;
@@ -457,7 +458,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
ThreadTaskManager.getInstance().retryThread(this);
} else {
ALog.e(TAG, String.format("任务【%s】执行失败", getFileName()));
sendFailMsg(null, false);
sendFailMsg(null, needRetry);
}
}

View File

@@ -39,7 +39,7 @@ public class UploadTask extends AbsTask<UTaskWrapper> {
}
@Override public String getKey() {
return mTaskWrapper.getEntity().getFilePath();
return mTaskWrapper.getEntity().getKey();
}
public UploadEntity getEntity() {

View File

@@ -16,7 +16,7 @@
package com.arialyy.aria.exception;
public class AriaFTPException extends AriaException {
private static final String FTP_EXCEPTION = "Aria SFTP Exception:";
private static final String FTP_EXCEPTION = "Aria FTP Exception:";
public AriaFTPException(String tag, String message) {
super(tag, String.format("%s\n%s", FTP_EXCEPTION, message));

View File

@@ -19,8 +19,8 @@ package com.arialyy.aria.util;
import android.text.TextUtils;
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.upload.UploadEntity;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.orm.DbEntity;
import java.lang.reflect.Modifier;
import java.net.HttpURLConnection;
@@ -78,16 +78,17 @@ public class CheckUtil {
*
* @param isForceDownload true如果路径冲突将删除其它任务的记录的
* @param filePath 文件保存路径
* @param type {@link AbsTaskWrapper#getRequestType()}
* @return false 任务不再执行true 任务继续执行
*/
public static boolean checkDPathConflicts(boolean isForceDownload, String filePath) {
public static boolean checkDPathConflicts(boolean isForceDownload, String filePath, int type) {
if (DbEntity.checkDataExist(DownloadEntity.class, "downloadPath=?", filePath)) {
if (!isForceDownload) {
ALog.e(TAG, String.format("下载失败,保存路径【%s】已经被其它任务占用请设置其它保存路径", filePath));
return false;
} else {
ALog.w(TAG, String.format("保存路径【%s】已经被其它任务占用当前任务将覆盖该路径的文件", filePath));
RecordUtil.delTaskRecord(filePath, IRecordHandler.TYPE_DOWNLOAD);
RecordUtil.delTaskRecord(filePath, type, false, true);
return true;
}
}
@@ -99,16 +100,17 @@ public class CheckUtil {
*
* @param isForceUpload true如果路径冲突将删除其它任务的记录的
* @param filePath 文件保存路径
* @param type {@link AbsTaskWrapper#getRequestType()}
* @return false 任务不再执行true 任务继续执行
*/
public static boolean checkUPathConflicts(boolean isForceUpload, String filePath) {
public static boolean checkUPathConflicts(boolean isForceUpload, String filePath, int type) {
if (DbEntity.checkDataExist(UploadEntity.class, "filePath=?", filePath)) {
if (!isForceUpload) {
ALog.e(TAG, String.format("上传失败,文件路径【%s】已经被其它任务占用请设置其它文件路径", filePath));
return false;
} else {
ALog.w(TAG, String.format("文件路径【%s】已经被其它任务占用当前任务将覆盖该路径的文件", filePath));
RecordUtil.delTaskRecord(filePath, IRecordHandler.TYPE_UPLOAD);
RecordUtil.delTaskRecord(filePath, type, false, true);
return true;
}
}
@@ -129,7 +131,7 @@ public class CheckUtil {
return false;
} else {
ALog.w(TAG, String.format("文件夹路径【%s】已经被其它任务占用当前任务将覆盖该路径", dirPath));
RecordUtil.delGroupTaskRecordByPath(dirPath, false);
DeleteDGRecord.getInstance().deleteRecord(dirPath, false, true);
return true;
}
}

View File

@@ -0,0 +1,125 @@
/*
* 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());
}
}
if (needRemoveEntity) {
DbEntity.deleteData(DownloadEntity.class, "groupHash=?", groupEntity.getGroupHash());
DbEntity.deleteData(DownloadGroupEntity.class, "groupHash=?", groupEntity.getGroupHash());
}
}
/**
* 删除多线程分块下载的分块文件
*/
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));
}
}
}

View File

@@ -0,0 +1,121 @@
/*
* 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());
return;
}
DbEntity.deleteData(ThreadRecord.class, "taskKey=? AND threadType=?", filePath,
String.valueOf(entity.getTaskType()));
if (needRemoveEntity || !entity.isComplete()) {
FileUtil.deleteFile(targetFile);
if (record.isBlock) {
removeBlockFile(record);
}
}
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));
}
}
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.util;
import android.text.TextUtils;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.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;
TaskRecord record = DbDataHelper.getTaskRecord(entity.getFilePath(), entity.getTaskType());
if (record == null) {
ALog.e(TAG, "删除下载记录失败记录为空filePath" + entity.getFilePath());
return;
}
final String filePath = entity.getFilePath();
DbEntity.deleteData(M3U8Entity.class, "filePath=?", filePath);
if (needRemoveFile || !entity.isComplete()) {
removeTsCache(new File(filePath), record.bandWidth);
FileUtil.deleteFile(filePath);
}
if (needRemoveEntity) {
DbEntity.deleteData(DownloadEntity.class, "downloadPath=?", filePath);
}
}
/**
* 删除ts文件和索引文件如果有的话
*/
private static void removeTsCache(File targetFile, long bandWidth) {
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();
}
}
}

View File

@@ -0,0 +1,90 @@
/*
* 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.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(TaskRecord.class, "filePath=? AND taskType=?", entity.getFilePath(),
String.valueOf(entity.getTaskType()));
if (needRemoveFile) {
FileUtil.deleteFile(entity.getFilePath());
}
if (needRemoveEntity) {
DbEntity.deleteData(UploadEntity.class, "filePath=?", entity.getFilePath());
}
}
}

View File

@@ -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.util;
import com.arialyy.aria.core.common.AbsEntity;
/**
* 删除记录
*/
public interface IDeleteRecord {
/**
* 删除记录
*
* @param key 记录关联的key
* @param needRemoveFile 是否需要删除文件
* @param needRemoveEntity 是否需要删除实体true 删除实体
*/
void deleteRecord(String key, boolean needRemoveFile, boolean needRemoveEntity);
/**
* 删除记录
*
* @param absEntity 记录关联的实体
* @param needRemoveFile 是否需要删除文件
* @param needRemoveEntity 是否需要删除实体true 删除实体
*/
void deleteRecord(AbsEntity absEntity, boolean needRemoveFile, boolean needRemoveEntity);
}

View File

@@ -18,18 +18,13 @@ 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.common.AbsNormalEntity;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.download.M3U8Entity;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.core.wrapper.RecordWrapper;
import com.arialyy.aria.orm.DbEntity;
import java.io.File;
import java.util.List;
/**
* 任务记录处理工具
@@ -49,93 +44,7 @@ public class RecordUtil {
return;
}
DownloadGroupEntity groupEntity = DbDataHelper.getDGEntityByHash(groupHash);
delGroupTaskRecord(groupEntity, removeFile, true);
}
/**
* 根据路径删除组合任务记录
*
* @param removeFile {@code true} 无论任务是否完成,都会删除记录和文件;
* {@code false} 如果任务已经完成,则只删除记录,不删除文件;任务未完成,记录和文件都会删除。
*/
public static void delGroupTaskRecordByPath(String dirPath, boolean removeFile) {
if (TextUtils.isEmpty(dirPath)) {
ALog.e(TAG, "删除下载任务组记录失败,组合任务路径为空");
return;
}
DownloadGroupEntity groupEntity = DbDataHelper.getDGEntityByPath(dirPath);
// 处理组任务存在,而子任务为空的情况
if (groupEntity == null) {
groupEntity = DbEntity.findFirst(DownloadGroupEntity.class, "dirPath=?", dirPath);
if (groupEntity != null) {
groupEntity.deleteData();
DbEntity.deleteData(DownloadEntity.class, "groupHash=?", groupEntity.getGroupHash());
}
return;
}
delGroupTaskRecord(groupEntity, removeFile, true);
}
/**
* 删除任务组记录
*
* @param removeFile {@code true} 无论任务是否完成,都会删除记录和文件;
* {@code false} 如果任务已经完成,则只删除记录,不删除文件;任务未完成,记录和文件都会删除。
*/
public static void delGroupTaskRecord(DownloadGroupEntity groupEntity, boolean removeFile,
boolean removeEntity) {
if (groupEntity == null) {
ALog.e(TAG, "删除下载任务组记录失败任务组实体为null");
return;
}
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) {
for (int i = 0, len = record.taskRecord.threadNum; i < len; i++) {
File partFile =
new File(String.format(IRecordHandler.SUB_PATH, record.taskRecord.filePath, i));
if (partFile.exists()) {
partFile.delete();
}
}
}
DbEntity.deleteData(ThreadRecord.class, "taskKey=?", record.taskRecord.filePath);
record.taskRecord.deleteData();
}
}
List<DownloadEntity> subs = groupEntity.getSubEntities();
if (subs != null) {
for (DownloadEntity sub : subs) {
File file = new File(sub.getFilePath());
if (file.exists() && (removeFile || !sub.isComplete())) {
file.delete();
}
}
}
// 删除文件夹
if (!TextUtils.isEmpty(groupEntity.getDirPath())) {
File dir = new File(groupEntity.getDirPath());
if (dir.exists() && (removeFile || !groupEntity.isComplete())) {
dir.delete();
}
}
if (removeEntity) {
DbEntity.deleteData(DownloadEntity.class, "groupHash=?", groupEntity.getGroupHash());
DbEntity.deleteData(DownloadGroupEntity.class, "groupHash=?", groupEntity.getGroupHash());
}
DeleteDGRecord.getInstance().deleteRecord(groupEntity, removeFile, true);
}
/**
@@ -145,215 +54,23 @@ public class RecordUtil {
* {@code false} 如果是下载任务,并且任务已经完成,则只删除记录,不删除文件;任务未完成,记录和文件都会删除。
* 如果是上传任务,无论任务是否完成,都只删除记录
*/
public static void delTaskRecord(AbsNormalEntity entity, boolean removeFile) {
if (entity == null) return;
String filePath;
int type;
if (entity instanceof DownloadEntity) {
type = IRecordHandler.TYPE_DOWNLOAD;
filePath = entity.getFilePath();
} else if (entity instanceof UploadEntity) {
type = IRecordHandler.TYPE_UPLOAD;
filePath = entity.getFilePath();
} else {
ALog.w(TAG, "删除记录失败,未知类型");
return;
}
File targetFile = new File(filePath);
TaskRecord record = getTaskRecord(filePath);
if (record == null) {
if (removeFile) {
removeTargetFile(targetFile);
}
removeRecord(filePath);
removeEntity(type, filePath);
return;
}
/*
* 处理任务未完成的情况
*/
if (!entity.isComplete()) {
if (recordIsM3U8(record.taskType)) { // 删除ts分片文件
removeTsCache(targetFile, record.bandWidth);
} else if (record.isBlock) { // 删除分块文件
removeBlockFile(record);
}
removeTargetFile(targetFile);
} else if (removeFile) { // 处理任务完成情况
if (recordIsM3U8(record.taskType)) {
removeTsCache(targetFile, record.bandWidth);
}
removeTargetFile(targetFile);
}
// 成功与否都将删除记录
removeRecord(filePath);
}
/**
* 任务记录是否是m3u8记录
*
* @param recordType 任务记录类型
* @return true 为m3u8任务
*/
private static boolean recordIsM3U8(int recordType) {
return recordType == ITaskWrapper.M3U8_VOD || recordType == ITaskWrapper.M3U8_LIVE;
}
/**
* 删除任务记录,默认删除文件
*
* @param filePath 文件路径
* @param removeFile {@code true} 无论任务是否完成,都会删除记录和文件;
* {@code false} 如果是下载任务,并且任务已经完成,则只删除记录,不删除文件;任务未完成,记录和文件都会删除。
* 如果是上传任务,无论任务是否完成,都只删除记录
* @param type {@link IRecordHandler#TYPE_DOWNLOAD}下载任务的记录,{@link IRecordHandler#TYPE_UPLOAD}
* 上传任务的记录
* @param removeEntity {@code true} 删除任务实体,
*/
public static void delTaskRecord(String filePath, int type, boolean removeFile,
boolean removeEntity) {
if (TextUtils.isEmpty(filePath)) {
throw new NullPointerException("删除记录失败,文件路径为空");
}
if (!filePath.startsWith("/")) {
throw new IllegalArgumentException(String.format("文件路径错误filePath%s", filePath));
}
if (type != IRecordHandler.TYPE_DOWNLOAD && type != IRecordHandler.TYPE_UPLOAD) {
throw new IllegalArgumentException("任务记录类型错误");
}
AbsEntity entity;
if (type == IRecordHandler.TYPE_DOWNLOAD) {
entity = DbEntity.findFirst(DownloadEntity.class, "downloadPath=?", filePath);
} else {
entity = DbEntity.findFirst(UploadEntity.class, "filePath=?", filePath);
}
File targetFile = new File(filePath);
TaskRecord record = getTaskRecord(filePath);
if (entity == null || record == null) {
if (removeFile) {
removeTargetFile(targetFile);
}
removeRecord(filePath);
removeEntity(type, filePath);
return;
}
/*
* 处理任务未完成的情况
*/
if (!entity.isComplete()) {
if (recordIsM3U8(record.taskType)) { // 删除ts分片文件
removeTsCache(targetFile, record.bandWidth);
} else if (record.isBlock) { // 删除分块文件
removeBlockFile(record);
}
removeTargetFile(targetFile);
} else if (removeFile) { // 处理任务完成情况
if (recordIsM3U8(record.taskType)) {
removeTsCache(targetFile, record.bandWidth);
}
removeTargetFile(targetFile);
}
// 成功与否都将删除记录
removeRecord(filePath);
if (removeEntity) {
removeEntity(type, filePath);
}
}
private static void removeTargetFile(File targetFile) {
if (targetFile.exists()) {
targetFile.delete();
}
}
private static void removeRecord(String filePath) {
ALog.i(TAG, "删除任务记录");
DbEntity.deleteData(ThreadRecord.class, "taskKey=?", filePath);
DbEntity.deleteData(TaskRecord.class, "filePath=?", filePath);
// 处理m3u8实体的删除
DbEntity.deleteData(M3U8Entity.class, "filePath=?", filePath);
}
/**
* 删除实体
*
* @param type {@link IRecordHandler#TYPE_DOWNLOAD}下载任务的记录,{@link IRecordHandler#TYPE_UPLOAD}
* 上传任务的记录
*/
private static void removeEntity(int type, String filePath) {
if (type == IRecordHandler.TYPE_DOWNLOAD) {
DbEntity.deleteData(DownloadEntity.class, "downloadPath=?", filePath);
} else {
DbEntity.deleteData(UploadEntity.class, "filePath=?", filePath);
}
}
/**
* 根据文件路径获取任务记录
*/
private static TaskRecord getTaskRecord(String filePath) {
List<RecordWrapper> recordWrapper =
DbEntity.findRelationData(RecordWrapper.class, "filePath=?", filePath);
if (recordWrapper == null
|| recordWrapper.isEmpty()
|| recordWrapper.get(0) == null
|| recordWrapper.get(0).taskRecord == null) {
return null;
} else {
return recordWrapper.get(0).taskRecord;
}
}
/**
* 删除多线程分块下载的分块文件
*/
private static void removeBlockFile(TaskRecord record) {
for (int i = 0, len = record.threadNum; i < len; i++) {
File partFile = new File(String.format(IRecordHandler.SUB_PATH, record.filePath, i));
if (partFile.exists()) {
partFile.delete();
}
}
}
/**
* 删除ts文件和索引文件如果有的话
*/
private static void removeTsCache(File targetFile, long bandWidth) {
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();
public static void delNormalTaskRecord(AbsNormalEntity entity, boolean removeFile) {
switch (entity.getTaskType()) {
case ITaskWrapper.D_FTP:
case ITaskWrapper.D_HTTP:
case ITaskWrapper.D_SFTP:
case ITaskWrapper.D_TCP:
DeleteDRecord.getInstance().deleteRecord(entity, removeFile, true);
break;
case ITaskWrapper.U_FTP:
case ITaskWrapper.U_HTTP:
case ITaskWrapper.U_SFTP:
DeleteURecord.getInstance().deleteRecord(entity, removeFile, true);
break;
case ITaskWrapper.M3U8_LIVE:
case ITaskWrapper.M3U8_VOD:
DeleteM3u8Record.getInstance().deleteRecord(entity, removeFile, true);
break;
}
}
@@ -361,11 +78,31 @@ public class RecordUtil {
* 删除任务记录,默认删除文件,删除任务实体
*
* @param filePath 文件路径
* @param type {@link IRecordHandler#TYPE_DOWNLOAD}下载任务的记录,{@link IRecordHandler#TYPE_UPLOAD}
* @param removeFile {@code true} 无论任务是否完成,都会删除记录和文件;
* @param type {@link AbsTaskWrapper#getRequestType()}
* {@code false} 如果是下载任务,并且任务已经完成,则只删除记录,不删除文件;任务未完成,记录和文件都会删除。
* 如果是上传任务,无论任务是否完成,都只删除记录
* 上传任务的记录
*/
public static void delTaskRecord(String filePath, int type) {
delTaskRecord(filePath, type, false, true);
public static void delTaskRecord(String filePath, int type, boolean removeFile,
boolean removeEntity) {
switch (type) {
case ITaskWrapper.D_FTP:
case ITaskWrapper.D_HTTP:
case ITaskWrapper.D_SFTP:
case ITaskWrapper.D_TCP:
DeleteDRecord.getInstance().deleteRecord(filePath, removeFile, removeEntity);
break;
case ITaskWrapper.U_FTP:
case ITaskWrapper.U_HTTP:
case ITaskWrapper.U_SFTP:
DeleteURecord.getInstance().deleteRecord(filePath, removeFile, removeEntity);
break;
case ITaskWrapper.M3U8_LIVE:
case ITaskWrapper.M3U8_VOD:
DeleteM3u8Record.getInstance().deleteRecord(filePath, removeFile, removeEntity);
break;
}
}
/**