diff --git a/downloadutil/src/main/java/com/arialyy/downloadutil/DownloadManager.java b/downloadutil/src/main/java/com/arialyy/downloadutil/core/DownloadManager.java similarity index 97% rename from downloadutil/src/main/java/com/arialyy/downloadutil/DownloadManager.java rename to downloadutil/src/main/java/com/arialyy/downloadutil/core/DownloadManager.java index f2e6fc19..fc1668db 100644 --- a/downloadutil/src/main/java/com/arialyy/downloadutil/DownloadManager.java +++ b/downloadutil/src/main/java/com/arialyy/downloadutil/core/DownloadManager.java @@ -1,4 +1,4 @@ -package com.arialyy.downloadutil; +package com.arialyy.downloadutil.core; import android.content.Context; diff --git a/downloadutil/src/main/java/com/arialyy/downloadutil/core/DownloadTarget.java b/downloadutil/src/main/java/com/arialyy/downloadutil/core/DownloadTarget.java index 31819ba9..6de35bb8 100644 --- a/downloadutil/src/main/java/com/arialyy/downloadutil/core/DownloadTarget.java +++ b/downloadutil/src/main/java/com/arialyy/downloadutil/core/DownloadTarget.java @@ -1,33 +1,69 @@ package com.arialyy.downloadutil.core; -import com.arialyy.downloadutil.core.inf.IDownloader; -import com.arialyy.downloadutil.core.inf.ITask; -import com.arialyy.downloadutil.core.pool.CachePool; -import com.arialyy.downloadutil.core.pool.ExecutePool; - /** - * Created by lyy on 2016/8/16. - * 任务下载器,提供抽象的方法供具体的实现类操作 + * Created by lyy on 2016/8/17. + * 下载任务调度类 */ -public abstract class DownloadTarget implements IDownloader, ITask { - protected CachePool mCachePool = CachePool.getInstance(); - protected ExecutePool mExecutePool = ExecutePool.getInstance(); - - /** - * 获取当前运行的任务数 - * - * @return 当前正在执行的任务数 - */ - public int getCurrentTaskNum() { - return mExecutePool.size(); - } - - /** - * 获取缓存任务数 - * - * @return 获取缓存的任务数 - */ - public int getCacheTaskNum() { - return mCachePool.size(); +public class DownloadTarget extends IDownloadTarget { + + private static final Object LOCK = new Object(); + private static volatile DownloadTarget INSTANCE = null; + + public static DownloadTarget getInstance() { + if (INSTANCE == null) { + synchronized (LOCK) { + INSTANCE = new DownloadTarget(); + } + } + return INSTANCE; + } + + private DownloadTarget() { + + } + + @Override + public void startTask(Task task) { + + } + + @Override + public void stopTask(Task task) { + + } + + @Override + public void cancelTask(Task task) { + + } + + @Override + public void reTryStart(Task task) { + + } + + @Override + public void createTask(String downloadUrl, String downloadPath) { + + } + + @Override + public Task getTask(String downloadUrl) { + return null; + } + + @Override + public int getTaskState(String downloadUrl) { + return 0; + } + + @Override + public void removeTask(String downloadUrl) { + + } + + @Override + public Task getNextTask() { + return null; } } diff --git a/downloadutil/src/main/java/com/arialyy/downloadutil/core/IDownloadTarget.java b/downloadutil/src/main/java/com/arialyy/downloadutil/core/IDownloadTarget.java new file mode 100644 index 00000000..6ff3a41f --- /dev/null +++ b/downloadutil/src/main/java/com/arialyy/downloadutil/core/IDownloadTarget.java @@ -0,0 +1,201 @@ +package com.arialyy.downloadutil.core; + +import android.os.Handler; +import android.os.Message; +import android.util.Log; + +import com.arialyy.downloadutil.core.inf.IDownloader; +import com.arialyy.downloadutil.core.inf.ITask; +import com.arialyy.downloadutil.core.pool.CachePool; +import com.arialyy.downloadutil.core.pool.ExecutePool; +import com.arialyy.downloadutil.entity.DownloadEntity; + +/** + * Created by lyy on 2016/8/16. + * 任务下载器,提供抽象的方法供具体的实现类操作 + */ +public abstract class IDownloadTarget implements IDownloader, ITask { + /** + * 任务开始 + */ + public static final int START = 1; + /** + * 任务停止 + */ + public static final int STOP = 2; + /** + * 任务失败 + */ + public static final int FAIL = 3; + /** + * 任务取消 + */ + public static final int CANCEL = 4; + /** + * 任务完成 + */ + public static final int COMPLETE = 5; + + protected CachePool mCachePool = CachePool.getInstance(); + protected ExecutePool mExecutePool = ExecutePool.getInstance(); + protected AutoTaskHandler mTaskHandler; + /** + * 下载失败次数 + */ + protected int mFailNum = 10; + + /** + * 超时时间 + */ + protected long mTimeOut = 10000; + + /** + * 下载器任务监听 + */ + private OnTargetListener mTargetListener; + + /** + * Target处理任务监听 + */ + public interface OnTargetListener { + /** + * 任务开始 + * + * @param task + */ + public void onTaskStart(Task task); + + /** + * 任务停止 + * + * @param task + */ + public void onTaskStop(Task task); + + /** + * 任务取消 + * + * @param task + */ + public void onTaskCancel(Task task); + + /** + * 任务下载失败 + * + * @param task + */ + public void onTaskFail(Task task); + + /** + * 任务完成 + * + * @param task + */ + public void onTaskComplete(Task task); + } + + protected IDownloadTarget() { + mTaskHandler = new AutoTaskHandler(this); + } + + /** + * 设置下载器监听 + * + * @param targetListener {@link OnTargetListener} + */ + public void setOnTargetListener(OnTargetListener targetListener) { + this.mTargetListener = targetListener; + } + + /** + * 获取当前运行的任务数 + * + * @return 当前正在执行的任务数 + */ + public int getCurrentTaskNum() { + return mExecutePool.size(); + } + + /** + * 获取缓存任务数 + * + * @return 获取缓存的任务数 + */ + public int getCacheTaskNum() { + return mCachePool.size(); + } + + public void setFailNum(int mFailNum) { + this.mFailNum = mFailNum; + } + + public void setTimeOut(long timeOut) { + this.mTimeOut = timeOut; + } + + /** + * 自动处理任务停止,下载失败,取消下载,自动下载下一个任务的操作 + */ + private static class AutoTaskHandler extends Handler { + private static final String TAG = "AutoTaskHandler"; + IDownloadTarget target; + + public AutoTaskHandler(IDownloadTarget target) { + this.target = target; + } + + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + DownloadEntity entity = (DownloadEntity) msg.obj; + if (entity == null) { + Log.e(TAG, "请传入下载实体DownloadEntity"); + return; + } + switch (msg.what) { + case STOP: + startNextTask(entity); + break; + case CANCEL: + startNextTask(entity); + break; + case COMPLETE: + startNextTask(entity); + break; + case FAIL: + handleFailTask(entity); + break; + } + } + + /** + * 处理下载任务下载失败的情形 + * + * @param entity 失败实体 + */ + private void handleFailTask(DownloadEntity entity) { + if (entity.getFailNum() <= target.mFailNum) { + Task task = target.getTask(entity.getDownloadUrl()); + target.reTryStart(task); + } else { + startNextTask(entity); + } + } + + /** + * 启动下一个任务,条件:任务停止,取消下载,任务完成 + * + * @param entity 通过Handler传递的下载实体 + */ + private void startNextTask(DownloadEntity entity) { + target.removeTask(entity.getDownloadUrl()); + Task newTask = target.getNextTask(); + if (newTask == null) { + Log.e(TAG, "没有下一任务"); + return; + } + target.startTask(newTask); + } + } + +} diff --git a/downloadutil/src/main/java/com/arialyy/downloadutil/core/Task.java b/downloadutil/src/main/java/com/arialyy/downloadutil/core/Task.java index ee26af3c..c30b3b93 100644 --- a/downloadutil/src/main/java/com/arialyy/downloadutil/core/Task.java +++ b/downloadutil/src/main/java/com/arialyy/downloadutil/core/Task.java @@ -5,7 +5,6 @@ import android.content.Intent; import android.os.Handler; import android.util.Log; -import com.arialyy.downloadutil.DownloadManager; import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.util.IDownloadListener; import com.arialyy.downloadutil.util.DownLoadUtil; @@ -17,27 +16,8 @@ import java.net.HttpURLConnection; * 下载任务类 */ public class Task { - public static final String TAG = "Task"; - /** - * 任务开始 - */ - public static final int START = 1; - /** - * 任务停止 - */ - public static final int STOP = 2; - /** - * 任务失败 - */ - public static final int FAILE = 3; - /** - * 任务取消 - */ - public static final int CANCEL = 4; - /** - * 任务完成 - */ - public static final int COMPLETE = 5; + public static final String TAG = "Task"; + DownloadEntity downloadEntity; IDownloadListener listener; Handler outHandler; @@ -121,7 +101,7 @@ public class Task { public void onStart(long startLocation) { super.onStart(startLocation); downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING); - sendInState2Target(START); + sendInState2Target(IDownloadTarget.START); sendIntent(DownloadManager.ACTION_START, startLocation); } @@ -138,7 +118,7 @@ public class Task { public void onStop(long stopLocation) { super.onStop(stopLocation); downloadEntity.setState(DownloadEntity.STATE_STOP); - sendInState2Target(STOP); + sendInState2Target(IDownloadTarget.STOP); sendIntent(DownloadManager.ACTION_STOP, stopLocation); } @@ -146,7 +126,7 @@ public class Task { public void onCancel() { super.onCancel(); downloadEntity.setState(DownloadEntity.STATE_CANCEL); - sendInState2Target(CANCEL); + sendInState2Target(IDownloadTarget.CANCEL); sendIntent(DownloadManager.ACTION_CANCEL, -1); downloadEntity.deleteData(); } @@ -156,7 +136,7 @@ public class Task { super.onComplete(); downloadEntity.setState(DownloadEntity.STATE_COMPLETE); downloadEntity.setDownloadComplete(true); - sendInState2Target(COMPLETE); + sendInState2Target(IDownloadTarget.COMPLETE); sendIntent(DownloadManager.ACTION_COMPLETE, -1); } @@ -164,14 +144,14 @@ public class Task { public void onFail() { super.onFail(); downloadEntity.setState(DownloadEntity.STATE_FAIL); - sendInState2Target(FAILE); + sendInState2Target(IDownloadTarget.FAIL); sendIntent(DownloadManager.ACTION_FAIL, -1); } /** * 将任务状态发送给下载器 * - * @param state {@link Task#START} + * @param state {@link IDownloadTarget#START} */ private void sendInState2Target(int state) { if (outHandler != null) { diff --git a/downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/IDownloader.java b/downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/IDownloader.java index a8b71c97..d6812de3 100644 --- a/downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/IDownloader.java +++ b/downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/IDownloader.java @@ -28,4 +28,11 @@ public interface IDownloader { */ public void cancelTask(Task task); + /** + * 重试下载 + * + * @param task {@link Task} + */ + public void reTryStart(Task task); + } diff --git a/downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/IPool.java b/downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/IPool.java index bf85bb92..58efda4f 100644 --- a/downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/IPool.java +++ b/downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/IPool.java @@ -37,6 +37,14 @@ public interface IPool { */ public boolean removeTask(Task task); + /** + * 通过下载链接移除下载任务 + * + * @param downloadUrl 下载链接 + * @return true:移除成功 + */ + public boolean removeTask(String downloadUrl); + /** * 池子大小 * diff --git a/downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/ITask.java b/downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/ITask.java index ee9c3171..b1ab819d 100644 --- a/downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/ITask.java +++ b/downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/ITask.java @@ -22,7 +22,7 @@ public interface ITask { * @param downloadUrl 下载链接 * @return {@link Task} */ - public Task searchTask(String downloadUrl); + public Task getTask(String downloadUrl); /** * 通过下载链接搜索下载任务 @@ -31,4 +31,19 @@ public interface ITask { * @return {@link com.arialyy.downloadutil.entity.DownloadEntity#STATE_FAIL} */ public int getTaskState(String downloadUrl); + + /** + * 通过下载链接删除任务 + * + * @param downloadUrl 下载链接 + */ + public void removeTask(String downloadUrl); + + /** + * 获取缓存池的下一个任务 + * + * @return 下载任务 or null + */ + public Task getNextTask(); + } diff --git a/downloadutil/src/main/java/com/arialyy/downloadutil/core/pool/CachePool.java b/downloadutil/src/main/java/com/arialyy/downloadutil/core/pool/CachePool.java index b16124b8..53ba514b 100644 --- a/downloadutil/src/main/java/com/arialyy/downloadutil/core/pool/CachePool.java +++ b/downloadutil/src/main/java/com/arialyy/downloadutil/core/pool/CachePool.java @@ -1,5 +1,6 @@ package com.arialyy.downloadutil.core.pool; +import android.text.TextUtils; import android.util.Log; import com.arialyy.downloadutil.core.Task; @@ -73,6 +74,10 @@ public class CachePool implements IPool { @Override public Task getTask(String downloadUrl) { synchronized (LOCK) { + if (TextUtils.isEmpty(downloadUrl)) { + Log.e(TAG, "请传入有效的下载链接"); + return null; + } String key = Util.keyToHashKey(downloadUrl); Task task = mCacheArray.get(key); if (task != null) { @@ -97,6 +102,20 @@ public class CachePool implements IPool { } } + @Override + public boolean removeTask(String downloadUrl) { + synchronized (LOCK) { + if (TextUtils.isEmpty(downloadUrl)) { + Log.e(TAG, "请传入有效的下载链接"); + return false; + } + String key = Util.keyToHashKey(downloadUrl); + Task task = mCacheArray.get(key); + mCacheArray.remove(key); + return mCacheQueue.remove(task); + } + } + @Override public int size() { return mCacheQueue.size(); diff --git a/downloadutil/src/main/java/com/arialyy/downloadutil/core/pool/ExecutePool.java b/downloadutil/src/main/java/com/arialyy/downloadutil/core/pool/ExecutePool.java index e6bd80c1..16e3d25a 100644 --- a/downloadutil/src/main/java/com/arialyy/downloadutil/core/pool/ExecutePool.java +++ b/downloadutil/src/main/java/com/arialyy/downloadutil/core/pool/ExecutePool.java @@ -1,5 +1,6 @@ package com.arialyy.downloadutil.core.pool; +import android.text.TextUtils; import android.util.Log; import com.arialyy.downloadutil.core.Task; @@ -115,6 +116,10 @@ public class ExecutePool implements IPool { @Override public Task getTask(String downloadUrl) { synchronized (LOCK) { + if (TextUtils.isEmpty(downloadUrl)) { + Log.e(TAG, "请传入有效的下载链接"); + return null; + } String key = Util.keyToHashKey(downloadUrl); Task task = mExecuteArray.get(key); if (task != null) { @@ -141,6 +146,20 @@ public class ExecutePool implements IPool { } } + @Override + public boolean removeTask(String downloadUrl) { + synchronized (LOCK) { + if (TextUtils.isEmpty(downloadUrl)) { + Log.e(TAG, "请传入有效的下载链接"); + return false; + } + String key = Util.keyToHashKey(downloadUrl); + Task task = mExecuteArray.get(key); + mExecuteArray.remove(key); + return mExecuteQueue.remove(task); + } + } + @Override public int size() { return mExecuteQueue.size(); diff --git a/downloadutil/src/main/java/com/arialyy/downloadutil/entity/DownloadEntity.java b/downloadutil/src/main/java/com/arialyy/downloadutil/entity/DownloadEntity.java index 5c12ad0b..97986f8f 100644 --- a/downloadutil/src/main/java/com/arialyy/downloadutil/entity/DownloadEntity.java +++ b/downloadutil/src/main/java/com/arialyy/downloadutil/entity/DownloadEntity.java @@ -46,6 +46,15 @@ public class DownloadEntity extends DbEntity implements Parcelable, Cloneable { private int state = STATE_WAIT; private boolean isDownloadComplete = false; //是否下载完成 private long currentProgress = 0; //当前下载进度 + private int failNum = 0; + + public int getFailNum() { + return failNum; + } + + public void setFailNum(int failNum) { + this.failNum = failNum; + } public String getDownloadUrl() { return downloadUrl; @@ -126,6 +135,7 @@ public class DownloadEntity extends DbEntity implements Parcelable, Cloneable { dest.writeInt(this.state); dest.writeByte(this.isDownloadComplete ? (byte) 1 : (byte) 0); dest.writeLong(this.currentProgress); + dest.writeInt(this.failNum); } protected DownloadEntity(Parcel in) { @@ -136,6 +146,7 @@ public class DownloadEntity extends DbEntity implements Parcelable, Cloneable { this.state = in.readInt(); this.isDownloadComplete = in.readByte() != 0; this.currentProgress = in.readLong(); + this.failNum = in.readInt(); } public static final Creator CREATOR = new Creator() { @@ -149,4 +160,18 @@ public class DownloadEntity extends DbEntity implements Parcelable, Cloneable { return new DownloadEntity[size]; } }; + + @Override + public String toString() { + return "DownloadEntity{" + + "downloadUrl='" + downloadUrl + '\'' + + ", downloadPath='" + downloadPath + '\'' + + ", completeTime=" + completeTime + + ", fileSize=" + fileSize + + ", state=" + state + + ", isDownloadComplete=" + isDownloadComplete + + ", currentProgress=" + currentProgress + + ", failNum=" + failNum + + '}'; + } } \ No newline at end of file