|
@@ -16,21 +16,17 @@
|
|
|
package com.arialyy.aria.core.common;
|
|
package com.arialyy.aria.core.common;
|
|
|
|
|
|
|
|
import android.content.Context;
|
|
import android.content.Context;
|
|
|
|
|
+import android.util.Log;
|
|
|
import android.util.SparseArray;
|
|
import android.util.SparseArray;
|
|
|
import com.arialyy.aria.core.AriaManager;
|
|
import com.arialyy.aria.core.AriaManager;
|
|
|
-import com.arialyy.aria.core.download.DownloadEntity;
|
|
|
|
|
|
|
+import com.arialyy.aria.core.download.DownloadTaskEntity;
|
|
|
import com.arialyy.aria.core.inf.AbsNormalEntity;
|
|
import com.arialyy.aria.core.inf.AbsNormalEntity;
|
|
|
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
|
import com.arialyy.aria.core.inf.AbsTaskEntity;
|
|
|
import com.arialyy.aria.core.inf.IDownloadListener;
|
|
import com.arialyy.aria.core.inf.IDownloadListener;
|
|
|
import com.arialyy.aria.core.inf.IEventListener;
|
|
import com.arialyy.aria.core.inf.IEventListener;
|
|
|
-import com.arialyy.aria.orm.DbEntity;
|
|
|
|
|
-import com.arialyy.aria.util.ALog;
|
|
|
|
|
|
|
+import com.arialyy.aria.core.upload.UploadTaskEntity;
|
|
|
import com.arialyy.aria.util.CommonUtil;
|
|
import com.arialyy.aria.util.CommonUtil;
|
|
|
-import com.arialyy.aria.util.DbHelper;
|
|
|
|
|
import java.io.File;
|
|
import java.io.File;
|
|
|
-import java.util.ArrayList;
|
|
|
|
|
-import java.util.HashSet;
|
|
|
|
|
-import java.util.List;
|
|
|
|
|
import java.util.Properties;
|
|
import java.util.Properties;
|
|
|
import java.util.Set;
|
|
import java.util.Set;
|
|
|
import java.util.Timer;
|
|
import java.util.Timer;
|
|
@@ -40,41 +36,28 @@ import java.util.concurrent.Executors;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* Created by AriaL on 2017/7/1.
|
|
* Created by AriaL on 2017/7/1.
|
|
|
- * 任务处理器
|
|
|
|
|
|
|
+ * 文件下载器
|
|
|
*/
|
|
*/
|
|
|
public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY extends AbsTaskEntity<ENTITY>>
|
|
public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY extends AbsTaskEntity<ENTITY>>
|
|
|
implements Runnable, IUtil {
|
|
implements Runnable, IUtil {
|
|
|
- public static final String STATE = "_state_";
|
|
|
|
|
- public static final String RECORD = "_record_";
|
|
|
|
|
- protected static final long SUB_LEN = 1024 * 1024;
|
|
|
|
|
-
|
|
|
|
|
- private final String TAG = "AbsFileer";
|
|
|
|
|
|
|
+ private final String TAG = "Downloader";
|
|
|
protected IEventListener mListener;
|
|
protected IEventListener mListener;
|
|
|
protected TASK_ENTITY mTaskEntity;
|
|
protected TASK_ENTITY mTaskEntity;
|
|
|
protected ENTITY mEntity;
|
|
protected ENTITY mEntity;
|
|
|
|
|
+ protected File mConfigFile;//信息配置文件
|
|
|
protected Context mContext;
|
|
protected Context mContext;
|
|
|
- protected File mTempFile; //文件
|
|
|
|
|
|
|
+ protected File mTempFile; //下载的文件
|
|
|
|
|
+ protected boolean isNewTask = true;
|
|
|
protected StateConstance mConstance;
|
|
protected StateConstance mConstance;
|
|
|
private ExecutorService mFixedThreadPool;
|
|
private ExecutorService mFixedThreadPool;
|
|
|
- //总线程数
|
|
|
|
|
- private int mTotalThreadNum;
|
|
|
|
|
- //启动线程数
|
|
|
|
|
- private int mStartThreadNum;
|
|
|
|
|
- //已完成的线程数
|
|
|
|
|
- private int mCompleteThreadNum;
|
|
|
|
|
|
|
+ private int mThreadNum, mRealThreadNum;
|
|
|
private SparseArray<AbsThreadTask> mTask = new SparseArray<>();
|
|
private SparseArray<AbsThreadTask> mTask = new SparseArray<>();
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 小于1m的文件不启用多线程
|
|
* 小于1m的文件不启用多线程
|
|
|
*/
|
|
*/
|
|
|
|
|
+ private static final long SUB_LEN = 1024 * 1024;
|
|
|
private Timer mTimer;
|
|
private Timer mTimer;
|
|
|
- @Deprecated
|
|
|
|
|
- private File mConfigFile;
|
|
|
|
|
- /**
|
|
|
|
|
- * 进度刷新间隔
|
|
|
|
|
- */
|
|
|
|
|
- private long mUpdateInterval = 1000;
|
|
|
|
|
- protected TaskRecord mRecord;
|
|
|
|
|
|
|
|
|
|
protected AbsFileer(IEventListener listener, TASK_ENTITY taskEntity) {
|
|
protected AbsFileer(IEventListener listener, TASK_ENTITY taskEntity) {
|
|
|
mListener = listener;
|
|
mListener = listener;
|
|
@@ -84,12 +67,8 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|
|
mConstance = new StateConstance();
|
|
mConstance = new StateConstance();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public void setNewTask(boolean newTask) {
|
|
|
|
|
- mTaskEntity.setNewTask(newTask);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
@Override public void setMaxSpeed(double maxSpeed) {
|
|
@Override public void setMaxSpeed(double maxSpeed) {
|
|
|
- for (int i = 0; i < mTotalThreadNum; i++) {
|
|
|
|
|
|
|
+ for (int i = 0; i < mThreadNum; i++) {
|
|
|
AbsThreadTask task = mTask.get(i);
|
|
AbsThreadTask task = mTask.get(i);
|
|
|
if (task != null) {
|
|
if (task != null) {
|
|
|
task.setMaxSpeed(maxSpeed);
|
|
task.setMaxSpeed(maxSpeed);
|
|
@@ -97,40 +76,43 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ public StateConstance getConstance() {
|
|
|
|
|
+ return mConstance;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
@Override public void run() {
|
|
@Override public void run() {
|
|
|
- if (mConstance.isRunning) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
startFlow();
|
|
startFlow();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 开始流程
|
|
|
|
|
|
|
+ * 开始下载流程
|
|
|
*/
|
|
*/
|
|
|
private void startFlow() {
|
|
private void startFlow() {
|
|
|
- mConstance.resetState();
|
|
|
|
|
checkTask();
|
|
checkTask();
|
|
|
- mConstance.TASK_RECORD = mRecord;
|
|
|
|
|
if (mListener instanceof IDownloadListener) {
|
|
if (mListener instanceof IDownloadListener) {
|
|
|
((IDownloadListener) mListener).onPostPre(mEntity.getFileSize());
|
|
((IDownloadListener) mListener).onPostPre(mEntity.getFileSize());
|
|
|
}
|
|
}
|
|
|
- if (!mTaskEntity.isSupportBP()) {
|
|
|
|
|
- mTotalThreadNum = 1;
|
|
|
|
|
- mStartThreadNum = 1;
|
|
|
|
|
|
|
+ mConstance.cleanState();
|
|
|
|
|
+ mConstance.isRunning = true;
|
|
|
|
|
+ if (!mTaskEntity.isSupportBP) {
|
|
|
|
|
+ mThreadNum = 1;
|
|
|
|
|
+ mConstance.THREAD_NUM = mThreadNum;
|
|
|
handleNoSupportBP();
|
|
handleNoSupportBP();
|
|
|
} else {
|
|
} else {
|
|
|
- mTotalThreadNum =
|
|
|
|
|
- mTaskEntity.isNewTask() ? (mStartThreadNum = setNewTaskThreadNum()) : mTotalThreadNum;
|
|
|
|
|
|
|
+ mThreadNum = isNewTask ? (getNewTaskThreadNum()) : mRealThreadNum;
|
|
|
|
|
+ mConstance.THREAD_NUM = mThreadNum;
|
|
|
handleBreakpoint();
|
|
handleBreakpoint();
|
|
|
}
|
|
}
|
|
|
- mConstance.START_THREAD_NUM = mTotalThreadNum;
|
|
|
|
|
startTimer();
|
|
startTimer();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 设置新任务的最大线程数
|
|
* 设置新任务的最大线程数
|
|
|
*/
|
|
*/
|
|
|
- protected abstract int setNewTaskThreadNum();
|
|
|
|
|
|
|
+ protected int getNewTaskThreadNum() {
|
|
|
|
|
+ return mEntity.getFileSize() <= SUB_LEN || mTaskEntity.requestType == AbsTaskEntity.FTP_DIR ? 1
|
|
|
|
|
+ : AriaManager.getInstance(mContext).getDownloadConfig().getThreadNum();
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 启动进度获取定时器
|
|
* 启动进度获取定时器
|
|
@@ -139,39 +121,22 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|
|
mTimer = new Timer(true);
|
|
mTimer = new Timer(true);
|
|
|
mTimer.schedule(new TimerTask() {
|
|
mTimer.schedule(new TimerTask() {
|
|
|
@Override public void run() {
|
|
@Override public void run() {
|
|
|
- if (mConstance.isComplete()
|
|
|
|
|
- || mConstance.isStop()
|
|
|
|
|
- || mConstance.isCancel()
|
|
|
|
|
- || !mConstance.isRunning) {
|
|
|
|
|
|
|
+ if (mConstance.isComplete() || !mConstance.isRunning) {
|
|
|
closeTimer();
|
|
closeTimer();
|
|
|
} else if (mConstance.CURRENT_LOCATION >= 0) {
|
|
} else if (mConstance.CURRENT_LOCATION >= 0) {
|
|
|
mListener.onProgress(mConstance.CURRENT_LOCATION);
|
|
mListener.onProgress(mConstance.CURRENT_LOCATION);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- }, 0, mUpdateInterval);
|
|
|
|
|
|
|
+ }, 0, 1000);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- protected void closeTimer() {
|
|
|
|
|
|
|
+ private void closeTimer() {
|
|
|
if (mTimer != null) {
|
|
if (mTimer != null) {
|
|
|
mTimer.purge();
|
|
mTimer.purge();
|
|
|
mTimer.cancel();
|
|
mTimer.cancel();
|
|
|
- mTimer = null;
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 设置定时器更新间隔
|
|
|
|
|
- *
|
|
|
|
|
- * @param interval 单位毫秒,不能小于0
|
|
|
|
|
- */
|
|
|
|
|
- protected void setUpdateInterval(long interval) {
|
|
|
|
|
- if (interval < 0) {
|
|
|
|
|
- ALog.w(TAG, "更新间隔不能小于0,默认为1000毫秒");
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- mUpdateInterval = interval;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
@Override public long getFileSize() {
|
|
@Override public long getFileSize() {
|
|
|
return mEntity.getFileSize();
|
|
return mEntity.getFileSize();
|
|
|
}
|
|
}
|
|
@@ -194,23 +159,28 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|
|
if (mFixedThreadPool != null) {
|
|
if (mFixedThreadPool != null) {
|
|
|
mFixedThreadPool.shutdown();
|
|
mFixedThreadPool.shutdown();
|
|
|
}
|
|
}
|
|
|
- for (int i = 0; i < mStartThreadNum; i++) {
|
|
|
|
|
|
|
+ for (int i = 0; i < mThreadNum; i++) {
|
|
|
AbsThreadTask task = mTask.get(i);
|
|
AbsThreadTask task = mTask.get(i);
|
|
|
if (task != null) {
|
|
if (task != null) {
|
|
|
task.cancel();
|
|
task.cancel();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ if (mTaskEntity instanceof DownloadTaskEntity) {
|
|
|
|
|
+ CommonUtil.delDownloadTaskConfig(mTaskEntity.removeFile, (DownloadTaskEntity) mTaskEntity);
|
|
|
|
|
+ } else if (mTaskEntity instanceof UploadTaskEntity) {
|
|
|
|
|
+ CommonUtil.delUploadTaskConfig(mTaskEntity.removeFile, (UploadTaskEntity) mTaskEntity);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override public void stop() {
|
|
@Override public void stop() {
|
|
|
closeTimer();
|
|
closeTimer();
|
|
|
- mConstance.isRunning = false;
|
|
|
|
|
- mConstance.isStop = true;
|
|
|
|
|
if (mConstance.isComplete()) return;
|
|
if (mConstance.isComplete()) return;
|
|
|
|
|
+ mConstance.isStop = true;
|
|
|
|
|
+ mConstance.isRunning = false;
|
|
|
if (mFixedThreadPool != null) {
|
|
if (mFixedThreadPool != null) {
|
|
|
mFixedThreadPool.shutdown();
|
|
mFixedThreadPool.shutdown();
|
|
|
}
|
|
}
|
|
|
- for (int i = 0; i < mStartThreadNum; i++) {
|
|
|
|
|
|
|
+ for (int i = 0; i < mThreadNum; i++) {
|
|
|
AbsThreadTask task = mTask.get(i);
|
|
AbsThreadTask task = mTask.get(i);
|
|
|
if (task != null) {
|
|
if (task != null) {
|
|
|
task.stop();
|
|
task.stop();
|
|
@@ -230,146 +200,68 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 检查任务、检查线程数
|
|
|
|
|
- * 新任务条件:
|
|
|
|
|
- * 1、文件不存在
|
|
|
|
|
- * 2、下载记录文件缺失或不匹配
|
|
|
|
|
- * 3、数据库记录不存在
|
|
|
|
|
- * 4、不支持断点,则是新任务
|
|
|
|
|
|
|
+ * 返回该下载器的
|
|
|
*/
|
|
*/
|
|
|
- protected void checkTask() {
|
|
|
|
|
- mConfigFile = new File(CommonUtil.getFileConfigPath(false, mEntity.getFileName()));
|
|
|
|
|
- if (mConfigFile.exists()) {
|
|
|
|
|
- convertDb();
|
|
|
|
|
- } else {
|
|
|
|
|
- mRecord = DbHelper.getTaskRecord(mTaskEntity.getKey());
|
|
|
|
|
- if (mRecord == null) {
|
|
|
|
|
- initRecord();
|
|
|
|
|
- mTaskEntity.setNewTask(true);
|
|
|
|
|
- } else {
|
|
|
|
|
- if (mRecord.threadRecords == null || mRecord.threadRecords.isEmpty()) {
|
|
|
|
|
- initRecord();
|
|
|
|
|
- mTaskEntity.setNewTask(true);
|
|
|
|
|
- } else if (mTempFile.length() == 0) {
|
|
|
|
|
- mRecord.deleteData();
|
|
|
|
|
- initRecord();
|
|
|
|
|
- mTaskEntity.setNewTask(true);
|
|
|
|
|
- } else {
|
|
|
|
|
- for (ThreadRecord tr : mRecord.threadRecords) {
|
|
|
|
|
- if (tr.isComplete) {
|
|
|
|
|
- mCompleteThreadNum++;
|
|
|
|
|
- } else {
|
|
|
|
|
- mStartThreadNum++;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- mTotalThreadNum = mRecord.threadRecords.size();
|
|
|
|
|
- mTaskEntity.setNewTask(false);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ public IEventListener getListener() {
|
|
|
|
|
+ return mListener;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * convertDb 为兼容性代码
|
|
|
|
|
- * 从3.4.1开始,线程配置信息将存储在数据库中。
|
|
|
|
|
- * 将配置文件的内容复制到数据库中,并将配置文件删除
|
|
|
|
|
|
|
+ * 检查任务是否是新任务,新任务条件:
|
|
|
|
|
+ * 1、文件不存在
|
|
|
|
|
+ * 2、下载记录文件不存在
|
|
|
|
|
+ * 3、下载记录文件缺失或不匹配
|
|
|
|
|
+ * 4、数据库记录不存在
|
|
|
|
|
+ * 5、不支持断点,则是新任务
|
|
|
*/
|
|
*/
|
|
|
- private void convertDb() {
|
|
|
|
|
- List<RecordWrapper> records =
|
|
|
|
|
- DbEntity.findRelationData(RecordWrapper.class, "TaskRecord.filePath=?",
|
|
|
|
|
- mTaskEntity.getKey());
|
|
|
|
|
- if (records == null || records.size() == 0) {
|
|
|
|
|
- Properties pro = CommonUtil.loadConfig(mConfigFile);
|
|
|
|
|
- if (pro.isEmpty()) {
|
|
|
|
|
- mTaskEntity.setNewTask(true);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- initRecord();
|
|
|
|
|
- Set<Object> keys = pro.keySet();
|
|
|
|
|
- // 老版本记录是5s存一次,但是5s中内,如果线程执行完成,record记录是没有的,只有state记录...
|
|
|
|
|
- // 第一步应该是record 和 state去重取正确的线程数
|
|
|
|
|
- Set<Integer> set = new HashSet<>();
|
|
|
|
|
- for (Object key : keys) {
|
|
|
|
|
- String str = String.valueOf(key);
|
|
|
|
|
- int i = Integer.parseInt(str.substring(str.length() - 1, str.length()));
|
|
|
|
|
- set.add(i);
|
|
|
|
|
- }
|
|
|
|
|
- int threadNum = set.size();
|
|
|
|
|
- if (threadNum == 0) {
|
|
|
|
|
- mTaskEntity.setNewTask(true);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- mRecord.threadNum = threadNum;
|
|
|
|
|
- mTotalThreadNum = threadNum;
|
|
|
|
|
-
|
|
|
|
|
- for (int i = 0; i < threadNum; i++) {
|
|
|
|
|
- ThreadRecord tRecord = new ThreadRecord();
|
|
|
|
|
- tRecord.key = mRecord.filePath;
|
|
|
|
|
- Object state = pro.getProperty(mTempFile.getName() + STATE + i);
|
|
|
|
|
- Object record = pro.getProperty(mTempFile.getName() + RECORD + i);
|
|
|
|
|
- if (state != null && Integer.parseInt(state + "") == 1) {
|
|
|
|
|
- mCompleteThreadNum++;
|
|
|
|
|
- tRecord.isComplete = true;
|
|
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
- mStartThreadNum++;
|
|
|
|
|
- if (record != null) {
|
|
|
|
|
- Long temp = Long.parseLong(record + "");
|
|
|
|
|
- tRecord.startLocation = temp > 0 ? temp : 0;
|
|
|
|
|
- } else {
|
|
|
|
|
- tRecord.startLocation = 0;
|
|
|
|
|
- }
|
|
|
|
|
- mRecord.threadRecords.add(tRecord);
|
|
|
|
|
- }
|
|
|
|
|
- mConfigFile.delete();
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ protected abstract void checkTask();
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 初始化记录
|
|
|
|
|
|
|
+ * 检查记录文件,如果是新任务返回{@code true},否则返回{@code false}
|
|
|
*/
|
|
*/
|
|
|
- private void initRecord() {
|
|
|
|
|
- mRecord = new TaskRecord();
|
|
|
|
|
- mRecord.fileName = mEntity.getFileName();
|
|
|
|
|
- mRecord.filePath = mTaskEntity.getKey();
|
|
|
|
|
- mRecord.threadRecords = new ArrayList<>();
|
|
|
|
|
- mRecord.isGroupRecord = mTaskEntity.getEntity().isGroupChild();
|
|
|
|
|
- mRecord.isOpenDynamicFile =
|
|
|
|
|
- AriaManager.getInstance(AriaManager.APP).getDownloadConfig().isOpenDynamicFile();
|
|
|
|
|
- if (mRecord.isGroupRecord) {
|
|
|
|
|
- if (mTaskEntity.getEntity() instanceof DownloadEntity) {
|
|
|
|
|
- mRecord.dGroupName = ((DownloadEntity) mTaskEntity.getEntity()).getGroupName();
|
|
|
|
|
|
|
+ protected boolean checkConfigFile() {
|
|
|
|
|
+ Properties pro = CommonUtil.loadConfig(mConfigFile);
|
|
|
|
|
+ if (pro.isEmpty()) {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ Set<Object> keys = pro.keySet();
|
|
|
|
|
+ int num = 0;
|
|
|
|
|
+ for (Object key : keys) {
|
|
|
|
|
+ if (String.valueOf(key).contains("_record_")) {
|
|
|
|
|
+ num++;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 保存任务记录
|
|
|
|
|
- */
|
|
|
|
|
- private void saveRecord() {
|
|
|
|
|
- mRecord.save();
|
|
|
|
|
- for (ThreadRecord tr : mRecord.threadRecords) {
|
|
|
|
|
- tr.save();
|
|
|
|
|
|
|
+ if (num == 0) {
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public TaskRecord getRecord() {
|
|
|
|
|
- return mRecord;
|
|
|
|
|
|
|
+ mRealThreadNum = num;
|
|
|
|
|
+ for (int i = 0; i < mRealThreadNum; i++) {
|
|
|
|
|
+ if (pro.getProperty(mTempFile.getName() + "_record_" + i) == null) {
|
|
|
|
|
+ Object state = pro.getProperty(mTempFile.getName() + "_state_" + i);
|
|
|
|
|
+ if (state != null && Integer.parseInt(state + "") == 1) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 恢复记录地址
|
|
* 恢复记录地址
|
|
|
*
|
|
*
|
|
|
- * @return {@code true}任务已完成
|
|
|
|
|
|
|
+ * @return true 表示下载完成
|
|
|
*/
|
|
*/
|
|
|
private boolean resumeRecordLocation(int i, long startL, long endL) {
|
|
private boolean resumeRecordLocation(int i, long startL, long endL) {
|
|
|
mConstance.CURRENT_LOCATION += endL - startL;
|
|
mConstance.CURRENT_LOCATION += endL - startL;
|
|
|
- ALog.d(TAG, "任务【" + mTaskEntity.getEntity().getFileName() + "】线程__" + i + "__已完成");
|
|
|
|
|
- mConstance.COMPLETE_THREAD_NUM = mCompleteThreadNum;
|
|
|
|
|
|
|
+ Log.d(TAG, "++++++++++ 线程_" + i + "_已经下载完成 ++++++++++");
|
|
|
|
|
+ mConstance.COMPLETE_THREAD_NUM++;
|
|
|
mConstance.STOP_NUM++;
|
|
mConstance.STOP_NUM++;
|
|
|
mConstance.CANCEL_NUM++;
|
|
mConstance.CANCEL_NUM++;
|
|
|
if (mConstance.isComplete()) {
|
|
if (mConstance.isComplete()) {
|
|
|
- mRecord.deleteData();
|
|
|
|
|
|
|
+ if (mConfigFile.exists()) {
|
|
|
|
|
+ mConfigFile.delete();
|
|
|
|
|
+ }
|
|
|
mListener.onComplete();
|
|
mListener.onComplete();
|
|
|
mConstance.isRunning = false;
|
|
mConstance.isRunning = false;
|
|
|
return true;
|
|
return true;
|
|
@@ -385,8 +277,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|
|
* @param endL 该任务结束位置
|
|
* @param endL 该任务结束位置
|
|
|
* @param fileLength 该任务需要处理的文件长度
|
|
* @param fileLength 该任务需要处理的文件长度
|
|
|
*/
|
|
*/
|
|
|
- private AbsThreadTask createSingThreadTask(int i, long startL, long endL, long fileLength,
|
|
|
|
|
- ThreadRecord record) {
|
|
|
|
|
|
|
+ private AbsThreadTask createSingThreadTask(int i, long startL, long endL, long fileLength) {
|
|
|
SubThreadConfig<TASK_ENTITY> config = new SubThreadConfig<>();
|
|
SubThreadConfig<TASK_ENTITY> config = new SubThreadConfig<>();
|
|
|
config.FILE_SIZE = fileLength;
|
|
config.FILE_SIZE = fileLength;
|
|
|
config.URL = mEntity.isRedirect() ? mEntity.getRedirectUrl() : mEntity.getUrl();
|
|
config.URL = mEntity.isRedirect() ? mEntity.getRedirectUrl() : mEntity.getUrl();
|
|
@@ -394,76 +285,63 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|
|
config.THREAD_ID = i;
|
|
config.THREAD_ID = i;
|
|
|
config.START_LOCATION = startL;
|
|
config.START_LOCATION = startL;
|
|
|
config.END_LOCATION = endL;
|
|
config.END_LOCATION = endL;
|
|
|
- config.SUPPORT_BP = mTaskEntity.isSupportBP();
|
|
|
|
|
|
|
+ config.CONFIG_FILE_PATH = mConfigFile.getPath();
|
|
|
|
|
+ config.SUPPORT_BP = mTaskEntity.isSupportBP;
|
|
|
config.TASK_ENTITY = mTaskEntity;
|
|
config.TASK_ENTITY = mTaskEntity;
|
|
|
- config.THREAD_RECORD = record;
|
|
|
|
|
return selectThreadTask(config);
|
|
return selectThreadTask(config);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 处理断点
|
|
|
|
|
+ */
|
|
|
private void handleBreakpoint() {
|
|
private void handleBreakpoint() {
|
|
|
long fileLength = mEntity.getFileSize();
|
|
long fileLength = mEntity.getFileSize();
|
|
|
- long blockSize = fileLength / mTotalThreadNum;
|
|
|
|
|
- int[] threadId = new int[mTotalThreadNum];
|
|
|
|
|
- int rl = 0;
|
|
|
|
|
-
|
|
|
|
|
- mRecord.fileLength = fileLength;
|
|
|
|
|
- for (int i = 0; i < mTotalThreadNum; i++) {
|
|
|
|
|
- threadId[i] = -1;
|
|
|
|
|
|
|
+ Properties pro = CommonUtil.loadConfig(mConfigFile);
|
|
|
|
|
+ int blockSize = (int) (fileLength / mThreadNum);
|
|
|
|
|
+ int[] recordL = new int[mThreadNum];
|
|
|
|
|
+ for (int i = 0; i < mThreadNum; i++) {
|
|
|
|
|
+ recordL[i] = -1;
|
|
|
}
|
|
}
|
|
|
- if (mTaskEntity.isNewTask() && !handleNewTask()) {
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ int rl = 0;
|
|
|
|
|
+ if (isNewTask) {
|
|
|
|
|
+ handleNewTask();
|
|
|
}
|
|
}
|
|
|
- for (int i = 0; i < mTotalThreadNum; i++) {
|
|
|
|
|
|
|
+ for (int i = 0; i < mThreadNum; i++) {
|
|
|
long startL = i * blockSize, endL = (i + 1) * blockSize;
|
|
long startL = i * blockSize, endL = (i + 1) * blockSize;
|
|
|
- ThreadRecord tr;
|
|
|
|
|
- boolean isNewTr = false; // 是否是新的线程记录
|
|
|
|
|
- if (mTaskEntity.isNewTask()) {
|
|
|
|
|
- tr = new ThreadRecord();
|
|
|
|
|
- tr.key = mRecord.filePath;
|
|
|
|
|
- tr.threadId = i;
|
|
|
|
|
- isNewTr = true;
|
|
|
|
|
- } else {
|
|
|
|
|
- tr = mRecord.threadRecords.get(i);
|
|
|
|
|
- }
|
|
|
|
|
- if (tr.isComplete) {//该线程已经完成
|
|
|
|
|
|
|
+ Object state = pro.getProperty(mTempFile.getName() + "_state_" + i);
|
|
|
|
|
+ if (state != null && Integer.parseInt(state + "") == 1) { //该线程已经完成
|
|
|
if (resumeRecordLocation(i, startL, endL)) return;
|
|
if (resumeRecordLocation(i, startL, endL)) return;
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+ //分配下载位置
|
|
|
|
|
+ Object record = pro.getProperty(mTempFile.getName() + "_record_" + i);
|
|
|
//如果有记录,则恢复下载
|
|
//如果有记录,则恢复下载
|
|
|
- if (tr.startLocation >= 0) {
|
|
|
|
|
- Long r = tr.startLocation;
|
|
|
|
|
- //记录的位置需要在线程区间中
|
|
|
|
|
- if (startL < r && r < (i == (mTotalThreadNum - 1) ? fileLength : endL)) {
|
|
|
|
|
- mConstance.CURRENT_LOCATION += r - startL;
|
|
|
|
|
- startL = r;
|
|
|
|
|
- }
|
|
|
|
|
- ALog.d(TAG, "任务【" + mEntity.getFileName() + "】线程__" + i + "__恢复下载");
|
|
|
|
|
|
|
+ if (!isNewTask && record != null && Long.parseLong(record + "") >= 0) {
|
|
|
|
|
+ Long r = Long.parseLong(record + "");
|
|
|
|
|
+ mConstance.CURRENT_LOCATION += r - startL;
|
|
|
|
|
+ Log.d(TAG, "任务【" + mEntity.getFileName() + "】线程__" + i + "__恢复下载");
|
|
|
|
|
+ startL = r;
|
|
|
|
|
+ recordL[rl] = i;
|
|
|
|
|
+ rl++;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ recordL[rl] = i;
|
|
|
|
|
+ rl++;
|
|
|
}
|
|
}
|
|
|
- //最后一个线程的结束位置即为文件的总长度
|
|
|
|
|
- if (i == (mTotalThreadNum - 1)) {
|
|
|
|
|
|
|
+ if (i == (mThreadNum - 1)) {
|
|
|
|
|
+ //最后一个线程的结束位置即为文件的总长度
|
|
|
endL = fileLength;
|
|
endL = fileLength;
|
|
|
}
|
|
}
|
|
|
- // 更新记录
|
|
|
|
|
- tr.startLocation = startL;
|
|
|
|
|
- tr.endLocation = endL;
|
|
|
|
|
- if (isNewTr) {
|
|
|
|
|
- mRecord.threadRecords.add(tr);
|
|
|
|
|
- }
|
|
|
|
|
- AbsThreadTask task = createSingThreadTask(i, startL, endL, fileLength, tr);
|
|
|
|
|
|
|
+ AbsThreadTask task = createSingThreadTask(i, startL, endL, fileLength);
|
|
|
if (task == null) return;
|
|
if (task == null) return;
|
|
|
mTask.put(i, task);
|
|
mTask.put(i, task);
|
|
|
- threadId[rl] = i;
|
|
|
|
|
- rl++;
|
|
|
|
|
}
|
|
}
|
|
|
- saveRecord();
|
|
|
|
|
- startThreadTask(threadId);
|
|
|
|
|
|
|
+ startSingleTask(recordL);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 启动单线程下载任务
|
|
* 启动单线程下载任务
|
|
|
*/
|
|
*/
|
|
|
- private void startThreadTask(int[] recordL) {
|
|
|
|
|
|
|
+ private void startSingleTask(int[] recordL) {
|
|
|
if (mConstance.CURRENT_LOCATION > 0) {
|
|
if (mConstance.CURRENT_LOCATION > 0) {
|
|
|
mListener.onResume(mConstance.CURRENT_LOCATION);
|
|
mListener.onResume(mConstance.CURRENT_LOCATION);
|
|
|
} else {
|
|
} else {
|
|
@@ -481,10 +359,8 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 处理新任务
|
|
* 处理新任务
|
|
|
- *
|
|
|
|
|
- * @return {@code true}创建新任务失败
|
|
|
|
|
*/
|
|
*/
|
|
|
- protected abstract boolean handleNewTask();
|
|
|
|
|
|
|
+ protected abstract void handleNewTask();
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 处理不支持断点的下载
|
|
* 处理不支持断点的下载
|
|
@@ -497,7 +373,8 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|
|
config.THREAD_ID = 0;
|
|
config.THREAD_ID = 0;
|
|
|
config.START_LOCATION = 0;
|
|
config.START_LOCATION = 0;
|
|
|
config.END_LOCATION = config.FILE_SIZE;
|
|
config.END_LOCATION = config.FILE_SIZE;
|
|
|
- config.SUPPORT_BP = mTaskEntity.isSupportBP();
|
|
|
|
|
|
|
+ config.CONFIG_FILE_PATH = mConfigFile.getPath();
|
|
|
|
|
+ config.SUPPORT_BP = mTaskEntity.isSupportBP;
|
|
|
config.TASK_ENTITY = mTaskEntity;
|
|
config.TASK_ENTITY = mTaskEntity;
|
|
|
AbsThreadTask task = selectThreadTask(config);
|
|
AbsThreadTask task = selectThreadTask(config);
|
|
|
if (task == null) return;
|
|
if (task == null) return;
|
|
@@ -511,4 +388,11 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|
|
* 选择单任务线程的类型
|
|
* 选择单任务线程的类型
|
|
|
*/
|
|
*/
|
|
|
protected abstract AbsThreadTask selectThreadTask(SubThreadConfig<TASK_ENTITY> config);
|
|
protected abstract AbsThreadTask selectThreadTask(SubThreadConfig<TASK_ENTITY> config);
|
|
|
|
|
+
|
|
|
|
|
+ protected void failDownload(String errorMsg) {
|
|
|
|
|
+ closeTimer();
|
|
|
|
|
+ Log.e(TAG, errorMsg);
|
|
|
|
|
+ mConstance.isRunning = false;
|
|
|
|
|
+ mListener.onFail();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|