diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/CheckDGEntityUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/CheckDGEntityUtil.java index 2834c5c3..15f698c4 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/CheckDGEntityUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/CheckDGEntityUtil.java @@ -116,7 +116,7 @@ public class CheckDGEntityUtil implements ICheckEntityUtil { @Override public boolean checkEntity() { if (mWrapper.getErrorEvent() != null) { - ALog.e(TAG, String.format("下载失败,%s", mWrapper.getErrorEvent().errorMsg)); + ALog.e(TAG, String.format("操作失败,%s", mWrapper.getErrorEvent().errorMsg)); return false; } @@ -195,7 +195,7 @@ public class CheckDGEntityUtil implements ICheckEntityUtil { */ private boolean checkUrls() { if (mEntity.getUrls().isEmpty()) { - ALog.e(TAG, "下载失败,子任务下载列表为null"); + ALog.e(TAG, "操作失败,子任务下载列表为null"); return false; } diff --git a/FtpComponent/src/main/java/com/arialyy/aria/ftp/download/FtpDGLoader.java b/FtpComponent/src/main/java/com/arialyy/aria/ftp/download/FtpDGLoader.java index 3fe51b57..33adbf9e 100644 --- a/FtpComponent/src/main/java/com/arialyy/aria/ftp/download/FtpDGLoader.java +++ b/FtpComponent/src/main/java/com/arialyy/aria/ftp/download/FtpDGLoader.java @@ -45,13 +45,18 @@ final class FtpDGLoader extends AbsGroupLoader { @Override protected AbsSubDLoadUtil createSubLoader(DTaskWrapper wrapper, boolean needGetFileInfo) { - return new FtpSubDLoaderUtil(wrapper, getScheduler(), needGetFileInfo); + return new FtpSubDLoaderUtil(wrapper, getScheduler(), needGetFileInfo, getKey()); } /** * 启动子任务下载 */ private void startSub() { + if (isBreak()) { + return; + } + onPostStart(); + // ftp需要获取完成只任务信息才更新只任务数量 getState().setSubSize(getWrapper().getSubTaskWrapper().size()); @@ -70,12 +75,12 @@ final class FtpDGLoader extends AbsGroupLoader { startSub(); } else { ALog.e(TAG, "获取任务信息失败,code:" + info.code); - mListener.onFail(false, null); + getListener().onFail(false, null); } } @Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) { - mListener.onFail(needRetry, e); + getListener().onFail(needRetry, e); } }); } diff --git a/FtpComponent/src/main/java/com/arialyy/aria/ftp/download/FtpSubDLoaderUtil.java b/FtpComponent/src/main/java/com/arialyy/aria/ftp/download/FtpSubDLoaderUtil.java index 1617cb18..2aa47541 100644 --- a/FtpComponent/src/main/java/com/arialyy/aria/ftp/download/FtpSubDLoaderUtil.java +++ b/FtpComponent/src/main/java/com/arialyy/aria/ftp/download/FtpSubDLoaderUtil.java @@ -31,14 +31,16 @@ final class FtpSubDLoaderUtil extends AbsSubDLoadUtil { * @param schedulers 调度器 * @param needGetInfo {@code true} 需要获取文件信息。{@code false} 不需要获取文件信息 */ - FtpSubDLoaderUtil(DTaskWrapper taskWrapper, Handler schedulers, boolean needGetInfo) { - super(taskWrapper, schedulers, needGetInfo); + FtpSubDLoaderUtil(DTaskWrapper taskWrapper, Handler schedulers, boolean needGetInfo, + String parentKey) { + super(taskWrapper, schedulers, needGetInfo, parentKey); } @Override protected SubLoader getLoader() { if (mDLoader == null) { mDLoader = new SubLoader(getWrapper(), getSchedulers()); mDLoader.setNeedGetInfo(isNeedGetInfo()); + mDLoader.setParentKey(getParentKey()); } return mDLoader; } diff --git a/HttpComponent/src/main/java/com/arialyy/aria/http/download/HttpDGInfoTask.java b/HttpComponent/src/main/java/com/arialyy/aria/http/download/HttpDGInfoTask.java index 2e4d9123..e93e9f1e 100644 --- a/HttpComponent/src/main/java/com/arialyy/aria/http/download/HttpDGInfoTask.java +++ b/HttpComponent/src/main/java/com/arialyy/aria/http/download/HttpDGInfoTask.java @@ -66,7 +66,7 @@ public final class HttpDGInfoTask implements IInfoTask { } }; - public HttpDGInfoTask(DGTaskWrapper wrapper, DownloadGroupListener listener) { + HttpDGInfoTask(DGTaskWrapper wrapper, DownloadGroupListener listener) { this.wrapper = wrapper; this.listener = listener; } @@ -76,7 +76,7 @@ public final class HttpDGInfoTask implements IInfoTask { if (mPool != null && !getLenComplete) { ALog.d(TAG, "获取长度未完成的情况下,停止组合任务"); mPool.shutdown(); - //mListener.onStop(0); + listener.onStop(0); return; } // 处理组合任务大小未知的情况 diff --git a/HttpComponent/src/main/java/com/arialyy/aria/http/download/HttpDGLoader.java b/HttpComponent/src/main/java/com/arialyy/aria/http/download/HttpDGLoader.java index c18c788f..14d4d201 100644 --- a/HttpComponent/src/main/java/com/arialyy/aria/http/download/HttpDGLoader.java +++ b/HttpComponent/src/main/java/com/arialyy/aria/http/download/HttpDGLoader.java @@ -22,7 +22,7 @@ import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.group.AbsGroupLoader; import com.arialyy.aria.core.group.AbsSubDLoadUtil; -import com.arialyy.aria.core.listener.IEventListener; +import com.arialyy.aria.core.listener.DownloadGroupListener; import com.arialyy.aria.core.loader.IInfoTask; import com.arialyy.aria.core.wrapper.AbsTaskWrapper; import com.arialyy.aria.exception.BaseException; @@ -31,7 +31,7 @@ import com.arialyy.aria.exception.BaseException; * http 组合任务加载器 */ final class HttpDGLoader extends AbsGroupLoader { - HttpDGLoader(AbsTaskWrapper groupWrapper, IEventListener listener) { + HttpDGLoader(AbsTaskWrapper groupWrapper, DownloadGroupListener listener) { super(groupWrapper, listener); } @@ -44,13 +44,14 @@ final class HttpDGLoader extends AbsGroupLoader { @Override protected AbsSubDLoadUtil createSubLoader(DTaskWrapper wrapper, boolean needGetFileInfo) { - return new HttpSubDLoaderUtil(wrapper, getScheduler(), needGetFileInfo); + return new HttpSubDLoaderUtil(wrapper, getScheduler(), needGetFileInfo, getKey()); } private void startSub() { if (isBreak()) { return; } + onPostStart(); for (DTaskWrapper wrapper : getWrapper().getSubTaskWrapper()) { DownloadEntity dEntity = wrapper.getEntity(); startSubLoader(createSubLoader(wrapper, dEntity.getFileSize() < 0)); @@ -65,7 +66,7 @@ final class HttpDGLoader extends AbsGroupLoader { } @Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) { - mListener.onFail(needRetry, e); + getListener().onFail(needRetry, e); } }); } diff --git a/HttpComponent/src/main/java/com/arialyy/aria/http/download/HttpDGLoaderUtil.java b/HttpComponent/src/main/java/com/arialyy/aria/http/download/HttpDGLoaderUtil.java index c53f07ad..2777ddcc 100644 --- a/HttpComponent/src/main/java/com/arialyy/aria/http/download/HttpDGLoaderUtil.java +++ b/HttpComponent/src/main/java/com/arialyy/aria/http/download/HttpDGLoaderUtil.java @@ -36,7 +36,8 @@ public final class HttpDGLoaderUtil extends AbsGroupLoaderUtil { } @Override protected AbsGroupLoader getLoader() { - return mLoader == null ? new HttpDGLoader(getTaskWrapper(), getListener()) : mLoader; + return mLoader == null ? new HttpDGLoader(getTaskWrapper(), + (DownloadGroupListener) getListener()) : mLoader; } @Override protected LoaderStructure buildLoaderStructure() { diff --git a/HttpComponent/src/main/java/com/arialyy/aria/http/download/HttpSubDLoaderUtil.java b/HttpComponent/src/main/java/com/arialyy/aria/http/download/HttpSubDLoaderUtil.java index 0e4d54d9..a7079691 100644 --- a/HttpComponent/src/main/java/com/arialyy/aria/http/download/HttpSubDLoaderUtil.java +++ b/HttpComponent/src/main/java/com/arialyy/aria/http/download/HttpSubDLoaderUtil.java @@ -32,14 +32,16 @@ final class HttpSubDLoaderUtil extends AbsSubDLoadUtil { * @param schedulers 调度器 * @param needGetInfo {@code true} 需要获取文件信息。{@code false} 不需要获取文件信息 */ - HttpSubDLoaderUtil(DTaskWrapper taskWrapper, Handler schedulers, boolean needGetInfo) { - super(taskWrapper, schedulers, needGetInfo); + HttpSubDLoaderUtil(DTaskWrapper taskWrapper, Handler schedulers, boolean needGetInfo, + String parentKey) { + super(taskWrapper, schedulers, needGetInfo, parentKey); } @Override protected SubLoader getLoader() { if (mDLoader == null) { mDLoader = new SubLoader(getWrapper(), getSchedulers()); mDLoader.setNeedGetInfo(isNeedGetInfo()); + mDLoader.setParentKey(getParentKey()); } return mDLoader; } diff --git a/M3U8Component/src/main/java/com/arialyy/aria/m3u8/live/M3U8LiveLoader.java b/M3U8Component/src/main/java/com/arialyy/aria/m3u8/live/M3U8LiveLoader.java index 72cbb938..0bd13449 100644 --- a/M3U8Component/src/main/java/com/arialyy/aria/m3u8/live/M3U8LiveLoader.java +++ b/M3U8Component/src/main/java/com/arialyy/aria/m3u8/live/M3U8LiveLoader.java @@ -31,6 +31,7 @@ import com.arialyy.aria.core.manager.ThreadTaskManager; import com.arialyy.aria.core.processor.ILiveTsUrlConverter; import com.arialyy.aria.core.processor.ITsMergeHandler; import com.arialyy.aria.core.task.ThreadTask; +import com.arialyy.aria.core.wrapper.ITaskWrapper; import com.arialyy.aria.exception.BaseException; import com.arialyy.aria.exception.M3U8Exception; import com.arialyy.aria.exception.TaskException; @@ -180,7 +181,8 @@ final class M3U8LiveLoader extends BaseM3U8Loader { config.record = record; config.stateHandler = mStateHandler; config.peerIndex = indexId; - + config.threadType = SubThreadConfig.getThreadType(ITaskWrapper.M3U8_LIVE); + config.updateInterval = SubThreadConfig.getUpdateInterval(ITaskWrapper.M3U8_LIVE); if (!config.tempFile.exists()) { FileUtil.createFile(config.tempFile); } diff --git a/M3U8Component/src/main/java/com/arialyy/aria/m3u8/vod/M3U8VodLoader.java b/M3U8Component/src/main/java/com/arialyy/aria/m3u8/vod/M3U8VodLoader.java index 23e0de7b..d3f46333 100644 --- a/M3U8Component/src/main/java/com/arialyy/aria/m3u8/vod/M3U8VodLoader.java +++ b/M3U8Component/src/main/java/com/arialyy/aria/m3u8/vod/M3U8VodLoader.java @@ -34,6 +34,7 @@ import com.arialyy.aria.core.loader.IThreadTaskBuilder; import com.arialyy.aria.core.manager.ThreadTaskManager; import com.arialyy.aria.core.processor.IVodTsUrlConverter; import com.arialyy.aria.core.task.ThreadTask; +import com.arialyy.aria.core.wrapper.ITaskWrapper; import com.arialyy.aria.exception.BaseException; import com.arialyy.aria.exception.M3U8Exception; import com.arialyy.aria.m3u8.BaseM3U8Loader; @@ -473,6 +474,8 @@ final class M3U8VodLoader extends BaseM3U8Loader { config.record = record; config.stateHandler = mStateHandler; config.peerIndex = index; + config.threadType = SubThreadConfig.getThreadType(ITaskWrapper.M3U8_LIVE); + config.updateInterval = SubThreadConfig.getUpdateInterval(ITaskWrapper.M3U8_LIVE); if (!config.tempFile.exists()) { FileUtil.createFile(config.tempFile); } diff --git a/M3U8Component/src/main/java/com/arialyy/aria/m3u8/vod/VodStateManager.java b/M3U8Component/src/main/java/com/arialyy/aria/m3u8/vod/VodStateManager.java index ff1b7dbf..cbba8db3 100644 --- a/M3U8Component/src/main/java/com/arialyy/aria/m3u8/vod/VodStateManager.java +++ b/M3U8Component/src/main/java/com/arialyy/aria/m3u8/vod/VodStateManager.java @@ -113,8 +113,8 @@ public final class VodStateManager implements IThreadStateManager { if (isFail()) { ALog.d(TAG, String.format("vod任务【%s】失败", loader.getTempFile().getName())); Bundle b = msg.getData(); - listener.onFail(b.getBoolean(KEY_RETRY, true), - (BaseException) b.getSerializable(KEY_ERROR_INFO)); + listener.onFail(b.getBoolean(DATA_RETRY, true), + (BaseException) b.getSerializable(DATA_ERROR_INFO)); quitLooper(); } break; diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/common/SubThreadConfig.java b/PublicComponent/src/main/java/com/arialyy/aria/core/common/SubThreadConfig.java index 46a351ca..e7846b1b 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/common/SubThreadConfig.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/common/SubThreadConfig.java @@ -16,14 +16,21 @@ package com.arialyy.aria.core.common; import android.os.Handler; +import com.arialyy.aria.core.AriaConfig; import com.arialyy.aria.core.ThreadRecord; import com.arialyy.aria.core.wrapper.AbsTaskWrapper; +import com.arialyy.aria.core.wrapper.ITaskWrapper; import java.io.File; /** * 子线程下载信息类 */ public class SubThreadConfig { + public static final int TYPE_HTTP = 1; + public static final int TYPE_FTP = 2; + public static final int TYPE_M3U8_PEER = 3; + public static final int TYPE_HTTP_DG_SUB = 4; + public static final int TYPE_FTP_DG_SUB = 5; public AbsTaskWrapper taskWrapper; public boolean isBlock = false; @@ -37,4 +44,65 @@ public class SubThreadConfig { public Handler stateHandler; // m3u8切片索引 public int peerIndex; + // 线程任务类型 + public int threadType = TYPE_HTTP; + // 更新间隔,单位:毫秒 + public long updateInterval = 1000; + + /** + * 转换线程任务类型 + * + * @param requestType {@link AbsTaskWrapper#getRequestType()} + * @return {@link #threadType} + */ + public static int getThreadType(int requestType) { + int threadType = SubThreadConfig.TYPE_HTTP; + switch (requestType) { + case ITaskWrapper.D_HTTP: + case ITaskWrapper.U_HTTP: + threadType = SubThreadConfig.TYPE_HTTP; + break; + case ITaskWrapper.D_FTP: + case ITaskWrapper.U_FTP: + threadType = SubThreadConfig.TYPE_FTP; + break; + case ITaskWrapper.D_FTP_DIR: + threadType = SubThreadConfig.TYPE_FTP_DG_SUB; + break; + case ITaskWrapper.DG_HTTP: + threadType = SubThreadConfig.TYPE_HTTP_DG_SUB; + break; + case ITaskWrapper.M3U8_LIVE: + case ITaskWrapper.M3U8_VOD: + threadType = SubThreadConfig.TYPE_M3U8_PEER; + break; + } + return threadType; + } + + /** + * 根据配置肚脐更新间隔 + * + * @param requestType {@link AbsTaskWrapper#getRequestType()} + * @return {@link #updateInterval} + */ + public static long getUpdateInterval(int requestType) { + long updateInterval = 1000; + switch (requestType) { + case ITaskWrapper.D_HTTP: + case ITaskWrapper.D_FTP: + case ITaskWrapper.M3U8_LIVE: + case ITaskWrapper.M3U8_VOD: + updateInterval = AriaConfig.getInstance().getDConfig().getUpdateInterval(); + break; + case ITaskWrapper.D_FTP_DIR: + case ITaskWrapper.DG_HTTP: + updateInterval = AriaConfig.getInstance().getDGConfig().getUpdateInterval(); + break; + case ITaskWrapper.U_HTTP: + case ITaskWrapper.U_FTP: + updateInterval = AriaConfig.getInstance().getUConfig().getUpdateInterval(); + } + return updateInterval; + } } \ No newline at end of file diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsGroupLoader.java b/PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsGroupLoader.java index bab6fab0..e7e8705b 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsGroupLoader.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsGroupLoader.java @@ -45,7 +45,7 @@ public abstract class AbsGroupLoader implements ILoaderVisitor, ILoader { protected final String TAG = CommonUtil.getClassName(getClass()); private long mCurrentLocation = 0; - protected IDGroupListener mListener; + private IDGroupListener mListener; private ScheduledThreadPoolExecutor mTimer; private long mUpdateInterval; private boolean isStop = false, isCancel = false; @@ -76,6 +76,10 @@ public abstract class AbsGroupLoader implements ILoaderVisitor, ILoader { */ protected abstract AbsSubDLoadUtil createSubLoader(DTaskWrapper wrapper, boolean needGetFileInfo); + protected IDGroupListener getListener() { + return mListener; + } + protected DGTaskWrapper getWrapper() { return mGTWrapper; } @@ -113,7 +117,7 @@ public abstract class AbsGroupLoader implements ILoaderVisitor, ILoader { getWrapper().setState(IEntity.STATE_POST_PRE); } mState.updateProgress(mCurrentLocation); - mScheduler = new Handler(looper, SimpleSchedulers.newInstance(mState)); + mScheduler = new Handler(looper, SimpleSchedulers.newInstance(mState, mGTWrapper.getKey())); } @Override public String getKey() { @@ -248,18 +252,26 @@ public abstract class AbsGroupLoader implements ILoaderVisitor, ILoader { mListener.onComplete(); return; } - - mListener.onPostPre(mGTWrapper.getEntity().getFileSize()); - if (mCurrentLocation > 0) { - mListener.onResume(mCurrentLocation); - } else { - mListener.onStart(mCurrentLocation); - } startTimer(); handlerTask(looper); Looper.loop(); } + /** + * 组合任务获取完成子任务的信息后调用 + */ + protected void onPostStart() { + if (isBreak()) { + return; + } + getListener().onPostPre(getWrapper().getEntity().getFileSize()); + if (getWrapper().getEntity().getFileSize() > 0) { + getListener().onResume(getWrapper().getEntity().getCurrentProgress()); + } else { + getListener().onStart(getWrapper().getEntity().getCurrentProgress()); + } + } + private synchronized void startTimer() { mState.isRunning = true; mTimer = new ScheduledThreadPoolExecutor(1); diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsSubDLoadUtil.java b/PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsSubDLoadUtil.java index 3fa50bb3..fe5ebb3b 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsSubDLoadUtil.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsSubDLoadUtil.java @@ -34,19 +34,19 @@ public abstract class AbsSubDLoadUtil implements IUtil, Runnable { protected SubLoader mDLoader; private DTaskWrapper mWrapper; private Handler mSchedulers; - private ChildDLoadListener mListener; private boolean needGetInfo; private boolean isStop = false, isCancel = false; + private String parentKey; /** * @param schedulers 调度器 * @param needGetInfo {@code true} 需要获取文件信息。{@code false} 不需要获取文件信息 */ - protected AbsSubDLoadUtil(DTaskWrapper taskWrapper, Handler schedulers, boolean needGetInfo) { + protected AbsSubDLoadUtil(DTaskWrapper taskWrapper, Handler schedulers, boolean needGetInfo, String parentKey) { mWrapper = taskWrapper; mSchedulers = schedulers; + this.parentKey = parentKey; this.needGetInfo = needGetInfo; - mListener = new ChildDLoadListener(mSchedulers, AbsSubDLoadUtil.this); mDLoader = getLoader(); } @@ -57,6 +57,10 @@ public abstract class AbsSubDLoadUtil implements IUtil, Runnable { protected abstract LoaderStructure buildLoaderStructure(); + public String getParentKey() { + return parentKey; + } + protected boolean isNeedGetInfo() { return needGetInfo; } @@ -66,7 +70,7 @@ public abstract class AbsSubDLoadUtil implements IUtil, Runnable { } @Override public String getKey() { - return mWrapper.getKey(); + return mDLoader.getKey(); } public DTaskWrapper getWrapper() { @@ -77,15 +81,10 @@ public abstract class AbsSubDLoadUtil implements IUtil, Runnable { return mWrapper.getEntity(); } - public ChildDLoadListener getListener() { - return mListener; - } - @Override public void run() { if (isStop || isCancel) { return; } - mListener.onPre(); buildLoaderStructure(); mDLoader.run(); } @@ -107,10 +106,6 @@ public abstract class AbsSubDLoadUtil implements IUtil, Runnable { } } - public SubLoader getDownloader() { - return mDLoader; - } - /** * @deprecated 子任务不实现这个 */ diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/group/ChildDLoadListener.java b/PublicComponent/src/main/java/com/arialyy/aria/core/group/ChildDLoadListener.java deleted file mode 100644 index c606a78b..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/group/ChildDLoadListener.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * 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.group; - -import android.os.Handler; -import com.arialyy.aria.core.download.DownloadEntity; -import com.arialyy.aria.core.inf.IEntity; -import com.arialyy.aria.core.listener.IDLoadListener; -import com.arialyy.aria.core.listener.ISchedulers; -import com.arialyy.aria.exception.BaseException; -import com.arialyy.aria.util.CommonUtil; - -/** - * 子任务事件监听 - */ -public class ChildDLoadListener implements IDLoadListener { - private DownloadEntity subEntity; - private int RUN_SAVE_INTERVAL = 5 * 1000; //5s保存一次下载中的进度 - private long lastSaveTime; - private long lastLen; - private Handler schedulers; - private AbsSubDLoadUtil loader; - - ChildDLoadListener(Handler schedulers, AbsSubDLoadUtil loader) { - this.loader = loader; - this.schedulers = schedulers; - subEntity = loader.getEntity(); - subEntity.setFailNum(0); - lastLen = subEntity.getCurrentProgress(); - lastSaveTime = System.currentTimeMillis(); - } - - @Override public void supportBreakpoint(boolean support) { - - } - - @Override public void onPre() { - saveData(IEntity.STATE_PRE, subEntity.getCurrentProgress()); - } - - @Override public void onPostPre(long fileSize) { - subEntity.setFileSize(fileSize); - subEntity.setConvertFileSize(CommonUtil.formatFileSize(fileSize)); - saveData(IEntity.STATE_POST_PRE, subEntity.getCurrentProgress()); - sendToTarget(ISchedulers.POST_PRE, loader); - } - - @Override public void onResume(long resumeLocation) { - lastLen = resumeLocation; - saveData(IEntity.STATE_POST_PRE, subEntity.getCurrentProgress()); - sendToTarget(ISchedulers.START, loader); - } - - @Override public void onStart(long startLocation) { - lastLen = startLocation; - saveData(IEntity.STATE_POST_PRE, subEntity.getCurrentProgress()); - sendToTarget(ISchedulers.START, loader); - } - - @Override public void onProgress(long currentLocation) { - long diff = currentLocation - lastLen; - //mCurrentLocation += speed; - subEntity.setCurrentProgress(currentLocation); - handleSpeed(diff); - sendToTarget(ISchedulers.RUNNING, loader); - if (System.currentTimeMillis() - lastSaveTime >= RUN_SAVE_INTERVAL) { - saveData(IEntity.STATE_RUNNING, currentLocation); - lastSaveTime = System.currentTimeMillis(); - } - lastLen = currentLocation; - } - - @Override public void onStop(long stopLocation) { - handleSpeed(0); - saveData(IEntity.STATE_STOP, stopLocation); - sendToTarget(ISchedulers.STOP, loader); - } - - /** - * 组合任务子任务不允许删除 - */ - @Deprecated - @Override public void onCancel() { - - } - - @Override public void onComplete() { - subEntity.setComplete(true); - saveData(IEntity.STATE_COMPLETE, subEntity.getFileSize()); - handleSpeed(0); - sendToTarget(ISchedulers.COMPLETE, loader); - } - - @Override public void onFail(boolean needRetry, BaseException e) { - subEntity.setFailNum(subEntity.getFailNum() + 1); - saveData(IEntity.STATE_FAIL, subEntity.getCurrentProgress()); - handleSpeed(0); - sendToTarget(ISchedulers.FAIL, loader); - } - - private void handleSpeed(long speed) { - subEntity.setSpeed(speed); - subEntity.setConvertSpeed( - speed <= 0 ? "" : String.format("%s/s", CommonUtil.formatFileSize(speed))); - subEntity.setPercent((int) (subEntity.getFileSize() <= 0 ? 0 - : subEntity.getCurrentProgress() * 100 / subEntity.getFileSize())); - } - - private void saveData(int state, long location) { - loader.getWrapper().setState(state); - subEntity.setState(state); - subEntity.setComplete(state == IEntity.STATE_COMPLETE); - if (state == IEntity.STATE_CANCEL) { - subEntity.deleteData(); - } else if (state == IEntity.STATE_STOP) { - subEntity.setStopTime(System.currentTimeMillis()); - } else if (subEntity.isComplete()) { - subEntity.setCompleteTime(System.currentTimeMillis()); - subEntity.setCurrentProgress(subEntity.getFileSize()); - } else if (location > 0) { - subEntity.setCurrentProgress(location); - } - } - - /** - * 发送状态到子任务调度器{@link SimpleSchedulers},让调度器处理任务调度 - * - * @param state {@link ISchedulers} - */ - private void sendToTarget(int state, AbsSubDLoadUtil util) { - schedulers.obtainMessage(state, util).sendToTarget(); - } -} \ No newline at end of file diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/group/SimpleSchedulers.java b/PublicComponent/src/main/java/com/arialyy/aria/core/group/SimpleSchedulers.java index 945e5b87..9634b497 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/group/SimpleSchedulers.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/group/SimpleSchedulers.java @@ -16,6 +16,7 @@ package com.arialyy.aria.core.group; +import android.os.Bundle; import android.os.Handler; import android.os.Message; import com.arialyy.aria.core.AriaConfig; @@ -37,45 +38,56 @@ class SimpleSchedulers implements Handler.Callback { private static final String TAG = "SimpleSchedulers"; private SimpleSubQueue mQueue; private GroupRunState mGState; + private String mKey; // 组合任务的key - private SimpleSchedulers(GroupRunState state) { + private SimpleSchedulers(GroupRunState state, String key) { mQueue = state.queue; mGState = state; + mKey = key; } - static SimpleSchedulers newInstance(GroupRunState state) { - - return new SimpleSchedulers(state); + static SimpleSchedulers newInstance(GroupRunState state, String key) { + return new SimpleSchedulers(state, key); } @Override public boolean handleMessage(Message msg) { - // todo key 应该从bundle中获取 - String key = (String) msg.obj; - AbsSubDLoadUtil loader = mQueue.getLoaderUtil(key); - if (loader == null) { - ALog.e(TAG, "子任务loder不存在,key:" + key); + Bundle b = msg.getData(); + if (b == null) { + ALog.w(TAG, "组合任务子任务调度数据为空"); + return true; + } + String threadName = b.getString(IThreadStateManager.DATA_THREAD_NAME); + AbsSubDLoadUtil loaderUtil = mQueue.getLoaderUtil(threadName); + if (loaderUtil == null) { + ALog.e(TAG, String.format("子任务loader不存在,state:%s,key:%s", msg.what, threadName)); return true; } - // todo 处理的是子任务的线程,需要删除 ThreadTaskManager.removeSingleTaskThread 删除线程任务 + long curLocation = b.getLong(IThreadStateManager.DATA_THREAD_LOCATION, + loaderUtil.getLoader().getWrapper().getEntity().getCurrentProgress()); + // 处理状态 switch (msg.what) { case IThreadStateManager.STATE_RUNNING: - mGState.listener.onSubRunning(loader.getEntity()); + long range = (long) msg.obj; + mGState.listener.onSubRunning(loaderUtil.getEntity(), range); break; - case PRE: - mGState.listener.onSubPre(loader.getEntity()); - mGState.updateCount(loader.getKey()); + case IThreadStateManager.STATE_PRE: + mGState.listener.onSubPre(loaderUtil.getEntity()); + mGState.updateCount(loaderUtil.getKey()); break; - case START: - mGState.listener.onSubStart(loader.getEntity()); + case IThreadStateManager.STATE_START: + mGState.listener.onSubStart(loaderUtil.getEntity()); break; case IThreadStateManager.STATE_STOP: - handleStop(loader); + handleStop(loaderUtil, curLocation); + ThreadTaskManager.getInstance().removeSingleTaskThread(mKey, threadName); break; case IThreadStateManager.STATE_COMPLETE: - handleComplete(loader); + handleComplete(loaderUtil); + ThreadTaskManager.getInstance().removeSingleTaskThread(mKey, threadName); break; case IThreadStateManager.STATE_FAIL: - handleFail(loader); + handleFail(loaderUtil); + ThreadTaskManager.getInstance().removeSingleTaskThread(mKey, threadName); break; } return true; @@ -96,7 +108,7 @@ class SimpleSchedulers implements Handler.Callback { final int reTryNum = num; if ((!NetUtils.isConnected(AriaConfig.getInstance().getAPP()) && !isNotNetRetry) - || loaderUtil.getDownloader() == null // 如果获取不到文件信息,loader为空 + || loaderUtil.getLoader() == null // 如果获取不到文件信息,loader为空 || loaderUtil.getEntity().getFailNum() > reTryNum) { mQueue.removeTaskFromExecQ(loaderUtil); mGState.listener.onSubFail(loaderUtil.getEntity(), new TaskException(TAG, @@ -136,8 +148,8 @@ class SimpleSchedulers implements Handler.Callback { * 1、所有的子任务已经停止,则认为组合任务停止 * 2、completeNum + failNum + stopNum = subSize,则认为组合任务停止 */ - private synchronized void handleStop(AbsSubDLoadUtil loadUtil) { - mGState.listener.onSubStop(loadUtil.getEntity()); + private synchronized void handleStop(AbsSubDLoadUtil loadUtil, long curLocation) { + mGState.listener.onSubStop(loadUtil.getEntity(), curLocation); mGState.countStopNum(loadUtil.getKey()); if (mGState.getStopNum() == mGState.getSubSize() || mGState.getStopNum() diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/group/SimpleSubQueue.java b/PublicComponent/src/main/java/com/arialyy/aria/core/group/SimpleSubQueue.java index 3ca54e71..57020f3c 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/group/SimpleSubQueue.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/group/SimpleSubQueue.java @@ -17,6 +17,7 @@ package com.arialyy.aria.core.group; import com.arialyy.aria.core.config.Configuration; import com.arialyy.aria.util.ALog; +import com.arialyy.aria.util.CommonUtil; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; @@ -29,7 +30,7 @@ import java.util.Set; * 组合任务队列,该队列生命周期和{@link AbsGroupLoaderUtil}生命周期一致 */ class SimpleSubQueue implements ISubQueue { - private static final String TAG = "SimpleSubQueue"; + private final String TAG = CommonUtil.getClassName(getClass()); /** * 缓存下载器 */ @@ -162,12 +163,7 @@ class SimpleSubQueue implements ISubQueue { } @Override public void removeTaskFromExecQ(AbsSubDLoadUtil fileer) { - if (mExec.containsKey(fileer.getKey())) { - if (fileer.isRunning()) { - fileer.stop(); - } - mExec.remove(fileer.getKey()); - } + mExec.remove(fileer.getKey()); } @Override public void removeTask(AbsSubDLoadUtil fileer) { diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/inf/IThreadStateManager.java b/PublicComponent/src/main/java/com/arialyy/aria/core/inf/IThreadStateManager.java index 66c9f5fc..5b3811a7 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/inf/IThreadStateManager.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/inf/IThreadStateManager.java @@ -32,8 +32,10 @@ public interface IThreadStateManager extends ILoaderComponent { int STATE_UPDATE_PROGRESS = 0x06; int STATE_PRE = 0x07; int STATE_START = 0x08; - String KEY_RETRY = "KEY_RETRY"; - String KEY_ERROR_INFO = "KEY_ERROR_INFO"; + String DATA_RETRY = "DATA_RETRY"; + String DATA_ERROR_INFO = "DATA_ERROR_INFO"; + String DATA_THREAD_NAME = "DATA_THREAD_NAME"; + String DATA_THREAD_LOCATION = "DATA_THREAD_LOCATION"; /** * 任务是否已经失败 diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/listener/DownloadGroupListener.java b/PublicComponent/src/main/java/com/arialyy/aria/core/listener/DownloadGroupListener.java index f15167c2..5c21a326 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/listener/DownloadGroupListener.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/listener/DownloadGroupListener.java @@ -21,8 +21,8 @@ import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadGroupEntity; import com.arialyy.aria.core.group.GroupSendParams; import com.arialyy.aria.core.inf.IEntity; -import com.arialyy.aria.core.loader.IRecordHandler; import com.arialyy.aria.core.inf.TaskSchedulerType; +import com.arialyy.aria.core.loader.IRecordHandler; import com.arialyy.aria.core.task.AbsTask; import com.arialyy.aria.core.task.DownloadGroupTask; import com.arialyy.aria.exception.BaseException; @@ -47,6 +47,7 @@ public class DownloadGroupListener @Override public void onSubPre(DownloadEntity subEntity) { + handleSpeed(subEntity, 0); saveSubState(IEntity.STATE_PRE, subEntity); sendInState2Target(ISchedulers.SUB_PRE, subEntity); } @@ -58,12 +59,15 @@ public class DownloadGroupListener @Override public void onSubStart(DownloadEntity subEntity) { + handleSpeed(subEntity, 0); saveSubState(IEntity.STATE_RUNNING, subEntity); sendInState2Target(ISchedulers.SUB_START, subEntity); } @Override - public void onSubStop(DownloadEntity subEntity) { + public void onSubStop(DownloadEntity subEntity, long stopLocation) { + subEntity.setCurrentProgress(stopLocation); + handleSpeed(subEntity, 0); saveSubState(IEntity.STATE_STOP, subEntity); saveCurrentLocation(); sendInState2Target(ISchedulers.SUB_STOP, subEntity); @@ -71,6 +75,7 @@ public class DownloadGroupListener @Override public void onSubComplete(DownloadEntity subEntity) { + handleSpeed(subEntity, 0); saveSubState(IEntity.STATE_COMPLETE, subEntity); saveCurrentLocation(); sendInState2Target(ISchedulers.SUB_COMPLETE, subEntity); @@ -78,6 +83,7 @@ public class DownloadGroupListener @Override public void onSubFail(DownloadEntity subEntity, BaseException e) { + handleSpeed(subEntity, 0); saveSubState(IEntity.STATE_FAIL, subEntity); saveCurrentLocation(); sendInState2Target(ISchedulers.SUB_FAIL, subEntity); @@ -89,13 +95,16 @@ public class DownloadGroupListener @Override public void onSubCancel(DownloadEntity subEntity) { + handleSpeed(subEntity, 0); saveSubState(IEntity.STATE_CANCEL, subEntity); saveCurrentLocation(); sendInState2Target(ISchedulers.SUB_CANCEL, subEntity); } @Override - public void onSubRunning(DownloadEntity subEntity) { + public void onSubRunning(DownloadEntity subEntity, long currentProgress) { + + handleSpeed(subEntity, currentProgress); if (System.currentTimeMillis() - mLastSaveTime >= RUN_SAVE_INTERVAL) { saveSubState(IEntity.STATE_RUNNING, subEntity); mLastSaveTime = System.currentTimeMillis(); @@ -103,6 +112,21 @@ public class DownloadGroupListener sendInState2Target(ISchedulers.SUB_RUNNING, subEntity); } + private void handleSpeed(DownloadEntity subEntity, long currentProgress) { + if (currentProgress == 0){ + subEntity.setSpeed(0); + subEntity.setConvertSpeed("0kb/s"); + return; + } + long range = currentProgress - subEntity.getCurrentProgress() ; + subEntity.setSpeed(range); + subEntity.setConvertSpeed( + range <= 0 ? "" : String.format("%s/s", CommonUtil.formatFileSize(range))); + subEntity.setPercent((int) (subEntity.getFileSize() <= 0 ? 0 + : subEntity.getCurrentProgress() * 100 / subEntity.getFileSize())); + subEntity.setCurrentProgress(currentProgress); + } + /** * 将任务状态发送给下载器 * diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/listener/IDGroupListener.java b/PublicComponent/src/main/java/com/arialyy/aria/core/listener/IDGroupListener.java index eca54860..31fc5ddc 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/listener/IDGroupListener.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/listener/IDGroupListener.java @@ -16,7 +16,6 @@ package com.arialyy.aria.core.listener; import com.arialyy.aria.core.download.DownloadEntity; -import com.arialyy.aria.core.listener.IDLoadListener; import com.arialyy.aria.exception.BaseException; /** @@ -45,7 +44,7 @@ public interface IDGroupListener extends IDLoadListener { /** * 子任务停止下载 */ - void onSubStop(DownloadEntity subEntity); + void onSubStop(DownloadEntity subEntity, long stopLocation); /** * 子任务下载完成 @@ -64,6 +63,8 @@ public interface IDGroupListener extends IDLoadListener { /** * 子任务执行中 + * + * @param currentProgress 当前进度 */ - void onSubRunning(DownloadEntity subEntity); + void onSubRunning(DownloadEntity subEntity, long currentProgress); } diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalTTBuilder.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalTTBuilder.java index d775f3e2..c7c8db5b 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalTTBuilder.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalTTBuilder.java @@ -84,6 +84,8 @@ public abstract class AbsNormalTTBuilder implements IThreadTaskBuilder { config.taskWrapper = mWrapper; config.record = record; config.stateHandler = mStateHandler; + config.threadType = SubThreadConfig.getThreadType(mWrapper.getRequestType()); + config.updateInterval = SubThreadConfig.getUpdateInterval(mWrapper.getRequestType()); return createThreadTask(config); } diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/NormalThreadStateManager.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/NormalThreadStateManager.java index 72e6430f..bff67ba7 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/NormalThreadStateManager.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/NormalThreadStateManager.java @@ -90,8 +90,8 @@ public class NormalThreadStateManager implements IThreadStateManager { mFailNum++; if (isFail()) { Bundle b = msg.getData(); - mListener.onFail(b.getBoolean(KEY_RETRY, false), - (BaseException) b.getSerializable(KEY_ERROR_INFO)); + mListener.onFail(b.getBoolean(DATA_RETRY, false), + (BaseException) b.getSerializable(DATA_ERROR_INFO)); quitLooper(); } break; diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/SubLoader.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/SubLoader.java index d5eb3d7d..8a5f0379 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/SubLoader.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/SubLoader.java @@ -15,13 +15,17 @@ */ package com.arialyy.aria.core.loader; +import android.os.Bundle; import android.os.Handler; +import android.os.Message; +import android.text.TextUtils; +import com.arialyy.aria.core.TaskRecord; import com.arialyy.aria.core.common.AbsEntity; import com.arialyy.aria.core.common.CompleteInfo; import com.arialyy.aria.core.inf.IThreadStateManager; -import com.arialyy.aria.core.listener.ISchedulers; import com.arialyy.aria.core.manager.ThreadTaskManager; import com.arialyy.aria.core.task.IThreadTask; +import com.arialyy.aria.core.task.ThreadTask; import com.arialyy.aria.core.wrapper.AbsTaskWrapper; import com.arialyy.aria.exception.BaseException; import com.arialyy.aria.util.ALog; @@ -42,29 +46,84 @@ public final class SubLoader implements ILoader, ILoaderVisitor { private IThreadTaskBuilder ttBuild; private IRecordHandler recordHandler; private IThreadTask threadTask; + private String parentKey; public SubLoader(AbsTaskWrapper wrapper, Handler schedulers) { this.wrapper = wrapper; this.schedulers = schedulers; } + public AbsTaskWrapper getWrapper() { + return wrapper; + } + + /** + * 发送状态到调度器 + * + * @param state {@link IThreadStateManager} + */ + private void sendNormalState(int state) { + Message msg = schedulers.obtainMessage(); + Bundle b = msg.getData(); + if (b == null) { + b = new Bundle(); + } + b.putString(IThreadStateManager.DATA_THREAD_NAME, getKey()); + msg.what = state; + msg.setData(b); + msg.sendToTarget(); + } + + /** + * 发送失败的状态 + */ + private void sendFailState(boolean needRetry) { + Message msg = schedulers.obtainMessage(); + Bundle b = msg.getData(); + if (b == null) { + b = new Bundle(); + } + b.putString(IThreadStateManager.DATA_THREAD_NAME, getKey()); + b.putBoolean(IThreadStateManager.DATA_RETRY, needRetry); + msg.what = IThreadStateManager.STATE_FAIL; + msg.setData(b); + msg.sendToTarget(); + } + private void handlerTask() { - List task = - ttBuild.buildThreadTask(recordHandler.getRecord(wrapper.getEntity().getFileSize()), - schedulers); + TaskRecord record = recordHandler.getRecord(wrapper.getEntity().getFileSize()); + if (record.threadRecords != null + && !record.threadRecords.isEmpty() + && record.threadRecords.get(0).isComplete) { + ALog.d(TAG, "子任务已完成,key:" + wrapper.getKey()); + sendNormalState(IThreadStateManager.STATE_COMPLETE); + return; + } + List task = ttBuild.buildThreadTask(record, schedulers); if (task == null || task.isEmpty()) { - ALog.e(TAG, "创建子任务的线程任务失败,key:" + getKey()); - //schedulers.obtainMessage(ISchedulers.FAIL, SubLoader.this).sendToTarget(); + ALog.e(TAG, "创建子任务的线程任务失败,key:" + wrapper.getKey()); + sendFailState(false); + return; + } + if (TextUtils.isEmpty(parentKey)) { + ALog.e(TAG, "parentKey为空"); + sendFailState(false); return; } + sendNormalState(IThreadStateManager.STATE_PRE); threadTask = task.get(0); try { - ThreadTaskManager.getInstance().startThread(getKey(), threadTask); + ThreadTaskManager.getInstance().startThread(parentKey, threadTask); + sendNormalState(IThreadStateManager.STATE_START); } catch (Exception e) { e.printStackTrace(); } } + public void setParentKey(String parentKey) { + this.parentKey = parentKey; + } + public void setNeedGetInfo(boolean needGetInfo) { this.needGetInfo = needGetInfo; } @@ -91,7 +150,7 @@ public final class SubLoader implements ILoader, ILoaderVisitor { } @Override public boolean isRunning() { - return !threadTask.isBreak(); + return threadTask != null && !threadTask.isBreak(); } @Override public void cancel() { @@ -112,8 +171,13 @@ public final class SubLoader implements ILoader, ILoaderVisitor { return false; } + /** + * 线程名,一个子任务的loader只有一个线程,使用线程名标示key + * + * @return {@link ThreadTask#getThreadName()} + */ @Override public String getKey() { - return wrapper.getKey(); + return CommonUtil.getThreadName(wrapper.getKey(), 0); } /** @@ -136,7 +200,7 @@ public final class SubLoader implements ILoader, ILoaderVisitor { } @Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) { - schedulers.obtainMessage(ISchedulers.FAIL, SubLoader.this).sendToTarget(); + sendFailState(needRetry); } }); } diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/manager/ThreadTaskManager.java b/PublicComponent/src/main/java/com/arialyy/aria/core/manager/ThreadTaskManager.java index 39f8233e..b985dca8 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/manager/ThreadTaskManager.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/manager/ThreadTaskManager.java @@ -16,6 +16,7 @@ package com.arialyy.aria.core.manager; +import android.text.TextUtils; import com.arialyy.aria.core.task.IThreadTask; import com.arialyy.aria.core.wrapper.AbsTaskWrapper; import com.arialyy.aria.util.ALog; @@ -24,7 +25,6 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; @@ -153,6 +153,49 @@ public class ThreadTaskManager { } } + /** + * 根据线程名删除任务的中的线程 + * + * @param key 任务的key,如果是组合任务,则为组合任务的key + * @param threadName 线程名 + * @return true 删除线程成功;false 删除线程失败 + */ + public boolean removeSingleTaskThread(String key, String threadName) { + try { + LOCK.tryLock(2, TimeUnit.SECONDS); + if (mExePool.isShutdown()) { + ALog.e(TAG, "线程池已经关闭"); + return false; + } + if (TextUtils.isEmpty(threadName)) { + ALog.e(TAG, "线程名为空"); + return false; + } + + key = getKey(key); + Set temp = mThreadTasks.get(key); + if (temp != null && temp.size() > 0) { + FutureContainer tempC = null; + for (FutureContainer container : temp) { + if (container.threadTask.getThreadName().equals(threadName)) { + tempC = container; + break; + } + } + if (tempC != null) { + tempC.threadTask.destroy(); + temp.remove(tempC); + return true; + } + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + LOCK.unlock(); + } + return false; + } + /** * 删除单个线程任务 * diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/task/IThreadTask.java b/PublicComponent/src/main/java/com/arialyy/aria/core/task/IThreadTask.java index 364510a6..1077d357 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/task/IThreadTask.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/task/IThreadTask.java @@ -90,7 +90,11 @@ public interface IThreadTask extends Callable { /** * 获取线程id - * @return */ int getThreadId(); + + /** + * 线程名字,命名规则:md5(任务地址 + 线程id) + */ + String getThreadName(); } diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/task/ThreadTask.java b/PublicComponent/src/main/java/com/arialyy/aria/core/task/ThreadTask.java index e8cab93c..b34abaf0 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/task/ThreadTask.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/task/ThreadTask.java @@ -53,7 +53,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver { private IEntity mEntity; protected AbsTaskWrapper mTaskWrapper; private int mFailTimes = 0; - private long mLastSaveTime; + private long mLastSaveTime, mLastSendProgressTime; private boolean isNotNetRetry; //断网情况是否重试 private boolean taskBreak = false; //任务跳出 private boolean isDestroy = false; @@ -67,6 +67,8 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver { private long mRangeProgress; private IThreadTaskAdapter mAdapter; private ThreadRecord mRecord; + private String mThreadNmae; + private long updateInterval = 1000; // 更新间隔 private Thread mConfigThread = new Thread(new Runnable() { @Override public void run() { @@ -87,6 +89,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver { isNotNetRetry = AriaConfig.getInstance().getAConfig().isNotNetRetry(); mRangeProgress = mRecord.startLocation; + updateInterval = config.updateInterval; } /** @@ -219,7 +222,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver { blockFile.getName(), blockFile.length(), mRecord.blockLen, mRecord.startLocation, mRecord.endLocation)); if (blockFile.exists()) { - blockFile.delete(); + FileUtil.deleteFile(blockFile); ALog.i(TAG, String.format("删除分块【%s】成功", blockFile.getName())); } retryBlockTask(isBreak()); @@ -232,19 +235,24 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver { return mRecord.threadId; } + @Override public String getThreadName() { + return mThreadNmae == null ? CommonUtil.getThreadName(getConfig().url, getThreadId()) + : mThreadNmae; + } + /** * 停止任务 */ @Override public void stop() { isStop = true; + final long stopLocation = mRangeProgress; updateState(IThreadStateManager.STATE_STOP, null); if (mTaskWrapper.getRequestType() == ITaskWrapper.M3U8_VOD) { writeConfig(false, getConfig().tempFile.length()); ALog.i(TAG, String.format("任务【%s】已停止", getFileName())); } else { if (mTaskWrapper.isSupportBP()) { - final long stopLocation = mRangeProgress; ALog.d(TAG, String.format("任务【%s】thread__%s__停止【当前线程停止位置:%s】", getFileName(), mRecord.threadId, stopLocation)); @@ -264,12 +272,14 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver { @Override public synchronized void updateState(int state, Bundle bundle) { Message msg = mStateHandler.obtainMessage(); - - msg.what = state; - if (bundle != null) { - msg.setData(bundle); + if (bundle == null) { + bundle = new Bundle(); } - int reqType = mTaskWrapper.getRequestType(); + msg.setData(bundle); + bundle.putString(IThreadStateManager.DATA_THREAD_NAME, getThreadName()); + bundle.putLong(IThreadStateManager.DATA_THREAD_LOCATION, mRangeProgress); + msg.what = state; + int reqType = getConfig().threadType; if (reqType == ITaskWrapper.M3U8_VOD || reqType == ITaskWrapper.M3U8_LIVE) { sendM3U8Info(state, msg); } @@ -287,9 +297,6 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver { } Bundle bundle = msg.getData(); if ((state == IThreadStateManager.STATE_COMPLETE || state == IThreadStateManager.STATE_FAIL)) { - if (bundle == null) { - bundle = new Bundle(); - } bundle.putString(ISchedulers.DATA_M3U8_URL, getConfig().url); bundle.putString(ISchedulers.DATA_M3U8_PEER_PATH, getConfig().tempFile.getPath()); bundle.putInt(ISchedulers.DATA_M3U8_PEER_INDEX, getConfig().peerIndex); @@ -318,7 +325,21 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver { if (!loopThread.isAlive() || loopThread.isInterrupted()) { return; } - mStateHandler.obtainMessage(IThreadStateManager.STATE_RUNNING, len).sendToTarget(); + // 不需要太频繁发送,以减少消息队列的压力 + if (System.currentTimeMillis() - mLastSendProgressTime > updateInterval) { + Message msg = mStateHandler.obtainMessage(); + Bundle b = msg.getData(); + if (b == null) { + b = new Bundle(); + msg.setData(b); + } + b.putString(IThreadStateManager.DATA_THREAD_NAME, getThreadName()); + msg.what = IThreadStateManager.STATE_RUNNING; + msg.obj = mRangeProgress; + msg.sendToTarget(); + mLastSendProgressTime = System.currentTimeMillis(); + } + if (System.currentTimeMillis() - mLastSaveTime > 5000 && mRangeProgress < mRecord.endLocation) { mLastSaveTime = System.currentTimeMillis(); @@ -435,7 +456,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver { */ if (blockFileLen > threadRect) { ALog.i(TAG, String.format("分块【%s】错误,将重新下载该分块", temp.getName())); - temp.delete(); + FileUtil.deleteFile(temp); mRecord.startLocation = mRecord.endLocation - mRecord.blockLen; mRecord.isComplete = false; } else if (blockFileLen < mRecord.blockLen) { @@ -459,9 +480,9 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver { */ private void sendFailMsg(BaseException e, boolean needRetry) { Bundle b = new Bundle(); - b.putBoolean(IThreadStateManager.KEY_RETRY, needRetry); + b.putBoolean(IThreadStateManager.DATA_RETRY, needRetry); if (e != null) { - b.putSerializable(IThreadStateManager.KEY_ERROR_INFO, e); + b.putSerializable(IThreadStateManager.DATA_ERROR_INFO, e); updateState(IThreadStateManager.STATE_FAIL, b); } else { updateState(IThreadStateManager.STATE_FAIL, b); diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/wrapper/ITaskWrapper.java b/PublicComponent/src/main/java/com/arialyy/aria/core/wrapper/ITaskWrapper.java index 7f3acdc8..e222842d 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/wrapper/ITaskWrapper.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/wrapper/ITaskWrapper.java @@ -97,7 +97,10 @@ public interface ITaskWrapper { IEntity getEntity(); /** - * 获取任务唯一标志 + * 获取任务唯一标志: + * 下载任务,对应文件的下载地址 + * 上传任务,对应需要上传的文件路径 + * 组合任务,对应组合任务的groupHash */ String getKey(); } diff --git a/PublicComponent/src/main/java/com/arialyy/aria/util/CommonUtil.java b/PublicComponent/src/main/java/com/arialyy/aria/util/CommonUtil.java index c046381f..bbb0f4d6 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/util/CommonUtil.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/util/CommonUtil.java @@ -61,6 +61,16 @@ public class CommonUtil { public static final String SERVER_CHARSET = "ISO-8859-1"; private static long lastClickTime; + /** + * 获取线程名称,命名规则:md5(任务地址 + 线程id) + * + * @param url 任务地址 + * @param threadId 线程id + */ + public static String getThreadName(String url, int threadId) { + return getStrMd5(url.concat(String.valueOf(threadId))); + } + /** * 检查sql的expression是否合法 * @@ -436,7 +446,7 @@ public class CommonUtil { md.update(str.getBytes()); return new BigInteger(1, md.digest()).toString(16); } catch (NoSuchAlgorithmException e) { - ALog.e(TAG, e.getMessage()); + e.printStackTrace(); } return ""; } @@ -633,7 +643,7 @@ public class CommonUtil { ignore.add(field); } } - if (!ignore.isEmpty()){ + if (!ignore.isEmpty()) { fields.removeAll(ignore); } return fields; diff --git a/PublicComponent/src/main/java/com/arialyy/aria/util/RecordUtil.java b/PublicComponent/src/main/java/com/arialyy/aria/util/RecordUtil.java index 45b71aec..02d51649 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/util/RecordUtil.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/util/RecordUtil.java @@ -85,7 +85,7 @@ public class RecordUtil { DbEntity.findRelationData(RecordWrapper.class, "dGroupHash=?", groupEntity.getGroupHash()); if (records == null || records.isEmpty()) { - ALog.w(TAG, "组任务记录删除失败,记录为null"); + ALog.w(TAG, "组任务记录已删除"); } else { for (RecordWrapper record : records) { if (record == null || record.taskRecord == null) { diff --git a/app/src/main/java/com/arialyy/simple/core/download/group/DownloadGroupActivity.java b/app/src/main/java/com/arialyy/simple/core/download/group/DownloadGroupActivity.java index 2b9980a1..48d9d47b 100644 --- a/app/src/main/java/com/arialyy/simple/core/download/group/DownloadGroupActivity.java +++ b/app/src/main/java/com/arialyy/simple/core/download/group/DownloadGroupActivity.java @@ -67,6 +67,7 @@ public class DownloadGroupActivity extends BaseActivity