优化AbsThreadTask代码, 新增文件长度处理功能 https://github.com/AriaLyy/Aria/issues/393
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
package com.arialyy.aria.core.common;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
import android.util.SparseArray;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.download.BaseDListener;
|
||||
|
||||
@@ -58,22 +58,19 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
*/
|
||||
protected long mChildCurrentLocation = 0;
|
||||
protected IEventListener mListener;
|
||||
protected StateConstance STATE;
|
||||
protected SubThreadConfig<TASK_WRAPPER> mConfig;
|
||||
protected ENTITY mEntity;
|
||||
protected TASK_WRAPPER mTaskWrapper;
|
||||
private StateConstance sState;
|
||||
private SubThreadConfig<TASK_WRAPPER> sConfig;
|
||||
private ENTITY mEntity;
|
||||
private TASK_WRAPPER mTaskWrapper;
|
||||
private int mFailTimes = 0;
|
||||
private long mLastSaveTime;
|
||||
private ExecutorService mConfigThreadPool;
|
||||
protected boolean isNotNetRetry; //断网情况是否重试
|
||||
private boolean isNotNetRetry; //断网情况是否重试
|
||||
private boolean taskBreak = false; //任务跳出
|
||||
protected int mThreadNum;
|
||||
/**
|
||||
* 速度限制工具
|
||||
*/
|
||||
protected BandwidthLimiter mSpeedBandUtil;
|
||||
private int mThreadNum;
|
||||
protected BandwidthLimiter mSpeedBandUtil; //速度限制工具
|
||||
protected AriaManager mAridManager;
|
||||
protected boolean isInterrupted = false;
|
||||
private boolean isInterrupted = false;
|
||||
|
||||
private Thread mConfigThread = new Thread(new Runnable() {
|
||||
@Override public void run() {
|
||||
@@ -85,14 +82,14 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
|
||||
protected AbsThreadTask(StateConstance constance, IEventListener listener,
|
||||
SubThreadConfig<TASK_WRAPPER> config) {
|
||||
STATE = constance;
|
||||
sState = constance;
|
||||
sConfig = config;
|
||||
mListener = listener;
|
||||
mConfig = config;
|
||||
mTaskWrapper = mConfig.TASK_WRAPPER;
|
||||
mTaskWrapper = getConfig().TASK_WRAPPER;
|
||||
mEntity = mTaskWrapper.getEntity();
|
||||
mLastSaveTime = System.currentTimeMillis();
|
||||
mConfigThreadPool = Executors.newCachedThreadPool();
|
||||
mThreadNum = STATE.TASK_RECORD.threadRecords.size();
|
||||
mThreadNum = getState().TASK_RECORD.threadRecords.size();
|
||||
mAridManager = AriaManager.getInstance(AriaManager.APP);
|
||||
if (getMaxSpeed() > 0) {
|
||||
mSpeedBandUtil = new BandwidthLimiter(getMaxSpeed(), mThreadNum);
|
||||
@@ -122,21 +119,42 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
* 当前线程是否完成,对于不支持断点的任务,一律未完成 {@code true} 完成;{@code false} 未完成
|
||||
*/
|
||||
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() {
|
||||
return STATE.TASK_RECORD;
|
||||
return getState().TASK_RECORD;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取线程记录
|
||||
*/
|
||||
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() {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
taskBreak = true;
|
||||
if (mConfig.SUPPORT_BP) {
|
||||
if (getConfig().SUPPORT_BP) {
|
||||
final long currentTemp = mChildCurrentLocation;
|
||||
STATE.STOP_NUM++;
|
||||
ALog.d(TAG, String.format("任务【%s】thread__%s__中断【停止位置:%s】", mConfig.TEMP_FILE.getName(),
|
||||
mConfig.THREAD_ID, currentTemp));
|
||||
getState().STOP_NUM++;
|
||||
ALog.d(TAG, String.format("任务【%s】thread__%s__中断【停止位置:%s】", getConfig().TEMP_FILE.getName(),
|
||||
getConfig().THREAD_ID, currentTemp));
|
||||
writeConfig(false, currentTemp);
|
||||
if (STATE.isStop()) {
|
||||
ALog.i(TAG, String.format("任务【%s】已中断", mConfig.TEMP_FILE.getName()));
|
||||
STATE.isRunning = false;
|
||||
if (getState().isStop()) {
|
||||
ALog.i(TAG, String.format("任务【%s】已中断", getConfig().TEMP_FILE.getName()));
|
||||
getState().isRunning = false;
|
||||
}
|
||||
} else {
|
||||
ALog.i(TAG, String.format("任务【%s】已中断", mConfig.TEMP_FILE.getName()));
|
||||
STATE.isRunning = false;
|
||||
ALog.i(TAG, String.format("任务【%s】已中断", getConfig().TEMP_FILE.getName()));
|
||||
getState().isRunning = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -193,7 +211,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
* @return {@code true}正在运行
|
||||
*/
|
||||
public boolean isRunning() {
|
||||
return STATE.isRunning;
|
||||
return getState().isRunning;
|
||||
}
|
||||
|
||||
public boolean isInterrupted() {
|
||||
@@ -203,8 +221,8 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
/**
|
||||
* 获取线程配置信息
|
||||
*/
|
||||
public SubThreadConfig getConfig() {
|
||||
return mConfig;
|
||||
protected SubThreadConfig<TASK_WRAPPER> getConfig() {
|
||||
return sConfig;
|
||||
}
|
||||
|
||||
@Override protected void finalize() throws Throwable {
|
||||
@@ -220,7 +238,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
* @return {@code true} 中断,{@code false} 不是中断
|
||||
*/
|
||||
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() {
|
||||
List<String> partPath = new ArrayList<>();
|
||||
for (int i = 0, len = STATE.TASK_RECORD.threadNum; i < len; i++) {
|
||||
partPath.add(String.format(AbsFileer.SUB_PATH, STATE.TASK_RECORD.filePath, i));
|
||||
for (int i = 0, len = getState().TASK_RECORD.threadNum; i < len; 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) {
|
||||
for (String pp : partPath) {
|
||||
File f = new File(pp);
|
||||
@@ -241,10 +259,10 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
f.delete();
|
||||
}
|
||||
}
|
||||
File targetFile = new File(STATE.TASK_RECORD.filePath);
|
||||
if (targetFile.exists() && targetFile.length() > mEntity.getFileSize()) {
|
||||
File targetFile = new File(getState().TASK_RECORD.filePath);
|
||||
if (targetFile.exists() && targetFile.length() > getEntity().getFileSize()) {
|
||||
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 true;
|
||||
@@ -282,30 +300,31 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
*/
|
||||
public void stop() {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
if (mConfig.SUPPORT_BP) {
|
||||
if (getConfig().SUPPORT_BP) {
|
||||
final long stopLocation;
|
||||
if (getTaskRecord().isBlock) {
|
||||
File blockFile = getBockFile();
|
||||
ThreadRecord tr = getThreadRecord();
|
||||
long block = mEntity.getFileSize() / getTaskRecord().threadRecords.size();
|
||||
long block = getEntity().getFileSize() / getTaskRecord().threadRecords.size();
|
||||
stopLocation =
|
||||
blockFile.exists() ? (tr.threadId * block + blockFile.length()) : tr.threadId * block;
|
||||
} else {
|
||||
stopLocation = mChildCurrentLocation;
|
||||
}
|
||||
STATE.STOP_NUM++;
|
||||
ALog.d(TAG, String.format("任务【%s】thread__%s__停止【当前线程停止位置:%s】", mConfig.TEMP_FILE.getName(),
|
||||
mConfig.THREAD_ID, stopLocation));
|
||||
getState().STOP_NUM++;
|
||||
ALog.d(TAG,
|
||||
String.format("任务【%s】thread__%s__停止【当前线程停止位置:%s】", getConfig().TEMP_FILE.getName(),
|
||||
getConfig().THREAD_ID, stopLocation));
|
||||
writeConfig(false, stopLocation);
|
||||
if (STATE.isStop()) {
|
||||
ALog.i(TAG, String.format("任务【%s】已停止", mConfig.TEMP_FILE.getName()));
|
||||
STATE.isRunning = false;
|
||||
mListener.onStop(STATE.CURRENT_LOCATION);
|
||||
if (getState().isStop()) {
|
||||
ALog.i(TAG, String.format("任务【%s】已停止", getConfig().TEMP_FILE.getName()));
|
||||
getState().isRunning = false;
|
||||
mListener.onStop(getState().CURRENT_LOCATION);
|
||||
}
|
||||
} else {
|
||||
ALog.i(TAG, String.format("任务【%s】已停止", mConfig.TEMP_FILE.getName()));
|
||||
STATE.isRunning = false;
|
||||
mListener.onStop(STATE.CURRENT_LOCATION);
|
||||
ALog.i(TAG, String.format("任务【%s】已停止", getConfig().TEMP_FILE.getName()));
|
||||
getState().isRunning = false;
|
||||
mListener.onStop(getState().CURRENT_LOCATION);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -315,19 +334,20 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
*/
|
||||
protected void progress(long len) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
if (STATE.CURRENT_LOCATION > mEntity.getFileSize() && !mTaskWrapper.asHttp().isChunked()) {
|
||||
if (getState().CURRENT_LOCATION > getEntity().getFileSize() && !getTaskWrapper().asHttp()
|
||||
.isChunked()) {
|
||||
String errorMsg =
|
||||
String.format("下载失败,下载长度超出文件真实长度;currentLocation=%s, fileSize=%s",
|
||||
STATE.CURRENT_LOCATION,
|
||||
mEntity.getFileSize());
|
||||
getState().CURRENT_LOCATION,
|
||||
getEntity().getFileSize());
|
||||
taskBreak = true;
|
||||
fail(mChildCurrentLocation, new FileException(TAG, errorMsg), false);
|
||||
return;
|
||||
}
|
||||
mChildCurrentLocation += len;
|
||||
STATE.CURRENT_LOCATION += len;
|
||||
getState().CURRENT_LOCATION += len;
|
||||
if (System.currentTimeMillis() - mLastSaveTime > 5000
|
||||
&& mChildCurrentLocation < mConfig.END_LOCATION) {
|
||||
&& mChildCurrentLocation < getConfig().END_LOCATION) {
|
||||
mLastSaveTime = System.currentTimeMillis();
|
||||
if (!mConfigThreadPool.isShutdown()) {
|
||||
mConfigThreadPool.execute(mConfigThread);
|
||||
@@ -341,21 +361,22 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
*/
|
||||
public void cancel() {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
if (mConfig.SUPPORT_BP) {
|
||||
STATE.CANCEL_NUM++;
|
||||
if (getConfig().SUPPORT_BP) {
|
||||
getState().CANCEL_NUM++;
|
||||
ALog.d(TAG,
|
||||
String.format("任务【%s】thread__%s__取消", mConfig.TEMP_FILE.getName(), mConfig.THREAD_ID));
|
||||
if (STATE.isCancel()) {
|
||||
if (mConfig.TEMP_FILE.exists() && !(mEntity instanceof UploadEntity)) {
|
||||
mConfig.TEMP_FILE.delete();
|
||||
String.format("任务【%s】thread__%s__取消", getConfig().TEMP_FILE.getName(),
|
||||
getConfig().THREAD_ID));
|
||||
if (getState().isCancel()) {
|
||||
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();
|
||||
}
|
||||
} else {
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -377,18 +398,16 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
* @param subCurrentLocation 当前子线程进度
|
||||
*/
|
||||
protected void fail(final long subCurrentLocation, BaseException ex, boolean needRetry) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
if (ex != null) {
|
||||
ALog.e(TAG, ALog.getExceptionString(ex));
|
||||
}
|
||||
if (mConfig.SUPPORT_BP) {
|
||||
writeConfig(false, subCurrentLocation);
|
||||
retryThis(needRetry && STATE.START_THREAD_NUM != 1);
|
||||
} else {
|
||||
ALog.e(TAG, String.format("任务【%s】执行失败", mConfig.TEMP_FILE.getName()));
|
||||
ErrorHelp.saveError(TAG, "", ALog.getExceptionString(ex));
|
||||
handleFailState(!isBreak());
|
||||
}
|
||||
if (ex != null) {
|
||||
ALog.e(TAG, ALog.getExceptionString(ex));
|
||||
}
|
||||
if (getConfig().SUPPORT_BP) {
|
||||
writeConfig(false, subCurrentLocation);
|
||||
retryThis(needRetry && getState().START_THREAD_NUM != 1);
|
||||
} else {
|
||||
ALog.e(TAG, String.format("任务【%s】执行失败", getConfig().TEMP_FILE.getName()));
|
||||
ErrorHelp.saveError(TAG, "", ALog.getExceptionString(ex));
|
||||
handleFailState(!isBreak());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -398,22 +417,20 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
* @param needRetry 是否可以重试
|
||||
*/
|
||||
private void retryThis(boolean needRetry) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
if (!NetUtils.isConnected(AriaManager.APP) && !isNotNetRetry) {
|
||||
ALog.w(TAG, String.format("任务【%s】thread__%s__重试失败,网络未连接", mConfig.TEMP_FILE.getName(),
|
||||
mConfig.THREAD_ID));
|
||||
}
|
||||
if (mFailTimes < RETRY_NUM && needRetry && (NetUtils.isConnected(AriaManager.APP)
|
||||
|| isNotNetRetry) && !isBreak()) {
|
||||
ALog.w(TAG,
|
||||
String.format("任务【%s】thread__%s__正在重试", mConfig.TEMP_FILE.getName(),
|
||||
mConfig.THREAD_ID));
|
||||
mFailTimes++;
|
||||
handleRetryRecord();
|
||||
ThreadTaskManager.getInstance().retryThread(AbsThreadTask.this);
|
||||
} else {
|
||||
handleFailState(!isBreak());
|
||||
}
|
||||
if (!NetUtils.isConnected(AriaManager.APP) && !isNotNetRetry) {
|
||||
ALog.w(TAG, String.format("任务【%s】thread__%s__重试失败,网络未连接", getConfig().TEMP_FILE.getName(),
|
||||
getConfig().THREAD_ID));
|
||||
}
|
||||
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));
|
||||
mFailTimes++;
|
||||
handleRetryRecord();
|
||||
ThreadTaskManager.getInstance().retryThread(AbsThreadTask.this);
|
||||
} else {
|
||||
handleFailState(!isBreak());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -423,7 +440,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
private void handleRetryRecord() {
|
||||
if (getTaskRecord().isBlock) {
|
||||
ThreadRecord tr = getThreadRecord();
|
||||
long block = mEntity.getFileSize() / getTaskRecord().threadRecords.size();
|
||||
long block = getEntity().getFileSize() / getTaskRecord().threadRecords.size();
|
||||
|
||||
File blockFile = getBockFile();
|
||||
if (blockFile.length() > tr.blockLen) {
|
||||
@@ -431,22 +448,22 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
blockFile.delete();
|
||||
tr.startLocation = block * tr.threadId;
|
||||
tr.isComplete = false;
|
||||
mConfig.START_LOCATION = tr.startLocation;
|
||||
getConfig().START_LOCATION = tr.startLocation;
|
||||
} else if (blockFile.length() < tr.blockLen) {
|
||||
tr.startLocation = block * tr.threadId + blockFile.length();
|
||||
tr.isComplete = false;
|
||||
mConfig.START_LOCATION = tr.startLocation;
|
||||
STATE.CURRENT_LOCATION = getBlockRealTotalSize();
|
||||
getConfig().START_LOCATION = tr.startLocation;
|
||||
getState().CURRENT_LOCATION = getBlockRealTotalSize();
|
||||
ALog.i(TAG, String.format("修正分块【%s】,开始位置:%s,当前进度:%s", blockFile.getPath(), tr.startLocation,
|
||||
STATE.CURRENT_LOCATION));
|
||||
getState().CURRENT_LOCATION));
|
||||
} else {
|
||||
STATE.COMPLETE_THREAD_NUM++;
|
||||
getState().COMPLETE_THREAD_NUM++;
|
||||
tr.isComplete = true;
|
||||
}
|
||||
tr.update();
|
||||
} else {
|
||||
mConfig.START_LOCATION = mChildCurrentLocation == 0 ? mConfig.START_LOCATION
|
||||
: mConfig.THREAD_RECORD.startLocation;
|
||||
getConfig().START_LOCATION = mChildCurrentLocation == 0 ? getConfig().START_LOCATION
|
||||
: getConfig().THREAD_RECORD.startLocation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,7 +473,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
* @return 分块文件
|
||||
*/
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -482,15 +499,13 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
* @param taskNeedReTry 任务是否需要重试{@code true} 需要
|
||||
*/
|
||||
private void handleFailState(boolean taskNeedReTry) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
STATE.FAIL_NUM++;
|
||||
if (STATE.isFail()) {
|
||||
STATE.isRunning = false;
|
||||
// 手动停止不进行fail回调
|
||||
if (!STATE.isStop) {
|
||||
String errorMsg = String.format("任务【%s】执行失败", mConfig.TEMP_FILE.getName());
|
||||
mListener.onFail(taskNeedReTry, new TaskException(TAG, errorMsg));
|
||||
}
|
||||
getState().FAIL_NUM++;
|
||||
if (getState().isFail()) {
|
||||
getState().isRunning = false;
|
||||
// 手动停止不进行fail回调
|
||||
if (!getState().isStop) {
|
||||
String errorMsg = String.format("任务【%s】执行失败", getConfig().TEMP_FILE.getName());
|
||||
mListener.onFail(taskNeedReTry, new TaskException(TAG, errorMsg));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -502,21 +517,19 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
|
||||
* @param record 当前下载进度
|
||||
*/
|
||||
protected void writeConfig(boolean isComplete, final long record) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
ThreadRecord tr = getThreadRecord();
|
||||
if (tr != null) {
|
||||
tr.isComplete = isComplete;
|
||||
if (getTaskRecord().isBlock) {
|
||||
ThreadRecord tr = getThreadRecord();
|
||||
if (tr != null) {
|
||||
tr.isComplete = isComplete;
|
||||
if (getTaskRecord().isBlock) {
|
||||
tr.startLocation = record;
|
||||
} else if (getTaskRecord().isOpenDynamicFile) {
|
||||
tr.startLocation = getConfig().TEMP_FILE.length();
|
||||
} else {
|
||||
if (0 < record && record < getConfig().END_LOCATION) {
|
||||
tr.startLocation = record;
|
||||
} else if (getTaskRecord().isOpenDynamicFile) {
|
||||
tr.startLocation = mConfig.TEMP_FILE.length();
|
||||
} else {
|
||||
if (0 < record && record < mConfig.END_LOCATION) {
|
||||
tr.startLocation = record;
|
||||
}
|
||||
}
|
||||
tr.update();
|
||||
}
|
||||
tr.update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.arialyy.aria.core.common;
|
||||
|
||||
import com.arialyy.aria.core.inf.AbsEntity;
|
||||
import com.arialyy.aria.exception.BaseException;
|
||||
|
||||
public interface OnFileInfoCallback {
|
||||
@@ -30,5 +31,5 @@ public interface OnFileInfoCallback {
|
||||
*
|
||||
* @param e 错误信息
|
||||
*/
|
||||
void onFail(String url, BaseException e, boolean needRetry);
|
||||
void onFail(AbsEntity entity, BaseException e, boolean needRetry);
|
||||
}
|
||||
@@ -374,7 +374,7 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
|
||||
|
||||
private void failDownload(BaseException e, boolean needRetry) {
|
||||
if (mCallback != null) {
|
||||
mCallback.onFail(mEntity.getKey(), e, needRetry);
|
||||
mCallback.onFail(mEntity, e, needRetry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ public abstract class AbsFtpThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTI
|
||||
*/
|
||||
protected FTPClient createClient() {
|
||||
FTPClient client = null;
|
||||
final FtpUrlEntity urlEntity = mTaskWrapper.asFtp().getUrlEntity();
|
||||
final FtpUrlEntity urlEntity = getTaskWrapper().asFtp().getUrlEntity();
|
||||
if (urlEntity.validAddr == null) {
|
||||
try {
|
||||
InetAddress[] ips = InetAddress.getAllByName(urlEntity.hostName);
|
||||
@@ -106,8 +106,8 @@ public abstract class AbsFtpThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTI
|
||||
// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码
|
||||
charSet = "UTF-8";
|
||||
if (reply != FTPReply.COMMAND_IS_SUPERFLUOUS) {
|
||||
if (!TextUtils.isEmpty(mTaskWrapper.asFtp().getCharSet())) {
|
||||
charSet = mTaskWrapper.asFtp().getCharSet();
|
||||
if (!TextUtils.isEmpty(getTaskWrapper().asFtp().getCharSet())) {
|
||||
charSet = getTaskWrapper().asFtp().getCharSet();
|
||||
}
|
||||
}
|
||||
client.setControlEncoding(charSet);
|
||||
@@ -116,7 +116,7 @@ public abstract class AbsFtpThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTI
|
||||
client.enterLocalPassiveMode();
|
||||
client.setFileType(FTP.BINARY_FILE_TYPE);
|
||||
client.setControlKeepAliveTimeout(5000);
|
||||
if (mTaskWrapper.asFtp().getUrlEntity().isFtps) {
|
||||
if (getTaskWrapper().asFtp().getUrlEntity().isFtps) {
|
||||
((FTPSClient) client).execPROT("P");
|
||||
}
|
||||
} catch (java.io.IOException e) {
|
||||
@@ -150,7 +150,7 @@ public abstract class AbsFtpThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTI
|
||||
private FTPClient connect(FTPClient client, InetAddress[] ips, int index, int port) {
|
||||
try {
|
||||
client.connect(ips[index], port);
|
||||
mTaskWrapper.asFtp().getUrlEntity().validAddr = ips[index];
|
||||
getTaskWrapper().asFtp().getUrlEntity().validAddr = ips[index];
|
||||
return client;
|
||||
} catch (java.io.IOException e) {
|
||||
try {
|
||||
|
||||
@@ -1,104 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.common.http;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import com.arialyy.aria.core.download.DGTaskWrapper;
|
||||
import com.arialyy.aria.core.download.DTaskWrapper;
|
||||
import com.arialyy.aria.core.download.DownloadGroupTarget;
|
||||
import com.arialyy.aria.core.inf.AbsTarget;
|
||||
import com.arialyy.aria.core.inf.ITargetHandler;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* HTTP参数委托
|
||||
* @param <TARGET>
|
||||
*/
|
||||
class HttpDelegate<TARGET extends AbsTarget> implements ITargetHandler {
|
||||
private static final String TAG = "PostDelegate";
|
||||
TARGET mTarget;
|
||||
|
||||
HttpDelegate(TARGET target) {
|
||||
mTarget = target;
|
||||
}
|
||||
|
||||
public TARGET setParams(Map<String, String> params) {
|
||||
mTarget.getTaskWrapper().asHttp().setParams(params);
|
||||
if (mTarget instanceof DownloadGroupTarget) {
|
||||
for (DTaskWrapper subTask : ((DGTaskWrapper) mTarget.getTaskWrapper()).getSubTaskWrapper()) {
|
||||
subTask.asHttp().setParams(params);
|
||||
}
|
||||
}
|
||||
return mTarget;
|
||||
}
|
||||
|
||||
public TARGET setParam(String key, String value) {
|
||||
if (TextUtils.isEmpty(key) || TextUtils.isEmpty(value)) {
|
||||
ALog.d(TAG, "key 或value 为空");
|
||||
return mTarget;
|
||||
}
|
||||
Map<String, String> params = mTarget.getTaskWrapper().asHttp().getParams();
|
||||
if (params == null) {
|
||||
params = new HashMap<>();
|
||||
mTarget.getTaskWrapper().asHttp().setParams(params);
|
||||
}
|
||||
params.put(key, value);
|
||||
if (mTarget instanceof DownloadGroupTarget) {
|
||||
for (DTaskWrapper subTask : ((DGTaskWrapper) mTarget.getTaskWrapper()).getSubTaskWrapper()) {
|
||||
subTask.asHttp().setParams(params);
|
||||
}
|
||||
}
|
||||
return mTarget;
|
||||
}
|
||||
|
||||
@Override public void add() {
|
||||
mTarget.add();
|
||||
}
|
||||
|
||||
@Override public void start() {
|
||||
mTarget.start();
|
||||
}
|
||||
|
||||
@Override public void stop() {
|
||||
mTarget.stop();
|
||||
}
|
||||
|
||||
@Override public void resume() {
|
||||
mTarget.resume();
|
||||
}
|
||||
|
||||
@Override public void cancel() {
|
||||
mTarget.cancel();
|
||||
}
|
||||
|
||||
@Override public void save() {
|
||||
mTarget.save();
|
||||
}
|
||||
|
||||
@Override public void cancel(boolean removeFile) {
|
||||
mTarget.cancel(removeFile);
|
||||
}
|
||||
|
||||
@Override public void reTry() {
|
||||
mTarget.reTry();
|
||||
}
|
||||
|
||||
@Override public void reStart() {
|
||||
mTarget.reStart();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.common.http;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import com.arialyy.aria.core.download.DGTaskWrapper;
|
||||
import com.arialyy.aria.core.download.DTaskWrapper;
|
||||
import com.arialyy.aria.core.download.DownloadGroupTarget;
|
||||
import com.arialyy.aria.core.inf.AbsTarget;
|
||||
import com.arialyy.aria.core.inf.ITargetHandler;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* HTTP参数委托
|
||||
*/
|
||||
class HttpDelegate<TARGET extends AbsTarget> implements ITargetHandler {
|
||||
private static final String TAG = "PostDelegate";
|
||||
TARGET mTarget;
|
||||
|
||||
HttpDelegate(TARGET target) {
|
||||
mTarget = target;
|
||||
}
|
||||
|
||||
public TARGET setParams(Map<String, String> params) {
|
||||
mTarget.getTaskWrapper().asHttp().setParams(params);
|
||||
if (mTarget instanceof DownloadGroupTarget) {
|
||||
for (DTaskWrapper subTask : ((DGTaskWrapper) mTarget.getTaskWrapper()).getSubTaskWrapper()) {
|
||||
subTask.asHttp().setParams(params);
|
||||
}
|
||||
}
|
||||
return mTarget;
|
||||
}
|
||||
|
||||
public TARGET setParam(String key, String value) {
|
||||
if (TextUtils.isEmpty(key) || TextUtils.isEmpty(value)) {
|
||||
ALog.d(TAG, "key 或value 为空");
|
||||
return mTarget;
|
||||
}
|
||||
Map<String, String> params = mTarget.getTaskWrapper().asHttp().getParams();
|
||||
if (params == null) {
|
||||
params = new HashMap<>();
|
||||
mTarget.getTaskWrapper().asHttp().setParams(params);
|
||||
}
|
||||
params.put(key, value);
|
||||
if (mTarget instanceof DownloadGroupTarget) {
|
||||
for (DTaskWrapper subTask : ((DGTaskWrapper) mTarget.getTaskWrapper()).getSubTaskWrapper()) {
|
||||
subTask.asHttp().setParams(params);
|
||||
}
|
||||
}
|
||||
return mTarget;
|
||||
}
|
||||
|
||||
@Override public void add() {
|
||||
mTarget.add();
|
||||
}
|
||||
|
||||
@Override public void start() {
|
||||
mTarget.start();
|
||||
}
|
||||
|
||||
@Override public void stop() {
|
||||
mTarget.stop();
|
||||
}
|
||||
|
||||
@Override public void resume() {
|
||||
mTarget.resume();
|
||||
}
|
||||
|
||||
@Override public void cancel() {
|
||||
mTarget.cancel();
|
||||
}
|
||||
|
||||
@Override public void save() {
|
||||
mTarget.save();
|
||||
}
|
||||
|
||||
@Override public void cancel(boolean removeFile) {
|
||||
mTarget.cancel(removeFile);
|
||||
}
|
||||
|
||||
@Override public void reTry() {
|
||||
mTarget.reTry();
|
||||
}
|
||||
|
||||
@Override public void reStart() {
|
||||
mTarget.reStart();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,20 @@ 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;
|
||||
@@ -80,7 +90,31 @@ public class HttpHeaderDelegate<TARGET extends AbsTarget>
|
||||
return mTarget;
|
||||
}
|
||||
|
||||
public void addHeader(AbsTaskWrapper taskWrapper, String key, String value) {
|
||||
public TARGET setFileLenAdapter(AbsHttpFileLenAdapter adapter) {
|
||||
if (adapter == null) {
|
||||
throw new IllegalArgumentException("adapter为空");
|
||||
}
|
||||
try {
|
||||
adapter.clone();
|
||||
mTarget.getTaskWrapper().asHttp().setFileLenAdapter((IHttpFileLenAdapter) adapter.clone());
|
||||
} 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);
|
||||
|
||||
return mTarget;
|
||||
}
|
||||
|
||||
private void addHeader(AbsTaskWrapper taskWrapper, String key, String value) {
|
||||
HttpTaskDelegate taskDelegate = taskWrapper.asHttp();
|
||||
if (taskDelegate.getHeaders().get(key) == null) {
|
||||
taskDelegate.getHeaders().put(key, value);
|
||||
@@ -89,7 +123,7 @@ public class HttpHeaderDelegate<TARGET extends AbsTarget>
|
||||
}
|
||||
}
|
||||
|
||||
public void addHeaders(AbsTaskWrapper taskWrapper, Map<String, String> headers) {
|
||||
private void addHeaders(AbsTaskWrapper taskWrapper, Map<String, String> headers) {
|
||||
HttpTaskDelegate taskDelegate = taskWrapper.asHttp();
|
||||
/*
|
||||
两个map比较逻辑
|
||||
|
||||
@@ -1,187 +1,198 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.arialyy.aria.core.common.http;
|
||||
|
||||
import com.arialyy.aria.core.common.RequestEnum;
|
||||
import com.arialyy.aria.core.inf.ITargetHeadDelegate;
|
||||
import java.net.CookieManager;
|
||||
import java.net.Proxy;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Http任务设置的信息,如:cookie、请求参数
|
||||
*/
|
||||
public class HttpTaskDelegate implements ITargetHeadDelegate {
|
||||
|
||||
private CookieManager cookieManager;
|
||||
|
||||
/**
|
||||
* 请求参数
|
||||
*/
|
||||
private Map<String, String> params;
|
||||
|
||||
/**
|
||||
* http 请求头
|
||||
*/
|
||||
private Map<String, String> headers = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 字符编码,默认为"utf-8"
|
||||
*/
|
||||
private String charSet = "utf-8";
|
||||
|
||||
/**
|
||||
* 网络请求类型
|
||||
*/
|
||||
private RequestEnum requestEnum = RequestEnum.GET;
|
||||
|
||||
/**
|
||||
* 是否使用服务器通过content-disposition传递的文件名,内容格式{@code attachment; filename="filename.jpg"} {@code true}
|
||||
* 使用
|
||||
*/
|
||||
private boolean useServerFileName = false;
|
||||
|
||||
/**
|
||||
* 重定向链接
|
||||
*/
|
||||
private String redirectUrl = "";
|
||||
|
||||
/**
|
||||
* 是否是chunk模式
|
||||
*/
|
||||
private boolean isChunked = false;
|
||||
/**
|
||||
* 文件上传需要的key
|
||||
*/
|
||||
private String attachment;
|
||||
/**
|
||||
* 上传的文件类型
|
||||
*/
|
||||
private String contentType = "multipart/form-data";
|
||||
private String userAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)";
|
||||
|
||||
private Proxy proxy;
|
||||
/**
|
||||
* 文件上传表单
|
||||
*/
|
||||
private Map<String, String> formFields = new HashMap<>();
|
||||
|
||||
public Map<String, String> getFormFields() {
|
||||
return formFields;
|
||||
}
|
||||
|
||||
public void setFormFields(Map<String, String> formFields) {
|
||||
this.formFields = formFields;
|
||||
}
|
||||
|
||||
public String getAttachment() {
|
||||
return attachment;
|
||||
}
|
||||
|
||||
public void setAttachment(String attachment) {
|
||||
this.attachment = attachment;
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public void setContentType(String contentType) {
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
public String getUserAgent() {
|
||||
return userAgent;
|
||||
}
|
||||
|
||||
public void setUserAgent(String userAgent) {
|
||||
this.userAgent = userAgent;
|
||||
}
|
||||
|
||||
public boolean isChunked() {
|
||||
return isChunked;
|
||||
}
|
||||
|
||||
public void setChunked(boolean chunked) {
|
||||
isChunked = chunked;
|
||||
}
|
||||
|
||||
public CookieManager getCookieManager() {
|
||||
return cookieManager;
|
||||
}
|
||||
|
||||
public void setCookieManager(CookieManager cookieManager) {
|
||||
this.cookieManager = cookieManager;
|
||||
}
|
||||
|
||||
public Proxy getProxy() {
|
||||
return proxy;
|
||||
}
|
||||
|
||||
public void setProxy(Proxy proxy) {
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
||||
public Map<String, String> getHeaders() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
public void setHeaders(Map<String, String> headers) {
|
||||
this.headers = headers;
|
||||
}
|
||||
|
||||
public String getCharSet() {
|
||||
return charSet;
|
||||
}
|
||||
|
||||
public void setCharSet(String charSet) {
|
||||
this.charSet = charSet;
|
||||
}
|
||||
|
||||
public RequestEnum getRequestEnum() {
|
||||
return requestEnum;
|
||||
}
|
||||
|
||||
public void setRequestEnum(RequestEnum requestEnum) {
|
||||
this.requestEnum = requestEnum;
|
||||
}
|
||||
|
||||
public boolean isUseServerFileName() {
|
||||
return useServerFileName;
|
||||
}
|
||||
|
||||
public void setUseServerFileName(boolean useServerFileName) {
|
||||
this.useServerFileName = useServerFileName;
|
||||
}
|
||||
|
||||
public String getRedirectUrl() {
|
||||
return redirectUrl;
|
||||
}
|
||||
|
||||
public void setRedirectUrl(String redirectUrl) {
|
||||
this.redirectUrl = redirectUrl;
|
||||
}
|
||||
|
||||
public Map<String, String> getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public void setParams(Map<String, String> params) {
|
||||
this.params = params;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.arialyy.aria.core.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.net.CookieManager;
|
||||
import java.net.Proxy;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Http任务设置的信息,如:cookie、请求参数
|
||||
*/
|
||||
public class HttpTaskDelegate implements ITargetHeadDelegate {
|
||||
|
||||
private CookieManager cookieManager;
|
||||
|
||||
/**
|
||||
* 请求参数
|
||||
*/
|
||||
private Map<String, String> params;
|
||||
|
||||
/**
|
||||
* http 请求头
|
||||
*/
|
||||
private Map<String, String> headers = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 字符编码,默认为"utf-8"
|
||||
*/
|
||||
private String charSet = "utf-8";
|
||||
|
||||
/**
|
||||
* 网络请求类型
|
||||
*/
|
||||
private RequestEnum requestEnum = RequestEnum.GET;
|
||||
|
||||
/**
|
||||
* 是否使用服务器通过content-disposition传递的文件名,内容格式{@code attachment; filename="filename.jpg"} {@code true}
|
||||
* 使用
|
||||
*/
|
||||
private boolean useServerFileName = false;
|
||||
|
||||
/**
|
||||
* 重定向链接
|
||||
*/
|
||||
private String redirectUrl = "";
|
||||
|
||||
/**
|
||||
* 是否是chunk模式
|
||||
*/
|
||||
private boolean isChunked = false;
|
||||
/**
|
||||
* 文件上传需要的key
|
||||
*/
|
||||
private String attachment;
|
||||
/**
|
||||
* 上传的文件类型
|
||||
*/
|
||||
private String contentType = "multipart/form-data";
|
||||
private String userAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)";
|
||||
|
||||
private Proxy proxy;
|
||||
/**
|
||||
* 文件上传表单
|
||||
*/
|
||||
private Map<String, String> formFields = new HashMap<>();
|
||||
|
||||
private IHttpFileLenAdapter fileLenAdapter;
|
||||
|
||||
public IHttpFileLenAdapter getFileLenAdapter() {
|
||||
return fileLenAdapter;
|
||||
}
|
||||
|
||||
public void setFileLenAdapter(IHttpFileLenAdapter fileLenAdapter) {
|
||||
this.fileLenAdapter = fileLenAdapter;
|
||||
}
|
||||
|
||||
public Map<String, String> getFormFields() {
|
||||
return formFields;
|
||||
}
|
||||
|
||||
public void setFormFields(Map<String, String> formFields) {
|
||||
this.formFields = formFields;
|
||||
}
|
||||
|
||||
public String getAttachment() {
|
||||
return attachment;
|
||||
}
|
||||
|
||||
public void setAttachment(String attachment) {
|
||||
this.attachment = attachment;
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public void setContentType(String contentType) {
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
public String getUserAgent() {
|
||||
return userAgent;
|
||||
}
|
||||
|
||||
public void setUserAgent(String userAgent) {
|
||||
this.userAgent = userAgent;
|
||||
}
|
||||
|
||||
public boolean isChunked() {
|
||||
return isChunked;
|
||||
}
|
||||
|
||||
public void setChunked(boolean chunked) {
|
||||
isChunked = chunked;
|
||||
}
|
||||
|
||||
public CookieManager getCookieManager() {
|
||||
return cookieManager;
|
||||
}
|
||||
|
||||
public void setCookieManager(CookieManager cookieManager) {
|
||||
this.cookieManager = cookieManager;
|
||||
}
|
||||
|
||||
public Proxy getProxy() {
|
||||
return proxy;
|
||||
}
|
||||
|
||||
public void setProxy(Proxy proxy) {
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
||||
public Map<String, String> getHeaders() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
public void setHeaders(Map<String, String> headers) {
|
||||
this.headers = headers;
|
||||
}
|
||||
|
||||
public String getCharSet() {
|
||||
return charSet;
|
||||
}
|
||||
|
||||
public void setCharSet(String charSet) {
|
||||
this.charSet = charSet;
|
||||
}
|
||||
|
||||
public RequestEnum getRequestEnum() {
|
||||
return requestEnum;
|
||||
}
|
||||
|
||||
public void setRequestEnum(RequestEnum requestEnum) {
|
||||
this.requestEnum = requestEnum;
|
||||
}
|
||||
|
||||
public boolean isUseServerFileName() {
|
||||
return useServerFileName;
|
||||
}
|
||||
|
||||
public void setUseServerFileName(boolean useServerFileName) {
|
||||
this.useServerFileName = useServerFileName;
|
||||
}
|
||||
|
||||
public String getRedirectUrl() {
|
||||
return redirectUrl;
|
||||
}
|
||||
|
||||
public void setRedirectUrl(String redirectUrl) {
|
||||
this.redirectUrl = redirectUrl;
|
||||
}
|
||||
|
||||
public Map<String, String> getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public void setParams(Map<String, String> params) {
|
||||
this.params = params;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,171 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.download;
|
||||
|
||||
import android.support.annotation.CheckResult;
|
||||
import android.text.TextUtils;
|
||||
import com.arialyy.aria.core.inf.AbsEntity;
|
||||
import com.arialyy.aria.core.inf.AbsTarget;
|
||||
import com.arialyy.aria.core.inf.AbsTaskWrapper;
|
||||
import com.arialyy.aria.core.manager.SubTaskManager;
|
||||
import com.arialyy.aria.core.queue.DownloadGroupTaskQueue;
|
||||
import com.arialyy.aria.orm.DbEntity;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2017/7/26.
|
||||
*/
|
||||
abstract class AbsDGTarget<TARGET extends AbsDGTarget> extends AbsTarget<TARGET> {
|
||||
|
||||
///**
|
||||
// * 组任务名
|
||||
// */
|
||||
//String mGroupHash;
|
||||
///**
|
||||
// * 文件夹临时路径
|
||||
// */
|
||||
//String mDirPathTemp;
|
||||
///**
|
||||
// * 是否需要修改路径
|
||||
// */
|
||||
//boolean needModifyPath = false;
|
||||
|
||||
private SubTaskManager mSubTaskManager;
|
||||
|
||||
/**
|
||||
* 获取子任务管理器
|
||||
*
|
||||
* @return 子任务管理器
|
||||
*/
|
||||
@CheckResult
|
||||
public SubTaskManager getSubTaskManager() {
|
||||
if (mSubTaskManager == null) {
|
||||
mSubTaskManager = new SubTaskManager(getTargetName(), getTaskWrapper());
|
||||
}
|
||||
return mSubTaskManager;
|
||||
}
|
||||
|
||||
@Override public DownloadGroupEntity getEntity() {
|
||||
return (DownloadGroupEntity) super.getEntity();
|
||||
}
|
||||
|
||||
@Override public DGTaskWrapper getTaskWrapper() {
|
||||
return (DGTaskWrapper) super.getTaskWrapper();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置任务组别名
|
||||
*/
|
||||
@CheckResult
|
||||
public TARGET setGroupAlias(String alias) {
|
||||
if (TextUtils.isEmpty(alias)) return (TARGET) this;
|
||||
getEntity().setAlias(alias);
|
||||
return (TARGET) this;
|
||||
}
|
||||
|
||||
//@Override public boolean taskExists() {
|
||||
// return DbEntity.checkDataExist(DownloadGroupEntity.class, "groupHash=?", mGroupHash);
|
||||
//}
|
||||
|
||||
///**
|
||||
// * 设置任务组的文件夹路径,在Aria中,任务组的所有子任务都会下载到以任务组组名的文件夹中。
|
||||
// * 如:groupDirPath = "/mnt/sdcard/download/group_test"
|
||||
// * <pre>
|
||||
// * {@code
|
||||
// * + mnt
|
||||
// * + sdcard
|
||||
// * + download
|
||||
// * + group_test
|
||||
// * - task1.apk
|
||||
// * - task2.apk
|
||||
// * - task3.apk
|
||||
// * ....
|
||||
// *
|
||||
// * }
|
||||
// * </pre>
|
||||
// *
|
||||
// * @param dirPath 任务组保存文件夹路径
|
||||
// */
|
||||
//@CheckResult
|
||||
//public TARGET setDirPath(String dirPath) {
|
||||
// mDirPathTemp = dirPath;
|
||||
// return (TARGET) this;
|
||||
//}
|
||||
|
||||
//@Override public boolean isRunning() {
|
||||
// DownloadGroupTask task = DownloadGroupTaskQueue.getInstance().getTask(getEntity().getKey());
|
||||
// return task != null && task.isRunning();
|
||||
//}
|
||||
|
||||
///**
|
||||
// * 改变任务组文件夹路径,修改文件夹路径会将子任务所有路径更换
|
||||
// *
|
||||
// * @param newDirPath 新的文件夹路径
|
||||
// */
|
||||
//void reChangeDirPath(String newDirPath) {
|
||||
// List<DTaskWrapper> subTasks = getTaskWrapper().getSubTaskWrapper();
|
||||
// if (subTasks != null && !subTasks.isEmpty()) {
|
||||
// List<DbEntity> des = new ArrayList<>();
|
||||
// for (DTaskWrapper dte : subTasks) {
|
||||
// DownloadEntity de = dte.getEntity();
|
||||
// String oldPath = de.getDownloadPath();
|
||||
// String newPath = newDirPath + "/" + de.getFileName();
|
||||
// File file = new File(oldPath);
|
||||
// if (file.exists()) {
|
||||
// file.renameTo(new File(newPath));
|
||||
// }
|
||||
// de.setDownloadPath(newPath);
|
||||
// des.add(de);
|
||||
// }
|
||||
// AbsEntity.saveAll(des);
|
||||
// }
|
||||
//}
|
||||
|
||||
///**
|
||||
// * 检查并设置文件夹路径
|
||||
// *
|
||||
// * @return {@code true} 合法
|
||||
// */
|
||||
//boolean checkDirPath() {
|
||||
// if (TextUtils.isEmpty(mDirPathTemp)) {
|
||||
// ALog.e(TAG, "文件夹路径不能为null");
|
||||
// return false;
|
||||
// } else if (!mDirPathTemp.startsWith("/")) {
|
||||
// ALog.e(TAG, "文件夹路径【" + mDirPathTemp + "】错误");
|
||||
// return false;
|
||||
// }
|
||||
// File file = new File(mDirPathTemp);
|
||||
// if (file.isFile()) {
|
||||
// ALog.e(TAG, "路径【" + mDirPathTemp + "】是文件,请设置文件夹路径");
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// if (TextUtils.isEmpty(getEntity().getDirPath()) || !getEntity().getDirPath()
|
||||
// .equals(mDirPathTemp)) {
|
||||
// if (!file.exists()) {
|
||||
// file.mkdirs();
|
||||
// }
|
||||
// needModifyPath = true;
|
||||
// getEntity().setDirPath(mDirPathTemp);
|
||||
// ALog.i(TAG, String.format("文件夹路径改变,将更新文件夹路径为:%s", mDirPathTemp));
|
||||
// }
|
||||
//
|
||||
// return true;
|
||||
//}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.download;
|
||||
|
||||
import android.support.annotation.CheckResult;
|
||||
import android.text.TextUtils;
|
||||
import com.arialyy.aria.core.inf.AbsEntity;
|
||||
import com.arialyy.aria.core.inf.AbsTarget;
|
||||
import com.arialyy.aria.core.inf.AbsTaskWrapper;
|
||||
import com.arialyy.aria.core.manager.SubTaskManager;
|
||||
import com.arialyy.aria.core.queue.DownloadGroupTaskQueue;
|
||||
import com.arialyy.aria.orm.DbEntity;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2017/7/26.
|
||||
*/
|
||||
abstract class AbsDGTarget<TARGET extends AbsDGTarget> extends AbsTarget<TARGET> {
|
||||
|
||||
private SubTaskManager mSubTaskManager;
|
||||
|
||||
/**
|
||||
* 获取子任务管理器
|
||||
*
|
||||
* @return 子任务管理器
|
||||
*/
|
||||
@CheckResult
|
||||
public SubTaskManager getSubTaskManager() {
|
||||
if (mSubTaskManager == null) {
|
||||
mSubTaskManager = new SubTaskManager(getTargetName(), getTaskWrapper());
|
||||
}
|
||||
return mSubTaskManager;
|
||||
}
|
||||
|
||||
@Override public DownloadGroupEntity getEntity() {
|
||||
return (DownloadGroupEntity) super.getEntity();
|
||||
}
|
||||
|
||||
@Override public DGTaskWrapper getTaskWrapper() {
|
||||
return (DGTaskWrapper) super.getTaskWrapper();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置任务组别名
|
||||
*/
|
||||
@CheckResult
|
||||
public TARGET setGroupAlias(String alias) {
|
||||
if (TextUtils.isEmpty(alias)) return (TARGET) this;
|
||||
getEntity().setAlias(alias);
|
||||
return (TARGET) this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ class DownloadGroupListener
|
||||
mTaskWrapper.setState(state);
|
||||
mEntity.setState(state);
|
||||
if (state == IEntity.STATE_CANCEL) {
|
||||
CommonUtil.delGroupTaskRecord(mTaskWrapper.isRemoveFile(), mEntity);
|
||||
CommonUtil.delGroupTaskRecord(mEntity, mTaskWrapper.isRemoveFile());
|
||||
return;
|
||||
} else if (state == IEntity.STATE_STOP) {
|
||||
mEntity.setStopTime(System.currentTimeMillis());
|
||||
|
||||
@@ -19,6 +19,8 @@ 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;
|
||||
import com.arialyy.aria.exception.ParamException;
|
||||
@@ -157,6 +159,13 @@ public class DownloadGroupTarget extends AbsDGTarget<DownloadGroupTarget> implem
|
||||
return mGroupDelegate.setSubFileName(subTaskFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果你需要使用header中特定的key来设置文件长度,或有定制文件长度的需要,那么你可以通过该方法自行处理文件长度
|
||||
*/
|
||||
public DownloadGroupTarget setFileLenAdapter(AbsHttpFileLenAdapter adapter) {
|
||||
return mHeaderDelegate.setFileLenAdapter(adapter);
|
||||
}
|
||||
|
||||
@Override public int getTargetType() {
|
||||
return GROUP_HTTP;
|
||||
}
|
||||
@@ -175,17 +184,11 @@ public class DownloadGroupTarget extends AbsDGTarget<DownloadGroupTarget> implem
|
||||
|
||||
@CheckResult
|
||||
@Override public DownloadGroupTarget addHeader(@NonNull String key, @NonNull String value) {
|
||||
for (DTaskWrapper subTask : getTaskWrapper().getSubTaskWrapper()) {
|
||||
mHeaderDelegate.addHeader(subTask, key, value);
|
||||
}
|
||||
return mHeaderDelegate.addHeader(key, value);
|
||||
}
|
||||
|
||||
@CheckResult
|
||||
@Override public DownloadGroupTarget addHeaders(Map<String, String> headers) {
|
||||
for (DTaskWrapper subTask : getTaskWrapper().getSubTaskWrapper()) {
|
||||
mHeaderDelegate.addHeaders(subTask, headers);
|
||||
}
|
||||
return mHeaderDelegate.addHeaders(headers);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,147 +1,156 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.download;
|
||||
|
||||
import android.support.annotation.CheckResult;
|
||||
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.IHttpHeaderDelegate;
|
||||
import java.net.Proxy;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2016/12/5.
|
||||
* https://github.com/AriaLyy/Aria
|
||||
*/
|
||||
public class DownloadTarget extends AbsDTarget<DownloadTarget>
|
||||
implements IHttpHeaderDelegate<DownloadTarget> {
|
||||
private HttpHeaderDelegate<DownloadTarget> mHeaderDelegate;
|
||||
private DNormalDelegate<DownloadTarget> mNormalDelegate;
|
||||
|
||||
DownloadTarget(DownloadEntity entity, String targetName) {
|
||||
this(entity.getUrl(), targetName);
|
||||
}
|
||||
|
||||
DownloadTarget(String url, String targetName) {
|
||||
mNormalDelegate = new DNormalDelegate<>(this, url, targetName);
|
||||
mHeaderDelegate = new HttpHeaderDelegate<>(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post处理
|
||||
*/
|
||||
@CheckResult
|
||||
public PostDelegate asPost() {
|
||||
return new PostDelegate<>(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* get参数传递
|
||||
*/
|
||||
@CheckResult
|
||||
public GetDelegate asGet() {
|
||||
return new GetDelegate<>(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否使用服务器通过content-disposition传递的文件名,内容格式{@code attachment;filename=***}
|
||||
* 如果获取不到服务器文件名,则使用用户设置的文件名
|
||||
*
|
||||
* @param use {@code true} 使用
|
||||
*/
|
||||
@CheckResult
|
||||
public DownloadTarget useServerFileName(boolean use) {
|
||||
getTaskWrapper().asHttp().setUseServerFileName(use);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置文件存储路径,如果需要修改新的文件名,修改路径便可。
|
||||
* 如:原文件路径 /mnt/sdcard/test.zip
|
||||
* 如果需要将test.zip改为game.zip,只需要重新设置文件路径为:/mnt/sdcard/game.zip
|
||||
*
|
||||
* @param filePath 路径必须为文件路径,不能为文件夹路径
|
||||
*/
|
||||
@CheckResult
|
||||
public DownloadTarget setFilePath(@NonNull String filePath) {
|
||||
mNormalDelegate.setTempFilePath(filePath);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置文件存储路径,如果需要修改新的文件名,修改路径便可。
|
||||
* 如:原文件路径 /mnt/sdcard/test.zip
|
||||
* 如果需要将test.zip改为game.zip,只需要重新设置文件路径为:/mnt/sdcard/game.zip
|
||||
*
|
||||
* @param filePath 路径必须为文件路径,不能为文件夹路径
|
||||
* @param forceDownload {@code true}强制下载,不考虑文件路径是否被占用
|
||||
*/
|
||||
@CheckResult
|
||||
public DownloadTarget setFilePath(@NonNull String filePath, boolean forceDownload) {
|
||||
mNormalDelegate.setTempFilePath(filePath);
|
||||
mNormalDelegate.setForceDownload(forceDownload);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从header中获取文件描述信息
|
||||
*/
|
||||
public String getContentDisposition() {
|
||||
return getEntity().getDisposition();
|
||||
}
|
||||
|
||||
@Override public DownloadTarget updateUrl(String newUrl) {
|
||||
return mNormalDelegate.updateUrl(newUrl);
|
||||
}
|
||||
|
||||
@Override public int getTargetType() {
|
||||
return HTTP;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置URL的代理
|
||||
*
|
||||
* @param proxy {@link Proxy}
|
||||
*/
|
||||
@CheckResult
|
||||
@Override public DownloadTarget setUrlProxy(Proxy proxy) {
|
||||
return mHeaderDelegate.setUrlProxy(proxy);
|
||||
}
|
||||
|
||||
@CheckResult
|
||||
@Override public DownloadTarget addHeader(@NonNull String key, @NonNull String value) {
|
||||
return mHeaderDelegate.addHeader(key, value);
|
||||
}
|
||||
|
||||
@CheckResult
|
||||
@Override public DownloadTarget addHeaders(Map<String, String> headers) {
|
||||
return mHeaderDelegate.addHeaders(headers);
|
||||
}
|
||||
|
||||
@Override protected boolean checkEntity() {
|
||||
return mNormalDelegate.checkEntity();
|
||||
}
|
||||
|
||||
@Override public boolean isRunning() {
|
||||
return mNormalDelegate.isRunning();
|
||||
}
|
||||
|
||||
@Override public boolean taskExists() {
|
||||
return mNormalDelegate.taskExists();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.download;
|
||||
|
||||
import android.support.annotation.CheckResult;
|
||||
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.IHttpFileLenAdapter;
|
||||
import com.arialyy.aria.core.inf.IHttpHeaderDelegate;
|
||||
import java.net.Proxy;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2016/12/5.
|
||||
* https://github.com/AriaLyy/Aria
|
||||
*/
|
||||
public class DownloadTarget extends AbsDTarget<DownloadTarget>
|
||||
implements IHttpHeaderDelegate<DownloadTarget> {
|
||||
private HttpHeaderDelegate<DownloadTarget> mHeaderDelegate;
|
||||
private DNormalDelegate<DownloadTarget> mNormalDelegate;
|
||||
|
||||
DownloadTarget(DownloadEntity entity, String targetName) {
|
||||
this(entity.getUrl(), targetName);
|
||||
}
|
||||
|
||||
DownloadTarget(String url, String targetName) {
|
||||
mNormalDelegate = new DNormalDelegate<>(this, url, targetName);
|
||||
mHeaderDelegate = new HttpHeaderDelegate<>(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post处理
|
||||
*/
|
||||
@CheckResult
|
||||
public PostDelegate asPost() {
|
||||
return new PostDelegate<>(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* get参数传递
|
||||
*/
|
||||
@CheckResult
|
||||
public GetDelegate asGet() {
|
||||
return new GetDelegate<>(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否使用服务器通过content-disposition传递的文件名,内容格式{@code attachment;filename=***}
|
||||
* 如果获取不到服务器文件名,则使用用户设置的文件名
|
||||
*
|
||||
* @param use {@code true} 使用
|
||||
*/
|
||||
@CheckResult
|
||||
public DownloadTarget useServerFileName(boolean use) {
|
||||
getTaskWrapper().asHttp().setUseServerFileName(use);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置文件存储路径,如果需要修改新的文件名,修改路径便可。
|
||||
* 如:原文件路径 /mnt/sdcard/test.zip
|
||||
* 如果需要将test.zip改为game.zip,只需要重新设置文件路径为:/mnt/sdcard/game.zip
|
||||
*
|
||||
* @param filePath 路径必须为文件路径,不能为文件夹路径
|
||||
*/
|
||||
@CheckResult
|
||||
public DownloadTarget setFilePath(@NonNull String filePath) {
|
||||
mNormalDelegate.setTempFilePath(filePath);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置文件存储路径,如果需要修改新的文件名,修改路径便可。
|
||||
* 如:原文件路径 /mnt/sdcard/test.zip
|
||||
* 如果需要将test.zip改为game.zip,只需要重新设置文件路径为:/mnt/sdcard/game.zip
|
||||
*
|
||||
* @param filePath 路径必须为文件路径,不能为文件夹路径
|
||||
* @param forceDownload {@code true}强制下载,不考虑文件路径是否被占用
|
||||
*/
|
||||
@CheckResult
|
||||
public DownloadTarget setFilePath(@NonNull String filePath, boolean forceDownload) {
|
||||
mNormalDelegate.setTempFilePath(filePath);
|
||||
mNormalDelegate.setForceDownload(forceDownload);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果你需要使用header中特定的key来设置文件长度,或有定制文件长度的需要,那么你可以通过该方法自行处理文件长度
|
||||
*/
|
||||
public DownloadTarget setFileLenAdapter(IHttpFileLenAdapter adapter) {
|
||||
//return mHeaderDelegate.setFileLenAdapter(adapter);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从header中获取文件描述信息
|
||||
*/
|
||||
public String getContentDisposition() {
|
||||
return getEntity().getDisposition();
|
||||
}
|
||||
|
||||
@Override public DownloadTarget updateUrl(String newUrl) {
|
||||
return mNormalDelegate.updateUrl(newUrl);
|
||||
}
|
||||
|
||||
@Override public int getTargetType() {
|
||||
return HTTP;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置URL的代理
|
||||
*
|
||||
* @param proxy {@link Proxy}
|
||||
*/
|
||||
@CheckResult
|
||||
@Override public DownloadTarget setUrlProxy(Proxy proxy) {
|
||||
return mHeaderDelegate.setUrlProxy(proxy);
|
||||
}
|
||||
|
||||
@CheckResult
|
||||
@Override public DownloadTarget addHeader(@NonNull String key, @NonNull String value) {
|
||||
return mHeaderDelegate.addHeader(key, value);
|
||||
}
|
||||
|
||||
@CheckResult
|
||||
@Override public DownloadTarget addHeaders(Map<String, String> headers) {
|
||||
return mHeaderDelegate.addHeaders(headers);
|
||||
}
|
||||
|
||||
@Override protected boolean checkEntity() {
|
||||
return mNormalDelegate.checkEntity();
|
||||
}
|
||||
|
||||
@Override public boolean isRunning() {
|
||||
return mNormalDelegate.isRunning();
|
||||
}
|
||||
|
||||
@Override public boolean taskExists() {
|
||||
return mNormalDelegate.taskExists();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,8 +38,7 @@ class FtpFileInfoThread extends AbsFtpInfoThread<DownloadEntity, DTaskWrapper> {
|
||||
@Override protected void handleFile(String remotePath, FTPFile ftpFile) {
|
||||
super.handleFile(remotePath, ftpFile);
|
||||
if (!CommonUtil.checkSDMemorySpace(mEntity.getDownloadPath(), ftpFile.getSize())) {
|
||||
mCallback.onFail(mEntity.getUrl(),
|
||||
new AriaIOException(TAG,
|
||||
mCallback.onFail(mEntity, new AriaIOException(TAG,
|
||||
String.format("获取ftp文件信息失败,内存空间不足, filePath: %s", mEntity.getDownloadPath())),
|
||||
false);
|
||||
}
|
||||
|
||||
@@ -48,31 +48,31 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
FtpThreadTask(StateConstance constance, IDownloadListener listener,
|
||||
SubThreadConfig<DTaskWrapper> downloadInfo) {
|
||||
super(constance, listener, downloadInfo);
|
||||
isOpenDynamicFile = STATE.TASK_RECORD.isOpenDynamicFile;
|
||||
isBlock = STATE.TASK_RECORD.isBlock;
|
||||
isOpenDynamicFile = getState().TASK_RECORD.isOpenDynamicFile;
|
||||
isBlock = getState().TASK_RECORD.isBlock;
|
||||
}
|
||||
|
||||
@Override public FtpThreadTask call() throws Exception {
|
||||
super.call();
|
||||
if (mConfig.THREAD_RECORD.isComplete) {
|
||||
if (getConfig().THREAD_RECORD.isComplete) {
|
||||
handleComplete();
|
||||
return this;
|
||||
}
|
||||
mChildCurrentLocation = mConfig.START_LOCATION;
|
||||
mChildCurrentLocation = getConfig().START_LOCATION;
|
||||
FTPClient client = null;
|
||||
InputStream is = null;
|
||||
|
||||
try {
|
||||
ALog.d(TAG,
|
||||
String.format("任务【%s】线程__%s__开始下载【开始位置 : %s,结束位置:%s】", mConfig.TEMP_FILE.getName(),
|
||||
mConfig.THREAD_ID, mConfig.START_LOCATION, mConfig.END_LOCATION));
|
||||
String.format("任务【%s】线程__%s__开始下载【开始位置 : %s,结束位置:%s】", getConfig().TEMP_FILE.getName(),
|
||||
getConfig().THREAD_ID, getConfig().START_LOCATION, getConfig().END_LOCATION));
|
||||
client = createClient();
|
||||
if (client == null) {
|
||||
fail(mChildCurrentLocation, new TaskException(TAG, "ftp client 创建失败"));
|
||||
return this;
|
||||
}
|
||||
if (mConfig.START_LOCATION > 0) {
|
||||
client.setRestartOffset(mConfig.START_LOCATION);
|
||||
if (getConfig().START_LOCATION > 0) {
|
||||
client.setRestartOffset(getConfig().START_LOCATION);
|
||||
}
|
||||
//发送第二次指令时,还需要再做一次判断
|
||||
int reply = client.getReplyCode();
|
||||
@@ -84,7 +84,7 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
return this;
|
||||
}
|
||||
String remotePath =
|
||||
new String(mTaskWrapper.asFtp().getUrlEntity().remotePath.getBytes(charSet),
|
||||
new String(getTaskWrapper().asFtp().getUrlEntity().remotePath.getBytes(charSet),
|
||||
SERVER_CHARSET);
|
||||
ALog.i(TAG, String.format("remotePath【%s】", remotePath));
|
||||
is = client.retrieveFileStream(remotePath);
|
||||
@@ -105,10 +105,10 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
}
|
||||
} catch (IOException e) {
|
||||
fail(mChildCurrentLocation,
|
||||
new AriaIOException(TAG, String.format("下载失败【%s】", mConfig.URL), e));
|
||||
new AriaIOException(TAG, String.format("下载失败【%s】", getConfig().URL), e));
|
||||
} catch (Exception e) {
|
||||
fail(mChildCurrentLocation,
|
||||
new AriaIOException(TAG, String.format("下载失败【%s】", mConfig.URL), e));
|
||||
new AriaIOException(TAG, String.format("下载失败【%s】", getConfig().URL), e));
|
||||
} finally {
|
||||
try {
|
||||
if (is != null) {
|
||||
@@ -135,28 +135,28 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
return;
|
||||
}
|
||||
ALog.i(TAG,
|
||||
String.format("任务【%s】线程__%s__下载完毕", mConfig.TEMP_FILE.getName(), mConfig.THREAD_ID));
|
||||
writeConfig(true, mConfig.END_LOCATION);
|
||||
STATE.COMPLETE_THREAD_NUM++;
|
||||
if (STATE.isComplete()) {
|
||||
String.format("任务【%s】线程__%s__下载完毕", getConfig().TEMP_FILE.getName(), getConfig().THREAD_ID));
|
||||
writeConfig(true, getConfig().END_LOCATION);
|
||||
getState().COMPLETE_THREAD_NUM++;
|
||||
if (getState().isComplete()) {
|
||||
if (isBlock) {
|
||||
boolean success = mergeFile();
|
||||
if (!success) {
|
||||
//ALog.e(TAG, String.format("任务【%s】分块文件合并失败", mConfig.TEMP_FILE.getName()));
|
||||
STATE.isRunning = false;
|
||||
//ALog.e(TAG, String.format("任务【%s】分块文件合并失败", getConfig().TEMP_FILE.getName()));
|
||||
getState().isRunning = false;
|
||||
mListener.onFail(false,
|
||||
new TaskException(TAG, String.format("任务【%s】分块文件合并失败", mConfig.TEMP_FILE.getName())));
|
||||
new TaskException(TAG, String.format("任务【%s】分块文件合并失败", getConfig().TEMP_FILE.getName())));
|
||||
return;
|
||||
}
|
||||
}
|
||||
STATE.TASK_RECORD.deleteData();
|
||||
STATE.isRunning = false;
|
||||
getState().TASK_RECORD.deleteData();
|
||||
getState().isRunning = false;
|
||||
mListener.onComplete();
|
||||
}
|
||||
if (STATE.isFail()) {
|
||||
STATE.isRunning = false;
|
||||
if (getState().isFail()) {
|
||||
getState().isRunning = false;
|
||||
mListener.onFail(false,
|
||||
new TaskException(TAG, String.format("任务【%s】下载失败", mConfig.TEMP_FILE.getName())));
|
||||
new TaskException(TAG, String.format("任务【%s】下载失败", getConfig().TEMP_FILE.getName())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
ReadableByteChannel fic = null;
|
||||
try {
|
||||
int len;
|
||||
fos = new FileOutputStream(mConfig.TEMP_FILE, true);
|
||||
fos = new FileOutputStream(getConfig().TEMP_FILE, true);
|
||||
foc = fos.getChannel();
|
||||
fic = Channels.newChannel(is);
|
||||
ByteBuffer bf = ByteBuffer.allocate(getTaskConfig().getBuffSize());
|
||||
@@ -180,8 +180,8 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
if (mSpeedBandUtil != null) {
|
||||
mSpeedBandUtil.limitNextBytes(len);
|
||||
}
|
||||
if (mChildCurrentLocation + len >= mConfig.END_LOCATION) {
|
||||
len = (int) (mConfig.END_LOCATION - mChildCurrentLocation);
|
||||
if (mChildCurrentLocation + len >= getConfig().END_LOCATION) {
|
||||
len = (int) (getConfig().END_LOCATION - mChildCurrentLocation);
|
||||
bf.flip();
|
||||
fos.write(bf.array(), 0, len);
|
||||
bf.compact();
|
||||
@@ -197,7 +197,7 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
handleComplete();
|
||||
} catch (IOException e) {
|
||||
fail(mChildCurrentLocation,
|
||||
new AriaIOException(TAG, String.format("下载失败【%s】", mConfig.URL), e));
|
||||
new AriaIOException(TAG, String.format("下载失败【%s】", getConfig().URL), e));
|
||||
} finally {
|
||||
try {
|
||||
if (fos != null) {
|
||||
@@ -221,8 +221,8 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
private void readNormal(InputStream is) {
|
||||
BufferedRandomAccessFile file = null;
|
||||
try {
|
||||
file = new BufferedRandomAccessFile(mConfig.TEMP_FILE, "rwd", getTaskConfig().getBuffSize());
|
||||
file.seek(mConfig.START_LOCATION);
|
||||
file = new BufferedRandomAccessFile(getConfig().TEMP_FILE, "rwd", getTaskConfig().getBuffSize());
|
||||
file.seek(getConfig().START_LOCATION);
|
||||
byte[] buffer = new byte[getTaskConfig().getBuffSize()];
|
||||
int len;
|
||||
while (isLive() && (len = is.read(buffer)) != -1) {
|
||||
@@ -232,8 +232,8 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
if (mSpeedBandUtil != null) {
|
||||
mSpeedBandUtil.limitNextBytes(len);
|
||||
}
|
||||
if (mChildCurrentLocation + len >= mConfig.END_LOCATION) {
|
||||
len = (int) (mConfig.END_LOCATION - mChildCurrentLocation);
|
||||
if (mChildCurrentLocation + len >= getConfig().END_LOCATION) {
|
||||
len = (int) (getConfig().END_LOCATION - mChildCurrentLocation);
|
||||
file.write(buffer, 0, len);
|
||||
progress(len);
|
||||
break;
|
||||
@@ -244,7 +244,7 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
}
|
||||
} catch (IOException e) {
|
||||
fail(mChildCurrentLocation,
|
||||
new AriaIOException(TAG, String.format("下载失败【%s】", mConfig.URL), e));
|
||||
new AriaIOException(TAG, String.format("下载失败【%s】", getConfig().URL), e));
|
||||
} finally {
|
||||
try {
|
||||
if (file != null) {
|
||||
@@ -261,6 +261,6 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
}
|
||||
|
||||
@Override protected DownloadConfig getTaskConfig() {
|
||||
return mTaskWrapper.getConfig();
|
||||
return getTaskWrapper().getConfig();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.arialyy.aria.core.common.RequestEnum;
|
||||
import com.arialyy.aria.core.download.DTaskWrapper;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.core.common.http.HttpTaskDelegate;
|
||||
import com.arialyy.aria.core.inf.IHttpFileLenAdapter;
|
||||
import com.arialyy.aria.exception.AriaIOException;
|
||||
import com.arialyy.aria.exception.BaseException;
|
||||
import com.arialyy.aria.exception.TaskException;
|
||||
@@ -109,22 +110,11 @@ public class HttpFileInfoThread implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
long len = conn.getContentLength();
|
||||
if (len < 0) {
|
||||
String temp = conn.getHeaderField("Content-Length");
|
||||
len = TextUtils.isEmpty(temp) ? -1 : Long.parseLong(temp);
|
||||
// 某些服务,如果设置了conn.setRequestProperty("Range", "bytes=" + 0 + "-");
|
||||
// 会返回 Content-Range: bytes 0-225427911/225427913
|
||||
if (len < 0) {
|
||||
temp = conn.getHeaderField("Content-Range");
|
||||
if (TextUtils.isEmpty(temp)) {
|
||||
len = -1;
|
||||
} else {
|
||||
int start = temp.indexOf("/");
|
||||
len = Long.parseLong(temp.substring(start + 1));
|
||||
}
|
||||
}
|
||||
IHttpFileLenAdapter lenAdapter = mTaskWrapper.asHttp().getFileLenAdapter();
|
||||
if (lenAdapter == null) {
|
||||
lenAdapter = new FileLenAdapter();
|
||||
}
|
||||
long len = lenAdapter.handleFileLen(conn.getHeaderFields());
|
||||
|
||||
if (!CommonUtil.checkSDMemorySpace(mEntity.getDownloadPath(), len)) {
|
||||
failDownload(new TaskException(TAG,
|
||||
@@ -288,7 +278,7 @@ public class HttpFileInfoThread implements Runnable {
|
||||
if (TextUtils.isEmpty(newUrl) || newUrl.equalsIgnoreCase("null") || !newUrl.startsWith(
|
||||
"http")) {
|
||||
if (onFileInfoCallback != null) {
|
||||
onFileInfoCallback.onFail(mEntity.getUrl(), new TaskException(TAG, "获取重定向链接失败"), false);
|
||||
onFileInfoCallback.onFail(mEntity, new TaskException(TAG, "获取重定向链接失败"), false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -327,7 +317,32 @@ public class HttpFileInfoThread implements Runnable {
|
||||
|
||||
private void failDownload(BaseException e, boolean needRetry) {
|
||||
if (onFileInfoCallback != null) {
|
||||
onFileInfoCallback.onFail(mEntity.getUrl(), e, needRetry);
|
||||
onFileInfoCallback.onFail(mEntity, e, needRetry);
|
||||
}
|
||||
}
|
||||
|
||||
private static class FileLenAdapter implements 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);
|
||||
long len = TextUtils.isEmpty(temp) ? -1 : Long.parseLong(temp);
|
||||
// 某些服务,如果设置了conn.setRequestProperty("Range", "bytes=" + 0 + "-");
|
||||
// 会返回 Content-Range: bytes 0-225427911/225427913
|
||||
if (len < 0) {
|
||||
List<String> sRange = headers.get("Content-Range");
|
||||
if (sRange == null || sRange.isEmpty()) {
|
||||
len = -1;
|
||||
} else {
|
||||
int start = temp.indexOf("/");
|
||||
len = Long.parseLong(temp.substring(start + 1));
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,8 +55,8 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
HttpThreadTask(StateConstance constance, IDownloadListener listener,
|
||||
SubThreadConfig<DTaskWrapper> downloadInfo) {
|
||||
super(constance, listener, downloadInfo);
|
||||
isOpenDynamicFile = STATE.TASK_RECORD.isOpenDynamicFile;
|
||||
isBlock = STATE.TASK_RECORD.isBlock;
|
||||
isOpenDynamicFile = getState().TASK_RECORD.isOpenDynamicFile;
|
||||
isBlock = getState().TASK_RECORD.isBlock;
|
||||
}
|
||||
|
||||
@Override public HttpThreadTask call() throws Exception {
|
||||
@@ -69,17 +69,17 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
BufferedInputStream is = null;
|
||||
BufferedRandomAccessFile file = null;
|
||||
//当前子线程的下载位置
|
||||
mChildCurrentLocation = mConfig.START_LOCATION;
|
||||
mChildCurrentLocation = getConfig().START_LOCATION;
|
||||
try {
|
||||
HttpTaskDelegate taskDelegate = mTaskWrapper.asHttp();
|
||||
URL url = ConnectionHelp.handleUrl(mConfig.URL, taskDelegate);
|
||||
HttpTaskDelegate taskDelegate = getTaskWrapper().asHttp();
|
||||
URL url = ConnectionHelp.handleUrl(getConfig().URL, taskDelegate);
|
||||
conn = ConnectionHelp.handleConnection(url, taskDelegate);
|
||||
if (mConfig.SUPPORT_BP) {
|
||||
if (getConfig().SUPPORT_BP) {
|
||||
ALog.d(TAG,
|
||||
String.format("任务【%s】线程__%s__开始下载【开始位置 : %s,结束位置:%s】", mConfig.TEMP_FILE.getName(),
|
||||
mConfig.THREAD_ID, mConfig.START_LOCATION, mConfig.END_LOCATION));
|
||||
conn.setRequestProperty("Range",
|
||||
String.format("bytes=%s-%s", mConfig.START_LOCATION, (mConfig.END_LOCATION - 1)));
|
||||
String.format("任务【%s】线程__%s__开始下载【开始位置 : %s,结束位置:%s】", getConfig().TEMP_FILE.getName(),
|
||||
getConfig().THREAD_ID, getConfig().START_LOCATION, getConfig().END_LOCATION));
|
||||
conn.setRequestProperty("Range", String.format("bytes=%s-%s", getConfig().START_LOCATION,
|
||||
(getConfig().END_LOCATION - 1)));
|
||||
} else {
|
||||
ALog.w(TAG, "该下载不支持断点");
|
||||
}
|
||||
@@ -117,24 +117,25 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
} else {
|
||||
//创建可设置位置的文件
|
||||
file =
|
||||
new BufferedRandomAccessFile(mConfig.TEMP_FILE, "rwd", getTaskConfig().getBuffSize());
|
||||
new BufferedRandomAccessFile(getConfig().TEMP_FILE, "rwd",
|
||||
getTaskConfig().getBuffSize());
|
||||
//设置每条线程写入文件的位置
|
||||
file.seek(mConfig.START_LOCATION);
|
||||
file.seek(getConfig().START_LOCATION);
|
||||
readNormal(is, file);
|
||||
handleComplete();
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
fail(mChildCurrentLocation, new TaskException(TAG,
|
||||
String.format("任务【%s】下载失败,filePath: %s, url: %s", mConfig.TEMP_FILE.getName(),
|
||||
mEntity.getDownloadPath(), mEntity.getUrl()), e));
|
||||
String.format("任务【%s】下载失败,filePath: %s, url: %s", getConfig().TEMP_FILE.getName(),
|
||||
getEntity().getDownloadPath(), getEntity().getUrl()), e));
|
||||
} catch (IOException e) {
|
||||
fail(mChildCurrentLocation, new TaskException(TAG,
|
||||
String.format("任务【%s】下载失败,filePath: %s, url: %s", mConfig.TEMP_FILE.getName(),
|
||||
mEntity.getDownloadPath(), mEntity.getUrl()), e));
|
||||
String.format("任务【%s】下载失败,filePath: %s, url: %s", getConfig().TEMP_FILE.getName(),
|
||||
getEntity().getDownloadPath(), getEntity().getUrl()), e));
|
||||
} catch (Exception e) {
|
||||
fail(mChildCurrentLocation, new TaskException(TAG,
|
||||
String.format("任务【%s】下载失败,filePath: %s, url: %s", mConfig.TEMP_FILE.getName(),
|
||||
mEntity.getDownloadPath(), mEntity.getUrl()), e));
|
||||
String.format("任务【%s】下载失败,filePath: %s, url: %s", getConfig().TEMP_FILE.getName(),
|
||||
getEntity().getDownloadPath(), getEntity().getUrl()), e));
|
||||
} finally {
|
||||
try {
|
||||
if (file != null) {
|
||||
@@ -159,7 +160,7 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
private void readChunked(InputStream is) {
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(mConfig.TEMP_FILE, true);
|
||||
fos = new FileOutputStream(getConfig().TEMP_FILE, true);
|
||||
byte[] buffer = new byte[getTaskConfig().getBuffSize()];
|
||||
int len;
|
||||
while (isLive() && (len = is.read(buffer)) != -1) {
|
||||
@@ -175,7 +176,7 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
handleComplete();
|
||||
} catch (IOException e) {
|
||||
fail(mChildCurrentLocation, new AriaIOException(TAG,
|
||||
String.format("文件下载失败,savePath: %s, url: %s", mEntity.getDownloadPath(), mConfig.URL),
|
||||
String.format("文件下载失败,savePath: %s, url: %s", getEntity().getDownloadPath(), getConfig().URL),
|
||||
e));
|
||||
} finally {
|
||||
if (fos != null) {
|
||||
@@ -197,7 +198,7 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
ReadableByteChannel fic = null;
|
||||
try {
|
||||
int len;
|
||||
fos = new FileOutputStream(mConfig.TEMP_FILE, true);
|
||||
fos = new FileOutputStream(getConfig().TEMP_FILE, true);
|
||||
foc = fos.getChannel();
|
||||
fic = Channels.newChannel(is);
|
||||
ByteBuffer bf = ByteBuffer.allocate(getTaskConfig().getBuffSize());
|
||||
@@ -210,8 +211,8 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
if (mSpeedBandUtil != null) {
|
||||
mSpeedBandUtil.limitNextBytes(len);
|
||||
}
|
||||
if (mChildCurrentLocation + len >= mConfig.END_LOCATION) {
|
||||
len = (int) (mConfig.END_LOCATION - mChildCurrentLocation);
|
||||
if (mChildCurrentLocation + len >= getConfig().END_LOCATION) {
|
||||
len = (int) (getConfig().END_LOCATION - mChildCurrentLocation);
|
||||
bf.flip();
|
||||
fos.write(bf.array(), 0, len);
|
||||
bf.compact();
|
||||
@@ -227,7 +228,7 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
handleComplete();
|
||||
} catch (IOException e) {
|
||||
fail(mChildCurrentLocation, new AriaIOException(TAG,
|
||||
String.format("文件下载失败,savePath: %s, url: %s", mEntity.getDownloadPath(), mConfig.URL),
|
||||
String.format("文件下载失败,savePath: %s, url: %s", getEntity().getDownloadPath(), getConfig().URL),
|
||||
e));
|
||||
} finally {
|
||||
try {
|
||||
@@ -276,48 +277,49 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
if (!checkBlock()) {
|
||||
return;
|
||||
}
|
||||
if (mTaskWrapper.asHttp().isChunked()) {
|
||||
if (getTaskWrapper().asHttp().isChunked()) {
|
||||
ALog.i(TAG, "任务下载完成");
|
||||
STATE.isRunning = false;
|
||||
getState().isRunning = false;
|
||||
mListener.onComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mChildCurrentLocation == mConfig.END_LOCATION) {
|
||||
if (mChildCurrentLocation == getConfig().END_LOCATION) {
|
||||
//支持断点的处理
|
||||
if (mConfig.SUPPORT_BP) {
|
||||
if (getConfig().SUPPORT_BP) {
|
||||
ALog.i(TAG,
|
||||
String.format("任务【%s】线程__%s__下载完毕", mConfig.TEMP_FILE.getName(), mConfig.THREAD_ID));
|
||||
writeConfig(true, mConfig.END_LOCATION);
|
||||
STATE.COMPLETE_THREAD_NUM++;
|
||||
if (STATE.isComplete()) {
|
||||
String.format("任务【%s】线程__%s__下载完毕", getConfig().TEMP_FILE.getName(),
|
||||
getConfig().THREAD_ID));
|
||||
writeConfig(true, getConfig().END_LOCATION);
|
||||
getState().COMPLETE_THREAD_NUM++;
|
||||
if (getState().isComplete()) {
|
||||
if (isBlock) {
|
||||
boolean success = mergeFile();
|
||||
if (!success) {
|
||||
STATE.isRunning = false;
|
||||
getState().isRunning = false;
|
||||
mListener.onFail(false, new TaskException(TAG,
|
||||
String.format("任务【%s】分块文件合并失败", mConfig.TEMP_FILE.getName())));
|
||||
String.format("任务【%s】分块文件合并失败", getConfig().TEMP_FILE.getName())));
|
||||
return;
|
||||
}
|
||||
}
|
||||
STATE.TASK_RECORD.deleteData();
|
||||
STATE.isRunning = false;
|
||||
getState().TASK_RECORD.deleteData();
|
||||
getState().isRunning = false;
|
||||
mListener.onComplete();
|
||||
}
|
||||
if (STATE.isFail()) {
|
||||
STATE.isRunning = false;
|
||||
if (getState().isFail()) {
|
||||
getState().isRunning = false;
|
||||
mListener.onFail(false,
|
||||
new TaskException(TAG,
|
||||
String.format("任务【%s】下载失败,filePath: %s, url: %s", mConfig.TEMP_FILE.getName(),
|
||||
mEntity.getDownloadPath(), mEntity.getUrl())));
|
||||
String.format("任务【%s】下载失败,filePath: %s, url: %s", getConfig().TEMP_FILE.getName(),
|
||||
getEntity().getDownloadPath(), getEntity().getUrl())));
|
||||
}
|
||||
} else {
|
||||
ALog.i(TAG, "任务下载完成");
|
||||
STATE.isRunning = false;
|
||||
getState().isRunning = false;
|
||||
mListener.onComplete();
|
||||
}
|
||||
} else {
|
||||
STATE.FAIL_NUM++;
|
||||
getState().FAIL_NUM++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,6 +328,6 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DTaskWrapper> {
|
||||
}
|
||||
|
||||
@Override protected DownloadConfig getTaskConfig() {
|
||||
return mTaskWrapper.getConfig();
|
||||
return getTaskWrapper().getConfig();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ 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.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;
|
||||
@@ -131,7 +132,7 @@ public class SimpleDownloadUtil implements IUtil, Runnable {
|
||||
mDownloader.start();
|
||||
}
|
||||
|
||||
@Override public void onFail(String url, BaseException e, boolean needRetry) {
|
||||
@Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) {
|
||||
failDownload(e, needRetry);
|
||||
mDownloader.closeTimer();
|
||||
}
|
||||
@@ -143,7 +144,7 @@ public class SimpleDownloadUtil implements IUtil, Runnable {
|
||||
mDownloader.start();
|
||||
}
|
||||
|
||||
@Override public void onFail(String url, BaseException e, boolean needRetry) {
|
||||
@Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) {
|
||||
failDownload(e, needRetry);
|
||||
mDownloader.closeTimer();
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.arialyy.aria.core.download.group;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import com.arialyy.aria.core.common.IUtil;
|
||||
import com.arialyy.aria.core.common.http.HttpTaskDelegate;
|
||||
import com.arialyy.aria.core.config.Configuration;
|
||||
import com.arialyy.aria.core.download.DTaskWrapper;
|
||||
import com.arialyy.aria.core.download.DGTaskWrapper;
|
||||
@@ -293,12 +294,31 @@ 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 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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,11 @@ import com.arialyy.aria.core.common.IUtil;
|
||||
import com.arialyy.aria.core.common.OnFileInfoCallback;
|
||||
import com.arialyy.aria.core.download.DGTaskWrapper;
|
||||
import com.arialyy.aria.core.download.DTaskWrapper;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.core.download.downloader.HttpFileInfoThread;
|
||||
import com.arialyy.aria.core.inf.AbsEntity;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.exception.AriaIOException;
|
||||
import com.arialyy.aria.exception.BaseException;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@@ -84,6 +87,7 @@ public class DownloadGroupUtil extends AbsGroupUtil implements IUtil {
|
||||
private void getGroupSize() {
|
||||
new Thread(new Runnable() {
|
||||
int count;
|
||||
int failCount;
|
||||
|
||||
@Override public void run() {
|
||||
for (DTaskWrapper dTaskWrapper : mGTWrapper.getSubTaskWrapper()) {
|
||||
@@ -91,13 +95,16 @@ public class DownloadGroupUtil extends AbsGroupUtil implements IUtil {
|
||||
@Override public void onComplete(String url, CompleteInfo info) {
|
||||
createSubLoader((DTaskWrapper) info.wrapper, false);
|
||||
count++;
|
||||
checkGetSizeComplete(count);
|
||||
checkGetSizeComplete(count, failCount);
|
||||
}
|
||||
|
||||
@Override public void onFail(String url, BaseException e, boolean needRetry) {
|
||||
ALog.e(TAG, String.format("获取文件信息失败,url:%s", url));
|
||||
@Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) {
|
||||
ALog.e(TAG, String.format("获取文件信息失败,url:%s", ((DownloadEntity) entity).getUrl()));
|
||||
count++;
|
||||
checkGetSizeComplete(count);
|
||||
failCount++;
|
||||
mListener.onSubFail((DownloadEntity) entity, new AriaIOException(TAG,
|
||||
String.format("子任务获取文件长度失败,url:%s", ((DownloadEntity) entity).getUrl())));
|
||||
checkGetSizeComplete(count, failCount);
|
||||
}
|
||||
}));
|
||||
}
|
||||
@@ -108,17 +115,20 @@ public class DownloadGroupUtil extends AbsGroupUtil implements IUtil {
|
||||
/**
|
||||
* 检查组合任务大小是否获取完成,获取完成后取消阻塞,并设置组合任务大小
|
||||
*/
|
||||
private void checkGetSizeComplete(int count) {
|
||||
private void checkGetSizeComplete(int count, int failCount) {
|
||||
if (count == mGTWrapper.getSubTaskWrapper().size()) {
|
||||
long size = 0;
|
||||
for (DTaskWrapper wrapper : mGTWrapper.getSubTaskWrapper()) {
|
||||
size += wrapper.getEntity().getFileSize();
|
||||
}
|
||||
mGTWrapper.getEntity().setFileSize(size);
|
||||
mGTWrapper.getEntity().update();
|
||||
} else if (failCount == mGTWrapper.getSubTaskWrapper().size()) {
|
||||
mListener.onFail(true, new AriaIOException(TAG, "获取子任务长度失败"));
|
||||
}
|
||||
|
||||
synchronized (LOCK) {
|
||||
LOCK.notify();
|
||||
}
|
||||
synchronized (LOCK) {
|
||||
LOCK.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import com.arialyy.aria.core.common.CompleteInfo;
|
||||
import com.arialyy.aria.core.common.OnFileInfoCallback;
|
||||
import com.arialyy.aria.core.download.DGTaskWrapper;
|
||||
import com.arialyy.aria.core.download.DTaskWrapper;
|
||||
import com.arialyy.aria.core.inf.AbsEntity;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.exception.BaseException;
|
||||
|
||||
@@ -49,7 +50,7 @@ public class FtpDirDownloadUtil extends AbsGroupUtil {
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void onFail(String url, BaseException e, boolean needRetry) {
|
||||
@Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) {
|
||||
mListener.onFail(needRetry, e);
|
||||
}
|
||||
}).start();
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.arialyy.aria.core.download.DTaskWrapper;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.core.download.downloader.Downloader;
|
||||
import com.arialyy.aria.core.download.downloader.HttpFileInfoThread;
|
||||
import com.arialyy.aria.core.inf.AbsEntity;
|
||||
import com.arialyy.aria.core.inf.AbsTaskWrapper;
|
||||
import com.arialyy.aria.core.scheduler.ISchedulers;
|
||||
import com.arialyy.aria.exception.BaseException;
|
||||
@@ -104,7 +105,7 @@ class SubDownloadLoader implements IUtil {
|
||||
mDownloader.start();
|
||||
}
|
||||
|
||||
@Override public void onFail(String url, BaseException e, boolean needRetry) {
|
||||
@Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) {
|
||||
mSchedulers.obtainMessage(ISchedulers.FAIL, SubDownloadLoader.this);
|
||||
}
|
||||
})).start();
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,348 +1,340 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.inf;
|
||||
|
||||
import android.support.annotation.CheckResult;
|
||||
import android.text.TextUtils;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.command.ICmd;
|
||||
import com.arialyy.aria.core.command.normal.CancelCmd;
|
||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
||||
import com.arialyy.aria.core.common.TaskRecord;
|
||||
import com.arialyy.aria.core.download.DGTaskWrapper;
|
||||
import com.arialyy.aria.core.download.DownloadGroupEntity;
|
||||
import com.arialyy.aria.core.download.DTaskWrapper;
|
||||
import com.arialyy.aria.core.manager.TaskWrapperManager;
|
||||
import com.arialyy.aria.core.upload.UTaskWrapper;
|
||||
import com.arialyy.aria.orm.DbEntity;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/7/3.
|
||||
*/
|
||||
public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHandler {
|
||||
|
||||
protected String TAG;
|
||||
private AbsEntity mEntity;
|
||||
private AbsTaskWrapper mTaskWrapper;
|
||||
private String mTargetName;
|
||||
|
||||
protected AbsTarget() {
|
||||
TAG = CommonUtil.getClassName(this);
|
||||
}
|
||||
|
||||
public void setTaskWrapper(AbsTaskWrapper wrapper) {
|
||||
mTaskWrapper = wrapper;
|
||||
mEntity = wrapper.getEntity();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置状态,将任务状态设置为未开始状态
|
||||
* 注意:如果在后续方法调用链中没有调用 {@link #start()}、{@link #stop()}、{@link #cancel()}、{@link #resume()}
|
||||
* 等操作任务的方法,那么你需要调用{@link #save()}才能将修改保存到数据库
|
||||
*/
|
||||
@CheckResult(suggest = "after use #start()、#stop()、#cancel()、#resume()、#save()?")
|
||||
public TARGET resetState() {
|
||||
mTaskWrapper.getEntity().setState(IEntity.STATE_WAIT);
|
||||
mTaskWrapper.setRefreshInfo(true);
|
||||
return (TARGET) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除记录,如果任务正在执行,则会删除正在下载的任务
|
||||
*/
|
||||
public void removeRecord() {
|
||||
if (isRunning()) {
|
||||
ALog.d("AbsTarget", "任务正在下载,即将删除任务");
|
||||
cancel();
|
||||
} else {
|
||||
if (mEntity instanceof AbsNormalEntity) {
|
||||
TaskRecord record =
|
||||
DbEntity.findFirst(TaskRecord.class, "TaskRecord.filePath=?", mTaskWrapper.getKey());
|
||||
if (record != null) {
|
||||
CommonUtil.delTaskRecord(record, mTaskWrapper.isRemoveFile(), (AbsNormalEntity) mEntity);
|
||||
} else {
|
||||
mEntity.deleteData();
|
||||
}
|
||||
} else if (mEntity instanceof DownloadGroupEntity) {
|
||||
CommonUtil.delGroupTaskRecord(mTaskWrapper.isRemoveFile(), ((DownloadGroupEntity) mEntity));
|
||||
}
|
||||
TaskWrapperManager.getInstance().removeTaskWrapper(mEntity.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
public AbsEntity getEntity() {
|
||||
return mEntity;
|
||||
}
|
||||
|
||||
public String getTargetName() {
|
||||
return mTargetName;
|
||||
}
|
||||
|
||||
public void setTargetName(String mTargetName) {
|
||||
this.mTargetName = mTargetName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务实体
|
||||
*/
|
||||
public AbsTaskWrapper getTaskWrapper() {
|
||||
return mTaskWrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务进度,如果任务存在,则返回当前进度
|
||||
*
|
||||
* @return 该任务进度
|
||||
*/
|
||||
public long getCurrentProgress() {
|
||||
return mEntity == null ? -1 : mEntity.getCurrentProgress();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务文件大小
|
||||
*
|
||||
* @return 文件大小
|
||||
*/
|
||||
public long getFileSize() {
|
||||
return mEntity == null ? 0 : mEntity.getFileSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单位转换后的文件大小
|
||||
*
|
||||
* @return 文件大小{@code xxx mb}
|
||||
*/
|
||||
public String getConvertFileSize() {
|
||||
return mEntity == null ? "0b" : CommonUtil.formatFileSize(mEntity.getFileSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置扩展字段,用来保存你的其它数据,如果你的数据比较多,你可以把你的数据转换为JSON字符串,然后再存到Aria中
|
||||
* 注意:如果在后续方法调用链中没有调用 {@link #start()}、{@link #stop()}、{@link #cancel()}、{@link #resume()}
|
||||
* 等操作任务的方法,那么你需要调用{@link #save()}才能将修改保存到数据库
|
||||
*
|
||||
* @param str 扩展数据
|
||||
*/
|
||||
@CheckResult(suggest = "after use #start()、#stop()、#cancel()、#resume()、#save()?")
|
||||
public TARGET setExtendField(String str) {
|
||||
if (TextUtils.isEmpty(str)) return (TARGET) this;
|
||||
if (TextUtils.isEmpty(mEntity.getStr()) || !mEntity.getStr().equals(str)) {
|
||||
mEntity.setStr(str);
|
||||
} else {
|
||||
ALog.e(TAG, "设置扩展字段失败,扩展字段为一致");
|
||||
}
|
||||
|
||||
return (TARGET) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取存放的扩展字段
|
||||
* 设置扩展字段{@link #setExtendField(String)}
|
||||
*/
|
||||
public String getExtendField() {
|
||||
return mEntity.getStr();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务状态
|
||||
*
|
||||
* @return {@link IEntity}
|
||||
*/
|
||||
public int getTaskState() {
|
||||
return mEntity.getState();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务进度百分比
|
||||
*
|
||||
* @return 返回任务进度
|
||||
*/
|
||||
public int getPercent() {
|
||||
if (mEntity == null) {
|
||||
ALog.e("AbsTarget", "下载管理器中没有该任务");
|
||||
return 0;
|
||||
}
|
||||
if (mEntity.getFileSize() != 0) {
|
||||
return (int) (mEntity.getCurrentProgress() * 100 / mEntity.getFileSize());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查实体是否合法,如果实体合法,将保存实体到数据库,或更新数据库中的实体对象
|
||||
*
|
||||
* @return {@code true} 合法
|
||||
*/
|
||||
protected abstract boolean checkEntity();
|
||||
|
||||
protected int checkTaskType() {
|
||||
int taskType = 0;
|
||||
if (mTaskWrapper instanceof DTaskWrapper) {
|
||||
taskType = ICmd.TASK_TYPE_DOWNLOAD;
|
||||
} else if (mTaskWrapper instanceof DGTaskWrapper) {
|
||||
taskType = ICmd.TASK_TYPE_DOWNLOAD_GROUP;
|
||||
} else if (mTaskWrapper instanceof UTaskWrapper) {
|
||||
taskType = ICmd.TASK_TYPE_UPLOAD;
|
||||
}
|
||||
return taskType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存修改
|
||||
*/
|
||||
@Override public void save() {
|
||||
if (!checkEntity()) {
|
||||
ALog.e(TAG, "保存修改失败");
|
||||
} else {
|
||||
ALog.i(TAG, "保存成功");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务是否在执行
|
||||
*
|
||||
* @return {@code true} 任务正在执行
|
||||
*/
|
||||
public abstract boolean isRunning();
|
||||
|
||||
/**
|
||||
* 任务是否存在
|
||||
*
|
||||
* @return {@code true} 任务存在
|
||||
*/
|
||||
public abstract boolean taskExists();
|
||||
|
||||
/**
|
||||
* 设置target类型
|
||||
*
|
||||
* @return {@link #HTTP}、{@link #FTP}、{@link #GROUP_HTTP}、{@link #GROUP_FTP_DIR}
|
||||
*/
|
||||
public abstract int getTargetType();
|
||||
|
||||
/**
|
||||
* 添加任务
|
||||
*/
|
||||
@Override public void add() {
|
||||
if (checkEntity()) {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(CommonUtil.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_CREATE,
|
||||
checkTaskType()))
|
||||
.exe();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始任务
|
||||
*/
|
||||
@Override public void start() {
|
||||
if (checkEntity()) {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(
|
||||
CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START,
|
||||
checkTaskType()))
|
||||
.exe();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止任务
|
||||
*
|
||||
* @see #stop()
|
||||
*/
|
||||
@Deprecated public void pause() {
|
||||
if (checkEntity()) {
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void stop() {
|
||||
if (checkEntity()) {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(
|
||||
CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_STOP, checkTaskType()))
|
||||
.exe();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复任务
|
||||
*/
|
||||
@Override public void resume() {
|
||||
if (checkEntity()) {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(
|
||||
CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START,
|
||||
checkTaskType()))
|
||||
.exe();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除任务
|
||||
*/
|
||||
@Override public void cancel() {
|
||||
if (checkEntity()) {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_CANCEL,
|
||||
checkTaskType()))
|
||||
.exe();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务重试
|
||||
*/
|
||||
@Override public void reTry() {
|
||||
if (checkEntity()) {
|
||||
List<ICmd> cmds = new ArrayList<>();
|
||||
int taskType = checkTaskType();
|
||||
cmds.add(
|
||||
CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_STOP, taskType));
|
||||
cmds.add(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START, taskType));
|
||||
AriaManager.getInstance(AriaManager.APP).setCmds(cmds).exe();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除任务
|
||||
*
|
||||
* @param removeFile {@code true} 不仅删除任务数据库记录,还会删除已经删除完成的文件
|
||||
* {@code false}如果任务已经完成,只删除任务数据库记录,
|
||||
*/
|
||||
@Override public void cancel(boolean removeFile) {
|
||||
if (checkEntity()) {
|
||||
CancelCmd cancelCmd =
|
||||
(CancelCmd) CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_CANCEL,
|
||||
checkTaskType());
|
||||
cancelCmd.removeFile = removeFile;
|
||||
AriaManager.getInstance(AriaManager.APP).setCmd(cancelCmd).exe();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新下载
|
||||
*/
|
||||
@Override public void reStart() {
|
||||
if (checkEntity()) {
|
||||
cancel();
|
||||
start();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.inf;
|
||||
|
||||
import android.support.annotation.CheckResult;
|
||||
import android.text.TextUtils;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.command.ICmd;
|
||||
import com.arialyy.aria.core.command.normal.CancelCmd;
|
||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
||||
import com.arialyy.aria.core.download.DGTaskWrapper;
|
||||
import com.arialyy.aria.core.download.DownloadGroupEntity;
|
||||
import com.arialyy.aria.core.download.DTaskWrapper;
|
||||
import com.arialyy.aria.core.manager.TaskWrapperManager;
|
||||
import com.arialyy.aria.core.upload.UTaskWrapper;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by AriaL on 2017/7/3.
|
||||
*/
|
||||
public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHandler {
|
||||
|
||||
protected String TAG;
|
||||
private AbsEntity mEntity;
|
||||
private AbsTaskWrapper mTaskWrapper;
|
||||
private String mTargetName;
|
||||
|
||||
protected AbsTarget() {
|
||||
TAG = CommonUtil.getClassName(this);
|
||||
}
|
||||
|
||||
public void setTaskWrapper(AbsTaskWrapper wrapper) {
|
||||
mTaskWrapper = wrapper;
|
||||
mEntity = wrapper.getEntity();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置状态,将任务状态设置为未开始状态
|
||||
* 注意:如果在后续方法调用链中没有调用 {@link #start()}、{@link #stop()}、{@link #cancel()}、{@link #resume()}
|
||||
* 等操作任务的方法,那么你需要调用{@link #save()}才能将修改保存到数据库
|
||||
*/
|
||||
@CheckResult(suggest = "after use #start()、#stop()、#cancel()、#resume()、#save()?")
|
||||
public TARGET resetState() {
|
||||
mTaskWrapper.getEntity().setState(IEntity.STATE_WAIT);
|
||||
mTaskWrapper.setRefreshInfo(true);
|
||||
return (TARGET) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除记录,如果任务正在执行,则会删除正在下载的任务
|
||||
*/
|
||||
public void removeRecord() {
|
||||
if (isRunning()) {
|
||||
ALog.d("AbsTarget", "任务正在下载,即将删除任务");
|
||||
cancel();
|
||||
} else {
|
||||
if (mEntity instanceof AbsNormalEntity) {
|
||||
CommonUtil.delTaskRecord((AbsNormalEntity) mEntity, mTaskWrapper.isRemoveFile());
|
||||
} else if (mEntity instanceof DownloadGroupEntity) {
|
||||
CommonUtil.delGroupTaskRecord(((DownloadGroupEntity) mEntity), mTaskWrapper.isRemoveFile());
|
||||
}
|
||||
TaskWrapperManager.getInstance().removeTaskWrapper(mEntity.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
public AbsEntity getEntity() {
|
||||
return mEntity;
|
||||
}
|
||||
|
||||
public String getTargetName() {
|
||||
return mTargetName;
|
||||
}
|
||||
|
||||
public void setTargetName(String mTargetName) {
|
||||
this.mTargetName = mTargetName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务实体
|
||||
*/
|
||||
public AbsTaskWrapper getTaskWrapper() {
|
||||
return mTaskWrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务进度,如果任务存在,则返回当前进度
|
||||
*
|
||||
* @return 该任务进度
|
||||
*/
|
||||
public long getCurrentProgress() {
|
||||
return mEntity == null ? -1 : mEntity.getCurrentProgress();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务文件大小
|
||||
*
|
||||
* @return 文件大小
|
||||
*/
|
||||
public long getFileSize() {
|
||||
return mEntity == null ? 0 : mEntity.getFileSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单位转换后的文件大小
|
||||
*
|
||||
* @return 文件大小{@code xxx mb}
|
||||
*/
|
||||
public String getConvertFileSize() {
|
||||
return mEntity == null ? "0b" : CommonUtil.formatFileSize(mEntity.getFileSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置扩展字段,用来保存你的其它数据,如果你的数据比较多,你可以把你的数据转换为JSON字符串,然后再存到Aria中
|
||||
* 注意:如果在后续方法调用链中没有调用 {@link #start()}、{@link #stop()}、{@link #cancel()}、{@link #resume()}
|
||||
* 等操作任务的方法,那么你需要调用{@link #save()}才能将修改保存到数据库
|
||||
*
|
||||
* @param str 扩展数据
|
||||
*/
|
||||
@CheckResult(suggest = "after use #start()、#stop()、#cancel()、#resume()、#save()?")
|
||||
public TARGET setExtendField(String str) {
|
||||
if (TextUtils.isEmpty(str)) return (TARGET) this;
|
||||
if (TextUtils.isEmpty(mEntity.getStr()) || !mEntity.getStr().equals(str)) {
|
||||
mEntity.setStr(str);
|
||||
} else {
|
||||
ALog.e(TAG, "设置扩展字段失败,扩展字段为一致");
|
||||
}
|
||||
|
||||
return (TARGET) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取存放的扩展字段
|
||||
* 设置扩展字段{@link #setExtendField(String)}
|
||||
*/
|
||||
public String getExtendField() {
|
||||
return mEntity.getStr();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务状态
|
||||
*
|
||||
* @return {@link IEntity}
|
||||
*/
|
||||
public int getTaskState() {
|
||||
return mEntity.getState();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务进度百分比
|
||||
*
|
||||
* @return 返回任务进度
|
||||
*/
|
||||
public int getPercent() {
|
||||
if (mEntity == null) {
|
||||
ALog.e("AbsTarget", "下载管理器中没有该任务");
|
||||
return 0;
|
||||
}
|
||||
if (mEntity.getFileSize() != 0) {
|
||||
return (int) (mEntity.getCurrentProgress() * 100 / mEntity.getFileSize());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查实体是否合法,如果实体合法,将保存实体到数据库,或更新数据库中的实体对象
|
||||
*
|
||||
* @return {@code true} 合法
|
||||
*/
|
||||
protected abstract boolean checkEntity();
|
||||
|
||||
protected int checkTaskType() {
|
||||
int taskType = 0;
|
||||
if (mTaskWrapper instanceof DTaskWrapper) {
|
||||
taskType = ICmd.TASK_TYPE_DOWNLOAD;
|
||||
} else if (mTaskWrapper instanceof DGTaskWrapper) {
|
||||
taskType = ICmd.TASK_TYPE_DOWNLOAD_GROUP;
|
||||
} else if (mTaskWrapper instanceof UTaskWrapper) {
|
||||
taskType = ICmd.TASK_TYPE_UPLOAD;
|
||||
}
|
||||
return taskType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存修改
|
||||
*/
|
||||
@Override public void save() {
|
||||
if (!checkEntity()) {
|
||||
ALog.e(TAG, "保存修改失败");
|
||||
} else {
|
||||
ALog.i(TAG, "保存成功");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务是否在执行
|
||||
*
|
||||
* @return {@code true} 任务正在执行
|
||||
*/
|
||||
public abstract boolean isRunning();
|
||||
|
||||
/**
|
||||
* 任务是否存在
|
||||
*
|
||||
* @return {@code true} 任务存在
|
||||
*/
|
||||
public abstract boolean taskExists();
|
||||
|
||||
/**
|
||||
* 设置target类型
|
||||
*
|
||||
* @return {@link #HTTP}、{@link #FTP}、{@link #GROUP_HTTP}、{@link #GROUP_FTP_DIR}
|
||||
*/
|
||||
public abstract int getTargetType();
|
||||
|
||||
/**
|
||||
* 添加任务
|
||||
*/
|
||||
@Override public void add() {
|
||||
if (checkEntity()) {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(CommonUtil.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_CREATE,
|
||||
checkTaskType()))
|
||||
.exe();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始任务
|
||||
*/
|
||||
@Override public void start() {
|
||||
if (checkEntity()) {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(
|
||||
CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START,
|
||||
checkTaskType()))
|
||||
.exe();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止任务
|
||||
*
|
||||
* @see #stop()
|
||||
*/
|
||||
@Deprecated public void pause() {
|
||||
if (checkEntity()) {
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void stop() {
|
||||
if (checkEntity()) {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(
|
||||
CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_STOP, checkTaskType()))
|
||||
.exe();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复任务
|
||||
*/
|
||||
@Override public void resume() {
|
||||
if (checkEntity()) {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(
|
||||
CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START,
|
||||
checkTaskType()))
|
||||
.exe();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除任务
|
||||
*/
|
||||
@Override public void cancel() {
|
||||
if (checkEntity()) {
|
||||
AriaManager.getInstance(AriaManager.APP)
|
||||
.setCmd(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_CANCEL,
|
||||
checkTaskType()))
|
||||
.exe();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务重试
|
||||
*/
|
||||
@Override public void reTry() {
|
||||
if (checkEntity()) {
|
||||
List<ICmd> cmds = new ArrayList<>();
|
||||
int taskType = checkTaskType();
|
||||
cmds.add(
|
||||
CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_STOP, taskType));
|
||||
cmds.add(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START, taskType));
|
||||
AriaManager.getInstance(AriaManager.APP).setCmds(cmds).exe();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除任务
|
||||
*
|
||||
* @param removeFile {@code true} 不仅删除任务数据库记录,还会删除已经删除完成的文件
|
||||
* {@code false}如果任务已经完成,只删除任务数据库记录,
|
||||
*/
|
||||
@Override public void cancel(boolean removeFile) {
|
||||
if (checkEntity()) {
|
||||
CancelCmd cancelCmd =
|
||||
(CancelCmd) CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_CANCEL,
|
||||
checkTaskType());
|
||||
cancelCmd.removeFile = removeFile;
|
||||
AriaManager.getInstance(AriaManager.APP).setCmd(cancelCmd).exe();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新下载
|
||||
*/
|
||||
@Override public void reStart() {
|
||||
if (checkEntity()) {
|
||||
cancel();
|
||||
start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.inf;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.net.URLConnection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Http文件长度适配器
|
||||
*/
|
||||
public interface IHttpFileLenAdapter extends Serializable {
|
||||
long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 同伙header中的数据获取文件长度
|
||||
*
|
||||
* @param headers header参数{@link URLConnection#getHeaderFields()}
|
||||
* @return 文件长度
|
||||
*/
|
||||
long handleFileLen(Map<String, List<String>> headers);
|
||||
}
|
||||
@@ -1,194 +1,194 @@
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.upload.uploader;
|
||||
|
||||
import aria.apache.commons.net.ftp.FTPClient;
|
||||
import aria.apache.commons.net.ftp.FTPReply;
|
||||
import aria.apache.commons.net.ftp.OnFtpInputStreamListener;
|
||||
import com.arialyy.aria.core.common.StateConstance;
|
||||
import com.arialyy.aria.core.common.SubThreadConfig;
|
||||
import com.arialyy.aria.core.common.ftp.AbsFtpThreadTask;
|
||||
import com.arialyy.aria.core.config.BaseTaskConfig;
|
||||
import com.arialyy.aria.core.config.DownloadConfig;
|
||||
import com.arialyy.aria.core.config.UploadConfig;
|
||||
import com.arialyy.aria.core.inf.IEventListener;
|
||||
import com.arialyy.aria.core.upload.UploadEntity;
|
||||
import com.arialyy.aria.core.upload.UTaskWrapper;
|
||||
import com.arialyy.aria.exception.AriaIOException;
|
||||
import com.arialyy.aria.exception.TaskException;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
/**
|
||||
* Created by Aria.Lao on 2017/7/28. FTP 单线程上传任务,需要FTP 服务器给用户打开append和write的权限
|
||||
*/
|
||||
class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UTaskWrapper> {
|
||||
private final String TAG = "FtpThreadTask";
|
||||
private String dir, remotePath;
|
||||
|
||||
FtpThreadTask(StateConstance constance, IEventListener listener,
|
||||
SubThreadConfig<UTaskWrapper> info) {
|
||||
super(constance, listener, info);
|
||||
}
|
||||
|
||||
@Override public int getMaxSpeed() {
|
||||
return getTaskConfig().getMaxSpeed();
|
||||
}
|
||||
|
||||
@Override protected UploadConfig getTaskConfig() {
|
||||
return mTaskWrapper.getConfig();
|
||||
}
|
||||
|
||||
@Override public FtpThreadTask call() throws Exception {
|
||||
super.call();
|
||||
//当前子线程的下载位置
|
||||
mChildCurrentLocation = mConfig.START_LOCATION;
|
||||
FTPClient client = null;
|
||||
BufferedRandomAccessFile file = null;
|
||||
try {
|
||||
ALog.d(TAG,
|
||||
String.format("任务【%s】线程__%s__开始上传【开始位置 : %s,结束位置:%s】", mConfig.TEMP_FILE.getName(),
|
||||
mConfig.THREAD_ID, mConfig.START_LOCATION, mConfig.END_LOCATION));
|
||||
client = createClient();
|
||||
if (client == null) {
|
||||
return this;
|
||||
}
|
||||
initPath();
|
||||
client.makeDirectory(dir);
|
||||
client.changeWorkingDirectory(dir);
|
||||
client.setRestartOffset(mConfig.START_LOCATION);
|
||||
int reply = client.getReplyCode();
|
||||
if (!FTPReply.isPositivePreliminary(reply) && reply != FTPReply.FILE_ACTION_OK) {
|
||||
fail(mChildCurrentLocation,
|
||||
new AriaIOException(TAG,
|
||||
String.format("文件上传错误,错误码为:%s, msg:%s, filePath: %s", reply,
|
||||
client.getReplyString(), mEntity.getFilePath())));
|
||||
client.disconnect();
|
||||
return this;
|
||||
}
|
||||
|
||||
file = new BufferedRandomAccessFile(mConfig.TEMP_FILE, "rwd", getTaskConfig().getBuffSize());
|
||||
if (mConfig.START_LOCATION != 0) {
|
||||
//file.skipBytes((int) mConfig.START_LOCATION);
|
||||
file.seek(mConfig.START_LOCATION);
|
||||
}
|
||||
boolean complete = upload(client, file);
|
||||
if (!complete || isBreak()) {
|
||||
return this;
|
||||
}
|
||||
ALog.i(TAG,
|
||||
String.format("任务【%s】线程__%s__上传完毕", mConfig.TEMP_FILE.getName(), mConfig.THREAD_ID));
|
||||
writeConfig(true, mConfig.END_LOCATION);
|
||||
STATE.COMPLETE_THREAD_NUM++;
|
||||
if (STATE.isComplete()) {
|
||||
STATE.TASK_RECORD.deleteData();
|
||||
STATE.isRunning = false;
|
||||
mListener.onComplete();
|
||||
}
|
||||
if (STATE.isFail()) {
|
||||
STATE.isRunning = false;
|
||||
mListener.onFail(false, new TaskException(TAG,
|
||||
String.format("上传失败,filePath: %s, uploadUrl: %s", mEntity.getFilePath(), mConfig.URL)));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
fail(mChildCurrentLocation, new AriaIOException(TAG,
|
||||
String.format("上传失败,filePath: %s, uploadUrl: %s", mEntity.getFilePath(), mConfig.URL)));
|
||||
} catch (Exception e) {
|
||||
fail(mChildCurrentLocation, new AriaIOException(TAG, null, e));
|
||||
} finally {
|
||||
try {
|
||||
if (file != null) {
|
||||
file.close();
|
||||
}
|
||||
if (client != null && client.isConnected()) {
|
||||
client.disconnect();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private void initPath() throws UnsupportedEncodingException {
|
||||
dir = new String(mTaskWrapper.asFtp().getUrlEntity().remotePath.getBytes(charSet),
|
||||
SERVER_CHARSET);
|
||||
remotePath = new String(String.format("%s/%s", mTaskWrapper.asFtp().getUrlEntity().remotePath,
|
||||
mEntity.getFileName()).getBytes(charSet), SERVER_CHARSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传
|
||||
*
|
||||
* @return {@code true}上传成功、{@code false} 上传失败
|
||||
*/
|
||||
private boolean upload(final FTPClient client, final BufferedRandomAccessFile bis)
|
||||
throws IOException {
|
||||
|
||||
try {
|
||||
ALog.d(TAG, String.format("remotePath: %s", remotePath));
|
||||
client.storeFile(remotePath, new FtpFISAdapter(bis), new OnFtpInputStreamListener() {
|
||||
boolean isStoped = false;
|
||||
|
||||
@Override public void onFtpInputStream(FTPClient client, long totalBytesTransferred,
|
||||
int bytesTransferred, long streamSize) {
|
||||
try {
|
||||
if (isBreak() && !isStoped) {
|
||||
isStoped = true;
|
||||
client.abor();
|
||||
}
|
||||
if (mSpeedBandUtil != null) {
|
||||
mSpeedBandUtil.limitNextBytes(bytesTransferred);
|
||||
}
|
||||
progress(bytesTransferred);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
String msg = String.format("文件上传错误,错误码为:%s, msg:%s, filePath: %s", client.getReplyCode(),
|
||||
client.getReplyString(), mEntity.getFilePath());
|
||||
if (client.isConnected()) {
|
||||
client.disconnect();
|
||||
}
|
||||
if (e.getMessage().contains("AriaIOException caught while copying")) {
|
||||
e.printStackTrace();
|
||||
} else {
|
||||
fail(mChildCurrentLocation,
|
||||
new AriaIOException(TAG, msg, e));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int reply = client.getReplyCode();
|
||||
if (!FTPReply.isPositiveCompletion(reply)) {
|
||||
if (reply != FTPReply.TRANSFER_ABORTED) {
|
||||
fail(mChildCurrentLocation,
|
||||
new AriaIOException(TAG,
|
||||
String.format("文件上传错误,错误码为:%s, msg:%s, filePath: %s", reply,
|
||||
client.getReplyString(), mEntity.getFilePath())));
|
||||
}
|
||||
if (client.isConnected()) {
|
||||
client.disconnect();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.arialyy.aria.core.upload.uploader;
|
||||
|
||||
import aria.apache.commons.net.ftp.FTPClient;
|
||||
import aria.apache.commons.net.ftp.FTPReply;
|
||||
import aria.apache.commons.net.ftp.OnFtpInputStreamListener;
|
||||
import com.arialyy.aria.core.common.StateConstance;
|
||||
import com.arialyy.aria.core.common.SubThreadConfig;
|
||||
import com.arialyy.aria.core.common.ftp.AbsFtpThreadTask;
|
||||
import com.arialyy.aria.core.config.BaseTaskConfig;
|
||||
import com.arialyy.aria.core.config.DownloadConfig;
|
||||
import com.arialyy.aria.core.config.UploadConfig;
|
||||
import com.arialyy.aria.core.inf.IEventListener;
|
||||
import com.arialyy.aria.core.upload.UploadEntity;
|
||||
import com.arialyy.aria.core.upload.UTaskWrapper;
|
||||
import com.arialyy.aria.exception.AriaIOException;
|
||||
import com.arialyy.aria.exception.TaskException;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
/**
|
||||
* Created by Aria.Lao on 2017/7/28. FTP 单线程上传任务,需要FTP 服务器给用户打开append和write的权限
|
||||
*/
|
||||
class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UTaskWrapper> {
|
||||
private final String TAG = "FtpThreadTask";
|
||||
private String dir, remotePath;
|
||||
|
||||
FtpThreadTask(StateConstance constance, IEventListener listener,
|
||||
SubThreadConfig<UTaskWrapper> info) {
|
||||
super(constance, listener, info);
|
||||
}
|
||||
|
||||
@Override public int getMaxSpeed() {
|
||||
return getTaskConfig().getMaxSpeed();
|
||||
}
|
||||
|
||||
@Override protected UploadConfig getTaskConfig() {
|
||||
return getTaskWrapper().getConfig();
|
||||
}
|
||||
|
||||
@Override public FtpThreadTask call() throws Exception {
|
||||
super.call();
|
||||
//当前子线程的下载位置
|
||||
mChildCurrentLocation = getConfig().START_LOCATION;
|
||||
FTPClient client = null;
|
||||
BufferedRandomAccessFile file = null;
|
||||
try {
|
||||
ALog.d(TAG,
|
||||
String.format("任务【%s】线程__%s__开始上传【开始位置 : %s,结束位置:%s】", getConfig().TEMP_FILE.getName(),
|
||||
getConfig().THREAD_ID, getConfig().START_LOCATION, getConfig().END_LOCATION));
|
||||
client = createClient();
|
||||
if (client == null) {
|
||||
return this;
|
||||
}
|
||||
initPath();
|
||||
client.makeDirectory(dir);
|
||||
client.changeWorkingDirectory(dir);
|
||||
client.setRestartOffset(getConfig().START_LOCATION);
|
||||
int reply = client.getReplyCode();
|
||||
if (!FTPReply.isPositivePreliminary(reply) && reply != FTPReply.FILE_ACTION_OK) {
|
||||
fail(mChildCurrentLocation,
|
||||
new AriaIOException(TAG,
|
||||
String.format("文件上传错误,错误码为:%s, msg:%s, filePath: %s", reply,
|
||||
client.getReplyString(), getEntity().getFilePath())));
|
||||
client.disconnect();
|
||||
return this;
|
||||
}
|
||||
|
||||
file = new BufferedRandomAccessFile(getConfig().TEMP_FILE, "rwd", getTaskConfig().getBuffSize());
|
||||
if (getConfig().START_LOCATION != 0) {
|
||||
//file.skipBytes((int) getConfig().START_LOCATION);
|
||||
file.seek(getConfig().START_LOCATION);
|
||||
}
|
||||
boolean complete = upload(client, file);
|
||||
if (!complete || isBreak()) {
|
||||
return this;
|
||||
}
|
||||
ALog.i(TAG,
|
||||
String.format("任务【%s】线程__%s__上传完毕", getConfig().TEMP_FILE.getName(), getConfig().THREAD_ID));
|
||||
writeConfig(true, getConfig().END_LOCATION);
|
||||
getState().COMPLETE_THREAD_NUM++;
|
||||
if (getState().isComplete()) {
|
||||
getState().TASK_RECORD.deleteData();
|
||||
getState().isRunning = false;
|
||||
mListener.onComplete();
|
||||
}
|
||||
if (getState().isFail()) {
|
||||
getState().isRunning = false;
|
||||
mListener.onFail(false, new TaskException(TAG,
|
||||
String.format("上传失败,filePath: %s, uploadUrl: %s", getEntity().getFilePath(), getConfig().URL)));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
fail(mChildCurrentLocation, new AriaIOException(TAG,
|
||||
String.format("上传失败,filePath: %s, uploadUrl: %s", getEntity().getFilePath(), getConfig().URL)));
|
||||
} catch (Exception e) {
|
||||
fail(mChildCurrentLocation, new AriaIOException(TAG, null, e));
|
||||
} finally {
|
||||
try {
|
||||
if (file != null) {
|
||||
file.close();
|
||||
}
|
||||
if (client != null && client.isConnected()) {
|
||||
client.disconnect();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private void initPath() throws UnsupportedEncodingException {
|
||||
dir = new String(getTaskWrapper().asFtp().getUrlEntity().remotePath.getBytes(charSet),
|
||||
SERVER_CHARSET);
|
||||
remotePath = new String(String.format("%s/%s", getTaskWrapper().asFtp().getUrlEntity().remotePath,
|
||||
getEntity().getFileName()).getBytes(charSet), SERVER_CHARSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传
|
||||
*
|
||||
* @return {@code true}上传成功、{@code false} 上传失败
|
||||
*/
|
||||
private boolean upload(final FTPClient client, final BufferedRandomAccessFile bis)
|
||||
throws IOException {
|
||||
|
||||
try {
|
||||
ALog.d(TAG, String.format("remotePath: %s", remotePath));
|
||||
client.storeFile(remotePath, new FtpFISAdapter(bis), new OnFtpInputStreamListener() {
|
||||
boolean isStoped = false;
|
||||
|
||||
@Override public void onFtpInputStream(FTPClient client, long totalBytesTransferred,
|
||||
int bytesTransferred, long streamSize) {
|
||||
try {
|
||||
if (isBreak() && !isStoped) {
|
||||
isStoped = true;
|
||||
client.abor();
|
||||
}
|
||||
if (mSpeedBandUtil != null) {
|
||||
mSpeedBandUtil.limitNextBytes(bytesTransferred);
|
||||
}
|
||||
progress(bytesTransferred);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
String msg = String.format("文件上传错误,错误码为:%s, msg:%s, filePath: %s", client.getReplyCode(),
|
||||
client.getReplyString(), getEntity().getFilePath());
|
||||
if (client.isConnected()) {
|
||||
client.disconnect();
|
||||
}
|
||||
if (e.getMessage().contains("AriaIOException caught while copying")) {
|
||||
e.printStackTrace();
|
||||
} else {
|
||||
fail(mChildCurrentLocation,
|
||||
new AriaIOException(TAG, msg, e));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int reply = client.getReplyCode();
|
||||
if (!FTPReply.isPositiveCompletion(reply)) {
|
||||
if (reply != FTPReply.TRANSFER_ABORTED) {
|
||||
fail(mChildCurrentLocation,
|
||||
new AriaIOException(TAG,
|
||||
String.format("文件上传错误,错误码为:%s, msg:%s, filePath: %s", reply,
|
||||
client.getReplyString(), getEntity().getFilePath())));
|
||||
}
|
||||
if (client.isConnected()) {
|
||||
client.disconnect();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,18 +59,18 @@ class HttpThreadTask extends AbsThreadTask<UploadEntity, UTaskWrapper> {
|
||||
|
||||
@Override public HttpThreadTask call() throws Exception {
|
||||
super.call();
|
||||
File uploadFile = new File(mEntity.getFilePath());
|
||||
File uploadFile = new File(getEntity().getFilePath());
|
||||
if (!uploadFile.exists()) {
|
||||
fail(new TaskException(TAG,
|
||||
String.format("上传失败,文件不存在;filePath: %s, url: %s", mEntity.getFilePath(),
|
||||
mEntity.getUrl())));
|
||||
String.format("上传失败,文件不存在;filePath: %s, url: %s", getEntity().getFilePath(),
|
||||
getEntity().getUrl())));
|
||||
return this;
|
||||
}
|
||||
mListener.onPre();
|
||||
URL url;
|
||||
try {
|
||||
url = new URL(mEntity.getUrl());
|
||||
HttpTaskDelegate taskDelegate = mTaskWrapper.asHttp();
|
||||
url = new URL(getEntity().getUrl());
|
||||
HttpTaskDelegate taskDelegate = getTaskWrapper().asHttp();
|
||||
mHttpConn = (HttpURLConnection) url.openConnection();
|
||||
mHttpConn.setRequestMethod(taskDelegate.getRequestEnum().name);
|
||||
mHttpConn.setUseCaches(false);
|
||||
@@ -100,12 +100,13 @@ class HttpThreadTask extends AbsThreadTask<UploadEntity, UTaskWrapper> {
|
||||
addFormField(writer, key, taskDelegate.getFormFields().get(key));
|
||||
}
|
||||
uploadFile(writer, taskDelegate.getAttachment(), uploadFile);
|
||||
mTaskWrapper.getEntity().setResponseStr(finish(writer));
|
||||
getEntity().setResponseStr(finish(writer));
|
||||
mListener.onComplete();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail(new TaskException(TAG,
|
||||
String.format("上传失败,filePath: %s, url: %s", mEntity.getFilePath(), mEntity.getUrl()), e));
|
||||
String.format("上传失败,filePath: %s, url: %s", getEntity().getFilePath(),
|
||||
getEntity().getUrl()), e));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@@ -113,7 +114,7 @@ class HttpThreadTask extends AbsThreadTask<UploadEntity, UTaskWrapper> {
|
||||
private void fail(BaseException e1) {
|
||||
try {
|
||||
mListener.onFail(true, e1);
|
||||
STATE.isRunning = false;
|
||||
getState().isRunning = false;
|
||||
if (mOutputStream != null) {
|
||||
mOutputStream.close();
|
||||
}
|
||||
@@ -132,7 +133,7 @@ class HttpThreadTask extends AbsThreadTask<UploadEntity, UTaskWrapper> {
|
||||
.append("\"")
|
||||
.append(LINE_END);
|
||||
writer.append("Content-Type: text/plain; charset=")
|
||||
.append(mTaskWrapper.asHttp().getCharSet())
|
||||
.append(getTaskWrapper().asHttp().getCharSet())
|
||||
.append(LINE_END);
|
||||
writer.append(LINE_END);
|
||||
writer.append(value).append(LINE_END);
|
||||
@@ -151,11 +152,11 @@ class HttpThreadTask extends AbsThreadTask<UploadEntity, UTaskWrapper> {
|
||||
writer.append("Content-Disposition: form-data; name=\"")
|
||||
.append(attachment)
|
||||
.append("\"; filename=\"")
|
||||
.append(mTaskWrapper.getEntity().getFileName())
|
||||
.append(getEntity().getFileName())
|
||||
.append("\"")
|
||||
.append(LINE_END);
|
||||
writer.append("Content-Type: ")
|
||||
.append(URLConnection.guessContentTypeFromName(mTaskWrapper.getEntity().getFileName()))
|
||||
.append(URLConnection.guessContentTypeFromName(getEntity().getFileName()))
|
||||
.append(LINE_END);
|
||||
writer.append("Content-Transfer-Encoding: binary").append(LINE_END);
|
||||
writer.append(LINE_END);
|
||||
@@ -165,9 +166,9 @@ class HttpThreadTask extends AbsThreadTask<UploadEntity, UTaskWrapper> {
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||
STATE.CURRENT_LOCATION += bytesRead;
|
||||
getState().CURRENT_LOCATION += bytesRead;
|
||||
mOutputStream.write(buffer, 0, bytesRead);
|
||||
if (STATE.isCancel) {
|
||||
if (getState().isCancel) {
|
||||
break;
|
||||
}
|
||||
if (mSpeedBandUtil != null) {
|
||||
@@ -180,11 +181,11 @@ class HttpThreadTask extends AbsThreadTask<UploadEntity, UTaskWrapper> {
|
||||
inputStream.close();
|
||||
writer.append(LINE_END);
|
||||
writer.flush();
|
||||
if (STATE.isCancel) {
|
||||
STATE.isRunning = false;
|
||||
if (getState().isCancel) {
|
||||
getState().isRunning = false;
|
||||
return;
|
||||
}
|
||||
STATE.isRunning = false;
|
||||
getState().isRunning = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,6 +225,6 @@ class HttpThreadTask extends AbsThreadTask<UploadEntity, UTaskWrapper> {
|
||||
}
|
||||
|
||||
@Override protected UploadConfig getTaskConfig() {
|
||||
return mTaskWrapper.getConfig();
|
||||
return getTaskWrapper().getConfig();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.arialyy.aria.core.upload.uploader;
|
||||
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.inf.AbsEntity;
|
||||
import com.arialyy.aria.core.inf.AbsTaskWrapper;
|
||||
import com.arialyy.aria.core.inf.IUploadListener;
|
||||
import com.arialyy.aria.core.upload.UTaskWrapper;
|
||||
@@ -61,7 +62,7 @@ public class SimpleUploadUtil implements IUtil, Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void onFail(String url, BaseException e, boolean needRetry) {
|
||||
@Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) {
|
||||
mListener.onFail(needRetry, e);
|
||||
}
|
||||
}).start();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,8 @@
|
||||
- 修复使用`Content-Disposition`的文件名时,第一次下载无法重命名文件的问题
|
||||
- 修复使用`Content-Disposition`的文件名时,多次重命名文件的问题
|
||||
- 组合任务新增`unknownSize()`,用于处理组合任务大小未知的情况,https://github.com/AriaLyy/Aria/issues/380
|
||||
- 优化`AbsThreadTask`代码
|
||||
- 新增文件长度处理功能 https://github.com/AriaLyy/Aria/issues/393
|
||||
+ v_3.6.3 (2019/4/2)
|
||||
- fix bug https://github.com/AriaLyy/Aria/issues/377
|
||||
+ v_3.6.2 (2019/4/1)
|
||||
|
||||
@@ -55,6 +55,9 @@ dependencies {
|
||||
// annotationProcessor 'com.arialyy.aria:aria-compiler:3.3.14'
|
||||
api 'com.github.PhilJay:MPAndroidChart:v3.0.3'
|
||||
implementation project(':AppFrame')
|
||||
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.4'
|
||||
implementation 'com.github.bumptech.glide:glide:3.7.0'
|
||||
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.arialyy.aria.core.Aria;
|
||||
import com.arialyy.frame.core.AbsFrame;
|
||||
import com.arialyy.simple.BuildConfig;
|
||||
import com.arialyy.simple.common.ConnectionChangeReceiver;
|
||||
import com.squareup.leakcanary.LeakCanary;
|
||||
|
||||
/**
|
||||
* Created by Lyy on 2016/9/27.
|
||||
@@ -44,12 +45,20 @@ public class BaseApplication extends Application {
|
||||
.build());
|
||||
StrictMode.setThreadPolicy(
|
||||
new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());
|
||||
}
|
||||
|
||||
registerReceiver(new ConnectionChangeReceiver(),
|
||||
new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
|
||||
if (LeakCanary.isInAnalyzerProcess(this)) {//1
|
||||
// This process is dedicated to LeakCanary for heap analysis.
|
||||
// You should not init your app in this process.
|
||||
return;
|
||||
}
|
||||
LeakCanary.install(this);
|
||||
}
|
||||
|
||||
registerReceiver(new ConnectionChangeReceiver(),
|
||||
new
|
||||
|
||||
IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
|
||||
}
|
||||
|
||||
public static BaseApplication getApp() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
@@ -36,6 +37,7 @@ import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.core.download.DownloadTarget;
|
||||
import com.arialyy.aria.core.download.DownloadTask;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.core.inf.IHttpFileLenAdapter;
|
||||
import com.arialyy.aria.core.scheduler.ISchedulers;
|
||||
import com.arialyy.aria.util.ALog;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
@@ -58,8 +60,8 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
|
||||
//"http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apks";
|
||||
//"http://120.55.95.61:8811/ghcg/zg/武义总规纲要成果.zip";
|
||||
//"https://yizi-kejian.oss-cn-beijing.aliyuncs.com/qimeng/package1/qmtable11.zip";
|
||||
//"http://rs.0.gaoshouyou.com/d/04/1e/400423a7551e1f3f0eb1812afa1f9b44.apk";
|
||||
"http://chargepile2.techsum.net/car-manage/file/download?path=2019-04-26/c0242efd18be4ecbb23911b1c509dcad--掌通各系统汇总.xls"; // 无长度的chunked
|
||||
"http://rs.0.gaoshouyou.com/d/04/1e/400423a7551e1f3f0eb1812afa1f9b44.apk";
|
||||
//"http://chargepile2.techsum.net/car-manage/file/download?path=2019-04-26/c0242efd18be4ecbb23911b1c509dcad--掌通各系统汇总.xls"; // 无长度的chunked
|
||||
//"http://58.210.9.131/tpk/sipgt//TDLYZTGH.tpk"; //chunked 下载
|
||||
//"http://apk500.bce.baidu-mgame.com/game/67000/67734/20170622040827_oem_5502845.apk?r=1";
|
||||
//"https://dl.genymotion.com/releases/genymotion-2.12.1/genymotion-2.12.1-vbox.exe";
|
||||
@@ -262,8 +264,8 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
|
||||
L.d(TAG, "path = " + task.getDownloadEntity().getDownloadPath());
|
||||
L.d(TAG, "md5Code = " + CommonUtil.getFileMD5(new File(task.getDownloadPath())));
|
||||
L.d(TAG, "data = " + Aria.download(this).getDownloadEntity(DOWNLOAD_URL));
|
||||
DownloadEntity temp = Aria.download(this).getDownloadEntity(DOWNLOAD_URL);
|
||||
L.d(TAG, "status = " + temp.getState() + ", isComplete = " + temp.isComplete());
|
||||
//DownloadEntity temp = Aria.download(this).getDownloadEntity(DOWNLOAD_URL);
|
||||
//L.d(TAG, "status = " + temp.getState() + ", isComplete = " + temp.isComplete());
|
||||
//Intent install = new Intent(Intent.ACTION_VIEW);
|
||||
//install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
//File apkFile = new File(task.getDownloadPath());
|
||||
@@ -289,15 +291,9 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
|
||||
switch (view.getId()) {
|
||||
case R.id.start:
|
||||
startD();
|
||||
//List<DownloadEntity> list = Aria.download(this).getAllNotCompleteTask(5, 2);
|
||||
//ALog.d("Tag", list.size() + "");
|
||||
break;
|
||||
case R.id.stop:
|
||||
Aria.download(this).load(DOWNLOAD_URL).stop();
|
||||
//startActivity(new Intent(this, SingleTaskActivity.class));
|
||||
//Aria.download(this).unRegister();
|
||||
//Aria.download(this).load(DOWNLOAD_URL).removeRecord();
|
||||
//Log.d(TAG, Aria.download(this).taskExists(DOWNLOAD_URL) + "");
|
||||
break;
|
||||
case R.id.cancel:
|
||||
Aria.download(this).load(DOWNLOAD_URL).cancel(true);
|
||||
@@ -310,9 +306,6 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
|
||||
|
||||
private void startD() {
|
||||
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/ggsg14.apk";
|
||||
//Map<String, String> params = new HashMap<>();
|
||||
//params.put("key", "value");
|
||||
//params.put("filename", "CentOS-7-x86_64-Minimal-1804.iso");
|
||||
Aria.download(SingleTaskActivity.this)
|
||||
.load(DOWNLOAD_URL)
|
||||
//.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3")
|
||||
@@ -321,6 +314,18 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
|
||||
//.addHeader("Cookie", "BAIDUID=648E5FF020CC69E8DD6F492D1068AAA9:FG=1; BIDUPSID=648E5FF020CC69E8DD6F492D1068AAA9; PSTM=1519099573; BD_UPN=12314753; locale=zh; BDSVRTM=0")
|
||||
.useServerFileName(true)
|
||||
.setFilePath(path, true)
|
||||
.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);
|
||||
}
|
||||
})
|
||||
//.asGet()
|
||||
//.asPost()
|
||||
//.setParams(params)
|
||||
|
||||
@@ -24,6 +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.frame.util.show.L;
|
||||
import com.arialyy.frame.util.show.T;
|
||||
import com.arialyy.simple.R;
|
||||
@@ -31,6 +33,7 @@ import com.arialyy.simple.base.BaseActivity;
|
||||
import com.arialyy.simple.databinding.ActivityDownloadGroupBinding;
|
||||
import com.arialyy.simple.widget.SubStateLinearLayout;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2017/7/6.
|
||||
@@ -87,6 +90,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);
|
||||
}
|
||||
})
|
||||
//.setFileSize(114981416)
|
||||
//.updateUrls(temp)
|
||||
.start();
|
||||
|
||||
Reference in New Issue
Block a user