修复分块可能出现的问题
This commit is contained in:
@@ -276,19 +276,20 @@ import org.xml.sax.SAXException;
|
||||
/**
|
||||
* 删除任务记录
|
||||
*
|
||||
* @param type 需要删除的任务类型,1、表示单任务下载。2、表示任务组下载。3、单任务上传
|
||||
* @param key 下载为保存路径、任务组为任务组名、上传为上传文件路径
|
||||
* @param type 需要删除的任务类型,1、普通下载任务;2、组合任务;3、普通上传任务。
|
||||
* @param key type为1时,key为保存路径;type为2时,key为组合任务hash;type为3时,key为文件上传路径。
|
||||
* @param removeFile {@code true} 不仅删除任务数据库记录,还会删除已经删除完成的文件;{@code false}如果任务已经完成,只删除任务数据库记录。
|
||||
*/
|
||||
public void delRecord(int type, String key) {
|
||||
public void delRecord(int type, String key, boolean removeFile) {
|
||||
switch (type) {
|
||||
case 1:
|
||||
DbEntity.deleteData(DownloadEntity.class, "url=? and isGroupChild='false'", key);
|
||||
case 1: // 删除普通任务记录
|
||||
CommonUtil.delTaskRecord(key, 1, removeFile, true);
|
||||
break;
|
||||
case 2:
|
||||
DbEntity.deleteData(DownloadGroupEntity.class, "groupHash=?", key);
|
||||
CommonUtil.delGroupTaskRecord(key, removeFile);
|
||||
break;
|
||||
case 3:
|
||||
DbEntity.deleteData(UploadEntity.class, "filePath=?", key);
|
||||
CommonUtil.delTaskRecord(key, 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,6 +212,9 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
|
||||
|| mConstance.isCancel()
|
||||
|| mConstance.isFail()
|
||||
|| !isRunning()) {
|
||||
if (mConstance.isComplete() || mConstance.isFail()) {
|
||||
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
|
||||
}
|
||||
closeTimer();
|
||||
} else if (mConstance.CURRENT_LOCATION >= 0) {
|
||||
mListener.onProgress(mConstance.CURRENT_LOCATION);
|
||||
@@ -251,9 +254,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
|
||||
}
|
||||
|
||||
public synchronized boolean isRunning() {
|
||||
boolean b = ThreadTaskManager.getInstance().taskIsRunning(mTaskWrapper.getKey());
|
||||
//ALog.d(TAG, "isRunning = " + b);
|
||||
return b;
|
||||
return ThreadTaskManager.getInstance().taskIsRunning(mTaskWrapper.getKey());
|
||||
}
|
||||
|
||||
public synchronized void cancel() {
|
||||
@@ -271,7 +272,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
|
||||
task.cancel();
|
||||
}
|
||||
}
|
||||
ThreadTaskManager.getInstance().stopTaskThread(mTaskWrapper.getKey());
|
||||
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
@@ -292,7 +293,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
|
||||
task.stop();
|
||||
}
|
||||
}
|
||||
ThreadTaskManager.getInstance().stopTaskThread(mTaskWrapper.getKey());
|
||||
ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey());
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
@@ -382,13 +383,14 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理分块任务的记录
|
||||
* 处理分块任务的记录,分块文件(blockFileLen)长度必须需要小于等于线程区间(threadRectLen)的长度
|
||||
*/
|
||||
private void handleBlockRecord() {
|
||||
final int threadNum = mRecord.threadRecords.size();
|
||||
final long blockLen = mEntity.getFileSize() / threadNum;
|
||||
int i = 0;
|
||||
// 默认线程分块长度
|
||||
long normalRectLen = mEntity.getFileSize() / mRecord.threadRecords.size();
|
||||
for (ThreadRecord tr : mRecord.threadRecords) {
|
||||
long threadRect = tr.blockLen;
|
||||
|
||||
File temp = new File(String.format(SUB_PATH, mRecord.filePath, tr.threadId));
|
||||
if (!temp.exists()) {
|
||||
ALog.i(TAG, String.format("分块文件【%s】不存在,该分块将重新开始", temp.getPath()));
|
||||
@@ -398,33 +400,38 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
|
||||
if (tr.isComplete) {
|
||||
mCompleteThreadNum++;
|
||||
} else {
|
||||
long realLocation = i * blockLen + temp.length();
|
||||
ALog.i(TAG, String.format(
|
||||
"startLocation = %s; endLocation = %s; block = %s; tempLen = %s; i = %s",
|
||||
tr.startLocation, tr.endLocation, blockLen, temp.length(), i));
|
||||
if (tr.endLocation == realLocation) {
|
||||
"startLocation = %s; endLocation = %s; block = %s; tempLen = %s; threadId = %s",
|
||||
tr.startLocation, tr.endLocation, threadRect, temp.length(), tr.threadId));
|
||||
|
||||
long blockFileLen = temp.length(); // 磁盘中的分块文件长度
|
||||
/*
|
||||
* 检查磁盘中的分块文件
|
||||
*/
|
||||
if (blockFileLen > threadRect) {
|
||||
ALog.i(TAG, String.format("分块【%s】错误,分块长度【%s】 > 线程区间长度【%s】,将重新开始该分块",
|
||||
tr.threadId, blockFileLen, threadRect));
|
||||
temp.delete();
|
||||
tr.startLocation = tr.threadId * threadRect;
|
||||
continue;
|
||||
}
|
||||
|
||||
long realLocation =
|
||||
tr.threadId * normalRectLen + blockFileLen; //正常情况下,该线程的startLocation的位置
|
||||
/*
|
||||
* 检查记录文件
|
||||
*/
|
||||
if (blockFileLen == threadRect) {
|
||||
ALog.i(TAG, String.format("分块【%s】已完成,更新记录", temp.getPath()));
|
||||
tr.startLocation = realLocation;
|
||||
tr.startLocation = blockFileLen;
|
||||
tr.isComplete = true;
|
||||
mCompleteThreadNum++;
|
||||
} else {
|
||||
tr.isComplete = false;
|
||||
if (realLocation == tr.startLocation) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (realLocation > tr.startLocation) {
|
||||
ALog.i(TAG, String.format("修正分块【%s】的进度记录为:%s", temp.getPath(), realLocation));
|
||||
tr.startLocation = realLocation;
|
||||
} else {
|
||||
ALog.i(TAG, String.format("分块【%s】错误,将重新开始该分块", temp.getPath()));
|
||||
temp.delete();
|
||||
tr.startLocation = i * blockLen;
|
||||
}
|
||||
} else if (tr.startLocation != realLocation) { // 处理记录小于分块文件长度的情况
|
||||
ALog.i(TAG, String.format("修正分块【%s】的进度记录为:%s", temp.getPath(), realLocation));
|
||||
tr.startLocation = realLocation;
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
mTotalThreadNum = mRecord.threadRecords.size();
|
||||
mTaskWrapper.setNewTask(false);
|
||||
@@ -517,13 +524,8 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
|
||||
private void saveRecord() {
|
||||
mRecord.threadNum = mRecord.threadRecords.size();
|
||||
mRecord.save();
|
||||
for (ThreadRecord tr : mRecord.threadRecords) {
|
||||
tr.save();
|
||||
}
|
||||
}
|
||||
|
||||
public TaskRecord getRecord() {
|
||||
return mRecord;
|
||||
ALog.d(TAG, String.format("保存记录,线程记录数:%s", mRecord.threadRecords.size()));
|
||||
DbEntity.saveAll(mRecord.threadRecords);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -573,10 +575,10 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_WRAPPER ext
|
||||
long fileLength = mEntity.getFileSize();
|
||||
long blockSize = fileLength / mTotalThreadNum;
|
||||
Set<Integer> threads = new HashSet<>();
|
||||
// 如果是新任务,检查下历史记录,如果有遗留的记录,删除并删除分块文件
|
||||
if (mTaskWrapper.isNewTask()) {
|
||||
CommonUtil.delTaskRecord(getFilePath(), 1, true);
|
||||
}
|
||||
//// 如果是新任务,检查下历史记录,如果有遗留的记录,删除并删除分块文件
|
||||
//if (mTaskWrapper.isNewTask()) {
|
||||
// CommonUtil.delTaskRecord(getFilePath(), 1, true);
|
||||
//}
|
||||
|
||||
mRecord.fileLength = fileLength;
|
||||
if (mTaskWrapper.isNewTask() && !handleNewTask()) {
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.arialyy.aria.core.config.BaseTaskConfig;
|
||||
import com.arialyy.aria.core.config.DGroupConfig;
|
||||
import com.arialyy.aria.core.config.DownloadConfig;
|
||||
import com.arialyy.aria.core.config.UploadConfig;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.core.inf.AbsNormalEntity;
|
||||
import com.arialyy.aria.core.inf.AbsTaskWrapper;
|
||||
import com.arialyy.aria.core.inf.IEventListener;
|
||||
@@ -31,6 +32,7 @@ import com.arialyy.aria.exception.BaseException;
|
||||
import com.arialyy.aria.exception.FileException;
|
||||
import com.arialyy.aria.exception.TaskException;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import com.arialyy.aria.util.ErrorHelp;
|
||||
import com.arialyy.aria.util.FileUtil;
|
||||
import com.arialyy.aria.util.NetUtils;
|
||||
@@ -272,8 +274,10 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
ThreadRecord tr = getThreadRecord();
|
||||
File blockFile = getBockFile();
|
||||
if (!blockFile.exists() || blockFile.length() != tr.blockLen) {
|
||||
ALog.i(TAG, String.format("分块【%s】下载错误,即将重新下载该分块,开始位置:%s,结束位置:%s", blockFile.getName(),
|
||||
tr.startLocation, tr.endLocation));
|
||||
ALog.i(TAG,
|
||||
String.format("分块【%s】错误,blockFileLen: %s, threadRect: %s; 即将重新下载该分块,开始位置:%s,结束位置:%s",
|
||||
blockFile.getName(), blockFile.length(), tr.blockLen, tr.startLocation,
|
||||
tr.endLocation));
|
||||
if (blockFile.exists()) {
|
||||
blockFile.delete();
|
||||
ALog.i(TAG, String.format("删除分块【%s】成功", blockFile.getName()));
|
||||
@@ -405,14 +409,11 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
*/
|
||||
private void retryThis(boolean needRetry) {
|
||||
if (!NetUtils.isConnected(AriaManager.APP) && !isNotNetRetry) {
|
||||
ALog.w(TAG, String.format("任务【%s】thread__%s__重试失败,网络未连接", getConfig().TEMP_FILE.getName(),
|
||||
getConfig().THREAD_ID));
|
||||
ALog.w(TAG, String.format("任务【%s】重试失败,网络未连接", getConfig().TEMP_FILE.getName()));
|
||||
}
|
||||
if (mFailTimes < RETRY_NUM && needRetry && (NetUtils.isConnected(AriaManager.APP)
|
||||
|| isNotNetRetry) && !isBreak()) {
|
||||
ALog.w(TAG,
|
||||
String.format("任务【%s】thread__%s__正在重试", getConfig().TEMP_FILE.getName(),
|
||||
getConfig().THREAD_ID));
|
||||
ALog.w(TAG, String.format("任务【%s】正在重试", getConfig().TEMP_FILE.getName()));
|
||||
mFailTimes++;
|
||||
handleRetryRecord();
|
||||
ThreadTaskManager.getInstance().retryThread(AbsThreadTask.this);
|
||||
@@ -427,25 +428,40 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
private void handleRetryRecord() {
|
||||
if (getTaskRecord().isBlock) {
|
||||
ThreadRecord tr = getThreadRecord();
|
||||
long block = getEntity().getFileSize() / getTaskRecord().threadRecords.size();
|
||||
// 默认线程分块长度
|
||||
long normalRectLen = getEntity().getFileSize() / getTaskRecord().threadRecords.size();
|
||||
File temp = getBockFile();
|
||||
|
||||
File blockFile = getBockFile();
|
||||
if (blockFile.length() > tr.blockLen) {
|
||||
ALog.i(TAG, String.format("分块【%s】错误,将重新下载该分块", blockFile.getPath()));
|
||||
blockFile.delete();
|
||||
tr.startLocation = block * tr.threadId;
|
||||
long blockFileLen = temp.length(); // 磁盘中的分块文件长度
|
||||
long threadRect = tr.blockLen; // 当前线程的区间
|
||||
|
||||
if (!temp.exists()) {
|
||||
ALog.i(TAG, String.format("分块文件【%s】不存在,该分块将重新开始", temp.getName()));
|
||||
tr.isComplete = false;
|
||||
getConfig().START_LOCATION = tr.startLocation;
|
||||
} else if (blockFile.length() < tr.blockLen) {
|
||||
tr.startLocation = block * tr.threadId + blockFile.length();
|
||||
tr.isComplete = false;
|
||||
getConfig().START_LOCATION = tr.startLocation;
|
||||
getState().CURRENT_LOCATION = getBlockRealTotalSize();
|
||||
ALog.i(TAG, String.format("修正分块【%s】,开始位置:%s,当前进度:%s", blockFile.getPath(), tr.startLocation,
|
||||
getState().CURRENT_LOCATION));
|
||||
} else {
|
||||
getState().COMPLETE_THREAD_NUM++;
|
||||
tr.isComplete = true;
|
||||
/*
|
||||
* 检查磁盘中的分块文件
|
||||
*/
|
||||
if (blockFileLen > threadRect) {
|
||||
ALog.i(TAG, String.format("分块【%s】错误,将重新下载该分块", temp.getName()));
|
||||
temp.delete();
|
||||
tr.startLocation = normalRectLen * tr.threadId;
|
||||
tr.isComplete = false;
|
||||
getConfig().START_LOCATION = tr.startLocation;
|
||||
} else if (blockFileLen < tr.blockLen) {
|
||||
tr.startLocation = normalRectLen * tr.threadId + blockFileLen;
|
||||
tr.isComplete = false;
|
||||
getConfig().START_LOCATION = tr.startLocation;
|
||||
getState().CURRENT_LOCATION = getBlockRealTotalSize();
|
||||
ALog.i(TAG,
|
||||
String.format("修正分块【%s】,开始位置:%s,当前进度:%s", temp.getName(), tr.startLocation,
|
||||
getState().CURRENT_LOCATION));
|
||||
} else {
|
||||
ALog.i(TAG, String.format("分块【%s】已完成,更新记录", temp.getName()));
|
||||
getState().COMPLETE_THREAD_NUM++;
|
||||
tr.isComplete = true;
|
||||
}
|
||||
}
|
||||
tr.update();
|
||||
} else {
|
||||
@@ -454,6 +470,16 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送任务完成的消息,并删除任务记录
|
||||
*/
|
||||
protected synchronized void sendCompleteMsg() {
|
||||
ALog.i(TAG, String.format("任务【%s】完成", mEntity.getFileName()));
|
||||
CommonUtil.delTaskRecord(mEntity.getKey(), mEntity instanceof DownloadEntity ? 1 : 2, false,
|
||||
false);
|
||||
mListener.onComplete();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分块文件
|
||||
*
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.arialyy.aria.orm.annotation.Foreign;
|
||||
* 任务的线程记录
|
||||
*/
|
||||
public class ThreadRecord extends DbEntity {
|
||||
|
||||
@Foreign(parent = TaskRecord.class, column = "filePath", onUpdate = ActionPolicy.CASCADE, onDelete = ActionPolicy.CASCADE)
|
||||
public String key;
|
||||
|
||||
@@ -46,7 +47,7 @@ public class ThreadRecord extends DbEntity {
|
||||
/**
|
||||
* 线程id
|
||||
*/
|
||||
public int threadId = -1;
|
||||
public int threadId = 0;
|
||||
|
||||
/**
|
||||
* 分块长度
|
||||
|
||||
@@ -17,20 +17,11 @@ package com.arialyy.aria.core.common.http;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.download.DGTaskWrapper;
|
||||
import com.arialyy.aria.core.download.DTaskWrapper;
|
||||
import com.arialyy.aria.core.inf.AbsHttpFileLenAdapter;
|
||||
import com.arialyy.aria.core.inf.AbsTarget;
|
||||
import com.arialyy.aria.core.inf.AbsTaskWrapper;
|
||||
import com.arialyy.aria.core.inf.IHttpFileLenAdapter;
|
||||
import com.arialyy.aria.core.inf.IHttpHeaderDelegate;
|
||||
import com.arialyy.aria.core.upload.UTaskWrapper;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.io.File;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.net.Proxy;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
@@ -90,27 +81,11 @@ public class HttpHeaderDelegate<TARGET extends AbsTarget>
|
||||
return mTarget;
|
||||
}
|
||||
|
||||
public TARGET setFileLenAdapter(AbsHttpFileLenAdapter adapter) {
|
||||
public TARGET setFileLenAdapter(IHttpFileLenAdapter adapter) {
|
||||
if (adapter == null) {
|
||||
throw new IllegalArgumentException("adapter为空");
|
||||
}
|
||||
//try {
|
||||
// adapter.clone();
|
||||
mTarget.getTaskWrapper().asHttp().setFileLenAdapter((IHttpFileLenAdapter) adapter);
|
||||
//} catch (CloneNotSupportedException e) {
|
||||
// e.printStackTrace();
|
||||
//}
|
||||
//// 以下代码有问题,匿名内部类不能序列化
|
||||
//String objPath = String.format("%s/obj_temp/%s", AriaManager.APP.getFilesDir().getPath(),
|
||||
// adapter.hashCode());
|
||||
//CommonUtil.writeObjToFile(objPath, adapter);
|
||||
//IHttpFileLenAdapter newAdapter = (IHttpFileLenAdapter) CommonUtil.readObjFromFile(objPath);
|
||||
//File temp = new File(objPath);
|
||||
//if (temp.exists()) {
|
||||
// temp.delete();
|
||||
//}
|
||||
//mTarget.getTaskWrapper().asHttp().setFileLenAdapter(newAdapter);
|
||||
|
||||
mTarget.getTaskWrapper().asHttp().setFileLenAdapter(adapter);
|
||||
return mTarget;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.arialyy.aria.core.common.http;
|
||||
import com.arialyy.aria.core.common.RequestEnum;
|
||||
import com.arialyy.aria.core.inf.IHttpFileLenAdapter;
|
||||
import com.arialyy.aria.core.inf.ITargetHeadDelegate;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.net.CookieManager;
|
||||
import java.net.Proxy;
|
||||
import java.util.HashMap;
|
||||
|
||||
@@ -76,6 +76,7 @@ abstract class AbsGroupDelegate<TARGET extends AbsDGTarget> implements IGroupTar
|
||||
* @param newDirPath 新的文件夹路径
|
||||
*/
|
||||
void reChangeDirPath(String newDirPath) {
|
||||
ALog.d(TAG, String.format("修改新路径为:%s", newDirPath));
|
||||
List<DTaskWrapper> subTasks = mWrapper.getSubTaskWrapper();
|
||||
if (subTasks != null && !subTasks.isEmpty()) {
|
||||
List<DownloadEntity> des = new ArrayList<>();
|
||||
@@ -90,7 +91,6 @@ abstract class AbsGroupDelegate<TARGET extends AbsDGTarget> implements IGroupTar
|
||||
de.setDownloadPath(newPath);
|
||||
des.add(de);
|
||||
}
|
||||
AbsEntity.saveAll(des);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ public class BaseDListener extends BaseListener<DownloadEntity, DTaskWrapper, Do
|
||||
mEntity.setState(state);
|
||||
|
||||
if (state == IEntity.STATE_CANCEL) {
|
||||
CommonUtil.delTaskRecord(mEntity.getDownloadPath(), 1, mTaskWrapper.isRemoveFile());
|
||||
CommonUtil.delTaskRecord(mEntity.getDownloadPath(), 1, mTaskWrapper.isRemoveFile(), true);
|
||||
return;
|
||||
} else if (state == IEntity.STATE_STOP) {
|
||||
mEntity.setStopTime(System.currentTimeMillis());
|
||||
|
||||
@@ -19,7 +19,6 @@ import android.support.annotation.CheckResult;
|
||||
import android.support.annotation.NonNull;
|
||||
import com.arialyy.aria.core.common.http.HttpHeaderDelegate;
|
||||
import com.arialyy.aria.core.common.http.PostDelegate;
|
||||
import com.arialyy.aria.core.inf.AbsHttpFileLenAdapter;
|
||||
import com.arialyy.aria.core.inf.IHttpFileLenAdapter;
|
||||
import com.arialyy.aria.core.inf.IHttpHeaderDelegate;
|
||||
import com.arialyy.aria.core.manager.TaskWrapperManager;
|
||||
@@ -162,7 +161,7 @@ public class DownloadGroupTarget extends AbsDGTarget<DownloadGroupTarget> implem
|
||||
/**
|
||||
* 如果你需要使用header中特定的key来设置文件长度,或有定制文件长度的需要,那么你可以通过该方法自行处理文件长度
|
||||
*/
|
||||
public DownloadGroupTarget setFileLenAdapter(AbsHttpFileLenAdapter adapter) {
|
||||
public DownloadGroupTarget setFileLenAdapter(IHttpFileLenAdapter adapter) {
|
||||
return mHeaderDelegate.setFileLenAdapter(adapter);
|
||||
}
|
||||
|
||||
|
||||
@@ -187,7 +187,7 @@ public class DownloadReceiver extends AbsReceiver {
|
||||
* 取消注册,如果是Activity或fragment,Aria会界面销毁时自动调用该方法,不需要你手动调用。
|
||||
* 注意事项:
|
||||
* 1、如果在activity中一定要调用该方法,那么请在{@code onDestroy()}中调用
|
||||
* 2、不要在activity的{@code onStop()}中调用改方法
|
||||
* 2、不要在activity的{@code onPreStop()}中调用改方法
|
||||
* 3、如果是Dialog或popupwindow,需要你在撤销界面时调用该方法
|
||||
* 4、如果你是在Module(非android组件类)中注册了Aria,那么你也需要在Module类中调用该方法,而不是在组件类中
|
||||
* 调用销毁,详情见
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.support.annotation.NonNull;
|
||||
import com.arialyy.aria.core.common.http.GetDelegate;
|
||||
import com.arialyy.aria.core.common.http.HttpHeaderDelegate;
|
||||
import com.arialyy.aria.core.common.http.PostDelegate;
|
||||
import com.arialyy.aria.core.inf.AbsHttpFileLenAdapter;
|
||||
import com.arialyy.aria.core.inf.IHttpFileLenAdapter;
|
||||
import com.arialyy.aria.core.inf.IHttpHeaderDelegate;
|
||||
import java.net.Proxy;
|
||||
@@ -103,9 +102,8 @@ public class DownloadTarget extends AbsDTarget<DownloadTarget>
|
||||
/**
|
||||
* 如果你需要使用header中特定的key来设置文件长度,或有定制文件长度的需要,那么你可以通过该方法自行处理文件长度
|
||||
*/
|
||||
public DownloadTarget setFileLenAdapter(AbsHttpFileLenAdapter adapter) {
|
||||
public DownloadTarget setFileLenAdapter(IHttpFileLenAdapter adapter) {
|
||||
return mHeaderDelegate.setFileLenAdapter(adapter);
|
||||
//return this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -125,8 +125,6 @@ class HttpGroupDelegate extends AbsGroupDelegate<DownloadGroupTarget> {
|
||||
}
|
||||
}
|
||||
|
||||
saveEntity();
|
||||
|
||||
if (isNeedModifyPath()) {
|
||||
reChangeDirPath(getDirPathTemp());
|
||||
}
|
||||
@@ -134,10 +132,11 @@ class HttpGroupDelegate extends AbsGroupDelegate<DownloadGroupTarget> {
|
||||
if (!mSubNameTemp.isEmpty()) {
|
||||
updateSingleSubFileName();
|
||||
}
|
||||
saveEntity();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void saveEntity(){
|
||||
private void saveEntity() {
|
||||
getEntity().save();
|
||||
DbEntity.saveAll(getEntity().getSubEntities());
|
||||
}
|
||||
@@ -148,10 +147,23 @@ class HttpGroupDelegate extends AbsGroupDelegate<DownloadGroupTarget> {
|
||||
private void updateSingleSubFileName() {
|
||||
List<DTaskWrapper> entities = getTaskWrapper().getSubTaskWrapper();
|
||||
int i = 0;
|
||||
for (DTaskWrapper entity : entities) {
|
||||
for (DTaskWrapper taskWrapper : entities) {
|
||||
if (i < mSubNameTemp.size()) {
|
||||
String newName = mSubNameTemp.get(i);
|
||||
updateSingleSubFileName(entity, newName);
|
||||
DownloadEntity entity = taskWrapper.getEntity();
|
||||
if (!newName.equals(entity.getFileName())) {
|
||||
String oldPath = getEntity().getDirPath() + "/" + entity.getFileName();
|
||||
String newPath = getEntity().getDirPath() + "/" + newName;
|
||||
if (DbEntity.checkDataExist(DownloadEntity.class, "downloadPath=? or isComplete='true'",
|
||||
newPath)) {
|
||||
ALog.w(TAG, String.format("更新文件名失败,路径【%s】已存在或文件已下载", newPath));
|
||||
return;
|
||||
}
|
||||
|
||||
CommonUtil.modifyTaskRecord(oldPath, newPath);
|
||||
entity.setDownloadPath(newPath);
|
||||
entity.setFileName(newName);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
@@ -203,27 +215,6 @@ class HttpGroupDelegate extends AbsGroupDelegate<DownloadGroupTarget> {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新单个子任务文件名
|
||||
*/
|
||||
private void updateSingleSubFileName(DTaskWrapper taskEntity, String newName) {
|
||||
DownloadEntity entity = taskEntity.getEntity();
|
||||
if (!newName.equals(entity.getFileName())) {
|
||||
String oldPath = getEntity().getDirPath() + "/" + entity.getFileName();
|
||||
String newPath = getEntity().getDirPath() + "/" + newName;
|
||||
if (DbEntity.checkDataExist(DownloadEntity.class, "downloadPath=? or isComplete='true'",
|
||||
newPath)) {
|
||||
ALog.w(TAG, String.format("更新文件名失败,路径【%s】已存在或文件已下载", newPath));
|
||||
return;
|
||||
}
|
||||
|
||||
CommonUtil.modifyTaskRecord(oldPath, newPath);
|
||||
entity.setDownloadPath(newPath);
|
||||
entity.setFileName(newName);
|
||||
entity.update();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果用户设置了子任务文件名,检查子任务文件名
|
||||
*
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.arialyy.aria.exception.BaseException;
|
||||
import com.arialyy.aria.exception.TaskException;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -59,6 +60,14 @@ public class Downloader extends AbsFileer<DownloadEntity, DTaskWrapper> {
|
||||
mTempFile.delete();
|
||||
}
|
||||
//CommonUtil.createFile(mTempFile.getPath());
|
||||
} else {
|
||||
for (int i = 0; i < mTotalThreadNum; i++) {
|
||||
File blockFile = new File(String.format(AbsFileer.SUB_PATH, mTempFile.getPath(), i));
|
||||
if (blockFile.exists()) {
|
||||
ALog.d(TAG, String.format("分块【%s】已经存在,将删除该分块", i));
|
||||
blockFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
BufferedRandomAccessFile file = null;
|
||||
try {
|
||||
|
||||
@@ -147,8 +147,7 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
getState().TASK_RECORD.deleteData();
|
||||
mListener.onComplete();
|
||||
sendCompleteMsg();
|
||||
}
|
||||
if (getState().isFail()) {
|
||||
mListener.onFail(false,
|
||||
|
||||
@@ -89,6 +89,8 @@ public class HttpFileInfoThread implements Runnable {
|
||||
if (conn != null) {
|
||||
conn.disconnect();
|
||||
}
|
||||
// 销毁文件长度适配器
|
||||
mTaskWrapper.asHttp().setFileLenAdapter(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,6 +115,8 @@ public class HttpFileInfoThread implements Runnable {
|
||||
IHttpFileLenAdapter lenAdapter = mTaskWrapper.asHttp().getFileLenAdapter();
|
||||
if (lenAdapter == null) {
|
||||
lenAdapter = new FileLenAdapter();
|
||||
} else {
|
||||
ALog.d(TAG, "使用自定义adapter");
|
||||
}
|
||||
long len = lenAdapter.handleFileLen(conn.getHeaderFields());
|
||||
|
||||
@@ -214,8 +218,6 @@ public class HttpFileInfoThread implements Runnable {
|
||||
onFileInfoCallback.onComplete(mEntity.getUrl(), info);
|
||||
}
|
||||
mEntity.update();
|
||||
// 销毁文件长度适配器
|
||||
mTaskWrapper.asHttp().setFileLenAdapter(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -176,7 +176,8 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
handleComplete();
|
||||
} catch (IOException e) {
|
||||
fail(mChildCurrentLocation, new AriaIOException(TAG,
|
||||
String.format("文件下载失败,savePath: %s, url: %s", getEntity().getDownloadPath(), getConfig().URL),
|
||||
String.format("文件下载失败,savePath: %s, url: %s", getEntity().getDownloadPath(),
|
||||
getConfig().URL),
|
||||
e));
|
||||
} finally {
|
||||
if (fos != null) {
|
||||
@@ -228,7 +229,8 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
handleComplete();
|
||||
} catch (IOException e) {
|
||||
fail(mChildCurrentLocation, new AriaIOException(TAG,
|
||||
String.format("文件下载失败,savePath: %s, url: %s", getEntity().getDownloadPath(), getConfig().URL),
|
||||
String.format("文件下载失败,savePath: %s, url: %s", getEntity().getDownloadPath(),
|
||||
getConfig().URL),
|
||||
e));
|
||||
} finally {
|
||||
try {
|
||||
@@ -278,8 +280,7 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
return;
|
||||
}
|
||||
if (getTaskWrapper().asHttp().isChunked()) {
|
||||
ALog.i(TAG, "任务下载完成");
|
||||
mListener.onComplete();
|
||||
sendCompleteMsg();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -300,8 +301,7 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
getState().TASK_RECORD.deleteData();
|
||||
mListener.onComplete();
|
||||
sendCompleteMsg();
|
||||
}
|
||||
if (getState().isFail()) {
|
||||
mListener.onFail(false,
|
||||
@@ -310,8 +310,7 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
getEntity().getDownloadPath(), getEntity().getUrl())));
|
||||
}
|
||||
} else {
|
||||
ALog.i(TAG, "任务下载完成");
|
||||
mListener.onComplete();
|
||||
sendCompleteMsg();
|
||||
}
|
||||
} else {
|
||||
getState().FAIL_NUM++;
|
||||
|
||||
@@ -23,7 +23,6 @@ import com.arialyy.aria.core.download.DTaskWrapper;
|
||||
import com.arialyy.aria.core.inf.AbsEntity;
|
||||
import com.arialyy.aria.core.inf.AbsTaskWrapper;
|
||||
import com.arialyy.aria.core.inf.IDownloadListener;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.exception.BaseException;
|
||||
|
||||
/**
|
||||
|
||||
@@ -152,7 +152,7 @@ public abstract class AbsGroupUtil implements IUtil, Runnable {
|
||||
private SubDownloadLoader getDownloader(String url) {
|
||||
SubDownloadLoader d = mExeLoader.get(url);
|
||||
if (d == null) {
|
||||
return createSubLoader(mCache.get(url));
|
||||
return createAndStartSubLoader(mCache.get(url));
|
||||
}
|
||||
return d;
|
||||
}
|
||||
@@ -172,38 +172,34 @@ public abstract class AbsGroupUtil implements IUtil, Runnable {
|
||||
@Override public void cancel() {
|
||||
isCancel = true;
|
||||
closeTimer();
|
||||
onCancel();
|
||||
Set<String> keys = mExeLoader.keySet();
|
||||
mSubQueue.clear();
|
||||
onPreCancel();
|
||||
|
||||
for (String key : keys) {
|
||||
SubDownloadLoader loader = mExeLoader.get(key);
|
||||
if (loader != null && loader.isRunning()) {
|
||||
loader.cancel();
|
||||
}
|
||||
}
|
||||
mSubQueue.removeAllTask();
|
||||
mListener.onCancel();
|
||||
}
|
||||
|
||||
public void onCancel() {
|
||||
/**
|
||||
* onCancel前的操作
|
||||
*/
|
||||
public void onPreCancel() {
|
||||
|
||||
}
|
||||
|
||||
@Override public void stop() {
|
||||
isStop = true;
|
||||
closeTimer();
|
||||
if (onStop()) {
|
||||
if (onPreStop()) {
|
||||
return;
|
||||
}
|
||||
mSubQueue.stopAllTask();
|
||||
}
|
||||
|
||||
/**
|
||||
* 子类的钩子
|
||||
* onStop前的操作
|
||||
*
|
||||
* @return 返回{@code true},直接回调{@link IDownloadGroupListener#onStop(long)}
|
||||
*/
|
||||
protected boolean onStop() {
|
||||
protected boolean onPreStop() {
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -286,8 +282,8 @@ public abstract class AbsGroupUtil implements IUtil, Runnable {
|
||||
/**
|
||||
* 创建并启动子任务下载器
|
||||
*/
|
||||
SubDownloadLoader createSubLoader(DTaskWrapper taskWrapper) {
|
||||
return createSubLoader(taskWrapper, true);
|
||||
SubDownloadLoader createAndStartSubLoader(DTaskWrapper taskWrapper) {
|
||||
return createAndStartSubLoader(taskWrapper, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -295,28 +291,10 @@ public abstract class AbsGroupUtil implements IUtil, Runnable {
|
||||
*
|
||||
* @param needGetFileInfo {@code true} 需要获取文件信息。{@code false} 不需要获取文件信息
|
||||
*/
|
||||
SubDownloadLoader createSubLoader(DTaskWrapper taskWrapper, boolean needGetFileInfo) {
|
||||
if (getTaskType() == HTTP_GROUP) {
|
||||
cloneHeader(taskWrapper);
|
||||
}
|
||||
SubDownloadLoader createAndStartSubLoader(DTaskWrapper taskWrapper, boolean needGetFileInfo) {
|
||||
SubDownloadLoader loader = new SubDownloadLoader(mScheduler, taskWrapper, needGetFileInfo);
|
||||
mExeLoader.put(loader.getKey(), loader);
|
||||
mSubQueue.startTask(loader);
|
||||
return loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* 子任务使用父包裹器的属性
|
||||
*/
|
||||
private void cloneHeader(DTaskWrapper taskWrapper) {
|
||||
HttpTaskDelegate groupDelegate = mGTWrapper.asHttp();
|
||||
HttpTaskDelegate subDelegate = taskWrapper.asHttp();
|
||||
|
||||
// 设置属性
|
||||
subDelegate.setFileLenAdapter(groupDelegate.getFileLenAdapter());
|
||||
subDelegate.setRequestEnum(groupDelegate.getRequestEnum());
|
||||
subDelegate.setHeaders(groupDelegate.getHeaders());
|
||||
subDelegate.setProxy(groupDelegate.getProxy());
|
||||
subDelegate.setParams(groupDelegate.getParams());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.arialyy.aria.core.download.group;
|
||||
import com.arialyy.aria.core.common.CompleteInfo;
|
||||
import com.arialyy.aria.core.common.IUtil;
|
||||
import com.arialyy.aria.core.common.OnFileInfoCallback;
|
||||
import com.arialyy.aria.core.common.http.HttpTaskDelegate;
|
||||
import com.arialyy.aria.core.download.DGTaskWrapper;
|
||||
import com.arialyy.aria.core.download.DTaskWrapper;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
@@ -49,11 +50,11 @@ public class DownloadGroupUtil extends AbsGroupUtil implements IUtil {
|
||||
return HTTP_GROUP;
|
||||
}
|
||||
|
||||
@Override public void onCancel() {
|
||||
super.onCancel();
|
||||
@Override public void onPreCancel() {
|
||||
super.onPreCancel();
|
||||
}
|
||||
|
||||
@Override protected boolean onStop() {
|
||||
@Override protected boolean onPreStop() {
|
||||
// 如果是isUnknownSize()标志,并且获取大小没有完成,则直接回调onStop
|
||||
if (mPool != null && !getLenComplete) {
|
||||
ALog.d(TAG, "获取长度未完成的情况下,停止组合任务");
|
||||
@@ -83,7 +84,7 @@ public class DownloadGroupUtil extends AbsGroupUtil implements IUtil {
|
||||
} else {
|
||||
for (DTaskWrapper wrapper : mGTWrapper.getSubTaskWrapper()) {
|
||||
if (wrapper.getState() != IEntity.STATE_COMPLETE) {
|
||||
createSubLoader(wrapper);
|
||||
createAndStartSubLoader(wrapper);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,10 +100,16 @@ public class DownloadGroupUtil extends AbsGroupUtil implements IUtil {
|
||||
int failCount;
|
||||
|
||||
@Override public void run() {
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
for (DTaskWrapper dTaskWrapper : mGTWrapper.getSubTaskWrapper()) {
|
||||
cloneHeader(dTaskWrapper);
|
||||
mPool.submit(new HttpFileInfoThread(dTaskWrapper, new OnFileInfoCallback() {
|
||||
@Override public void onComplete(String url, CompleteInfo info) {
|
||||
createSubLoader((DTaskWrapper) info.wrapper, false);
|
||||
createAndStartSubLoader((DTaskWrapper) info.wrapper, false);
|
||||
count++;
|
||||
checkGetSizeComplete(count, failCount);
|
||||
}
|
||||
@@ -133,15 +140,30 @@ public class DownloadGroupUtil extends AbsGroupUtil implements IUtil {
|
||||
mGTWrapper.getEntity().setConvertFileSize(CommonUtil.formatFileSize(size));
|
||||
mGTWrapper.getEntity().setFileSize(size);
|
||||
mGTWrapper.getEntity().update();
|
||||
mGTWrapper.asHttp().setFileLenAdapter(null);
|
||||
getLenComplete = true;
|
||||
ALog.d(TAG, String.format("获取组合任务长度完成,len:%s", size));
|
||||
} else if (failCount == mGTWrapper.getSubTaskWrapper().size()) {
|
||||
mListener.onFail(true, new AriaIOException(TAG, "获取子任务长度失败"));
|
||||
}
|
||||
|
||||
mGTWrapper.asHttp().setFileLenAdapter(null);
|
||||
synchronized (LOCK) {
|
||||
LOCK.notify();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 子任务使用父包裹器的属性
|
||||
*/
|
||||
private void cloneHeader(DTaskWrapper taskWrapper) {
|
||||
HttpTaskDelegate groupDelegate = mGTWrapper.asHttp();
|
||||
HttpTaskDelegate subDelegate = taskWrapper.asHttp();
|
||||
|
||||
// 设置属性
|
||||
subDelegate.setFileLenAdapter(groupDelegate.getFileLenAdapter());
|
||||
subDelegate.setRequestEnum(groupDelegate.getRequestEnum());
|
||||
subDelegate.setHeaders(groupDelegate.getHeaders());
|
||||
subDelegate.setProxy(groupDelegate.getProxy());
|
||||
subDelegate.setParams(groupDelegate.getParams());
|
||||
}
|
||||
}
|
||||
@@ -60,7 +60,7 @@ public class FtpDirDownloadUtil extends AbsGroupUtil {
|
||||
private void startDownload() {
|
||||
for (DTaskWrapper wrapper : mGTWrapper.getSubTaskWrapper()) {
|
||||
if (wrapper.getState() != IEntity.STATE_COMPLETE) {
|
||||
createSubLoader(wrapper);
|
||||
createAndStartSubLoader(wrapper);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,10 +63,16 @@ interface ISubQueue<Fileer extends IUtil> {
|
||||
void removeTaskFromExecQ(Fileer fileer);
|
||||
|
||||
/**
|
||||
* 删除任务
|
||||
* 删除任务,如果缓存队列中有等待中的任务,则启动等待中的任务
|
||||
*/
|
||||
void removeTask(Fileer fileer);
|
||||
|
||||
/**
|
||||
* 停止全部任务,停止所有正在执行的任务,并清空所有等待中的端服务
|
||||
*/
|
||||
void removeAllTask();
|
||||
|
||||
|
||||
/**
|
||||
* 获取下一个任务
|
||||
*/
|
||||
|
||||
@@ -168,6 +168,18 @@ class SimpleSubQueue implements ISubQueue<SubDownloadLoader> {
|
||||
mCache.remove(fileer.getKey());
|
||||
}
|
||||
|
||||
@Override public void removeAllTask() {
|
||||
ALog.d(TAG, "删除组合任务");
|
||||
Set<String> keys = mExec.keySet();
|
||||
for (String key : keys) {
|
||||
SubDownloadLoader loader = mExec.get(key);
|
||||
if (loader != null) {
|
||||
ALog.d(TAG, String.format("停止子任务:%s", loader.getEntity().getFileName()));
|
||||
loader.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public SubDownloadLoader getNextTask() {
|
||||
Iterator<String> keys = mCache.keySet().iterator();
|
||||
if (keys.hasNext()) {
|
||||
|
||||
@@ -87,8 +87,10 @@ class SubDownloadLoader implements IUtil {
|
||||
}
|
||||
|
||||
@Override public void cancel() {
|
||||
if (mDownloader != null) {
|
||||
if (mDownloader != null && isRunning()) {
|
||||
mDownloader.cancel();
|
||||
} else {
|
||||
mSchedulers.obtainMessage(ISchedulers.CANCEL, this).sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.arialyy.aria.core.inf;
|
||||
|
||||
public abstract class AbsHttpFileLenAdapter implements IHttpFileLenAdapter {
|
||||
|
||||
@Override public Object clone() throws CloneNotSupportedException {
|
||||
//AbsHttpFileLenAdapter newAdapter = super.clone();
|
||||
|
||||
return super.clone();
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* 线程管理器
|
||||
* 线程任务管理器
|
||||
*/
|
||||
public class ThreadTaskManager {
|
||||
private static volatile ThreadTaskManager INSTANCE = null;
|
||||
@@ -80,7 +80,7 @@ public class ThreadTaskManager {
|
||||
*
|
||||
* @param key 任务对应的key{@link AbsTaskWrapper#getKey()}
|
||||
*/
|
||||
public synchronized void stopTaskThread(String key) {
|
||||
public synchronized void removeTaskThread(String key) {
|
||||
if (mExePool.isShutdown()) {
|
||||
ALog.e(TAG, "线程池已经关闭");
|
||||
return;
|
||||
|
||||
@@ -36,7 +36,7 @@ class BaseUListener extends BaseListener<UploadEntity, UTaskWrapper, UploadTask>
|
||||
mTaskWrapper.setState(state);
|
||||
mEntity.setState(state);
|
||||
if (state == IEntity.STATE_CANCEL) {
|
||||
CommonUtil.delTaskRecord(mEntity.getFilePath(), 2, mTaskWrapper.isRemoveFile());
|
||||
CommonUtil.delTaskRecord(mEntity.getFilePath(), 2, mTaskWrapper.isRemoveFile(), true);
|
||||
} else if (state == IEntity.STATE_STOP) {
|
||||
mEntity.setStopTime(System.currentTimeMillis());
|
||||
} else if (state == IEntity.STATE_COMPLETE) {
|
||||
|
||||
@@ -96,8 +96,7 @@ class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UTaskWrapper> {
|
||||
writeConfig(true, getConfig().END_LOCATION);
|
||||
getState().COMPLETE_THREAD_NUM++;
|
||||
if (getState().isComplete()) {
|
||||
getState().TASK_RECORD.deleteData();
|
||||
mListener.onComplete();
|
||||
sendCompleteMsg();
|
||||
}
|
||||
if (getState().isFail()) {
|
||||
mListener.onFail(false, new TaskException(TAG,
|
||||
|
||||
@@ -101,7 +101,7 @@ class HttpThreadTask extends AbsThreadTask<UploadEntity, UTaskWrapper> {
|
||||
}
|
||||
uploadFile(writer, taskDelegate.getAttachment(), uploadFile);
|
||||
getEntity().setResponseStr(finish(writer));
|
||||
mListener.onComplete();
|
||||
sendCompleteMsg();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(new TaskException(TAG,
|
||||
|
||||
@@ -36,7 +36,7 @@ class DBConfig {
|
||||
static boolean DEBUG = false;
|
||||
static Map<String, Class> mapping = new HashMap<>();
|
||||
static String DB_NAME;
|
||||
static int VERSION = 45;
|
||||
static int VERSION = 46;
|
||||
|
||||
/**
|
||||
* 是否将数据库保存在Sd卡,{@code true} 是
|
||||
|
||||
@@ -1,290 +1,291 @@
|
||||
/*
|
||||
* 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.orm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2015/11/2. 所有数据库实体父类
|
||||
*/
|
||||
public abstract class DbEntity {
|
||||
private static final Object LOCK = new Object();
|
||||
protected long rowID = -1;
|
||||
|
||||
protected DbEntity() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询关联数据
|
||||
* <code>
|
||||
* DbEntity.findRelationData(DGEntityWrapper.class, "downloadUrl=?", downloadUrl);
|
||||
* </code>
|
||||
*
|
||||
* @param expression 查询条件
|
||||
*/
|
||||
public static <T extends AbsDbWrapper> List<T> findRelationData(Class<T> clazz,
|
||||
String... expression) {
|
||||
return DelegateWrapper.getInstance().findRelationData(clazz, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询关联数据
|
||||
*
|
||||
* <code>
|
||||
* DbEntity.findRelationData(DGEntityWrapper.class, 0, 10, "downloadUrl=?", downloadUrl);
|
||||
* </code>
|
||||
*
|
||||
* @param expression 查询条件
|
||||
* @param page 需要查询的页数,从1开始,如果page小于1 或 num 小于1,返回null
|
||||
* @param num 每页返回的数量
|
||||
* @return 没有数据返回null,如果页数大于总页数,返回null
|
||||
*/
|
||||
public static <T extends AbsDbWrapper> List<T> findRelationData(Class<T> clazz, int page, int num,
|
||||
String... expression) {
|
||||
if (page < 1 || num < 1) {
|
||||
return null;
|
||||
}
|
||||
return DelegateWrapper.getInstance().findRelationData(clazz, page, num, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查某个字段的值是否存在
|
||||
*
|
||||
* @param expression 字段和值"downloadPath=?"
|
||||
* @return {@code true}该字段的对应的value已存在
|
||||
*/
|
||||
public static boolean checkDataExist(Class clazz, String... expression) {
|
||||
return DelegateWrapper.getInstance().checkDataExist(clazz, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空表数据
|
||||
*/
|
||||
public static <T extends DbEntity> void clean(Class<T> clazz) {
|
||||
DelegateWrapper.getInstance().clean(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接执行sql语句
|
||||
*/
|
||||
public static void exeSql(String sql) {
|
||||
DelegateWrapper.getInstance().exeSql(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有数据
|
||||
*
|
||||
* @return 没有数据返回null
|
||||
*/
|
||||
public static <T extends DbEntity> List<T> findAllData(Class<T> clazz) {
|
||||
return DelegateWrapper.getInstance().findAllData(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询第一条数据
|
||||
*/
|
||||
public static <T extends DbEntity> T findFirst(Class<T> clazz) {
|
||||
List<T> list = findAllData(clazz);
|
||||
return (list == null || list.size() == 0) ? null : list.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询一组数据
|
||||
* <code>
|
||||
* DbEntity.findFirst(DownloadEntity.class, "downloadUrl=?", downloadUrl);
|
||||
* </code>
|
||||
*
|
||||
* @return 没有数据返回null
|
||||
*/
|
||||
public static <T extends DbEntity> List<T> findDatas(Class<T> clazz, String... expression) {
|
||||
return DelegateWrapper.getInstance().findData(clazz, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询数据
|
||||
* <code>
|
||||
* DbEntity.findFirst(DownloadEntity.class, 0, 10, "downloadUrl=?", downloadUrl);
|
||||
* </code>
|
||||
*
|
||||
* @param page 需要查询的页数,从1开始,如果page小于1 或 num 小于1,返回null
|
||||
* @param num 每页返回的数量
|
||||
* @return 没有数据返回null,如果页数大于总页数,返回null
|
||||
*/
|
||||
public static <T extends DbEntity> List<T> findDatas(Class<T> clazz, int page, int num,
|
||||
String... expression) {
|
||||
if (page < 1 || num < 1) {
|
||||
return null;
|
||||
}
|
||||
return DelegateWrapper.getInstance().findData(clazz, page, num, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* 模糊查询一组数据
|
||||
* <code>
|
||||
* DbEntity.findDataByFuzzy(DownloadEntity.class, "downloadUrl like http://");
|
||||
* </code>
|
||||
*
|
||||
* @return 没有数据返回null
|
||||
*/
|
||||
public static <T extends DbEntity> List<T> findDataByFuzzy(Class<T> clazz, String conditions) {
|
||||
return DelegateWrapper.getInstance().findDataByFuzzy(clazz, conditions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 模糊查询一组数据
|
||||
* <code>
|
||||
* DbEntity.findDataByFuzzy(DownloadEntity.class, 0, 10, "downloadUrl like http://");
|
||||
* </code>
|
||||
*
|
||||
* @param page 需要查询的页数,从1开始,如果page小于1 或 num 小于1,返回null
|
||||
* @param num 每页返回的数量
|
||||
* @return 没有数据返回null,如果页数大于总页数,返回null
|
||||
*/
|
||||
public static <T extends DbEntity> List<T> findDataByFuzzy(Class<T> clazz, int page, int num,
|
||||
String conditions) {
|
||||
return DelegateWrapper.getInstance().findDataByFuzzy(clazz, page, num, conditions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询一行数据
|
||||
* <code>
|
||||
* DbEntity.findFirst(DownloadEntity.class, "downloadUrl=?", downloadUrl);
|
||||
* </code>
|
||||
*
|
||||
* @return 没有数据返回null
|
||||
*/
|
||||
public static <T extends DbEntity> T findFirst(Class<T> clazz, String... expression) {
|
||||
DelegateWrapper util = DelegateWrapper.getInstance();
|
||||
List<T> datas = util.findData(clazz, expression);
|
||||
return datas == null ? null : datas.size() > 0 ? datas.get(0) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入多条数据
|
||||
*/
|
||||
public static void insertManyData(List<DbEntity> entities) {
|
||||
checkListData(entities);
|
||||
DelegateWrapper.getInstance().insertManyData(entities);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改多条数据
|
||||
*/
|
||||
public static void updateManyData(List<DbEntity> entities) {
|
||||
checkListData(entities);
|
||||
DelegateWrapper.getInstance().updateManyData(entities);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存多条数据,通过rowID来判断记录存在以否,如果数据库已有记录,则更新该记录;如果数据库中没有记录,则保存该记录
|
||||
*/
|
||||
public static <T extends DbEntity> void saveAll(List<T> entities) {
|
||||
checkListData(entities);
|
||||
List<DbEntity> insertD = new ArrayList<>();
|
||||
List<DbEntity> updateD = new ArrayList<>();
|
||||
DelegateWrapper wrapper = DelegateWrapper.getInstance();
|
||||
for (DbEntity entity : entities) {
|
||||
if (entity.rowID == -1) {
|
||||
insertD.add(entity);
|
||||
continue;
|
||||
}
|
||||
if (wrapper.isExist(entity.getClass(), entity.rowID)) {
|
||||
updateD.add(entity);
|
||||
} else {
|
||||
insertD.add(entity);
|
||||
}
|
||||
}
|
||||
if (!insertD.isEmpty()) {
|
||||
wrapper.insertManyData(insertD);
|
||||
} else {
|
||||
wrapper.updateManyData(updateD);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查批量操作的列表数据,如果数据为空,抛出{@link NullPointerException}
|
||||
*/
|
||||
private static <T extends DbEntity> void checkListData(List<T> entities) {
|
||||
if (entities == null || entities.isEmpty()) {
|
||||
throw new NullPointerException("列表数据为空");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除当前数据
|
||||
*/
|
||||
public void deleteData() {
|
||||
deleteData(getClass(), "rowid=?", rowID + "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件删除数据
|
||||
* <code>
|
||||
* DbEntity.deleteData(DownloadEntity.class, "downloadUrl=?", downloadUrl);
|
||||
* </code>
|
||||
*/
|
||||
public static <T extends DbEntity> void deleteData(Class<T> clazz, String... expression) {
|
||||
DelegateWrapper util = DelegateWrapper.getInstance();
|
||||
util.delData(clazz, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改数据
|
||||
*/
|
||||
public void update() {
|
||||
DelegateWrapper.getInstance().updateData(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存自身,如果表中已经有数据,则更新数据,否则插入数据 只有 target中checkEntity成功后才能保存,创建实体部分也不允许保存
|
||||
*/
|
||||
public void save() {
|
||||
synchronized (LOCK) {
|
||||
if (thisIsExist()) {
|
||||
update();
|
||||
} else {
|
||||
insert();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找数据在表中是否存在
|
||||
*/
|
||||
private boolean thisIsExist() {
|
||||
DelegateWrapper util = DelegateWrapper.getInstance();
|
||||
return rowID != -1 && util.isExist(getClass(), rowID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 表是否存在
|
||||
*
|
||||
* @return {@code true} 存在
|
||||
*/
|
||||
public static boolean tableExists(Class<DbEntity> clazz) {
|
||||
return DelegateWrapper.getInstance().tableExists(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入数据,只有 target中checkEntity成功后才能插入,创建实体部分也不允许操作
|
||||
*/
|
||||
public void insert() {
|
||||
DelegateWrapper.getInstance().insertData(this);
|
||||
}
|
||||
/*
|
||||
* 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.orm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2015/11/2. 所有数据库实体父类
|
||||
*/
|
||||
public abstract class DbEntity {
|
||||
private static final Object LOCK = new Object();
|
||||
protected long rowID = -1;
|
||||
|
||||
protected DbEntity() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询关联数据
|
||||
* <code>
|
||||
* DbEntity.findRelationData(DGEntityWrapper.class, "downloadUrl=?", downloadUrl);
|
||||
* </code>
|
||||
*
|
||||
* @param expression 查询条件
|
||||
*/
|
||||
public static <T extends AbsDbWrapper> List<T> findRelationData(Class<T> clazz,
|
||||
String... expression) {
|
||||
return DelegateWrapper.getInstance().findRelationData(clazz, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询关联数据
|
||||
*
|
||||
* <code>
|
||||
* DbEntity.findRelationData(DGEntityWrapper.class, 0, 10, "downloadUrl=?", downloadUrl);
|
||||
* </code>
|
||||
*
|
||||
* @param expression 查询条件
|
||||
* @param page 需要查询的页数,从1开始,如果page小于1 或 num 小于1,返回null
|
||||
* @param num 每页返回的数量
|
||||
* @return 没有数据返回null,如果页数大于总页数,返回null
|
||||
*/
|
||||
public static <T extends AbsDbWrapper> List<T> findRelationData(Class<T> clazz, int page, int num,
|
||||
String... expression) {
|
||||
if (page < 1 || num < 1) {
|
||||
return null;
|
||||
}
|
||||
return DelegateWrapper.getInstance().findRelationData(clazz, page, num, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查某个字段的值是否存在
|
||||
*
|
||||
* @param expression 字段和值"downloadPath=?"
|
||||
* @return {@code true}该字段的对应的value已存在
|
||||
*/
|
||||
public static boolean checkDataExist(Class clazz, String... expression) {
|
||||
return DelegateWrapper.getInstance().checkDataExist(clazz, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空表数据
|
||||
*/
|
||||
public static <T extends DbEntity> void clean(Class<T> clazz) {
|
||||
DelegateWrapper.getInstance().clean(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接执行sql语句
|
||||
*/
|
||||
public static void exeSql(String sql) {
|
||||
DelegateWrapper.getInstance().exeSql(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有数据
|
||||
*
|
||||
* @return 没有数据返回null
|
||||
*/
|
||||
public static <T extends DbEntity> List<T> findAllData(Class<T> clazz) {
|
||||
return DelegateWrapper.getInstance().findAllData(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询第一条数据
|
||||
*/
|
||||
public static <T extends DbEntity> T findFirst(Class<T> clazz) {
|
||||
List<T> list = findAllData(clazz);
|
||||
return (list == null || list.size() == 0) ? null : list.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询一组数据
|
||||
* <code>
|
||||
* DbEntity.findFirst(DownloadEntity.class, "downloadUrl=?", downloadUrl);
|
||||
* </code>
|
||||
*
|
||||
* @return 没有数据返回null
|
||||
*/
|
||||
public static <T extends DbEntity> List<T> findDatas(Class<T> clazz, String... expression) {
|
||||
return DelegateWrapper.getInstance().findData(clazz, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询数据
|
||||
* <code>
|
||||
* DbEntity.findFirst(DownloadEntity.class, 0, 10, "downloadUrl=?", downloadUrl);
|
||||
* </code>
|
||||
*
|
||||
* @param page 需要查询的页数,从1开始,如果page小于1 或 num 小于1,返回null
|
||||
* @param num 每页返回的数量
|
||||
* @return 没有数据返回null,如果页数大于总页数,返回null
|
||||
*/
|
||||
public static <T extends DbEntity> List<T> findDatas(Class<T> clazz, int page, int num,
|
||||
String... expression) {
|
||||
if (page < 1 || num < 1) {
|
||||
return null;
|
||||
}
|
||||
return DelegateWrapper.getInstance().findData(clazz, page, num, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* 模糊查询一组数据
|
||||
* <code>
|
||||
* DbEntity.findDataByFuzzy(DownloadEntity.class, "downloadUrl like http://");
|
||||
* </code>
|
||||
*
|
||||
* @return 没有数据返回null
|
||||
*/
|
||||
public static <T extends DbEntity> List<T> findDataByFuzzy(Class<T> clazz, String conditions) {
|
||||
return DelegateWrapper.getInstance().findDataByFuzzy(clazz, conditions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 模糊查询一组数据
|
||||
* <code>
|
||||
* DbEntity.findDataByFuzzy(DownloadEntity.class, 0, 10, "downloadUrl like http://");
|
||||
* </code>
|
||||
*
|
||||
* @param page 需要查询的页数,从1开始,如果page小于1 或 num 小于1,返回null
|
||||
* @param num 每页返回的数量
|
||||
* @return 没有数据返回null,如果页数大于总页数,返回null
|
||||
*/
|
||||
public static <T extends DbEntity> List<T> findDataByFuzzy(Class<T> clazz, int page, int num,
|
||||
String conditions) {
|
||||
return DelegateWrapper.getInstance().findDataByFuzzy(clazz, page, num, conditions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询一行数据
|
||||
* <code>
|
||||
* DbEntity.findFirst(DownloadEntity.class, "downloadUrl=?", downloadUrl);
|
||||
* </code>
|
||||
*
|
||||
* @return 没有数据返回null
|
||||
*/
|
||||
public static <T extends DbEntity> T findFirst(Class<T> clazz, String... expression) {
|
||||
DelegateWrapper util = DelegateWrapper.getInstance();
|
||||
List<T> datas = util.findData(clazz, expression);
|
||||
return datas == null ? null : datas.size() > 0 ? datas.get(0) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入多条数据
|
||||
*/
|
||||
public static <T extends DbEntity> void insertManyData(List<T> entities) {
|
||||
checkListData(entities);
|
||||
DelegateWrapper.getInstance().insertManyData(entities);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改多条数据
|
||||
*/
|
||||
public static <T extends DbEntity> void updateManyData(List<T> entities) {
|
||||
checkListData(entities);
|
||||
DelegateWrapper.getInstance().updateManyData(entities);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存多条数据,通过rowID来判断记录存在以否,如果数据库已有记录,则更新该记录;如果数据库中没有记录,则保存该记录
|
||||
*/
|
||||
public static <T extends DbEntity> void saveAll(List<T> entities) {
|
||||
checkListData(entities);
|
||||
List<T> insertD = new ArrayList<>();
|
||||
List<T> updateD = new ArrayList<>();
|
||||
DelegateWrapper wrapper = DelegateWrapper.getInstance();
|
||||
for (T entity : entities) {
|
||||
if (entity.rowID == -1) {
|
||||
insertD.add(entity);
|
||||
continue;
|
||||
}
|
||||
if (wrapper.isExist(entity.getClass(), entity.rowID)) {
|
||||
updateD.add(entity);
|
||||
} else {
|
||||
insertD.add(entity);
|
||||
}
|
||||
}
|
||||
if (!insertD.isEmpty()) {
|
||||
wrapper.insertManyData(insertD);
|
||||
}
|
||||
if (!updateD.isEmpty()) {
|
||||
wrapper.updateManyData(updateD);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查批量操作的列表数据,如果数据为空,抛出{@link NullPointerException}
|
||||
*/
|
||||
private static <T extends DbEntity> void checkListData(List<T> entities) {
|
||||
if (entities == null || entities.isEmpty()) {
|
||||
throw new NullPointerException("列表数据为空");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除当前数据
|
||||
*/
|
||||
public void deleteData() {
|
||||
deleteData(getClass(), "rowid=?", rowID + "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件删除数据
|
||||
* <code>
|
||||
* DbEntity.deleteData(DownloadEntity.class, "downloadUrl=?", downloadUrl);
|
||||
* </code>
|
||||
*/
|
||||
public static <T extends DbEntity> void deleteData(Class<T> clazz, String... expression) {
|
||||
DelegateWrapper util = DelegateWrapper.getInstance();
|
||||
util.delData(clazz, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改数据
|
||||
*/
|
||||
public void update() {
|
||||
DelegateWrapper.getInstance().updateData(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存自身,如果表中已经有数据,则更新数据,否则插入数据 只有 target中checkEntity成功后才能保存,创建实体部分也不允许保存
|
||||
*/
|
||||
public void save() {
|
||||
synchronized (LOCK) {
|
||||
if (thisIsExist()) {
|
||||
update();
|
||||
} else {
|
||||
insert();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找数据在表中是否存在
|
||||
*/
|
||||
private boolean thisIsExist() {
|
||||
DelegateWrapper util = DelegateWrapper.getInstance();
|
||||
return rowID != -1 && util.isExist(getClass(), rowID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 表是否存在
|
||||
*
|
||||
* @return {@code true} 存在
|
||||
*/
|
||||
public static boolean tableExists(Class<DbEntity> clazz) {
|
||||
return DelegateWrapper.getInstance().tableExists(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入数据,只有 target中checkEntity成功后才能插入,创建实体部分也不允许操作
|
||||
*/
|
||||
public void insert() {
|
||||
DelegateWrapper.getInstance().insertData(this);
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ class DelegateUpdate extends AbsDelegate {
|
||||
/**
|
||||
* 更新多条记录
|
||||
*/
|
||||
synchronized void updateManyData(SQLiteDatabase db, List<DbEntity> dbEntities) {
|
||||
synchronized <T extends DbEntity> void updateManyData(SQLiteDatabase db, List<T> dbEntities) {
|
||||
db = checkDb(db);
|
||||
db.beginTransaction();
|
||||
try {
|
||||
|
||||
@@ -117,7 +117,7 @@ public class DelegateWrapper {
|
||||
/**
|
||||
* 更新多条数据
|
||||
*/
|
||||
void updateManyData(List<DbEntity> dbEntitys) {
|
||||
<T extends DbEntity> void updateManyData(List<T> dbEntitys) {
|
||||
mDManager.getDelegate(DelegateUpdate.class).updateManyData(mDb, dbEntitys);
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ public class DelegateWrapper {
|
||||
/**
|
||||
* 插入多条数据
|
||||
*/
|
||||
void insertManyData(List<DbEntity> dbEntitys) {
|
||||
<T extends DbEntity> void insertManyData(List<T> dbEntitys) {
|
||||
mDManager.getDelegate(DelegateUpdate.class).insertManyData(mDb, dbEntitys);
|
||||
}
|
||||
|
||||
|
||||
@@ -98,6 +98,8 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
handle314AriaUpdate(db);
|
||||
} else if (oldVersion < 45) {
|
||||
handle360AriaUpdate(db);
|
||||
} else if (oldVersion < 46) {
|
||||
db.execSQL("UPDATE ThreadRecord SET threadId=0 WHERE threadId=-1");
|
||||
} else {
|
||||
handleDbUpdate(db, null, null);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.arialyy.aria.core.command.group.GroupCmdFactory;
|
||||
import com.arialyy.aria.core.command.normal.AbsNormalCmd;
|
||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
||||
import com.arialyy.aria.core.common.AbsFileer;
|
||||
import com.arialyy.aria.core.common.RecordWrapper;
|
||||
import com.arialyy.aria.core.common.TaskRecord;
|
||||
import com.arialyy.aria.core.common.ThreadRecord;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
@@ -587,6 +588,21 @@ public class CommonUtil {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除任务组记录
|
||||
*
|
||||
* @param removeFile {@code true} 不仅删除任务数据库记录,还会删除已经删除完成的文件 {@code false}如果任务已经完成,只删除任务数据库记录
|
||||
*/
|
||||
public static void delGroupTaskRecord(String groupHash, boolean removeFile) {
|
||||
if (TextUtils.isEmpty(groupHash)) {
|
||||
ALog.e(TAG, "删除下载任务组记录失败,groupHash为null");
|
||||
return;
|
||||
}
|
||||
DownloadGroupEntity groupEntity = DbDataHelper.getDGEntity(groupHash);
|
||||
|
||||
delGroupTaskRecord(groupEntity, removeFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除任务组记录
|
||||
*
|
||||
@@ -597,23 +613,28 @@ public class CommonUtil {
|
||||
ALog.e(TAG, "删除下载任务组记录失败,任务组实体为null");
|
||||
return;
|
||||
}
|
||||
List<TaskRecord> records =
|
||||
DbEntity.findDatas(TaskRecord.class, "dGroupHash=?", groupEntity.getGroupHash());
|
||||
List<RecordWrapper> records =
|
||||
DbEntity.findRelationData(RecordWrapper.class, "dGroupHash=?", groupEntity.getGroupHash());
|
||||
|
||||
if (records == null || records.isEmpty()) {
|
||||
ALog.w(TAG, "组任务记录删除失败,记录为null");
|
||||
} else {
|
||||
for (TaskRecord record : records) {
|
||||
for (RecordWrapper record : records) {
|
||||
if (record == null || record.taskRecord == null) {
|
||||
continue;
|
||||
}
|
||||
// 删除分块文件
|
||||
if (record.isBlock) {
|
||||
for (int i = 0, len = record.threadNum; i < len; i++) {
|
||||
File partFile = new File(String.format(AbsFileer.SUB_PATH, record.filePath, i));
|
||||
if (record.taskRecord.isBlock) {
|
||||
for (int i = 0, len = record.taskRecord.threadNum; i < len; i++) {
|
||||
File partFile =
|
||||
new File(String.format(AbsFileer.SUB_PATH, record.taskRecord.filePath, i));
|
||||
if (partFile.exists()) {
|
||||
partFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
record.deleteData();
|
||||
DbEntity.deleteData(ThreadRecord.class, "key=?", record.taskRecord.filePath);
|
||||
record.taskRecord.deleteData();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -632,12 +653,13 @@ public class CommonUtil {
|
||||
if (dir.exists() && (removeFile || !groupEntity.isComplete())) {
|
||||
dir.delete();
|
||||
}
|
||||
groupEntity.deleteData();
|
||||
}
|
||||
DbEntity.deleteData(DownloadEntity.class, "groupHash=?", groupEntity.getGroupHash());
|
||||
DbEntity.deleteData(DownloadGroupEntity.class, "groupHash=?", groupEntity.getGroupHash());
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除任务记录
|
||||
* 删除任务记录,默认删除任务实体
|
||||
*
|
||||
* @param removeFile {@code true} 不仅删除任务数据库记录,还会删除已经完成的文件 {@code false}如果任务已经完成,只删除任务数据库记录
|
||||
*/
|
||||
@@ -655,7 +677,7 @@ public class CommonUtil {
|
||||
ALog.w(TAG, "删除记录失败,未知类型");
|
||||
return;
|
||||
}
|
||||
delTaskRecord(filePath, type, removeFile);
|
||||
delTaskRecord(filePath, type, removeFile, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -664,21 +686,28 @@ public class CommonUtil {
|
||||
* @param filePath 文件路径
|
||||
* @param removeFile {@code true} 不仅删除任务数据库记录,还会删除已经删除完成的文件 {@code false}如果任务已经完成,只删除任务数据库记录
|
||||
* @param type {@code 1}下载任务的记录,{@code 2} 上传任务的记录 {@code false}如果任务已经完成,只删除任务数据库记录
|
||||
* @param removeEntity {@code true} 删除任务实体,
|
||||
*/
|
||||
public static void delTaskRecord(String filePath, int type, boolean removeFile) {
|
||||
public static void delTaskRecord(String filePath, int type, boolean removeFile,
|
||||
boolean removeEntity) {
|
||||
if (TextUtils.isEmpty(filePath)) {
|
||||
throw new NullPointerException("删除记录失败,文件路径为空");
|
||||
}
|
||||
if (type != 1 && type != 2) {
|
||||
throw new IllegalArgumentException("任务记录类型错误");
|
||||
}
|
||||
TaskRecord record = DbEntity.findFirst(TaskRecord.class, "filePath=?", filePath);
|
||||
DbEntity.deleteData(ThreadRecord.class, "key=?", filePath);
|
||||
List<RecordWrapper> recordWrapper =
|
||||
DbEntity.findRelationData(RecordWrapper.class, "filePath=?", filePath);
|
||||
DbEntity.deleteData(ThreadRecord.class, "key=?", filePath); // 必须先获取完成数据再删除线程记录
|
||||
|
||||
File file = new File(filePath);
|
||||
if (record == null) {
|
||||
if (recordWrapper == null
|
||||
|| recordWrapper.isEmpty()
|
||||
|| recordWrapper.get(0) == null
|
||||
|| recordWrapper.get(0).taskRecord == null) {
|
||||
ALog.w(TAG, "记录为空");
|
||||
} else {
|
||||
TaskRecord record = recordWrapper.get(0).taskRecord;
|
||||
// 删除分块文件
|
||||
if (record.isBlock) {
|
||||
for (int i = 0, len = record.threadNum; i < len; i++) {
|
||||
@@ -688,28 +717,31 @@ public class CommonUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
// 删除任务记录
|
||||
record.deleteData();
|
||||
}
|
||||
|
||||
if (file.exists() && removeFile) {
|
||||
file.delete();
|
||||
}
|
||||
//下载任务实体和下载实体为一对一关系,下载实体删除,任务实体自动删除
|
||||
if (type == 1) {
|
||||
DbEntity.deleteData(DownloadEntity.class, "downloadPath=?", filePath);
|
||||
} else {
|
||||
DbEntity.deleteData(UploadEntity.class, "filePath=?", filePath);
|
||||
|
||||
if (removeEntity) {
|
||||
if (type == 1) {
|
||||
DbEntity.deleteData(DownloadEntity.class, "downloadPath=?", filePath);
|
||||
} else {
|
||||
DbEntity.deleteData(UploadEntity.class, "filePath=?", filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除任务记录,默认删除文件
|
||||
* 删除任务记录,默认删除文件,删除任务实体
|
||||
*
|
||||
* @param filePath 文件路径
|
||||
* @param type {@code 1}下载任务的记录,{@code 2} 上传任务的记录 {@code false}如果任务已经完成,只删除任务数据库记录
|
||||
*/
|
||||
public static void delTaskRecord(String filePath, int type) {
|
||||
delTaskRecord(filePath, type, false);
|
||||
delTaskRecord(filePath, type, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -925,9 +957,9 @@ public class CommonUtil {
|
||||
* 获取当前类里面的所在字段
|
||||
*/
|
||||
public static Field[] getFields(Class clazz) {
|
||||
Field[] fields = null;
|
||||
Field[] fields;
|
||||
fields = clazz.getDeclaredFields();
|
||||
if (fields == null || fields.length == 0) {
|
||||
if (fields.length == 0) {
|
||||
Class superClazz = clazz.getSuperclass();
|
||||
if (superClazz != null) {
|
||||
fields = getFields(superClazz);
|
||||
@@ -1016,7 +1048,7 @@ public class CommonUtil {
|
||||
* @return 对象名
|
||||
*/
|
||||
public static String getClassName(Object obj) {
|
||||
String arrays[] = obj.getClass().getName().split("\\.");
|
||||
String[] arrays = obj.getClass().getName().split("\\.");
|
||||
return arrays[arrays.length - 1];
|
||||
}
|
||||
|
||||
@@ -1027,7 +1059,7 @@ public class CommonUtil {
|
||||
* @return 对象名
|
||||
*/
|
||||
public static String getClassName(Class clazz) {
|
||||
String arrays[] = clazz.getName().split("\\.");
|
||||
String[] arrays = clazz.getName().split("\\.");
|
||||
return arrays[arrays.length - 1];
|
||||
}
|
||||
|
||||
@@ -1165,7 +1197,7 @@ public class CommonUtil {
|
||||
blockFile.renameTo(new File(String.format(AbsFileer.SUB_PATH, newPath, tr.threadId)));
|
||||
}
|
||||
}
|
||||
DbEntity.saveAll(record.threadRecords);
|
||||
DbEntity.updateManyData(record.threadRecords);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.arialyy.aria.util;
|
||||
|
||||
import com.arialyy.aria.core.common.RecordWrapper;
|
||||
import com.arialyy.aria.core.common.TaskRecord;
|
||||
import com.arialyy.aria.core.common.ThreadRecord;
|
||||
import com.arialyy.aria.core.download.DGEntityWrapper;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.core.download.DownloadGroupEntity;
|
||||
@@ -37,12 +38,12 @@ public class DbDataHelper {
|
||||
* @return 没有记录返回null,有记录则返回任务记录
|
||||
*/
|
||||
public static TaskRecord getTaskRecord(String filePath) {
|
||||
List<RecordWrapper> records =
|
||||
List<RecordWrapper> record =
|
||||
DbEntity.findRelationData(RecordWrapper.class, "TaskRecord.filePath=?", filePath);
|
||||
if (records == null || records.size() == 0) {
|
||||
if (record == null || record.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
return records.get(0).taskRecord;
|
||||
return record.get(0).taskRecord;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
10
DEV_LOG.md
10
DEV_LOG.md
@@ -13,6 +13,16 @@
|
||||
- 组合任务新增`unknownSize()`,用于处理组合任务大小未知的情况,https://github.com/AriaLyy/Aria/issues/380
|
||||
- 优化`AbsThreadTask`代码
|
||||
- 新增文件长度处理功能 https://github.com/AriaLyy/Aria/issues/393
|
||||
```java
|
||||
.setFileLenAdapter(new IHttpFileLenAdapter() {
|
||||
@Override public long handleFileLen(Map<String, List<String>> headers) {
|
||||
...
|
||||
// 处理header中的文件长度
|
||||
|
||||
return fileLen;
|
||||
}
|
||||
})
|
||||
```
|
||||
- 修复组合任务多次回调`onStop`注解的问题
|
||||
- 优化`isRunning()`的逻辑,任务是否在执行的判断将更加准确
|
||||
- 修复多次重复快速点击`暂停、开始`时,任务有可能重复下载的问题
|
||||
|
||||
@@ -24,8 +24,8 @@ import com.arialyy.aria.core.Aria;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.core.download.DownloadGroupEntity;
|
||||
import com.arialyy.aria.core.download.DownloadGroupTask;
|
||||
import com.arialyy.aria.core.inf.AbsHttpFileLenAdapter;
|
||||
import com.arialyy.aria.core.inf.IHttpFileLenAdapter;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import com.arialyy.frame.util.show.L;
|
||||
import com.arialyy.frame.util.show.T;
|
||||
import com.arialyy.simple.R;
|
||||
@@ -59,6 +59,7 @@ public class DownloadGroupActivity extends BaseActivity<ActivityDownloadGroupBin
|
||||
getBinding().setProgress(entity.isComplete() ? 100
|
||||
: (int) (entity.getCurrentProgress() * 100 / entity.getFileSize()));
|
||||
}
|
||||
ALog.d(TAG, "size = " + entity.getSubEntities().size() + "; len = " + entity.getConvertFileSize());
|
||||
}
|
||||
|
||||
mChildList.setOnItemClickListener(new SubStateLinearLayout.OnItemClickListener() {
|
||||
@@ -90,18 +91,18 @@ public class DownloadGroupActivity extends BaseActivity<ActivityDownloadGroupBin
|
||||
//.setSubFileName(getModule(GroupModule.class).getSubName2())
|
||||
.setSubFileName(getModule(GroupModule.class).getSubName())
|
||||
.unknownSize()
|
||||
//.setFileLenAdapter(new AbsHttpFileLenAdapter() {
|
||||
// @Override public long handleFileLen(Map<String, List<String>> headers) {
|
||||
//
|
||||
// List<String> sLength = headers.get("Content-Length");
|
||||
// if (sLength == null || sLength.isEmpty()) {
|
||||
// return -1;
|
||||
// }
|
||||
// String temp = sLength.get(0);
|
||||
//
|
||||
// return Long.parseLong(temp);
|
||||
// }
|
||||
//})
|
||||
.setFileLenAdapter(new IHttpFileLenAdapter() {
|
||||
@Override public long handleFileLen(Map<String, List<String>> headers) {
|
||||
|
||||
List<String> sLength = headers.get("Content-Length");
|
||||
if (sLength == null || sLength.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
String temp = sLength.get(0);
|
||||
|
||||
return Long.parseLong(temp);
|
||||
}
|
||||
})
|
||||
//.setFileSize(114981416)
|
||||
//.updateUrls(temp)
|
||||
.start();
|
||||
|
||||
Reference in New Issue
Block a user