组合任务新增`unknownSize()`,用于处理组合任务大小未知的情况,https://github.com/AriaLyy/Aria/issues/380

v3.6.6
laoyuyu 6 years ago
parent 8c0ef0f879
commit 0c3e16cad7
  1. 32
      Aria/src/main/java/com/arialyy/aria/core/common/AbsThreadTask.java
  2. 7
      Aria/src/main/java/com/arialyy/aria/core/common/CompleteInfo.java
  3. 8
      Aria/src/main/java/com/arialyy/aria/core/common/StateConstance.java
  4. 15
      Aria/src/main/java/com/arialyy/aria/core/common/SubThreadConfig.java
  5. 10
      Aria/src/main/java/com/arialyy/aria/core/download/DGTaskWrapper.java
  6. 379
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTarget.java
  7. 4
      Aria/src/main/java/com/arialyy/aria/core/download/HttpGroupDelegate.java
  8. 2
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpFileInfoThread.java
  9. 2
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpFileInfoThread.java
  10. 2
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java
  11. 1
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/SimpleDownloadUtil.java
  12. 10
      Aria/src/main/java/com/arialyy/aria/core/download/group/AbsGroupUtil.java
  13. 73
      Aria/src/main/java/com/arialyy/aria/core/download/group/DownloadGroupUtil.java
  14. 2
      Aria/src/main/java/com/arialyy/aria/core/download/group/FtpDirInfoThread.java
  15. 7
      Aria/src/main/java/com/arialyy/aria/core/download/group/SubDownloadLoader.java
  16. 3
      Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpFileInfoThread.java
  17. 2
      Aria/src/main/java/com/arialyy/aria/util/DbDataHelper.java
  18. 1
      DEV_LOG.md
  19. 8
      app/src/main/java/com/arialyy/simple/core/download/SingleTaskActivity.java
  20. 8
      app/src/main/java/com/arialyy/simple/core/download/group/DownloadGroupActivity.java
  21. 2
      build.gradle

@ -115,8 +115,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
* @return {@code true}存活 * @return {@code true}存活
*/ */
protected boolean isLive() { protected boolean isLive() {
Thread t = Thread.currentThread(); return !Thread.currentThread().isInterrupted() && !isInterrupted;
return !t.isInterrupted() && !isInterrupted;
} }
/** /**
@ -399,19 +398,22 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
* @param needRetry 是否可以重试 * @param needRetry 是否可以重试
*/ */
private void retryThis(boolean needRetry) { private void retryThis(boolean needRetry) {
if (!NetUtils.isConnected(AriaManager.APP) && !isNotNetRetry) { synchronized (AriaManager.LOCK) {
ALog.w(TAG, String.format("任务【%s】thread__%s__重试失败,网络未连接", mConfig.TEMP_FILE.getName(), if (!NetUtils.isConnected(AriaManager.APP) && !isNotNetRetry) {
mConfig.THREAD_ID)); ALog.w(TAG, String.format("任务【%s】thread__%s__重试失败,网络未连接", mConfig.TEMP_FILE.getName(),
} mConfig.THREAD_ID));
if (mFailTimes < RETRY_NUM && needRetry && (NetUtils.isConnected(AriaManager.APP) }
|| isNotNetRetry) && !isBreak()) { if (mFailTimes < RETRY_NUM && needRetry && (NetUtils.isConnected(AriaManager.APP)
ALog.w(TAG, || isNotNetRetry) && !isBreak()) {
String.format("任务【%s】thread__%s__正在重试", mConfig.TEMP_FILE.getName(), mConfig.THREAD_ID)); ALog.w(TAG,
mFailTimes++; String.format("任务【%s】thread__%s__正在重试", mConfig.TEMP_FILE.getName(),
handleRetryRecord(); mConfig.THREAD_ID));
ThreadTaskManager.getInstance().retryThread(AbsThreadTask.this); mFailTimes++;
} else { handleRetryRecord();
handleFailState(!isBreak()); ThreadTaskManager.getInstance().retryThread(AbsThreadTask.this);
} else {
handleFailState(!isBreak());
}
} }
} }

@ -15,6 +15,8 @@
*/ */
package com.arialyy.aria.core.common; package com.arialyy.aria.core.common;
import com.arialyy.aria.core.inf.AbsTaskWrapper;
/** /**
* Created by AriaL on 2018/3/3. * Created by AriaL on 2018/3/3.
* 获取文件信息完成后 回调给下载线程的信息 * 获取文件信息完成后 回调给下载线程的信息
@ -25,7 +27,10 @@ public class CompleteInfo {
*/ */
public int code; public int code;
public CompleteInfo(int code) { public AbsTaskWrapper wrapper;
public CompleteInfo(int code, AbsTaskWrapper wrapper) {
this.code = code; this.code = code;
this.wrapper = wrapper;
} }
} }

@ -53,8 +53,8 @@ public class StateConstance {
* 所有子线程是否都已经停止 * 所有子线程是否都已经停止
*/ */
public boolean isStop() { public boolean isStop() {
//ALog.d(TAG, String.format("stop_num=%s; start_thread_num=%s; complete_num=%s", STOP_NUM, //ALog.d(TAG, String.format("stop_thread_num=%s; start_thread_num=%s; complete_thread_num=%s",
// START_THREAD_NUM, COMPLETE_THREAD_NUM)); // STOP_NUM, START_THREAD_NUM, COMPLETE_THREAD_NUM));
return STOP_NUM == START_THREAD_NUM || STOP_NUM + COMPLETE_THREAD_NUM == START_THREAD_NUM; return STOP_NUM == START_THREAD_NUM || STOP_NUM + COMPLETE_THREAD_NUM == START_THREAD_NUM;
} }
@ -62,8 +62,8 @@ public class StateConstance {
* 所有子线程是否都已经失败 * 所有子线程是否都已经失败
*/ */
public boolean isFail() { public boolean isFail() {
//ALog.d(TAG, String.format("fail_num=%s; start_thread_num=%s; complete_num=%s", FAIL_NUM, //ALog.d(TAG, String.format("fail_thread_num=%s; start_thread_num=%s; complete_thread_num=%s",
// START_THREAD_NUM, COMPLETE_THREAD_NUM)); // FAIL_NUM, START_THREAD_NUM, COMPLETE_THREAD_NUM));
return COMPLETE_THREAD_NUM != START_THREAD_NUM return COMPLETE_THREAD_NUM != START_THREAD_NUM
&& (FAIL_NUM == START_THREAD_NUM || FAIL_NUM + COMPLETE_THREAD_NUM == START_THREAD_NUM); && (FAIL_NUM == START_THREAD_NUM || FAIL_NUM + COMPLETE_THREAD_NUM == START_THREAD_NUM);
} }

@ -1,3 +1,18 @@
/*
* 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; package com.arialyy.aria.core.common;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;

@ -27,6 +27,8 @@ public class DGTaskWrapper extends AbsGroupTaskWrapper<DownloadGroupEntity, DTas
private List<DTaskWrapper> subTaskEntities; private List<DTaskWrapper> subTaskEntities;
private boolean unknownSize = false;
public DGTaskWrapper(DownloadGroupEntity entity) { public DGTaskWrapper(DownloadGroupEntity entity) {
super(entity); super(entity);
} }
@ -36,6 +38,14 @@ public class DGTaskWrapper extends AbsGroupTaskWrapper<DownloadGroupEntity, DTas
this.subTaskEntities = subTaskEntities; this.subTaskEntities = subTaskEntities;
} }
public boolean isUnknownSize() {
return unknownSize;
}
public void setUnknownSize(boolean unknownSize) {
this.unknownSize = unknownSize;
}
/** /**
* 组名 * 组名
*/ */

@ -1,183 +1,196 @@
/* /*
* 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 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.IHttpHeaderDelegate; import com.arialyy.aria.core.inf.IHttpHeaderDelegate;
import com.arialyy.aria.core.manager.TaskWrapperManager; import com.arialyy.aria.core.manager.TaskWrapperManager;
import com.arialyy.aria.exception.ParamException; import com.arialyy.aria.exception.ParamException;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import java.net.Proxy; import java.net.Proxy;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
* Created by AriaL on 2017/6/29. * Created by AriaL on 2017/6/29.
* 下载任务组 * 下载任务组
*/ */
public class DownloadGroupTarget extends AbsDGTarget<DownloadGroupTarget> implements public class DownloadGroupTarget extends AbsDGTarget<DownloadGroupTarget> implements
IHttpHeaderDelegate<DownloadGroupTarget> { IHttpHeaderDelegate<DownloadGroupTarget> {
private HttpHeaderDelegate<DownloadGroupTarget> mHeaderDelegate; private HttpHeaderDelegate<DownloadGroupTarget> mHeaderDelegate;
private HttpGroupDelegate mGroupDelegate; private HttpGroupDelegate mGroupDelegate;
DownloadGroupTarget(DownloadGroupEntity groupEntity, String targetName) { DownloadGroupTarget(DownloadGroupEntity groupEntity, String targetName) {
setTargetName(targetName); setTargetName(targetName);
if (groupEntity.getUrls() != null && !groupEntity.getUrls().isEmpty()) { if (groupEntity.getUrls() != null && !groupEntity.getUrls().isEmpty()) {
init(groupEntity.getUrls()); init(groupEntity.getUrls());
} else { } else {
throw new ParamException("组合任务只任务下载地址为空"); throw new ParamException("组合任务只任务下载地址为空");
} }
} }
DownloadGroupTarget(List<String> urls, String targetName) { DownloadGroupTarget(List<String> urls, String targetName) {
setTargetName(targetName); setTargetName(targetName);
init(urls); init(urls);
} }
private void init(List<String> urls) { private void init(List<String> urls) {
mGroupDelegate = new HttpGroupDelegate(this, mGroupDelegate = new HttpGroupDelegate(this,
TaskWrapperManager.getInstance().getDGTaskWrapper(DGTaskWrapper.class, urls)); TaskWrapperManager.getInstance().getDGTaskWrapper(DGTaskWrapper.class, urls));
mHeaderDelegate = new HttpHeaderDelegate<>(this); mHeaderDelegate = new HttpHeaderDelegate<>(this);
} }
/** /**
* Post处理 * Post处理
*/ */
@CheckResult @CheckResult
public PostDelegate asPost() { public PostDelegate asPost() {
return new PostDelegate<>(this); return new PostDelegate<>(this);
} }
/** /**
* 更新组合任务下载地址 * 更新组合任务下载地址
* *
* @param urls 新的组合任务下载地址列表 * @param urls 新的组合任务下载地址列表
*/ */
@CheckResult @CheckResult
public DownloadGroupTarget updateUrls(List<String> urls) { public DownloadGroupTarget updateUrls(List<String> urls) {
return mGroupDelegate.updateUrls(urls); return mGroupDelegate.updateUrls(urls);
} }
/** /**
* 任务组总任务大小任务组是一个抽象的概念没有真实的数据实体任务组的大小是Aria动态获取子任务大小相加而得到的 * 任务组总任务大小任务组是一个抽象的概念没有真实的数据实体任务组的大小是Aria动态获取子任务大小相加而得到的
* 如果你知道当前任务组总大小你也可以调用该方法给任务组设置大小 * 如果你知道当前任务组总大小你也可以调用该方法给任务组设置大小
* *
* 为了更好的用户体验组合任务必须设置文件大小 * 为了更好的用户体验组合任务最好设置文件大小默认需要强制设置文件大小如果无法获取到总长度请调用{@link #unknownSize()}
* *
* @param fileSize 任务组总大小 * @param fileSize 任务组总大小
*/ */
@CheckResult @CheckResult
public DownloadGroupTarget setFileSize(long fileSize) { public DownloadGroupTarget setFileSize(long fileSize) {
if (fileSize <= 0) { if (fileSize <= 0) {
ALog.e(TAG, "文件大小不能小于 0"); ALog.e(TAG, "文件大小不能小于 0");
return this; return this;
} }
if (getEntity().getFileSize() <= 1 || getEntity().getFileSize() != fileSize) { if (getEntity().getFileSize() <= 1 || getEntity().getFileSize() != fileSize) {
getEntity().setFileSize(fileSize); getEntity().setFileSize(fileSize);
} }
return this; return this;
} }
/** /**
* 如果你是使用{@link DownloadReceiver#load(DownloadGroupEntity)}进行下载操作那么你需要设置任务组的下载地址 * 如果无法获取到组合任务到总长度请调用该方法
*/ * 请注意
@CheckResult * 1如果组合任务到子任务数过多请不要使用该标志位否则Aria将需要消耗大量的时间获取组合任务的总长度
public DownloadGroupTarget setGroupUrl(List<String> urls) { * 2如果你的知道组合任务的总长度请使用{@link #setFileSize(long)}设置组合任务的长度
return mGroupDelegate.setGroupUrl(urls); * 3由于网络或其它原因的存在这种方式获取的组合任务大小有可能是不准确的
} */
@CheckResult
/** public DownloadGroupTarget unknownSize() {
* 设置子任务文件名该方法必须在{@link #setDirPath(String)}之后调用否则不生效 getTaskWrapper().setUnknownSize(true);
* return this;
* @deprecated {@link #setSubFileName(List)} 请使用该api }
*/
@CheckResult /**
@Deprecated public DownloadGroupTarget setSubTaskFileName(List<String> subTaskFileName) { * 如果你是使用{@link DownloadReceiver#load(DownloadGroupEntity)}进行下载操作那么你需要设置任务组的下载地址
return setSubFileName(subTaskFileName); */
} @CheckResult
public DownloadGroupTarget setGroupUrl(List<String> urls) {
/** return mGroupDelegate.setGroupUrl(urls);
* 设置任务组的文件夹路径在Aria中任务组的所有子任务都会下载到以任务组组名的文件夹中 }
* groupDirPath = "/mnt/sdcard/download/group_test"
* <pre> /**
* {@code * 设置子任务文件名该方法必须在{@link #setDirPath(String)}之后调用否则不生效
* + mnt *
* + sdcard * @deprecated {@link #setSubFileName(List)} 请使用该api
* + download */
* + group_test @CheckResult
* - task1.apk @Deprecated public DownloadGroupTarget setSubTaskFileName(List<String> subTaskFileName) {
* - task2.apk return setSubFileName(subTaskFileName);
* - task3.apk }
* ....
* /**
* } * 设置任务组的文件夹路径在Aria中任务组的所有子任务都会下载到以任务组组名的文件夹中
* </pre> * groupDirPath = "/mnt/sdcard/download/group_test"
* * <pre>
* @param dirPath 任务组保存文件夹路径 * {@code
*/ * + mnt
@CheckResult * + sdcard
public DownloadGroupTarget setDirPath(String dirPath) { * + download
return mGroupDelegate.setDirPath(dirPath); * + group_test
} * - task1.apk
* - task2.apk
/** * - task3.apk
* 设置子任务文件名该方法必须在{@link #setDirPath(String)}之后调用否则不生效 * ....
*/ *
@CheckResult * }
public DownloadGroupTarget setSubFileName(List<String> subTaskFileName) { * </pre>
return mGroupDelegate.setSubFileName(subTaskFileName); *
} * @param dirPath 任务组保存文件夹路径
*/
@Override public int getTargetType() { @CheckResult
return GROUP_HTTP; public DownloadGroupTarget setDirPath(String dirPath) {
} return mGroupDelegate.setDirPath(dirPath);
}
@Override protected boolean checkEntity() {
return mGroupDelegate.checkEntity(); /**
} * 设置子任务文件名该方法必须在{@link #setDirPath(String)}之后调用否则不生效
*/
@Override public boolean isRunning() { @CheckResult
return mGroupDelegate.isRunning(); public DownloadGroupTarget setSubFileName(List<String> subTaskFileName) {
} return mGroupDelegate.setSubFileName(subTaskFileName);
}
@Override public boolean taskExists() {
return mGroupDelegate.taskExists(); @Override public int getTargetType() {
} return GROUP_HTTP;
}
@CheckResult
@Override public DownloadGroupTarget addHeader(@NonNull String key, @NonNull String value) { @Override protected boolean checkEntity() {
for (DTaskWrapper subTask : getTaskWrapper().getSubTaskWrapper()) { return mGroupDelegate.checkEntity();
mHeaderDelegate.addHeader(subTask, key, value); }
}
return mHeaderDelegate.addHeader(key, value); @Override public boolean isRunning() {
} return mGroupDelegate.isRunning();
}
@CheckResult
@Override public DownloadGroupTarget addHeaders(Map<String, String> headers) { @Override public boolean taskExists() {
for (DTaskWrapper subTask : getTaskWrapper().getSubTaskWrapper()) { return mGroupDelegate.taskExists();
mHeaderDelegate.addHeaders(subTask, headers); }
}
return mHeaderDelegate.addHeaders(headers); @CheckResult
} @Override public DownloadGroupTarget addHeader(@NonNull String key, @NonNull String value) {
for (DTaskWrapper subTask : getTaskWrapper().getSubTaskWrapper()) {
@CheckResult mHeaderDelegate.addHeader(subTask, key, value);
@Override public DownloadGroupTarget setUrlProxy(Proxy proxy) { }
return mHeaderDelegate.setUrlProxy(proxy); return mHeaderDelegate.addHeader(key, value);
} }
}
@CheckResult
@Override public DownloadGroupTarget addHeaders(Map<String, String> headers) {
for (DTaskWrapper subTask : getTaskWrapper().getSubTaskWrapper()) {
mHeaderDelegate.addHeaders(subTask, headers);
}
return mHeaderDelegate.addHeaders(headers);
}
@CheckResult
@Override public DownloadGroupTarget setUrlProxy(Proxy proxy) {
return mHeaderDelegate.setUrlProxy(proxy);
}
}

@ -114,8 +114,8 @@ class HttpGroupDelegate extends AbsGroupDelegate<DownloadGroupTarget> {
return false; return false;
} }
if (getTaskWrapper().getEntity().getFileSize() == 0) { if (!getTaskWrapper().isUnknownSize() && getTaskWrapper().getEntity().getFileSize() == 0) {
ALog.e(TAG, "组合任务必须设置文件文件大小"); ALog.e(TAG, "组合任务必须设置文件文件大小,默认需要强制设置文件大小。如果无法获取到总长度,请调用#unknownSize()来标志该组合任务");
return false; return false;
} }

@ -55,6 +55,6 @@ class FtpFileInfoThread extends AbsFtpInfoThread<DownloadEntity, DTaskWrapper> {
mTaskWrapper.setNewTask(true); mTaskWrapper.setNewTask(true);
} }
mEntity.setFileSize(mSize); mEntity.setFileSize(mSize);
mCallback.onComplete(mEntity.getUrl(), new CompleteInfo(code)); mCallback.onComplete(mEntity.getUrl(), new CompleteInfo(code, mTaskWrapper));
} }
} }

@ -220,7 +220,7 @@ public class HttpFileInfoThread implements Runnable {
if (end) { if (end) {
mTaskDelegate.setChunked(isChunked); mTaskDelegate.setChunked(isChunked);
if (onFileInfoCallback != null) { if (onFileInfoCallback != null) {
CompleteInfo info = new CompleteInfo(code); CompleteInfo info = new CompleteInfo(code, mTaskWrapper);
onFileInfoCallback.onComplete(mEntity.getUrl(), info); onFileInfoCallback.onComplete(mEntity.getUrl(), info);
} }
mEntity.update(); mEntity.update();

@ -29,7 +29,6 @@ import com.arialyy.aria.exception.TaskException;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.BufferedRandomAccessFile; import com.arialyy.aria.util.BufferedRandomAccessFile;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -44,7 +43,6 @@ import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel; import java.nio.channels.ReadableByteChannel;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.zip.GZIPInputStream;
/** /**
* Created by lyy on 2017/1/18. 下载线程 * Created by lyy on 2017/1/18. 下载线程

@ -107,6 +107,7 @@ public class SimpleDownloadUtil implements IUtil, Runnable {
if (isStop || isCancel) { if (isStop || isCancel) {
return; return;
} }
// 如果网址没有变,而服务器端端文件改变,以下代码就没有用了
//if (mTaskWrapper.getEntity().getFileSize() <= 1 //if (mTaskWrapper.getEntity().getFileSize() <= 1
// || mTaskWrapper.isRefreshInfo() // || mTaskWrapper.isRefreshInfo()
// || mTaskWrapper.getRequestType() == AbsTaskWrapper.D_FTP // || mTaskWrapper.getRequestType() == AbsTaskWrapper.D_FTP

@ -288,7 +288,15 @@ public abstract class AbsGroupUtil implements IUtil, Runnable {
* 创建并启动子任务下载器 * 创建并启动子任务下载器
*/ */
SubDownloadLoader createSubLoader(DTaskWrapper taskWrapper) { SubDownloadLoader createSubLoader(DTaskWrapper taskWrapper) {
SubDownloadLoader loader = new SubDownloadLoader(mScheduler, taskWrapper); return createSubLoader(taskWrapper, true);
}
/**
* 创建并启动子任务下载器
* @param needGetFileInfo {@code true} 需要获取文件信息{@code false} 不需要获取文件信息
*/
SubDownloadLoader createSubLoader(DTaskWrapper taskWrapper, boolean needGetFileInfo) {
SubDownloadLoader loader = new SubDownloadLoader(mScheduler, taskWrapper, needGetFileInfo);
mExeLoader.put(loader.getKey(), loader); mExeLoader.put(loader.getKey(), loader);
mSubQueue.startTask(loader); mSubQueue.startTask(loader);
return loader; return loader;

@ -15,16 +15,26 @@
*/ */
package com.arialyy.aria.core.download.group; package com.arialyy.aria.core.download.group;
import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.core.common.IUtil; import com.arialyy.aria.core.common.IUtil;
import com.arialyy.aria.core.common.OnFileInfoCallback;
import com.arialyy.aria.core.download.DGTaskWrapper; import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.downloader.HttpFileInfoThread;
import com.arialyy.aria.core.inf.IEntity; import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.exception.BaseException;
import com.arialyy.aria.util.ALog;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/** /**
* Created by AriaL on 2017/6/30. * Created by AriaL on 2017/6/30.
* 任务组下载工具 * 任务组下载工具
*/ */
public class DownloadGroupUtil extends AbsGroupUtil implements IUtil { public class DownloadGroupUtil extends AbsGroupUtil implements IUtil {
private static final String TAG = "DownloadGroupUtil";
private final Object LOCK = new Object();
private ExecutorService mPool = null;
public DownloadGroupUtil(IDownloadGroupListener listener, DGTaskWrapper taskWrapper) { public DownloadGroupUtil(IDownloadGroupListener listener, DGTaskWrapper taskWrapper) {
super(listener, taskWrapper); super(listener, taskWrapper);
@ -47,11 +57,68 @@ public class DownloadGroupUtil extends AbsGroupUtil implements IUtil {
if (mState.getCompleteNum() == mState.getSubSize()) { if (mState.getCompleteNum() == mState.getSubSize()) {
mListener.onComplete(); mListener.onComplete();
} else { } else {
for (DTaskWrapper wrapper : mGTWrapper.getSubTaskWrapper()) { // 处理组合任务大小未知的情况
if (wrapper.getState() != IEntity.STATE_COMPLETE) { if (mGTWrapper.isUnknownSize() && mGTWrapper.getEntity().getFileSize() < 1) {
createSubLoader(wrapper); mPool = Executors.newCachedThreadPool();
getGroupSize();
try {
synchronized (LOCK) {
LOCK.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
for (DTaskWrapper wrapper : mGTWrapper.getSubTaskWrapper()) {
if (wrapper.getState() != IEntity.STATE_COMPLETE) {
createSubLoader(wrapper);
}
} }
} }
} }
} }
/**
* 获取组合任务大小使用该方式获取到的组合任务大小子任务不需要再重新获取文件大小
*/
private void getGroupSize() {
new Thread(new Runnable() {
int count;
@Override public void run() {
for (DTaskWrapper dTaskWrapper : mGTWrapper.getSubTaskWrapper()) {
mPool.submit(new HttpFileInfoThread(dTaskWrapper, new OnFileInfoCallback() {
@Override public void onComplete(String url, CompleteInfo info) {
createSubLoader((DTaskWrapper) info.wrapper, false);
count++;
checkGetSizeComplete(count);
}
@Override public void onFail(String url, BaseException e, boolean needRetry) {
ALog.e(TAG, String.format("获取文件信息失败,url:%s", url));
count++;
checkGetSizeComplete(count);
}
}));
}
}
}).start();
}
/**
* 检查组合任务大小是否获取完成获取完成后取消阻塞并设置组合任务大小
*/
private void checkGetSizeComplete(int count) {
if (count == mGTWrapper.getSubTaskWrapper().size()) {
long size = 0;
for (DTaskWrapper wrapper : mGTWrapper.getSubTaskWrapper()) {
size += wrapper.getEntity().getFileSize();
}
mGTWrapper.getEntity().setFileSize(size);
synchronized (LOCK) {
LOCK.notify();
}
}
}
} }

@ -50,7 +50,7 @@ class FtpDirInfoThread extends AbsFtpInfoThread<DownloadGroupEntity, DGTaskWrapp
@Override protected void onPreComplete(int code) { @Override protected void onPreComplete(int code) {
super.onPreComplete(code); super.onPreComplete(code);
mEntity.setFileSize(mSize); mEntity.setFileSize(mSize);
mCallback.onComplete(mEntity.getKey(), new CompleteInfo(code)); mCallback.onComplete(mEntity.getKey(), new CompleteInfo(code, mTaskWrapper));
} }
/** /**

@ -19,6 +19,7 @@ import android.os.Handler;
import com.arialyy.aria.core.common.CompleteInfo; import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.core.common.IUtil; import com.arialyy.aria.core.common.IUtil;
import com.arialyy.aria.core.common.OnFileInfoCallback; import com.arialyy.aria.core.common.OnFileInfoCallback;
import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.download.DTaskWrapper; 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.downloader.Downloader; import com.arialyy.aria.core.download.downloader.Downloader;
@ -39,7 +40,11 @@ class SubDownloadLoader implements IUtil {
private Handler mSchedulers; private Handler mSchedulers;
private ChildDownloadListener mListener; private ChildDownloadListener mListener;
SubDownloadLoader(Handler schedulers, DTaskWrapper taskWrapper) { /**
* @param schedulers 调度器
* @param needGetInfo {@code true} 需要获取文件信息{@code false} 不需要获取文件信息
*/
SubDownloadLoader(Handler schedulers, DTaskWrapper taskWrapper, boolean needGetInfo) {
mWrapper = taskWrapper; mWrapper = taskWrapper;
mSchedulers = schedulers; mSchedulers = schedulers;
mListener = new ChildDownloadListener(mSchedulers, SubDownloadLoader.this); mListener = new ChildDownloadListener(mSchedulers, SubDownloadLoader.this);

@ -95,6 +95,7 @@ class FtpFileInfoThread extends AbsFtpInfoThread<UploadEntity, UTaskWrapper> {
@Override protected void onPreComplete(int code) { @Override protected void onPreComplete(int code) {
super.onPreComplete(code); super.onPreComplete(code);
mCallback.onComplete(mEntity.getKey(), new CompleteInfo(isComplete ? CODE_COMPLETE : code)); mCallback.onComplete(mEntity.getKey(),
new CompleteInfo(isComplete ? CODE_COMPLETE : code, mTaskWrapper));
} }
} }

@ -56,7 +56,7 @@ public class DbDataHelper {
DbEntity.findRelationData(DGEntityWrapper.class, "DownloadGroupEntity.groupHash=?", DbEntity.findRelationData(DGEntityWrapper.class, "DownloadGroupEntity.groupHash=?",
groupHash); groupHash);
return wrapper == null ? null : wrapper.get(0).groupEntity; return wrapper == null || wrapper.size() == 0 ? null : wrapper.get(0).groupEntity;
} }
/** /**

@ -10,6 +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
+ 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)

@ -59,9 +59,9 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
//"http://120.55.95.61:8811/ghcg/zg/武义总规纲要成果.zip"; //"http://120.55.95.61:8811/ghcg/zg/武义总规纲要成果.zip";
//"https://yizi-kejian.oss-cn-beijing.aliyuncs.com/qimeng/package1/qmtable11.zip"; //"https://yizi-kejian.oss-cn-beijing.aliyuncs.com/qimeng/package1/qmtable11.zip";
//"http://rs.0.gaoshouyou.com/d/04/1e/400423a7551e1f3f0eb1812afa1f9b44.apk"; //"http://rs.0.gaoshouyou.com/d/04/1e/400423a7551e1f3f0eb1812afa1f9b44.apk";
//"http://chargepile2.techsum.net/car-manage/file/download?path=2019-04-26/c0242efd18be4ecbb23911b1c509dcad--掌通各系统汇总.xls"; // 无长度的chunked "http://chargepile2.techsum.net/car-manage/file/download?path=2019-04-26/c0242efd18be4ecbb23911b1c509dcad--掌通各系统汇总.xls"; // 无长度的chunked
//"http://58.210.9.131/tpk/sipgt//TDLYZTGH.tpk"; //chunked 下载 //"http://58.210.9.131/tpk/sipgt//TDLYZTGH.tpk"; //chunked 下载
"http://apk500.bce.baidu-mgame.com/game/67000/67734/20170622040827_oem_5502845.apk?r=1"; //"http://apk500.bce.baidu-mgame.com/game/67000/67734/20170622040827_oem_5502845.apk?r=1";
//"https://dl.genymotion.com/releases/genymotion-2.12.1/genymotion-2.12.1-vbox.exe"; //"https://dl.genymotion.com/releases/genymotion-2.12.1/genymotion-2.12.1-vbox.exe";
//"http://9.9.9.50:5000/download/CentOS-7-x86_64-Minimal-1804.iso"; //"http://9.9.9.50:5000/download/CentOS-7-x86_64-Minimal-1804.iso";
//"http://v2.qingdian1.com/m_20180730_991/2/2B9FB34A4BCD8CE61481D1C8418EFE36_1080P.m3u8"; //"http://v2.qingdian1.com/m_20180730_991/2/2B9FB34A4BCD8CE61481D1C8418EFE36_1080P.m3u8";
@ -316,8 +316,8 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
Aria.download(SingleTaskActivity.this) Aria.download(SingleTaskActivity.this)
.load(DOWNLOAD_URL) .load(DOWNLOAD_URL)
//.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3") //.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3")
.addHeader("Accept-Encoding", "gzip, deflate") //.addHeader("Accept-Encoding", "gzip, deflate")
.addHeader("DNT", "1") //.addHeader("DNT", "1")
//.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)

@ -24,14 +24,12 @@ import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity; import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.download.DownloadGroupTask; import com.arialyy.aria.core.download.DownloadGroupTask;
import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.frame.util.show.L; import com.arialyy.frame.util.show.L;
import com.arialyy.frame.util.show.T; import com.arialyy.frame.util.show.T;
import com.arialyy.simple.R; import com.arialyy.simple.R;
import com.arialyy.simple.base.BaseActivity; import com.arialyy.simple.base.BaseActivity;
import com.arialyy.simple.databinding.ActivityDownloadGroupBinding; import com.arialyy.simple.databinding.ActivityDownloadGroupBinding;
import com.arialyy.simple.widget.SubStateLinearLayout; import com.arialyy.simple.widget.SubStateLinearLayout;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
@ -80,9 +78,6 @@ public class DownloadGroupActivity extends BaseActivity<ActivityDownloadGroupBin
public void onClick(View view) { public void onClick(View view) {
switch (view.getId()) { switch (view.getId()) {
case R.id.start: case R.id.start:
List<String> temp = new ArrayList<>();
temp.add(
"https://d.pcs.baidu.com/file/130335545f3f4d9cc38afe709c19af5a?fid=1411168371-250528-1010657263806840&dstime=1531134714&rt=sh&sign=FDtAERVY-DCb740ccc5511e5e8fedcff06b081203-h8KgJ6gl4oY9UR6NqvwJsT4nVSM%3D&expires=8h&chkv=1&chkbd=0&chkpc=et&dp-logid=4401996296756616039&dp-callid=0&r=279987343");
Aria.download(this) Aria.download(this)
.loadGroup(mUrls) .loadGroup(mUrls)
.setDirPath( .setDirPath(
@ -91,7 +86,8 @@ public class DownloadGroupActivity extends BaseActivity<ActivityDownloadGroupBin
.setGroupAlias("任务组测试") .setGroupAlias("任务组测试")
//.setSubFileName(getModule(GroupModule.class).getSubName2()) //.setSubFileName(getModule(GroupModule.class).getSubName2())
.setSubFileName(getModule(GroupModule.class).getSubName()) .setSubFileName(getModule(GroupModule.class).getSubName())
.setFileSize(114981416) .unknownSize()
//.setFileSize(114981416)
//.updateUrls(temp) //.updateUrls(temp)
.start(); .start();
break; break;

@ -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_1' publishVersion = '3.6.4_dev_2'
// publishVersion = '1.0.4' //FTP插件 // publishVersion = '1.0.4' //FTP插件
repoName='maven' repoName='maven'
desc = 'android 下载框架' desc = 'android 下载框架'

Loading…
Cancel
Save