parent
dbddf3b4e2
commit
b976348ffe
@ -1,34 +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.command.group; |
|
||||||
|
|
||||||
import com.arialyy.aria.core.inf.AbsGroupTaskWrapper; |
|
||||||
|
|
||||||
/** |
|
||||||
* Created by AriaL on 2017/6/29. |
|
||||||
* 删除任务组子任务 |
|
||||||
*/ |
|
||||||
class GroupCancelCmd<T extends AbsGroupTaskWrapper> extends AbsGroupCmd<T> { |
|
||||||
GroupCancelCmd(T entity) { |
|
||||||
super(entity); |
|
||||||
} |
|
||||||
|
|
||||||
@Override public void executeCmd() { |
|
||||||
if (checkTask()) { |
|
||||||
tempTask.cancelSubTask(childUrl); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,146 @@ |
|||||||
|
/* |
||||||
|
* 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.download.group; |
||||||
|
|
||||||
|
import android.os.Handler; |
||||||
|
import com.arialyy.aria.core.download.DownloadEntity; |
||||||
|
import com.arialyy.aria.core.inf.IDownloadListener; |
||||||
|
import com.arialyy.aria.core.inf.IEntity; |
||||||
|
import com.arialyy.aria.core.scheduler.ISchedulers; |
||||||
|
import com.arialyy.aria.exception.BaseException; |
||||||
|
import com.arialyy.aria.util.CommonUtil; |
||||||
|
|
||||||
|
/** |
||||||
|
* 子任务事件监听 |
||||||
|
*/ |
||||||
|
class ChildDownloadListener implements IDownloadListener { |
||||||
|
private DownloadEntity subEntity; |
||||||
|
private int RUN_SAVE_INTERVAL = 5 * 1000; //5s保存一次下载中的进度
|
||||||
|
private long lastSaveTime; |
||||||
|
private long lastLen; |
||||||
|
private Handler schedulers; |
||||||
|
private SubDownloadLoader loader; |
||||||
|
|
||||||
|
ChildDownloadListener(Handler schedulers, SubDownloadLoader 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, -1); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void onPostPre(long fileSize) { |
||||||
|
subEntity.setFileSize(fileSize); |
||||||
|
subEntity.setConvertFileSize(CommonUtil.formatFileSize(fileSize)); |
||||||
|
saveData(IEntity.STATE_POST_PRE, -1); |
||||||
|
sendToTarget(ISchedulers.POST_PRE, loader); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void onResume(long resumeLocation) { |
||||||
|
lastLen = resumeLocation; |
||||||
|
saveData(IEntity.STATE_POST_PRE, IEntity.STATE_RUNNING); |
||||||
|
sendToTarget(ISchedulers.START, loader); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void onStart(long startLocation) { |
||||||
|
lastLen = startLocation; |
||||||
|
saveData(IEntity.STATE_POST_PRE, IEntity.STATE_RUNNING); |
||||||
|
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, lastLen); |
||||||
|
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, SubDownloadLoader util) { |
||||||
|
schedulers.obtainMessage(state, util).sendToTarget(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,169 @@ |
|||||||
|
/* |
||||||
|
* 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.download.group; |
||||||
|
|
||||||
|
import com.arialyy.aria.core.inf.AbsTaskWrapper; |
||||||
|
import java.util.HashSet; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
/** |
||||||
|
* 组合任务执行中的状态信息 |
||||||
|
*/ |
||||||
|
class GroupRunState { |
||||||
|
/** |
||||||
|
* 子任务数 |
||||||
|
*/ |
||||||
|
private int mSubSize; |
||||||
|
|
||||||
|
/** |
||||||
|
* 已经完成的任务数 |
||||||
|
*/ |
||||||
|
private int mCompleteNum; |
||||||
|
|
||||||
|
/** |
||||||
|
* 失败的任务数 |
||||||
|
*/ |
||||||
|
private int mFailNum; |
||||||
|
|
||||||
|
/** |
||||||
|
* 停止的任务数 |
||||||
|
*/ |
||||||
|
private int mStopNum; |
||||||
|
|
||||||
|
/** |
||||||
|
* 当前进度 |
||||||
|
*/ |
||||||
|
private long mProgress; |
||||||
|
|
||||||
|
/** |
||||||
|
* 组合任务监听 |
||||||
|
*/ |
||||||
|
IDownloadGroupListener listener; |
||||||
|
|
||||||
|
/** |
||||||
|
* 子任务队列 |
||||||
|
*/ |
||||||
|
SimpleSubQueue queue; |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否在执行 |
||||||
|
*/ |
||||||
|
boolean isRunning = false; |
||||||
|
|
||||||
|
/** |
||||||
|
* 子任务失败、停止记录,用于当子任务失败重新被用户点击开始时,更新{@link #mStopNum}或{@link #mFailNum} |
||||||
|
* 保存的数据为:子任务key |
||||||
|
*/ |
||||||
|
private Set<String> mFailTemp = new HashSet<>(), mStopTemp = new HashSet<>(); |
||||||
|
|
||||||
|
private String mGroupHash; |
||||||
|
|
||||||
|
GroupRunState(String groupHash, IDownloadGroupListener listener, int subSize, |
||||||
|
SimpleSubQueue queue) { |
||||||
|
this.listener = listener; |
||||||
|
this.queue = queue; |
||||||
|
mSubSize = subSize; |
||||||
|
mGroupHash = groupHash; |
||||||
|
} |
||||||
|
|
||||||
|
String getGroupHash() { |
||||||
|
return mGroupHash; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取组合任务子任务数 |
||||||
|
*/ |
||||||
|
int getSubSize() { |
||||||
|
return mSubSize; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取失败的数量 |
||||||
|
*/ |
||||||
|
int getFailNum() { |
||||||
|
return mFailNum; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取停止的数量 |
||||||
|
*/ |
||||||
|
int getStopNum() { |
||||||
|
return mStopNum; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取完成的数量 |
||||||
|
*/ |
||||||
|
int getCompleteNum() { |
||||||
|
return mCompleteNum; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取当前组合任务总进度 |
||||||
|
*/ |
||||||
|
long getProgress() { |
||||||
|
return mProgress; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 更新完成的数量,mCompleteNum + 1 |
||||||
|
*/ |
||||||
|
void updateCompleteNum() { |
||||||
|
mCompleteNum++; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 更新任务进度 |
||||||
|
*/ |
||||||
|
void updateProgress(long newProgress) { |
||||||
|
this.mProgress = newProgress; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 当子任务开始时,更新停止\失败的任务数 |
||||||
|
* |
||||||
|
* @param key {@link AbsTaskWrapper#getKey()} |
||||||
|
*/ |
||||||
|
void updateCount(String key) { |
||||||
|
if (mFailTemp.contains(key)) { |
||||||
|
mFailTemp.remove(key); |
||||||
|
mFailNum--; |
||||||
|
} else if (mStopTemp.contains(key)) { |
||||||
|
mStopTemp.remove(key); |
||||||
|
mStopNum--; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 统计子任务停止的数量 |
||||||
|
* |
||||||
|
* @param key {@link AbsTaskWrapper#getKey()} |
||||||
|
*/ |
||||||
|
void countStopNum(String key) { |
||||||
|
mStopTemp.add(key); |
||||||
|
mStopNum++; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 统计子任务失败的数量 |
||||||
|
* |
||||||
|
* @param key {@link AbsTaskWrapper#getKey()} |
||||||
|
*/ |
||||||
|
void countFailNum(String key) { |
||||||
|
mFailTemp.add(key); |
||||||
|
mFailNum++; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,113 @@ |
|||||||
|
/* |
||||||
|
* 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.download.group; |
||||||
|
|
||||||
|
import android.os.Handler; |
||||||
|
import com.arialyy.aria.core.common.CompleteInfo; |
||||||
|
import com.arialyy.aria.core.common.IUtil; |
||||||
|
import com.arialyy.aria.core.common.OnFileInfoCallback; |
||||||
|
import com.arialyy.aria.core.download.DTaskWrapper; |
||||||
|
import com.arialyy.aria.core.download.DownloadEntity; |
||||||
|
import com.arialyy.aria.core.download.downloader.Downloader; |
||||||
|
import com.arialyy.aria.core.download.downloader.HttpFileInfoThread; |
||||||
|
import com.arialyy.aria.core.scheduler.ISchedulers; |
||||||
|
import com.arialyy.aria.exception.BaseException; |
||||||
|
|
||||||
|
/** |
||||||
|
* 子任务下载工具,负责创建{@link Downloader} |
||||||
|
*/ |
||||||
|
class SubDownloadLoader implements IUtil { |
||||||
|
|
||||||
|
private Downloader mDownloader; |
||||||
|
private DTaskWrapper mWrapper; |
||||||
|
private Handler mSchedulers; |
||||||
|
private ChildDownloadListener mListener; |
||||||
|
|
||||||
|
SubDownloadLoader(Handler schedulers, DTaskWrapper taskWrapper) { |
||||||
|
mWrapper = taskWrapper; |
||||||
|
mSchedulers = schedulers; |
||||||
|
mListener = new ChildDownloadListener(mSchedulers, SubDownloadLoader.this); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public String getKey() { |
||||||
|
return mWrapper.getKey(); |
||||||
|
} |
||||||
|
|
||||||
|
public DTaskWrapper getWrapper() { |
||||||
|
return mWrapper; |
||||||
|
} |
||||||
|
|
||||||
|
public DownloadEntity getEntity() { |
||||||
|
return mWrapper.getEntity(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 重新开始任务 |
||||||
|
*/ |
||||||
|
void reStart() { |
||||||
|
if (mDownloader != null) { |
||||||
|
mDownloader.retryTask(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override public long getFileSize() { |
||||||
|
return mDownloader == null ? -1 : mDownloader.getFileSize(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public long getCurrentLocation() { |
||||||
|
return mDownloader == null ? -1 : mDownloader.getCurrentLocation(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public boolean isRunning() { |
||||||
|
return mDownloader != null && mDownloader.isRunning(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void cancel() { |
||||||
|
if (mDownloader != null) { |
||||||
|
mDownloader.cancel(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void stop() { |
||||||
|
if (mDownloader != null) { |
||||||
|
mDownloader.stop(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void start() { |
||||||
|
new Thread(new HttpFileInfoThread(mWrapper, new OnFileInfoCallback() { |
||||||
|
|
||||||
|
@Override public void onComplete(String url, CompleteInfo info) { |
||||||
|
mDownloader = new Downloader(mListener, mWrapper); |
||||||
|
mDownloader.start(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void onFail(String url, BaseException e, boolean needRetry) { |
||||||
|
mSchedulers.obtainMessage(ISchedulers.FAIL, SubDownloadLoader.this); |
||||||
|
} |
||||||
|
})).start(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void resume() { |
||||||
|
start(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override public void setMaxSpeed(int speed) { |
||||||
|
if (mDownloader != null) { |
||||||
|
mDownloader.setMaxSpeed(speed); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue