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