ftp下载获取dns的ip列表时添加超时限制,修复端口不存在导致的崩溃问题,https://github.com/AriaLyy/Aria/issues/251
ä修复https://github.com/AriaLyy/Aria/issues/233
This commit is contained in:
@@ -26,8 +26,8 @@ dependencies {
|
|||||||
testCompile 'junit:junit:4.12'
|
testCompile 'junit:junit:4.12'
|
||||||
compile 'com.android.support:appcompat-v7:23.1.1'
|
compile 'com.android.support:appcompat-v7:23.1.1'
|
||||||
compile project(':AriaAnnotations')
|
compile project(':AriaAnnotations')
|
||||||
compile 'com.arialyy.aria:aria-ftp-plug:1.0.3'
|
// compile 'com.arialyy.aria:aria-ftp-plug:1.0.3'
|
||||||
|
|
||||||
// compile project(':AriaFtpPlug')
|
compile project(':AriaFtpPlug')
|
||||||
}
|
}
|
||||||
apply from: 'bintray-release.gradle'
|
apply from: 'bintray-release.gradle'
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import com.arialyy.aria.core.inf.AbsGroupTaskEntity;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by AriaL on 2017/6/29.
|
* Created by AriaL on 2017/6/29.
|
||||||
* 删除任务组
|
* 删除任务组子任务
|
||||||
*/
|
*/
|
||||||
class GroupCancelCmd<T extends AbsGroupTaskEntity> extends AbsGroupCmd<T> {
|
class GroupCancelCmd<T extends AbsGroupTaskEntity> extends AbsGroupCmd<T> {
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -86,8 +86,11 @@ class StartCmd<T extends AbsTaskEntity> extends AbsNormalCmd<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!task.isRunning()) {
|
//任务没执行并且执行队列中没有该任务,才认为任务没有运行中
|
||||||
|
if (!task.isRunning() && !mQueue.taskIsRunning(task.getKey())) {
|
||||||
resumeTask();
|
resumeTask();
|
||||||
|
}else {
|
||||||
|
ALog.w(TAG, String.format("任务【%s】已经在运行", task.getTaskName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mQueue.getCurrentCachePoolNum() == 0) {
|
if (mQueue.getCurrentCachePoolNum() == 0) {
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
package com.arialyy.aria.core.common;
|
package com.arialyy.aria.core.common;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
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.DownloadEntity;
|
||||||
import com.arialyy.aria.core.inf.AbsNormalEntity;
|
import com.arialyy.aria.core.inf.AbsNormalEntity;
|
||||||
@@ -29,8 +28,10 @@ import com.arialyy.aria.util.CommonUtil;
|
|||||||
import com.arialyy.aria.util.DbHelper;
|
import com.arialyy.aria.util.DbHelper;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
@@ -65,8 +66,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
private int mStartThreadNum;
|
private int mStartThreadNum;
|
||||||
//已完成的线程数
|
//已完成的线程数
|
||||||
private int mCompleteThreadNum;
|
private int mCompleteThreadNum;
|
||||||
private SparseArray<AbsThreadTask> mTask = new SparseArray<>();
|
private Map<Integer, AbsThreadTask> mTask = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
private Timer mTimer;
|
private Timer mTimer;
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@@ -188,7 +188,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前下载位置
|
* 获取当前任务位置
|
||||||
*/
|
*/
|
||||||
@Override public long getCurrentLocation() {
|
@Override public long getCurrentLocation() {
|
||||||
return mConstance.CURRENT_LOCATION;
|
return mConstance.CURRENT_LOCATION;
|
||||||
@@ -244,7 +244,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
* 检查任务、检查线程数
|
* 检查任务、检查线程数
|
||||||
* 新任务条件:
|
* 新任务条件:
|
||||||
* 1、文件不存在
|
* 1、文件不存在
|
||||||
* 2、下载记录文件缺失或不匹配
|
* 2、任务记录文件缺失或不匹配
|
||||||
* 3、数据库记录不存在
|
* 3、数据库记录不存在
|
||||||
* 4、不支持断点,则是新任务
|
* 4、不支持断点,则是新任务
|
||||||
*/
|
*/
|
||||||
@@ -318,14 +318,14 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
tRecord.key = mRecord.filePath;
|
tRecord.key = mRecord.filePath;
|
||||||
Object state = pro.getProperty(mTempFile.getName() + STATE + i);
|
Object state = pro.getProperty(mTempFile.getName() + STATE + i);
|
||||||
Object record = pro.getProperty(mTempFile.getName() + RECORD + i);
|
Object record = pro.getProperty(mTempFile.getName() + RECORD + i);
|
||||||
if (state != null && Integer.parseInt(state + "") == 1) {
|
if (state != null && Integer.parseInt(String.valueOf(state)) == 1) {
|
||||||
mCompleteThreadNum++;
|
mCompleteThreadNum++;
|
||||||
tRecord.isComplete = true;
|
tRecord.isComplete = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
mStartThreadNum++;
|
mStartThreadNum++;
|
||||||
if (record != null) {
|
if (record != null) {
|
||||||
Long temp = Long.parseLong(record + "");
|
Long temp = Long.parseLong(String.valueOf(record));
|
||||||
tRecord.startLocation = temp > 0 ? temp : 0;
|
tRecord.startLocation = temp > 0 ? temp : 0;
|
||||||
} else {
|
} else {
|
||||||
tRecord.startLocation = 0;
|
tRecord.startLocation = 0;
|
||||||
@@ -373,7 +373,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
*/
|
*/
|
||||||
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 + "__已完成");
|
ALog.d(TAG, String.format("任务【%s】线程__%s__已完成", mTaskEntity.getEntity().getFileName(), i));
|
||||||
mConstance.COMPLETE_THREAD_NUM = mCompleteThreadNum;
|
mConstance.COMPLETE_THREAD_NUM = mCompleteThreadNum;
|
||||||
mConstance.STOP_NUM++;
|
mConstance.STOP_NUM++;
|
||||||
mConstance.CANCEL_NUM++;
|
mConstance.CANCEL_NUM++;
|
||||||
@@ -439,7 +439,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//如果有记录,则恢复下载
|
//如果有记录,则恢复任务
|
||||||
if (tr.startLocation >= 0) {
|
if (tr.startLocation >= 0) {
|
||||||
Long r = tr.startLocation;
|
Long r = tr.startLocation;
|
||||||
//记录的位置需要在线程区间中
|
//记录的位置需要在线程区间中
|
||||||
@@ -447,7 +447,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
mConstance.CURRENT_LOCATION += r - startL;
|
mConstance.CURRENT_LOCATION += r - startL;
|
||||||
startL = r;
|
startL = r;
|
||||||
}
|
}
|
||||||
ALog.d(TAG, "任务【" + mEntity.getFileName() + "】线程__" + i + "__恢复下载");
|
ALog.d(TAG, String.format("任务【%s】线程__%s__恢复任务", mEntity.getFileName(), i));
|
||||||
}
|
}
|
||||||
//最后一个线程的结束位置即为文件的总长度
|
//最后一个线程的结束位置即为文件的总长度
|
||||||
if (i == (mTotalThreadNum - 1)) {
|
if (i == (mTotalThreadNum - 1)) {
|
||||||
@@ -470,7 +470,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 启动单线程下载任务
|
* 启动单线程任务
|
||||||
*/
|
*/
|
||||||
private void startThreadTask(int[] recordL) {
|
private void startThreadTask(int[] recordL) {
|
||||||
if (mConstance.CURRENT_LOCATION > 0) {
|
if (mConstance.CURRENT_LOCATION > 0) {
|
||||||
@@ -488,6 +488,26 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重试线程任务,只有线程创建成功才能重试
|
||||||
|
*/
|
||||||
|
public void retryThradTask() {
|
||||||
|
if (mTask == null || mTask.size() == 0) {
|
||||||
|
ALog.w(TAG, "没有线程任务");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Set<Integer> keys = mTask.keySet();
|
||||||
|
for (Integer key : keys) {
|
||||||
|
AbsThreadTask task = mTask.get(key);
|
||||||
|
if (task != null && !task.isThreadComplete()) {
|
||||||
|
task.getConfig().START_LOCATION = task.getCurrentLocation();
|
||||||
|
ALog.d(TAG, String.format("任务【%s】开始重试,线程__%s__【开始位置:%s,结束位置:%s】", mEntity.getFileName(),
|
||||||
|
key, task.getConfig().START_LOCATION, task.getConfig().END_LOCATION));
|
||||||
|
mFixedThreadPool.execute(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理新任务
|
* 处理新任务
|
||||||
*
|
*
|
||||||
@@ -496,7 +516,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
|
|||||||
protected abstract boolean handleNewTask();
|
protected abstract boolean handleNewTask();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理不支持断点的下载
|
* 处理不支持断点的任务
|
||||||
*/
|
*/
|
||||||
private void handleNoSupportBP() {
|
private void handleNoSupportBP() {
|
||||||
SubThreadConfig<TASK_ENTITY> config = new SubThreadConfig<>();
|
SubThreadConfig<TASK_ENTITY> config = new SubThreadConfig<>();
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import com.arialyy.aria.util.Regular;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import org.apache.commons.net.ftp.FTP;
|
import org.apache.commons.net.ftp.FTP;
|
||||||
@@ -72,7 +73,7 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_ENTITY ext
|
|||||||
try {
|
try {
|
||||||
client = createFtpClient();
|
client = createFtpClient();
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
failDownload("创建FTP客户端失败", true);
|
ALog.e(TAG, String.format("任务【%s】失败", mTaskEntity.getUrlEntity().url));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String remotePath =
|
String remotePath =
|
||||||
@@ -82,8 +83,8 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_ENTITY ext
|
|||||||
ALog.i(TAG, s);
|
ALog.i(TAG, s);
|
||||||
boolean isExist = files.length != 0;
|
boolean isExist = files.length != 0;
|
||||||
if (!isExist && !isUpload) {
|
if (!isExist && !isUpload) {
|
||||||
failDownload("文件不存在,任务链接【" + mTaskEntity.getUrlEntity().url + "】,remotePath:" + remotePath,
|
failDownload(String.format("文件不存在,任务链接【%s】,remotePath:%s", mTaskEntity.getUrlEntity().url,
|
||||||
false);
|
remotePath), false);
|
||||||
int i = remotePath.lastIndexOf(File.separator);
|
int i = remotePath.lastIndexOf(File.separator);
|
||||||
FTPFile[] files1;
|
FTPFile[] files1;
|
||||||
if (i == -1) {
|
if (i == -1) {
|
||||||
@@ -92,7 +93,8 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_ENTITY ext
|
|||||||
files1 = client.listFiles(remotePath.substring(0, i + 1));
|
files1 = client.listFiles(remotePath.substring(0, i + 1));
|
||||||
}
|
}
|
||||||
if (files1.length > 0) {
|
if (files1.length > 0) {
|
||||||
ALog.i(TAG, "路径【" + setRemotePath() + "】下的文件列表 ===================================");
|
ALog.i(TAG,
|
||||||
|
String.format("路径【%s】下的文件列表 ===================================", setRemotePath()));
|
||||||
for (FTPFile file : files1) {
|
for (FTPFile file : files1) {
|
||||||
ALog.d(TAG, file.toString());
|
ALog.d(TAG, file.toString());
|
||||||
}
|
}
|
||||||
@@ -114,7 +116,8 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_ENTITY ext
|
|||||||
mTaskEntity.setNewTask(true);
|
mTaskEntity.setNewTask(true);
|
||||||
} else {
|
} else {
|
||||||
client.disconnect();
|
client.disconnect();
|
||||||
failDownload("获取文件信息错误,错误码为:" + reply + ",msg:" + client.getReplyString(), true);
|
failDownload(String.format("获取文件信息错误,错误码为:%s,msg:%s", reply, client.getReplyString()),
|
||||||
|
true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,11 +174,14 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_ENTITY ext
|
|||||||
if (m.find() && m.groupCount() > 0) {
|
if (m.find() && m.groupCount() > 0) {
|
||||||
client = new FTPClient();
|
client = new FTPClient();
|
||||||
InetAddress ip = InetAddress.getByName(urlEntity.hostName);
|
InetAddress ip = InetAddress.getByName(urlEntity.hostName);
|
||||||
client.setConnectTimeout(10000); // 连接10s超时
|
client.setConnectTimeout(mConnectTimeOut); // 连接10s超时
|
||||||
client.connect(ip, Integer.parseInt(urlEntity.port));
|
client.connect(ip, Integer.parseInt(urlEntity.port));
|
||||||
mTaskEntity.getUrlEntity().validAddr = ip;
|
mTaskEntity.getUrlEntity().validAddr = ip;
|
||||||
} else {
|
} else {
|
||||||
InetAddress[] ips = InetAddress.getAllByName(urlEntity.hostName);
|
DNSQueryThread dnsThread = new DNSQueryThread(urlEntity.hostName);
|
||||||
|
dnsThread.start();
|
||||||
|
dnsThread.join(mConnectTimeOut);
|
||||||
|
InetAddress[] ips = dnsThread.getIps();
|
||||||
client = connect(new FTPClient(), ips, 0, Integer.parseInt(urlEntity.port));
|
client = connect(new FTPClient(), ips, 0, Integer.parseInt(urlEntity.port));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +212,8 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_ENTITY ext
|
|||||||
int reply = client.getReplyCode();
|
int reply = client.getReplyCode();
|
||||||
if (!FTPReply.isPositiveCompletion(reply)) {
|
if (!FTPReply.isPositiveCompletion(reply)) {
|
||||||
client.disconnect();
|
client.disconnect();
|
||||||
failDownload("无法连接到ftp服务器,错误码为:" + reply + ",msg:" + client.getReplyString(), true);
|
failDownload(String.format("无法连接到ftp服务器,错误码为:%s,msg:%s", reply, client.getReplyString()),
|
||||||
|
true);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码
|
// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码
|
||||||
@@ -221,9 +228,10 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_ENTITY ext
|
|||||||
client.setDataTimeout(10 * 1000);
|
client.setDataTimeout(10 * 1000);
|
||||||
client.enterLocalPassiveMode();
|
client.enterLocalPassiveMode();
|
||||||
client.setFileType(FTP.BINARY_FILE_TYPE);
|
client.setFileType(FTP.BINARY_FILE_TYPE);
|
||||||
client.setConnectTimeout(mConnectTimeOut);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
@@ -232,7 +240,12 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_ENTITY ext
|
|||||||
* 连接到ftp服务器
|
* 连接到ftp服务器
|
||||||
*/
|
*/
|
||||||
private FTPClient connect(FTPClient client, InetAddress[] ips, int index, int port) {
|
private FTPClient connect(FTPClient client, InetAddress[] ips, int index, int port) {
|
||||||
|
if (ips == null || ips.length == 0) {
|
||||||
|
ALog.w(TAG, "无可用ip");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
|
client.setConnectTimeout(mConnectTimeOut); //需要先设置超时,这样才不会出现阻塞
|
||||||
client.connect(ips[index], port);
|
client.connect(ips[index], port);
|
||||||
mTaskEntity.getUrlEntity().validAddr = ips[index];
|
mTaskEntity.getUrlEntity().validAddr = ips[index];
|
||||||
return client;
|
return client;
|
||||||
@@ -295,4 +308,29 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_ENTITY ext
|
|||||||
mCallback.onFail(mEntity.getKey(), errorMsg, needRetry);
|
mCallback.onFail(mEntity.getKey(), errorMsg, needRetry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取可用IP的超时线程,InetAddress.getByName没有超时功能,需要自己处理超时
|
||||||
|
*/
|
||||||
|
private static class DNSQueryThread extends Thread {
|
||||||
|
|
||||||
|
private String hostName;
|
||||||
|
private InetAddress[] ips;
|
||||||
|
|
||||||
|
DNSQueryThread(String hostName) {
|
||||||
|
this.hostName = hostName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void run() {
|
||||||
|
try {
|
||||||
|
ips = InetAddress.getAllByName(hostName);
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized InetAddress[] getIps() {
|
||||||
|
return ips;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ public abstract class AbsFtpThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTI
|
|||||||
if (!FTPReply.isPositiveCompletion(reply)) {
|
if (!FTPReply.isPositiveCompletion(reply)) {
|
||||||
client.disconnect();
|
client.disconnect();
|
||||||
fail(mChildCurrentLocation,
|
fail(mChildCurrentLocation,
|
||||||
"无法连接到ftp服务器,错误码为:" + reply + ",msg:" + client.getReplyString(), null);
|
String.format("无法连接到ftp服务器,错误码为:%s,msg:%s", reply, client.getReplyString()), null);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码
|
// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码
|
||||||
|
|||||||
@@ -52,15 +52,14 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTITY
|
|||||||
protected SubThreadConfig<TASK_ENTITY> mConfig;
|
protected SubThreadConfig<TASK_ENTITY> mConfig;
|
||||||
protected ENTITY mEntity;
|
protected ENTITY mEntity;
|
||||||
protected TASK_ENTITY mTaskEntity;
|
protected TASK_ENTITY mTaskEntity;
|
||||||
private int mFailNum = 0;
|
private int mFailTimes = 0;
|
||||||
private String mTaskType;
|
|
||||||
private Timer mFailTimer;
|
private Timer mFailTimer;
|
||||||
private long mLastSaveTime;
|
private long mLastSaveTime;
|
||||||
private ExecutorService mConfigThreadPool;
|
private ExecutorService mConfigThreadPool;
|
||||||
protected int mConnectTimeOut; //连接超时时间
|
protected int mConnectTimeOut; //连接超时时间
|
||||||
protected int mReadTimeOut; //流读取的超时时间
|
protected int mReadTimeOut; //流读取的超时时间
|
||||||
protected boolean isNotNetRetry = false; //断网情况是否重试
|
protected boolean isNotNetRetry = false; //断网情况是否重试
|
||||||
protected boolean taskBreak = false; //任务中断
|
private boolean taskBreak = false; //任务中断
|
||||||
|
|
||||||
private Thread mConfigThread = new Thread(new Runnable() {
|
private Thread mConfigThread = new Thread(new Runnable() {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
@@ -76,13 +75,10 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTITY
|
|||||||
mConfig = info;
|
mConfig = info;
|
||||||
mTaskEntity = mConfig.TASK_ENTITY;
|
mTaskEntity = mConfig.TASK_ENTITY;
|
||||||
mEntity = mTaskEntity.getEntity();
|
mEntity = mTaskEntity.getEntity();
|
||||||
mTaskType = getTaskType();
|
|
||||||
mLastSaveTime = System.currentTimeMillis();
|
mLastSaveTime = System.currentTimeMillis();
|
||||||
mConfigThreadPool = Executors.newCachedThreadPool();
|
mConfigThreadPool = Executors.newCachedThreadPool();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract String getTaskType();
|
|
||||||
|
|
||||||
public void setMaxSpeed(double maxSpeed) {
|
public void setMaxSpeed(double maxSpeed) {
|
||||||
if (-0.9999 < maxSpeed && maxSpeed < 0.00001) {
|
if (-0.9999 < maxSpeed && maxSpeed < 0.00001) {
|
||||||
mSleepTime = 0;
|
mSleepTime = 0;
|
||||||
@@ -93,6 +89,28 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTITY
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前线程是否完成,对于不支持断点的任务,一律未完成
|
||||||
|
* {@code true} 完成;{@code false} 未完成
|
||||||
|
*/
|
||||||
|
public boolean isThreadComplete() {
|
||||||
|
return mConfig.THREAD_RECORD.isComplete;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取线程配置信息
|
||||||
|
*/
|
||||||
|
public SubThreadConfig getConfig() {
|
||||||
|
return mConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前线程下载进度
|
||||||
|
*/
|
||||||
|
public long getCurrentLocation() {
|
||||||
|
return mChildCurrentLocation;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean filterVersion() {
|
private boolean filterVersion() {
|
||||||
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
|
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
|
||||||
}
|
}
|
||||||
@@ -124,21 +142,16 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTITY
|
|||||||
if (mConfig.SUPPORT_BP) {
|
if (mConfig.SUPPORT_BP) {
|
||||||
final long currentTemp = mChildCurrentLocation;
|
final long currentTemp = mChildCurrentLocation;
|
||||||
STATE.STOP_NUM++;
|
STATE.STOP_NUM++;
|
||||||
ALog.d(TAG, "任务【"
|
ALog.d(TAG, String.format("任务【%s】thread__%s__停止【停止位置:%s】", mConfig.TEMP_FILE.getName(),
|
||||||
+ mConfig.TEMP_FILE.getName()
|
mConfig.THREAD_ID, currentTemp));
|
||||||
+ "】thread__"
|
|
||||||
+ mConfig.THREAD_ID
|
|
||||||
+ "__停止【停止位置: "
|
|
||||||
+ currentTemp
|
|
||||||
+ "】");
|
|
||||||
writeConfig(false, currentTemp);
|
writeConfig(false, currentTemp);
|
||||||
if (STATE.isStop()) {
|
if (STATE.isStop()) {
|
||||||
ALog.i(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】已停止");
|
ALog.i(TAG, String.format("任务【%s】已停止", mConfig.TEMP_FILE.getName()));
|
||||||
STATE.isRunning = false;
|
STATE.isRunning = false;
|
||||||
mListener.onStop(STATE.CURRENT_LOCATION);
|
mListener.onStop(STATE.CURRENT_LOCATION);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ALog.i(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】已停止");
|
ALog.i(TAG, String.format("任务【%s】已停止", mConfig.TEMP_FILE.getName()));
|
||||||
STATE.isRunning = false;
|
STATE.isRunning = false;
|
||||||
mListener.onStop(STATE.CURRENT_LOCATION);
|
mListener.onStop(STATE.CURRENT_LOCATION);
|
||||||
}
|
}
|
||||||
@@ -174,17 +187,18 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTITY
|
|||||||
synchronized (AriaManager.LOCK) {
|
synchronized (AriaManager.LOCK) {
|
||||||
if (mConfig.SUPPORT_BP) {
|
if (mConfig.SUPPORT_BP) {
|
||||||
STATE.CANCEL_NUM++;
|
STATE.CANCEL_NUM++;
|
||||||
ALog.d(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】thread__" + mConfig.THREAD_ID + "__取消");
|
ALog.d(TAG,
|
||||||
|
String.format("任务【%s】thread__%s__取消", mConfig.TEMP_FILE.getName(), mConfig.THREAD_ID));
|
||||||
if (STATE.isCancel()) {
|
if (STATE.isCancel()) {
|
||||||
if (mConfig.TEMP_FILE.exists() && !(mEntity instanceof UploadEntity)) {
|
if (mConfig.TEMP_FILE.exists() && !(mEntity instanceof UploadEntity)) {
|
||||||
mConfig.TEMP_FILE.delete();
|
mConfig.TEMP_FILE.delete();
|
||||||
}
|
}
|
||||||
ALog.d(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】已取消");
|
ALog.d(TAG, String.format("任务【%s】已取消", mConfig.TEMP_FILE.getName()));
|
||||||
STATE.isRunning = false;
|
STATE.isRunning = false;
|
||||||
mListener.onCancel();
|
mListener.onCancel();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ALog.d(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】已取消");
|
ALog.d(TAG, String.format("任务【%s】已取消", mConfig.TEMP_FILE.getName()));
|
||||||
STATE.isRunning = false;
|
STATE.isRunning = false;
|
||||||
mListener.onCancel();
|
mListener.onCancel();
|
||||||
}
|
}
|
||||||
@@ -216,9 +230,9 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTITY
|
|||||||
}
|
}
|
||||||
if (mConfig.SUPPORT_BP) {
|
if (mConfig.SUPPORT_BP) {
|
||||||
writeConfig(false, subCurrentLocation);
|
writeConfig(false, subCurrentLocation);
|
||||||
retryThis(STATE.START_THREAD_NUM != 1);
|
retryThis(needRetry && STATE.START_THREAD_NUM != 1);
|
||||||
} else {
|
} else {
|
||||||
ALog.e(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】执行失败");
|
ALog.e(TAG, String.format("任务【%s】执行失败", mConfig.TEMP_FILE.getName()));
|
||||||
mListener.onFail(true);
|
mListener.onFail(true);
|
||||||
ErrorHelp.saveError(TAG, "", ALog.getExceptionString(ex));
|
ErrorHelp.saveError(TAG, "", ALog.getExceptionString(ex));
|
||||||
}
|
}
|
||||||
@@ -236,23 +250,21 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTITY
|
|||||||
mFailTimer.cancel();
|
mFailTimer.cancel();
|
||||||
}
|
}
|
||||||
if (!NetUtils.isConnected(AriaManager.APP) && !isNotNetRetry) {
|
if (!NetUtils.isConnected(AriaManager.APP) && !isNotNetRetry) {
|
||||||
ALog.w(TAG,
|
ALog.w(TAG, String.format("任务【%s】thread__%s__重试失败,网络未连接", mConfig.TEMP_FILE.getName(),
|
||||||
"任务【" + mConfig.TEMP_FILE.getName() + "】thread__" + mConfig.THREAD_ID + "__重试失败,网络未连接");
|
mConfig.THREAD_ID));
|
||||||
}
|
}
|
||||||
if (mFailNum < RETRY_NUM
|
if (mFailTimes < RETRY_NUM
|
||||||
&& needRetry
|
&& needRetry
|
||||||
&& NetUtils.isConnected(AriaManager.APP)
|
&& (NetUtils.isConnected(AriaManager.APP) || isNotNetRetry)
|
||||||
&& !isNotNetRetry
|
&& isBreak()) {
|
||||||
&& !STATE.isCancel
|
|
||||||
&& !STATE.isStop) {
|
|
||||||
mFailTimer = new Timer(true);
|
mFailTimer = new Timer(true);
|
||||||
mFailTimer.schedule(new TimerTask() {
|
mFailTimer.schedule(new TimerTask() {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
mFailNum++;
|
mFailTimes++;
|
||||||
ALog.w(TAG,
|
ALog.w(TAG, String.format("任务【%s】thread__%s__正在重试", mConfig.TEMP_FILE.getName(),
|
||||||
"任务【" + mConfig.TEMP_FILE.getName() + "】thread__" + mConfig.THREAD_ID + "__正在重试");
|
mConfig.THREAD_ID));
|
||||||
mConfig.START_LOCATION =
|
final long temp = mChildCurrentLocation;
|
||||||
mChildCurrentLocation == 0 ? mConfig.START_LOCATION : mChildCurrentLocation;
|
mConfig.START_LOCATION = mChildCurrentLocation == 0 ? mConfig.START_LOCATION : temp;
|
||||||
AbsThreadTask.this.run();
|
AbsThreadTask.this.run();
|
||||||
}
|
}
|
||||||
}, RETRY_INTERVAL);
|
}, RETRY_INTERVAL);
|
||||||
@@ -261,7 +273,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTITY
|
|||||||
if (STATE.isFail()) {
|
if (STATE.isFail()) {
|
||||||
STATE.isRunning = false;
|
STATE.isRunning = false;
|
||||||
STATE.isStop = true;
|
STATE.isStop = true;
|
||||||
ALog.e(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】执行失败");
|
ALog.e(TAG, String.format("任务【%s】执行失败", mConfig.TEMP_FILE.getName()));
|
||||||
mListener.onFail(true);
|
mListener.onFail(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,6 +281,9 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_ENTITY
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 将记录写入到配置文件
|
* 将记录写入到配置文件
|
||||||
|
*
|
||||||
|
* @param isComplete 当前线程是否完成 {@code true}完成
|
||||||
|
* @param record 当前下载进度
|
||||||
*/
|
*/
|
||||||
protected void writeConfig(boolean isComplete, final long record) {
|
protected void writeConfig(boolean isComplete, final long record) {
|
||||||
if (mConfig.THREAD_RECORD != null) {
|
if (mConfig.THREAD_RECORD != null) {
|
||||||
|
|||||||
@@ -136,8 +136,12 @@ abstract class BaseNormalTarget<TARGET extends BaseNormalTarget>
|
|||||||
} else if (getTargetType() == FTP) {
|
} else if (getTargetType() == FTP) {
|
||||||
filePath += mEntity.getFileName();
|
filePath += mEntity.getFileName();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// http文件名设置
|
||||||
|
if (TextUtils.isEmpty(mEntity.getFileName())) {
|
||||||
|
mEntity.setFileName(file.getName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mEntity.setFileName(file.getName());
|
|
||||||
|
|
||||||
//设置文件保存路径,如果新文件路径和就文件路径不同,则修改路径
|
//设置文件保存路径,如果新文件路径和就文件路径不同,则修改路径
|
||||||
if (!filePath.equals(mEntity.getDownloadPath())) {
|
if (!filePath.equals(mEntity.getDownloadPath())) {
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ class DownloadGroupListener
|
|||||||
for (DownloadEntity e : mEntity.getSubEntities()) {
|
for (DownloadEntity e : mEntity.getSubEntities()) {
|
||||||
location += e.getCurrentProgress();
|
location += e.getCurrentProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
mEntity.setCurrentProgress(location);
|
mEntity.setCurrentProgress(location);
|
||||||
mEntity.update();
|
mEntity.update();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,9 +143,13 @@ public class DownloadGroupTarget extends BaseGroupTarget<DownloadGroupTarget> {
|
|||||||
reChangeDirPath(mDirPathTemp);
|
reChangeDirPath(mDirPathTemp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mSubNameTemp.isEmpty()) {
|
if (mSubNameTemp.isEmpty()) {
|
||||||
updateSingleSubFileName();
|
for (String url : mUrls) {
|
||||||
|
int lastIndex = url.lastIndexOf(File.separator);
|
||||||
|
mSubNameTemp.add(url.substring(lastIndex + 1, url.length()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
updateSingleSubFileName();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import java.util.concurrent.Executors;
|
|||||||
* 任务组核心逻辑
|
* 任务组核心逻辑
|
||||||
*/
|
*/
|
||||||
public abstract class AbsGroupUtil implements IUtil {
|
public abstract class AbsGroupUtil implements IUtil {
|
||||||
|
private static final Object LOCK = new Object();
|
||||||
private final String TAG = "AbsGroupUtil";
|
private final String TAG = "AbsGroupUtil";
|
||||||
/**
|
/**
|
||||||
* FTP文件夹
|
* FTP文件夹
|
||||||
@@ -158,6 +159,9 @@ public abstract class AbsGroupUtil implements IUtil {
|
|||||||
DownloadTaskEntity det = mTasksMap.get(url);
|
DownloadTaskEntity det = mTasksMap.get(url);
|
||||||
if (det != null) {
|
if (det != null) {
|
||||||
mTotalLen -= det.getEntity().getFileSize();
|
mTotalLen -= det.getEntity().getFileSize();
|
||||||
|
mCurrentLocation -= det.getEntity().getCurrentProgress();
|
||||||
|
mExeMap.remove(det.getKey());
|
||||||
|
mFailMap.remove(det.getKey());
|
||||||
mGroupSize--;
|
mGroupSize--;
|
||||||
if (mGroupSize == 0) {
|
if (mGroupSize == 0) {
|
||||||
closeTimer(false);
|
closeTimer(false);
|
||||||
@@ -305,12 +309,12 @@ public abstract class AbsGroupUtil implements IUtil {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearState(){
|
private void clearState() {
|
||||||
mDownloaderMap.clear();
|
mDownloaderMap.clear();
|
||||||
mFailMap.clear();
|
mFailMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void closeTimer(boolean isRunning) {
|
void closeTimer(boolean isRunning) {
|
||||||
this.isRunning = isRunning;
|
this.isRunning = isRunning;
|
||||||
if (mTimer != null) {
|
if (mTimer != null) {
|
||||||
mTimer.purge();
|
mTimer.purge();
|
||||||
@@ -374,6 +378,8 @@ public abstract class AbsGroupUtil implements IUtil {
|
|||||||
private int RUN_SAVE_INTERVAL = 5 * 1000; //5s保存一次下载中的进度
|
private int RUN_SAVE_INTERVAL = 5 * 1000; //5s保存一次下载中的进度
|
||||||
private long lastSaveTime;
|
private long lastSaveTime;
|
||||||
private long lastLen = 0;
|
private long lastLen = 0;
|
||||||
|
private Timer timer;
|
||||||
|
private boolean isNotNetRetry = false;
|
||||||
|
|
||||||
ChildDownloadListener(DownloadTaskEntity entity) {
|
ChildDownloadListener(DownloadTaskEntity entity) {
|
||||||
subTaskEntity = entity;
|
subTaskEntity = entity;
|
||||||
@@ -381,6 +387,7 @@ public abstract class AbsGroupUtil implements IUtil {
|
|||||||
subEntity.setFailNum(0);
|
subEntity.setFailNum(0);
|
||||||
lastLen = subEntity.getCurrentProgress();
|
lastLen = subEntity.getCurrentProgress();
|
||||||
lastSaveTime = System.currentTimeMillis();
|
lastSaveTime = System.currentTimeMillis();
|
||||||
|
isNotNetRetry = AriaManager.getInstance(AriaManager.APP).getDownloadConfig().isNotNetRetry();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onPre() {
|
@Override public void onPre() {
|
||||||
@@ -423,7 +430,7 @@ public abstract class AbsGroupUtil implements IUtil {
|
|||||||
saveData(IEntity.STATE_STOP, stopLocation);
|
saveData(IEntity.STATE_STOP, stopLocation);
|
||||||
handleSpeed(0);
|
handleSpeed(0);
|
||||||
mListener.onSubStop(subEntity);
|
mListener.onSubStop(subEntity);
|
||||||
synchronized (AbsGroupUtil.class) {
|
synchronized (AbsGroupUtil.LOCK) {
|
||||||
mStopNum++;
|
mStopNum++;
|
||||||
if (mStopNum + mCompleteNum + mFailMap.size() == mGroupSize) {
|
if (mStopNum + mCompleteNum + mFailMap.size() == mGroupSize) {
|
||||||
closeTimer(false);
|
closeTimer(false);
|
||||||
@@ -439,16 +446,17 @@ public abstract class AbsGroupUtil implements IUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onComplete() {
|
@Override public void onComplete() {
|
||||||
|
subEntity.setComplete(true);
|
||||||
saveData(IEntity.STATE_COMPLETE, subEntity.getFileSize());
|
saveData(IEntity.STATE_COMPLETE, subEntity.getFileSize());
|
||||||
handleSpeed(0);
|
handleSpeed(0);
|
||||||
mListener.onSubComplete(subEntity);
|
mListener.onSubComplete(subEntity);
|
||||||
synchronized (ChildDownloadListener.class) {
|
synchronized (AbsGroupUtil.LOCK) {
|
||||||
mCompleteNum++;
|
mCompleteNum++;
|
||||||
//如果子任务完成的数量和总任务数一致,表示任务组任务已经完成
|
//如果子任务完成的数量和总任务数一致,表示任务组任务已经完成
|
||||||
if (mCompleteNum >= mGroupSize) {
|
if (mCompleteNum == mGroupSize) {
|
||||||
closeTimer(false);
|
closeTimer(false);
|
||||||
mListener.onComplete();
|
mListener.onComplete();
|
||||||
} else if (mFailMap.size() > 0 && mStopNum + mCompleteNum + mFailMap.size() >= mGroupSize) {
|
} else if (mFailMap.size() > 0 && mStopNum + mCompleteNum + mFailMap.size() == mGroupSize) {
|
||||||
//如果子任务完成数量加上失败的数量和总任务数一致,则任务组停止下载
|
//如果子任务完成数量加上失败的数量和总任务数一致,则任务组停止下载
|
||||||
closeTimer(false);
|
closeTimer(false);
|
||||||
mListener.onStop(mCurrentLocation);
|
mListener.onStop(mCurrentLocation);
|
||||||
@@ -464,41 +472,48 @@ public abstract class AbsGroupUtil implements IUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重试下载
|
* 重试下载,只有全部都下载失败才会执行任务组的整体重试,否则只会执行单个子任务的重试
|
||||||
*/
|
*/
|
||||||
private void reTry(boolean needRetry) {
|
private void reTry(boolean needRetry) {
|
||||||
synchronized (ChildDownloadListener.class) {
|
synchronized (AbsGroupUtil.LOCK) {
|
||||||
if (subEntity.getFailNum() < 5 && needRetry && NetUtils.isConnected(AriaManager.APP)) {
|
if (subEntity.getFailNum() < 5
|
||||||
|
&& needRetry && (NetUtils.isConnected(AriaManager.APP) || isNotNetRetry)) {
|
||||||
reStartTask();
|
reStartTask();
|
||||||
} else {
|
} else {
|
||||||
mFailMap.put(subTaskEntity.getUrl(), subTaskEntity);
|
mFailMap.put(subTaskEntity.getUrl(), subTaskEntity);
|
||||||
mListener.onSubFail(subEntity);
|
mListener.onSubFail(subEntity);
|
||||||
//如果失败的任务数大于实际的下载任务数,任务组停止下载
|
if (mFailMap.size() == mExeMap.size() || mFailMap.size() + mCompleteNum == mGroupSize) {
|
||||||
if (mFailMap.size() >= mExeMap.size()) {
|
|
||||||
closeTimer(false);
|
closeTimer(false);
|
||||||
if (mFailMap.size() == mGroupSize) { //所有任务都失败了,则认为该任务组已经失败
|
}
|
||||||
mListener.onFail(true);
|
if (mFailMap.size() == mGroupSize) {
|
||||||
} else {
|
mListener.onFail(true);
|
||||||
mListener.onStop(mCurrentLocation);
|
} else if (mFailMap.size() + mCompleteNum >= mExeMap.size()) {
|
||||||
}
|
mListener.onStop(mCurrentLocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reStartTask() {
|
private void reStartTask() {
|
||||||
Timer timer = new Timer();
|
if (timer != null) {
|
||||||
|
timer.purge();
|
||||||
|
timer.cancel();
|
||||||
|
}
|
||||||
|
timer = new Timer();
|
||||||
timer.schedule(new TimerTask() {
|
timer.schedule(new TimerTask() {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
Downloader dt = mDownloaderMap.get(subEntity.getUrl());
|
Downloader dt = mDownloaderMap.get(subEntity.getUrl());
|
||||||
dt.start();
|
if (dt != null) {
|
||||||
|
dt.retryThradTask();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, 3000);
|
}, 3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSpeed(long speed) {
|
private void handleSpeed(long speed) {
|
||||||
subEntity.setSpeed(speed);
|
subEntity.setSpeed(speed);
|
||||||
subEntity.setConvertSpeed(speed <= 0 ? "" : CommonUtil.formatFileSize(speed) + "/s");
|
subEntity.setConvertSpeed(
|
||||||
|
speed <= 0 ? "" : String.format("%s/s", CommonUtil.formatFileSize(speed)));
|
||||||
subEntity.setPercent((int) (subEntity.getFileSize() <= 0 ? 0
|
subEntity.setPercent((int) (subEntity.getFileSize() <= 0 ? 0
|
||||||
: subEntity.getCurrentProgress() * 100 / subEntity.getFileSize()));
|
: subEntity.getCurrentProgress() * 100 / subEntity.getFileSize()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,14 @@ import java.util.concurrent.Executors;
|
|||||||
public class DownloadGroupUtil extends AbsGroupUtil implements IUtil {
|
public class DownloadGroupUtil extends AbsGroupUtil implements IUtil {
|
||||||
private final String TAG = "DownloadGroupUtil";
|
private final String TAG = "DownloadGroupUtil";
|
||||||
private ExecutorService mInfoPool;
|
private ExecutorService mInfoPool;
|
||||||
private int mInitCompleteNum, mInitFailNum;
|
/**
|
||||||
|
* 初始化完成的任务数
|
||||||
|
*/
|
||||||
|
private int mInitCompleteNum;
|
||||||
|
/**
|
||||||
|
* 初始化失败的任务数
|
||||||
|
*/
|
||||||
|
private int mInitFailNum;
|
||||||
private boolean isStop = false;
|
private boolean isStop = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -126,7 +133,7 @@ public class DownloadGroupUtil extends AbsGroupUtil implements IUtil {
|
|||||||
|
|
||||||
@Override public void onFail(String url, String errorMsg, boolean needRetry) {
|
@Override public void onFail(String url, String errorMsg, boolean needRetry) {
|
||||||
if (isStop) return;
|
if (isStop) return;
|
||||||
ALog.e(TAG, "任务【" + url + "】初始化失败。");
|
ALog.e(TAG, String.format("任务【%s】初始化失败", url));
|
||||||
DownloadTaskEntity te = mExeMap.get(url);
|
DownloadTaskEntity te = mExeMap.get(url);
|
||||||
if (te != null) {
|
if (te != null) {
|
||||||
mFailMap.put(url, te);
|
mFailMap.put(url, te);
|
||||||
@@ -154,7 +161,11 @@ public class DownloadGroupUtil extends AbsGroupUtil implements IUtil {
|
|||||||
*/
|
*/
|
||||||
private void checkStartFlow() {
|
private void checkStartFlow() {
|
||||||
synchronized (DownloadGroupUtil.class) {
|
synchronized (DownloadGroupUtil.class) {
|
||||||
if (mInitCompleteNum + mInitFailNum >= mGroupSize || !isNeedLoadFileSize) {
|
if (mInitFailNum == mGroupSize){
|
||||||
|
closeTimer(false);
|
||||||
|
mListener.onFail(true);
|
||||||
|
}
|
||||||
|
if (mInitCompleteNum + mInitFailNum == mGroupSize || !isNeedLoadFileSize) {
|
||||||
startRunningFlow();
|
startRunningFlow();
|
||||||
updateFileSize();
|
updateFileSize();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,15 +61,9 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity>
|
|||||||
InputStream is = null;
|
InputStream is = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ALog.d(TAG, "任务【"
|
ALog.d(TAG,
|
||||||
+ mConfig.TEMP_FILE.getName()
|
String.format("任务【%s】线程__%s__开始下载【开始位置 : %s,结束位置:%s】", mConfig.TEMP_FILE.getName(),
|
||||||
+ "】线程__"
|
mConfig.THREAD_ID, mConfig.START_LOCATION, mConfig.END_LOCATION));
|
||||||
+ mConfig.THREAD_ID
|
|
||||||
+ "__开始下载【开始位置 : "
|
|
||||||
+ mConfig.START_LOCATION
|
|
||||||
+ ",结束位置:"
|
|
||||||
+ mConfig.END_LOCATION
|
|
||||||
+ "】");
|
|
||||||
client = createClient();
|
client = createClient();
|
||||||
if (client == null) return;
|
if (client == null) return;
|
||||||
if (mConfig.START_LOCATION > 0) {
|
if (mConfig.START_LOCATION > 0) {
|
||||||
@@ -78,18 +72,20 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity>
|
|||||||
//发送第二次指令时,还需要再做一次判断
|
//发送第二次指令时,还需要再做一次判断
|
||||||
int reply = client.getReplyCode();
|
int reply = client.getReplyCode();
|
||||||
if (!FTPReply.isPositivePreliminary(reply) && reply != FTPReply.COMMAND_OK) {
|
if (!FTPReply.isPositivePreliminary(reply) && reply != FTPReply.COMMAND_OK) {
|
||||||
fail(mChildCurrentLocation, "获取文件信息错误,错误码为:" + reply + ",msg:" + client.getReplyString(),
|
fail(mChildCurrentLocation,
|
||||||
|
String.format("获取文件信息错误,错误码为:%s,msg:%s", reply, client.getReplyString()),
|
||||||
null);
|
null);
|
||||||
client.disconnect();
|
client.disconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String remotePath =
|
String remotePath =
|
||||||
new String(mTaskEntity.getUrlEntity().remotePath.getBytes(charSet), SERVER_CHARSET);
|
new String(mTaskEntity.getUrlEntity().remotePath.getBytes(charSet), SERVER_CHARSET);
|
||||||
ALog.i(TAG, "remotePath【" + remotePath + "】");
|
ALog.i(TAG, String.format("remotePath【%s】", remotePath));
|
||||||
is = client.retrieveFileStream(remotePath);
|
is = client.retrieveFileStream(remotePath);
|
||||||
reply = client.getReplyCode();
|
reply = client.getReplyCode();
|
||||||
if (!FTPReply.isPositivePreliminary(reply)) {
|
if (!FTPReply.isPositivePreliminary(reply)) {
|
||||||
fail(mChildCurrentLocation, "获取流失败,错误码为:" + reply + ",msg:" + client.getReplyString(),
|
fail(mChildCurrentLocation,
|
||||||
|
String.format("获取流失败,错误码为:%s,msg:%s", reply, client.getReplyString()),
|
||||||
null);
|
null);
|
||||||
client.disconnect();
|
client.disconnect();
|
||||||
return;
|
return;
|
||||||
@@ -101,11 +97,12 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity>
|
|||||||
readNormal(is);
|
readNormal(is);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isBreak()){
|
if (isBreak()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ALog.i(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】线程__" + mConfig.THREAD_ID + "__下载完毕");
|
ALog.i(TAG,
|
||||||
writeConfig(true, 1);
|
String.format("任务【%s】线程__%s__下载完毕", mConfig.TEMP_FILE.getName(), mConfig.THREAD_ID));
|
||||||
|
writeConfig(true, mConfig.END_LOCATION);
|
||||||
STATE.COMPLETE_THREAD_NUM++;
|
STATE.COMPLETE_THREAD_NUM++;
|
||||||
if (STATE.isComplete()) {
|
if (STATE.isComplete()) {
|
||||||
STATE.TASK_RECORD.deleteData();
|
STATE.TASK_RECORD.deleteData();
|
||||||
@@ -117,7 +114,7 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity>
|
|||||||
mListener.onFail(false);
|
mListener.onFail(false);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
fail(mChildCurrentLocation, "下载失败【" + mConfig.URL + "】", e);
|
fail(mChildCurrentLocation, String.format("下载失败【%s】", mConfig.URL), e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail(mChildCurrentLocation, "获取流失败", e);
|
fail(mChildCurrentLocation, "获取流失败", e);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -162,7 +159,7 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity>
|
|||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
fail(mChildCurrentLocation, "下载失败【" + mConfig.URL + "】", e);
|
fail(mChildCurrentLocation, String.format("下载失败【%s】", mConfig.URL), e);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (fos != null) {
|
if (fos != null) {
|
||||||
@@ -206,7 +203,7 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
fail(mChildCurrentLocation, "下载失败【" + mConfig.URL + "】", e);
|
fail(mChildCurrentLocation, String.format("下载失败【%s】", mConfig.URL), e);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} finally {
|
} finally {
|
||||||
@@ -219,8 +216,4 @@ class FtpThreadTask extends AbsFtpThreadTask<DownloadEntity, DownloadTaskEntity>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected String getTaskType() {
|
|
||||||
return "FTP_DOWNLOAD";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,18 +67,12 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEnt
|
|||||||
URL url = new URL(CommonUtil.convertUrl(mConfig.URL));
|
URL url = new URL(CommonUtil.convertUrl(mConfig.URL));
|
||||||
conn = ConnectionHelp.handleConnection(url);
|
conn = ConnectionHelp.handleConnection(url);
|
||||||
if (mConfig.SUPPORT_BP) {
|
if (mConfig.SUPPORT_BP) {
|
||||||
ALog.d(TAG, "任务【"
|
ALog.d(TAG,
|
||||||
+ mConfig.TEMP_FILE.getName()
|
String.format("任务【%s】线程__%s__开始下载【开始位置 : %s,结束位置:%s】", mConfig.TEMP_FILE.getName(),
|
||||||
+ "】线程__"
|
mConfig.THREAD_ID, mConfig.START_LOCATION, mConfig.END_LOCATION));
|
||||||
+ mConfig.THREAD_ID
|
|
||||||
+ "__开始下载【开始位置 : "
|
|
||||||
+ mConfig.START_LOCATION
|
|
||||||
+ ",结束位置:"
|
|
||||||
+ mConfig.END_LOCATION
|
|
||||||
+ "】");
|
|
||||||
//在头里面请求下载开始位置和结束位置
|
//在头里面请求下载开始位置和结束位置
|
||||||
conn.setRequestProperty("Range",
|
conn.setRequestProperty("Range",
|
||||||
"bytes=" + mConfig.START_LOCATION + "-" + (mConfig.END_LOCATION - 1));
|
String.format("bytes=%s-%s", mConfig.START_LOCATION, (mConfig.END_LOCATION - 1)));
|
||||||
} else {
|
} else {
|
||||||
ALog.w(TAG, "该下载不支持断点");
|
ALog.w(TAG, "该下载不支持断点");
|
||||||
}
|
}
|
||||||
@@ -108,7 +102,7 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEnt
|
|||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
fail(mChildCurrentLocation, "下载链接异常", e);
|
fail(mChildCurrentLocation, "下载链接异常", e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
fail(mChildCurrentLocation, "下载失败【" + mConfig.URL + "】", e);
|
fail(mChildCurrentLocation, String.format("下载失败【%s】", mConfig.URL), e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail(mChildCurrentLocation, "获取流失败", e);
|
fail(mChildCurrentLocation, "获取流失败", e);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -156,7 +150,7 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEnt
|
|||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
fail(mChildCurrentLocation, "下载失败【" + mConfig.URL + "】", e);
|
fail(mChildCurrentLocation, String.format("下载失败【%s】", mConfig.URL), e);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (fos != null) {
|
if (fos != null) {
|
||||||
@@ -210,8 +204,9 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEnt
|
|||||||
//支持断点的处理
|
//支持断点的处理
|
||||||
if (mConfig.SUPPORT_BP) {
|
if (mConfig.SUPPORT_BP) {
|
||||||
if (mChildCurrentLocation == mConfig.END_LOCATION) {
|
if (mChildCurrentLocation == mConfig.END_LOCATION) {
|
||||||
ALog.i(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】线程__" + mConfig.THREAD_ID + "__下载完毕");
|
ALog.i(TAG,
|
||||||
writeConfig(true, 1);
|
String.format("任务【%s】线程__%s__下载完毕", mConfig.TEMP_FILE.getName(), mConfig.THREAD_ID));
|
||||||
|
writeConfig(true, mConfig.END_LOCATION);
|
||||||
STATE.COMPLETE_THREAD_NUM++;
|
STATE.COMPLETE_THREAD_NUM++;
|
||||||
if (STATE.isComplete()) {
|
if (STATE.isComplete()) {
|
||||||
STATE.TASK_RECORD.deleteData();
|
STATE.TASK_RECORD.deleteData();
|
||||||
@@ -231,8 +226,4 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEnt
|
|||||||
mListener.onComplete();
|
mListener.onComplete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected String getTaskType() {
|
|
||||||
return "HTTP_DOWNLOAD";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ public abstract class AbsTarget<TARGET extends AbsTarget, ENTITY extends AbsEnti
|
|||||||
if (TextUtils.isEmpty(mEntity.getStr()) || !mEntity.getStr().equals(str)) {
|
if (TextUtils.isEmpty(mEntity.getStr()) || !mEntity.getStr().equals(str)) {
|
||||||
mEntity.setStr(str);
|
mEntity.setStr(str);
|
||||||
} else {
|
} else {
|
||||||
ALog.e(TAG, "设置扩展字段失败,扩展字段为null");
|
ALog.e(TAG, "设置扩展字段失败,扩展字段为一致");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (TARGET) this;
|
return (TARGET) this;
|
||||||
|
|||||||
@@ -165,12 +165,14 @@ abstract class AbsTaskQueue<TASK extends AbsTask, TASK_ENTITY extends AbsTaskEnt
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public void stopTask(TASK task) {
|
@Override public void stopTask(TASK task) {
|
||||||
if (!task.isRunning()) ALog.w(TAG, "停止任务【" + task.getTaskName() + "】失败,原因:已停止");
|
if (!task.isRunning()) {
|
||||||
|
ALog.w(TAG, String.format("停止任务【%s】失败,原因:已停止", task.getTaskName()));
|
||||||
|
}
|
||||||
if (mExecutePool.removeTask(task)) {
|
if (mExecutePool.removeTask(task)) {
|
||||||
task.stop();
|
task.stop();
|
||||||
} else {
|
} else {
|
||||||
task.stop();
|
task.stop();
|
||||||
ALog.w(TAG, "删除任务【" + task.getTaskName() + "】失败,原因:执行队列中没有该任务");
|
ALog.w(TAG, String.format("删除任务【%s】失败,原因:执行队列中没有该任务", task.getTaskName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,13 +180,13 @@ abstract class AbsTaskQueue<TASK extends AbsTask, TASK_ENTITY extends AbsTaskEnt
|
|||||||
//TEManager.getInstance().removeTEntity(key);
|
//TEManager.getInstance().removeTEntity(key);
|
||||||
TASK task = mExecutePool.getTask(key);
|
TASK task = mExecutePool.getTask(key);
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
ALog.d(TAG,
|
ALog.d(TAG, String.format("从执行池删除任务【%s】%s", task.getTaskName(),
|
||||||
"从执行池删除任务【" + task.getTaskName() + "】" + (mExecutePool.removeTask(task) ? "成功" : "失败"));
|
(mExecutePool.removeTask(task) ? "成功" : "失败")));
|
||||||
}
|
}
|
||||||
task = mCachePool.getTask(key);
|
task = mCachePool.getTask(key);
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
ALog.d(TAG,
|
ALog.d(TAG, String.format("从缓存池删除任务【%s】%s", task.getTaskName(),
|
||||||
"从缓存池删除任务【" + task.getTaskName() + "】" + (mCachePool.removeTask(task) ? "成功" : "失败"));
|
(mCachePool.removeTask(task) ? "成功" : "失败")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,7 +203,7 @@ abstract class AbsTaskQueue<TASK extends AbsTask, TASK_ENTITY extends AbsTaskEnt
|
|||||||
task.start();
|
task.start();
|
||||||
} else {
|
} else {
|
||||||
task.stop();
|
task.stop();
|
||||||
ALog.e(TAG, "任务【" + task.getTaskName() + "】重试失败,原因:任务没有完全停止,");
|
ALog.e(TAG, String.format("任务【%s】重试失败,原因:任务没有完全停止", task.getTaskName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package com.arialyy.aria.core.scheduler;
|
|||||||
|
|
||||||
import android.os.CountDownTimer;
|
import android.os.CountDownTimer;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
import android.util.Log;
|
||||||
import com.arialyy.aria.core.AriaManager;
|
import com.arialyy.aria.core.AriaManager;
|
||||||
import com.arialyy.aria.core.download.DownloadGroupTask;
|
import com.arialyy.aria.core.download.DownloadGroupTask;
|
||||||
import com.arialyy.aria.core.download.DownloadTask;
|
import com.arialyy.aria.core.download.DownloadTask;
|
||||||
@@ -292,7 +293,7 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskEntity, TASK extends Abs
|
|||||||
@Override public void onFinish() {
|
@Override public void onFinish() {
|
||||||
AbsEntity entity = task.getTaskEntity().getEntity();
|
AbsEntity entity = task.getTaskEntity().getEntity();
|
||||||
if (entity.getFailNum() <= reTryNum) {
|
if (entity.getFailNum() <= reTryNum) {
|
||||||
ALog.d(TAG, "任务【" + task.getTaskName() + "】开始重试");
|
ALog.d(TAG, String.format("任务【%s】开始重试", task.getTaskName()));
|
||||||
TASK task = mQueue.getTask(entity.getKey());
|
TASK task = mQueue.getTask(entity.getKey());
|
||||||
mQueue.reTryStart(task);
|
mQueue.reTryStart(task);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -54,15 +54,9 @@ class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UploadTaskEntity> {
|
|||||||
FTPClient client = null;
|
FTPClient client = null;
|
||||||
BufferedRandomAccessFile file = null;
|
BufferedRandomAccessFile file = null;
|
||||||
try {
|
try {
|
||||||
ALog.d(TAG, "任务【"
|
ALog.d(TAG,
|
||||||
+ mConfig.TEMP_FILE.getName()
|
String.format("任务【%s】线程__%s__开始上传【开始位置 : %s,结束位置:%s】", mConfig.TEMP_FILE.getName(),
|
||||||
+ "】线程__"
|
mConfig.THREAD_ID, mConfig.START_LOCATION, mConfig.END_LOCATION));
|
||||||
+ mConfig.THREAD_ID
|
|
||||||
+ "__开始上传【开始位置 : "
|
|
||||||
+ mConfig.START_LOCATION
|
|
||||||
+ ",结束位置:"
|
|
||||||
+ mConfig.END_LOCATION
|
|
||||||
+ "】");
|
|
||||||
client = createClient();
|
client = createClient();
|
||||||
if (client == null) return;
|
if (client == null) return;
|
||||||
initPath();
|
initPath();
|
||||||
@@ -85,8 +79,9 @@ class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UploadTaskEntity> {
|
|||||||
if (isBreak()) {
|
if (isBreak()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ALog.i(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】线程__" + mConfig.THREAD_ID + "__上传完毕");
|
ALog.i(TAG,
|
||||||
writeConfig(true, 1);
|
String.format("任务【%s】线程__%s__上传完毕", mConfig.TEMP_FILE.getName(), mConfig.THREAD_ID));
|
||||||
|
writeConfig(true, mConfig.END_LOCATION);
|
||||||
STATE.COMPLETE_THREAD_NUM++;
|
STATE.COMPLETE_THREAD_NUM++;
|
||||||
if (STATE.isComplete()) {
|
if (STATE.isComplete()) {
|
||||||
STATE.TASK_RECORD.deleteData();
|
STATE.TASK_RECORD.deleteData();
|
||||||
@@ -98,7 +93,7 @@ class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UploadTaskEntity> {
|
|||||||
mListener.onFail(false);
|
mListener.onFail(false);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
fail(mChildCurrentLocation, "上传失败【" + mConfig.URL + "】", e);
|
fail(mChildCurrentLocation, String.format("上传失败【%s】", mConfig.URL), e);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
fail(mChildCurrentLocation, "获取流失败", e);
|
fail(mChildCurrentLocation, "获取流失败", e);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -127,7 +122,7 @@ class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UploadTaskEntity> {
|
|||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ALog.d(TAG, "remotePath【" + remotePath + "】");
|
ALog.d(TAG, String.format("remotePath【%s】", remotePath));
|
||||||
client.storeFile(remotePath, new FtpFISAdapter(bis), new OnFtpInputStreamListener() {
|
client.storeFile(remotePath, new FtpFISAdapter(bis), new OnFtpInputStreamListener() {
|
||||||
boolean isStoped = false;
|
boolean isStoped = false;
|
||||||
|
|
||||||
@@ -155,7 +150,8 @@ class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UploadTaskEntity> {
|
|||||||
int reply = client.getReplyCode();
|
int reply = client.getReplyCode();
|
||||||
if (!FTPReply.isPositiveCompletion(reply)) {
|
if (!FTPReply.isPositiveCompletion(reply)) {
|
||||||
if (reply != FTPReply.TRANSFER_ABORTED) {
|
if (reply != FTPReply.TRANSFER_ABORTED) {
|
||||||
fail(mChildCurrentLocation, "上传文件错误,错误码为:" + reply + ",msg:" + client.getReplyString(),
|
fail(mChildCurrentLocation,
|
||||||
|
String.format("上传文件错误,错误码为:%s,msg:%s", reply, client.getReplyString()),
|
||||||
null);
|
null);
|
||||||
}
|
}
|
||||||
if (client.isConnected()) {
|
if (client.isConnected()) {
|
||||||
@@ -163,8 +159,4 @@ class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UploadTaskEntity> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected String getTaskType() {
|
|
||||||
return "FTP_UPLOAD";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ class HttpThreadTask extends AbsThreadTask<UploadEntity, UploadTaskEntity> {
|
|||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
File uploadFile = new File(mEntity.getFilePath());
|
File uploadFile = new File(mEntity.getFilePath());
|
||||||
if (!uploadFile.exists()) {
|
if (!uploadFile.exists()) {
|
||||||
ALog.e(TAG, "【" + mEntity.getFilePath() + "】,文件不存在。");
|
ALog.e(TAG, String.format("【%s】,文件不存在。", mEntity.getFilePath()));
|
||||||
fail();
|
fail();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -212,8 +212,4 @@ class HttpThreadTask extends AbsThreadTask<UploadEntity, UploadTaskEntity> {
|
|||||||
mOutputStream.close();
|
mOutputStream.close();
|
||||||
return response.toString();
|
return response.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected String getTaskType() {
|
|
||||||
return "HTTP_UPLOAD";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,6 +117,9 @@ public class ALog {
|
|||||||
* 将异常信息转换为字符串
|
* 将异常信息转换为字符串
|
||||||
*/
|
*/
|
||||||
public static String getExceptionString(Throwable ex) {
|
public static String getExceptionString(Throwable ex) {
|
||||||
|
if (ex == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
StringBuilder err = new StringBuilder();
|
StringBuilder err = new StringBuilder();
|
||||||
err.append("ExceptionDetailed:\n");
|
err.append("ExceptionDetailed:\n");
|
||||||
err.append("====================Exception Info====================\n");
|
err.append("====================Exception Info====================\n");
|
||||||
|
|||||||
@@ -246,53 +246,30 @@ public class CommonUtil {
|
|||||||
* @param url 输入的url{@code String url = "ftp://z:z@dygod18.com:21211/[电影天堂www.dy2018.com]猩球崛起3:终极之战BD国英双语中英双字.mkv";}
|
* @param url 输入的url{@code String url = "ftp://z:z@dygod18.com:21211/[电影天堂www.dy2018.com]猩球崛起3:终极之战BD国英双语中英双字.mkv";}
|
||||||
*/
|
*/
|
||||||
public static FtpUrlEntity getFtpUrlInfo(String url) {
|
public static FtpUrlEntity getFtpUrlInfo(String url) {
|
||||||
|
Uri uri = Uri.parse(url);
|
||||||
|
|
||||||
|
String userInfo = uri.getUserInfo(), remotePath = uri.getPath();
|
||||||
|
ALog.d(TAG,
|
||||||
|
String.format("scheme = %s, user = %s, host = %s, port = %s, path = %s", uri.getScheme(),
|
||||||
|
userInfo, uri.getHost(), uri.getPort(), remotePath));
|
||||||
|
|
||||||
FtpUrlEntity entity = new FtpUrlEntity();
|
FtpUrlEntity entity = new FtpUrlEntity();
|
||||||
entity.url = url;
|
entity.url = url;
|
||||||
//String regex = "(\\w+)://(.*):(\\d*)/(.*)";
|
entity.hostName = uri.getHost();
|
||||||
String regex = Regular.REG_FTP_URL;
|
entity.port = uri.getPort() == -1 ? "21" : String.valueOf(uri.getPort());
|
||||||
Pattern p = Pattern.compile(regex);
|
if (!TextUtils.isEmpty(userInfo)) {
|
||||||
Matcher m = p.matcher(url);
|
String[] temp = userInfo.split(":");
|
||||||
if (m.find() && m.groupCount() > 0) {
|
if (temp.length == 2) {
|
||||||
entity.protocol = m.group(1);
|
entity.user = temp[0];
|
||||||
String str = m.group(2);
|
entity.password = temp[1];
|
||||||
if (str.contains("@")) {
|
|
||||||
entity.needLogin = true;
|
|
||||||
//String hostReg = "(\\w+):?(\\w+)?@(.*)";
|
|
||||||
String hostReg = Regular.REG_FTP_HOST_NAME;
|
|
||||||
Pattern hp = Pattern.compile(hostReg);
|
|
||||||
Matcher hm = hp.matcher(str);
|
|
||||||
if (hm.find() && hm.groupCount() > 0) {
|
|
||||||
entity.user = hm.group(1);
|
|
||||||
entity.password = TextUtils.isEmpty(hm.group(2)) ? "" : hm.group(2);
|
|
||||||
entity.hostName = hm.group(3);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
entity.hostName = str;
|
entity.user = userInfo;
|
||||||
}
|
}
|
||||||
entity.port = m.group(3);
|
|
||||||
//entity.remotePath = TextUtils.isEmpty(m.group(4)) ? "/" : "/" + m.group(4);
|
|
||||||
entity.remotePath = TextUtils.isEmpty(m.group(4)) ? "/" : m.group(4);
|
|
||||||
}
|
}
|
||||||
|
entity.remotePath = TextUtils.isEmpty(remotePath) ? "/" : remotePath;
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 通过url获取FTP文件的remotePath
|
|
||||||
*
|
|
||||||
* @return remotePath。如果没有找到,返回""
|
|
||||||
*/
|
|
||||||
public static String getRemotePath(String url) {
|
|
||||||
String remotePath = null;
|
|
||||||
String regex = Regular.REG_FTP_URL;
|
|
||||||
Pattern p = Pattern.compile(regex);
|
|
||||||
Matcher m = p.matcher(url);
|
|
||||||
if (m.find() && m.groupCount() > 0) {
|
|
||||||
return TextUtils.isEmpty(m.group(4)) ? "" : "/" + m.group(4);
|
|
||||||
}
|
|
||||||
ALog.w(TAG, "链接【" + url + "】没有找到remotePath");
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 转换Url
|
* 转换Url
|
||||||
*
|
*
|
||||||
@@ -300,25 +277,27 @@ public class CommonUtil {
|
|||||||
* @return 转换后的地址
|
* @return 转换后的地址
|
||||||
*/
|
*/
|
||||||
public static String convertUrl(String url) {
|
public static String convertUrl(String url) {
|
||||||
if (hasDoubleCharacter(url)) {
|
Uri uri = Uri.parse(url);
|
||||||
//预先处理空格,URLEncoder只会把空格转换为+
|
url = uri.toString();
|
||||||
url = url.replaceAll(" ", "%20");
|
//if (hasDoubleCharacter(url)) {
|
||||||
//匹配双字节字符(包括汉字在内)
|
// //预先处理空格,URLEncoder只会把空格转换为+
|
||||||
String regex = Regular.REG_DOUBLE_CHAR_AND_SPACE;
|
// url = url.replaceAll(" ", "%20");
|
||||||
Pattern p = Pattern.compile(regex);
|
// //匹配双字节字符(包括汉字在内)
|
||||||
Matcher m = p.matcher(url);
|
// String regex = Regular.REG_DOUBLE_CHAR_AND_SPACE;
|
||||||
Set<String> strs = new HashSet<>();
|
// Pattern p = Pattern.compile(regex);
|
||||||
while (m.find()) {
|
// Matcher m = p.matcher(url);
|
||||||
strs.add(m.group());
|
// Set<String> strs = new HashSet<>();
|
||||||
}
|
// while (m.find()) {
|
||||||
try {
|
// strs.add(m.group());
|
||||||
for (String str : strs) {
|
// }
|
||||||
url = url.replaceAll(str, URLEncoder.encode(str, "UTF-8"));
|
// try {
|
||||||
}
|
// for (String str : strs) {
|
||||||
} catch (UnsupportedEncodingException e) {
|
// url = url.replaceAll(str, URLEncoder.encode(str, "UTF-8"));
|
||||||
e.printStackTrace();
|
// }
|
||||||
}
|
// } catch (UnsupportedEncodingException e) {
|
||||||
}
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
//}
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,15 +5,6 @@ package com.arialyy.aria.util;
|
|||||||
* 正则表达式
|
* 正则表达式
|
||||||
*/
|
*/
|
||||||
public interface Regular {
|
public interface Regular {
|
||||||
/**
|
|
||||||
* ftp地址
|
|
||||||
*/
|
|
||||||
String REG_FTP_URL = "(\\w+)://(.*):(\\d*)/(.*)";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ftp主机、用户、密码分割
|
|
||||||
*/
|
|
||||||
String REG_FTP_HOST_NAME = "(\\w+):?(\\w+)?@(.*)";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取文件名
|
* 获取文件名
|
||||||
|
|||||||
@@ -126,8 +126,7 @@ protected void onCreate(Bundle savedInstanceState) {
|
|||||||
|
|
||||||
## 其他
|
## 其他
|
||||||
有任何问题,可以在[issues](https://github.com/AriaLyy/Aria/issues)给我留言反馈。</br>
|
有任何问题,可以在[issues](https://github.com/AriaLyy/Aria/issues)给我留言反馈。</br>
|
||||||
在提交问题前,希望你已经查看过[wiki](https://github.com/AriaLyy/Aria/wiki)或搜索过[issues](https://github.com/AriaLyy/Aria/issues)。</br>
|
在提交问题前,希望你已经查看过[wiki](https://aria.laoyuyu.me/aria_doc/)或搜索过[issues](https://github.com/AriaLyy/Aria/issues)。</br>
|
||||||
Aria交流群:524329160(加群条件:对aria有过star、commit、issues)
|
|
||||||
***
|
***
|
||||||
|
|
||||||
License
|
License
|
||||||
|
|||||||
@@ -14,8 +14,9 @@
|
|||||||
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.TestActivity"-->
|
|
||||||
<!--android:name=".MainActivity"-->
|
<!--android:name=".MainActivity"-->
|
||||||
|
<!--android:name=".download.group.DownloadGroupActivity"-->
|
||||||
|
<!--android:name=".test.TestActivity"-->
|
||||||
<activity
|
<activity
|
||||||
android:name=".test.AnyRunActivity"
|
android:name=".test.AnyRunActivity"
|
||||||
android:label="@string/app_name">
|
android:label="@string/app_name">
|
||||||
@@ -33,7 +34,7 @@
|
|||||||
<activity android:name=".download.multi_download.MultiDownloadActivity"/>
|
<activity android:name=".download.multi_download.MultiDownloadActivity"/>
|
||||||
<activity android:name=".download.HighestPriorityActivity"/>
|
<activity android:name=".download.HighestPriorityActivity"/>
|
||||||
<activity android:name=".test.TestMutilTaskSysDownload"/>
|
<activity android:name=".test.TestMutilTaskSysDownload"/>
|
||||||
<activity android:name=".download.group.DownloadGroupActivity"/>
|
<!--<activity android:name=".download.group.DownloadGroupActivity"/>-->
|
||||||
<activity android:name=".download.FtpDownloadActivity"/>
|
<activity android:name=".download.FtpDownloadActivity"/>
|
||||||
<activity android:name=".download.group.FTPDirDownloadActivity"/>
|
<activity android:name=".download.group.FTPDirDownloadActivity"/>
|
||||||
<activity android:name=".upload.HttpUploadActivity"/>
|
<activity android:name=".upload.HttpUploadActivity"/>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
3、从3.4.1开始,如果线程数为1,文件初始化时将不再预占用对应长度的空间,下载多少byte,则占多大的空间;
|
3、从3.4.1开始,如果线程数为1,文件初始化时将不再预占用对应长度的空间,下载多少byte,则占多大的空间;
|
||||||
对于采用多线程的任务或旧任务,依然采用原来的文件空间占用方式;
|
对于采用多线程的任务或旧任务,依然采用原来的文件空间占用方式;
|
||||||
-->
|
-->
|
||||||
<threadNum value="3"/>
|
<threadNum value="1"/>
|
||||||
|
|
||||||
<!--设置下载队列最大任务数, 默认为2-->
|
<!--设置下载队列最大任务数, 默认为2-->
|
||||||
<maxTaskNum value="2"/>
|
<maxTaskNum value="2"/>
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ public class DownloadGroupActivity extends BaseActivity<ActivityDownloadGroupBin
|
|||||||
.setDirPath(
|
.setDirPath(
|
||||||
Environment.getExternalStorageDirectory().getPath() + "/Download/group_test_3")
|
Environment.getExternalStorageDirectory().getPath() + "/Download/group_test_3")
|
||||||
.setGroupAlias("任务组测试")
|
.setGroupAlias("任务组测试")
|
||||||
.setSubFileName(getModule(GroupModule.class).getSubName())
|
//.setSubFileName(getModule(GroupModule.class).getSubName())
|
||||||
//.setFileSize(32895492)
|
//.setFileSize(32895492)
|
||||||
.start();
|
.start();
|
||||||
break;
|
break;
|
||||||
@@ -92,7 +92,8 @@ public class DownloadGroupActivity extends BaseActivity<ActivityDownloadGroupBin
|
|||||||
Aria.download(this).load(mUrls).stop();
|
Aria.download(this).load(mUrls).stop();
|
||||||
break;
|
break;
|
||||||
case R.id.cancel:
|
case R.id.cancel:
|
||||||
Aria.download(this).load(mUrls).cancel(true);
|
//Aria.download(this).load(mUrls).cancel(true);
|
||||||
|
Aria.download(this).removeAllTask(true);
|
||||||
//mUrls = getModule(GroupModule.class).getUrls1();
|
//mUrls = getModule(GroupModule.class).getUrls1();
|
||||||
//Aria.download(this)
|
//Aria.download(this)
|
||||||
// .load(mUrls)
|
// .load(mUrls)
|
||||||
|
|||||||
@@ -19,11 +19,13 @@ public class AnyRunActivity extends BaseActivity<ActivityTestBinding> {
|
|||||||
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://z:z@dygod18.com:21211/[电影天堂www.dy2018.com]猩球崛起3:终极之战BD国英双语中英双字.mkv";
|
||||||
|
|
||||||
@Override protected int setLayoutId() {
|
@Override protected int setLayoutId() {
|
||||||
return R.layout.activity_test;
|
return R.layout.activity_test;
|
||||||
@@ -49,8 +51,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);
|
//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());
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.arialyy.simple.test;
|
package com.arialyy.simple.test;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -7,6 +8,7 @@ import com.arialyy.annotations.Upload;
|
|||||||
import com.arialyy.aria.core.Aria;
|
import com.arialyy.aria.core.Aria;
|
||||||
import com.arialyy.aria.core.common.RequestEnum;
|
import com.arialyy.aria.core.common.RequestEnum;
|
||||||
import com.arialyy.aria.core.upload.UploadTask;
|
import com.arialyy.aria.core.upload.UploadTask;
|
||||||
|
import com.arialyy.aria.util.ALog;
|
||||||
import com.arialyy.aria.util.CommonUtil;
|
import com.arialyy.aria.util.CommonUtil;
|
||||||
import com.arialyy.simple.R;
|
import com.arialyy.simple.R;
|
||||||
import com.arialyy.simple.base.BaseActivity;
|
import com.arialyy.simple.base.BaseActivity;
|
||||||
@@ -22,8 +24,8 @@ public class TestActivity extends BaseActivity<ActivityTestBinding> {
|
|||||||
//String URL = "http://58.210.9.131/tpk/sipgt//TDLYZTGH.tpk"; //chunked 下载
|
//String URL = "http://58.210.9.131/tpk/sipgt//TDLYZTGH.tpk"; //chunked 下载
|
||||||
//private final String URL = "ftp://192.168.1.3:21/download//AriaPrj.rar";
|
//private final String URL = "ftp://192.168.1.3:21/download//AriaPrj.rar";
|
||||||
private final String FILE_PATH = "/mnt/sdcard/AriaPrj.rar";
|
private final String FILE_PATH = "/mnt/sdcard/AriaPrj.rar";
|
||||||
//private final String URL = "ftp://192.168.29.140:21/aa//你好";
|
private final String URL = "ftp://192.168.1.2:21/aa//你好";
|
||||||
private final String URL = "ftp://192.168.29.140:21/upload/";
|
|
||||||
|
|
||||||
@Override protected int setLayoutId() {
|
@Override protected int setLayoutId() {
|
||||||
return R.layout.activity_test;
|
return R.layout.activity_test;
|
||||||
@@ -81,6 +83,8 @@ public class TestActivity extends BaseActivity<ActivityTestBinding> {
|
|||||||
.setUploadUrl(URL)
|
.setUploadUrl(URL)
|
||||||
.setExtendField("韩寒哈大双")
|
.setExtendField("韩寒哈大双")
|
||||||
.start();
|
.start();
|
||||||
|
//Uri uri = Uri.parse("ftp://z:z@dygod18.com:21211/[电影天堂www.dy2018.com]猩球崛起3:终极之战BD国英双语中英双字.mkv");
|
||||||
|
//ALog.d(TAG, "sh = " + uri.getScheme() + ", user = " + uri.getUserInfo() + ", host = " + uri.getHost() + ", port = " + uri.getPort() + " remotePath = " + uri.getPath());
|
||||||
break;
|
break;
|
||||||
case R.id.stop:
|
case R.id.stop:
|
||||||
Aria.upload(this).loadFtp(FILE_PATH).stop();
|
Aria.upload(this).loadFtp(FILE_PATH).stop();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.arialyy.aria">
|
package="com.arialyy.aria">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:supportsRtl="true">
|
android:supportsRtl="true">
|
||||||
|
|||||||
Reference in New Issue
Block a user