分块下载实现
This commit is contained in:
@@ -28,10 +28,10 @@ import org.xml.sax.helpers.DefaultHandler;
|
|||||||
class ConfigHelper extends DefaultHandler {
|
class ConfigHelper extends DefaultHandler {
|
||||||
private final String TAG = "ConfigHelper";
|
private final String TAG = "ConfigHelper";
|
||||||
|
|
||||||
private boolean isDownloadConfig = false, isUploadConfig = false, isAppConfig = false;
|
|
||||||
private Configuration.DownloadConfig mDownloadConfig = Configuration.DownloadConfig.getInstance();
|
private Configuration.DownloadConfig mDownloadConfig = Configuration.DownloadConfig.getInstance();
|
||||||
private Configuration.UploadConfig mUploadConfig = Configuration.UploadConfig.getInstance();
|
private Configuration.UploadConfig mUploadConfig = Configuration.UploadConfig.getInstance();
|
||||||
private Configuration.AppConfig mAppConfig = Configuration.AppConfig.getInstance();
|
private Configuration.AppConfig mAppConfig = Configuration.AppConfig.getInstance();
|
||||||
|
private @ConfigType int mType;
|
||||||
|
|
||||||
@Override public void startDocument() throws SAXException {
|
@Override public void startDocument() throws SAXException {
|
||||||
super.startDocument();
|
super.startDocument();
|
||||||
@@ -41,21 +41,19 @@ class ConfigHelper extends DefaultHandler {
|
|||||||
public void startElement(String uri, String localName, String qName, Attributes attributes)
|
public void startElement(String uri, String localName, String qName, Attributes attributes)
|
||||||
throws SAXException {
|
throws SAXException {
|
||||||
super.startElement(uri, localName, qName, attributes);
|
super.startElement(uri, localName, qName, attributes);
|
||||||
if (qName.equals("download")) {
|
switch (qName) {
|
||||||
isDownloadConfig = true;
|
case "download":
|
||||||
isUploadConfig = false;
|
mType = ConfigType.DOWNLOAD;
|
||||||
isAppConfig = false;
|
break;
|
||||||
} else if (qName.equals("upload")) {
|
case "upload":
|
||||||
isUploadConfig = true;
|
mType = ConfigType.UPLOAD;
|
||||||
isDownloadConfig = false;
|
break;
|
||||||
isAppConfig = false;
|
case "app":
|
||||||
} else if (qName.equals("app")) {
|
mType = ConfigType.APP;
|
||||||
isUploadConfig = false;
|
break;
|
||||||
isDownloadConfig = false;
|
|
||||||
isAppConfig = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDownloadConfig || isUploadConfig) {
|
if (mType == ConfigType.DOWNLOAD || mType == ConfigType.UPLOAD) {
|
||||||
|
|
||||||
String value = attributes.getValue("value");
|
String value = attributes.getValue("value");
|
||||||
switch (qName) {
|
switch (qName) {
|
||||||
@@ -100,8 +98,11 @@ class ConfigHelper extends DefaultHandler {
|
|||||||
case "notNetRetry":
|
case "notNetRetry":
|
||||||
loadNotNetRetry(value);
|
loadNotNetRetry(value);
|
||||||
break;
|
break;
|
||||||
|
case "useBlock":
|
||||||
|
loadUseBlock(value);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else if (isAppConfig) {
|
} else if (mType == ConfigType.APP) {
|
||||||
String value = attributes.getValue("value");
|
String value = attributes.getValue("value");
|
||||||
switch (qName) {
|
switch (qName) {
|
||||||
case "useAriaCrashHandler":
|
case "useAriaCrashHandler":
|
||||||
@@ -114,11 +115,17 @@ class ConfigHelper extends DefaultHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void loadUseBlock(String value) {
|
||||||
|
if (mType == ConfigType.DOWNLOAD) {
|
||||||
|
mDownloadConfig.useBlock = checkBoolean(value) ? Boolean.valueOf(value) : false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void loadNotNetRetry(String value) {
|
private void loadNotNetRetry(String value) {
|
||||||
if (isDownloadConfig) {
|
if (mType == ConfigType.DOWNLOAD) {
|
||||||
mDownloadConfig.notNetRetry = checkBoolean(value) ? Boolean.valueOf(value) : false;
|
mDownloadConfig.notNetRetry = checkBoolean(value) ? Boolean.valueOf(value) : false;
|
||||||
}
|
}
|
||||||
if (isUploadConfig) {
|
if (mType == ConfigType.UPLOAD) {
|
||||||
mUploadConfig.notNetRetry = checkBoolean(value) ? Boolean.valueOf(value) : false;
|
mUploadConfig.notNetRetry = checkBoolean(value) ? Boolean.valueOf(value) : false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,10 +157,10 @@ class ConfigHelper extends DefaultHandler {
|
|||||||
|
|
||||||
private void loadUpdateInterval(String value) {
|
private void loadUpdateInterval(String value) {
|
||||||
long temp = checkLong(value) ? Long.parseLong(value) : 1000;
|
long temp = checkLong(value) ? Long.parseLong(value) : 1000;
|
||||||
if (isDownloadConfig) {
|
if (mType == ConfigType.DOWNLOAD) {
|
||||||
mDownloadConfig.updateInterval = temp;
|
mDownloadConfig.updateInterval = temp;
|
||||||
}
|
}
|
||||||
if (isUploadConfig) {
|
if (mType == ConfigType.UPLOAD) {
|
||||||
mUploadConfig.updateInterval = temp;
|
mUploadConfig.updateInterval = temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,17 +171,17 @@ class ConfigHelper extends DefaultHandler {
|
|||||||
"wait"))) {
|
"wait"))) {
|
||||||
mod = value;
|
mod = value;
|
||||||
}
|
}
|
||||||
if (isDownloadConfig) {
|
if (mType == ConfigType.DOWNLOAD) {
|
||||||
mDownloadConfig.queueMod = mod;
|
mDownloadConfig.queueMod = mod;
|
||||||
}
|
}
|
||||||
if (isUploadConfig) {
|
if (mType == ConfigType.UPLOAD) {
|
||||||
mUploadConfig.queueMod = mod;
|
mUploadConfig.queueMod = mod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadMaxSpeed(String value) {
|
private void loadMaxSpeed(String value) {
|
||||||
int maxSpeed = checkInt(value) ? Integer.parseInt(value) : 0;
|
int maxSpeed = checkInt(value) ? Integer.parseInt(value) : 0;
|
||||||
if (isDownloadConfig) {
|
if (mType == ConfigType.DOWNLOAD) {
|
||||||
mDownloadConfig.maxSpeed = maxSpeed;
|
mDownloadConfig.maxSpeed = maxSpeed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,10 +192,10 @@ class ConfigHelper extends DefaultHandler {
|
|||||||
open = Boolean.parseBoolean(value);
|
open = Boolean.parseBoolean(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDownloadConfig) {
|
if (mType == ConfigType.DOWNLOAD) {
|
||||||
mDownloadConfig.isConvertSpeed = open;
|
mDownloadConfig.isConvertSpeed = open;
|
||||||
}
|
}
|
||||||
if (isUploadConfig) {
|
if (mType == ConfigType.UPLOAD) {
|
||||||
mUploadConfig.isConvertSpeed = open;
|
mUploadConfig.isConvertSpeed = open;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -200,13 +207,13 @@ class ConfigHelper extends DefaultHandler {
|
|||||||
time = 2 * 1000;
|
time = 2 * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDownloadConfig) {
|
if (mType == ConfigType.DOWNLOAD) {
|
||||||
mDownloadConfig.reTryInterval = time;
|
mDownloadConfig.reTryInterval = time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadCA(String name, String path) {
|
private void loadCA(String name, String path) {
|
||||||
if (isDownloadConfig) {
|
if (mType == ConfigType.DOWNLOAD) {
|
||||||
mDownloadConfig.caName = name;
|
mDownloadConfig.caName = name;
|
||||||
mDownloadConfig.caPath = path;
|
mDownloadConfig.caPath = path;
|
||||||
}
|
}
|
||||||
@@ -219,11 +226,11 @@ class ConfigHelper extends DefaultHandler {
|
|||||||
buffSize = 2048;
|
buffSize = 2048;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDownloadConfig) {
|
if (mType == ConfigType.DOWNLOAD) {
|
||||||
mDownloadConfig.buffSize = buffSize;
|
mDownloadConfig.buffSize = buffSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUploadConfig) {
|
if (mType == ConfigType.UPLOAD) {
|
||||||
mUploadConfig.buffSize = buffSize;
|
mUploadConfig.buffSize = buffSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -235,11 +242,11 @@ class ConfigHelper extends DefaultHandler {
|
|||||||
time = 10 * 1000;
|
time = 10 * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDownloadConfig) {
|
if (mType == ConfigType.DOWNLOAD) {
|
||||||
mDownloadConfig.iOTimeOut = time;
|
mDownloadConfig.iOTimeOut = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isUploadConfig) {
|
if (mType == ConfigType.UPLOAD) {
|
||||||
mUploadConfig.iOTimeOut = time;
|
mUploadConfig.iOTimeOut = time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,10 +254,10 @@ class ConfigHelper extends DefaultHandler {
|
|||||||
private void loadConnectTime(String value) {
|
private void loadConnectTime(String value) {
|
||||||
int time = checkInt(value) ? Integer.parseInt(value) : 5 * 1000;
|
int time = checkInt(value) ? Integer.parseInt(value) : 5 * 1000;
|
||||||
|
|
||||||
if (isDownloadConfig) {
|
if (mType == ConfigType.DOWNLOAD) {
|
||||||
mDownloadConfig.connectTimeOut = time;
|
mDownloadConfig.connectTimeOut = time;
|
||||||
}
|
}
|
||||||
if (isUploadConfig) {
|
if (mType == ConfigType.UPLOAD) {
|
||||||
mUploadConfig.connectTimeOut = time;
|
mUploadConfig.connectTimeOut = time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,10 +265,10 @@ class ConfigHelper extends DefaultHandler {
|
|||||||
private void loadReTry(String value) {
|
private void loadReTry(String value) {
|
||||||
int num = checkInt(value) ? Integer.parseInt(value) : 0;
|
int num = checkInt(value) ? Integer.parseInt(value) : 0;
|
||||||
|
|
||||||
if (isDownloadConfig) {
|
if (mType == ConfigType.DOWNLOAD) {
|
||||||
mDownloadConfig.reTryNum = num;
|
mDownloadConfig.reTryNum = num;
|
||||||
}
|
}
|
||||||
if (isUploadConfig) {
|
if (mType == ConfigType.UPLOAD) {
|
||||||
mUploadConfig.reTryNum = num;
|
mUploadConfig.reTryNum = num;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -272,10 +279,10 @@ class ConfigHelper extends DefaultHandler {
|
|||||||
ALog.w(TAG, "任务队列数不能小于 1");
|
ALog.w(TAG, "任务队列数不能小于 1");
|
||||||
num = 2;
|
num = 2;
|
||||||
}
|
}
|
||||||
if (isDownloadConfig) {
|
if (mType == ConfigType.DOWNLOAD) {
|
||||||
mDownloadConfig.maxTaskNum = num;
|
mDownloadConfig.maxTaskNum = num;
|
||||||
}
|
}
|
||||||
if (isUploadConfig) {
|
if (mType == ConfigType.UPLOAD) {
|
||||||
mUploadConfig.maxTaskNum = num;
|
mUploadConfig.maxTaskNum = num;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -286,7 +293,7 @@ class ConfigHelper extends DefaultHandler {
|
|||||||
ALog.e(TAG, "下载线程数不能小于 1");
|
ALog.e(TAG, "下载线程数不能小于 1");
|
||||||
num = 1;
|
num = 1;
|
||||||
}
|
}
|
||||||
if (isDownloadConfig) {
|
if (mType == ConfigType.DOWNLOAD) {
|
||||||
mDownloadConfig.threadNum = num;
|
mDownloadConfig.threadNum = num;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
31
Aria/src/main/java/com/arialyy/aria/core/ConfigType.java
Normal file
31
Aria/src/main/java/com/arialyy/aria/core/ConfigType.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import android.support.annotation.IntDef;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
@IntDef({
|
||||||
|
ConfigType.DOWNLOAD,
|
||||||
|
ConfigType.UPLOAD,
|
||||||
|
ConfigType.APP
|
||||||
|
})
|
||||||
|
@Retention(RetentionPolicy.SOURCE) @interface ConfigType {
|
||||||
|
int DOWNLOAD = 1;
|
||||||
|
int UPLOAD = 2;
|
||||||
|
int APP = 3;
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@ package com.arialyy.aria.core.common;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
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.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;
|
||||||
@@ -47,6 +48,10 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
implements Runnable, IUtil {
|
implements Runnable, IUtil {
|
||||||
private static final String STATE = "_state_";
|
private static final String STATE = "_state_";
|
||||||
private static final String RECORD = "_record_";
|
private static final String RECORD = "_record_";
|
||||||
|
/**
|
||||||
|
* 分块文件路径
|
||||||
|
*/
|
||||||
|
public static final String SUB_PATH = "%s.%s.part";
|
||||||
/**
|
/**
|
||||||
* 小于1m的文件不启用多线程
|
* 小于1m的文件不启用多线程
|
||||||
*/
|
*/
|
||||||
@@ -74,7 +79,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
* 进度刷新间隔
|
* 进度刷新间隔
|
||||||
*/
|
*/
|
||||||
private long mUpdateInterval = 1000;
|
private long mUpdateInterval = 1000;
|
||||||
private TaskRecord mRecord;
|
protected TaskRecord mRecord;
|
||||||
|
|
||||||
protected AbsFileer(IEventListener listener, TASK_ENTITY taskEntity) {
|
protected AbsFileer(IEventListener listener, TASK_ENTITY taskEntity) {
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
@@ -117,23 +122,36 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
if (!mTaskEntity.isSupportBP()) {
|
if (!mTaskEntity.isSupportBP()) {
|
||||||
mTotalThreadNum = 1;
|
mTotalThreadNum = 1;
|
||||||
mStartThreadNum = 1;
|
mStartThreadNum = 1;
|
||||||
handleNoSupportBP();
|
|
||||||
} else {
|
} else {
|
||||||
mTotalThreadNum =
|
mTotalThreadNum =
|
||||||
mTaskEntity.isNewTask() ? (mStartThreadNum = setNewTaskThreadNum()) : mTotalThreadNum;
|
mTaskEntity.isNewTask() ? (mStartThreadNum = setNewTaskThreadNum()) : mTotalThreadNum;
|
||||||
handleBreakpoint();
|
|
||||||
}
|
}
|
||||||
mConstance.START_THREAD_NUM = mTotalThreadNum;
|
mConstance.START_THREAD_NUM = mTotalThreadNum;
|
||||||
|
|
||||||
|
// 处理分块和动态文件参数
|
||||||
|
if (mTaskEntity.isNewTask() && mTaskEntity instanceof DownloadTaskEntity) {
|
||||||
|
AriaManager manager = AriaManager.getInstance(AriaManager.APP);
|
||||||
|
mRecord.isBlock = mTotalThreadNum > 1 && manager.getDownloadConfig().isUseBlock();
|
||||||
|
// 线程数不等1并且没有使用块下载,则认为没有使用动态文件
|
||||||
|
mRecord.isOpenDynamicFile = mTotalThreadNum == 1 || mRecord.isBlock;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* mTaskEntity.getEntity().getFileSize() != mTempFile.length()为兼容以前老版本代码
|
* mTaskEntity.getEntity().getFileSize() != mTempFile.length()为兼容以前老版本代码
|
||||||
* 动态长度条件:
|
* 动态长度条件:
|
||||||
* 1、总线程数为1,并且是新任务
|
* 1、总线程数为1,并且是新任务
|
||||||
* 2、总线程数为1,不是新任务,但是长度不是文件全长度
|
* 2、总线程数为1,不是新任务,但是长度不是文件全长度
|
||||||
*/
|
*/
|
||||||
if (mTotalThreadNum == 1 && (mTaskEntity.isNewTask()
|
if (mTotalThreadNum == 1 && (mTaskEntity.getEntity().getFileSize() != mTempFile.length())) {
|
||||||
|| mTaskEntity.getEntity().getFileSize() != mTempFile.length())) {
|
mRecord.isOpenDynamicFile = true;
|
||||||
mConstance.isOpenDynamicFile = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mTaskEntity.isSupportBP()) {
|
||||||
|
handleNoSupportBP();
|
||||||
|
} else {
|
||||||
|
handleBreakpoint();
|
||||||
|
}
|
||||||
|
|
||||||
startTimer();
|
startTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,17 +272,16 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
} else {
|
} else {
|
||||||
mRecord = DbHelper.getTaskRecord(mTaskEntity.getKey());
|
mRecord = DbHelper.getTaskRecord(mTaskEntity.getKey());
|
||||||
if (mRecord == null) {
|
if (mRecord == null) {
|
||||||
initRecord();
|
initRecord(true);
|
||||||
mTaskEntity.setNewTask(true);
|
|
||||||
} else {
|
} else {
|
||||||
if (mRecord.threadRecords == null || mRecord.threadRecords.isEmpty()) {
|
if (mRecord.threadRecords == null || mRecord.threadRecords.isEmpty()) {
|
||||||
initRecord();
|
initRecord(true);
|
||||||
mTaskEntity.setNewTask(true);
|
}
|
||||||
} else if (mTempFile.length() == 0) {
|
//else if (mTempFile.length() == 0) {
|
||||||
mRecord.deleteData();
|
// mRecord.deleteData();
|
||||||
initRecord();
|
// initRecord(true);
|
||||||
mTaskEntity.setNewTask(true);
|
//}
|
||||||
} else {
|
else {
|
||||||
for (ThreadRecord tr : mRecord.threadRecords) {
|
for (ThreadRecord tr : mRecord.threadRecords) {
|
||||||
if (tr.isComplete) {
|
if (tr.isComplete) {
|
||||||
mCompleteThreadNum++;
|
mCompleteThreadNum++;
|
||||||
@@ -294,7 +311,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
mTaskEntity.setNewTask(true);
|
mTaskEntity.setNewTask(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
initRecord();
|
initRecord(false);
|
||||||
Set<Object> keys = pro.keySet();
|
Set<Object> keys = pro.keySet();
|
||||||
// 老版本记录是5s存一次,但是5s中内,如果线程执行完成,record记录是没有的,只有state记录...
|
// 老版本记录是5s存一次,但是5s中内,如果线程执行完成,record记录是没有的,只有state记录...
|
||||||
// 第一步应该是record 和 state去重取正确的线程数
|
// 第一步应该是record 和 state去重取正确的线程数
|
||||||
@@ -338,7 +355,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
/**
|
/**
|
||||||
* 初始化记录
|
* 初始化记录
|
||||||
*/
|
*/
|
||||||
private void initRecord() {
|
private void initRecord(boolean isNewTask) {
|
||||||
mRecord = new TaskRecord();
|
mRecord = new TaskRecord();
|
||||||
mRecord.fileName = mEntity.getFileName();
|
mRecord.fileName = mEntity.getFileName();
|
||||||
mRecord.filePath = mTaskEntity.getKey();
|
mRecord.filePath = mTaskEntity.getKey();
|
||||||
@@ -349,6 +366,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
mRecord.dGroupName = ((DownloadEntity) mTaskEntity.getEntity()).getGroupName();
|
mRecord.dGroupName = ((DownloadEntity) mTaskEntity.getEntity()).getGroupName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mTaskEntity.setNewTask(isNewTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -399,7 +417,8 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
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();
|
||||||
config.TEMP_FILE = mTempFile;
|
config.TEMP_FILE =
|
||||||
|
mRecord.isBlock ? new File(String.format(SUB_PATH, mTempFile.getPath(), i)) : mTempFile;
|
||||||
config.THREAD_ID = i;
|
config.THREAD_ID = i;
|
||||||
config.START_LOCATION = startL;
|
config.START_LOCATION = startL;
|
||||||
config.END_LOCATION = endL;
|
config.END_LOCATION = endL;
|
||||||
|
|||||||
@@ -23,8 +23,12 @@ import com.arialyy.aria.core.inf.IEventListener;
|
|||||||
import com.arialyy.aria.core.upload.UploadEntity;
|
import com.arialyy.aria.core.upload.UploadEntity;
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
import com.arialyy.aria.util.ErrorHelp;
|
import com.arialyy.aria.util.ErrorHelp;
|
||||||
|
import com.arialyy.aria.util.FileUtil;
|
||||||
import com.arialyy.aria.util.NetUtils;
|
import com.arialyy.aria.util.NetUtils;
|
||||||
|
import java.io.File;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
@@ -69,10 +73,10 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTITY
|
|||||||
});
|
});
|
||||||
|
|
||||||
protected AbsThreadTask(StateConstance constance, IEventListener listener,
|
protected AbsThreadTask(StateConstance constance, IEventListener listener,
|
||||||
SubThreadConfig<TASK_ENTITY> info) {
|
SubThreadConfig<TASK_ENTITY> config) {
|
||||||
STATE = constance;
|
STATE = constance;
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
mConfig = info;
|
mConfig = config;
|
||||||
mTaskEntity = mConfig.TASK_ENTITY;
|
mTaskEntity = mConfig.TASK_ENTITY;
|
||||||
mEntity = mTaskEntity.getEntity();
|
mEntity = mTaskEntity.getEntity();
|
||||||
mLastSaveTime = System.currentTimeMillis();
|
mLastSaveTime = System.currentTimeMillis();
|
||||||
@@ -134,6 +138,30 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTITY
|
|||||||
return STATE.isCancel || STATE.isStop || taskBreak;
|
return STATE.isCancel || STATE.isStop || taskBreak;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 合并文件
|
||||||
|
*
|
||||||
|
* @return {@code true} 合并成功,{@code false}合并失败
|
||||||
|
*/
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
boolean isSuccess = FileUtil.mergeFile(STATE.TASK_RECORD.filePath, partPath);
|
||||||
|
if (isSuccess) {
|
||||||
|
for (String pp : partPath) {
|
||||||
|
File f = new File(pp);
|
||||||
|
if (f.exists()) {
|
||||||
|
f.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 停止任务
|
* 停止任务
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ package com.arialyy.aria.core.common;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by lyy on 2017/1/18.
|
* Created by lyy on 2017/1/18.
|
||||||
* 下载状态常量
|
* 状态常量
|
||||||
*/
|
*/
|
||||||
public class StateConstance {
|
public class StateConstance {
|
||||||
public int CANCEL_NUM = 0;
|
public int CANCEL_NUM = 0;
|
||||||
@@ -30,13 +30,8 @@ public class StateConstance {
|
|||||||
public boolean isCancel = false;
|
public boolean isCancel = false;
|
||||||
public boolean isStop = false;
|
public boolean isStop = false;
|
||||||
public TaskRecord TASK_RECORD;
|
public TaskRecord TASK_RECORD;
|
||||||
/**
|
|
||||||
* 是否是使用虚拟文件下载的
|
|
||||||
* {@code true}是,{@code false}不是
|
|
||||||
*/
|
|
||||||
public boolean isOpenDynamicFile = false;
|
|
||||||
|
|
||||||
public StateConstance() {
|
StateConstance() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetState() {
|
public void resetState() {
|
||||||
@@ -50,14 +45,14 @@ public class StateConstance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 所有子线程是否都已经停止下载
|
* 所有子线程是否都已经停止
|
||||||
*/
|
*/
|
||||||
public boolean isStop() {
|
public boolean isStop() {
|
||||||
return STOP_NUM == START_THREAD_NUM;
|
return STOP_NUM == START_THREAD_NUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 所有子线程是否都已经下载失败
|
* 所有子线程是否都已经失败
|
||||||
*/
|
*/
|
||||||
public boolean isFail() {
|
public boolean isFail() {
|
||||||
return COMPLETE_THREAD_NUM != START_THREAD_NUM
|
return COMPLETE_THREAD_NUM != START_THREAD_NUM
|
||||||
@@ -65,14 +60,14 @@ public class StateConstance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 所有子线程是否都已经完成下载
|
* 所有子线程是否都已经完成
|
||||||
*/
|
*/
|
||||||
public boolean isComplete() {
|
public boolean isComplete() {
|
||||||
return COMPLETE_THREAD_NUM >= START_THREAD_NUM;
|
return COMPLETE_THREAD_NUM >= START_THREAD_NUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 所有子线程是否都已经取消下载
|
* 所有子线程是否都已经取消
|
||||||
*/
|
*/
|
||||||
public boolean isCancel() {
|
public boolean isCancel() {
|
||||||
return CANCEL_NUM == START_THREAD_NUM;
|
return CANCEL_NUM == START_THREAD_NUM;
|
||||||
|
|||||||
@@ -73,4 +73,15 @@ public class TaskRecord extends DbEntity {
|
|||||||
@Ignore
|
@Ignore
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public String uGroupName;
|
public String uGroupName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否是分块{@code true}是,{@code false} 不是
|
||||||
|
*/
|
||||||
|
public boolean isBlock = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否是使用虚拟文件下载的
|
||||||
|
* {@code true}是,{@code false}不是
|
||||||
|
*/
|
||||||
|
public boolean isOpenDynamicFile = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 线程任务管理器
|
||||||
|
*/
|
||||||
|
class ThreadTaskManager {
|
||||||
|
private static volatile ThreadTaskManager INSTANCE = null;
|
||||||
|
private Map<String, List<AbsThreadTask>> mThreadTasks = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private ThreadTaskManager() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ThreadTaskManager getInstance() {
|
||||||
|
if (INSTANCE == null) {
|
||||||
|
synchronized (ThreadTaskManager.class) {
|
||||||
|
INSTANCE = new ThreadTaskManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加单条线程记录
|
||||||
|
*
|
||||||
|
* @param key 任务对应的key
|
||||||
|
* @param threadTask 线程任务
|
||||||
|
*/
|
||||||
|
public void addTask(String key, AbsThreadTask threadTask) {
|
||||||
|
if (mThreadTasks.get(key) == null) {
|
||||||
|
mThreadTasks.put(key, new ArrayList<AbsThreadTask>());
|
||||||
|
}
|
||||||
|
mThreadTasks.get(key).add(threadTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除对应的任务的线程记录
|
||||||
|
*
|
||||||
|
* @param key 任务对应的key
|
||||||
|
*/
|
||||||
|
public void removeTask(String key) {
|
||||||
|
for (Iterator<Map.Entry<String, List<AbsThreadTask>>> iter = mThreadTasks.entrySet().iterator();
|
||||||
|
iter.hasNext(); ) {
|
||||||
|
Map.Entry<String, List<AbsThreadTask>> entry = iter.next();
|
||||||
|
if (key.equals(entry.getKey())) {
|
||||||
|
List<AbsThreadTask> list = mThreadTasks.get(key);
|
||||||
|
if (list != null && !list.isEmpty()) {
|
||||||
|
list.clear();
|
||||||
|
}
|
||||||
|
iter.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -57,22 +57,20 @@ class Downloader extends AbsFileer<DownloadEntity, DownloadTaskEntity> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override protected boolean handleNewTask() {
|
@Override protected boolean handleNewTask() {
|
||||||
CommonUtil.createFile(mTempFile.getPath());
|
if (!mRecord.isBlock) {
|
||||||
|
CommonUtil.createFile(mTempFile.getPath());
|
||||||
|
}
|
||||||
BufferedRandomAccessFile file = null;
|
BufferedRandomAccessFile file = null;
|
||||||
try {
|
try {
|
||||||
if (mTotalThreadNum > 1) {
|
if (mTotalThreadNum > 1 && !mRecord.isBlock) {
|
||||||
file = new BufferedRandomAccessFile(new File(mTempFile.getPath()), "rwd", 8192);
|
file = new BufferedRandomAccessFile(new File(mTempFile.getPath()), "rwd", 8192);
|
||||||
//设置文件长度
|
//设置文件长度
|
||||||
file.setLength(mEntity.getFileSize());
|
file.setLength(mEntity.getFileSize());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
failDownload("下载失败【downloadUrl:"
|
failDownload(String.format("下载失败【downloadUrl:%s】;【filePath:%s】\n %S", mEntity.getUrl(),
|
||||||
+ mEntity.getUrl()
|
mEntity.getDownloadPath(), ALog.getExceptionString(e)));
|
||||||
+ "】\n【filePath:"
|
|
||||||
+ mEntity.getDownloadPath()
|
|
||||||
+ "】\n"
|
|
||||||
+ ALog.getExceptionString(e));
|
|
||||||
} finally {
|
} finally {
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import org.apache.commons.net.ftp.FTPReply;
|
|||||||
class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity> {
|
class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity> {
|
||||||
private final String TAG = "FtpThreadTask";
|
private final String TAG = "FtpThreadTask";
|
||||||
private boolean isOpenDynamicFile;
|
private boolean isOpenDynamicFile;
|
||||||
|
private boolean isBlock;
|
||||||
|
|
||||||
FtpThreadTask(StateConstance constance, IDownloadListener listener,
|
FtpThreadTask(StateConstance constance, IDownloadListener listener,
|
||||||
SubThreadConfig<DownloadTaskEntity> downloadInfo) {
|
SubThreadConfig<DownloadTaskEntity> downloadInfo) {
|
||||||
@@ -50,11 +51,16 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity>
|
|||||||
mReadTimeOut = manager.getDownloadConfig().getIOTimeOut();
|
mReadTimeOut = manager.getDownloadConfig().getIOTimeOut();
|
||||||
mBufSize = manager.getDownloadConfig().getBuffSize();
|
mBufSize = manager.getDownloadConfig().getBuffSize();
|
||||||
isNotNetRetry = manager.getDownloadConfig().isNotNetRetry();
|
isNotNetRetry = manager.getDownloadConfig().isNotNetRetry();
|
||||||
isOpenDynamicFile = STATE.isOpenDynamicFile;
|
isOpenDynamicFile = STATE.TASK_RECORD.isOpenDynamicFile;
|
||||||
|
isBlock = STATE.TASK_RECORD.isBlock;
|
||||||
setMaxSpeed(manager.getDownloadConfig().getMaxSpeed());
|
setMaxSpeed(manager.getDownloadConfig().getMaxSpeed());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
|
if (mConfig.THREAD_RECORD.isComplete) {
|
||||||
|
handleComplete();
|
||||||
|
return;
|
||||||
|
}
|
||||||
//当前子线程的下载位置
|
//当前子线程的下载位置
|
||||||
mChildCurrentLocation = mConfig.START_LOCATION;
|
mChildCurrentLocation = mConfig.START_LOCATION;
|
||||||
FTPClient client = null;
|
FTPClient client = null;
|
||||||
@@ -100,19 +106,7 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity>
|
|||||||
if (isBreak()) {
|
if (isBreak()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ALog.i(TAG,
|
handleComplete();
|
||||||
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);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
fail(mChildCurrentLocation, String.format("下载失败【%s】", mConfig.URL), e);
|
fail(mChildCurrentLocation, String.format("下载失败【%s】", mConfig.URL), e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -131,6 +125,34 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理线程完成的情况
|
||||||
|
*/
|
||||||
|
private void handleComplete() {
|
||||||
|
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()) {
|
||||||
|
if (isBlock) {
|
||||||
|
boolean success = mergeFile();
|
||||||
|
if (!success) {
|
||||||
|
ALog.e(TAG, String.format("任务【%s】分块文件合并失败", mConfig.TEMP_FILE.getName()));
|
||||||
|
STATE.isRunning = false;
|
||||||
|
mListener.onFail(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
STATE.TASK_RECORD.deleteData();
|
||||||
|
STATE.isRunning = false;
|
||||||
|
mListener.onComplete();
|
||||||
|
}
|
||||||
|
if (STATE.isFail()) {
|
||||||
|
STATE.isRunning = false;
|
||||||
|
mListener.onFail(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 动态长度文件读取方式
|
* 动态长度文件读取方式
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import java.nio.channels.ReadableByteChannel;
|
|||||||
final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEntity> {
|
final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEntity> {
|
||||||
private final String TAG = "HttpThreadTask";
|
private final String TAG = "HttpThreadTask";
|
||||||
private boolean isOpenDynamicFile;
|
private boolean isOpenDynamicFile;
|
||||||
|
private boolean isBlock;
|
||||||
|
|
||||||
HttpThreadTask(StateConstance constance, IDownloadListener listener,
|
HttpThreadTask(StateConstance constance, IDownloadListener listener,
|
||||||
SubThreadConfig<DownloadTaskEntity> downloadInfo) {
|
SubThreadConfig<DownloadTaskEntity> downloadInfo) {
|
||||||
@@ -53,11 +54,16 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEnt
|
|||||||
mReadTimeOut = manager.getDownloadConfig().getIOTimeOut();
|
mReadTimeOut = manager.getDownloadConfig().getIOTimeOut();
|
||||||
mBufSize = manager.getDownloadConfig().getBuffSize();
|
mBufSize = manager.getDownloadConfig().getBuffSize();
|
||||||
isNotNetRetry = manager.getDownloadConfig().isNotNetRetry();
|
isNotNetRetry = manager.getDownloadConfig().isNotNetRetry();
|
||||||
isOpenDynamicFile = STATE.isOpenDynamicFile;
|
isOpenDynamicFile = STATE.TASK_RECORD.isOpenDynamicFile;
|
||||||
|
isBlock = STATE.TASK_RECORD.isBlock;
|
||||||
setMaxSpeed(manager.getDownloadConfig().getMaxSpeed());
|
setMaxSpeed(manager.getDownloadConfig().getMaxSpeed());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
|
if (mConfig.THREAD_RECORD.isComplete) {
|
||||||
|
handleComplete();
|
||||||
|
return;
|
||||||
|
}
|
||||||
HttpURLConnection conn = null;
|
HttpURLConnection conn = null;
|
||||||
BufferedInputStream is = null;
|
BufferedInputStream is = null;
|
||||||
BufferedRandomAccessFile file = null;
|
BufferedRandomAccessFile file = null;
|
||||||
@@ -209,6 +215,15 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEnt
|
|||||||
writeConfig(true, mConfig.END_LOCATION);
|
writeConfig(true, mConfig.END_LOCATION);
|
||||||
STATE.COMPLETE_THREAD_NUM++;
|
STATE.COMPLETE_THREAD_NUM++;
|
||||||
if (STATE.isComplete()) {
|
if (STATE.isComplete()) {
|
||||||
|
if (isBlock) {
|
||||||
|
boolean success = mergeFile();
|
||||||
|
if (!success) {
|
||||||
|
ALog.e(TAG, String.format("任务【%s】分块文件合并失败", mConfig.TEMP_FILE.getName()));
|
||||||
|
STATE.isRunning = false;
|
||||||
|
mListener.onFail(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
STATE.TASK_RECORD.deleteData();
|
STATE.TASK_RECORD.deleteData();
|
||||||
STATE.isRunning = false;
|
STATE.isRunning = false;
|
||||||
mListener.onComplete();
|
mListener.onComplete();
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class DBConfig {
|
|||||||
/*adb pull /mnt/sdcard/Android/data/com.arialyy.simple/files/DB/AriaLyyDb d:/db*/
|
/*adb pull /mnt/sdcard/Android/data/com.arialyy.simple/files/DB/AriaLyyDb d:/db*/
|
||||||
static Map<String, Class> mapping = new HashMap<>();
|
static Map<String, Class> mapping = new HashMap<>();
|
||||||
static String DB_NAME;
|
static String DB_NAME;
|
||||||
static int VERSION = 34;
|
static int VERSION = 35;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否将数据库保存在Sd卡,{@code true} 是
|
* 是否将数据库保存在Sd卡,{@code true} 是
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import com.arialyy.aria.core.command.group.AbsGroupCmd;
|
|||||||
import com.arialyy.aria.core.command.group.GroupCmdFactory;
|
import com.arialyy.aria.core.command.group.GroupCmdFactory;
|
||||||
import com.arialyy.aria.core.command.normal.AbsNormalCmd;
|
import com.arialyy.aria.core.command.normal.AbsNormalCmd;
|
||||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
||||||
|
import com.arialyy.aria.core.common.AbsFileer;
|
||||||
import com.arialyy.aria.core.common.TaskRecord;
|
import com.arialyy.aria.core.common.TaskRecord;
|
||||||
import com.arialyy.aria.core.download.DownloadEntity;
|
import com.arialyy.aria.core.download.DownloadEntity;
|
||||||
import com.arialyy.aria.core.download.DownloadGroupEntity;
|
import com.arialyy.aria.core.download.DownloadGroupEntity;
|
||||||
@@ -411,8 +412,17 @@ public class CommonUtil {
|
|||||||
if (records == null || records.isEmpty()) {
|
if (records == null || records.isEmpty()) {
|
||||||
ALog.w(TAG, "组任务记录删除失败,记录为null");
|
ALog.w(TAG, "组任务记录删除失败,记录为null");
|
||||||
} else {
|
} else {
|
||||||
for (TaskRecord tr : records) {
|
for (TaskRecord record : records) {
|
||||||
tr.deleteData();
|
// 删除分块文件
|
||||||
|
if (record.isBlock) {
|
||||||
|
for (int i = 0, len = record.threadNum; i < len; i++) {
|
||||||
|
File partFile = new File(String.format(AbsFileer.SUB_PATH, record.filePath, i));
|
||||||
|
if (partFile.exists()) {
|
||||||
|
partFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
record.deleteData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,8 +459,19 @@ public class CommonUtil {
|
|||||||
ALog.w(TAG, "删除记录失败,未知类型");
|
ALog.w(TAG, "删除记录失败,未知类型");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (file.exists() && (removeFile || !dEntity.isComplete())) {
|
if (removeFile || !dEntity.isComplete()) {
|
||||||
file.delete();
|
// 删除分块文件
|
||||||
|
if (record.isBlock) {
|
||||||
|
for (int i = 0, len = record.threadNum; i < len; i++) {
|
||||||
|
File partFile = new File(String.format(AbsFileer.SUB_PATH, record.filePath, i));
|
||||||
|
if (partFile.exists()) {
|
||||||
|
partFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (file.exists()) {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (record != null) {
|
if (record != null) {
|
||||||
|
|||||||
@@ -43,42 +43,44 @@ public class FileUtil {
|
|||||||
*
|
*
|
||||||
* @param targetPath 目标文件
|
* @param targetPath 目标文件
|
||||||
* @param subPaths 碎片文件路径
|
* @param subPaths 碎片文件路径
|
||||||
|
* @return {@code true} 合并成功,{@code false}合并失败
|
||||||
*/
|
*/
|
||||||
public static void mergeFile(String targetPath, List<String> subPaths) {
|
public static boolean mergeFile(String targetPath, List<String> subPaths) {
|
||||||
File file = new File(targetPath);
|
File file = new File(targetPath);
|
||||||
FileOutputStream fos = null;
|
FileOutputStream fos = null;
|
||||||
FileChannel foc = null;
|
FileChannel foc = null;
|
||||||
try {
|
try {
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
file.createNewFile();
|
file.createNewFile();
|
||||||
fos = new FileOutputStream(targetPath);
|
|
||||||
foc = fos.getChannel();
|
|
||||||
List<FileInputStream> streams = new LinkedList<>();
|
|
||||||
for (String subPath : subPaths) {
|
|
||||||
File f = new File(subPath);
|
|
||||||
if (!f.exists()) {
|
|
||||||
ALog.d(TAG, String.format("合并文件失败,文件【%s】不存在", subPath));
|
|
||||||
for (FileInputStream fis : streams) {
|
|
||||||
fis.close();
|
|
||||||
}
|
|
||||||
streams.clear();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
streams.add(new FileInputStream(subPath));
|
|
||||||
}
|
|
||||||
Enumeration<FileInputStream> en = Collections.enumeration(streams);
|
|
||||||
SequenceInputStream sis = new SequenceInputStream(en);
|
|
||||||
ReadableByteChannel fic = Channels.newChannel(sis);
|
|
||||||
ByteBuffer bf = ByteBuffer.allocate(8196);
|
|
||||||
while (fic.read(bf) != -1) {
|
|
||||||
bf.flip();
|
|
||||||
foc.write(bf);
|
|
||||||
bf.compact();
|
|
||||||
}
|
|
||||||
fic.close();
|
|
||||||
sis.close();
|
|
||||||
}
|
}
|
||||||
|
fos = new FileOutputStream(targetPath);
|
||||||
|
foc = fos.getChannel();
|
||||||
|
List<FileInputStream> streams = new LinkedList<>();
|
||||||
|
for (String subPath : subPaths) {
|
||||||
|
File f = new File(subPath);
|
||||||
|
if (!f.exists()) {
|
||||||
|
ALog.d(TAG, String.format("合并文件失败,文件【%s】不存在", subPath));
|
||||||
|
for (FileInputStream fis : streams) {
|
||||||
|
fis.close();
|
||||||
|
}
|
||||||
|
streams.clear();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
streams.add(new FileInputStream(subPath));
|
||||||
|
}
|
||||||
|
Enumeration<FileInputStream> en = Collections.enumeration(streams);
|
||||||
|
SequenceInputStream sis = new SequenceInputStream(en);
|
||||||
|
ReadableByteChannel fic = Channels.newChannel(sis);
|
||||||
|
ByteBuffer bf = ByteBuffer.allocate(8196);
|
||||||
|
while (fic.read(bf) != -1) {
|
||||||
|
bf.flip();
|
||||||
|
foc.write(bf);
|
||||||
|
bf.compact();
|
||||||
|
}
|
||||||
|
fic.close();
|
||||||
|
sis.close();
|
||||||
|
return true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} finally {
|
} finally {
|
||||||
@@ -93,6 +95,7 @@ public class FileUtil {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -11,6 +11,15 @@
|
|||||||
|
|
||||||
<!--注意,修改该配置文件中的属性会覆盖代码中所设置的属性-->
|
<!--注意,修改该配置文件中的属性会覆盖代码中所设置的属性-->
|
||||||
<download>
|
<download>
|
||||||
|
<!--
|
||||||
|
多线程下载是否使用块下载模式,{@code true}使用,{@code false}不使用
|
||||||
|
注意:
|
||||||
|
1、使用分块模式,在读写性能底下的手机上,合并文件需要的时间会更加长;
|
||||||
|
2、优点是使用多线程的块下载,初始化时,文件初始化时将不会预占用对应长度的空间;
|
||||||
|
3、只对新的多线程下载任务有效
|
||||||
|
4、只对多线程的任务有效
|
||||||
|
-->
|
||||||
|
<useBlock value="true"/>
|
||||||
|
|
||||||
<!--断网的时候是否重试,true:断网也重试;false:断网不重试,直接走失败的回调-->
|
<!--断网的时候是否重试,true:断网也重试;false:断网不重试,直接走失败的回调-->
|
||||||
<notNetRetry value="true"/>
|
<notNetRetry value="true"/>
|
||||||
@@ -22,7 +31,7 @@
|
|||||||
3、从3.4.1开始,如果线程数为1,文件初始化时将不再预占用对应长度的空间,下载多少byte,则占多大的空间;
|
3、从3.4.1开始,如果线程数为1,文件初始化时将不再预占用对应长度的空间,下载多少byte,则占多大的空间;
|
||||||
对于采用多线程的任务或旧任务,依然采用原来的文件空间占用方式;
|
对于采用多线程的任务或旧任务,依然采用原来的文件空间占用方式;
|
||||||
-->
|
-->
|
||||||
<threadNum value="1"/>
|
<threadNum value="3"/>
|
||||||
|
|
||||||
<!--设置下载队列最大任务数, 默认为2-->
|
<!--设置下载队列最大任务数, 默认为2-->
|
||||||
<maxTaskNum value="1"/>
|
<maxTaskNum value="1"/>
|
||||||
|
|||||||
@@ -18,10 +18,10 @@ public class AnyRunActivity extends BaseActivity<ActivityTestBinding> {
|
|||||||
AnyRunnModule module;
|
AnyRunnModule module;
|
||||||
String[] urls;
|
String[] urls;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
//String URL = "http://static.gaoshouyou.com/d/12/0d/7f120f50c80d2e7b8c4ba24ece4f9cdd.apk";
|
String URL = "http://static.gaoshouyou.com/d/12/0d/7f120f50c80d2e7b8c4ba24ece4f9cdd.apk";
|
||||||
//String URL = "http://58.213.157.242:8081/sims_file/rest/v1/file/mshd_touchscreen_ms/guideFile/41c33556-dc4a-4d78-bb76-b9f627f94448.mp4/%E5%85%AB%E5%8D%A6%E6%B4%B2%E5%8D%97%E4%BA%AC%E5%86%9C%E4%B8%9A%E5%98%89%E5%B9%B4%E5%8D%8E0511.mp4";
|
//String URL = "http://58.213.157.242:8081/sims_file/rest/v1/file/mshd_touchscreen_ms/guideFile/41c33556-dc4a-4d78-bb76-b9f627f94448.mp4/%E5%85%AB%E5%8D%A6%E6%B4%B2%E5%8D%97%E4%BA%AC%E5%86%9C%E4%B8%9A%E5%98%89%E5%B9%B4%E5%8D%8E0511.mp4";
|
||||||
//String URL = "http://d1.showself.com/download/showself_android-s236279_release.apk";
|
//String URL = "http://d1.showself.com/download/showself_android-s236279_release.apk";
|
||||||
String URL = "http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk";
|
//String URL = "http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk";
|
||||||
//private final String URL = "ftp://192.168.29.140:21/download/AriaPrj.rar";
|
//private final String URL = "ftp://192.168.29.140:21/download/AriaPrj.rar";
|
||||||
//String URL = "https://dl.genymotion.com/releases/genymotion-2.12.1/genymotion-2.12.1-vbox.exe";
|
//String URL = "https://dl.genymotion.com/releases/genymotion-2.12.1/genymotion-2.12.1-vbox.exe";
|
||||||
//String URL = "ftp://192.168.29.140:21/download/SDK_Demo-release.apk";
|
//String URL = "ftp://192.168.29.140:21/download/SDK_Demo-release.apk";
|
||||||
|
|||||||
@@ -65,11 +65,11 @@ public class AnyRunnModule {
|
|||||||
|
|
||||||
void start(String url) {
|
void start(String url) {
|
||||||
mUrl = url;
|
mUrl = url;
|
||||||
String path = Environment.getExternalStorageDirectory().getPath() + "/abcds.exe";
|
String path = Environment.getExternalStorageDirectory().getPath() + "/abcds.apk";
|
||||||
File file = new File(path);
|
//File file = new File(path);
|
||||||
if (file.exists()) {
|
//if (file.exists()) {
|
||||||
file.delete();
|
// file.delete();
|
||||||
}
|
//}
|
||||||
Aria.download(this)
|
Aria.download(this)
|
||||||
.load(url)
|
.load(url)
|
||||||
//.addHeader("Accept-Encoding", "gzip")
|
//.addHeader("Accept-Encoding", "gzip")
|
||||||
|
|||||||
@@ -379,6 +379,26 @@ class Configuration {
|
|||||||
*/
|
*/
|
||||||
int maxSpeed = 0;
|
int maxSpeed = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多线程下载是否使用块下载模式,{@code true}使用,{@code false}不使用
|
||||||
|
* 注意:
|
||||||
|
* 1、使用分块模式,在读写性能底下的手机上,合并文件需要的时间会更加长;
|
||||||
|
* 2、优点是使用多线程的块下载,初始化时,文件初始化时将不会预占用对应长度的空间;
|
||||||
|
* 3、只对新的多线程下载任务有效
|
||||||
|
* 4、只对多线程的任务有效
|
||||||
|
*/
|
||||||
|
boolean useBlock = false;
|
||||||
|
|
||||||
|
public boolean isUseBlock() {
|
||||||
|
return useBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DownloadConfig setUseBlock(boolean useBlock) {
|
||||||
|
this.useBlock = useBlock;
|
||||||
|
saveKey("useBlock", String.valueOf(useBlock));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public DownloadConfig setMaxTaskNum(int maxTaskNum) {
|
public DownloadConfig setMaxTaskNum(int maxTaskNum) {
|
||||||
oldMaxTaskNum = this.maxTaskNum;
|
oldMaxTaskNum = this.maxTaskNum;
|
||||||
this.maxTaskNum = maxTaskNum;
|
this.maxTaskNum = maxTaskNum;
|
||||||
@@ -398,9 +418,10 @@ class Configuration {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setThreadNum(int threadNum) {
|
public DownloadConfig setThreadNum(int threadNum) {
|
||||||
this.threadNum = threadNum;
|
this.threadNum = threadNum;
|
||||||
saveKey("threadNum", String.valueOf(threadNum));
|
saveKey("threadNum", String.valueOf(threadNum));
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCaPath() {
|
public String getCaPath() {
|
||||||
|
|||||||
Reference in New Issue
Block a user