4 Commits
3.7.10 ... 3.8

Author SHA1 Message Date
laoyuyu
27c889e171 修复ftp服务器无法响应abor命令导致的无法停止上传的问题
修复ftp上传时,服务器有长度为0的文件导致上传失败的问题
修复下载任务和上传任务的文件路径是同一个时,导致的记录混乱问题
2019-12-17 22:04:25 +08:00
laoyuyu
0d93953cd9 修复组合任务初始化失败时,无法删除的问题
修复`reStart()`后,无法停止的问题
ftp增加主动模式,开启主动模式:https://aria.laoyuyu.me/aria_doc/api/ftp_params.html
优化提示
2019-12-16 20:18:51 +08:00
laoyuyu
f3d5e0135a m3u8增加了ignoreFailureTs方法,忽略虾类失败的ts切片
修复在dialogFragment的`onCreateDialog()`注册导致的注解不生效问题
2019-12-15 21:52:54 +08:00
laoyuyu
d9ed7f87d2 移除androidx、support依赖,现在哪个版本的appcompat库都可以导入Aria
修复一个在xml中使用fragment导致的内存泄漏问题
2019-12-08 11:09:11 +08:00
112 changed files with 951 additions and 657 deletions

View File

@@ -92,5 +92,6 @@ public class RegularExpression {
/**
* IP
*/
public static String IP = "\\d+\\.\\d+\\.\\d+\\.\\d+";
public static String IP =
"([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}";
}

View File

@@ -23,7 +23,7 @@ android {
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
testImplementation 'junit:junit:4.12'
implementation "androidx.appcompat:appcompat:${rootProject.ext.XAppcompatVersion}"
// implementation "androidx.appcompat:appcompat:${rootProject.ext.XAppcompatVersion}"
api project(':AriaAnnotations')
api project(path: ':PublicComponent')
api project(path: ':HttpComponent')

View File

@@ -290,19 +290,31 @@ import java.util.concurrent.ConcurrentHashMap;
}
}
private IReceiver putReceiver(@ReceiverType String type, Object obj) {
private IReceiver putReceiver(String type, Object obj) {
final String key = getKey(type, obj);
IReceiver receiver = mReceivers.get(key);
boolean needRmReceiver = false;
// 监控Dialog、fragment、popupWindow的生命周期
final WidgetLiftManager widgetLiftManager = new WidgetLiftManager();
Context subParenActivity = null;
if (obj instanceof Dialog) {
needRmReceiver = widgetLiftManager.handleDialogLift((Dialog) obj);
subParenActivity = ((Dialog) obj).getOwnerActivity();
} else if (obj instanceof PopupWindow) {
needRmReceiver = widgetLiftManager.handlePopupWindowLift((PopupWindow) obj);
subParenActivity = ((PopupWindow) obj).getContentView().getContext();
} else if (isDialogFragment(obj.getClass())) {
needRmReceiver = widgetLiftManager.handleDialogFragmentLift(getDialog(obj));
subParenActivity = getFragmentActivity(obj);
} else if (isFragment(obj.getClass())) {
subParenActivity = getFragmentActivity(obj);
}
if (subParenActivity instanceof Activity) {
relateSubClass(type, obj, (Activity) subParenActivity);
}
if (receiver == null) {
AbsReceiver absReceiver =
type.equals(ReceiverType.DOWNLOAD) ? new DownloadReceiver() : new UploadReceiver();
@@ -315,30 +327,6 @@ import java.util.concurrent.ConcurrentHashMap;
return receiver;
}
/**
* 根据功能类型和控件类型获取对应的key
*
* @param type {@link ReceiverType}
* @param obj 观察者对象
* @return {@link #createKey(String, Object)}
*/
private String getKey(@ReceiverType String type, Object obj) {
if (isFragment(obj.getClass())) {
relateSubClass(type, obj, getFragmentActivity(obj));
} else if (obj instanceof Dialog) {
Activity activity = ((Dialog) obj).getOwnerActivity();
if (activity != null) {
relateSubClass(type, obj, activity);
}
} else if (obj instanceof PopupWindow) {
Context context = ((PopupWindow) obj).getContentView().getContext();
if (context instanceof Activity) {
relateSubClass(type, obj, (Activity) context);
}
}
return createKey(type, obj);
}
/**
* 获取fragment的activity
*
@@ -421,14 +409,17 @@ import java.util.concurrent.ConcurrentHashMap;
* @param sub Fragment或dialog类
* @param activity activity寄主类
*/
private void relateSubClass(@ReceiverType String type, Object sub, Activity activity) {
String key = createKey(type, activity);
List<String> list = mSubClass.get(key);
if (list == null) {
list = new ArrayList<>();
mSubClass.put(key, list);
private void relateSubClass(String type, Object sub, Activity activity) {
String key = getKey(type, activity);
List<String> subClass = mSubClass.get(key);
if (subClass == null) {
subClass = new ArrayList<>();
mSubClass.put(key, subClass);
}
subClass.add(getKey(type, sub));
if (mReceivers.get(key) == null) { // 将activity填充进去
mReceivers.put(key, new DownloadReceiver());
}
list.add(createKey(type, sub));
}
/**
@@ -439,7 +430,7 @@ import java.util.concurrent.ConcurrentHashMap;
* @return key的格式为{@code String.format("%s_%s_%s", obj.getClass().getName(), type,
* obj.hashCode());}
*/
private String createKey(@ReceiverType String type, Object obj) {
private String getKey(String type, Object obj) {
return String.format("%s_%s_%s", obj.getClass().getName(), type, obj.hashCode());
}

View File

@@ -73,8 +73,16 @@ final class WidgetLiftManager {
/**
* 处理对话框取消或dismiss
*
* @return true 设置了dialog的销毁事件。false 没有设置dialog的销毁事件
*/
boolean handleDialogLift(Dialog dialog) {
if (dialog == null) {
ALog.w(TAG,
"dialog 为空没有设置自动销毁事件为了防止内存泄露请在dismiss方法中调用Aria.download(this).unRegister();来注销事件\n"
+ "如果你使用的是DialogFragment那么你需要在onDestroy()中进行销毁Aria事件操作");
return false;
}
try {
Field dismissField = CommonUtil.getField(dialog.getClass(), "mDismissMessage");
Message dismissMsg = (Message) dismissField.get(dialog);

View File

@@ -15,9 +15,9 @@
*/
package com.arialyy.aria.core.command;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.inf.TaskSchedulerType;
/**
* 重新开始任务命令
@@ -34,8 +34,8 @@ final class ReStartCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
task = createTask();
}
if (task != null) {
task.cancel(TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY);
task.start(TaskSchedulerType.TYPE_START_AND_RESET_STATE);
mQueue.cancelTask(task, TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY);
mQueue.startTask(task, TaskSchedulerType.TYPE_START_AND_RESET_STATE);
}
}
}

View File

@@ -202,8 +202,8 @@ public abstract class AbsNormalTarget<TARGET extends AbsNormalTarget> extends Ab
* 重新下载
*/
@Override
public void reStart() {
getController().reStart();
public long reStart() {
return getController().reStart();
}
@Override

View File

@@ -33,6 +33,9 @@ public class FtpOption extends BaseOption {
private String protocol, keyAlias, storePass, storePath;
private boolean isImplicit = true;
private IFtpUploadInterceptor uploadInterceptor;
private int connMode = FtpConnectionMode.DATA_CONNECTION_MODE_PASV;
private int minPort, maxPort;
private String activeExternalIPAddress;
public FtpOption() {
super();
@@ -70,7 +73,7 @@ public class FtpOption extends BaseOption {
*
* @param protocol {@link ProtocolType}
*/
public FtpOption setProtocol(@ProtocolType String protocol) {
public FtpOption setProtocol(String protocol) {
if (TextUtils.isEmpty(protocol)) {
ALog.e(TAG, "设置协议失败,协议信息为空");
return this;
@@ -143,6 +146,63 @@ public class FtpOption extends BaseOption {
return this;
}
/**
* 设置数据传输模式,默认为被动模式。
* 主动模式传输文件时客户端开启一个端口ftp服务器连接到客户端的该端口ftp服务器推送数据到客户端
* 被动模式传输文件时ftp服务器开启一个端口客户端连接到ftp服务器的这个端口客户端请求ftp服务器的数据
* 请注意主动模式是服务器主动连接到android如果使用住的模式请确保ftp服务器能ping通android
*
* @param connMode {@link FtpConnectionMode#DATA_CONNECTION_MODE_PASV},
* {@link FtpConnectionMode#DATA_CONNECTION_MODE_ACTIVITY}
*/
public FtpOption setConnectionMode(int connMode) {
if (connMode != FtpConnectionMode.DATA_CONNECTION_MODE_PASV
&& connMode != FtpConnectionMode.DATA_CONNECTION_MODE_ACTIVITY) {
ALog.e(TAG, "连接模式设置失败,默认启用被动模式");
return this;
}
this.connMode = connMode;
return this;
}
/**
* 主动模式下的端口范围
*/
public FtpOption setActivePortRange(int minPort, int maxPort) {
if (minPort > maxPort) {
ALog.e(TAG, "设置端口范围错误minPort > maxPort");
return this;
}
if (minPort <= 0 || minPort >= 65535) {
ALog.e(TAG, "端口范围错误");
return this;
}
if (maxPort >= 65535) {
ALog.e(TAG, "端口范围错误");
return this;
}
this.minPort = minPort;
this.maxPort = maxPort;
return this;
}
/**
* 主动模式下对外ip可被Ftp服务器访问的ip
*/
public FtpOption setActiveExternalIPAddress(String ip) {
if (TextUtils.isEmpty(ip)) {
ALog.e(TAG, "ip为空");
return this;
}
if (!CheckUtil.checkIp(ip)) {
ALog.e(TAG, "ip地址错误" + ip);
return this;
}
this.activeExternalIPAddress = ip;
return this;
}
public void setUrlEntity(FtpUrlEntity urlEntity) {
this.urlEntity = urlEntity;
urlEntity.needLogin = isNeedLogin;

View File

@@ -16,11 +16,6 @@
package com.arialyy.aria.core.common;
import android.text.TextUtils;
import androidx.annotation.CheckResult;
import androidx.annotation.NonNull;
import com.arialyy.aria.core.download.target.HttpBuilderTarget;
import com.arialyy.aria.core.inf.IOptionConstant;
import com.arialyy.aria.core.inf.Suggest;
import com.arialyy.aria.core.processor.IHttpFileLenAdapter;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CheckUtil;
@@ -50,7 +45,6 @@ public class HttpOption extends BaseOption {
*
* @param requestEnum {@link RequestEnum}
*/
@CheckResult(suggest = Suggest.TO_CONTROLLER)
public HttpOption setRequestType(RequestEnum requestEnum) {
this.requestEnum = requestEnum;
return this;
@@ -97,7 +91,7 @@ public class HttpOption extends BaseOption {
* @param key header对应的key
* @param value header对应的value
*/
public HttpOption addHeader(@NonNull String key, @NonNull String value) {
public HttpOption addHeader(String key, String value) {
if (TextUtils.isEmpty(key)) {
ALog.w(TAG, "设置header失败header对应的key不能为null");
return this;
@@ -118,7 +112,7 @@ public class HttpOption extends BaseOption {
*
* @param headers 一组http header数据
*/
public HttpOption addHeaders(@NonNull Map<String, String> headers) {
public HttpOption addHeaders(Map<String, String> headers) {
if (headers.size() == 0) {
ALog.w(TAG, "设置header失败map没有header数据");
return this;

View File

@@ -75,50 +75,23 @@ public class ProxyHelper {
return result;
}
result = new HashSet<>();
try {
if (getClass().getClassLoader()
.loadClass(className.concat(TaskEnum.DOWNLOAD_GROUP.proxySuffix))
!= null) {
result.add(PROXY_TYPE_DOWNLOAD_GROUP);
}
} catch (ClassNotFoundException e) {
//e.printStackTrace();
if (checkProxyExist(className, TaskEnum.DOWNLOAD_GROUP.proxySuffix)) {
result.add(PROXY_TYPE_DOWNLOAD_GROUP);
}
try {
if (getClass().getClassLoader().loadClass(className.concat(TaskEnum.DOWNLOAD.proxySuffix))
!= null) {
result.add(PROXY_TYPE_DOWNLOAD);
}
} catch (ClassNotFoundException e) {
//e.printStackTrace();
if (checkProxyExist(className, TaskEnum.DOWNLOAD.proxySuffix)) {
result.add(PROXY_TYPE_DOWNLOAD);
}
try {
if (getClass().getClassLoader().loadClass(className.concat(TaskEnum.UPLOAD.proxySuffix))
!= null) {
result.add(PROXY_TYPE_UPLOAD);
}
} catch (ClassNotFoundException e) {
//e.printStackTrace();
if (checkProxyExist(className, TaskEnum.UPLOAD.proxySuffix)) {
result.add(PROXY_TYPE_UPLOAD);
}
try {
if (getClass().getClassLoader().loadClass(className.concat(TaskEnum.M3U8_PEER.proxySuffix))
!= null) {
result.add(PROXY_TYPE_M3U8_PEER);
}
} catch (ClassNotFoundException e) {
//e.printStackTrace();
if (checkProxyExist(className, TaskEnum.M3U8_PEER.proxySuffix)) {
result.add(PROXY_TYPE_M3U8_PEER);
}
try {
if (getClass().getClassLoader()
.loadClass(className.concat(TaskEnum.DOWNLOAD_GROUP_SUB.proxySuffix))
!= null) {
result.add(PROXY_TYPE_DOWNLOAD_GROUP_SUB);
}
} catch (ClassNotFoundException e) {
//e.printStackTrace();
if (checkProxyExist(className, TaskEnum.DOWNLOAD_GROUP_SUB.proxySuffix)) {
result.add(PROXY_TYPE_DOWNLOAD_GROUP_SUB);
}
if (!result.isEmpty()) {
@@ -126,4 +99,20 @@ public class ProxyHelper {
}
return result;
}
private boolean checkProxyExist(String className, String proxySuffix) {
String clsName = className.concat(proxySuffix);
try {
if (getClass().getClassLoader().loadClass(clsName) != null) {
return true;
}
if (Class.forName(clsName) != null) {
return true;
}
} catch (ClassNotFoundException e) {
//e.printStackTrace();
}
return false;
}
}

View File

@@ -15,11 +15,10 @@
*/
package com.arialyy.aria.core.common.controller;
import com.arialyy.aria.core.command.CmdHelper;
import com.arialyy.aria.core.command.NormalCmdFactory;
import com.arialyy.aria.core.event.EventMsgUtil;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.command.CmdHelper;
import com.arialyy.aria.util.ALog;
/**
* 创建任务时使用的控制器
@@ -36,6 +35,7 @@ public final class BuilderController extends FeatureController implements IStart
* @return 正常添加返回任务id否则返回-1
*/
public long add() {
setAction(ACTION_ADD);
if (checkConfig()) {
EventMsgUtil.getDefault()
.post(CmdHelper.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_CREATE,
@@ -51,17 +51,18 @@ public final class BuilderController extends FeatureController implements IStart
* @return 正常启动返回任务id否则返回-1
*/
public long create() {
setAction(ACTION_CREATE);
if (checkConfig()) {
EventMsgUtil.getDefault()
.post(CmdHelper.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_START,
checkTaskType()));
return getEntity().getId();
}
return -1;
}
@Override public long setHighestPriority() {
setAction(ACTION_PRIORITY);
if (checkConfig()) {
EventMsgUtil.getDefault()
.post(CmdHelper.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_HIGHEST_PRIORITY,

View File

@@ -43,6 +43,17 @@ import java.lang.reflect.InvocationTargetException;
* 功能控制器
*/
public abstract class FeatureController {
private static final int ACTION_DEF = 0;
public static final int ACTION_CREATE = 1;
public static final int ACTION_RESUME = 2;
public static final int ACTION_STOP = 3;
public static final int ACTION_CANCEL = 4;
public static final int ACTION_ADD = 5;
public static final int ACTION_PRIORITY = 6;
public static final int ACTION_RETRY = 7;
public static final int ACTION_RESTART = 8;
public static final int ACTION_SAVE = 9;
private final String TAG;
private AbsTaskWrapper mTaskWrapper;
@@ -50,6 +61,7 @@ public abstract class FeatureController {
* 是否忽略权限检查 true 忽略权限检查
*/
private boolean ignoreCheckPermissions = false;
private int action = ACTION_DEF;
FeatureController(AbsTaskWrapper wrapper) {
mTaskWrapper = wrapper;
@@ -91,6 +103,10 @@ public abstract class FeatureController {
return null;
}
void setAction(int action) {
this.action = action;
}
/**
* 是否忽略权限检查
*/
@@ -180,15 +196,15 @@ public abstract class FeatureController {
private boolean checkEntity() {
ICheckEntityUtil checkUtil = null;
if (mTaskWrapper instanceof DTaskWrapper) {
checkUtil = CheckDEntityUtil.newInstance((DTaskWrapper) mTaskWrapper);
checkUtil = CheckDEntityUtil.newInstance((DTaskWrapper) mTaskWrapper, action);
} else if (mTaskWrapper instanceof DGTaskWrapper) {
if (mTaskWrapper.getRequestType() == ITaskWrapper.D_FTP_DIR) {
checkUtil = CheckFtpDirEntityUtil.newInstance((DGTaskWrapper) mTaskWrapper);
checkUtil = CheckFtpDirEntityUtil.newInstance((DGTaskWrapper) mTaskWrapper, action);
} else if (mTaskWrapper.getRequestType() == ITaskWrapper.DG_HTTP) {
checkUtil = CheckDGEntityUtil.newInstance((DGTaskWrapper) mTaskWrapper);
checkUtil = CheckDGEntityUtil.newInstance((DGTaskWrapper) mTaskWrapper, action);
}
} else if (mTaskWrapper instanceof UTaskWrapper) {
checkUtil = CheckUEntityUtil.newInstance((UTaskWrapper) mTaskWrapper);
checkUtil = CheckUEntityUtil.newInstance((UTaskWrapper) mTaskWrapper, action);
}
return checkUtil != null && checkUtil.checkEntity();
}

View File

@@ -59,7 +59,7 @@ public interface INormalFeature {
/**
* 重新下载
*/
void reStart();
long reStart();
/**
* 保存数据

View File

@@ -38,6 +38,7 @@ public final class NormalController extends FeatureController implements INormal
*/
@Override
public void stop() {
setAction(ACTION_STOP);
if (checkConfig()) {
EventMsgUtil.getDefault()
.post(CmdHelper.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_STOP,
@@ -60,6 +61,7 @@ public final class NormalController extends FeatureController implements INormal
* @param newStart true 立即将任务恢复到执行队列中
*/
@Override public void resume(boolean newStart) {
setAction(ACTION_RESUME);
if (checkConfig()) {
StartCmd cmd =
(StartCmd) CmdHelper.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_START,
@@ -75,11 +77,7 @@ public final class NormalController extends FeatureController implements INormal
*/
@Override
public void cancel() {
if (checkConfig()) {
EventMsgUtil.getDefault()
.post(CmdHelper.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_CANCEL,
checkTaskType()));
}
cancel(false);
}
/**
@@ -87,6 +85,7 @@ public final class NormalController extends FeatureController implements INormal
*/
@Override
public void reTry() {
setAction(ACTION_RETRY);
if (checkConfig()) {
int taskType = checkTaskType();
EventMsgUtil.getDefault()
@@ -105,6 +104,7 @@ public final class NormalController extends FeatureController implements INormal
*/
@Override
public void cancel(boolean removeFile) {
setAction(ACTION_CANCEL);
if (checkConfig()) {
CancelCmd cancelCmd =
(CancelCmd) CmdHelper.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_CANCEL,
@@ -118,15 +118,19 @@ public final class NormalController extends FeatureController implements INormal
* 重新下载
*/
@Override
public void reStart() {
public long reStart() {
setAction(ACTION_RESTART);
if (checkConfig()) {
EventMsgUtil.getDefault()
.post(CmdHelper.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_RESTART,
checkTaskType()));
return getEntity().getId();
}
return -1;
}
@Override public void save() {
setAction(ACTION_SAVE);
if (!checkConfig()) {
ALog.e(TAG, "保存修改失败");
} else {

View File

@@ -16,6 +16,7 @@
package com.arialyy.aria.core.download;
import android.text.TextUtils;
import com.arialyy.aria.core.common.controller.FeatureController;
import com.arialyy.aria.core.inf.ICheckEntityUtil;
import com.arialyy.aria.core.inf.IOptionConstant;
import com.arialyy.aria.core.inf.ITargetHandler;
@@ -34,12 +35,14 @@ public class CheckDEntityUtil implements ICheckEntityUtil {
private final String TAG = CommonUtil.getClassName(getClass());
private DTaskWrapper mWrapper;
private DownloadEntity mEntity;
private int action;
public static CheckDEntityUtil newInstance(DTaskWrapper wrapper) {
return new CheckDEntityUtil(wrapper);
public static CheckDEntityUtil newInstance(DTaskWrapper wrapper, int action) {
return new CheckDEntityUtil(wrapper, action);
}
private CheckDEntityUtil(DTaskWrapper wrapper) {
private CheckDEntityUtil(DTaskWrapper wrapper, int action) {
this.action = action;
mWrapper = wrapper;
mEntity = mWrapper.getEntity();
}
@@ -80,19 +83,22 @@ public class CheckDEntityUtil implements ICheckEntityUtil {
} else {
m3U8Entity.update();
}
if (mWrapper.getRequestType() == ITaskWrapper.M3U8_VOD) {
if (mWrapper.getRequestType() == ITaskWrapper.M3U8_VOD
&& action == FeatureController.ACTION_CREATE) {
if (mEntity.getFileSize() == 0) {
ALog.w(TAG,
"由于m3u8协议的特殊性质无法有效快速获取到正确到文件长度如果你需要显示文件中长度你需要自行设置文件长度.asM3U8().asVod().setFileSize(xxx)");
}
} else if (mWrapper.getRequestType() == ITaskWrapper.M3U8_LIVE) {
} else if (mWrapper.getRequestType() == ITaskWrapper.M3U8_LIVE
&& action != FeatureController.ACTION_CANCEL) {
if (file.exists()) {
ALog.w(TAG, "对于直播来说每次下载都是一个新文件所以你需要设置新都文件路径否则Aria框架将会覆盖已下载的文件");
file.delete();
}
}
if (mWrapper.getM3U8Params().getHandler(IOptionConstant.bandWidthUrlConverter) != null
if (action != FeatureController.ACTION_CANCEL
&& mWrapper.getM3U8Params().getHandler(IOptionConstant.bandWidthUrlConverter) != null
&& bandWidth == 0) {
ALog.w(TAG, "你已经设置了码率url转换器但是没有设置码率Aria框架将采用第一个获取到的码率");
}
@@ -151,11 +157,11 @@ public class CheckDEntityUtil implements ICheckEntityUtil {
File oldFile = new File(mEntity.getFilePath());
if (oldFile.exists()) {
// 处理普通任务的重命名
RecordUtil.modifyTaskRecord(oldFile.getPath(), newFile.getPath());
RecordUtil.modifyTaskRecord(oldFile.getPath(), newFile.getPath(), mEntity.getTaskType());
ALog.i(TAG, String.format("将任务重命名为:%s", newFile.getName()));
} else if (RecordUtil.blockTaskExists(oldFile.getPath())) {
// 处理分块任务的重命名
RecordUtil.modifyTaskRecord(oldFile.getPath(), newFile.getPath());
RecordUtil.modifyTaskRecord(oldFile.getPath(), newFile.getPath(), mEntity.getTaskType());
ALog.i(TAG, String.format("将分块任务重命名为:%s", newFile.getName()));
}
}

View File

@@ -17,6 +17,7 @@ package com.arialyy.aria.core.download;
import android.text.TextUtils;
import com.arialyy.aria.core.common.RequestEnum;
import com.arialyy.aria.core.common.controller.FeatureController;
import com.arialyy.aria.core.inf.ICheckEntityUtil;
import com.arialyy.aria.core.inf.IOptionConstant;
import com.arialyy.aria.orm.DbEntity;
@@ -41,12 +42,14 @@ public class CheckDGEntityUtil implements ICheckEntityUtil {
* 是否需要修改路径
*/
private boolean needModifyPath = false;
private int action;
public static CheckDGEntityUtil newInstance(DGTaskWrapper wrapper) {
return new CheckDGEntityUtil(wrapper);
public static CheckDGEntityUtil newInstance(DGTaskWrapper wrapper, int action) {
return new CheckDGEntityUtil(wrapper, action);
}
private CheckDGEntityUtil(DGTaskWrapper wrapper) {
private CheckDGEntityUtil(DGTaskWrapper wrapper, int action) {
this.action = action;
mWrapper = wrapper;
mEntity = mWrapper.getEntity();
}
@@ -129,7 +132,9 @@ public class CheckDGEntityUtil implements ICheckEntityUtil {
return false;
}
if (!mWrapper.isUnknownSize() && mEntity.getFileSize() == 0) {
if (action != FeatureController.ACTION_CANCEL
&& !mWrapper.isUnknownSize()
&& mEntity.getFileSize() == 0) {
ALog.e(TAG, "组合任务必须设置文件文件大小,默认需要强制设置文件大小。如果无法获取到总长度,请调用#unknownSize()来标志该组合任务");
return false;
}
@@ -174,7 +179,7 @@ public class CheckDGEntityUtil implements ICheckEntityUtil {
return;
}
RecordUtil.modifyTaskRecord(oldPath, newPath);
RecordUtil.modifyTaskRecord(oldPath, newPath, mEntity.getTaskType());
entity.setFilePath(newPath);
entity.setFileName(newName);
}

View File

@@ -17,7 +17,6 @@ package com.arialyy.aria.core.download;
import android.text.TextUtils;
import com.arialyy.aria.core.FtpUrlEntity;
import com.arialyy.aria.core.common.ErrorCode;
import com.arialyy.aria.core.inf.ICheckEntityUtil;
import com.arialyy.aria.core.inf.IOptionConstant;
import com.arialyy.aria.orm.DbEntity;
@@ -28,12 +27,14 @@ public class CheckFtpDirEntityUtil implements ICheckEntityUtil {
private final String TAG = "CheckFtpDirEntityUtil";
private DGTaskWrapper mWrapper;
private DownloadGroupEntity mEntity;
private int action;
public static CheckFtpDirEntityUtil newInstance(DGTaskWrapper wrapper) {
return new CheckFtpDirEntityUtil(wrapper);
public static CheckFtpDirEntityUtil newInstance(DGTaskWrapper wrapper, int action) {
return new CheckFtpDirEntityUtil(wrapper, action);
}
private CheckFtpDirEntityUtil(DGTaskWrapper wrapper) {
private CheckFtpDirEntityUtil(DGTaskWrapper wrapper, int action) {
this.action = action;
mWrapper = wrapper;
mEntity = mWrapper.getEntity();
}

View File

@@ -15,8 +15,6 @@
*/
package com.arialyy.aria.core.download;
import androidx.annotation.CheckResult;
import androidx.annotation.NonNull;
import com.arialyy.annotations.TaskEnum;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.AriaManager;
@@ -74,8 +72,7 @@ public class DownloadReceiver extends AbsReceiver {
*
* @param url 下载地址
*/
@CheckResult
public HttpBuilderTarget load(@NonNull String url) {
public HttpBuilderTarget load(String url) {
ComponentUtil.getInstance().checkComponentExist(ComponentUtil.COMPONENT_TYPE_HTTP);
return DTargetFactory.getInstance()
.generateBuilderTarget(HttpBuilderTarget.class, url);
@@ -87,7 +84,6 @@ public class DownloadReceiver extends AbsReceiver {
* @param taskId 任务id可从{@link AbsBuilderTarget#create()}、{@link AbsBuilderTarget#add()}、{@link
* AbsEntity#getId()}读取任务id
*/
@CheckResult
public HttpNormalTarget load(long taskId) {
ComponentUtil.getInstance().checkComponentExist(ComponentUtil.COMPONENT_TYPE_HTTP);
return DTargetFactory.getInstance()
@@ -99,7 +95,6 @@ public class DownloadReceiver extends AbsReceiver {
*
* @param urls 组合任务只任务列被,如果任务组的中的下载地址改变了,则任务从新的一个任务组
*/
@CheckResult
public GroupBuilderTarget loadGroup(List<String> urls) {
ComponentUtil.getInstance().checkComponentExist(ComponentUtil.COMPONENT_TYPE_HTTP);
return DTargetFactory.getInstance().generateGroupBuilderTarget(urls);
@@ -111,7 +106,7 @@ public class DownloadReceiver extends AbsReceiver {
* @param taskId 任务id可从{@link AbsBuilderTarget#create()}、{@link AbsBuilderTarget#add()}、{@link
* * AbsEntity#getId()}读取任务id
*/
@CheckResult
public GroupNormalTarget loadGroup(long taskId) {
ComponentUtil.getInstance().checkComponentExist(ComponentUtil.COMPONENT_TYPE_HTTP);
return DTargetFactory.getInstance()
@@ -121,8 +116,8 @@ public class DownloadReceiver extends AbsReceiver {
/**
* 加载ftp单任务下载地址用于任务第一次下载如果需要控制任务停止或删除等操作请使用{@link #loadFtp(long)}
*/
@CheckResult
public FtpBuilderTarget loadFtp(@NonNull String url) {
public FtpBuilderTarget loadFtp(String url) {
ComponentUtil.getInstance().checkComponentExist(ComponentUtil.COMPONENT_TYPE_FTP);
return DTargetFactory.getInstance()
.generateBuilderTarget(FtpBuilderTarget.class, url);
@@ -134,7 +129,7 @@ public class DownloadReceiver extends AbsReceiver {
* @param taskId 任务id可从{@link AbsBuilderTarget#create()}、{@link AbsBuilderTarget#add()}、{@link
* AbsEntity#getId()}读取任务id
*/
@CheckResult
public FtpNormalTarget loadFtp(long taskId) {
ComponentUtil.getInstance().checkComponentExist(ComponentUtil.COMPONENT_TYPE_FTP);
return DTargetFactory.getInstance()
@@ -144,8 +139,8 @@ public class DownloadReceiver extends AbsReceiver {
/**
* 加载ftp文件夹下载地址用于任务第一次下载如果需要控制任务停止或删除等操作请使用{@link #loadFtpDir(long)}
*/
@CheckResult
public FtpDirBuilderTarget loadFtpDir(@NonNull String dirUrl) {
public FtpDirBuilderTarget loadFtpDir(String dirUrl) {
ComponentUtil.getInstance().checkComponentExist(ComponentUtil.COMPONENT_TYPE_FTP);
return DTargetFactory.getInstance().generateDirBuilderTarget(dirUrl);
}
@@ -156,7 +151,7 @@ public class DownloadReceiver extends AbsReceiver {
* @param taskId 任务id可从{@link AbsBuilderTarget#create()}、{@link AbsBuilderTarget#add()}、{@link
* AbsEntity#getId()}读取任务id
*/
@CheckResult
public FtpDirNormalTarget loadFtpDir(long taskId) {
ComponentUtil.getInstance().checkComponentExist(ComponentUtil.COMPONENT_TYPE_FTP);
return DTargetFactory.getInstance()

View File

@@ -33,12 +33,21 @@ public class M3U8Option<OP extends M3U8Option> extends BaseOption {
private ITsMergeHandler mergeHandler;
private IBandWidthUrlConverter bandWidthUrlConverter;
private IKeyUrlConverter keyUrlConverter;
private boolean ignoreFailureTs = false;
M3U8Option() {
super();
ComponentUtil.getInstance().checkComponentExist(ComponentUtil.COMPONENT_TYPE_M3U8);
}
/**
* 忽略下载失败的ts切片即使有失败的切片下载完成后也要合并所有切片并进入complete回调
*/
public OP ignoreFailureTs() {
this.ignoreFailureTs = true;
return (OP) this;
}
/**
* 生成m3u8索引文件
* 注意:创建索引文件,{@link #merge(boolean)}方法设置与否都不再合并文件

View File

@@ -16,9 +16,7 @@
package com.arialyy.aria.core.download.target;
import android.text.TextUtils;
import androidx.annotation.CheckResult;
import com.arialyy.aria.core.common.AbsNormalTarget;
import com.arialyy.aria.core.common.ErrorCode;
import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.event.ErrorEvent;
@@ -66,7 +64,6 @@ abstract class AbsGroupConfigHandler<TARGET extends AbsTarget> implements IConfi
*
* @return 子任务管理器
*/
@CheckResult
SubTaskManager getSubTaskManager() {
if (mSubTaskManager == null) {
mSubTaskManager = new SubTaskManager(getTaskWrapper());
@@ -89,7 +86,6 @@ abstract class AbsGroupConfigHandler<TARGET extends AbsTarget> implements IConfi
return task != null && task.isRunning();
}
@CheckResult
TARGET setDirPath(String dirPath) {
mWrapper.setDirPathTemp(dirPath);
return mTarget;

View File

@@ -15,12 +15,9 @@
*/
package com.arialyy.aria.core.download.target;
import androidx.annotation.CheckResult;
import androidx.annotation.NonNull;
import com.arialyy.aria.core.common.AbsBuilderTarget;
import com.arialyy.aria.core.common.FtpOption;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.inf.Suggest;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.util.CommonUtil;
@@ -34,13 +31,13 @@ public class FtpBuilderTarget extends AbsBuilderTarget<FtpBuilderTarget> {
mConfigHandler = new DNormalConfigHandler<>(this, -1);
mConfigHandler.setUrl(url);
getTaskWrapper().setRequestType(ITaskWrapper.D_FTP);
getEntity().setTaskType(ITaskWrapper.D_FTP);
getTaskWrapper().setNewTask(true);
}
/**
* 设置登陆、字符串编码、ftps等参数
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public FtpBuilderTarget option(FtpOption option) {
if (option == null) {
throw new NullPointerException("ftp 任务配置为空");
@@ -56,8 +53,7 @@ public class FtpBuilderTarget extends AbsBuilderTarget<FtpBuilderTarget> {
* 1、如果保存路径是该文件的保存路径/mnt/sdcard/file.zip则使用路径中的文件名file.zip
* 2、如果保存路径是文件夹路径/mnt/sdcard/则使用FTP服务器该文件的文件名
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public FtpBuilderTarget setFilePath(@NonNull String filePath) {
public FtpBuilderTarget setFilePath(String filePath) {
int lastIndex = mConfigHandler.getUrl().lastIndexOf("/");
getEntity().setFileName(mConfigHandler.getUrl().substring(lastIndex + 1));
mConfigHandler.setTempFilePath(filePath);
@@ -74,8 +70,7 @@ public class FtpBuilderTarget extends AbsBuilderTarget<FtpBuilderTarget> {
* @deprecated 使用 {@link #ignoreFilePathOccupy()}
*/
@Deprecated
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public FtpBuilderTarget setFilePath(@NonNull String filePath, boolean forceDownload) {
public FtpBuilderTarget setFilePath(String filePath, boolean forceDownload) {
mConfigHandler.setTempFilePath(filePath);
mConfigHandler.setForceDownload(forceDownload);
return this;

View File

@@ -15,11 +15,9 @@
*/
package com.arialyy.aria.core.download.target;
import androidx.annotation.CheckResult;
import com.arialyy.aria.core.common.AbsBuilderTarget;
import com.arialyy.aria.core.common.FtpOption;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.inf.Suggest;
import com.arialyy.aria.core.manager.SubTaskManager;
import com.arialyy.aria.util.CommonUtil;
@@ -57,7 +55,6 @@ public class FtpDirBuilderTarget extends AbsBuilderTarget<FtpDirBuilderTarget> {
*
* @param dirPath 任务组保存文件夹路径
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public FtpDirBuilderTarget setDirPath(String dirPath) {
return mConfigHandler.setDirPath(dirPath);
}
@@ -65,7 +62,6 @@ public class FtpDirBuilderTarget extends AbsBuilderTarget<FtpDirBuilderTarget> {
/**
* 设置任务组别名
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public FtpDirBuilderTarget setGroupAlias(String alias) {
mConfigHandler.setGroupAlias(alias);
return this;
@@ -74,7 +70,6 @@ public class FtpDirBuilderTarget extends AbsBuilderTarget<FtpDirBuilderTarget> {
/**
* 设置登陆、字符串编码、ftps等参数
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public FtpDirBuilderTarget option(FtpOption option) {
if (option == null) {
throw new NullPointerException("ftp 任务配置为空");
@@ -93,7 +88,6 @@ public class FtpDirBuilderTarget extends AbsBuilderTarget<FtpDirBuilderTarget> {
*
* @return 子任务管理器
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public SubTaskManager getSubTaskManager() {
return mConfigHandler.getSubTaskManager();
}

View File

@@ -33,11 +33,12 @@ class FtpDirConfigHandler<TARGET extends AbsTarget> extends AbsGroupConfigHandle
}
private void init() {
getTaskWrapper().setRequestType(AbsTaskWrapper.D_FTP_DIR);
getTaskWrapper().setRequestType(ITaskWrapper.D_FTP_DIR);
List<DTaskWrapper> wrappers = getTaskWrapper().getSubTaskWrapper();
if (!wrappers.isEmpty()) {
for (DTaskWrapper subWrapper : wrappers) {
subWrapper.setRequestType(ITaskWrapper.D_FTP);
subWrapper.getEntity().setTaskType(ITaskWrapper.D_FTP);
}
}
}

View File

@@ -15,11 +15,9 @@
*/
package com.arialyy.aria.core.download.target;
import androidx.annotation.CheckResult;
import com.arialyy.aria.core.common.AbsNormalTarget;
import com.arialyy.aria.core.common.FtpOption;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.inf.Suggest;
import com.arialyy.aria.core.manager.SubTaskManager;
import com.arialyy.aria.util.CommonUtil;
@@ -62,7 +60,6 @@ public class FtpDirNormalTarget extends AbsNormalTarget<FtpDirNormalTarget> {
*
* @param dirPath 任务组保存文件夹路径
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public FtpDirNormalTarget modifyDirPath(String dirPath) {
return mConfigHandler.setDirPath(dirPath);
}
@@ -70,7 +67,6 @@ public class FtpDirNormalTarget extends AbsNormalTarget<FtpDirNormalTarget> {
/**
* 设置登陆、字符串编码、ftps等参数
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public FtpDirNormalTarget option(FtpOption option) {
if (option == null) {
throw new NullPointerException("ftp 任务配置为空");
@@ -89,7 +85,6 @@ public class FtpDirNormalTarget extends AbsNormalTarget<FtpDirNormalTarget> {
*
* @return 子任务管理器
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public SubTaskManager getSubTaskManager() {
return mConfigHandler.getSubTaskManager();
}

View File

@@ -15,12 +15,9 @@
*/
package com.arialyy.aria.core.download.target;
import androidx.annotation.CheckResult;
import androidx.annotation.NonNull;
import com.arialyy.aria.core.common.AbsNormalTarget;
import com.arialyy.aria.core.common.FtpOption;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.inf.Suggest;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.util.CommonUtil;
@@ -40,7 +37,6 @@ public class FtpNormalTarget extends AbsNormalTarget<FtpNormalTarget> {
/**
* 设置登陆、字符串编码、ftps等参数
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public FtpNormalTarget option(FtpOption option) {
if (option == null) {
throw new NullPointerException("ftp 任务配置为空");
@@ -56,8 +52,7 @@ public class FtpNormalTarget extends AbsNormalTarget<FtpNormalTarget> {
* 1、如果保存路径是该文件的保存路径/mnt/sdcard/file.zip则使用路径中的文件名file.zip
* 2、如果保存路径是文件夹路径/mnt/sdcard/则使用FTP服务器该文件的文件名
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public FtpNormalTarget modifyFilePath(@NonNull String filePath) {
public FtpNormalTarget modifyFilePath(String filePath) {
int lastIndex = mConfigHandler.getUrl().lastIndexOf("/");
getEntity().setFileName(mConfigHandler.getUrl().substring(lastIndex + 1));
mConfigHandler.setTempFilePath(filePath);
@@ -67,7 +62,6 @@ public class FtpNormalTarget extends AbsNormalTarget<FtpNormalTarget> {
/**
* 更新下载地址
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public FtpNormalTarget updateUrl(String newUrl) {
return mConfigHandler.updateUrl(newUrl);
}

View File

@@ -15,11 +15,9 @@
*/
package com.arialyy.aria.core.download.target;
import androidx.annotation.CheckResult;
import com.arialyy.aria.core.common.AbsBuilderTarget;
import com.arialyy.aria.core.common.HttpOption;
import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.inf.Suggest;
import com.arialyy.aria.core.manager.SubTaskManager;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.util.ALog;
@@ -42,7 +40,6 @@ public class GroupBuilderTarget extends AbsBuilderTarget<GroupBuilderTarget> {
/**
* 设置http请求参数header等信息
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public GroupBuilderTarget option(HttpOption option) {
if (option == null) {
throw new NullPointerException("任务配置为空");
@@ -59,7 +56,6 @@ public class GroupBuilderTarget extends AbsBuilderTarget<GroupBuilderTarget> {
*
* @param fileSize 任务组总大小
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public GroupBuilderTarget setFileSize(long fileSize) {
if (fileSize <= 0) {
ALog.e(TAG, "文件大小不能小于 0");
@@ -78,7 +74,6 @@ public class GroupBuilderTarget extends AbsBuilderTarget<GroupBuilderTarget> {
* 2、如果你的知道组合任务的总长度请使用{@link #setFileSize(long)}设置组合任务的长度。
* 3、由于网络或其它原因的存在这种方式获取的组合任务大小有可能是不准确的。
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public GroupBuilderTarget unknownSize() {
((DGTaskWrapper) getTaskWrapper()).setUnknownSize(true);
return this;
@@ -89,7 +84,6 @@ public class GroupBuilderTarget extends AbsBuilderTarget<GroupBuilderTarget> {
*
* @return 子任务管理器
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public SubTaskManager getSubTaskManager() {
return mConfigHandler.getSubTaskManager();
}
@@ -99,7 +93,6 @@ public class GroupBuilderTarget extends AbsBuilderTarget<GroupBuilderTarget> {
*
* @deprecated {@link #setSubFileName(List)} 请使用该api
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
@Deprecated public GroupBuilderTarget setSubTaskFileName(List<String> subTaskFileName) {
return setSubFileName(subTaskFileName);
}
@@ -107,7 +100,6 @@ public class GroupBuilderTarget extends AbsBuilderTarget<GroupBuilderTarget> {
/**
* 设置任务组别名
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public GroupBuilderTarget setGroupAlias(String alias) {
mConfigHandler.setGroupAlias(alias);
return this;
@@ -132,7 +124,6 @@ public class GroupBuilderTarget extends AbsBuilderTarget<GroupBuilderTarget> {
*
* @param dirPath 任务组保存文件夹路径
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public GroupBuilderTarget setDirPath(String dirPath) {
return mConfigHandler.setDirPath(dirPath);
}
@@ -140,7 +131,6 @@ public class GroupBuilderTarget extends AbsBuilderTarget<GroupBuilderTarget> {
/**
* 设置子任务文件名,该方法必须在{@link #setDirPath(String)}之后调用,否则不生效
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public GroupBuilderTarget setSubFileName(List<String> subTaskFileName) {
return mConfigHandler.setSubFileName(subTaskFileName);
}

View File

@@ -15,10 +15,8 @@
*/
package com.arialyy.aria.core.download.target;
import androidx.annotation.CheckResult;
import com.arialyy.aria.core.common.AbsNormalTarget;
import com.arialyy.aria.core.common.HttpOption;
import com.arialyy.aria.core.inf.Suggest;
import com.arialyy.aria.core.manager.SubTaskManager;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import java.util.List;
@@ -39,7 +37,6 @@ public class GroupNormalTarget extends AbsNormalTarget<GroupNormalTarget> {
/**
* 设置http请求参数header等信息
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public GroupNormalTarget option(HttpOption option) {
if (option == null) {
throw new NullPointerException("任务配置为空");
@@ -53,7 +50,6 @@ public class GroupNormalTarget extends AbsNormalTarget<GroupNormalTarget> {
*
* @return 子任务管理器
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public SubTaskManager getSubTaskManager() {
return mConfigHandler.getSubTaskManager();
}
@@ -61,7 +57,6 @@ public class GroupNormalTarget extends AbsNormalTarget<GroupNormalTarget> {
/**
* 设置任务组别名
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public GroupNormalTarget setGroupAlias(String alias) {
mConfigHandler.setGroupAlias(alias);
return this;
@@ -72,7 +67,6 @@ public class GroupNormalTarget extends AbsNormalTarget<GroupNormalTarget> {
*
* @param urls 新的组合任务下载地址列表
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public GroupNormalTarget updateUrls(List<String> urls) {
return mConfigHandler.updateUrls(urls);
}
@@ -96,7 +90,6 @@ public class GroupNormalTarget extends AbsNormalTarget<GroupNormalTarget> {
*
* @param dirPath 任务组保存文件夹路径
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public GroupNormalTarget modifyDirPath(String dirPath) {
return mConfigHandler.setDirPath(dirPath);
}
@@ -104,7 +97,6 @@ public class GroupNormalTarget extends AbsNormalTarget<GroupNormalTarget> {
/**
* 更新子任务文件名,该方法必须在{@link #modifyDirPath(String)}之后调用,否则不生效
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public GroupNormalTarget modifySubFileName(List<String> subTaskFileName) {
return mConfigHandler.setSubFileName(subTaskFileName);
}

View File

@@ -15,14 +15,12 @@
*/
package com.arialyy.aria.core.download.target;
import androidx.annotation.CheckResult;
import androidx.annotation.NonNull;
import com.arialyy.aria.core.common.AbsBuilderTarget;
import com.arialyy.aria.core.common.HttpOption;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.m3u8.M3U8LiveOption;
import com.arialyy.aria.core.download.m3u8.M3U8VodOption;
import com.arialyy.aria.core.inf.Suggest;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
@@ -35,9 +33,9 @@ public class HttpBuilderTarget extends AbsBuilderTarget<HttpBuilderTarget> {
mConfigHandler.setUrl(url);
getTaskWrapper().setRequestType(ITaskWrapper.D_HTTP);
getTaskWrapper().setNewTask(true);
((DownloadEntity)getEntity()).setTaskType(ITaskWrapper.D_HTTP);
}
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public HttpBuilderTarget m3u8VodOption(M3U8VodOption m3U8VodOption) {
if (m3U8VodOption == null) {
throw new NullPointerException("m3u8任务设置为空");
@@ -48,7 +46,6 @@ public class HttpBuilderTarget extends AbsBuilderTarget<HttpBuilderTarget> {
return this;
}
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public HttpBuilderTarget m3u8LiveOption(M3U8LiveOption m3U8LiveOption) {
if (m3U8LiveOption == null) {
throw new NullPointerException("m3u8任务设置为空");
@@ -61,7 +58,6 @@ public class HttpBuilderTarget extends AbsBuilderTarget<HttpBuilderTarget> {
/**
* 设置http请求参数header等信息
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public HttpBuilderTarget option(HttpOption option) {
if (option == null) {
throw new NullPointerException("任务配置为空");
@@ -77,8 +73,7 @@ public class HttpBuilderTarget extends AbsBuilderTarget<HttpBuilderTarget> {
*
* @param filePath 路径必须为文件路径,不能为文件夹路径
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public HttpBuilderTarget setFilePath(@NonNull String filePath) {
public HttpBuilderTarget setFilePath(String filePath) {
mConfigHandler.setTempFilePath(filePath);
return this;
}
@@ -93,8 +88,7 @@ public class HttpBuilderTarget extends AbsBuilderTarget<HttpBuilderTarget> {
* @deprecated 使用 {@link #ignoreFilePathOccupy()}
*/
@Deprecated
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public HttpBuilderTarget setFilePath(@NonNull String filePath, boolean forceDownload) {
public HttpBuilderTarget setFilePath(String filePath, boolean forceDownload) {
mConfigHandler.setTempFilePath(filePath);
mConfigHandler.setForceDownload(forceDownload);
return this;

View File

@@ -15,10 +15,10 @@
*/
package com.arialyy.aria.core.download.target;
import androidx.annotation.CheckResult;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.inf.AbsTarget;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
@@ -59,6 +59,7 @@ class HttpGroupConfigHandler<TARGET extends AbsTarget> extends AbsGroupConfigHan
List<DownloadEntity> subEntities = DbDataHelper.createHttpSubTask(groupHash, mUrls);
List<DTaskWrapper> wrappers = new ArrayList<>();
for (DownloadEntity subEntity : subEntities) {
subEntity.setTaskType(ITaskWrapper.D_HTTP);
wrappers.add(new DTaskWrapper(subEntity));
}
getEntity().setUrls(urls);
@@ -69,7 +70,6 @@ class HttpGroupConfigHandler<TARGET extends AbsTarget> extends AbsGroupConfigHan
/**
* 设置子任务文件名,该方法必须在{@link #setDirPath(String)}之后调用,否则不生效
*/
@CheckResult
TARGET setSubFileName(List<String> subTaskFileName) {
if (subTaskFileName == null || subTaskFileName.isEmpty()) {
ALog.w(TAG, "修改子任务的文件名失败列表为null");
@@ -90,7 +90,6 @@ class HttpGroupConfigHandler<TARGET extends AbsTarget> extends AbsGroupConfigHan
*
* @param urls 新的组合任务下载地址列表
*/
@CheckResult
TARGET updateUrls(List<String> urls) {
if (urls == null || urls.isEmpty()) {
throw new NullPointerException("下载地址列表为空");

View File

@@ -15,14 +15,12 @@
*/
package com.arialyy.aria.core.download.target;
import androidx.annotation.CheckResult;
import com.arialyy.aria.core.common.AbsNormalTarget;
import com.arialyy.aria.core.common.HttpOption;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.m3u8.M3U8LiveOption;
import com.arialyy.aria.core.download.m3u8.M3U8VodOption;
import com.arialyy.aria.core.inf.Suggest;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
/**
@@ -38,7 +36,6 @@ public class HttpNormalTarget extends AbsNormalTarget<HttpNormalTarget> {
getTaskWrapper().setNewTask(false);
}
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public M3U8NormalTarget m3u8VodOption(M3U8VodOption m3U8VodOption) {
if (m3U8VodOption == null) {
throw new NullPointerException("m3u8任务设置为空");
@@ -49,12 +46,10 @@ public class HttpNormalTarget extends AbsNormalTarget<HttpNormalTarget> {
return new M3U8NormalTarget((DTaskWrapper) getTaskWrapper());
}
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public M3U8NormalTarget m3u8VodOption() {
return new M3U8NormalTarget((DTaskWrapper) getTaskWrapper());
}
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public HttpNormalTarget m3u8LiveOption(M3U8LiveOption m3U8LiveOption) {
if (m3U8LiveOption == null) {
throw new NullPointerException("m3u8任务设置为空");
@@ -67,7 +62,6 @@ public class HttpNormalTarget extends AbsNormalTarget<HttpNormalTarget> {
/**
* 设置http请求参数header等信息
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public HttpNormalTarget option(HttpOption option) {
if (option == null) {
throw new NullPointerException("任务配置为空");
@@ -81,7 +75,6 @@ public class HttpNormalTarget extends AbsNormalTarget<HttpNormalTarget> {
* 如:原文件路径 /mnt/sdcard/test.zip
* 如果需要将test.zip改为game.zip只需要重新设置文件路径为/mnt/sdcard/game.zip
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public HttpNormalTarget modifyFilePath(String filePath) {
mConfigHandler.setTempFilePath(filePath);
return this;
@@ -97,7 +90,6 @@ public class HttpNormalTarget extends AbsNormalTarget<HttpNormalTarget> {
/**
* 更新下载地址
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public HttpNormalTarget updateUrl(String newUrl) {
return mConfigHandler.updateUrl(newUrl);
}

View File

@@ -15,11 +15,8 @@
*/
package com.arialyy.aria.core.download.target;
import androidx.annotation.CheckResult;
import androidx.annotation.NonNull;
import com.arialyy.aria.core.common.AbsBuilderTarget;
import com.arialyy.aria.core.inf.Suggest;
import com.arialyy.aria.core.download.tcp.TcpDelegate;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
/**
@@ -33,6 +30,7 @@ public class TcpBuilderTarget extends AbsBuilderTarget<TcpBuilderTarget> {
TcpBuilderTarget(String ip, int port) {
mConfigHandler = new DNormalConfigHandler<>(this, -1);
getTaskWrapper().setRequestType(ITaskWrapper.D_TCP);
((DownloadEntity) getEntity()).setTaskType(ITaskWrapper.D_TCP);
getTaskWrapper().setNewTask(true);
}
//
@@ -51,10 +49,8 @@ public class TcpBuilderTarget extends AbsBuilderTarget<TcpBuilderTarget> {
*
* @param filePath 路径必须为文件路径,不能为文件夹路径
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public TcpBuilderTarget setFilePath(@NonNull String filePath) {
public TcpBuilderTarget setFilePath(String filePath) {
mConfigHandler.setTempFilePath(filePath);
return this;
}
}

View File

@@ -16,11 +16,10 @@
package com.arialyy.aria.core.inf;
import android.text.TextUtils;
import androidx.annotation.CheckResult;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.common.controller.BuilderController;
import com.arialyy.aria.core.common.controller.NormalController;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
@@ -61,7 +60,6 @@ public abstract class AbsTarget<TARGET extends AbsTarget> {
*
* @param str 扩展数据
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public TARGET setExtendField(String str) {
if (TextUtils.isEmpty(str)) return (TARGET) this;
if (TextUtils.isEmpty(mEntity.getStr()) || !mEntity.getStr().equals(str)) {
@@ -80,7 +78,6 @@ public abstract class AbsTarget<TARGET extends AbsTarget> {
* BuilderController#add()}
* 等操作任务的方法,那么你需要调用{@link NormalController#save()}才能将修改保存到数据库
*/
@CheckResult(suggest = "after use #create()、#stop()、#cancel()、#resume()、#save()?")
public TARGET resetState() {
getTaskWrapper().getEntity().setState(IEntity.STATE_WAIT);
getTaskWrapper().setRefreshInfo(true);

View File

@@ -49,5 +49,5 @@ public interface IReceiver {
*
* @return {@link ReceiverType}
*/
@ReceiverType String getType();
String getType();
}

View File

@@ -15,19 +15,10 @@
*/
package com.arialyy.aria.core.inf;
import androidx.annotation.StringDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* {@link AbsReceiver}类型
*/
@StringDef({
ReceiverType.DOWNLOAD,
ReceiverType.UPLOAD,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ReceiverType {
public interface ReceiverType {
String DOWNLOAD = "download";
String UPLOAD = "upload";
}

View File

@@ -20,6 +20,7 @@ import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.IRecordHandler;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import java.io.File;
/**
@@ -71,7 +72,7 @@ class DTaskWrapperFactory implements INormalTEFactory<DownloadEntity, DTaskWrapp
if (!entity.isComplete()) {
TaskRecord record =
TaskRecord.findFirst(TaskRecord.class, "filePath=?", entity.getDownloadPath());
TaskRecord.findFirst(TaskRecord.class, "filePath=?", entity.getFilePath());
if (record == null) {
resetEntity(entity);
} else {
@@ -87,7 +88,7 @@ class DTaskWrapperFactory implements INormalTEFactory<DownloadEntity, DTaskWrapp
resetEntity(entity);
}
} else if (!file.exists()
&& record.taskType != TaskRecord.TYPE_M3U8_VOD) { // 非分块文件需要判断文件是否存在
&& record.taskType != ITaskWrapper.M3U8_VOD) { // 非分块文件需要判断文件是否存在
resetEntity(entity);
}
}

View File

@@ -15,11 +15,11 @@
*/
package com.arialyy.aria.core.manager;
import androidx.collection.LruCache;
import android.util.LruCache;
import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.upload.UTaskWrapper;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import java.util.concurrent.locks.Lock;

View File

@@ -16,10 +16,6 @@
package com.arialyy.aria.core.queue;
import com.arialyy.aria.core.task.DownloadGroupTask;
import com.arialyy.aria.core.task.DownloadTask;
import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.manager.TaskWrapperManager;
@@ -29,7 +25,11 @@ import com.arialyy.aria.core.queue.pool.BaseExecutePool;
import com.arialyy.aria.core.queue.pool.DGLoadSharePool;
import com.arialyy.aria.core.queue.pool.DLoadSharePool;
import com.arialyy.aria.core.queue.pool.UploadSharePool;
import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.core.task.DownloadGroupTask;
import com.arialyy.aria.core.task.DownloadTask;
import com.arialyy.aria.core.task.UploadTask;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.util.ALog;
/**
@@ -213,6 +213,10 @@ public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends Ab
}
@Override public void startTask(TASK task) {
startTask(task, TaskSchedulerType.TYPE_DEFAULT);
}
@Override public void startTask(TASK task, int action) {
if (task == null) {
ALog.w(TAG, "create fail, task is null");
}
@@ -223,7 +227,7 @@ public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends Ab
mCachePool.removeTask(task);
mExecutePool.putTask(task);
task.getTaskWrapper().getEntity().setFailNum(0);
task.start();
task.start(action);
}
@Override public void stopTask(TASK task) {
@@ -312,7 +316,11 @@ public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends Ab
}
@Override public void cancelTask(TASK task) {
task.cancel();
cancelTask(task, TaskSchedulerType.TYPE_DEFAULT);
}
@Override public void cancelTask(TASK task, int action) {
task.cancel(action);
}
@Override public TASK getNextTask() {

View File

@@ -17,13 +17,14 @@
package com.arialyy.aria.core.queue;
import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.task.DownloadGroupTask;
import com.arialyy.aria.core.task.DownloadTask;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.task.ITask;
import com.arialyy.aria.core.task.UploadTask;
import com.arialyy.aria.core.upload.UTaskWrapper;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
/**
* Created by lyy on 2016/8/16. 任务功能接口
@@ -65,6 +66,13 @@ public interface ITaskQueue<TASK extends ITask, TASK_WRAPPER extends AbsTaskWrap
*/
void startTask(TASK task);
/**
* 开始任务
*
* @param action {@link TaskSchedulerType}
*/
void startTask(TASK task, int action);
/**
* 停止任务
*
@@ -73,12 +81,19 @@ public interface ITaskQueue<TASK extends ITask, TASK_WRAPPER extends AbsTaskWrap
void stopTask(TASK task);
/**
* 取消下载任务
* 取消任务
*
* @param task {@link DownloadTask}、{@link UploadTask}、{@link DownloadGroupTask}
*/
void cancelTask(TASK task);
/**
* 取消任务
*
* @param action {@link TaskSchedulerType}
*/
void cancelTask(TASK task, int action);
/**
* 通过key从队列中删除任务
*

View File

@@ -25,12 +25,14 @@ public class CheckUEntityUtil implements ICheckEntityUtil {
private final String TAG = "CheckUEntityUtil";
private UTaskWrapper mWrapper;
private UploadEntity mEntity;
private int action;
public static CheckUEntityUtil newInstance(UTaskWrapper wrapper) {
return new CheckUEntityUtil(wrapper);
public static CheckUEntityUtil newInstance(UTaskWrapper wrapper, int action) {
return new CheckUEntityUtil(wrapper, action);
}
private CheckUEntityUtil(UTaskWrapper wrapper) {
private CheckUEntityUtil(UTaskWrapper wrapper, int action) {
this.action = action;
mWrapper = wrapper;
mEntity = mWrapper.getEntity();
}

View File

@@ -16,8 +16,6 @@
package com.arialyy.aria.core.upload;
import android.text.TextUtils;
import androidx.annotation.CheckResult;
import androidx.annotation.NonNull;
import com.arialyy.annotations.TaskEnum;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.AriaManager;
@@ -68,8 +66,8 @@ public class UploadReceiver extends AbsReceiver {
*
* @param filePath 文件路径
*/
@CheckResult
public HttpBuilderTarget load(@NonNull String filePath) {
public HttpBuilderTarget load(String filePath) {
ComponentUtil.getInstance().checkComponentExist(ComponentUtil.COMPONENT_TYPE_HTTP);
CheckUtil.checkUploadPathIsEmpty(filePath);
return UTargetFactory.getInstance()
@@ -82,7 +80,7 @@ public class UploadReceiver extends AbsReceiver {
* @param taskId 任务id可从{@link AbsBuilderTarget#create()}、{@link AbsBuilderTarget#add()}、{@link
* AbsEntity#getId()}读取任务id
*/
@CheckResult
public HttpNormalTarget load(long taskId) {
ComponentUtil.getInstance().checkComponentExist(ComponentUtil.COMPONENT_TYPE_HTTP);
return UTargetFactory.getInstance()
@@ -94,8 +92,8 @@ public class UploadReceiver extends AbsReceiver {
*
* @param filePath 文件路径
*/
@CheckResult
public FtpBuilderTarget loadFtp(@NonNull String filePath) {
public FtpBuilderTarget loadFtp(String filePath) {
ComponentUtil.getInstance().checkComponentExist(ComponentUtil.COMPONENT_TYPE_FTP);
CheckUtil.checkUploadPathIsEmpty(filePath);
return UTargetFactory.getInstance()
@@ -108,7 +106,7 @@ public class UploadReceiver extends AbsReceiver {
* @param taskId 任务id可从{@link AbsBuilderTarget#create()}、{@link AbsBuilderTarget#add()}、{@link
* AbsEntity#getId()}读取任务id
*/
@CheckResult
public FtpNormalTarget loadFtp(long taskId) {
ComponentUtil.getInstance().checkComponentExist(ComponentUtil.COMPONENT_TYPE_FTP);
return UTargetFactory.getInstance()

View File

@@ -15,11 +15,9 @@
*/
package com.arialyy.aria.core.upload.target;
import androidx.annotation.CheckResult;
import com.arialyy.aria.core.common.AbsBuilderTarget;
import com.arialyy.aria.core.common.FtpOption;
import com.arialyy.aria.core.inf.Suggest;
import com.arialyy.aria.core.upload.UTaskWrapper;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.util.CommonUtil;
@@ -35,6 +33,7 @@ public class FtpBuilderTarget extends AbsBuilderTarget<FtpBuilderTarget> {
mConfigHandler = new UNormalConfigHandler<>(this, -1);
mConfigHandler.setFilePath(filePath);
getTaskWrapper().setRequestType(ITaskWrapper.U_FTP);
((UploadEntity)getEntity()).setTaskType(ITaskWrapper.U_FTP);
getTaskWrapper().setNewTask(true);
}
@@ -43,7 +42,6 @@ public class FtpBuilderTarget extends AbsBuilderTarget<FtpBuilderTarget> {
*
* @param tempUrl 上传路径
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public FtpBuilderTarget setUploadUrl(String tempUrl) {
url = tempUrl;
mConfigHandler.setTempUrl(tempUrl);
@@ -64,7 +62,6 @@ public class FtpBuilderTarget extends AbsBuilderTarget<FtpBuilderTarget> {
/**
* 设置登陆、字符串编码、ftps等参数
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public FtpBuilderTarget option(FtpOption option) {
if (option == null) {
throw new NullPointerException("ftp 任务配置为空");

View File

@@ -15,10 +15,8 @@
*/
package com.arialyy.aria.core.upload.target;
import androidx.annotation.CheckResult;
import com.arialyy.aria.core.common.AbsNormalTarget;
import com.arialyy.aria.core.common.FtpOption;
import com.arialyy.aria.core.inf.Suggest;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.util.CommonUtil;
@@ -39,7 +37,6 @@ public class FtpNormalTarget extends AbsNormalTarget<FtpNormalTarget> {
/**
* 设置登陆、字符串编码、ftps等参数
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public FtpNormalTarget option(FtpOption option) {
if (option == null) {
throw new NullPointerException("ftp 任务配置为空");

View File

@@ -15,11 +15,10 @@
*/
package com.arialyy.aria.core.upload.target;
import androidx.annotation.CheckResult;
import com.arialyy.aria.core.common.AbsBuilderTarget;
import com.arialyy.aria.core.common.HttpOption;
import com.arialyy.aria.core.inf.Suggest;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
/**
* Created by lyy on 2017/2/28.
@@ -33,7 +32,8 @@ public class HttpBuilderTarget extends AbsBuilderTarget<HttpBuilderTarget> {
mConfigHandler.setFilePath(filePath);
//http暂时不支持断点上传
getTaskWrapper().setSupportBP(false);
getTaskWrapper().setRequestType(AbsTaskWrapper.U_HTTP);
getTaskWrapper().setRequestType(ITaskWrapper.U_HTTP);
((UploadEntity) getEntity()).setTaskType(ITaskWrapper.U_HTTP);
getTaskWrapper().setNewTask(true);
}
@@ -42,7 +42,6 @@ public class HttpBuilderTarget extends AbsBuilderTarget<HttpBuilderTarget> {
*
* @param tempUrl 上传路径
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public HttpBuilderTarget setUploadUrl(String tempUrl) {
mConfigHandler.setTempUrl(tempUrl);
return this;
@@ -51,7 +50,6 @@ public class HttpBuilderTarget extends AbsBuilderTarget<HttpBuilderTarget> {
/**
* 设置http请求参数header等信息
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public HttpBuilderTarget option(HttpOption option) {
if (option == null) {

View File

@@ -15,10 +15,8 @@
*/
package com.arialyy.aria.core.upload.target;
import androidx.annotation.CheckResult;
import com.arialyy.aria.core.common.AbsNormalTarget;
import com.arialyy.aria.core.common.HttpOption;
import com.arialyy.aria.core.inf.Suggest;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.util.ALog;
@@ -41,7 +39,6 @@ public class HttpNormalTarget extends AbsNormalTarget<HttpNormalTarget> {
*
* @param tempUrl 上传路径
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public HttpNormalTarget setUploadUrl(String tempUrl) {
mConfigHandler.setTempUrl(tempUrl);
return this;
@@ -50,7 +47,6 @@ public class HttpNormalTarget extends AbsNormalTarget<HttpNormalTarget> {
/**
* 设置http请求参数header等信息
*/
@CheckResult(suggest = Suggest.TASK_CONTROLLER)
public HttpNormalTarget option(HttpOption option) {
if (option == null) {
throw new NullPointerException("任务配置为空");

View File

@@ -1,4 +1,17 @@
## 开发日志
+ v_3.8 (2019/12/17)
- 移除androidx和support的依赖现在无论是哪个版本的appcompat包都可以使用本框架
- 修复一个在xml中使用fragment导致的内存泄漏问题
- m3u8协议的key信息增加了`keyFormat``keyFormatVersion`字段
- m3u8增加了`ignoreFailureTs`方法忽略下载失败的ts切片
- 修复在dialogFragment的`onCreateDialog()`注册导致的注解不生效问题
- 修复组合任务初始化失败时,无法删除的问题
- 修复`reStart()`后,无法停止的问题
- ftp增加主动模式开启主动模式https://aria.laoyuyu.me/aria_doc/api/ftp_params.html
- 修复ftp服务器无法响应`abor`命令导致的无法停止上传的问题 https://github.com/AriaLyy/Aria/issues/564
- 修复ftp上传时服务器有长度为0的文件导致上传失败的问题
- 修复下载任务和上传任务的文件路径是同一个时,导致的记录混乱问题
- 优化提示
+ v_3.7.10 (2019/12/3)
- fix bug https://github.com/AriaLyy/Aria/issues/543#issuecomment-559733124
- fix bug https://github.com/AriaLyy/Aria/issues/542

View File

@@ -25,8 +25,6 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "androidx.appcompat:appcompat:${rootProject.ext.XAppcompatVersion}"
implementation project(path: ':PublicComponent')
}

View File

@@ -16,8 +16,13 @@
*/
package aria.apache.commons.net.ftp;
import aria.apache.commons.net.MalformedServerReplyException;
import aria.apache.commons.net.SocketClient;
import aria.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory;
import aria.apache.commons.net.ftp.parser.FTPFileEntryParserFactory;
import aria.apache.commons.net.ftp.parser.MLSxEntryParser;
import aria.apache.commons.net.ftp.parser.ParserInitializationException;
import aria.apache.commons.net.io.CRLFLineReader;
import aria.apache.commons.net.io.CopyStreamAdapter;
import aria.apache.commons.net.io.CopyStreamEvent;
import aria.apache.commons.net.io.CopyStreamException;
@@ -53,12 +58,6 @@ import java.util.Properties;
import java.util.Random;
import java.util.Set;
import aria.apache.commons.net.MalformedServerReplyException;
import aria.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory;
import aria.apache.commons.net.ftp.parser.FTPFileEntryParserFactory;
import aria.apache.commons.net.ftp.parser.MLSxEntryParser;
import aria.apache.commons.net.io.CRLFLineReader;
/**
* FTPClient encapsulates all the functionality necessary to store and
* retrieve files from an FTP server. This class takes care of all
@@ -2263,8 +2262,8 @@ public class FTPClient extends FTP implements Configurable {
}
/*
* Create the feature map if not already created.
*/
* Create the feature map if not already created.
*/
private boolean initFeatureMap() throws IOException {
if (__featuresMap == null) {
// Don't create map here, because next line may throw exception
@@ -2375,10 +2374,10 @@ public class FTPClient extends FTP implements Configurable {
boolean success = FTPReply.isPositiveCompletion(sendCommand(FTPCmd.MLST, pathname));
if (success) {
String reply = getReplyStrings()[1];
/* check the response makes sense.
* Must have space before fact(s) and between fact(s) and filename
* Fact(s) can be absent, so at least 3 chars are needed.
*/
/* check the response makes sense.
* Must have space before fact(s) and between fact(s) and filename
* Fact(s) can be absent, so at least 3 chars are needed.
*/
if (reply.length() < 3 || reply.charAt(0) != ' ') {
throw new MalformedServerReplyException("Invalid server reply (MLST): '" + reply + "'");
}

View File

@@ -27,24 +27,21 @@ import aria.apache.commons.net.ftp.FTPSClient;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.FtpUrlEntity;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.common.FtpConnectionMode;
import com.arialyy.aria.core.inf.OnFileInfoCallback;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.exception.AriaIOException;
import com.arialyy.aria.exception.BaseException;
import com.arialyy.aria.exception.FileNotFoundException;
import com.arialyy.aria.exception.TaskException;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.Regular;
import com.arialyy.aria.util.SSLContextUtil;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.net.ssl.SSLContext;
/**
@@ -53,7 +50,7 @@ import javax.net.ssl.SSLContext;
public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER extends AbsTaskWrapper<ENTITY>>
implements Runnable {
private final String TAG = CommonUtil.getClassName(getClass());
protected final String TAG = CommonUtil.getClassName(getClass());
protected ENTITY mEntity;
protected TASK_WRAPPER mTaskWrapper;
protected FtpTaskOption mTaskOption;
@@ -117,16 +114,16 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
}
closeClient(client);
failDownload(new FileNotFoundException(TAG,
failDownload(client,
String.format("文件不存在url: %s, remotePath%s", mTaskOption.getUrlEntity().url,
remotePath)), false);
remotePath), null, false);
return;
}
// 处理拦截功能
if (!onInterceptor(client, files)) {
closeClient(client);
ALog.d(TAG, "拦截器处理完成任务,任务将不再执行");
ALog.d(TAG, "拦截器处理完成任务");
return;
}
@@ -139,9 +136,7 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
mTaskWrapper.setNewTask(true);
} else {
closeClient(client);
failDownload(new AriaIOException(TAG,
String.format("获取文件信息错误url: %s, errorCode%s, errorMsg%s",
mTaskOption.getUrlEntity().url, reply, client.getReplyString())), true);
failDownload(client, "获取文件信息错误url: " + mTaskOption.getUrlEntity().url, null, true);
return;
}
}
@@ -152,9 +147,11 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
onPreComplete(reply);
mEntity.update();
} catch (IOException e) {
failDownload(new AriaIOException(TAG,
String.format("FTP错误信息code%smsg%s", client.getReplyCode(), client.getReplyString()),
e), true);
e.printStackTrace();
failDownload(client, "FTP错误信息", e, true);
} catch (InterruptedException e) {
e.printStackTrace();
failDownload(client, "FTP错误信息", e, true);
} finally {
closeClient(client);
}
@@ -191,88 +188,83 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
/**
* 创建FTP客户端
*/
private FTPClient createFtpClient() {
private FTPClient createFtpClient() throws IOException, InterruptedException {
FTPClient client = null;
final FtpUrlEntity urlEntity = mTaskOption.getUrlEntity();
try {
Pattern p = Pattern.compile(Regular.REG_IP_V4);
Matcher m = p.matcher(urlEntity.hostName);
if (m.find() && m.groupCount() > 0) {
client = newInstanceClient(urlEntity);
client.setConnectTimeout(mConnectTimeOut); // 连接10s超时
InetAddress ip = InetAddress.getByName(urlEntity.hostName);
if (CheckUtil.checkIp(urlEntity.hostName)) {
client = newInstanceClient(urlEntity);
client.setConnectTimeout(mConnectTimeOut); // 连接10s超时
InetAddress ip = InetAddress.getByName(urlEntity.hostName);
client = connect(client, new InetAddress[] { ip }, 0, Integer.parseInt(urlEntity.port));
mTaskOption.getUrlEntity().validAddr = ip;
} else {
DNSQueryThread dnsThread = new DNSQueryThread(urlEntity.hostName);
dnsThread.start();
dnsThread.join(mConnectTimeOut);
InetAddress[] ips = dnsThread.getIps();
client = connect(newInstanceClient(urlEntity), ips, 0, Integer.parseInt(urlEntity.port));
}
if (client == null) {
failDownload(new AriaIOException(TAG,
String.format("链接失败, url: %s", mTaskOption.getUrlEntity().url)), false);
return null;
}
boolean loginSuccess = true;
if (urlEntity.needLogin) {
try {
if (TextUtils.isEmpty(urlEntity.account)) {
loginSuccess = client.login(urlEntity.user, urlEntity.password);
} else {
loginSuccess = client.login(urlEntity.user, urlEntity.password, urlEntity.account);
}
} catch (IOException e) {
ALog.e(TAG,
new TaskException(TAG, String.format("登录失败,错误码为:%s msg%s", client.getReplyCode(),
client.getReplyString()), e));
return null;
}
}
if (!loginSuccess) {
failDownload(
new TaskException(TAG, String.format("登录失败,错误码为:%s msg%s", client.getReplyCode(),
client.getReplyString())),
false);
client.disconnect();
return null;
}
int reply = client.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
client.disconnect();
failDownload(new AriaIOException(TAG,
String.format("无法连接到ftp服务器filePath: %s, url: %s, errorCode: %s, errorMsg%s",
mEntity.getKey(), mTaskOption.getUrlEntity().url, reply,
client.getReplyString())),
true);
return null;
}
// 开启服务器对UTF-8的支持如果服务器支持就用UTF-8编码
charSet = "UTF-8";
reply = client.sendCommand("OPTS UTF8", "ON");
if (reply != FTPReply.COMMAND_IS_SUPERFLUOUS) {
ALog.i(TAG, "D_FTP 服务器不支持开启UTF8编码尝试使用Aria手动设置的编码");
if (!TextUtils.isEmpty(mTaskOption.getCharSet())) {
charSet = mTaskOption.getCharSet();
}
}
client.setControlEncoding(charSet);
client.setDataTimeout(10 * 1000);
client.enterLocalPassiveMode();
client.setFileType(FTP.BINARY_FILE_TYPE);
} catch (IOException e) {
closeClient(client);
e.printStackTrace();
} catch (InterruptedException e) {
closeClient(client);
e.printStackTrace();
client = connect(client, new InetAddress[] { ip }, 0, Integer.parseInt(urlEntity.port));
mTaskOption.getUrlEntity().validAddr = ip;
} else {
DNSQueryThread dnsThread = new DNSQueryThread(urlEntity.hostName);
dnsThread.start();
dnsThread.join(mConnectTimeOut);
InetAddress[] ips = dnsThread.getIps();
client = connect(newInstanceClient(urlEntity), ips, 0, Integer.parseInt(urlEntity.port));
}
if (client == null) {
failDownload(client, String.format("链接失败, url: %s", mTaskOption.getUrlEntity().url), null,
true);
return null;
}
boolean loginSuccess = true;
if (urlEntity.needLogin) {
try {
if (TextUtils.isEmpty(urlEntity.account)) {
loginSuccess = client.login(urlEntity.user, urlEntity.password);
} else {
loginSuccess = client.login(urlEntity.user, urlEntity.password, urlEntity.account);
}
} catch (IOException e) {
ALog.e(TAG,
new TaskException(TAG, String.format("登录失败,错误码为:%s msg%s", client.getReplyCode(),
client.getReplyString()), e));
return null;
}
}
if (!loginSuccess) {
failDownload(client, "登录失败", null, false);
client.disconnect();
return null;
}
int reply = client.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
failDownload(client, String.format("无法连接到ftp服务器filePath: %s, url: %s", mEntity.getKey(),
mTaskOption.getUrlEntity().url), null, true);
client.disconnect();
return null;
}
// 开启服务器对UTF-8的支持如果服务器支持就用UTF-8编码
charSet = "UTF-8";
reply = client.sendCommand("OPTS UTF8", "ON");
if (reply != FTPReply.COMMAND_IS_SUPERFLUOUS) {
ALog.i(TAG, "D_FTP 服务器不支持开启UTF8编码尝试使用Aria手动设置的编码");
if (!TextUtils.isEmpty(mTaskOption.getCharSet())) {
charSet = mTaskOption.getCharSet();
}
}
client.setControlEncoding(charSet);
client.setDataTimeout(10 * 1000);
if (mTaskOption.getConnMode() == FtpConnectionMode.DATA_CONNECTION_MODE_ACTIVITY) {
client.enterLocalActiveMode();
if (mTaskOption.getMinPort() != 0 && mTaskOption.getMaxPort() != 0) {
client.setActivePortRange(mTaskOption.getMinPort(), mTaskOption.getMaxPort());
}
if (!TextUtils.isEmpty(mTaskOption.getActiveExternalIPAddress())) {
client.setActiveExternalIPAddress(mTaskOption.getActiveExternalIPAddress());
}
} else {
client.enterLocalPassiveMode();
}
client.setFileType(FTP.BINARY_FILE_TYPE);
return client;
}
@@ -387,9 +379,18 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
protected void handleFile(String remotePath, FTPFile ftpFile) {
}
protected void failDownload(BaseException e, boolean needRetry) {
protected void failDownload(FTPClient client, String msg, Exception e, boolean needRetry) {
if (mCallback != null) {
mCallback.onFail(mEntity, e, needRetry);
if (client == null) {
msg = "创建ftp客户端失败";
needRetry = false;
} else {
msg = String.format("%s, code: %s, msg: %s", msg, client.getReplyCode(),
client.getReplyString());
needRetry = needRetry && !CheckUtil.ftpIsBadRequest(client.getReplyCode());
}
mCallback.onFail(mEntity, new AriaIOException(TAG, msg), needRetry);
}
}

View File

@@ -22,6 +22,7 @@ import aria.apache.commons.net.ftp.FTPClientConfig;
import aria.apache.commons.net.ftp.FTPReply;
import aria.apache.commons.net.ftp.FTPSClient;
import com.arialyy.aria.core.FtpUrlEntity;
import com.arialyy.aria.core.common.FtpConnectionMode;
import com.arialyy.aria.core.common.SubThreadConfig;
import com.arialyy.aria.core.task.AbsThreadTaskAdapter;
import com.arialyy.aria.exception.AriaIOException;
@@ -118,7 +119,17 @@ public abstract class BaseFtpThreadTaskAdapter extends AbsThreadTaskAdapter {
client.setControlEncoding(charSet);
client.setDataTimeout(getTaskConfig().getIOTimeOut());
client.setConnectTimeout(getTaskConfig().getConnectTimeOut());
client.enterLocalPassiveMode();
if (mTaskOption.getConnMode() == FtpConnectionMode.DATA_CONNECTION_MODE_ACTIVITY) {
client.enterLocalActiveMode();
if (mTaskOption.getMinPort() != 0 && mTaskOption.getMaxPort() != 0) {
client.setActivePortRange(mTaskOption.getMinPort(), mTaskOption.getMaxPort());
}
if (!TextUtils.isEmpty(mTaskOption.getActiveExternalIPAddress())) {
client.setActiveExternalIPAddress(mTaskOption.getActiveExternalIPAddress());
}
} else {
client.enterLocalPassiveMode();
}
client.setFileType(FTP.BINARY_FILE_TYPE);
client.setControlKeepAliveTimeout(5000);
} catch (IOException e) {

View File

@@ -15,6 +15,7 @@
*/
package com.arialyy.aria.ftp;
import aria.apache.commons.net.ftp.FTPClient;
import aria.apache.commons.net.ftp.FTPFile;
import com.arialyy.aria.core.FtpUrlEntity;
import com.arialyy.aria.core.common.CompleteInfo;
@@ -24,8 +25,6 @@ import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.inf.OnFileInfoCallback;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.exception.BaseException;
import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.RecordUtil;
import java.nio.charset.Charset;
@@ -105,11 +104,11 @@ public class FtpDirInfoThread extends AbsFtpInfoThread<DownloadGroupEntity, DGTa
subOption.setUploadInterceptor(mTaskOption.getUploadInterceptor());
subWrapper.setTaskOption(subOption);
}
@Override protected void failDownload(BaseException e, boolean needRetry) {
super.failDownload(e, needRetry);
@Override
protected void failDownload(FTPClient client, String msg, Exception e, boolean needRetry) {
super.failDownload(client, msg, e, needRetry);
RecordUtil.delGroupTaskRecord(mTaskWrapper.getEntity(), true, true);
}
}

View File

@@ -58,7 +58,7 @@ public class FtpRecordAdapter extends AbsRecordHandlerAdapter {
tr.threadId = threadId;
tr.startLocation = startL;
tr.isComplete = false;
tr.threadType = TaskRecord.TYPE_HTTP_FTP;
tr.threadType = getWrapper().getEntity().getTaskType();
//最后一个线程的结束位置即为文件的总长度
if (threadId == (record.threadNum - 1)) {
endL = getEntity().getFileSize();
@@ -81,7 +81,7 @@ public class FtpRecordAdapter extends AbsRecordHandlerAdapter {
} else {
record.isBlock = false;
}
record.taskType = TaskRecord.TYPE_HTTP_FTP;
record.taskType = getWrapper().getEntity().getTaskType();
record.isGroupRecord = getEntity().isGroupChild();
if (record.isGroupRecord) {
if (getEntity() instanceof DownloadEntity) {

View File

@@ -17,9 +17,10 @@ package com.arialyy.aria.ftp;
import aria.apache.commons.net.ftp.FTPClientConfig;
import com.arialyy.aria.core.FtpUrlEntity;
import com.arialyy.aria.core.common.FtpConnectionMode;
import com.arialyy.aria.core.inf.ITaskOption;
import com.arialyy.aria.core.processor.FtpInterceptHandler;
import com.arialyy.aria.core.processor.IFtpUploadInterceptor;
import com.arialyy.aria.core.inf.ITaskOption;
import java.lang.ref.SoftReference;
import java.net.Proxy;
@@ -55,6 +56,54 @@ public class FtpTaskOption implements ITaskOption {
*/
private FTPClientConfig clientConfig;
/**
* 连接模式,默认为被动模式
* {@link FtpConnectionMode}
*/
private int connMode;
/**
* 主动模式下的端口范围
*/
private int minPort, maxPort;
/**
* 主动模式下对外ip可被Ftp服务器访问的ip
*/
private String activeExternalIPAddress;
public String getActiveExternalIPAddress() {
return activeExternalIPAddress;
}
public void setActiveExternalIPAddress(String activeExternalIPAddress) {
this.activeExternalIPAddress = activeExternalIPAddress;
}
public int getMinPort() {
return minPort;
}
public void setMinPort(int minPort) {
this.minPort = minPort;
}
public int getMaxPort() {
return maxPort;
}
public void setMaxPort(int maxPort) {
this.maxPort = maxPort;
}
public int getConnMode() {
return connMode;
}
public void setConnMode(int connMode) {
this.connMode = connMode;
}
public FTPClientConfig getClientConfig() {
return clientConfig;
}

View File

@@ -180,7 +180,9 @@ final class FtpDThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
try {
file =
new BufferedRandomAccessFile(getThreadConfig().tempFile, "rwd", getTaskConfig().getBuffSize());
file.seek(getThreadRecord().startLocation);
if (getThreadRecord().startLocation > 0){
file.seek(getThreadRecord().startLocation);
}
byte[] buffer = new byte[getTaskConfig().getBuffSize()];
int len;
while (getThreadTask().isLive() && (len = is.read(buffer)) != -1) {

View File

@@ -15,7 +15,6 @@
*/
package com.arialyy.aria.ftp.upload;
import androidx.annotation.NonNull;
import com.arialyy.aria.util.BufferedRandomAccessFile;
import java.io.IOException;
import java.io.InputStream;
@@ -34,12 +33,12 @@ final class FtpFISAdapter extends InputStream {
void onProgressCallback(byte[] buffer, int byteOffset, int byteCount) throws IOException;
}
FtpFISAdapter(@NonNull BufferedRandomAccessFile is, @NonNull ProgressCallback callback) {
FtpFISAdapter(BufferedRandomAccessFile is, ProgressCallback callback) {
mIs = is;
mCallback = callback;
}
FtpFISAdapter(@NonNull BufferedRandomAccessFile is) {
FtpFISAdapter(BufferedRandomAccessFile is) {
mIs = is;
}
@@ -51,7 +50,7 @@ final class FtpFISAdapter extends InputStream {
return mIs.read();
}
@Override public int read(@NonNull byte[] buffer) throws IOException {
@Override public int read(byte[] buffer) throws IOException {
count = mIs.read(buffer);
if (mCallback != null) {
mCallback.onProgressCallback(buffer, 0, count);
@@ -59,7 +58,7 @@ final class FtpFISAdapter extends InputStream {
return count;
}
@Override public int read(@NonNull byte[] buffer, int byteOffset, int byteCount)
@Override public int read(byte[] buffer, int byteOffset, int byteCount)
throws IOException {
count = mIs.read(buffer, byteOffset, byteCount);
if (mCallback != null) {

View File

@@ -22,11 +22,11 @@ import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.core.inf.OnFileInfoCallback;
import com.arialyy.aria.core.processor.FtpInterceptHandler;
import com.arialyy.aria.core.processor.IFtpUploadInterceptor;
import com.arialyy.aria.core.upload.UTaskWrapper;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.ftp.AbsFtpInfoThread;
import com.arialyy.aria.core.processor.FtpInterceptHandler;
import com.arialyy.aria.core.processor.IFtpUploadInterceptor;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.DbDataHelper;
@@ -39,7 +39,6 @@ import java.util.List;
* 单任务上传远程服务器文件信息
*/
class FtpUFileInfoThread extends AbsFtpInfoThread<UploadEntity, UTaskWrapper> {
private static final String TAG = "FtpUploadFileInfoThread";
static final int CODE_COMPLETE = 0xab1;
private boolean isComplete = false;
private String remotePath;
@@ -59,10 +58,10 @@ class FtpUFileInfoThread extends AbsFtpInfoThread<UploadEntity, UTaskWrapper> {
@Override protected boolean onInterceptor(FTPClient client, FTPFile[] ftpFiles) {
// 旧任务将不做处理,否则断点续传上传将失效
if (!mTaskWrapper.isNewTask()) {
ALog.d(TAG, "任务是旧任务,忽略该拦截器");
return true;
}
//if (!mTaskWrapper.isNewTask()) {
// ALog.d(TAG, "任务是旧任务,忽略该拦截器");
// return true;
//}
try {
IFtpUploadInterceptor interceptor = mTaskOption.getUploadInterceptor();
if (interceptor != null) {
@@ -78,7 +77,7 @@ class FtpUFileInfoThread extends AbsFtpInfoThread<UploadEntity, UTaskWrapper> {
FtpInterceptHandler interceptHandler = interceptor.onIntercept(mEntity, files);
/*
处理远端有同名文件的情况
* 处理远端有同名文件的情况
*/
if (files.contains(mEntity.getFileName())) {
if (interceptHandler.isCoverServerFile()) {
@@ -94,6 +93,7 @@ class FtpUFileInfoThread extends AbsFtpInfoThread<UploadEntity, UTaskWrapper> {
+ "/"
+ interceptHandler.getNewFileName();
mTaskOption.setNewFileName(interceptHandler.getNewFileName());
closeClient(client);
run();
return false;
@@ -123,6 +123,9 @@ class FtpUFileInfoThread extends AbsFtpInfoThread<UploadEntity, UTaskWrapper> {
if (ftpFile.getSize() == mEntity.getFileSize()) {
isComplete = true;
ALog.d(TAG, "FTP服务器上已存在该文件【" + ftpFile.getName() + "");
} else if (ftpFile.getSize() == 0) {
mTaskWrapper.setNewTask(true);
ALog.d(TAG, "FTP服务器上已存在该文件【" + ftpFile.getName() + "但文件长度为0重新上传该文件");
} else {
ALog.w(TAG, "FTP服务器已存在未完成的文件【"
+ ftpFile.getName()
@@ -135,7 +138,8 @@ class FtpUFileInfoThread extends AbsFtpInfoThread<UploadEntity, UTaskWrapper> {
mTaskWrapper.setNewTask(false);
// 修改记录
TaskRecord record = DbDataHelper.getTaskRecord(mTaskWrapper.getKey());
TaskRecord record = DbDataHelper.getTaskRecord(mTaskWrapper.getKey(),
mTaskWrapper.getEntity().getTaskType());
if (record == null) {
record = new TaskRecord();
record.fileName = mEntity.getFileName();

View File

@@ -34,6 +34,7 @@ import java.io.UnsupportedEncodingException;
*/
class FtpUThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
private String dir, remotePath;
private boolean storeFail = false;
FtpUThreadTaskAdapter(SubThreadConfig config) {
super(config);
@@ -67,8 +68,7 @@ class FtpUThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
file =
new BufferedRandomAccessFile(getThreadConfig().tempFile, "rwd",
getTaskConfig().getBuffSize());
if (getThreadRecord().startLocation != 0) {
//file.skipBytes((int) getThreadConfig().START_LOCATION);
if (getThreadRecord().startLocation > 0) {
file.seek(getThreadRecord().startLocation);
}
boolean complete = upload(client, file);
@@ -79,6 +79,7 @@ class FtpUThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
String.format("任务【%s】线程__%s__上传完毕", getEntity().getKey(), getThreadRecord().threadId));
complete();
} catch (IOException e) {
e.printStackTrace();
fail(new AriaIOException(TAG,
String.format("上传失败filePath: %s, uploadUrl: %s", getEntity().getFilePath(),
getThreadConfig().url)), true);
@@ -118,10 +119,11 @@ class FtpUThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
*/
private boolean upload(final FTPClient client, final BufferedRandomAccessFile bis)
throws IOException {
final FtpFISAdapter fa = new FtpFISAdapter(bis);
storeFail = false;
try {
ALog.d(TAG, String.format("remotePath: %s", remotePath));
client.storeFile(remotePath, new FtpFISAdapter(bis), new OnFtpInputStreamListener() {
client.storeFile(remotePath, fa, new OnFtpInputStreamListener() {
boolean isStoped = false;
@Override public void onFtpInputStream(FTPClient client, long totalBytesTransferred,
@@ -137,23 +139,30 @@ class FtpUThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
progress(bytesTransferred);
} catch (IOException e) {
e.printStackTrace();
storeFail = true;
try {
fa.close();
} catch (IOException e1) {
e1.printStackTrace();
}
closeClient(client);
}
}
});
} catch (IOException e) {
String msg = String.format("文件上传错误,错误码为:%s, msg%s, filePath: %s", client.getReplyCode(),
client.getReplyString(), getEntity().getFilePath());
if (client.isConnected()) {
client.disconnect();
}
closeClient(client);
if (e.getMessage().contains("AriaIOException caught while copying")) {
e.printStackTrace();
} else {
fail(new AriaIOException(TAG, msg, e), true);
fail(new AriaIOException(TAG, msg, e), !storeFail);
}
return false;
}
if (storeFail) {
return false;
}
int reply = client.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
if (reply != FTPReply.TRANSFER_ABORTED) {
@@ -161,9 +170,7 @@ class FtpUThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
String.format("文件上传错误,错误码为:%s, msg%s, filePath: %s", reply, client.getReplyString(),
getEntity().getFilePath())), false);
}
if (client.isConnected()) {
client.disconnect();
}
closeClient(client);
return false;
}
return true;

View File

@@ -10,7 +10,6 @@ android {
versionCode rootProject.ext.versionCode
versionName rootProject.ext.versionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
@@ -25,9 +24,6 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "androidx.appcompat:appcompat:${rootProject.ext.XAppcompatVersion}"
testImplementation 'junit:junit:4.12'
implementation project(path: ':PublicComponent')
}

View File

@@ -24,8 +24,8 @@ import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.core.common.RequestEnum;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.processor.IHttpFileLenAdapter;
import com.arialyy.aria.core.inf.OnFileInfoCallback;
import com.arialyy.aria.core.processor.IHttpFileLenAdapter;
import com.arialyy.aria.exception.AriaIOException;
import com.arialyy.aria.exception.BaseException;
import com.arialyy.aria.exception.TaskException;
@@ -214,7 +214,7 @@ public class HttpFileInfoThread implements Runnable {
} else {
failDownload(new AriaIOException(TAG,
String.format("任务下载失败errorCode%s, errorMsg: %s, url: %s", code,
conn.getResponseMessage(), mEntity.getUrl())), true);
conn.getResponseMessage(), mEntity.getUrl())), !CheckUtil.httpIsBadRequest(code));
}
if (end) {
taskOption.setChunked(isChunked);
@@ -277,7 +277,7 @@ public class HttpFileInfoThread implements Runnable {
}
mEntity.setFileName(newName);
mEntity.setFilePath(newPath);
RecordUtil.modifyTaskRecord(oldFile.getPath(), newPath);
RecordUtil.modifyTaskRecord(oldFile.getPath(), newPath, mEntity.getTaskType());
}
/**

View File

@@ -67,7 +67,7 @@ public class HttpRecordAdapter extends AbsRecordHandlerAdapter {
tr.startLocation = startL;
tr.isComplete = false;
tr.threadType = TaskRecord.TYPE_HTTP_FTP;
tr.threadType = getEntity().getTaskType();
//最后一个线程的结束位置即为文件的总长度
if (threadId == (record.threadNum - 1)) {
endL = getEntity().getFileSize();
@@ -91,7 +91,7 @@ public class HttpRecordAdapter extends AbsRecordHandlerAdapter {
} else {
record.isBlock = false;
}
record.taskType = TaskRecord.TYPE_HTTP_FTP;
record.taskType = getEntity().getTaskType();
record.isGroupRecord = getEntity().isGroupChild();
if (record.isGroupRecord) {
if (getEntity() instanceof DownloadEntity) {

View File

@@ -112,7 +112,9 @@ final class HttpDThreadTaskAdapter extends BaseHttpThreadTaskAdapter {
new BufferedRandomAccessFile(getThreadConfig().tempFile, "rwd",
getTaskConfig().getBuffSize());
//设置每条线程写入文件的位置
file.seek(getThreadRecord().startLocation);
if (getThreadRecord().startLocation > 0){
file.seek(getThreadRecord().startLocation);
}
readNormal(is, file);
handleComplete();
}

View File

@@ -25,7 +25,6 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "androidx.appcompat:appcompat:${rootProject.ext.XAppcompatVersion}"
implementation project(path: ':HttpComponent')
implementation project(path: ':PublicComponent')
}

View File

@@ -255,6 +255,10 @@ final public class M3U8InfoThread implements Runnable {
m3U8Entity.keyUrl) + ".key";
} else if (param.startsWith("IV")) {
m3U8Entity.iv = param.split("=")[1];
}else if (param.startsWith("KEYFORMAT")){
m3U8Entity.keyFormat = param.split("=")[1];
}else if (param.startsWith("KEYFORMATVERSIONS")){
m3U8Entity.keyFormatVersion = param.split("=")[1];
}
}
downloadKey(m3U8Entity);

View File

@@ -106,7 +106,7 @@ public class M3U8RecordAdapter extends AbsRecordHandlerAdapter {
tr.threadId = threadId;
tr.isComplete = false;
tr.startLocation = 0;
tr.threadType = TaskRecord.TYPE_M3U8_VOD;
tr.threadType = getEntity().getTaskType();
tr.tsUrl = mOption.getUrls().get(threadId);
return tr;
}
@@ -118,13 +118,7 @@ public class M3U8RecordAdapter extends AbsRecordHandlerAdapter {
record.threadRecords = new ArrayList<>();
record.threadNum = threadNum;
record.isBlock = true;
int requestType = getWrapper().getRequestType();
if (requestType == ITaskWrapper.M3U8_VOD) {
record.taskType = TaskRecord.TYPE_M3U8_VOD;
} else if (requestType == ITaskWrapper.M3U8_LIVE) {
record.taskType = TaskRecord.TYPE_M3U8_LIVE;
}
record.taskType = getEntity().getTaskType();
record.bandWidth = mOption.getBandWidth();
return record;
}

View File

@@ -109,6 +109,20 @@ public class M3U8TaskOption implements ITaskOption {
*/
private SoftReference<IKeyUrlConverter> keyUrlConverter;
/**
* 忽略下载失败的ts切片。
* true即使有失败的切片下载完成后也要合并所有切片并进入complete回调
*/
private boolean ignoreFailureTs = false;
public boolean isIgnoreFailureTs() {
return ignoreFailureTs;
}
public void setIgnoreFailureTs(boolean ignoreFailureTs) {
this.ignoreFailureTs = ignoreFailureTs;
}
public IKeyUrlConverter getKeyUrlConverter() {
return keyUrlConverter == null ? null : keyUrlConverter.get();
}

View File

@@ -169,7 +169,7 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
record.taskKey = mRecord.filePath;
record.isComplete = false;
record.tsUrl = tsUrl;
record.threadType = TaskRecord.TYPE_M3U8_LIVE;
record.threadType = getEntity().getTaskType();
record.threadId = indexId;
mRecord.threadRecords.add(record);

View File

@@ -221,9 +221,9 @@ public class M3U8VodLoader extends BaseM3U8Loader {
}
}
mManager.updateStateCount();
if (mCompleteNum <= 0){
if (mCompleteNum <= 0) {
mListener.onStart(0);
}else {
} else {
int percent = mCompleteNum * 100 / mRecord.threadRecords.size();
mListener.onResume(percent);
}
@@ -570,9 +570,9 @@ public class M3U8VodLoader extends BaseM3U8Loader {
ALog.d(TAG, String.format("vod任务【%s】完成", mTempFile.getName()));
if (mM3U8Option.isGenerateIndexFile()) {
if (generateIndexFile(false)){
if (generateIndexFile(false)) {
listener.onComplete();
}else {
} else {
listener.onFail(false, new TaskException(TAG, "创建索引文件失败"));
}
} else if (mM3U8Option.isMergeFile()) {
@@ -621,7 +621,11 @@ public class M3U8VodLoader extends BaseM3U8Loader {
}
@Override public boolean isComplete() {
return mCompleteNum == taskRecord.threadRecords.size() && !isJump;
if (mM3U8Option.isIgnoreFailureTs()) {
return mCompleteNum + failNum >= taskRecord.threadRecords.size() && !isJump;
} else {
return mCompleteNum == taskRecord.threadRecords.size() && !isJump;
}
}
@Override public long getCurrentProgress() {

View File

@@ -24,7 +24,6 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "androidx.appcompat:appcompat:${rootProject.ext.XAppcompatVersion}"
testImplementation 'junit:junit:4.12'
}

View File

@@ -92,7 +92,6 @@ public class FtpUrlEntity implements Cloneable {
* 连接协议
* {@link ProtocolType}
*/
@ProtocolType
public String protocol = ProtocolType.Default;
/**

View File

@@ -15,20 +15,7 @@
*/
package com.arialyy.aria.core;
import androidx.annotation.StringDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@StringDef({
ProtocolType.Default,
ProtocolType.SSL,
ProtocolType.SSLv3,
ProtocolType.TLS,
ProtocolType.TLSv1,
ProtocolType.TLSv1_1,
ProtocolType.TLSv1_2
})
@Retention(RetentionPolicy.SOURCE) public @interface ProtocolType {
public interface ProtocolType {
String Default = "TLS";
String SSL = "SSL";
String SSLv3 = "SSLv3";

View File

@@ -15,6 +15,7 @@
*/
package com.arialyy.aria.core;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.orm.annotation.Ignore;
import com.arialyy.aria.orm.annotation.NoNull;
@@ -26,9 +27,9 @@ import java.util.List;
* 任务上传或下载的任务记录
*/
public class TaskRecord extends DbEntity {
public static final int TYPE_HTTP_FTP = 0;
public static final int TYPE_M3U8_VOD = 1;
public static final int TYPE_M3U8_LIVE = 2;
//public static final int TYPE_HTTP_FTP = 0;
//public static final int TYPE_M3U8_VOD = 1;
//public static final int TYPE_M3U8_LIVE = 2;
@Ignore
public List<ThreadRecord> threadRecords;
@@ -41,7 +42,6 @@ public class TaskRecord extends DbEntity {
/**
* 任务文件路径
*/
@Unique
public String filePath;
/**
@@ -79,8 +79,8 @@ public class TaskRecord extends DbEntity {
public boolean isBlock = false;
/**
* 线程类型
* {@link #TYPE_HTTP_FTP}、{@link #TYPE_M3U8_VOD}
* 任务类型
* {@link ITaskWrapper}
*/
public int taskType = 0;

View File

@@ -15,6 +15,7 @@
*/
package com.arialyy.aria.core;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.DbEntity;
/**
@@ -56,7 +57,7 @@ public class ThreadRecord extends DbEntity {
/**
* 线程类型
* {@link TaskRecord#TYPE_HTTP_FTP}、{@link TaskRecord#TYPE_M3U8_VOD}
* {@link ITaskWrapper}
*/
public int threadType = 0;

View File

@@ -17,6 +17,7 @@ package com.arialyy.aria.core.common;
import android.os.Parcel;
import android.os.Parcelable;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.annotation.Default;
/**
@@ -44,6 +45,20 @@ public abstract class AbsNormalEntity extends AbsEntity implements Parcelable {
private boolean isRedirect = false; //是否重定向
private String redirectUrl; //重定向链接
/**
* 任务类型
* {@link ITaskWrapper}
*/
private int taskType;
@Override public int getTaskType() {
return taskType;
}
public void setTaskType(int taskType) {
this.taskType = taskType;
}
public String getUrl() {
return url;
}

View File

@@ -1,13 +1,11 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* http://www.apache.org/licenses/LICENSE-2.0
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.common;
/**
* FTP 连接模式
*/
public interface FtpConnectionMode {
/**
* 被动模式
*/
int DATA_CONNECTION_MODE_PASV = 0;
/**
* 主动模式
*/
int DATA_CONNECTION_MODE_ACTIVITY = 1;
}

View File

@@ -71,8 +71,11 @@ public class RecordHandler implements IRecordHandler {
convertDb();
} else {
mAdapter.onPre();
mTaskRecord = DbDataHelper.getTaskRecord(getFilePath());
mTaskRecord = DbDataHelper.getTaskRecord(getFilePath(), mEntity.getTaskType());
if (mTaskRecord == null) {
if (!new File(getFilePath()).exists()){
FileUtil.createFile(getFilePath());
}
initRecord(true);
} else {
File file = new File(mTaskRecord.filePath);

View File

@@ -15,17 +15,7 @@
*/
package com.arialyy.aria.core.config;
import androidx.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@IntDef({
ConfigType.DOWNLOAD,
ConfigType.UPLOAD,
ConfigType.APP,
ConfigType.D_GROUP
})
@Retention(RetentionPolicy.SOURCE) @interface ConfigType {
public interface ConfigType {
int DOWNLOAD = 1;
int UPLOAD = 2;
int APP = 3;

View File

@@ -33,7 +33,7 @@ public class XMLReader extends DefaultHandler {
private UploadConfig mUploadConfig = Configuration.getInstance().uploadCfg;
private AppConfig mAppConfig = Configuration.getInstance().appCfg;
private DGroupConfig mDGroupConfig = Configuration.getInstance().dGroupCfg;
private @ConfigType int mType;
private int mType;
@Override public void startDocument() throws SAXException {
super.startDocument();

View File

@@ -78,22 +78,22 @@ public class DownloadEntity extends AbsNormalEntity implements Parcelable {
return getUrl();
}
@Override public int getTaskType() {
int type;
if (TextUtils.isEmpty(getUrl())) {
type = ITaskWrapper.ERROR;
} else if (getUrl().startsWith("ftp")) {
type = ITaskWrapper.D_FTP;
} else {
M3U8Entity temp = getM3U8Entity();
if (temp == null) {
type = ITaskWrapper.D_HTTP;
} else {
type = temp.isLive() ? ITaskWrapper.M3U8_LIVE : ITaskWrapper.M3U8_VOD;
}
}
return type;
}
//@Override public int getTaskType() {
// int type;
// if (TextUtils.isEmpty(getUrl())) {
// type = ITaskWrapper.ERROR;
// } else if (getUrl().startsWith("ftp")) {
// type = ITaskWrapper.D_FTP;
// } else {
// M3U8Entity temp = getM3U8Entity();
// if (temp == null) {
// type = ITaskWrapper.D_HTTP;
// } else {
// type = temp.isLive() ? ITaskWrapper.M3U8_LIVE : ITaskWrapper.M3U8_VOD;
// }
// }
// return type;
//}
public DownloadEntity() {
}

View File

@@ -20,7 +20,9 @@ import android.os.Parcelable;
import android.text.TextUtils;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.orm.annotation.Default;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.DbDataHelper;
import java.io.File;
@@ -78,6 +80,33 @@ public class M3U8Entity extends DbEntity implements Parcelable {
*/
public String iv;
/**
* key的格式可能为空
*/
public String keyFormat;
/**
* key的格式版本默认为1如果是多个版本使用"/"分隔,如:"1", "1/2", or "1/2/5"
*/
@Default("1")
public String keyFormatVersion = "1";
public String getKeyFormat() {
return keyFormat;
}
public void setKeyFormat(String keyFormat) {
this.keyFormat = keyFormat;
}
public String getKeyFormatVersion() {
return keyFormatVersion;
}
public void setKeyFormatVersion(String keyFormatVersion) {
this.keyFormatVersion = keyFormatVersion;
}
public String getKeyPath() {
return keyPath;
}
@@ -125,7 +154,8 @@ public class M3U8Entity extends DbEntity implements Parcelable {
return null;
}
List<PeerInfo> peers = new ArrayList<>();
TaskRecord taskRecord = DbDataHelper.getTaskRecord(filePath);
TaskRecord taskRecord = DbDataHelper.getTaskRecord(filePath,
isLive ? ITaskWrapper.M3U8_LIVE : ITaskWrapper.M3U8_VOD);
File cacheDir = new File(getCacheDir());
if ((taskRecord == null
|| taskRecord.threadRecords == null

View File

@@ -1,17 +1,6 @@
package com.arialyy.aria.core.inf;
import androidx.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@IntDef({
TaskSchedulerType.TYPE_DEFAULT,
TaskSchedulerType.TYPE_STOP_NOT_NEXT,
TaskSchedulerType.TYPE_STOP_AND_WAIT,
TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY,
TaskSchedulerType.TYPE_START_AND_RESET_STATE
})
@Retention(RetentionPolicy.SOURCE) public @interface TaskSchedulerType {
public interface TaskSchedulerType {
int TYPE_DEFAULT = 1;
/**
* 停止当前任务并且不自动启动下一任务

View File

@@ -15,7 +15,6 @@
*/
package com.arialyy.aria.core.processor;
import androidx.annotation.Nullable;
import com.arialyy.aria.core.download.M3U8Entity;
import com.arialyy.aria.core.inf.IEventHandler;
import java.util.List;
@@ -33,5 +32,5 @@ public interface ITsMergeHandler extends IEventHandler {
* @param tsPath ts文件列表
* @return {@code true} 合并成功
*/
boolean merge(@Nullable M3U8Entity m3U8Entity, List<String> tsPath);
boolean merge(M3U8Entity m3U8Entity, List<String> tsPath);
}

View File

@@ -52,7 +52,6 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
/**
* 该任务的调度类型
*/
@TaskSchedulerType
private int mSchedulerType = TaskSchedulerType.TYPE_DEFAULT;
protected IEventListener mListener;
@@ -193,7 +192,7 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
start(TaskSchedulerType.TYPE_DEFAULT);
}
@Override public void start(@TaskSchedulerType int type) {
@Override public void start(int type) {
mSchedulerType = type;
if (type == TaskSchedulerType.TYPE_START_AND_RESET_STATE) {
if (getUtil().isRunning()) {
@@ -216,7 +215,7 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
stop(TaskSchedulerType.TYPE_DEFAULT);
}
@Override public void stop(@TaskSchedulerType int type) {
@Override public void stop(int type) {
isStop = true;
mSchedulerType = type;
getUtil().stop();
@@ -226,7 +225,7 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
cancel(TaskSchedulerType.TYPE_DEFAULT);
}
@Override public void cancel(@TaskSchedulerType int type) {
@Override public void cancel(int type) {
isCancel = true;
mSchedulerType = type;
getUtil().cancel();

View File

@@ -91,7 +91,7 @@ public interface ITask<TASK_WRAPPER extends AbsTaskWrapper> {
*
* @param type {@link TaskSchedulerType}
*/
void start(@TaskSchedulerType int type);
void start(int type);
/**
* 停止任务
@@ -103,7 +103,7 @@ public interface ITask<TASK_WRAPPER extends AbsTaskWrapper> {
*
* @param type {@link TaskSchedulerType}
*/
void stop(@TaskSchedulerType int type);
void stop(int type);
/**
* 删除任务
@@ -115,7 +115,7 @@ public interface ITask<TASK_WRAPPER extends AbsTaskWrapper> {
*
* @param type {@link TaskSchedulerType}
*/
void cancel(@TaskSchedulerType int type);
void cancel(int type);
/**
* 读取扩展数据

View File

@@ -16,7 +16,6 @@
package com.arialyy.aria.core.task;
import android.os.Bundle;
import androidx.annotation.Nullable;
import com.arialyy.aria.core.inf.IThreadState;
import com.arialyy.aria.exception.BaseException;
@@ -33,7 +32,7 @@ public interface IThreadTaskObserver {
*
* @param state state {@link IThreadState#STATE_STOP}..
*/
void updateState(int state, @Nullable Bundle bundle);
void updateState(int state, Bundle bundle);
/**
* 更新完成的状态
@@ -45,7 +44,7 @@ public interface IThreadTaskObserver {
*
* @param needRetry 是否需要重试,一般是网络错误才需要重试
*/
void updateFailState(@Nullable BaseException e, boolean needRetry);
void updateFailState(BaseException e, boolean needRetry);
/**
* 更新进度

View File

@@ -20,7 +20,6 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Process;
import androidx.annotation.Nullable;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.common.SubThreadConfig;
@@ -259,7 +258,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
* @param bundle 而外数据
*/
@Override
public synchronized void updateState(int state, @Nullable Bundle bundle) {
public synchronized void updateState(int state, Bundle bundle) {
Message msg = mStateHandler.obtainMessage();
msg.what = state;
if (state != IThreadState.STATE_UPDATE_PROGRESS) {
@@ -297,7 +296,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
*
* @param needRetry 是否需要重试,一般是网络错误才需要重试
*/
@Override public synchronized void updateFailState(@Nullable BaseException e, boolean needRetry) {
@Override public synchronized void updateFailState(BaseException e, boolean needRetry) {
fail(mRangeProgress, e, needRetry);
}
@@ -448,7 +447,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
/**
* 发送失败信息
*/
private void sendFailMsg(@Nullable BaseException e,boolean needRetry) {
private void sendFailMsg(BaseException e, boolean needRetry) {
Bundle b = new Bundle();
b.putBoolean(IThreadState.KEY_RETRY, needRetry);
if (e != null) {

View File

@@ -17,9 +17,7 @@ package com.arialyy.aria.core.upload;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import com.arialyy.aria.core.common.AbsNormalEntity;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.annotation.Primary;
/**
@@ -58,12 +56,12 @@ public class UploadEntity extends AbsNormalEntity implements Parcelable {
return filePath;
}
@Override public int getTaskType() {
if (TextUtils.isEmpty(getUrl())){
return ITaskWrapper.ERROR;
}
return getUrl().startsWith("ftp") ? ITaskWrapper.U_FTP : ITaskWrapper.U_HTTP;
}
//@Override public int getTaskType() {
// if (TextUtils.isEmpty(getUrl())){
// return ITaskWrapper.ERROR;
// }
// return getUrl().startsWith("ftp") ? ITaskWrapper.U_FTP : ITaskWrapper.U_HTTP;
//}
public UploadEntity() {
}

View File

@@ -28,16 +28,7 @@ import java.net.URLEncoder;
abstract class AbsDelegate {
static final String TAG = "AbsDelegate";
/**
* URL编码字符串
*
* @param str 原始字符串
* @return 编码后的字符串
*/
String encodeStr(String str) {
str = str.replaceAll("\\\\+", "%2B");
return URLEncoder.encode(str);
}
/**
* 检查list参数是否合法list只能是{@code List<String>}

View File

@@ -34,7 +34,7 @@ class DBConfig {
static boolean DEBUG = false;
static Map<String, Class<? extends DbEntity>> mapping = new LinkedHashMap<>();
static String DB_NAME;
static int VERSION = 56;
static int VERSION = 57;
/**
* 是否将数据库保存在Sd卡{@code true} 是

View File

@@ -113,7 +113,7 @@ class DelegateCommon extends AbsDelegate {
sql = sql.replace("?", "%s");
Object[] params = new String[expression.length - 1];
for (int i = 0, len = params.length; i < len; i++) {
params[i] = String.format("'%s'", encodeStr(expression[i + 1]));
params[i] = String.format("'%s'", SqlUtil.encodeStr(expression[i + 1]));
}
sql = String.format(sql, params);
Cursor cursor = db.rawQuery(sql, null);

View File

@@ -205,7 +205,7 @@ class DelegateFind extends AbsDelegate {
sql = sql.replace("?", "%s");
Object[] params = new String[expression.length - 1];
for (int i = 0, len = params.length; i < len; i++) {
params[i] = String.format("'%s'", encodeStr(expression[i + 1]));
params[i] = String.format("'%s'", SqlUtil.encodeStr(expression[i + 1]));
}
sql = String.format(sql, params);
} else {
@@ -421,7 +421,7 @@ class DelegateFind extends AbsDelegate {
String[] temp = new String[selectionArgs.length];
int i = 0;
for (String arg : selectionArgs) {
temp[i] = encodeStr(arg);
temp[i] = SqlUtil.encodeStr(arg);
i++;
}
Cursor cursor = db.rawQuery(sql, temp);

View File

@@ -47,7 +47,7 @@ class DelegateUpdate extends AbsDelegate {
sql = sql.replace("?", "%s");
Object[] params = new String[expression.length - 1];
for (int i = 0, len = params.length; i < len; i++) {
params[i] = String.format("'%s'", encodeStr(expression[i + 1]));
params[i] = String.format("'%s'", SqlUtil.encodeStr(expression[i + 1]));
}
sql = String.format(sql, params);
db.execSQL(sql);
@@ -166,7 +166,7 @@ class DelegateUpdate extends AbsDelegate {
value = field.get(dbEntity).toString();
}
}
values.put(field.getName(), encodeStr(value));
values.put(field.getName(), SqlUtil.encodeStr(value));
}
return values;
} catch (IllegalAccessException e) {

View File

@@ -21,6 +21,9 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Build;
import android.text.TextUtils;
import com.arialyy.aria.core.download.M3U8Entity;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.util.ALog;
import java.io.File;
import java.util.ArrayList;
@@ -102,6 +105,10 @@ final class SqlHelper extends SQLiteOpenHelper {
} else {
handleDbUpdate(db, null);
}
// 处理380版本TaskRecord 增加的记录类型判断
if (newVersion == 57) {
addTaskRecordType(db);
}
}
}
@@ -256,6 +263,79 @@ final class SqlHelper extends SQLiteOpenHelper {
return temp;
}
/**
* 给TaskRecord 增加任务类型
*/
private void addTaskRecordType(SQLiteDatabase db) {
try {
db.beginTransaction();
/*
* 增加下载实体的类型
*/
String dSql = "SELECT downloadPath, url FROM DownloadEntity";
Cursor c = db.rawQuery(dSql, null);
while (c.moveToNext()) {
int type;
String filePath = c.getString(0);
String url = c.getString(1);
if (url.startsWith("ftp") || url.startsWith("sftp")) {
type = ITaskWrapper.D_FTP;
} else {
if (mDelegate.tableExists(db, M3U8Entity.class)) {
Cursor m3u8c = db.rawQuery("SELECT isLive FROM M3U8Entity WHERE filePath=\""
+ SqlUtil.encodeStr(filePath)
+ "\"", null);
if (m3u8c.moveToNext()) {
String temp = m3u8c.getString(0);
type =
(TextUtils.isEmpty(temp) ? false : Boolean.valueOf(temp)) ? ITaskWrapper.M3U8_LIVE
: ITaskWrapper.M3U8_VOD;
} else {
type = ITaskWrapper.D_HTTP;
}
m3u8c.close();
} else {
type = ITaskWrapper.D_HTTP;
}
}
db.execSQL("UPDATE DownloadEntity SET taskType=? WHERE downloadPath=?",
new Object[] { type, filePath });
db.execSQL("UPDATE TaskRecord SET taskType=? WHERE filePath=?",
new Object[] { type, filePath });
db.execSQL("UPDATE ThreadRecord SET threadType=? WHERE taskKey=?",
new Object[] { type, filePath });
}
c.close();
/*
* 增加上传实体的类型
*/
String uSql = "SELECT filePath, url FROM UploadEntity";
c = db.rawQuery(uSql, null);
while (c.moveToNext()) {
int type;
String filePath = c.getString(c.getColumnIndex("filePath"));
String url = c.getString(c.getColumnIndex("url"));
if (url.startsWith("ftp") || url.startsWith("sftp")) {
type = ITaskWrapper.D_FTP;
} else {
type = ITaskWrapper.D_HTTP;
}
db.execSQL("UPDATE UploadEntity SET taskType=? WHERE filePath=?",
new Object[] { type, filePath });
db.execSQL("UPDATE TaskRecord SET taskType=? WHERE filePath=?",
new Object[] { type, filePath });
db.execSQL("UPDATE ThreadRecord SET threadType=? WHERE taskKey=?",
new Object[] { type, filePath });
}
c.close();
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
/**
* 删除重复的repeat数据
*/

View File

@@ -29,6 +29,7 @@ import com.arialyy.aria.orm.annotation.Wrapper;
import com.arialyy.aria.util.CommonUtil;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -41,6 +42,17 @@ import java.util.Set;
*/
final class SqlUtil {
/**
* URL编码字符串
*
* @param str 原始字符串
* @return 编码后的字符串
*/
static String encodeStr(String str) {
str = str.replaceAll("\\\\+", "%2B");
return URLEncoder.encode(str);
}
/**
* 获取主键字段名
*/

View File

@@ -23,7 +23,10 @@ import com.arialyy.aria.core.inf.IRecordHandler;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.orm.DbEntity;
import java.lang.reflect.Modifier;
import java.net.HttpURLConnection;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by Lyy on 2016/9/23.
@@ -32,6 +35,44 @@ import java.util.List;
public class CheckUtil {
private static final String TAG = "CheckUtil";
/**
* 检查ip是否正确
*
* @param ip ipv4 地址
* @return {@code true} ip 正确,{@code false} ip 错误
*/
public static boolean checkIp(String ip) {
if (TextUtils.isEmpty(ip) || ip.length() < 7 || ip.length() > 15) {
return false;
}
Pattern p = Pattern.compile(Regular.REG_IP_V4);
Matcher m = p.matcher(ip);
return m.find() && m.groupCount() > 0;
}
/**
* 判断http请求是否有效
* {@link HttpURLConnection#HTTP_BAD_GATEWAY} or {@link HttpURLConnection#HTTP_BAD_METHOD}
* or {@link HttpURLConnection#HTTP_BAD_REQUEST} 无法重试
*
* @param errorCode http 返回码
* @return {@code true} 无效请求;{@code false} 有效请求
*/
public static boolean httpIsBadRequest(int errorCode) {
return errorCode == HttpURLConnection.HTTP_BAD_GATEWAY
|| errorCode == HttpURLConnection.HTTP_BAD_METHOD
|| errorCode == HttpURLConnection.HTTP_BAD_REQUEST;
}
/**
* 判断ftp请求是否有效
*
* @return {@code true} 无效请求;{@code false} 有效请求
*/
public static boolean ftpIsBadRequest(int errorCode) {
return errorCode >= 400 && errorCode < 600;
}
/**
* 检查和处理下载任务的路径冲突
*
@@ -100,8 +141,15 @@ public class CheckUtil {
*/
public static void checkMemberClass(Class clazz) {
int modifiers = clazz.getModifiers();
if (!clazz.isMemberClass() || !Modifier.isStatic(modifiers) || Modifier.isPrivate(modifiers)) {
ALog.e(TAG, "为了防止内存泄漏,请使用静态的成员类(public static class xxx)或文件类(A.java)");
//ALog.d(TAG, "isMemberClass = "
// + clazz.isMemberClass()
// + "; isStatic = "
// + Modifier.isStatic(modifiers)
// + "; isPrivate = "
// + Modifier.isPrivate(modifiers));
if (!clazz.isMemberClass() || !Modifier.isStatic(modifiers)) {
ALog.e(TAG, String.format("为了防止内存泄漏,请使用静态的成员类(public static class %s)或文件类(%s.java)",
clazz.getSimpleName(), clazz.getSimpleName()));
}
}

View File

@@ -15,12 +15,13 @@
*/
package com.arialyy.aria.util;
import com.arialyy.aria.core.wrapper.RecordWrapper;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.download.DGEntityWrapper;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.DbEntity;
import java.io.File;
import java.util.ArrayList;
@@ -35,15 +36,20 @@ public class DbDataHelper {
* 获取任务记录
*
* @param filePath 文件地址
* @param taskType 任务类型{@link ITaskWrapper}
* @return 没有记录返回null有记录则返回任务记录
*/
public static TaskRecord getTaskRecord(String filePath) {
List<RecordWrapper> record =
DbEntity.findRelationData(RecordWrapper.class, "TaskRecord.filePath=?", filePath);
if (record == null || record.size() == 0) {
return null;
public static TaskRecord getTaskRecord(String filePath, int taskType) {
TaskRecord taskRecord =
DbEntity.findFirst(TaskRecord.class, "filePath=? AND taskType=?", filePath,
String.valueOf(taskType));
if (taskRecord != null) {
taskRecord.threadRecords =
DbEntity.findDatas(ThreadRecord.class, "taskKey=? AND threadType=?", filePath,
String.valueOf(taskType));
}
return record.get(0).taskRecord;
return taskRecord;
}
/**

View File

@@ -25,6 +25,7 @@ import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.download.M3U8Entity;
import com.arialyy.aria.core.inf.IRecordHandler;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.core.wrapper.RecordWrapper;
import com.arialyy.aria.orm.DbEntity;
import java.io.File;
@@ -187,7 +188,7 @@ public class RecordUtil {
* @return true 为m3u8任务
*/
private static boolean recordIsM3U8(int recordType) {
return recordType == TaskRecord.TYPE_M3U8_VOD || recordType == TaskRecord.TYPE_M3U8_LIVE;
return recordType == ITaskWrapper.M3U8_VOD || recordType == ITaskWrapper.M3U8_LIVE;
}
/**
@@ -361,13 +362,14 @@ public class RecordUtil {
*
* @param oldPath 旧的文件路径
* @param newPath 新的文件路径
* @param taskType 任务类型{@link ITaskWrapper}
*/
public static void modifyTaskRecord(String oldPath, String newPath) {
public static void modifyTaskRecord(String oldPath, String newPath, int taskType) {
if (oldPath.equals(newPath)) {
ALog.w(TAG, "修改任务记录失败,新文件路径和旧文件路径一致");
return;
}
TaskRecord record = DbDataHelper.getTaskRecord(oldPath);
TaskRecord record = DbDataHelper.getTaskRecord(oldPath, taskType);
if (record == null) {
if (new File(oldPath).exists()) {
ALog.w(TAG, "修改任务记录失败,文件【" + oldPath + "】对应的任务记录不存在");

View File

@@ -56,8 +56,7 @@ public class SSLContextUtil {
* @param caPath 保存在assets目录下的CA证书完整路径
* @param protocol 连接协议
*/
public static SSLContext getSSLContextFromAssets(String caAlias, String caPath,
@ProtocolType String protocol) {
public static SSLContext getSSLContextFromAssets(String caAlias, String caPath, String protocol) {
if (TextUtils.isEmpty(caAlias) || TextUtils.isEmpty(caPath)) {
return null;
}
@@ -83,8 +82,7 @@ public class SSLContextUtil {
* @param caPath CA证书路径
* @param protocol 连接协议
*/
public static SSLContext getSSLContext(String caAlias, String caPath,
@ProtocolType String protocol) {
public static SSLContext getSSLContext(String caAlias, String caPath, String protocol) {
if (TextUtils.isEmpty(caAlias) || TextUtils.isEmpty(caPath)) {
return null;
}
@@ -105,8 +103,8 @@ public class SSLContextUtil {
/**
* @param cacheKey 别名 + 证书路径然后取md5
*/
private static SSLContext createContext(String caAlias, Certificate ca,
@ProtocolType String protocol, String cacheKey) {
private static SSLContext createContext(String caAlias, Certificate ca, String protocol,
String cacheKey) {
try {
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
@@ -154,7 +152,7 @@ public class SSLContextUtil {
/**
* 服务器证书不是由 CA 签署的而是自签署时获取默认的SSL
*/
public static SSLContext getDefaultSLLContext(@ProtocolType String protocol) {
public static SSLContext getDefaultSLLContext(String protocol) {
SSLContext sslContext = null;
try {
sslContext =

View File

@@ -27,9 +27,6 @@ package com.arialyy.aria.util;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import java.lang.ref.WeakReference;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -51,7 +48,7 @@ import java.util.concurrent.locks.ReentrantLock;
// hard reference to Callback. We need to keep callback in memory
private final ExecHandler mExec;
private Lock mLock = new ReentrantLock();
@SuppressWarnings("ConstantConditions") @VisibleForTesting final ChainedRef mRunnables =
@SuppressWarnings("ConstantConditions") final ChainedRef mRunnables =
new ChainedRef(mLock, null);
/**
@@ -76,7 +73,7 @@ import java.util.concurrent.locks.ReentrantLock;
*
* @param callback The callback interface in which to handle messages, or null.
*/
public WeakHandler(@Nullable Handler.Callback callback) {
public WeakHandler(Handler.Callback callback) {
mCallback = callback; // Hard referencing body
mExec = new ExecHandler(new WeakReference<>(callback)); // Weak referencing inside ExecHandler
}
@@ -86,7 +83,7 @@ import java.util.concurrent.locks.ReentrantLock;
*
* @param looper The looper, must not be null.
*/
public WeakHandler(@NonNull Looper looper) {
public WeakHandler(Looper looper) {
mCallback = null;
mExec = new ExecHandler(looper);
}
@@ -98,7 +95,7 @@ import java.util.concurrent.locks.ReentrantLock;
* @param looper The looper, must not be null.
* @param callback The callback interface in which to handle messages, or null.
*/
public WeakHandler(@NonNull Looper looper, @NonNull Handler.Callback callback) {
public WeakHandler(Looper looper, Handler.Callback callback) {
mCallback = callback;
mExec = new ExecHandler(looper, new WeakReference<>(callback));
}
@@ -113,7 +110,7 @@ import java.util.concurrent.locks.ReentrantLock;
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public final boolean post(@NonNull Runnable r) {
public final boolean post(Runnable r) {
return mExec.post(wrapRunnable(r));
}
@@ -133,7 +130,7 @@ import java.util.concurrent.locks.ReentrantLock;
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis) {
public final boolean postAtTime(Runnable r, long uptimeMillis) {
return mExec.postAtTime(wrapRunnable(r), uptimeMillis);
}
@@ -367,7 +364,7 @@ import java.util.concurrent.locks.ReentrantLock;
return mExec.getLooper();
}
private WeakRunnable wrapRunnable(@NonNull Runnable r) {
private WeakRunnable wrapRunnable(Runnable r) {
//noinspection ConstantConditions
if (r == null) {
throw new NullPointerException("Runnable can't be null");
@@ -398,7 +395,7 @@ import java.util.concurrent.locks.ReentrantLock;
mCallback = callback;
}
@Override public void handleMessage(@NonNull Message msg) {
@Override public void handleMessage(Message msg) {
if (mCallback == null) {
return;
}
@@ -432,14 +429,14 @@ import java.util.concurrent.locks.ReentrantLock;
}
static class ChainedRef {
@Nullable ChainedRef next;
@Nullable ChainedRef prev;
@NonNull final Runnable runnable;
@NonNull final WeakRunnable wrapper;
ChainedRef next;
ChainedRef prev;
final Runnable runnable;
final WeakRunnable wrapper;
@NonNull Lock lock;
Lock lock;
public ChainedRef(@NonNull Lock lock, @NonNull Runnable r) {
public ChainedRef(Lock lock, Runnable r) {
this.runnable = r;
this.lock = lock;
this.wrapper = new WeakRunnable(new WeakReference<>(r), new WeakReference<>(this));
@@ -462,7 +459,7 @@ import java.util.concurrent.locks.ReentrantLock;
return wrapper;
}
public void insertAfter(@NonNull ChainedRef candidate) {
public void insertAfter(ChainedRef candidate) {
lock.lock();
try {
if (this.next != null) {
@@ -477,7 +474,7 @@ import java.util.concurrent.locks.ReentrantLock;
}
}
@Nullable public WeakRunnable remove(Runnable obj) {
public WeakRunnable remove(Runnable obj) {
lock.lock();
try {
ChainedRef curr = this.next; // Skipping head

View File

@@ -44,16 +44,16 @@ Aria有以下特点
## 引入库
[![license](http://img.shields.io/badge/license-Apache2.0-brightgreen.svg?style=flat)](https://github.com/AriaLyy/Aria/blob/master/LICENSE)
[![Core](https://img.shields.io/badge/Core-3.7.10-blue)](https://github.com/AriaLyy/Aria)
[![Compiler](https://img.shields.io/badge/Compiler-3.7.10-blue)](https://github.com/AriaLyy/Aria)
[![FtpComponent](https://img.shields.io/badge/FtpComponent-3.7.10-orange)](https://github.com/AriaLyy/Aria)
[![M3U8Component](https://img.shields.io/badge/M3U8Component-3.7.10-orange)](https://github.com/AriaLyy/Aria)
[![Core](https://img.shields.io/badge/Core-3.8-blue)](https://github.com/AriaLyy/Aria)
[![Compiler](https://img.shields.io/badge/Compiler-3.8-blue)](https://github.com/AriaLyy/Aria)
[![FtpComponent](https://img.shields.io/badge/FtpComponent-3.8-orange)](https://github.com/AriaLyy/Aria)
[![M3U8Component](https://img.shields.io/badge/M3U8Component-3.8-orange)](https://github.com/AriaLyy/Aria)
```java
implementation 'com.arialyy.aria:core:3.7.10'
annotationProcessor 'com.arialyy.aria:compiler:3.7.10'
implementation 'com.arialyy.aria:ftpComponent:3.7.10' # 如果需要使用ftp请增加该组件
implementation 'com.arialyy.aria:m3u8Component:3.7.10' # 如果需要使用m3u8下载功能请增加该组件
implementation 'com.arialyy.aria:core:3.8'
annotationProcessor 'com.arialyy.aria:compiler:3.8'
implementation 'com.arialyy.aria:ftpComponent:3.8' # 如果需要使用ftp请增加该组件
implementation 'com.arialyy.aria:m3u8Component:3.8' # 如果需要使用m3u8下载功能请增加该组件
```
如果出现android support依赖错误请将 `compile 'com.arialyy.aria:core:<last-version>'`替换为
```
@@ -65,7 +65,7 @@ api('com.arialyy.aria:core:<last-version>'){
__注意3.5.4以下版本升级时,需要更新[配置文件](https://aria.laoyuyu.me/aria_doc/start/config.html)__
__注意3.7 以上版本已经适配了AndroidX,如果是使用support库的,可使用[老版本](https://github.com/AriaLyy/Aria/tree/v3.6.6)__
__注意3.8 以上版本已经适配了AndroidXsupport库都可以使用
***
## 使用
@@ -137,13 +137,19 @@ protected void onCreate(Bundle savedInstanceState) {
### 版本日志
+ v_3.7.10 (2019/12/3)
- fix bug https://github.com/AriaLyy/Aria/issues/543#issuecomment-559733124
- fix bug https://github.com/AriaLyy/Aria/issues/542
- fix bug https://github.com/AriaLyy/Aria/issues/547
- 修复下载失败时,中断重试无效的问题
- 增加忽略权限检查的api`ignoreCheckPermissions()`
- 增加通用的的忽略文件路径被占用的api`isIgnoreFilePathOccupy()`
+ v_3.8 (2019/12/17)
- 移除androidx和support的依赖现在无论是哪个版本的appcompat包都可以使用本框架
- 修复一个在xml中使用fragment导致的内存泄漏问题
- m3u8协议的key信息增加了`keyFormat``keyFormatVersion`字段
- m3u8增加了`ignoreFailureTs`方法忽略下载失败的ts切片
- 修复在dialogFragment的`onCreateDialog()`注册导致的注解不生效问题
- 修复组合任务初始化失败时,无法删除的问题
- 修复`reStart()`后,无法停止的问题
- ftp增加主动模式开启主动模式https://aria.laoyuyu.me/aria_doc/api/ftp_params.html
- 修复ftp服务器无法响应`abor`命令导致的无法停止上传的问题 https://github.com/AriaLyy/Aria/issues/564
- 修复ftp上传时服务器有长度为0的文件导致上传失败的问题
- 修复下载任务和上传任务的文件路径是同一个时,导致的记录混乱问题
- 优化提示
[更多版本记录](https://github.com/AriaLyy/Aria/blob/master/DEV_LOG.md)

View File

@@ -25,7 +25,6 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "androidx.appcompat:appcompat:${rootProject.ext.XAppcompatVersion}"
implementation "com.jcraft:jsch:0.1.55"
implementation "com.jcraft:jzlib:1.1.3"
implementation project(path: ':FtpComponent')

View File

@@ -23,6 +23,7 @@ import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import com.arialyy.annotations.Download;
import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.common.FtpConnectionMode;
import com.arialyy.aria.core.common.FtpOption;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.inf.IEntity;
@@ -80,11 +81,11 @@ public class FtpDownloadActivity extends BaseActivity<ActivityFtpDownloadBinding
}
});
getBinding().setViewModel(this);
try {
getBinding().codeView.setSource(AppUtil.getHelpCode(this, "FtpDownload.java"));
} catch (IOException e) {
e.printStackTrace();
}
//try {
// getBinding().codeView.setSource(AppUtil.getHelpCode(this, "FtpDownload.java"));
//} catch (IOException e) {
// e.printStackTrace();
//}
}
public void onClick(View view) {
@@ -123,6 +124,7 @@ public class FtpDownloadActivity extends BaseActivity<ActivityFtpDownloadBinding
private FtpOption getFtpOption() {
FtpOption option = new FtpOption();
option.login(user, passw);
option.setConnectionMode(FtpConnectionMode.DATA_CONNECTION_MODE_ACTIVITY);
return option;
}

Some files were not shown because too many files have changed in this diff Show More