删除记录bug修复;动态文件长度实现修改;
This commit is contained in:
@@ -59,9 +59,6 @@ class ConfigHelper extends DefaultHandler {
|
|||||||
|
|
||||||
String value = attributes.getValue("value");
|
String value = attributes.getValue("value");
|
||||||
switch (qName) {
|
switch (qName) {
|
||||||
case "openDynamicFile":
|
|
||||||
loadOpenDynamicFile(value);
|
|
||||||
break;
|
|
||||||
case "threadNum":
|
case "threadNum":
|
||||||
loadThreadNum(value);
|
loadThreadNum(value);
|
||||||
break;
|
break;
|
||||||
@@ -117,12 +114,6 @@ class ConfigHelper extends DefaultHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadOpenDynamicFile(String value) {
|
|
||||||
if (isDownloadConfig) {
|
|
||||||
mDownloadConfig.openDynamicFile = checkBoolean(value) ? Boolean.valueOf(value) : false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadNotNetRetry(String value) {
|
private void loadNotNetRetry(String value) {
|
||||||
if (isDownloadConfig) {
|
if (isDownloadConfig) {
|
||||||
mDownloadConfig.notNetRetry = checkBoolean(value) ? Boolean.valueOf(value) : false;
|
mDownloadConfig.notNetRetry = checkBoolean(value) ? Boolean.valueOf(value) : false;
|
||||||
|
|||||||
@@ -44,8 +44,11 @@ import java.util.concurrent.Executors;
|
|||||||
*/
|
*/
|
||||||
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_";
|
private static final String STATE = "_state_";
|
||||||
public static final String RECORD = "_record_";
|
private static final String RECORD = "_record_";
|
||||||
|
/**
|
||||||
|
* 小于1m的文件不启用多线程
|
||||||
|
*/
|
||||||
protected static final long SUB_LEN = 1024 * 1024;
|
protected static final long SUB_LEN = 1024 * 1024;
|
||||||
|
|
||||||
private final String TAG = "AbsFileer";
|
private final String TAG = "AbsFileer";
|
||||||
@@ -57,16 +60,14 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
protected StateConstance mConstance;
|
protected StateConstance mConstance;
|
||||||
private ExecutorService mFixedThreadPool;
|
private ExecutorService mFixedThreadPool;
|
||||||
//总线程数
|
//总线程数
|
||||||
private int mTotalThreadNum;
|
protected int mTotalThreadNum;
|
||||||
//启动线程数
|
//启动线程数
|
||||||
private int mStartThreadNum;
|
private int mStartThreadNum;
|
||||||
//已完成的线程数
|
//已完成的线程数
|
||||||
private int mCompleteThreadNum;
|
private int mCompleteThreadNum;
|
||||||
private SparseArray<AbsThreadTask> mTask = new SparseArray<>();
|
private SparseArray<AbsThreadTask> mTask = new SparseArray<>();
|
||||||
|
|
||||||
/**
|
|
||||||
* 小于1m的文件不启用多线程
|
|
||||||
*/
|
|
||||||
private Timer mTimer;
|
private Timer mTimer;
|
||||||
@Deprecated
|
@Deprecated
|
||||||
private File mConfigFile;
|
private File mConfigFile;
|
||||||
@@ -74,7 +75,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
* 进度刷新间隔
|
* 进度刷新间隔
|
||||||
*/
|
*/
|
||||||
private long mUpdateInterval = 1000;
|
private long mUpdateInterval = 1000;
|
||||||
protected TaskRecord mRecord;
|
private TaskRecord mRecord;
|
||||||
|
|
||||||
protected AbsFileer(IEventListener listener, TASK_ENTITY taskEntity) {
|
protected AbsFileer(IEventListener listener, TASK_ENTITY taskEntity) {
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
@@ -124,6 +125,16 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
handleBreakpoint();
|
handleBreakpoint();
|
||||||
}
|
}
|
||||||
mConstance.START_THREAD_NUM = mTotalThreadNum;
|
mConstance.START_THREAD_NUM = mTotalThreadNum;
|
||||||
|
/*
|
||||||
|
* mTaskEntity.getEntity().getFileSize() != mTempFile.length()为兼容以前老版本代码
|
||||||
|
* 动态长度条件:
|
||||||
|
* 1、总线程数为1,并且是新任务
|
||||||
|
* 2、总线程数为1,不是新任务,但是长度不是文件全长度
|
||||||
|
*/
|
||||||
|
if (mTotalThreadNum == 1 && (mTaskEntity.isNewTask()
|
||||||
|
|| mTaskEntity.getEntity().getFileSize() != mTempFile.length())) {
|
||||||
|
mConstance.isOpenDynamicFile = true;
|
||||||
|
}
|
||||||
startTimer();
|
startTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,7 +248,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
* 3、数据库记录不存在
|
* 3、数据库记录不存在
|
||||||
* 4、不支持断点,则是新任务
|
* 4、不支持断点,则是新任务
|
||||||
*/
|
*/
|
||||||
protected void checkTask() {
|
private void checkTask() {
|
||||||
mConfigFile = new File(CommonUtil.getFileConfigPath(false, mEntity.getFileName()));
|
mConfigFile = new File(CommonUtil.getFileConfigPath(false, mEntity.getFileName()));
|
||||||
if (mConfigFile.exists()) {
|
if (mConfigFile.exists()) {
|
||||||
convertDb();
|
convertDb();
|
||||||
@@ -334,8 +345,6 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
mRecord.filePath = mTaskEntity.getKey();
|
mRecord.filePath = mTaskEntity.getKey();
|
||||||
mRecord.threadRecords = new ArrayList<>();
|
mRecord.threadRecords = new ArrayList<>();
|
||||||
mRecord.isGroupRecord = mTaskEntity.getEntity().isGroupChild();
|
mRecord.isGroupRecord = mTaskEntity.getEntity().isGroupChild();
|
||||||
mRecord.isOpenDynamicFile =
|
|
||||||
AriaManager.getInstance(AriaManager.APP).getDownloadConfig().isOpenDynamicFile();
|
|
||||||
if (mRecord.isGroupRecord) {
|
if (mRecord.isGroupRecord) {
|
||||||
if (mTaskEntity.getEntity() instanceof DownloadEntity) {
|
if (mTaskEntity.getEntity() instanceof DownloadEntity) {
|
||||||
mRecord.dGroupName = ((DownloadEntity) mTaskEntity.getEntity()).getGroupName();
|
mRecord.dGroupName = ((DownloadEntity) mTaskEntity.getEntity()).getGroupName();
|
||||||
|
|||||||
@@ -30,6 +30,11 @@ 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() {
|
public StateConstance() {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,10 +73,4 @@ public class TaskRecord extends DbEntity {
|
|||||||
@Ignore
|
@Ignore
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public String uGroupName;
|
public String uGroupName;
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否是使用虚拟文件下载的
|
|
||||||
* {@code true}是,{@code false}不是
|
|
||||||
*/
|
|
||||||
public boolean isOpenDynamicFile = false;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ import android.os.Handler;
|
|||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaManager;
|
||||||
import com.arialyy.aria.core.common.TaskRecord;
|
import com.arialyy.aria.core.common.TaskRecord;
|
||||||
import com.arialyy.aria.core.inf.AbsEntity;
|
import com.arialyy.aria.core.inf.AbsEntity;
|
||||||
import com.arialyy.aria.core.inf.AbsGroupEntity;
|
|
||||||
import com.arialyy.aria.core.inf.AbsNormalEntity;
|
|
||||||
import com.arialyy.aria.core.inf.AbsTask;
|
import com.arialyy.aria.core.inf.AbsTask;
|
||||||
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;
|
||||||
@@ -158,14 +156,16 @@ class BaseDListener<ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity<
|
|||||||
mEntity.setState(state);
|
mEntity.setState(state);
|
||||||
mEntity.setComplete(state == IEntity.STATE_COMPLETE);
|
mEntity.setComplete(state == IEntity.STATE_COMPLETE);
|
||||||
if (state == IEntity.STATE_CANCEL) {
|
if (state == IEntity.STATE_CANCEL) {
|
||||||
if (mEntity instanceof AbsNormalEntity) {
|
if (mEntity instanceof DownloadEntity) {
|
||||||
TaskRecord record =
|
TaskRecord record =
|
||||||
DbEntity.findFirst(TaskRecord.class, "TaskRecord.filePath=?", mTaskEntity.getKey());
|
DbEntity.findFirst(TaskRecord.class, "TaskRecord.filePath=?", mTaskEntity.getKey());
|
||||||
if (record != null) {
|
if (record != null) {
|
||||||
CommonUtil.delTaskRecord(record, mTaskEntity.isRemoveFile(), (AbsNormalEntity) mEntity);
|
CommonUtil.delTaskRecord(record, mTaskEntity.isRemoveFile(), (DownloadEntity) mEntity);
|
||||||
|
} else {
|
||||||
|
mEntity.deleteData();
|
||||||
}
|
}
|
||||||
} else if (mEntity instanceof AbsGroupEntity) {
|
} else if (mEntity instanceof DownloadGroupEntity) {
|
||||||
CommonUtil.delGroupTaskRecord(mTaskEntity.isRemoveFile(), ((AbsGroupEntity) mEntity));
|
CommonUtil.delGroupTaskRecord(mTaskEntity.isRemoveFile(), ((DownloadGroupEntity) mEntity));
|
||||||
}
|
}
|
||||||
//mEntity.deleteData();
|
//mEntity.deleteData();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -45,23 +45,26 @@ class Downloader extends AbsFileer<DownloadEntity, DownloadTaskEntity> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override protected int setNewTaskThreadNum() {
|
@Override protected int setNewTaskThreadNum() {
|
||||||
|
int threadNum = AriaManager.getInstance(mContext).getDownloadConfig().getThreadNum();
|
||||||
return
|
return
|
||||||
// 小于1m的文件或是任务组的子任务、使用虚拟文件,线程数都是1
|
// 小于1m的文件或是任务组的子任务、使用虚拟文件,线程数都是1
|
||||||
mEntity.getFileSize() <= SUB_LEN
|
mEntity.getFileSize() <= SUB_LEN
|
||||||
|| mTaskEntity.getRequestType() == AbsTaskEntity.D_FTP_DIR
|
|| mTaskEntity.getRequestType() == AbsTaskEntity.D_FTP_DIR
|
||||||
|| mTaskEntity.getRequestType() == AbsTaskEntity.DG_HTTP
|
|| mTaskEntity.getRequestType() == AbsTaskEntity.DG_HTTP
|
||||||
|| mRecord.isOpenDynamicFile
|
|| threadNum == 1
|
||||||
? 1
|
? 1
|
||||||
: AriaManager.getInstance(mContext).getDownloadConfig().getThreadNum();
|
: threadNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected boolean handleNewTask() {
|
@Override protected boolean handleNewTask() {
|
||||||
CommonUtil.createFile(mTempFile.getPath());
|
CommonUtil.createFile(mTempFile.getPath());
|
||||||
BufferedRandomAccessFile file = null;
|
BufferedRandomAccessFile file = null;
|
||||||
try {
|
try {
|
||||||
file = new BufferedRandomAccessFile(new File(mTempFile.getPath()), "rwd", 8192);
|
if (mTotalThreadNum > 1) {
|
||||||
//设置文件长度
|
file = new BufferedRandomAccessFile(new File(mTempFile.getPath()), "rwd", 8192);
|
||||||
file.setLength(mRecord.isOpenDynamicFile ? 1 : mEntity.getFileSize());
|
//设置文件长度
|
||||||
|
file.setLength(mEntity.getFileSize());
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
failDownload("下载失败【downloadUrl:"
|
failDownload("下载失败【downloadUrl:"
|
||||||
|
|||||||
@@ -24,8 +24,13 @@ import com.arialyy.aria.core.download.DownloadTaskEntity;
|
|||||||
import com.arialyy.aria.core.inf.IDownloadListener;
|
import com.arialyy.aria.core.inf.IDownloadListener;
|
||||||
import com.arialyy.aria.util.ALog;
|
import com.arialyy.aria.util.ALog;
|
||||||
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.Channels;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.nio.channels.ReadableByteChannel;
|
||||||
import org.apache.commons.net.ftp.FTPClient;
|
import org.apache.commons.net.ftp.FTPClient;
|
||||||
import org.apache.commons.net.ftp.FTPReply;
|
import org.apache.commons.net.ftp.FTPReply;
|
||||||
|
|
||||||
@@ -36,10 +41,6 @@ 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;
|
||||||
/**
|
|
||||||
* 2M的动态长度
|
|
||||||
*/
|
|
||||||
private final int LEN_INTERVAL = 1024 * 1024 * 2;
|
|
||||||
|
|
||||||
FtpThreadTask(StateConstance constance, IDownloadListener listener,
|
FtpThreadTask(StateConstance constance, IDownloadListener listener,
|
||||||
SubThreadConfig<DownloadTaskEntity> downloadInfo) {
|
SubThreadConfig<DownloadTaskEntity> downloadInfo) {
|
||||||
@@ -49,7 +50,7 @@ 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.TASK_RECORD.isOpenDynamicFile;
|
isOpenDynamicFile = STATE.isOpenDynamicFile;
|
||||||
setMaxSpeed(manager.getDownloadConfig().getMaxSpeed());
|
setMaxSpeed(manager.getDownloadConfig().getMaxSpeed());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +59,7 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity>
|
|||||||
mChildCurrentLocation = mConfig.START_LOCATION;
|
mChildCurrentLocation = mConfig.START_LOCATION;
|
||||||
FTPClient client = null;
|
FTPClient client = null;
|
||||||
InputStream is = null;
|
InputStream is = null;
|
||||||
BufferedRandomAccessFile file = null;
|
|
||||||
try {
|
try {
|
||||||
ALog.d(TAG, "任务【"
|
ALog.d(TAG, "任务【"
|
||||||
+ mConfig.TEMP_FILE.getName()
|
+ mConfig.TEMP_FILE.getName()
|
||||||
@@ -94,31 +95,12 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
file = new BufferedRandomAccessFile(mConfig.TEMP_FILE, "rwd", mBufSize);
|
if (isOpenDynamicFile) {
|
||||||
file.seek(mConfig.START_LOCATION);
|
readDynamicFile(is);
|
||||||
byte[] buffer = new byte[mBufSize];
|
} else {
|
||||||
int len;
|
readNormal(is);
|
||||||
|
|
||||||
while ((len = is.read(buffer)) != -1) {
|
|
||||||
if (STATE.isCancel || STATE.isStop) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (mSleepTime > 0) Thread.sleep(mSleepTime);
|
|
||||||
if (isOpenDynamicFile) {
|
|
||||||
file.setLength(
|
|
||||||
STATE.CURRENT_LOCATION + LEN_INTERVAL < mEntity.getFileSize() ? STATE.CURRENT_LOCATION
|
|
||||||
+ LEN_INTERVAL : mEntity.getFileSize());
|
|
||||||
}
|
|
||||||
if (mChildCurrentLocation + len >= mConfig.END_LOCATION) {
|
|
||||||
len = (int) (mConfig.END_LOCATION - mChildCurrentLocation);
|
|
||||||
file.write(buffer, 0, len);
|
|
||||||
progress(len);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
file.write(buffer, 0, len);
|
|
||||||
progress(len);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (STATE.isCancel || STATE.isStop) return;
|
if (STATE.isCancel || STATE.isStop) return;
|
||||||
ALog.i(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】线程__" + mConfig.THREAD_ID + "__下载完毕");
|
ALog.i(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】线程__" + mConfig.THREAD_ID + "__下载完毕");
|
||||||
writeConfig(true, 1);
|
writeConfig(true, 1);
|
||||||
@@ -138,9 +120,6 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity>
|
|||||||
fail(mChildCurrentLocation, "获取流失败", e);
|
fail(mChildCurrentLocation, "获取流失败", e);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (file != null) {
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
if (is != null) {
|
if (is != null) {
|
||||||
is.close();
|
is.close();
|
||||||
}
|
}
|
||||||
@@ -153,6 +132,92 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态长度文件读取方式
|
||||||
|
*/
|
||||||
|
private void readDynamicFile(InputStream is) {
|
||||||
|
FileOutputStream fos = null;
|
||||||
|
FileChannel foc = null;
|
||||||
|
ReadableByteChannel fic = null;
|
||||||
|
try {
|
||||||
|
int len;
|
||||||
|
fos = new FileOutputStream(mConfig.TEMP_FILE, true);
|
||||||
|
foc = fos.getChannel();
|
||||||
|
fic = Channels.newChannel(is);
|
||||||
|
ByteBuffer bf = ByteBuffer.allocate(mBufSize);
|
||||||
|
while ((len = fic.read(bf)) != -1) {
|
||||||
|
if (STATE.isCancel || STATE.isStop) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (mSleepTime > 0) {
|
||||||
|
Thread.sleep(mSleepTime);
|
||||||
|
}
|
||||||
|
bf.flip();
|
||||||
|
foc.write(bf);
|
||||||
|
bf.compact();
|
||||||
|
progress(len);
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail(mChildCurrentLocation, "下载失败【" + mConfig.URL + "】", e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (fos != null) {
|
||||||
|
fos.close();
|
||||||
|
}
|
||||||
|
if (foc != null) {
|
||||||
|
foc.close();
|
||||||
|
}
|
||||||
|
if (fic != null) {
|
||||||
|
fic.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多线程写文件方式
|
||||||
|
*/
|
||||||
|
private void readNormal(InputStream is) {
|
||||||
|
BufferedRandomAccessFile file = null;
|
||||||
|
try {
|
||||||
|
file = new BufferedRandomAccessFile(mConfig.TEMP_FILE, "rwd", mBufSize);
|
||||||
|
file.seek(mConfig.START_LOCATION);
|
||||||
|
byte[] buffer = new byte[mBufSize];
|
||||||
|
int len;
|
||||||
|
while ((len = is.read(buffer)) != -1) {
|
||||||
|
if (STATE.isCancel || STATE.isStop) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (mSleepTime > 0) Thread.sleep(mSleepTime);
|
||||||
|
if (mChildCurrentLocation + len >= mConfig.END_LOCATION) {
|
||||||
|
len = (int) (mConfig.END_LOCATION - mChildCurrentLocation);
|
||||||
|
file.write(buffer, 0, len);
|
||||||
|
progress(len);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
file.write(buffer, 0, len);
|
||||||
|
progress(len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail(mChildCurrentLocation, "下载失败【" + mConfig.URL + "】", e);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (file != null) {
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override protected String getTaskType() {
|
@Override protected String getTaskType() {
|
||||||
return "FTP_DOWNLOAD";
|
return "FTP_DOWNLOAD";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,11 +26,16 @@ import com.arialyy.aria.util.ALog;
|
|||||||
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
import com.arialyy.aria.util.BufferedRandomAccessFile;
|
||||||
import com.arialyy.aria.util.CommonUtil;
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.channels.Channels;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.nio.channels.ReadableByteChannel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by lyy on 2017/1/18.
|
* Created by lyy on 2017/1/18.
|
||||||
@@ -38,10 +43,6 @@ import java.net.URL;
|
|||||||
*/
|
*/
|
||||||
final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEntity> {
|
final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEntity> {
|
||||||
private final String TAG = "HttpThreadTask";
|
private final String TAG = "HttpThreadTask";
|
||||||
/**
|
|
||||||
* 2M的动态长度
|
|
||||||
*/
|
|
||||||
private final int LEN_INTERVAL = 1024 * 1024 * 2;
|
|
||||||
private boolean isOpenDynamicFile;
|
private boolean isOpenDynamicFile;
|
||||||
|
|
||||||
HttpThreadTask(StateConstance constance, IDownloadListener listener,
|
HttpThreadTask(StateConstance constance, IDownloadListener listener,
|
||||||
@@ -52,7 +53,7 @@ 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.TASK_RECORD.isOpenDynamicFile;
|
isOpenDynamicFile = STATE.isOpenDynamicFile;
|
||||||
setMaxSpeed(manager.getDownloadConfig().getMaxSpeed());
|
setMaxSpeed(manager.getDownloadConfig().getMaxSpeed());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,15 +87,18 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEnt
|
|||||||
conn.setReadTimeout(mReadTimeOut); //设置读取流的等待时间,必须设置该参数
|
conn.setReadTimeout(mReadTimeOut); //设置读取流的等待时间,必须设置该参数
|
||||||
|
|
||||||
is = new BufferedInputStream(ConnectionHelp.convertInputStream(conn));
|
is = new BufferedInputStream(ConnectionHelp.convertInputStream(conn));
|
||||||
//创建可设置位置的文件
|
if (isOpenDynamicFile) {
|
||||||
file = new BufferedRandomAccessFile(mConfig.TEMP_FILE, "rwd", mBufSize);
|
readDynamicFile(is);
|
||||||
//设置每条线程写入文件的位置
|
|
||||||
file.seek(mConfig.START_LOCATION);
|
|
||||||
|
|
||||||
if (mTaskEntity.isChunked()) {
|
|
||||||
readChunk(is, file);
|
|
||||||
} else {
|
} else {
|
||||||
readNormal(is, file);
|
//创建可设置位置的文件
|
||||||
|
file = new BufferedRandomAccessFile(mConfig.TEMP_FILE, "rwd", mBufSize);
|
||||||
|
//设置每条线程写入文件的位置
|
||||||
|
file.seek(mConfig.START_LOCATION);
|
||||||
|
if (mTaskEntity.isChunked()) {
|
||||||
|
readChunk(is, file);
|
||||||
|
} else {
|
||||||
|
readNormal(is, file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (STATE.isCancel || STATE.isStop) {
|
if (STATE.isCancel || STATE.isStop) {
|
||||||
@@ -124,6 +128,52 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEnt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态长度文件读取方式
|
||||||
|
*/
|
||||||
|
private void readDynamicFile(InputStream is) {
|
||||||
|
FileOutputStream fos = null;
|
||||||
|
FileChannel foc = null;
|
||||||
|
ReadableByteChannel fic = null;
|
||||||
|
try {
|
||||||
|
int len;
|
||||||
|
fos = new FileOutputStream(mConfig.TEMP_FILE, true);
|
||||||
|
foc = fos.getChannel();
|
||||||
|
fic = Channels.newChannel(is);
|
||||||
|
ByteBuffer bf = ByteBuffer.allocate(mBufSize);
|
||||||
|
while ((len = fic.read(bf)) != -1) {
|
||||||
|
if (STATE.isCancel || STATE.isStop) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (mSleepTime > 0) {
|
||||||
|
Thread.sleep(mSleepTime);
|
||||||
|
}
|
||||||
|
bf.flip();
|
||||||
|
foc.write(bf);
|
||||||
|
bf.compact();
|
||||||
|
progress(len);
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail(mChildCurrentLocation, "下载失败【" + mConfig.URL + "】", e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (fos != null) {
|
||||||
|
fos.close();
|
||||||
|
}
|
||||||
|
if (foc != null) {
|
||||||
|
foc.close();
|
||||||
|
}
|
||||||
|
if (fic != null) {
|
||||||
|
fic.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 读取chunk模式的文件流
|
* 读取chunk模式的文件流
|
||||||
*
|
*
|
||||||
@@ -148,11 +198,6 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEnt
|
|||||||
if (mSleepTime > 0) {
|
if (mSleepTime > 0) {
|
||||||
Thread.sleep(mSleepTime);
|
Thread.sleep(mSleepTime);
|
||||||
}
|
}
|
||||||
if (isOpenDynamicFile) {
|
|
||||||
file.setLength(
|
|
||||||
STATE.CURRENT_LOCATION + LEN_INTERVAL < mEntity.getFileSize() ? STATE.CURRENT_LOCATION
|
|
||||||
+ LEN_INTERVAL : mEntity.getFileSize());
|
|
||||||
}
|
|
||||||
file.write(buffer, 0, len);
|
file.write(buffer, 0, len);
|
||||||
progress(len);
|
progress(len);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -311,7 +311,9 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, TASK extends Abs
|
|||||||
private void startNextTask() {
|
private void startNextTask() {
|
||||||
TASK newTask = mQueue.getNextTask();
|
TASK newTask = mQueue.getNextTask();
|
||||||
if (newTask == null) {
|
if (newTask == null) {
|
||||||
ALog.i(TAG, "没有下一任务");
|
if (mQueue.getCurrentExePoolNum() == 0) {
|
||||||
|
ALog.i(TAG, "没有下一任务");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (newTask.getState() == IEntity.STATE_WAIT) {
|
if (newTask.getState() == IEntity.STATE_WAIT) {
|
||||||
|
|||||||
@@ -144,15 +144,16 @@ class BaseUListener<ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity<
|
|||||||
mEntity.setState(state);
|
mEntity.setState(state);
|
||||||
mEntity.setComplete(state == IEntity.STATE_COMPLETE);
|
mEntity.setComplete(state == IEntity.STATE_COMPLETE);
|
||||||
if (state == IEntity.STATE_CANCEL) {
|
if (state == IEntity.STATE_CANCEL) {
|
||||||
if (mEntity instanceof AbsNormalEntity) {
|
if (mEntity instanceof UploadEntity) {
|
||||||
TaskRecord record =
|
TaskRecord record =
|
||||||
DbEntity.findFirst(TaskRecord.class, "TaskRecord.filePath=?", mTaskEntity.getKey());
|
DbEntity.findFirst(TaskRecord.class, "TaskRecord.filePath=?", mTaskEntity.getKey());
|
||||||
if (record != null) {
|
if (record != null) {
|
||||||
CommonUtil.delTaskRecord(record, mTaskEntity.isRemoveFile(), (AbsNormalEntity) mEntity);
|
CommonUtil.delTaskRecord(record, mTaskEntity.isRemoveFile(), (UploadEntity) mEntity);
|
||||||
}
|
}
|
||||||
} else if (mEntity instanceof AbsGroupEntity) {
|
|
||||||
CommonUtil.delGroupTaskRecord(mTaskEntity.isRemoveFile(), ((AbsGroupEntity) mEntity));
|
|
||||||
}
|
}
|
||||||
|
//else if (mEntity instanceof AbsGroupEntity) {
|
||||||
|
// CommonUtil.delGroupTaskRecord(mTaskEntity.isRemoveFile(), ((AbsGroupEntity) mEntity));
|
||||||
|
//}
|
||||||
return;
|
return;
|
||||||
} else if (mEntity.isComplete()) {
|
} else if (mEntity.isComplete()) {
|
||||||
mEntity.setCompleteTime(System.currentTimeMillis());
|
mEntity.setCompleteTime(System.currentTimeMillis());
|
||||||
|
|||||||
@@ -410,11 +410,10 @@ public class CommonUtil {
|
|||||||
|
|
||||||
if (records == null || records.isEmpty()) {
|
if (records == null || records.isEmpty()) {
|
||||||
ALog.w(TAG, "组任务记录删除失败,记录为null");
|
ALog.w(TAG, "组任务记录删除失败,记录为null");
|
||||||
return;
|
} else {
|
||||||
}
|
for (TaskRecord tr : records) {
|
||||||
|
tr.deleteData();
|
||||||
for (TaskRecord tr : records) {
|
}
|
||||||
tr.deleteData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
File dir = new File(groupEntity.getDirPath());
|
File dir = new File(groupEntity.getDirPath());
|
||||||
|
|||||||
@@ -15,10 +15,10 @@
|
|||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme.NoActionBar">
|
android:theme="@style/AppTheme.NoActionBar">
|
||||||
<!--android:name=".test.TestGroupActivity"-->
|
<!--android:name=".test.TestGroupActivity"-->
|
||||||
<!--android:name=".test.AnyRunActivity"-->
|
|
||||||
<!--android:name=".test.TestActivity"-->
|
<!--android:name=".test.TestActivity"-->
|
||||||
|
<!--android:name=".MainActivity"-->
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".test.AnyRunActivity"
|
||||||
android:label="@string/app_name">
|
android:label="@string/app_name">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
|||||||
@@ -11,17 +11,17 @@
|
|||||||
|
|
||||||
<!--注意,修改该配置文件中的属性会覆盖代码中所设置的属性-->
|
<!--注意,修改该配置文件中的属性会覆盖代码中所设置的属性-->
|
||||||
<download>
|
<download>
|
||||||
<!--是否开启动态文件,开启动态文件后初始化时将不占用磁盘空间,下载多少byte,占多少空间,效果见chrome的下载。-->
|
|
||||||
<!--注意:
|
|
||||||
1、使用该功能,将自动关闭多线程下载;
|
|
||||||
2、对于已经采用了多线程的任务,依然采用原来的下载方式;
|
|
||||||
3、原本参数是true,任务没下载完成,就参数改为false,那么没下载完成的任务还是会按照参数修改前的方式下载;只有新任务才会根据参数调用不同的下载方式。-->
|
|
||||||
<openDynamicFile value="true"/>
|
|
||||||
|
|
||||||
<!--断网的时候是否重试,true:断网也重试;false:断网不重试,直接走失败的回调-->
|
<!--断网的时候是否重试,true:断网也重试;false:断网不重试,直接走失败的回调-->
|
||||||
<notNetRetry value="true"/>
|
<notNetRetry value="true"/>
|
||||||
|
|
||||||
<!--设置下载线程,线程下载数改变后,新的下载任务才会生效,如果任务大小小于1m,该设置也不会生效-->
|
<!--设置下载线程数,下载线程数不能小于1
|
||||||
|
注意:
|
||||||
|
1、线程下载数改变后,新的下载任务才会生效;
|
||||||
|
2、如果任务大小小于1m,该设置不会生效;
|
||||||
|
3、从3.4.1开始,如果线程数为1,文件初始化时将不再预占用对应长度的空间,下载多少byte,则占多大的空间;
|
||||||
|
对于采用多线程的任务或旧任务,依然采用原来的文件空间占用方式;
|
||||||
|
-->
|
||||||
<threadNum value="3"/>
|
<threadNum value="3"/>
|
||||||
|
|
||||||
<!--设置下载队列最大任务数, 默认为2-->
|
<!--设置下载队列最大任务数, 默认为2-->
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ 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://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";
|
||||||
|
|
||||||
@Override protected int setLayoutId() {
|
@Override protected int setLayoutId() {
|
||||||
@@ -42,7 +42,8 @@ public class AnyRunActivity extends BaseActivity<ActivityTestBinding> {
|
|||||||
//}
|
//}
|
||||||
//for (int i = 0; i < 10; i++) {
|
//for (int i = 0; i < 10; i++) {
|
||||||
|
|
||||||
module.startFtp(URL);
|
//module.startFtp(URL);
|
||||||
|
module.start(URL);
|
||||||
//}
|
//}
|
||||||
//List<AbsEntity> list = Aria.download(this).getTotalTaskList();
|
//List<AbsEntity> list = Aria.download(this).getTotalTaskList();
|
||||||
//ALog.d(TAG, "size ==> " + list.size());
|
//ALog.d(TAG, "size ==> " + list.size());
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public class AnyRunnModule {
|
|||||||
.load(url)
|
.load(url)
|
||||||
//.addHeader("Accept-Encoding", "gzip")
|
//.addHeader("Accept-Encoding", "gzip")
|
||||||
.setRequestMode(RequestEnum.GET)
|
.setRequestMode(RequestEnum.GET)
|
||||||
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/ggsg123456.apk")
|
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/ggsg1234567.apk")
|
||||||
//.resetState()
|
//.resetState()
|
||||||
.start();
|
.start();
|
||||||
//String[] urls = new String[] {
|
//String[] urls = new String[] {
|
||||||
|
|||||||
@@ -366,6 +366,11 @@ class Configuration {
|
|||||||
String caName;
|
String caName;
|
||||||
/**
|
/**
|
||||||
* 下载线程数,下载线程数不能小于1
|
* 下载线程数,下载线程数不能小于1
|
||||||
|
* 注意:
|
||||||
|
* 1、线程下载数改变后,新的下载任务才会生效;
|
||||||
|
* 2、如果任务大小小于1m,该设置不会生效;
|
||||||
|
* 3、从3.4.1开始,如果线程数为1,文件初始化时将不再预占用对应长度的空间,下载多少byte,则占多大的空间;
|
||||||
|
* 对于采用多线程的任务或旧任务,依然采用原来的文件空间占用方式;
|
||||||
*/
|
*/
|
||||||
int threadNum = 3;
|
int threadNum = 3;
|
||||||
|
|
||||||
@@ -374,26 +379,6 @@ class Configuration {
|
|||||||
*/
|
*/
|
||||||
int maxSpeed = 0;
|
int maxSpeed = 0;
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否开启动态文件,开启动态文件后初始化时将不占用磁盘空间,下载多少byte,占多少空间,效果见chrome的下载
|
|
||||||
* 注意:
|
|
||||||
* 1、使用该功能,将自动关闭多线程下载;
|
|
||||||
* 2、对于已经采用了多线程的任务,依然采用原来的下载方式;
|
|
||||||
* 3、原本参数是true,任务没下载完成,就参数改为false,那么没下载完成的任务还是会按照参数修改前的方式下载,只有新任务才会根据参数调用不同的下载方式
|
|
||||||
* {@code true}使用
|
|
||||||
*/
|
|
||||||
boolean openDynamicFile = true;
|
|
||||||
|
|
||||||
public DownloadConfig setOpenDynamicFile(boolean openDynamicFile) {
|
|
||||||
this.openDynamicFile = openDynamicFile;
|
|
||||||
saveKey("openDynamicFile", String.valueOf(openDynamicFile));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOpenDynamicFile() {
|
|
||||||
return openDynamicFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DownloadConfig setMaxTaskNum(int maxTaskNum) {
|
public DownloadConfig setMaxTaskNum(int maxTaskNum) {
|
||||||
oldMaxTaskNum = this.maxTaskNum;
|
oldMaxTaskNum = this.maxTaskNum;
|
||||||
this.maxTaskNum = maxTaskNum;
|
this.maxTaskNum = maxTaskNum;
|
||||||
|
|||||||
Reference in New Issue
Block a user