|
|
@ -58,22 +58,19 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected long mChildCurrentLocation = 0; |
|
|
|
protected long mChildCurrentLocation = 0; |
|
|
|
protected IEventListener mListener; |
|
|
|
protected IEventListener mListener; |
|
|
|
protected StateConstance STATE; |
|
|
|
private StateConstance sState; |
|
|
|
protected SubThreadConfig<TASK_WRAPPER> mConfig; |
|
|
|
private SubThreadConfig<TASK_WRAPPER> sConfig; |
|
|
|
protected ENTITY mEntity; |
|
|
|
private ENTITY mEntity; |
|
|
|
protected TASK_WRAPPER mTaskWrapper; |
|
|
|
private TASK_WRAPPER mTaskWrapper; |
|
|
|
private int mFailTimes = 0; |
|
|
|
private int mFailTimes = 0; |
|
|
|
private long mLastSaveTime; |
|
|
|
private long mLastSaveTime; |
|
|
|
private ExecutorService mConfigThreadPool; |
|
|
|
private ExecutorService mConfigThreadPool; |
|
|
|
protected boolean isNotNetRetry; //断网情况是否重试
|
|
|
|
private boolean isNotNetRetry; //断网情况是否重试
|
|
|
|
private boolean taskBreak = false; //任务跳出
|
|
|
|
private boolean taskBreak = false; //任务跳出
|
|
|
|
protected int mThreadNum; |
|
|
|
private int mThreadNum; |
|
|
|
/** |
|
|
|
protected BandwidthLimiter mSpeedBandUtil; //速度限制工具
|
|
|
|
* 速度限制工具 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
protected BandwidthLimiter mSpeedBandUtil; |
|
|
|
|
|
|
|
protected AriaManager mAridManager; |
|
|
|
protected AriaManager mAridManager; |
|
|
|
protected boolean isInterrupted = false; |
|
|
|
private boolean isInterrupted = false; |
|
|
|
|
|
|
|
|
|
|
|
private Thread mConfigThread = new Thread(new Runnable() { |
|
|
|
private Thread mConfigThread = new Thread(new Runnable() { |
|
|
|
@Override public void run() { |
|
|
|
@Override public void run() { |
|
|
@ -85,14 +82,14 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER |
|
|
|
|
|
|
|
|
|
|
|
protected AbsThreadTask(StateConstance constance, IEventListener listener, |
|
|
|
protected AbsThreadTask(StateConstance constance, IEventListener listener, |
|
|
|
SubThreadConfig<TASK_WRAPPER> config) { |
|
|
|
SubThreadConfig<TASK_WRAPPER> config) { |
|
|
|
STATE = constance; |
|
|
|
sState = constance; |
|
|
|
|
|
|
|
sConfig = config; |
|
|
|
mListener = listener; |
|
|
|
mListener = listener; |
|
|
|
mConfig = config; |
|
|
|
mTaskWrapper = getConfig().TASK_WRAPPER; |
|
|
|
mTaskWrapper = mConfig.TASK_WRAPPER; |
|
|
|
|
|
|
|
mEntity = mTaskWrapper.getEntity(); |
|
|
|
mEntity = mTaskWrapper.getEntity(); |
|
|
|
mLastSaveTime = System.currentTimeMillis(); |
|
|
|
mLastSaveTime = System.currentTimeMillis(); |
|
|
|
mConfigThreadPool = Executors.newCachedThreadPool(); |
|
|
|
mConfigThreadPool = Executors.newCachedThreadPool(); |
|
|
|
mThreadNum = STATE.TASK_RECORD.threadRecords.size(); |
|
|
|
mThreadNum = getState().TASK_RECORD.threadRecords.size(); |
|
|
|
mAridManager = AriaManager.getInstance(AriaManager.APP); |
|
|
|
mAridManager = AriaManager.getInstance(AriaManager.APP); |
|
|
|
if (getMaxSpeed() > 0) { |
|
|
|
if (getMaxSpeed() > 0) { |
|
|
|
mSpeedBandUtil = new BandwidthLimiter(getMaxSpeed(), mThreadNum); |
|
|
|
mSpeedBandUtil = new BandwidthLimiter(getMaxSpeed(), mThreadNum); |
|
|
@ -122,21 +119,42 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER |
|
|
|
* 当前线程是否完成,对于不支持断点的任务,一律未完成 {@code true} 完成;{@code false} 未完成 |
|
|
|
* 当前线程是否完成,对于不支持断点的任务,一律未完成 {@code true} 完成;{@code false} 未完成 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
boolean isThreadComplete() { |
|
|
|
boolean isThreadComplete() { |
|
|
|
return mConfig.THREAD_RECORD.isComplete; |
|
|
|
return getConfig().THREAD_RECORD.isComplete; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* 获取状态信息 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
protected StateConstance getState() { |
|
|
|
|
|
|
|
return sState; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* 获取实体 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
protected ENTITY getEntity() { |
|
|
|
|
|
|
|
return mEntity; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* 获取任务驱动对象 |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
protected TASK_WRAPPER getTaskWrapper() { |
|
|
|
|
|
|
|
return mTaskWrapper; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* 获取任务记录 |
|
|
|
* 获取任务记录 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private TaskRecord getTaskRecord() { |
|
|
|
private TaskRecord getTaskRecord() { |
|
|
|
return STATE.TASK_RECORD; |
|
|
|
return getState().TASK_RECORD; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* 获取线程记录 |
|
|
|
* 获取线程记录 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected ThreadRecord getThreadRecord() { |
|
|
|
protected ThreadRecord getThreadRecord() { |
|
|
|
return mConfig.THREAD_RECORD; |
|
|
|
return getConfig().THREAD_RECORD; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -170,19 +188,19 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER |
|
|
|
void breakTask() { |
|
|
|
void breakTask() { |
|
|
|
synchronized (AriaManager.LOCK) { |
|
|
|
synchronized (AriaManager.LOCK) { |
|
|
|
taskBreak = true; |
|
|
|
taskBreak = true; |
|
|
|
if (mConfig.SUPPORT_BP) { |
|
|
|
if (getConfig().SUPPORT_BP) { |
|
|
|
final long currentTemp = mChildCurrentLocation; |
|
|
|
final long currentTemp = mChildCurrentLocation; |
|
|
|
STATE.STOP_NUM++; |
|
|
|
getState().STOP_NUM++; |
|
|
|
ALog.d(TAG, String.format("任务【%s】thread__%s__中断【停止位置:%s】", mConfig.TEMP_FILE.getName(), |
|
|
|
ALog.d(TAG, String.format("任务【%s】thread__%s__中断【停止位置:%s】", getConfig().TEMP_FILE.getName(), |
|
|
|
mConfig.THREAD_ID, currentTemp)); |
|
|
|
getConfig().THREAD_ID, currentTemp)); |
|
|
|
writeConfig(false, currentTemp); |
|
|
|
writeConfig(false, currentTemp); |
|
|
|
if (STATE.isStop()) { |
|
|
|
if (getState().isStop()) { |
|
|
|
ALog.i(TAG, String.format("任务【%s】已中断", mConfig.TEMP_FILE.getName())); |
|
|
|
ALog.i(TAG, String.format("任务【%s】已中断", getConfig().TEMP_FILE.getName())); |
|
|
|
STATE.isRunning = false; |
|
|
|
getState().isRunning = false; |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
ALog.i(TAG, String.format("任务【%s】已中断", mConfig.TEMP_FILE.getName())); |
|
|
|
ALog.i(TAG, String.format("任务【%s】已中断", getConfig().TEMP_FILE.getName())); |
|
|
|
STATE.isRunning = false; |
|
|
|
getState().isRunning = false; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -193,7 +211,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER |
|
|
|
* @return {@code true}正在运行 |
|
|
|
* @return {@code true}正在运行 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public boolean isRunning() { |
|
|
|
public boolean isRunning() { |
|
|
|
return STATE.isRunning; |
|
|
|
return getState().isRunning; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public boolean isInterrupted() { |
|
|
|
public boolean isInterrupted() { |
|
|
@ -203,8 +221,8 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER |
|
|
|
/** |
|
|
|
/** |
|
|
|
* 获取线程配置信息 |
|
|
|
* 获取线程配置信息 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public SubThreadConfig getConfig() { |
|
|
|
protected SubThreadConfig<TASK_WRAPPER> getConfig() { |
|
|
|
return mConfig; |
|
|
|
return sConfig; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override protected void finalize() throws Throwable { |
|
|
|
@Override protected void finalize() throws Throwable { |
|
|
@ -220,7 +238,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER |
|
|
|
* @return {@code true} 中断,{@code false} 不是中断 |
|
|
|
* @return {@code true} 中断,{@code false} 不是中断 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected boolean isBreak() { |
|
|
|
protected boolean isBreak() { |
|
|
|
return STATE.isCancel || STATE.isStop || taskBreak; |
|
|
|
return getState().isCancel || getState().isStop || taskBreak; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -230,10 +248,10 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected boolean mergeFile() { |
|
|
|
protected boolean mergeFile() { |
|
|
|
List<String> partPath = new ArrayList<>(); |
|
|
|
List<String> partPath = new ArrayList<>(); |
|
|
|
for (int i = 0, len = STATE.TASK_RECORD.threadNum; i < len; i++) { |
|
|
|
for (int i = 0, len = getState().TASK_RECORD.threadNum; i < len; i++) { |
|
|
|
partPath.add(String.format(AbsFileer.SUB_PATH, STATE.TASK_RECORD.filePath, i)); |
|
|
|
partPath.add(String.format(AbsFileer.SUB_PATH, getState().TASK_RECORD.filePath, i)); |
|
|
|
} |
|
|
|
} |
|
|
|
boolean isSuccess = FileUtil.mergeFile(STATE.TASK_RECORD.filePath, partPath); |
|
|
|
boolean isSuccess = FileUtil.mergeFile(getState().TASK_RECORD.filePath, partPath); |
|
|
|
if (isSuccess) { |
|
|
|
if (isSuccess) { |
|
|
|
for (String pp : partPath) { |
|
|
|
for (String pp : partPath) { |
|
|
|
File f = new File(pp); |
|
|
|
File f = new File(pp); |
|
|
@ -241,10 +259,10 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER |
|
|
|
f.delete(); |
|
|
|
f.delete(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
File targetFile = new File(STATE.TASK_RECORD.filePath); |
|
|
|
File targetFile = new File(getState().TASK_RECORD.filePath); |
|
|
|
if (targetFile.exists() && targetFile.length() > mEntity.getFileSize()) { |
|
|
|
if (targetFile.exists() && targetFile.length() > getEntity().getFileSize()) { |
|
|
|
ALog.e(TAG, String.format("任务【%s】分块文件合并失败,下载长度超出文件真实长度,downloadLen: %s,fileSize: %s", |
|
|
|
ALog.e(TAG, String.format("任务【%s】分块文件合并失败,下载长度超出文件真实长度,downloadLen: %s,fileSize: %s", |
|
|
|
mConfig.TEMP_FILE.getName(), targetFile.length(), mEntity.getFileSize())); |
|
|
|
getConfig().TEMP_FILE.getName(), targetFile.length(), getEntity().getFileSize())); |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
return true; |
|
|
@ -282,30 +300,31 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public void stop() { |
|
|
|
public void stop() { |
|
|
|
synchronized (AriaManager.LOCK) { |
|
|
|
synchronized (AriaManager.LOCK) { |
|
|
|
if (mConfig.SUPPORT_BP) { |
|
|
|
if (getConfig().SUPPORT_BP) { |
|
|
|
final long stopLocation; |
|
|
|
final long stopLocation; |
|
|
|
if (getTaskRecord().isBlock) { |
|
|
|
if (getTaskRecord().isBlock) { |
|
|
|
File blockFile = getBockFile(); |
|
|
|
File blockFile = getBockFile(); |
|
|
|
ThreadRecord tr = getThreadRecord(); |
|
|
|
ThreadRecord tr = getThreadRecord(); |
|
|
|
long block = mEntity.getFileSize() / getTaskRecord().threadRecords.size(); |
|
|
|
long block = getEntity().getFileSize() / getTaskRecord().threadRecords.size(); |
|
|
|
stopLocation = |
|
|
|
stopLocation = |
|
|
|
blockFile.exists() ? (tr.threadId * block + blockFile.length()) : tr.threadId * block; |
|
|
|
blockFile.exists() ? (tr.threadId * block + blockFile.length()) : tr.threadId * block; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
stopLocation = mChildCurrentLocation; |
|
|
|
stopLocation = mChildCurrentLocation; |
|
|
|
} |
|
|
|
} |
|
|
|
STATE.STOP_NUM++; |
|
|
|
getState().STOP_NUM++; |
|
|
|
ALog.d(TAG, String.format("任务【%s】thread__%s__停止【当前线程停止位置:%s】", mConfig.TEMP_FILE.getName(), |
|
|
|
ALog.d(TAG, |
|
|
|
mConfig.THREAD_ID, stopLocation)); |
|
|
|
String.format("任务【%s】thread__%s__停止【当前线程停止位置:%s】", getConfig().TEMP_FILE.getName(), |
|
|
|
|
|
|
|
getConfig().THREAD_ID, stopLocation)); |
|
|
|
writeConfig(false, stopLocation); |
|
|
|
writeConfig(false, stopLocation); |
|
|
|
if (STATE.isStop()) { |
|
|
|
if (getState().isStop()) { |
|
|
|
ALog.i(TAG, String.format("任务【%s】已停止", mConfig.TEMP_FILE.getName())); |
|
|
|
ALog.i(TAG, String.format("任务【%s】已停止", getConfig().TEMP_FILE.getName())); |
|
|
|
STATE.isRunning = false; |
|
|
|
getState().isRunning = false; |
|
|
|
mListener.onStop(STATE.CURRENT_LOCATION); |
|
|
|
mListener.onStop(getState().CURRENT_LOCATION); |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
ALog.i(TAG, String.format("任务【%s】已停止", mConfig.TEMP_FILE.getName())); |
|
|
|
ALog.i(TAG, String.format("任务【%s】已停止", getConfig().TEMP_FILE.getName())); |
|
|
|
STATE.isRunning = false; |
|
|
|
getState().isRunning = false; |
|
|
|
mListener.onStop(STATE.CURRENT_LOCATION); |
|
|
|
mListener.onStop(getState().CURRENT_LOCATION); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -315,19 +334,20 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected void progress(long len) { |
|
|
|
protected void progress(long len) { |
|
|
|
synchronized (AriaManager.LOCK) { |
|
|
|
synchronized (AriaManager.LOCK) { |
|
|
|
if (STATE.CURRENT_LOCATION > mEntity.getFileSize() && !mTaskWrapper.asHttp().isChunked()) { |
|
|
|
if (getState().CURRENT_LOCATION > getEntity().getFileSize() && !getTaskWrapper().asHttp() |
|
|
|
|
|
|
|
.isChunked()) { |
|
|
|
String errorMsg = |
|
|
|
String errorMsg = |
|
|
|
String.format("下载失败,下载长度超出文件真实长度;currentLocation=%s, fileSize=%s", |
|
|
|
String.format("下载失败,下载长度超出文件真实长度;currentLocation=%s, fileSize=%s", |
|
|
|
STATE.CURRENT_LOCATION, |
|
|
|
getState().CURRENT_LOCATION, |
|
|
|
mEntity.getFileSize()); |
|
|
|
getEntity().getFileSize()); |
|
|
|
taskBreak = true; |
|
|
|
taskBreak = true; |
|
|
|
fail(mChildCurrentLocation, new FileException(TAG, errorMsg), false); |
|
|
|
fail(mChildCurrentLocation, new FileException(TAG, errorMsg), false); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
mChildCurrentLocation += len; |
|
|
|
mChildCurrentLocation += len; |
|
|
|
STATE.CURRENT_LOCATION += len; |
|
|
|
getState().CURRENT_LOCATION += len; |
|
|
|
if (System.currentTimeMillis() - mLastSaveTime > 5000 |
|
|
|
if (System.currentTimeMillis() - mLastSaveTime > 5000 |
|
|
|
&& mChildCurrentLocation < mConfig.END_LOCATION) { |
|
|
|
&& mChildCurrentLocation < getConfig().END_LOCATION) { |
|
|
|
mLastSaveTime = System.currentTimeMillis(); |
|
|
|
mLastSaveTime = System.currentTimeMillis(); |
|
|
|
if (!mConfigThreadPool.isShutdown()) { |
|
|
|
if (!mConfigThreadPool.isShutdown()) { |
|
|
|
mConfigThreadPool.execute(mConfigThread); |
|
|
|
mConfigThreadPool.execute(mConfigThread); |
|
|
@ -341,21 +361,22 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public void cancel() { |
|
|
|
public void cancel() { |
|
|
|
synchronized (AriaManager.LOCK) { |
|
|
|
synchronized (AriaManager.LOCK) { |
|
|
|
if (mConfig.SUPPORT_BP) { |
|
|
|
if (getConfig().SUPPORT_BP) { |
|
|
|
STATE.CANCEL_NUM++; |
|
|
|
getState().CANCEL_NUM++; |
|
|
|
ALog.d(TAG, |
|
|
|
ALog.d(TAG, |
|
|
|
String.format("任务【%s】thread__%s__取消", mConfig.TEMP_FILE.getName(), mConfig.THREAD_ID)); |
|
|
|
String.format("任务【%s】thread__%s__取消", getConfig().TEMP_FILE.getName(), |
|
|
|
if (STATE.isCancel()) { |
|
|
|
getConfig().THREAD_ID)); |
|
|
|
if (mConfig.TEMP_FILE.exists() && !(mEntity instanceof UploadEntity)) { |
|
|
|
if (getState().isCancel()) { |
|
|
|
mConfig.TEMP_FILE.delete(); |
|
|
|
if (getConfig().TEMP_FILE.exists() && !(getEntity() instanceof UploadEntity)) { |
|
|
|
} |
|
|
|
getConfig().TEMP_FILE.delete(); |
|
|
|
ALog.d(TAG, String.format("任务【%s】已取消", mConfig.TEMP_FILE.getName())); |
|
|
|
} |
|
|
|
STATE.isRunning = false; |
|
|
|
ALog.d(TAG, String.format("任务【%s】已取消", getConfig().TEMP_FILE.getName())); |
|
|
|
|
|
|
|
getState().isRunning = false; |
|
|
|
mListener.onCancel(); |
|
|
|
mListener.onCancel(); |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
ALog.d(TAG, String.format("任务【%s】已取消", mConfig.TEMP_FILE.getName())); |
|
|
|
ALog.d(TAG, String.format("任务【%s】已取消", getConfig().TEMP_FILE.getName())); |
|
|
|
STATE.isRunning = false; |
|
|
|
getState().isRunning = false; |
|
|
|
mListener.onCancel(); |
|
|
|
mListener.onCancel(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -377,20 +398,18 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER |
|
|
|
* @param subCurrentLocation 当前子线程进度 |
|
|
|
* @param subCurrentLocation 当前子线程进度 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected void fail(final long subCurrentLocation, BaseException ex, boolean needRetry) { |
|
|
|
protected void fail(final long subCurrentLocation, BaseException ex, boolean needRetry) { |
|
|
|
synchronized (AriaManager.LOCK) { |
|
|
|
|
|
|
|
if (ex != null) { |
|
|
|
if (ex != null) { |
|
|
|
ALog.e(TAG, ALog.getExceptionString(ex)); |
|
|
|
ALog.e(TAG, ALog.getExceptionString(ex)); |
|
|
|
} |
|
|
|
} |
|
|
|
if (mConfig.SUPPORT_BP) { |
|
|
|
if (getConfig().SUPPORT_BP) { |
|
|
|
writeConfig(false, subCurrentLocation); |
|
|
|
writeConfig(false, subCurrentLocation); |
|
|
|
retryThis(needRetry && STATE.START_THREAD_NUM != 1); |
|
|
|
retryThis(needRetry && getState().START_THREAD_NUM != 1); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
ALog.e(TAG, String.format("任务【%s】执行失败", mConfig.TEMP_FILE.getName())); |
|
|
|
ALog.e(TAG, String.format("任务【%s】执行失败", getConfig().TEMP_FILE.getName())); |
|
|
|
ErrorHelp.saveError(TAG, "", ALog.getExceptionString(ex)); |
|
|
|
ErrorHelp.saveError(TAG, "", ALog.getExceptionString(ex)); |
|
|
|
handleFailState(!isBreak()); |
|
|
|
handleFailState(!isBreak()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* 重试当前线程,如果其中一条线程已经下载失败,则任务该任务下载失败,并且停止该任务的所有线程 |
|
|
|
* 重试当前线程,如果其中一条线程已经下载失败,则任务该任务下载失败,并且停止该任务的所有线程 |
|
|
@ -398,16 +417,15 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER |
|
|
|
* @param needRetry 是否可以重试 |
|
|
|
* @param needRetry 是否可以重试 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private void retryThis(boolean needRetry) { |
|
|
|
private void retryThis(boolean needRetry) { |
|
|
|
synchronized (AriaManager.LOCK) { |
|
|
|
|
|
|
|
if (!NetUtils.isConnected(AriaManager.APP) && !isNotNetRetry) { |
|
|
|
if (!NetUtils.isConnected(AriaManager.APP) && !isNotNetRetry) { |
|
|
|
ALog.w(TAG, String.format("任务【%s】thread__%s__重试失败,网络未连接", mConfig.TEMP_FILE.getName(), |
|
|
|
ALog.w(TAG, String.format("任务【%s】thread__%s__重试失败,网络未连接", getConfig().TEMP_FILE.getName(), |
|
|
|
mConfig.THREAD_ID)); |
|
|
|
getConfig().THREAD_ID)); |
|
|
|
} |
|
|
|
} |
|
|
|
if (mFailTimes < RETRY_NUM && needRetry && (NetUtils.isConnected(AriaManager.APP) |
|
|
|
if (mFailTimes < RETRY_NUM && needRetry && (NetUtils.isConnected(AriaManager.APP) |
|
|
|
|| isNotNetRetry) && !isBreak()) { |
|
|
|
|| isNotNetRetry) && !isBreak()) { |
|
|
|
ALog.w(TAG, |
|
|
|
ALog.w(TAG, |
|
|
|
String.format("任务【%s】thread__%s__正在重试", mConfig.TEMP_FILE.getName(), |
|
|
|
String.format("任务【%s】thread__%s__正在重试", getConfig().TEMP_FILE.getName(), |
|
|
|
mConfig.THREAD_ID)); |
|
|
|
getConfig().THREAD_ID)); |
|
|
|
mFailTimes++; |
|
|
|
mFailTimes++; |
|
|
|
handleRetryRecord(); |
|
|
|
handleRetryRecord(); |
|
|
|
ThreadTaskManager.getInstance().retryThread(AbsThreadTask.this); |
|
|
|
ThreadTaskManager.getInstance().retryThread(AbsThreadTask.this); |
|
|
@ -415,7 +433,6 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER |
|
|
|
handleFailState(!isBreak()); |
|
|
|
handleFailState(!isBreak()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* 处理线程重试的记录,只有多线程任务才会执行 |
|
|
|
* 处理线程重试的记录,只有多线程任务才会执行 |
|
|
@ -423,7 +440,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER |
|
|
|
private void handleRetryRecord() { |
|
|
|
private void handleRetryRecord() { |
|
|
|
if (getTaskRecord().isBlock) { |
|
|
|
if (getTaskRecord().isBlock) { |
|
|
|
ThreadRecord tr = getThreadRecord(); |
|
|
|
ThreadRecord tr = getThreadRecord(); |
|
|
|
long block = mEntity.getFileSize() / getTaskRecord().threadRecords.size(); |
|
|
|
long block = getEntity().getFileSize() / getTaskRecord().threadRecords.size(); |
|
|
|
|
|
|
|
|
|
|
|
File blockFile = getBockFile(); |
|
|
|
File blockFile = getBockFile(); |
|
|
|
if (blockFile.length() > tr.blockLen) { |
|
|
|
if (blockFile.length() > tr.blockLen) { |
|
|
@ -431,22 +448,22 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER |
|
|
|
blockFile.delete(); |
|
|
|
blockFile.delete(); |
|
|
|
tr.startLocation = block * tr.threadId; |
|
|
|
tr.startLocation = block * tr.threadId; |
|
|
|
tr.isComplete = false; |
|
|
|
tr.isComplete = false; |
|
|
|
mConfig.START_LOCATION = tr.startLocation; |
|
|
|
getConfig().START_LOCATION = tr.startLocation; |
|
|
|
} else if (blockFile.length() < tr.blockLen) { |
|
|
|
} else if (blockFile.length() < tr.blockLen) { |
|
|
|
tr.startLocation = block * tr.threadId + blockFile.length(); |
|
|
|
tr.startLocation = block * tr.threadId + blockFile.length(); |
|
|
|
tr.isComplete = false; |
|
|
|
tr.isComplete = false; |
|
|
|
mConfig.START_LOCATION = tr.startLocation; |
|
|
|
getConfig().START_LOCATION = tr.startLocation; |
|
|
|
STATE.CURRENT_LOCATION = getBlockRealTotalSize(); |
|
|
|
getState().CURRENT_LOCATION = getBlockRealTotalSize(); |
|
|
|
ALog.i(TAG, String.format("修正分块【%s】,开始位置:%s,当前进度:%s", blockFile.getPath(), tr.startLocation, |
|
|
|
ALog.i(TAG, String.format("修正分块【%s】,开始位置:%s,当前进度:%s", blockFile.getPath(), tr.startLocation, |
|
|
|
STATE.CURRENT_LOCATION)); |
|
|
|
getState().CURRENT_LOCATION)); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
STATE.COMPLETE_THREAD_NUM++; |
|
|
|
getState().COMPLETE_THREAD_NUM++; |
|
|
|
tr.isComplete = true; |
|
|
|
tr.isComplete = true; |
|
|
|
} |
|
|
|
} |
|
|
|
tr.update(); |
|
|
|
tr.update(); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
mConfig.START_LOCATION = mChildCurrentLocation == 0 ? mConfig.START_LOCATION |
|
|
|
getConfig().START_LOCATION = mChildCurrentLocation == 0 ? getConfig().START_LOCATION |
|
|
|
: mConfig.THREAD_RECORD.startLocation; |
|
|
|
: getConfig().THREAD_RECORD.startLocation; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -456,7 +473,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER |
|
|
|
* @return 分块文件 |
|
|
|
* @return 分块文件 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private File getBockFile() { |
|
|
|
private File getBockFile() { |
|
|
|
return new File(String.format(AbsFileer.SUB_PATH, STATE.TASK_RECORD.filePath, |
|
|
|
return new File(String.format(AbsFileer.SUB_PATH, getState().TASK_RECORD.filePath, |
|
|
|
getThreadRecord().threadId)); |
|
|
|
getThreadRecord().threadId)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -482,18 +499,16 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER |
|
|
|
* @param taskNeedReTry 任务是否需要重试{@code true} 需要 |
|
|
|
* @param taskNeedReTry 任务是否需要重试{@code true} 需要 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private void handleFailState(boolean taskNeedReTry) { |
|
|
|
private void handleFailState(boolean taskNeedReTry) { |
|
|
|
synchronized (AriaManager.LOCK) { |
|
|
|
getState().FAIL_NUM++; |
|
|
|
STATE.FAIL_NUM++; |
|
|
|
if (getState().isFail()) { |
|
|
|
if (STATE.isFail()) { |
|
|
|
getState().isRunning = false; |
|
|
|
STATE.isRunning = false; |
|
|
|
|
|
|
|
// 手动停止不进行fail回调
|
|
|
|
// 手动停止不进行fail回调
|
|
|
|
if (!STATE.isStop) { |
|
|
|
if (!getState().isStop) { |
|
|
|
String errorMsg = String.format("任务【%s】执行失败", mConfig.TEMP_FILE.getName()); |
|
|
|
String errorMsg = String.format("任务【%s】执行失败", getConfig().TEMP_FILE.getName()); |
|
|
|
mListener.onFail(taskNeedReTry, new TaskException(TAG, errorMsg)); |
|
|
|
mListener.onFail(taskNeedReTry, new TaskException(TAG, errorMsg)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* 将记录写入到配置文件 |
|
|
|
* 将记录写入到配置文件 |
|
|
@ -502,23 +517,21 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER |
|
|
|
* @param record 当前下载进度 |
|
|
|
* @param record 当前下载进度 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected void writeConfig(boolean isComplete, final long record) { |
|
|
|
protected void writeConfig(boolean isComplete, final long record) { |
|
|
|
synchronized (AriaManager.LOCK) { |
|
|
|
|
|
|
|
ThreadRecord tr = getThreadRecord(); |
|
|
|
ThreadRecord tr = getThreadRecord(); |
|
|
|
if (tr != null) { |
|
|
|
if (tr != null) { |
|
|
|
tr.isComplete = isComplete; |
|
|
|
tr.isComplete = isComplete; |
|
|
|
if (getTaskRecord().isBlock) { |
|
|
|
if (getTaskRecord().isBlock) { |
|
|
|
tr.startLocation = record; |
|
|
|
tr.startLocation = record; |
|
|
|
} else if (getTaskRecord().isOpenDynamicFile) { |
|
|
|
} else if (getTaskRecord().isOpenDynamicFile) { |
|
|
|
tr.startLocation = mConfig.TEMP_FILE.length(); |
|
|
|
tr.startLocation = getConfig().TEMP_FILE.length(); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
if (0 < record && record < mConfig.END_LOCATION) { |
|
|
|
if (0 < record && record < getConfig().END_LOCATION) { |
|
|
|
tr.startLocation = record; |
|
|
|
tr.startLocation = record; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
tr.update(); |
|
|
|
tr.update(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override public AbsThreadTask call() throws Exception { |
|
|
|
@Override public AbsThreadTask call() throws Exception { |
|
|
|
isInterrupted = false; |
|
|
|
isInterrupted = false; |
|
|
|