初始化任务时,如果url、path有错误将会回调`@Download.onTaskFail`、`@Upload.onTaskFail`、`@DownGroup.onTaskFail`
v3.6.6 3.6.4
laoyuyu 6 years ago
parent 9212aabd95
commit 15978cd2b6
  1. 2
      Aria/src/main/java/com/arialyy/aria/core/common/BaseListener.java
  2. 2
      Aria/src/main/java/com/arialyy/aria/core/common/ftp/AbsFtpInfoThread.java
  3. 248
      Aria/src/main/java/com/arialyy/aria/core/common/ftp/FTPSDelegate.java
  4. 2
      Aria/src/main/java/com/arialyy/aria/core/common/http/HttpHeaderDelegate.java
  5. 114
      Aria/src/main/java/com/arialyy/aria/core/download/AbsDTarget.java
  6. 7
      Aria/src/main/java/com/arialyy/aria/core/download/DNormalDelegate.java
  7. 2
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java
  8. 310
      Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java
  9. 19
      Aria/src/main/java/com/arialyy/aria/core/download/HttpGroupDelegate.java
  10. 2
      Aria/src/main/java/com/arialyy/aria/core/download/group/AbsGroupUtil.java
  11. 2
      Aria/src/main/java/com/arialyy/aria/core/download/group/DownloadGroupUtil.java
  12. 130
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java
  13. 35
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsTask.java
  14. 6
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsTaskWrapper.java
  15. 100
      Aria/src/main/java/com/arialyy/aria/core/inf/IHttpHeaderDelegate.java
  16. 156
      Aria/src/main/java/com/arialyy/aria/core/inf/ITargetHandler.java
  17. 272
      Aria/src/main/java/com/arialyy/aria/core/inf/ITask.java
  18. 3
      Aria/src/main/java/com/arialyy/aria/core/queue/ITaskQueue.java
  19. 16
      Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java
  20. 208
      Aria/src/main/java/com/arialyy/aria/core/upload/FtpUploadTarget.java
  21. 3
      Aria/src/main/java/com/arialyy/aria/core/upload/UNormalDelegate.java
  22. 250
      Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java
  23. 2
      Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpThreadTask.java
  24. 6
      Aria/src/main/java/com/arialyy/aria/util/CheckUtil.java
  25. 6
      DEV_LOG.md
  26. 40
      README.md
  27. 15
      app/src/main/java/com/arialyy/simple/base/BaseApplication.java
  28. 7
      app/src/main/java/com/arialyy/simple/core/download/FtpDownloadActivity.java
  29. 4
      app/src/main/java/com/arialyy/simple/core/download/SingleTaskActivity.java
  30. 2
      build.gradle

@ -110,7 +110,7 @@ public abstract class BaseListener<ENTITY extends AbsEntity, TASK_WRAPPER extend
mEntity.setFailNum(mEntity.getFailNum() + 1); mEntity.setFailNum(mEntity.getFailNum() + 1);
saveData(IEntity.STATE_FAIL, mEntity.getCurrentProgress()); saveData(IEntity.STATE_FAIL, mEntity.getCurrentProgress());
handleSpeed(0); handleSpeed(0);
mTask.needRetry = needRetry; mTask.setNeedRetry(needRetry);
mTask.putExpand(AbsTask.ERROR_INFO_KEY, e); mTask.putExpand(AbsTask.ERROR_INFO_KEY, e);
sendInState2Target(ISchedulers.FAIL); sendInState2Target(ISchedulers.FAIL);
e.printStackTrace(); e.printStackTrace();

@ -257,7 +257,7 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
charSet = "UTF-8"; charSet = "UTF-8";
reply = client.sendCommand("OPTS UTF8", "ON"); reply = client.sendCommand("OPTS UTF8", "ON");
if (reply != FTPReply.COMMAND_IS_SUPERFLUOUS) { if (reply != FTPReply.COMMAND_IS_SUPERFLUOUS) {
ALog.i(TAG, "FTP 服务器不支持开启UTF8编码,尝试使用Aria手动设置的编码"); ALog.i(TAG, "D_FTP 服务器不支持开启UTF8编码,尝试使用Aria手动设置的编码");
if (!TextUtils.isEmpty(mTaskWrapper.asFtp().getCharSet())) { if (!TextUtils.isEmpty(mTaskWrapper.asFtp().getCharSet())) {
charSet = mTaskWrapper.asFtp().getCharSet(); charSet = mTaskWrapper.asFtp().getCharSet();
} }

@ -1,124 +1,124 @@
/* /*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.common.ftp; package com.arialyy.aria.core.common.ftp;
import android.text.TextUtils; import android.text.TextUtils;
import com.arialyy.aria.core.FtpUrlEntity; import com.arialyy.aria.core.FtpUrlEntity;
import com.arialyy.aria.core.common.ProtocolType; import com.arialyy.aria.core.common.ProtocolType;
import com.arialyy.aria.core.inf.AbsTarget; import com.arialyy.aria.core.inf.AbsTarget;
import com.arialyy.aria.core.inf.ITargetHandler; import com.arialyy.aria.core.inf.ITargetHandler;
/** /**
* FTP SSL/TSL 参数委托 * D_FTP SSL/TSL 参数委托
*/ */
public class FTPSDelegate<TARGET extends AbsTarget> implements ITargetHandler { public class FTPSDelegate<TARGET extends AbsTarget> implements ITargetHandler {
private final String TAG = "FTPSDelegate"; private final String TAG = "FTPSDelegate";
private TARGET mTarget; private TARGET mTarget;
private FtpUrlEntity mUrlEntity; private FtpUrlEntity mUrlEntity;
public FTPSDelegate(TARGET target) { public FTPSDelegate(TARGET target) {
mTarget = target; mTarget = target;
mUrlEntity = mTarget.getTaskWrapper().asFtp().getUrlEntity(); mUrlEntity = mTarget.getTaskWrapper().asFtp().getUrlEntity();
} }
/** /**
* 设置协议类型 * 设置协议类型
* *
* @param protocol {@link ProtocolType} * @param protocol {@link ProtocolType}
*/ */
public FTPSDelegate setProtocol(@ProtocolType String protocol) { public FTPSDelegate setProtocol(@ProtocolType String protocol) {
if (TextUtils.isEmpty(protocol)) { if (TextUtils.isEmpty(protocol)) {
throw new NullPointerException("协议为空"); throw new NullPointerException("协议为空");
} }
mUrlEntity.protocol = protocol; mUrlEntity.protocol = protocol;
return this; return this;
} }
/** /**
* 设置证书别名 * 设置证书别名
* *
* @param keyAlias 别名 * @param keyAlias 别名
*/ */
public FTPSDelegate setAlias(String keyAlias) { public FTPSDelegate setAlias(String keyAlias) {
if (TextUtils.isEmpty(keyAlias)) { if (TextUtils.isEmpty(keyAlias)) {
throw new NullPointerException("别名为空"); throw new NullPointerException("别名为空");
} }
mUrlEntity.keyAlias = keyAlias; mUrlEntity.keyAlias = keyAlias;
return this; return this;
} }
/** /**
* 设置证书密码 * 设置证书密码
* *
* @param storePass 私钥密码 * @param storePass 私钥密码
*/ */
public FTPSDelegate setStorePass(String storePass) { public FTPSDelegate setStorePass(String storePass) {
if (TextUtils.isEmpty(storePass)) { if (TextUtils.isEmpty(storePass)) {
throw new NullPointerException("证书密码为空"); throw new NullPointerException("证书密码为空");
} }
mUrlEntity.storePass = storePass; mUrlEntity.storePass = storePass;
return this; return this;
} }
/** /**
* 设置证书路径 * 设置证书路径
* *
* @param storePath 证书路径 * @param storePath 证书路径
*/ */
public FTPSDelegate setStorePath(String storePath) { public FTPSDelegate setStorePath(String storePath) {
if (TextUtils.isEmpty(storePath)) { if (TextUtils.isEmpty(storePath)) {
throw new NullPointerException("证书路径为空"); throw new NullPointerException("证书路径为空");
} }
mUrlEntity.storePath = storePath; mUrlEntity.storePath = storePath;
return this; return this;
} }
@Override public void add() { @Override public void add() {
mTarget.add(); mTarget.add();
} }
@Override public void start() { @Override public void start() {
mTarget.start(); mTarget.start();
} }
@Override public void stop() { @Override public void stop() {
mTarget.stop(); mTarget.stop();
} }
@Override public void resume() { @Override public void resume() {
mTarget.resume(); mTarget.resume();
} }
@Override public void cancel() { @Override public void cancel() {
mTarget.cancel(); mTarget.cancel();
} }
@Override public void save() { @Override public void save() {
mTarget.save(); mTarget.save();
} }
@Override public void cancel(boolean removeFile) { @Override public void cancel(boolean removeFile) {
mTarget.cancel(removeFile); mTarget.cancel(removeFile);
} }
@Override public void reTry() { @Override public void reTry() {
mTarget.reTry(); mTarget.reTry();
} }
@Override public void reStart() { @Override public void reStart() {
mTarget.reStart(); mTarget.reStart();
} }
} }

@ -29,7 +29,7 @@ import java.util.Set;
/** /**
* Created by laoyuyu on 2018/3/9. * Created by laoyuyu on 2018/3/9.
* HTTP header参数设置委托类 * D_HTTP header参数设置委托类
*/ */
public class HttpHeaderDelegate<TARGET extends AbsTarget> public class HttpHeaderDelegate<TARGET extends AbsTarget>
implements IHttpHeaderDelegate<TARGET> { implements IHttpHeaderDelegate<TARGET> {

@ -1,57 +1,57 @@
/* /*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.download; package com.arialyy.aria.core.download;
import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.command.normal.NormalCmdFactory; import com.arialyy.aria.core.command.normal.NormalCmdFactory;
import com.arialyy.aria.core.inf.AbsTarget; import com.arialyy.aria.core.inf.AbsTarget;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
/** /**
* Created by lyy on 2017/2/28. * Created by lyy on 2017/2/28.
*/ */
abstract class AbsDTarget<TARGET extends AbsDTarget> extends AbsTarget<TARGET> { abstract class AbsDTarget<TARGET extends AbsDTarget> extends AbsTarget<TARGET> {
/** /**
* 更新下载url * 更新下载url
* *
* @param newUrl 新的下载url * @param newUrl 新的下载url
*/ */
public abstract TARGET updateUrl(String newUrl); public abstract TARGET updateUrl(String newUrl);
/** /**
* 将任务设置为最高优先级任务最高优先级任务有以下特点 * 将任务设置为最高优先级任务最高优先级任务有以下特点
* 1在下载队列中有且只有一个最高优先级任务 * 1在下载队列中有且只有一个最高优先级任务
* 2最高优先级任务会一直存在直到用户手动暂停或任务完成 * 2最高优先级任务会一直存在直到用户手动暂停或任务完成
* 3任务调度器不会暂停最高优先级任务 * 3任务调度器不会暂停最高优先级任务
* 4用户手动暂停或任务完成后第二次重新执行该任务该命令将失效 * 4用户手动暂停或任务完成后第二次重新执行该任务该命令将失效
* 5如果下载队列中已经满了则会停止队尾的任务当高优先级任务完成后该队尾任务将自动执行 * 5如果下载队列中已经满了则会停止队尾的任务当高优先级任务完成后该队尾任务将自动执行
* 6把任务设置为最高优先级任务后将自动执行任务不需要重新调用start()启动任务 * 6把任务设置为最高优先级任务后将自动执行任务不需要重新调用start()启动任务
*/ */
public void setHighestPriority() { public void setHighestPriority() {
if (checkEntity()) { if (checkConfig()) {
AriaManager.getInstance(AriaManager.APP) AriaManager.getInstance(AriaManager.APP)
.setCmd( .setCmd(
CommonUtil.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_HIGHEST_PRIORITY, CommonUtil.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_HIGHEST_PRIORITY,
checkTaskType())) checkTaskType()))
.exe(); .exe();
} }
} }
@Override public DownloadEntity getEntity() { @Override public DownloadEntity getEntity() {
return (DownloadEntity) super.getEntity(); return (DownloadEntity) super.getEntity();
} }
} }

@ -22,6 +22,7 @@ import com.arialyy.aria.core.manager.TaskWrapperManager;
import com.arialyy.aria.core.queue.DownloadTaskQueue; import com.arialyy.aria.core.queue.DownloadTaskQueue;
import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import java.io.File; import java.io.File;
@ -113,10 +114,10 @@ class DNormalDelegate<TARGET extends AbsDTarget> implements INormalTarget {
} }
File file = new File(filePath); File file = new File(filePath);
if (file.isDirectory()) { if (file.isDirectory()) {
if (mTarget.getTargetType() == ITargetHandler.HTTP) { if (mTarget.getTargetType() == ITargetHandler.D_HTTP) {
ALog.e(TAG, "下载失败,保存路径【" + filePath + "】不能为文件夹,路径需要是完整的文件路径,如:/mnt/sdcard/game.zip"); ALog.e(TAG, "下载失败,保存路径【" + filePath + "】不能为文件夹,路径需要是完整的文件路径,如:/mnt/sdcard/game.zip");
return false; return false;
} else if (mTarget.getTargetType() == ITargetHandler.FTP) { } else if (mTarget.getTargetType() == ITargetHandler.D_FTP) {
filePath += mEntity.getFileName(); filePath += mEntity.getFileName();
} }
} else { } else {
@ -167,7 +168,7 @@ class DNormalDelegate<TARGET extends AbsDTarget> implements INormalTarget {
if (TextUtils.isEmpty(url)) { if (TextUtils.isEmpty(url)) {
ALog.e(TAG, "下载失败,url为null"); ALog.e(TAG, "下载失败,url为null");
return false; return false;
} else if (!url.startsWith("http") && !url.startsWith("ftp")) { } else if (!CheckUtil.checkUrlNotThrow(url)) {
ALog.e(TAG, "下载失败,url【" + url + "】错误"); ALog.e(TAG, "下载失败,url【" + url + "】错误");
return false; return false;
} }

@ -118,7 +118,7 @@ public class DownloadTarget extends AbsDTarget<DownloadTarget>
} }
@Override public int getTargetType() { @Override public int getTargetType() {
return HTTP; return D_HTTP;
} }
/** /**

@ -1,155 +1,155 @@
/* /*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.download; package com.arialyy.aria.core.download;
import android.support.annotation.CheckResult; import android.support.annotation.CheckResult;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.text.TextUtils; import android.text.TextUtils;
import com.arialyy.aria.core.common.ftp.FTPSDelegate; import com.arialyy.aria.core.common.ftp.FTPSDelegate;
import com.arialyy.aria.core.common.ftp.FtpDelegate; import com.arialyy.aria.core.common.ftp.FtpDelegate;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;
import com.arialyy.aria.core.inf.IFtpTarget; import com.arialyy.aria.core.inf.IFtpTarget;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import java.net.Proxy; import java.net.Proxy;
/** /**
* Created by lyy on 2016/12/5. * Created by lyy on 2016/12/5.
* https://github.com/AriaLyy/Aria * https://github.com/AriaLyy/Aria
*/ */
public class FtpDownloadTarget extends AbsDTarget<FtpDownloadTarget> public class FtpDownloadTarget extends AbsDTarget<FtpDownloadTarget>
implements IFtpTarget<FtpDownloadTarget> { implements IFtpTarget<FtpDownloadTarget> {
private FtpDelegate<FtpDownloadTarget> mFtpDelegate; private FtpDelegate<FtpDownloadTarget> mFtpDelegate;
private DNormalDelegate<FtpDownloadTarget> mNormalDelegate; private DNormalDelegate<FtpDownloadTarget> mNormalDelegate;
FtpDownloadTarget(DownloadEntity entity, String targetName) { FtpDownloadTarget(DownloadEntity entity, String targetName) {
this(entity.getUrl(), targetName); this(entity.getUrl(), targetName);
} }
FtpDownloadTarget(String url, String targetName) { FtpDownloadTarget(String url, String targetName) {
mNormalDelegate = new DNormalDelegate<>(this, url, targetName); mNormalDelegate = new DNormalDelegate<>(this, url, targetName);
init(); init();
} }
private void init() { private void init() {
int lastIndex = mNormalDelegate.getUrl().lastIndexOf("/"); int lastIndex = mNormalDelegate.getUrl().lastIndexOf("/");
getEntity().setFileName(mNormalDelegate.getUrl().substring(lastIndex + 1)); getEntity().setFileName(mNormalDelegate.getUrl().substring(lastIndex + 1));
getTaskWrapper().asFtp().setUrlEntity(CommonUtil.getFtpUrlInfo(mNormalDelegate.getUrl())); getTaskWrapper().asFtp().setUrlEntity(CommonUtil.getFtpUrlInfo(mNormalDelegate.getUrl()));
getTaskWrapper().setRequestType(AbsTaskWrapper.D_FTP); getTaskWrapper().setRequestType(AbsTaskWrapper.D_FTP);
mFtpDelegate = new FtpDelegate<>(this); mFtpDelegate = new FtpDelegate<>(this);
} }
/** /**
* 是否是FTPS协议 * 是否是FTPS协议
* 如果是FTPS协议需要使用{@link FTPSDelegate#setStorePath(String)} {@link FTPSDelegate#setAlias(String)} * 如果是FTPS协议需要使用{@link FTPSDelegate#setStorePath(String)} {@link FTPSDelegate#setAlias(String)}
* 设置证书信息 * 设置证书信息
*/ */
@CheckResult @CheckResult
public FTPSDelegate<FtpDownloadTarget> asFtps() { public FTPSDelegate<FtpDownloadTarget> asFtps() {
getTaskWrapper().asFtp().getUrlEntity().isFtps = true; getTaskWrapper().asFtp().getUrlEntity().isFtps = true;
return new FTPSDelegate<>(this); return new FTPSDelegate<>(this);
} }
@Override protected boolean checkEntity() { @Override protected boolean checkEntity() {
if (getTaskWrapper().asFtp().getUrlEntity().isFtps) { if (getTaskWrapper().asFtp().getUrlEntity().isFtps) {
if (TextUtils.isEmpty(getTaskWrapper().asFtp().getUrlEntity().storePath)) { if (TextUtils.isEmpty(getTaskWrapper().asFtp().getUrlEntity().storePath)) {
ALog.e(TAG, "证书路径为空"); ALog.e(TAG, "证书路径为空");
return false; return false;
} }
if (TextUtils.isEmpty(getTaskWrapper().asFtp().getUrlEntity().keyAlias)) { if (TextUtils.isEmpty(getTaskWrapper().asFtp().getUrlEntity().keyAlias)) {
ALog.e(TAG, "证书别名为空"); ALog.e(TAG, "证书别名为空");
return false; return false;
} }
} }
return mNormalDelegate.checkEntity(); return mNormalDelegate.checkEntity();
} }
@Override public boolean isRunning() { @Override public boolean isRunning() {
return mNormalDelegate.isRunning(); return mNormalDelegate.isRunning();
} }
@Override public boolean taskExists() { @Override public boolean taskExists() {
return mNormalDelegate.taskExists(); return mNormalDelegate.taskExists();
} }
/** /**
* 设置文件保存文件夹路径 * 设置文件保存文件夹路径
* *
* @param filePath 文件保存路径 * @param filePath 文件保存路径
* @deprecated {@link #setFilePath(String)} 请使用这个api * @deprecated {@link #setFilePath(String)} 请使用这个api
*/ */
@Deprecated @Deprecated
@CheckResult @CheckResult
public FtpDownloadTarget setDownloadPath(@NonNull String filePath) { public FtpDownloadTarget setDownloadPath(@NonNull String filePath) {
return setFilePath(filePath); return setFilePath(filePath);
} }
/** /**
* 设置文件保存文件夹路径 * 设置文件保存文件夹路径
* 关于文件名 * 关于文件名
* 1如果保存路径是该文件的保存路径/mnt/sdcard/file.zip则使用路径中的文件名file.zip * 1如果保存路径是该文件的保存路径/mnt/sdcard/file.zip则使用路径中的文件名file.zip
* 2如果保存路径是文件夹路径/mnt/sdcard/则使用FTP服务器该文件的文件名 * 2如果保存路径是文件夹路径/mnt/sdcard/则使用FTP服务器该文件的文件名
*/ */
@CheckResult @CheckResult
public FtpDownloadTarget setFilePath(@NonNull String filePath) { public FtpDownloadTarget setFilePath(@NonNull String filePath) {
mNormalDelegate.setTempFilePath(filePath); mNormalDelegate.setTempFilePath(filePath);
return this; return this;
} }
/** /**
* 设置文件存储路径如果需要修改新的文件名修改路径便可 * 设置文件存储路径如果需要修改新的文件名修改路径便可
* 原文件路径 /mnt/sdcard/test.zip * 原文件路径 /mnt/sdcard/test.zip
* 如果需要将test.zip改为game.zip只需要重新设置文件路径为/mnt/sdcard/game.zip * 如果需要将test.zip改为game.zip只需要重新设置文件路径为/mnt/sdcard/game.zip
* *
* @param filePath 路径必须为文件路径不能为文件夹路径 * @param filePath 路径必须为文件路径不能为文件夹路径
* @param forceDownload {@code true}强制下载不考虑文件路径是否被占用 * @param forceDownload {@code true}强制下载不考虑文件路径是否被占用
*/ */
@CheckResult @CheckResult
public FtpDownloadTarget setFilePath(@NonNull String filePath, boolean forceDownload) { public FtpDownloadTarget setFilePath(@NonNull String filePath, boolean forceDownload) {
mNormalDelegate.setTempFilePath(filePath); mNormalDelegate.setTempFilePath(filePath);
mNormalDelegate.setForceDownload(forceDownload); mNormalDelegate.setForceDownload(forceDownload);
return this; return this;
} }
@Override public int getTargetType() { @Override public int getTargetType() {
return FTP; return D_FTP;
} }
@CheckResult @CheckResult
@Override public FtpDownloadTarget charSet(String charSet) { @Override public FtpDownloadTarget charSet(String charSet) {
return mFtpDelegate.charSet(charSet); return mFtpDelegate.charSet(charSet);
} }
@CheckResult @CheckResult
@Override public FtpDownloadTarget login(String userName, String password) { @Override public FtpDownloadTarget login(String userName, String password) {
return mFtpDelegate.login(userName, password); return mFtpDelegate.login(userName, password);
} }
@CheckResult @CheckResult
@Override public FtpDownloadTarget login(String userName, String password, String account) { @Override public FtpDownloadTarget login(String userName, String password, String account) {
return mFtpDelegate.login(userName, password, account); return mFtpDelegate.login(userName, password, account);
} }
@CheckResult @CheckResult
@Override public FtpDownloadTarget setProxy(Proxy proxy) { @Override public FtpDownloadTarget setProxy(Proxy proxy) {
return mFtpDelegate.setProxy(proxy); return mFtpDelegate.setProxy(proxy);
} }
@Override public FtpDownloadTarget updateUrl(String newUrl) { @Override public FtpDownloadTarget updateUrl(String newUrl) {
return mNormalDelegate.updateUrl(newUrl); return mNormalDelegate.updateUrl(newUrl);
} }
} }

@ -22,6 +22,7 @@ import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -61,11 +62,11 @@ class HttpGroupDelegate extends AbsGroupDelegate<DownloadGroupTarget> {
@CheckResult @CheckResult
DownloadGroupTarget setSubFileName(List<String> subTaskFileName) { DownloadGroupTarget setSubFileName(List<String> subTaskFileName) {
if (subTaskFileName == null || subTaskFileName.isEmpty()) { if (subTaskFileName == null || subTaskFileName.isEmpty()) {
ALog.e(TAG, "修改子任务的文件名失败:列表为null"); ALog.w(TAG, "修改子任务的文件名失败:列表为null");
return getTarget(); return getTarget();
} }
if (subTaskFileName.size() != getTaskWrapper().getSubTaskWrapper().size()) { if (subTaskFileName.size() != getTaskWrapper().getSubTaskWrapper().size()) {
ALog.e(TAG, "修改子任务的文件名失败:子任务文件名列表数量和子任务的数量不匹配"); ALog.w(TAG, "修改子任务的文件名失败:子任务文件名列表数量和子任务的数量不匹配");
return getTarget(); return getTarget();
} }
mSubNameTemp.clear(); mSubNameTemp.clear();
@ -179,6 +180,19 @@ class HttpGroupDelegate extends AbsGroupDelegate<DownloadGroupTarget> {
ALog.e(TAG, "下载失败,子任务下载列表为null"); ALog.e(TAG, "下载失败,子任务下载列表为null");
return false; return false;
} }
Set<String> repeated = new HashSet<>();
List<String> results = new ArrayList<>();
for (String url : mUrls) {
if (!repeated.add(url)) {
results.add(url);
}
}
if (!results.isEmpty()) {
ALog.e(TAG, String.format("组合任务中有url重复,重复的url:%s", Arrays.toString(results.toArray())));
return false;
}
Set<Integer> delItem = new HashSet<>(); Set<Integer> delItem = new HashSet<>();
int i = 0; int i = 0;
@ -188,7 +202,6 @@ class HttpGroupDelegate extends AbsGroupDelegate<DownloadGroupTarget> {
delItem.add(i); delItem.add(i);
continue; continue;
} else if (!url.startsWith("http")) { } else if (!url.startsWith("http")) {
//} else if (!url.startsWith("http") && !url.startsWith("ftp")) {
ALog.e(TAG, "子任务url【" + url + "】错误,即将删除该子任务。"); ALog.e(TAG, "子任务url【" + url + "】错误,即将删除该子任务。");
delItem.add(i); delItem.add(i);
continue; continue;

@ -41,7 +41,7 @@ public abstract class AbsGroupUtil implements IUtil, Runnable {
*/ */
int FTP_DIR = 0xa1; int FTP_DIR = 0xa1;
/** /**
* HTTP 任务组 * D_HTTP 任务组
*/ */
int HTTP_GROUP = 0xa2; int HTTP_GROUP = 0xa2;

@ -148,7 +148,7 @@ public class DownloadGroupUtil extends AbsGroupUtil implements IUtil {
mGTWrapper.asHttp().setFileLenAdapter(null); mGTWrapper.asHttp().setFileLenAdapter(null);
synchronized (LOCK) { synchronized (LOCK) {
LOCK.notify(); LOCK.notifyAll();
} }
} }

@ -15,6 +15,8 @@
*/ */
package com.arialyy.aria.core.inf; package com.arialyy.aria.core.inf;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.CheckResult; import android.support.annotation.CheckResult;
import android.text.TextUtils; import android.text.TextUtils;
import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.AriaManager;
@ -25,6 +27,10 @@ import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.download.DownloadGroupEntity; import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.manager.TaskWrapperManager; import com.arialyy.aria.core.manager.TaskWrapperManager;
import com.arialyy.aria.core.scheduler.DownloadGroupSchedulers;
import com.arialyy.aria.core.scheduler.DownloadSchedulers;
import com.arialyy.aria.core.scheduler.ISchedulers;
import com.arialyy.aria.core.scheduler.UploadSchedulers;
import com.arialyy.aria.core.upload.UTaskWrapper; import com.arialyy.aria.core.upload.UTaskWrapper;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
@ -196,11 +202,41 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
return taskType; return taskType;
} }
/**
* 如果检查实体失败将错误回调
*/
protected boolean checkConfig() {
boolean b = checkEntity();
ISchedulers schedulers = getScheduler();
if (!b && schedulers != null) {
new Handler(Looper.getMainLooper(), schedulers).obtainMessage(ISchedulers.FAIL,
new TempTask(mTaskWrapper, mEntity)).sendToTarget();
}
return b;
}
private ISchedulers getScheduler() {
int type = getTargetType();
switch (type) {
case D_FTP:
case D_HTTP:
return DownloadSchedulers.getInstance();
case U_FTP:
case U_HTTP:
return UploadSchedulers.getInstance();
case GROUP_HTTP:
case GROUP_FTP_DIR:
return DownloadGroupSchedulers.getInstance();
}
return null;
}
/** /**
* 保存修改 * 保存修改
*/ */
@Override public void save() { @Override public void save() {
if (!checkEntity()) { if (!checkConfig()) {
ALog.e(TAG, "保存修改失败"); ALog.e(TAG, "保存修改失败");
} else { } else {
ALog.i(TAG, "保存成功"); ALog.i(TAG, "保存成功");
@ -224,7 +260,8 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
/** /**
* 设置target类型 * 设置target类型
* *
* @return {@link #HTTP}{@link #FTP}{@link #GROUP_HTTP}{@link #GROUP_FTP_DIR} * @return {@link #D_HTTP}{@link #U_HTTP}{@link #D_FTP}{@link #U_FTP}{@link
* #GROUP_HTTP}{@link #GROUP_FTP_DIR}
*/ */
public abstract int getTargetType(); public abstract int getTargetType();
@ -232,7 +269,7 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
* 添加任务 * 添加任务
*/ */
@Override public void add() { @Override public void add() {
if (checkEntity()) { if (checkConfig()) {
AriaManager.getInstance(AriaManager.APP) AriaManager.getInstance(AriaManager.APP)
.setCmd(CommonUtil.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_CREATE, .setCmd(CommonUtil.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_CREATE,
checkTaskType())) checkTaskType()))
@ -244,7 +281,7 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
* 开始任务 * 开始任务
*/ */
@Override public void start() { @Override public void start() {
if (checkEntity()) { if (checkConfig()) {
AriaManager.getInstance(AriaManager.APP) AriaManager.getInstance(AriaManager.APP)
.setCmd( .setCmd(
CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START, CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START,
@ -259,13 +296,13 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
* @see #stop() * @see #stop()
*/ */
@Deprecated public void pause() { @Deprecated public void pause() {
if (checkEntity()) { if (checkConfig()) {
stop(); stop();
} }
} }
@Override public void stop() { @Override public void stop() {
if (checkEntity()) { if (checkConfig()) {
AriaManager.getInstance(AriaManager.APP) AriaManager.getInstance(AriaManager.APP)
.setCmd( .setCmd(
CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_STOP, checkTaskType())) CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_STOP, checkTaskType()))
@ -277,7 +314,7 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
* 恢复任务 * 恢复任务
*/ */
@Override public void resume() { @Override public void resume() {
if (checkEntity()) { if (checkConfig()) {
AriaManager.getInstance(AriaManager.APP) AriaManager.getInstance(AriaManager.APP)
.setCmd( .setCmd(
CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START, CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_START,
@ -290,7 +327,7 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
* 删除任务 * 删除任务
*/ */
@Override public void cancel() { @Override public void cancel() {
if (checkEntity()) { if (checkConfig()) {
AriaManager.getInstance(AriaManager.APP) AriaManager.getInstance(AriaManager.APP)
.setCmd(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_CANCEL, .setCmd(CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_CANCEL,
checkTaskType())) checkTaskType()))
@ -302,7 +339,7 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
* 任务重试 * 任务重试
*/ */
@Override public void reTry() { @Override public void reTry() {
if (checkEntity()) { if (checkConfig()) {
List<ICmd> cmds = new ArrayList<>(); List<ICmd> cmds = new ArrayList<>();
int taskType = checkTaskType(); int taskType = checkTaskType();
cmds.add( cmds.add(
@ -319,7 +356,7 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
* {@code false}如果任务已经完成只删除任务数据库记录 * {@code false}如果任务已经完成只删除任务数据库记录
*/ */
@Override public void cancel(boolean removeFile) { @Override public void cancel(boolean removeFile) {
if (checkEntity()) { if (checkConfig()) {
CancelCmd cancelCmd = CancelCmd cancelCmd =
(CancelCmd) CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_CANCEL, (CancelCmd) CommonUtil.createNormalCmd(mTaskWrapper, NormalCmdFactory.TASK_CANCEL,
checkTaskType()); checkTaskType());
@ -332,9 +369,80 @@ public abstract class AbsTarget<TARGET extends AbsTarget> implements ITargetHand
* 重新下载 * 重新下载
*/ */
@Override public void reStart() { @Override public void reStart() {
if (checkEntity()) { if (checkConfig()) {
cancel(); cancel();
start(); start();
} }
} }
private static class TempTask implements ITask {
private AbsTaskWrapper wrapper;
private AbsEntity entity;
private TempTask(AbsTaskWrapper wrapper, AbsEntity entity) {
this.wrapper = wrapper;
this.entity = entity;
}
@Override public int getTaskType() {
return TEMP;
}
@Override public int getState() {
return entity.getState();
}
@Override public String getKey() {
return entity.getKey();
}
@Override public boolean isRunning() {
return false;
}
@Override public AbsTaskWrapper getTaskWrapper() {
return wrapper;
}
@Override public void start() {
}
@Override public void stop() {
}
@Override public void stop(int type) {
}
@Override public void cancel() {
}
@Override public Object getExpand(String key) {
return null;
}
@Override public boolean isStop() {
return false;
}
@Override public boolean isCancel() {
return false;
}
@Override public boolean isNeedRetry() {
return false;
}
@Override public String getTaskName() {
return "TempTask";
}
@Override public int getSchedulerType() {
return TaskSchedulerType.TYPE_DEFAULT;
}
}
} }

@ -32,9 +32,9 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
public static final String ERROR_INFO_KEY = "ERROR_INFO_KEY"; public static final String ERROR_INFO_KEY = "ERROR_INFO_KEY";
/** /**
* 是否需要重试默认为true * 是否需要重试默认为false
*/ */
public boolean needRetry = true; private boolean needRetry = true;
protected TASK_WRAPPER mTaskWrapper; protected TASK_WRAPPER mTaskWrapper;
protected Handler mOutHandler; protected Handler mOutHandler;
protected Context mContext; protected Context mContext;
@ -76,9 +76,18 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
mExpand.put(key, obj); mExpand.put(key, obj);
} }
@Override public boolean isNeedRetry() {
return needRetry;
}
public void setNeedRetry(boolean needRetry) {
this.needRetry = needRetry;
}
/** /**
* 读取扩展数据 * 读取扩展数据
*/ */
@Override
public Object getExpand(String key) { public Object getExpand(String key) {
return mExpand.get(key); return mExpand.get(key);
} }
@ -106,7 +115,7 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
/** /**
* 获取当前下载进度 * 获取当前下载进度
*/ */
@Override public long getCurrentProgress() { public long getCurrentProgress() {
return mTaskWrapper.getEntity().getCurrentProgress(); return mTaskWrapper.getEntity().getCurrentProgress();
} }
@ -115,7 +124,7 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
* *
* @return 已经下载3mb的大小则返回{@code 3mb} * @return 已经下载3mb的大小则返回{@code 3mb}
*/ */
@Override public String getConvertCurrentProgress() { public String getConvertCurrentProgress() {
if (mTaskWrapper.getEntity().getCurrentProgress() == 0) { if (mTaskWrapper.getEntity().getCurrentProgress() == 0) {
return "0b"; return "0b";
} }
@ -127,7 +136,7 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
* *
* @return 如果文件长度为0则返回0m否则返回转换后的长度1b1kb1mb1gb1tb * @return 如果文件长度为0则返回0m否则返回转换后的长度1b1kb1mb1gb1tb
*/ */
@Override public String getConvertFileSize() { public String getConvertFileSize() {
if (mTaskWrapper.getEntity().getFileSize() == 0) { if (mTaskWrapper.getEntity().getFileSize() == 0) {
return "0mb"; return "0mb";
} }
@ -137,7 +146,7 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
/** /**
* 获取文件大小 * 获取文件大小
*/ */
@Override public long getFileSize() { public long getFileSize() {
return mTaskWrapper.getEntity().getFileSize(); return mTaskWrapper.getEntity().getFileSize();
} }
@ -146,7 +155,7 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
* *
* @return 返回百分比进度如果文件长度为0返回0 * @return 返回百分比进度如果文件长度为0返回0
*/ */
@Override public int getPercent() { public int getPercent() {
if (mTaskWrapper.getEntity().getFileSize() == 0) { if (mTaskWrapper.getEntity().getFileSize() == 0) {
return 0; return 0;
} }
@ -217,6 +226,7 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
/** /**
* 任务的调度类型 * 任务的调度类型
*/ */
@Override
public int getSchedulerType() { public int getSchedulerType() {
return mSchedulerType; return mSchedulerType;
} }
@ -226,6 +236,7 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
* *
* @return {@code true}任务已经取消 * @return {@code true}任务已经取消
*/ */
@Override
public boolean isCancel() { public boolean isCancel() {
return isCancel; return isCancel;
} }
@ -235,6 +246,7 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
* *
* @return {@code true}任务已经停止 * @return {@code true}任务已经停止
*/ */
@Override
public boolean isStop() { public boolean isStop() {
return isStop; return isStop;
} }
@ -256,7 +268,7 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
* </pre> * </pre>
* 才能生效 * 才能生效
*/ */
@Override public long getSpeed() { public long getSpeed() {
return mTaskWrapper.getEntity().getSpeed(); return mTaskWrapper.getEntity().getSpeed();
} }
@ -277,7 +289,7 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
* </pre> * </pre>
* 才能生效 * 才能生效
*/ */
@Override public String getConvertSpeed() { public String getConvertSpeed() {
return mTaskWrapper.getEntity().getConvertSpeed(); return mTaskWrapper.getEntity().getConvertSpeed();
} }
@ -285,11 +297,6 @@ public abstract class AbsTask<ENTITY extends AbsEntity, TASK_WRAPPER extends Abs
return mTaskWrapper; return mTaskWrapper;
} }
/**
* 获取任务名也就是文件名
*/
public abstract String getTaskName();
public boolean isHighestPriorityTask() { public boolean isHighestPriorityTask() {
return isHeighestTask; return isHeighestTask;
} }

@ -39,11 +39,6 @@ public abstract class AbsTaskWrapper<ENTITY extends AbsEntity>
*/ */
private boolean refreshInfo = false; private boolean refreshInfo = false;
/**
* 任务状态和Entity的state同步
*/
private int state = IEntity.STATE_WAIT;
/** /**
* 是否是新任务{@code true} 新任务 * 是否是新任务{@code true} 新任务
*/ */
@ -142,7 +137,6 @@ public abstract class AbsTaskWrapper<ENTITY extends AbsEntity>
} }
public void setState(int state) { public void setState(int state) {
this.state = state;
entity.setState(state); entity.setState(state);
} }

@ -1,50 +1,50 @@
/* /*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.inf; package com.arialyy.aria.core.inf;
import android.support.annotation.CheckResult; import android.support.annotation.CheckResult;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import java.net.Proxy; import java.net.Proxy;
import java.util.Map; import java.util.Map;
/** /**
* Created by laoyuyu on 2018/3/9. * Created by laoyuyu on 2018/3/9.
* HTTP Header功能接口 * D_HTTP Header功能接口
*/ */
public interface IHttpHeaderDelegate<TARGET extends ITargetHandler> { public interface IHttpHeaderDelegate<TARGET extends ITargetHandler> {
/** /**
* 给url请求添加Header数据 * 给url请求添加Header数据
* 如果新的header数据和数据保存的不一致则更新数据库中对应的header数据 * 如果新的header数据和数据保存的不一致则更新数据库中对应的header数据
* *
* @param key header对应的key * @param key header对应的key
* @param value header对应的value * @param value header对应的value
*/ */
@CheckResult @CheckResult
TARGET addHeader(@NonNull String key, @NonNull String value); TARGET addHeader(@NonNull String key, @NonNull String value);
/** /**
* 给url请求添加一组header数据 * 给url请求添加一组header数据
* 如果新的header数据和数据保存的不一致则更新数据库中对应的header数据 * 如果新的header数据和数据保存的不一致则更新数据库中对应的header数据
* *
* @param headers 一组http header数据 * @param headers 一组http header数据
*/ */
@CheckResult @CheckResult
TARGET addHeaders(Map<String, String> headers); TARGET addHeaders(Map<String, String> headers);
@CheckResult @CheckResult
TARGET setUrlProxy(Proxy proxy); TARGET setUrlProxy(Proxy proxy);
} }

@ -1,77 +1,79 @@
/* /*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.inf; package com.arialyy.aria.core.inf;
/** /**
* Created by AriaL on 2017/6/29. * Created by AriaL on 2017/6/29.
* 任务接收器的控制接口处理添加任务开始任务停止任务删除任务等功能 * 任务接收器的控制接口处理添加任务开始任务停止任务删除任务等功能
*/ */
public interface ITargetHandler { public interface ITargetHandler {
int HTTP = 1; int D_HTTP = 1;
int FTP = 2; int U_HTTP = 2;
//HTTP任务组 int U_FTP = 3;
int GROUP_HTTP = 3; int D_FTP = 4;
//FTP文件夹 //HTTP任务组
int GROUP_FTP_DIR = 4; int GROUP_HTTP = 5;
//FTP文件夹
/** int GROUP_FTP_DIR = 6;
* 添加任务
*/ /**
void add(); * 添加任务
*/
/** void add();
* 开始下载
*/ /**
void start(); * 开始下载
*/
/** void start();
* 停止下载
*/ /**
void stop(); * 停止下载
*/
/** void stop();
* 恢复下载
*/ /**
void resume(); * 恢复下载
*/
/** void resume();
* 取消下载
*/ /**
void cancel(); * 取消下载
*/
/** void cancel();
* 保存修改
*/ /**
void save(); * 保存修改
*/
/** void save();
* 删除任务
* /**
* @param removeFile {@code true} 不仅删除任务数据库记录还会删除已经删除完成的文件 * 删除任务
* {@code false}如果任务已经完成只删除任务数据库记录 *
*/ * @param removeFile {@code true} 不仅删除任务数据库记录还会删除已经删除完成的文件
void cancel(boolean removeFile); * {@code false}如果任务已经完成只删除任务数据库记录
*/
/** void cancel(boolean removeFile);
* 任务重试
*/ /**
void reTry(); * 任务重试
*/
/** void reTry();
* 重新下载
*/ /**
void reStart(); * 重新下载
} */
void reStart();
}

@ -1,133 +1,139 @@
/* /*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.inf; package com.arialyy.aria.core.inf;
import com.arialyy.aria.core.download.DownloadGroupTask; import com.arialyy.aria.core.download.DownloadGroupTask;
import com.arialyy.aria.core.download.DownloadTask; import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.core.upload.UploadTask; import com.arialyy.aria.core.upload.UploadTask;
/** /**
* Created by lyy on 2017/2/13. * Created by lyy on 2017/2/13.
* 任务接口{@link DownloadTask}{@link UploadTask}{@link DownloadGroupTask} * 任务接口{@link DownloadTask}{@link UploadTask}{@link DownloadGroupTask}
*/ */
public interface ITask<TASK_WRAPPER extends AbsTaskWrapper> { public interface ITask<TASK_WRAPPER extends AbsTaskWrapper> {
/** /**
* 普通下载任务 * 普通下载任务
*/ */
int DOWNLOAD = 1; int DOWNLOAD = 1;
/** /**
* 上传任务 * 上传任务
*/ */
int UPLOAD = 2; int UPLOAD = 2;
/** /**
* 组合任务 * 组合任务
*/ */
int DOWNLOAD_GROUP = 3; int DOWNLOAD_GROUP = 3;
/** /**
* 组合任务的子任务 * 组合任务的子任务
*/ */
int DOWNLOAD_GROUP_SUB = 4; int DOWNLOAD_GROUP_SUB = 4;
/** /**
* 未知 * 填充的
*/ */
int OTHER = -1; int TEMP = 5;
/**
/** * 未知
* 获取任务类型 */
* int OTHER = -1;
* @return {@link #DOWNLOAD}{@link #UPLOAD}{@link #DOWNLOAD_GROUP}
*/ /**
int getTaskType(); * 获取任务类型
*
/** * @return {@link #DOWNLOAD}{@link #UPLOAD}{@link #DOWNLOAD_GROUP}
* 获取下载状态 */
*/ int getTaskType();
int getState();
/**
/** * 获取下载状态
* 唯一标识符DownloadTask 为下载地址UploadTask 为文件路径 */
*/ int getState();
String getKey();
/**
/** * 唯一标识符DownloadTask 为下载地址UploadTask 为文件路径
* 任务是否正在执行 */
* String getKey();
* @return true正在执行
*/ /**
boolean isRunning(); * 任务是否正在执行
*
/** * @return true正在执行
* 获取信息实体 */
*/ boolean isRunning();
TASK_WRAPPER getTaskWrapper();
/**
void start(); * 获取信息实体
*/
/** TASK_WRAPPER getTaskWrapper();
* 停止任务
*/ void start();
void stop();
/**
/** * 停止任务
* 停止任务 */
* void stop();
* @param type {@code 0}默认操作{@code 1}停止任务不自动执行下一任务
*/ /**
void stop(int type); * 停止任务
*
/** * @param type {@code 0}默认操作{@code 1}停止任务不自动执行下一任务
* 删除任务 */
*/ void stop(int type);
void cancel();
/**
/** * 删除任务
* 原始byte速度 */
*/ void cancel();
long getSpeed();
/**
/** * 读取扩展数据
* 转换单位后的速度 */
*/ Object getExpand(String key);
String getConvertSpeed();
/**
/** * 任务是否停止了
* 获取百分比进度 *
*/ * @return {@code true}任务已经停止
int getPercent(); */
boolean isStop();
/**
* 原始文件byte长度 /**
*/ * 任务是否取消了
long getFileSize(); *
* @return {@code true}任务已经取消
/** */
* 转换单位后的文件长度 boolean isCancel();
*/
String getConvertFileSize(); /**
* 任务是否需要重试
/** *
* 获取当前进度 * @return {@code true}任务已经取消
*/ */
long getCurrentProgress(); boolean isNeedRetry();
/** /**
* 获取单位转换后的进度 * 获取任务名也就是文件名
* */
* @return 返回 3mb String getTaskName();
*/
String getConvertCurrentProgress(); /**
} * 任务的调度类型
* {@link TaskSchedulerType}
*/
int getSchedulerType();
}

@ -22,13 +22,14 @@ import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.inf.AbsTask; import com.arialyy.aria.core.inf.AbsTask;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;
import com.arialyy.aria.core.inf.ITask;
import com.arialyy.aria.core.upload.UploadTask; import com.arialyy.aria.core.upload.UploadTask;
import com.arialyy.aria.core.upload.UTaskWrapper; import com.arialyy.aria.core.upload.UTaskWrapper;
/** /**
* Created by lyy on 2016/8/16. 任务功能接口 * Created by lyy on 2016/8/16. 任务功能接口
*/ */
public interface ITaskQueue<TASK extends AbsTask, TASK_WRAPPER extends AbsTaskWrapper> { public interface ITaskQueue<TASK extends ITask, TASK_WRAPPER extends AbsTaskWrapper> {
/** /**
* 通过key跑断任务是在存在 * 通过key跑断任务是在存在

@ -45,7 +45,7 @@ import java.util.concurrent.TimeUnit;
/** /**
* Created by lyy on 2017/6/4. 事件调度器用于处理任务状态的调度 * Created by lyy on 2017/6/4. 事件调度器用于处理任务状态的调度
*/ */
abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends AbsTask, abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends ITask,
QUEUE extends ITaskQueue<TASK, TASK_ENTITY>> implements ISchedulers { QUEUE extends ITaskQueue<TASK, TASK_ENTITY>> implements ISchedulers {
private final String TAG = "AbsSchedulers"; private final String TAG = "AbsSchedulers";
@ -273,7 +273,8 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends Ab
listener.onTaskComplete(task); listener.onTaskComplete(task);
break; break;
case FAIL: case FAIL:
listener.onTaskFail(task, (Exception) task.getExpand(AbsTask.ERROR_INFO_KEY)); listener.onTaskFail(task.getTaskType() == ITask.TEMP ? null : task,
(Exception) task.getExpand(AbsTask.ERROR_INFO_KEY));
break; break;
case NO_SUPPORT_BREAK_POINT: case NO_SUPPORT_BREAK_POINT:
listener.onNoSupportBreakPoint(task); listener.onNoSupportBreakPoint(task);
@ -290,12 +291,13 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends Ab
if (!canSend) { if (!canSend) {
return; return;
} }
if (task.getTaskType() == ITask.DOWNLOAD || task.getTaskType() == ITask.DOWNLOAD_GROUP) { int type = task.getTaskType();
if (type == ITask.DOWNLOAD || type == ITask.DOWNLOAD_GROUP) {
AriaManager.APP.sendBroadcast( AriaManager.APP.sendBroadcast(
createData(state, task.getTaskType(), task.getTaskWrapper().getEntity())); createData(state, type, task.getTaskWrapper().getEntity()));
} else if (task.getTaskType() == ITask.UPLOAD) { } else if (type == ITask.UPLOAD) {
AriaManager.APP.sendBroadcast( AriaManager.APP.sendBroadcast(
createData(state, task.getTaskType(), task.getTaskWrapper().getEntity())); createData(state, type, task.getTaskWrapper().getEntity()));
} else { } else {
ALog.w(TAG, "发送广播失败,没有对应的任务"); ALog.w(TAG, "发送广播失败,没有对应的任务");
} }
@ -326,7 +328,7 @@ abstract class AbsSchedulers<TASK_ENTITY extends AbsTaskWrapper, TASK extends Ab
* @param task 下载任务 * @param task 下载任务
*/ */
private void handleFailTask(final TASK task) { private void handleFailTask(final TASK task) {
if (!task.needRetry || task.isStop() || task.isCancel()) { if (!task.isNeedRetry() || task.isStop() || task.isCancel()) {
mQueue.removeTaskFormQueue(task.getKey()); mQueue.removeTaskFormQueue(task.getKey());
startNextTask(task); startNextTask(task);
callback(FAIL, task); callback(FAIL, task);

@ -1,104 +1,104 @@
/* /*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.upload; package com.arialyy.aria.core.upload;
import android.support.annotation.CheckResult; import android.support.annotation.CheckResult;
import com.arialyy.aria.core.FtpUrlEntity; import com.arialyy.aria.core.FtpUrlEntity;
import com.arialyy.aria.core.common.ftp.FTPSDelegate; import com.arialyy.aria.core.common.ftp.FTPSDelegate;
import com.arialyy.aria.core.common.ftp.FtpDelegate; import com.arialyy.aria.core.common.ftp.FtpDelegate;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;
import com.arialyy.aria.core.inf.IFtpTarget; import com.arialyy.aria.core.inf.IFtpTarget;
import com.arialyy.aria.util.CheckUtil; import com.arialyy.aria.util.CheckUtil;
import java.net.Proxy; import java.net.Proxy;
/** /**
* Created by Aria.Lao on 2017/7/27. * Created by Aria.Lao on 2017/7/27.
* ftp单任务上传 * ftp单任务上传
*/ */
public class FtpUploadTarget extends AbsUploadTarget<FtpUploadTarget> public class FtpUploadTarget extends AbsUploadTarget<FtpUploadTarget>
implements IFtpTarget<FtpUploadTarget> { implements IFtpTarget<FtpUploadTarget> {
private FtpDelegate<FtpUploadTarget> mFtpDelegate; private FtpDelegate<FtpUploadTarget> mFtpDelegate;
private UNormalDelegate<FtpUploadTarget> mNormalDelegate; private UNormalDelegate<FtpUploadTarget> mNormalDelegate;
FtpUploadTarget(String filePath, String targetName) { FtpUploadTarget(String filePath, String targetName) {
mNormalDelegate = new UNormalDelegate<>(this, filePath, targetName); mNormalDelegate = new UNormalDelegate<>(this, filePath, targetName);
initTask(); initTask();
} }
private void initTask() { private void initTask() {
getTaskWrapper().setRequestType(AbsTaskWrapper.U_FTP); getTaskWrapper().setRequestType(AbsTaskWrapper.U_FTP);
mFtpDelegate = new FtpDelegate<>(this); mFtpDelegate = new FtpDelegate<>(this);
} }
/** /**
* 设置上传路径 * 设置上传路径
* *
* @param tempUrl 上传路径 * @param tempUrl 上传路径
*/ */
public FtpUploadTarget setUploadUrl(String tempUrl) { public FtpUploadTarget setUploadUrl(String tempUrl) {
mNormalDelegate.setTempUrl(tempUrl); mNormalDelegate.setTempUrl(tempUrl);
return this; return this;
} }
/** /**
* 是否是FTPS协议 * 是否是FTPS协议
* 如果是FTPS协议需要使用{@link FTPSDelegate#setStorePath(String)} {@link FTPSDelegate#setAlias(String)} * 如果是FTPS协议需要使用{@link FTPSDelegate#setStorePath(String)} {@link FTPSDelegate#setAlias(String)}
* 设置证书信息 * 设置证书信息
*/ */
@CheckResult @CheckResult
public FTPSDelegate<FtpUploadTarget> asFtps() { public FTPSDelegate<FtpUploadTarget> asFtps() {
if (getTaskWrapper().asFtp().getUrlEntity() == null) { if (getTaskWrapper().asFtp().getUrlEntity() == null) {
FtpUrlEntity urlEntity = new FtpUrlEntity(); FtpUrlEntity urlEntity = new FtpUrlEntity();
urlEntity.isFtps = true; urlEntity.isFtps = true;
getTaskWrapper().asFtp().setUrlEntity(urlEntity); getTaskWrapper().asFtp().setUrlEntity(urlEntity);
} }
return new FTPSDelegate<>(this); return new FTPSDelegate<>(this);
} }
@CheckResult @CheckResult
@Override public FtpUploadTarget charSet(String charSet) { @Override public FtpUploadTarget charSet(String charSet) {
return mFtpDelegate.charSet(charSet); return mFtpDelegate.charSet(charSet);
} }
@Override public FtpUploadTarget login(String userName, String password) { @Override public FtpUploadTarget login(String userName, String password) {
return mFtpDelegate.login(userName, password); return mFtpDelegate.login(userName, password);
} }
@Override public FtpUploadTarget login(String userName, String password, String account) { @Override public FtpUploadTarget login(String userName, String password, String account) {
CheckUtil.checkFtpUploadUrl(mNormalDelegate.getTempUrl()); CheckUtil.checkFtpUploadUrl(mNormalDelegate.getTempUrl());
return mFtpDelegate.login(userName, password, account); return mFtpDelegate.login(userName, password, account);
} }
@Override public FtpUploadTarget setProxy(Proxy proxy) { @Override public FtpUploadTarget setProxy(Proxy proxy) {
return mFtpDelegate.setProxy(proxy); return mFtpDelegate.setProxy(proxy);
} }
@Override protected boolean checkEntity() { @Override protected boolean checkEntity() {
return mNormalDelegate.checkEntity(); return mNormalDelegate.checkEntity();
} }
@Override public boolean isRunning() { @Override public boolean isRunning() {
return mNormalDelegate.isRunning(); return mNormalDelegate.isRunning();
} }
@Override public boolean taskExists() { @Override public boolean taskExists() {
return mNormalDelegate.taskExists(); return mNormalDelegate.taskExists();
} }
@Override public int getTargetType() { @Override public int getTargetType() {
return FTP; return U_FTP;
} }
} }

@ -22,6 +22,7 @@ import com.arialyy.aria.core.manager.TaskWrapperManager;
import com.arialyy.aria.core.queue.UploadTaskQueue; import com.arialyy.aria.core.queue.UploadTaskQueue;
import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import java.io.File; import java.io.File;
@ -121,7 +122,7 @@ class UNormalDelegate<TARGET extends AbsUploadTarget> implements INormalTarget {
if (TextUtils.isEmpty(url)) { if (TextUtils.isEmpty(url)) {
ALog.e(TAG, "上传失败,url为null"); ALog.e(TAG, "上传失败,url为null");
return false; return false;
} else if (!url.startsWith("http") && !url.startsWith("ftp")) { } else if (!CheckUtil.checkUrlNotThrow(url)) {
ALog.e(TAG, "上传失败,url【" + url + "】错误"); ALog.e(TAG, "上传失败,url【" + url + "】错误");
return false; return false;
} }

@ -1,125 +1,125 @@
/* /*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.upload; package com.arialyy.aria.core.upload;
import android.support.annotation.CheckResult; import android.support.annotation.CheckResult;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import com.arialyy.aria.core.common.http.HttpHeaderDelegate; import com.arialyy.aria.core.common.http.HttpHeaderDelegate;
import com.arialyy.aria.core.common.http.PostDelegate; import com.arialyy.aria.core.common.http.PostDelegate;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;
import com.arialyy.aria.core.inf.IHttpHeaderDelegate; import com.arialyy.aria.core.inf.IHttpHeaderDelegate;
import java.net.Proxy; import java.net.Proxy;
import java.util.Map; import java.util.Map;
/** /**
* Created by lyy on 2017/2/28. * Created by lyy on 2017/2/28.
* http 单文件上传 * http 单文件上传
*/ */
public class UploadTarget extends AbsUploadTarget<UploadTarget> public class UploadTarget extends AbsUploadTarget<UploadTarget>
implements IHttpHeaderDelegate<UploadTarget> { implements IHttpHeaderDelegate<UploadTarget> {
private HttpHeaderDelegate<UploadTarget> mHeaderDelegate; private HttpHeaderDelegate<UploadTarget> mHeaderDelegate;
private UNormalDelegate<UploadTarget> mNormalDelegate; private UNormalDelegate<UploadTarget> mNormalDelegate;
UploadTarget(String filePath, String targetName) { UploadTarget(String filePath, String targetName) {
mNormalDelegate = new UNormalDelegate<>(this, filePath, targetName); mNormalDelegate = new UNormalDelegate<>(this, filePath, targetName);
initTask(); initTask();
} }
private void initTask() { private void initTask() {
//http暂时不支持断点上传 //http暂时不支持断点上传
getTaskWrapper().setSupportBP(false); getTaskWrapper().setSupportBP(false);
getTaskWrapper().setRequestType(AbsTaskWrapper.U_HTTP); getTaskWrapper().setRequestType(AbsTaskWrapper.U_HTTP);
mHeaderDelegate = new HttpHeaderDelegate<>(this); mHeaderDelegate = new HttpHeaderDelegate<>(this);
} }
/** /**
* 设置上传路径 * 设置上传路径
* *
* @param tempUrl 上传路径 * @param tempUrl 上传路径
*/ */
public UploadTarget setUploadUrl(String tempUrl) { public UploadTarget setUploadUrl(String tempUrl) {
mNormalDelegate.setTempUrl(tempUrl); mNormalDelegate.setTempUrl(tempUrl);
return this; return this;
} }
/** /**
* Post处理 * Post处理
*/ */
public PostDelegate asPost() { public PostDelegate asPost() {
return new PostDelegate<>(this); return new PostDelegate<>(this);
} }
/** /**
* 设置userAgent * 设置userAgent
*/ */
@CheckResult @CheckResult
public UploadTarget setUserAngent(@NonNull String userAgent) { public UploadTarget setUserAngent(@NonNull String userAgent) {
getTaskWrapper().asHttp().setUserAgent(userAgent); getTaskWrapper().asHttp().setUserAgent(userAgent);
return this; return this;
} }
/** /**
* 设置服务器需要的附件key * 设置服务器需要的附件key
* *
* @param attachment 附件key * @param attachment 附件key
*/ */
@CheckResult @CheckResult
public UploadTarget setAttachment(@NonNull String attachment) { public UploadTarget setAttachment(@NonNull String attachment) {
getTaskWrapper().asHttp().setAttachment(attachment); getTaskWrapper().asHttp().setAttachment(attachment);
return this; return this;
} }
/** /**
* 设置上传文件类型 * 设置上传文件类型
* *
* @param contentType tipmultipart/form-data * @param contentType tipmultipart/form-data
*/ */
@CheckResult @CheckResult
public UploadTarget setContentType(String contentType) { public UploadTarget setContentType(String contentType) {
getTaskWrapper().asHttp().setContentType(contentType); getTaskWrapper().asHttp().setContentType(contentType);
return this; return this;
} }
@CheckResult @CheckResult
@Override public UploadTarget addHeader(@NonNull String key, @NonNull String value) { @Override public UploadTarget addHeader(@NonNull String key, @NonNull String value) {
return mHeaderDelegate.addHeader(key, value); return mHeaderDelegate.addHeader(key, value);
} }
@CheckResult @CheckResult
@Override public UploadTarget addHeaders(Map<String, String> headers) { @Override public UploadTarget addHeaders(Map<String, String> headers) {
return mHeaderDelegate.addHeaders(headers); return mHeaderDelegate.addHeaders(headers);
} }
@Override public UploadTarget setUrlProxy(Proxy proxy) { @Override public UploadTarget setUrlProxy(Proxy proxy) {
return mHeaderDelegate.setUrlProxy(proxy); return mHeaderDelegate.setUrlProxy(proxy);
} }
@Override protected boolean checkEntity() { @Override protected boolean checkEntity() {
return mNormalDelegate.checkEntity(); return mNormalDelegate.checkEntity();
} }
@Override public boolean isRunning() { @Override public boolean isRunning() {
return mNormalDelegate.isRunning(); return mNormalDelegate.isRunning();
} }
@Override public boolean taskExists() { @Override public boolean taskExists() {
return mNormalDelegate.taskExists(); return mNormalDelegate.taskExists();
} }
@Override public int getTargetType() { @Override public int getTargetType() {
return HTTP; return U_HTTP;
} }
} }

@ -35,7 +35,7 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
/** /**
* Created by Aria.Lao on 2017/7/28. FTP 单线程上传任务需要FTP 服务器给用户打开append和write的权限 * Created by Aria.Lao on 2017/7/28. D_FTP 单线程上传任务需要FTP 服务器给用户打开append和write的权限
*/ */
class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UTaskWrapper> { class FtpThreadTask extends AbsFtpThreadTask<UploadEntity, UTaskWrapper> {
private final String TAG = "FtpThreadTask"; private final String TAG = "FtpThreadTask";

@ -118,7 +118,7 @@ public class CheckUtil {
public static void checkUrlInvalidThrow(String url) { public static void checkUrlInvalidThrow(String url) {
if (TextUtils.isEmpty(url)) { if (TextUtils.isEmpty(url)) {
throw new IllegalArgumentException("url不能为null"); throw new IllegalArgumentException("url不能为null");
} else if (!url.startsWith("http") && !url.startsWith("ftp")) { } else if (!url.startsWith("http") && !url.startsWith("ftp") && !url.startsWith("sftp")) {
throw new IllegalArgumentException("url错误"); throw new IllegalArgumentException("url错误");
} }
int index = url.indexOf("://"); int index = url.indexOf("://");
@ -133,7 +133,7 @@ public class CheckUtil {
public static void checkUrl(String url) { public static void checkUrl(String url) {
if (TextUtils.isEmpty(url)) { if (TextUtils.isEmpty(url)) {
throw new NullPointerException("url为空"); throw new NullPointerException("url为空");
} else if (!url.startsWith("http") && !url.startsWith("ftp")) { } else if (!url.startsWith("http") && !url.startsWith("ftp") && !url.startsWith("sftp")) {
throw new IllegalArgumentException(String.format("url【%s】错误", url)); throw new IllegalArgumentException(String.format("url【%s】错误", url));
} }
int index = url.indexOf("://"); int index = url.indexOf("://");
@ -151,7 +151,7 @@ public class CheckUtil {
if (TextUtils.isEmpty(url)) { if (TextUtils.isEmpty(url)) {
ALog.e(TAG, "url不能为null"); ALog.e(TAG, "url不能为null");
return false; return false;
} else if (!url.startsWith("http") && !url.startsWith("ftp")) { } else if (!url.startsWith("http") && !url.startsWith("ftp") && !url.startsWith("sftp")) {
ALog.e(TAG, "url【" + url + "】错误"); ALog.e(TAG, "url【" + url + "】错误");
return false; return false;
} }

@ -1,5 +1,5 @@
## 开发日志 ## 开发日志
+ v_3.6.4 + v_3.6.4 (2019/5/16)
- 优化任务接收器的代码结构 - 优化任务接收器的代码结构
- 修复`DbEntity.saveAll()`失败的问题 - 修复`DbEntity.saveAll()`失败的问题
- 修复分块任务重命名失败的问题 - 修复分块任务重命名失败的问题
@ -10,7 +10,7 @@
- fix bug https://github.com/AriaLyy/Aria/issues/388 - fix bug https://github.com/AriaLyy/Aria/issues/388
- 修复使用`Content-Disposition`的文件名时,第一次下载无法重命名文件的问题 - 修复使用`Content-Disposition`的文件名时,第一次下载无法重命名文件的问题
- 修复使用`Content-Disposition`的文件名时,多次重命名文件的问题 - 修复使用`Content-Disposition`的文件名时,多次重命名文件的问题
- 组合任务新增`unknownSize()`,用于处理组合任务大小未知的情况,https://github.com/AriaLyy/Aria/issues/380 - 组合任务新增`unknownSize()`,用于处理组合任务大小ø未知的情况,https://github.com/AriaLyy/Aria/issues/380
- 优化`AbsThreadTask`代码 - 优化`AbsThreadTask`代码
- 新增文件长度处理功能 https://github.com/AriaLyy/Aria/issues/393 - 新增文件长度处理功能 https://github.com/AriaLyy/Aria/issues/393
```java ```java
@ -27,6 +27,8 @@
- 优化`isRunning()`的逻辑,任务是否在执行的判断将更加准确 - 优化`isRunning()`的逻辑,任务是否在执行的判断将更加准确
- 修复多次重复快速点击`暂停、开始`时,任务有可能重复下载的问题 - 修复多次重复快速点击`暂停、开始`时,任务有可能重复下载的问题
- 修复组合任务中没有等待中的只任务实体保存失败的问题 - 修复组合任务中没有等待中的只任务实体保存失败的问题
- 新增组合任务url重复检查 https://github.com/AriaLyy/Aria/issues/395
- 初始化任务时,如果url、path有错误将会回调`@Download.onTaskFail`、`@Upload.onTaskFail`、`@DownGroup.onTaskFail`
+ v_3.6.3 (2019/4/2) + v_3.6.3 (2019/4/2)
- fix bug https://github.com/AriaLyy/Aria/issues/377 - fix bug https://github.com/AriaLyy/Aria/issues/377
+ v_3.6.2 (2019/4/1) + v_3.6.2 (2019/4/1)

@ -42,8 +42,8 @@ Aria有以下特点:
[![Compiler](https://api.bintray.com/packages/arialyy/maven/AriaCompiler/images/download.svg)](https://bintray.com/arialyy/maven/AriaCompiler/_latestVersion) [![Compiler](https://api.bintray.com/packages/arialyy/maven/AriaCompiler/images/download.svg)](https://bintray.com/arialyy/maven/AriaCompiler/_latestVersion)
```java ```java
compile 'com.arialyy.aria:aria-core:3.6.3' compile 'com.arialyy.aria:aria-core:3.6.4'
annotationProcessor 'com.arialyy.aria:aria-compiler:3.6.3' annotationProcessor 'com.arialyy.aria:aria-compiler:3.6.4'
``` ```
如果出现android support依赖错误,请将 `compile 'com.arialyy.aria:aria-core:<last-version>'`替换为 如果出现android support依赖错误,请将 `compile 'com.arialyy.aria:aria-core:<last-version>'`替换为
``` ```
@ -113,12 +113,36 @@ protected void onCreate(Bundle savedInstanceState) {
### 版本日志 ### 版本日志
* v3.6.3 (2019/4/2) + v_3.6.4 (2019/5/16)
- fix bug https://github.com/AriaLyy/Aria/issues/368 - 优化任务接收器的代码结构
- 增加gradle 5.0支持 - 修复`DbEntity.saveAll()`失败的问题
- fix bug https://github.com/AriaLyy/Aria/issues/374 - 修复分块任务重命名失败的问题
- fix bug https://github.com/AriaLyy/Aria/issues/377 - fix bug https://github.com/AriaLyy/Aria/issues/379
- 增加分页获取任务列表api, 详情见:https://aria.laoyuyu.me/aria_doc/api/task_list.html#%E4%BB%BB%E5%8A%A1%E5%88%97%E8%A1%A8%E5%88%86%E9%A1%B5%EF%BC%88362%E4%BB%A5%E4%B8%8A%E7%89%88%E6%9C%AC%E6%94%AF%E6%8C%81%EF%BC%89 - 移除`getDownloadTask(String url)`、`getGroupTask(List<String> urls)`、`getFtpDirTask(String path)`
等获取任务的api,如果你希望获取对应状态,请使用实体的状态判断,如:`getDownloadEntity()`、`getDownloadGroupEntity()`
`getFtpDirEntity()`
- fix bug https://github.com/AriaLyy/Aria/issues/388
- 修复使用`Content-Disposition`的文件名时,第一次下载无法重命名文件的问题
- 修复使用`Content-Disposition`的文件名时,多次重命名文件的问题
- 组合任务新增`unknownSize()`,用于处理组合任务大小ø未知的情况,https://github.com/AriaLyy/Aria/issues/380
- 优化`AbsThreadTask`代码
- 新增文件长度处理功能 https://github.com/AriaLyy/Aria/issues/393
```java
.setFileLenAdapter(new IHttpFileLenAdapter() {
@Override public long handleFileLen(Map<String, List<String>> headers) {
...
// 处理header中的文件长度
return fileLen;
}
})
```
- 修复组合任务多次回调`onStop`注解的问题
- 优化`isRunning()`的逻辑,任务是否在执行的判断将更加准确
- 修复多次重复快速点击`暂停、开始`时,任务有可能重复下载的问题
- 修复组合任务中没有等待中的只任务实体保存失败的问题
- 新增组合任务url重复检查 https://github.com/AriaLyy/Aria/issues/395
- 初始化任务时,如果url、path有错误将会回调`@Download.onTaskFail`、`@Upload.onTaskFail`、`@DownGroup.onTaskFail`
[更多版本记录](https://github.com/AriaLyy/Aria/blob/master/DEV_LOG.md) [更多版本记录](https://github.com/AriaLyy/Aria/blob/master/DEV_LOG.md)

@ -24,7 +24,7 @@ import com.arialyy.aria.core.Aria;
import com.arialyy.frame.core.AbsFrame; import com.arialyy.frame.core.AbsFrame;
import com.arialyy.simple.BuildConfig; import com.arialyy.simple.BuildConfig;
import com.arialyy.simple.common.ConnectionChangeReceiver; import com.arialyy.simple.common.ConnectionChangeReceiver;
import com.squareup.leakcanary.LeakCanary; //import com.squareup.leakcanary.LeakCanary;
/** /**
* Created by Lyy on 2016/9/27. * Created by Lyy on 2016/9/27.
@ -45,18 +45,15 @@ public class BaseApplication extends Application {
.build()); .build());
StrictMode.setThreadPolicy( StrictMode.setThreadPolicy(
new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build()); new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());
if (LeakCanary.isInAnalyzerProcess(this)) {//1 //if (LeakCanary.isInAnalyzerProcess(this)) {//1
// This process is dedicated to LeakCanary for heap analysis. // This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process. // You should not init your app in this process.
return; //return;
} //}
LeakCanary.install(this); //LeakCanary.install(this);
} }
registerReceiver(new ConnectionChangeReceiver(), //registerReceiver(new ConnectionChangeReceiver(), new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
new
IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
} }
public static BaseApplication getApp() { public static BaseApplication getApp() {

@ -35,7 +35,7 @@ import java.io.File;
* Ftp下载测试 * Ftp下载测试
*/ */
public class FtpDownloadActivity extends BaseActivity<ActivityFtpDownloadBinding> { public class FtpDownloadActivity extends BaseActivity<ActivityFtpDownloadBinding> {
private final String URL = "ftp://9.9.9.205:2121/Cyberduck-6.9.4.30164.zip"; private final String URL = "sftp://9.9.9.205:2222/Cyberduck-6.9.4.30164.zip";
//private final String URL = "ftp://182.92.180.213:21/video/572fed5c2ad48_1024.jpg"; //private final String URL = "ftp://182.92.180.213:21/video/572fed5c2ad48_1024.jpg";
//private final String URL = "ftp://182.92.180.213:21/DATA/20180205/rar/1111.rar"; //private final String URL = "ftp://182.92.180.213:21/DATA/20180205/rar/1111.rar";
//private final String URL = "ftp://d:d@dygodj8.com:12311/咖啡风暴HD大陆公映意语中字[飘花www.piaohua.com].mp4"; //private final String URL = "ftp://d:d@dygodj8.com:12311/咖啡风暴HD大陆公映意语中字[飘花www.piaohua.com].mp4";
@ -60,8 +60,9 @@ public class FtpDownloadActivity extends BaseActivity<ActivityFtpDownloadBinding
switch (view.getId()) { switch (view.getId()) {
case R.id.start: case R.id.start:
Aria.download(this).loadFtp(URL) Aria.download(this).loadFtp(URL)
.login("lao", "123456") .login("N0rI", "0qcK")
.setFilePath("/mnt/sdcard/").start(); .setFilePath("/mnt/sdcard/", true)
.start();
break; break;
case R.id.stop: case R.id.stop:
Aria.download(this).loadFtp(URL).stop(); Aria.download(this).loadFtp(URL).stop();

@ -22,6 +22,7 @@ import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.os.Handler;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.Menu; import android.view.Menu;
@ -37,7 +38,6 @@ import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadTarget; import com.arialyy.aria.core.download.DownloadTarget;
import com.arialyy.aria.core.download.DownloadTask; import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.core.inf.AbsHttpFileLenAdapter;
import com.arialyy.aria.core.inf.IEntity; import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.IHttpFileLenAdapter; import com.arialyy.aria.core.inf.IHttpFileLenAdapter;
import com.arialyy.aria.core.scheduler.ISchedulers; import com.arialyy.aria.core.scheduler.ISchedulers;
@ -317,7 +317,7 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
//.addHeader("Cookie", "BAIDUID=648E5FF020CC69E8DD6F492D1068AAA9:FG=1; BIDUPSID=648E5FF020CC69E8DD6F492D1068AAA9; PSTM=1519099573; BD_UPN=12314753; locale=zh; BDSVRTM=0") //.addHeader("Cookie", "BAIDUID=648E5FF020CC69E8DD6F492D1068AAA9:FG=1; BIDUPSID=648E5FF020CC69E8DD6F492D1068AAA9; PSTM=1519099573; BD_UPN=12314753; locale=zh; BDSVRTM=0")
.useServerFileName(true) .useServerFileName(true)
.setFilePath(path, true) .setFilePath(path, true)
.setFileLenAdapter(new AbsHttpFileLenAdapter() { .setFileLenAdapter(new IHttpFileLenAdapter() {
@Override public long handleFileLen(Map<String, List<String>> headers) { @Override public long handleFileLen(Map<String, List<String>> headers) {
List<String> sLength = headers.get("Content-Length"); List<String> sLength = headers.get("Content-Length");

@ -43,7 +43,7 @@ task clean(type: Delete) {
ext { ext {
userOrg = 'arialyy' userOrg = 'arialyy'
groupId = 'com.arialyy.aria' groupId = 'com.arialyy.aria'
publishVersion = '3.6.4_dev_2' publishVersion = '3.6.4'
// publishVersion = '1.0.4' //FTP插件 // publishVersion = '1.0.4' //FTP插件
repoName='maven' repoName='maven'
desc = 'android 下载框架' desc = 'android 下载框架'

Loading…
Cancel
Save