package com.yang.easyhttp.download;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils;
import android.util.Log;
import com.yang.easyhttp.BuildConfig;
import com.yang.easyhttp.cache.EasyCacheType;
import com.yang.easyhttp.db.EasyDaoManager;
import com.yang.easyhttp.manager.EasyHttpClientManager;
import com.yang.easyhttp.utils.EasyConstants;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
/**
* Created by yangy on 2017/2/16.
*/
public class EasyDownloadManager {
private static EasyDownloadManager mInstance;
// ok http client
private OkHttpClient mClient;
// the thread count
private int mThreadCount = 1;
// greenDao seesion
private DaoSession mDaoSession;
// ThreadPoolExecutor
private ThreadPoolExecutor mExecutor;
// task list
private Map<String, EasyDownloadTask> mCurrentTaskList;
// queue
private LinkedBlockingQueue<Runnable> mQueue;
private EasyDownloadManager() {
}
public static synchronized EasyDownloadManager getInstance() {
if (mInstance == null) {
mInstance = new EasyDownloadManager();
}
return mInstance;
}
public void init(Context context) {
init(context, getAppropriateThreadCount());
}
public void init(Context context, int threadCount) {
init(context, threadCount, getOkHttpClient());
}
public void init(Context context, int threadCount, OkHttpClient client) {
setupDatabase(context);
recoveryTaskState();
mClient = client;
mThreadCount = threadCount < 1 ? 1 : threadCount <= EasyConstants.MAX_THREAD_COUNT ? threadCount : EasyConstants.MAX_THREAD_COUNT;
mExecutor = new ThreadPoolExecutor(
mThreadCount,
mThreadCount,
20,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()
);
mCurrentTaskList = new HashMap<>();
mQueue = (LinkedBlockingQueue<Runnable>) mExecutor.getQueue();
}
private void setupDatabase(Context context) {
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(context, "download.db", null);
SQLiteDatabase db = helper.getWritableDatabase();
DaoMaster master = new DaoMaster(db);
mDaoSession = master.newSession();
}
public DaoSession getDaoSession() {
return mDaoSession;
}
/**
* generate default client
*/
private OkHttpClient getOkHttpClient() {
return EasyHttpClientManager.getInstance().getOkHttpClient(EasyCacheType.CACHE_TYPE_DEFAULT);
}
/**
* @return generate the appropriate thread count.
*/
private int getAppropriateThreadCount() {
return Runtime.getRuntime().availableProcessors() * 2 + 1;
}
public void addTask(EasyDownloadTask task) {
EasyTaskEntity taskEntity = task.getTaskEntity();
if (taskEntity != null
&& taskEntity.getTaskStatus() != EasyTaskStatus.TASK_STATUS_DOWNLOADING
&& taskEntity.getTaskStatus() != EasyTaskStatus.TASK_STATUS_DOWNLOAD_START) {
task.setClient(mClient);
mCurrentTaskList.put(taskEntity.getTaskId(), task);
if (!mQueue.contains(task)) {
mExecutor.execute(task);
}
if (mExecutor.getTaskCount() > mThreadCount) {
task.queue();
}
}
}
public void pauseTask(EasyDownloadTask task) {
if (mQueue.contains(task)) {
mQueue.remove(task);
}
task.pause();
}
public void resumeTask(EasyDownloadTask task) {
addTask(task);
}
public void cancelTask(EasyDownloadTask task) {
if(task == null) {
return;
}
EasyTaskEntity taskEntity = task.getTaskEntity();
if (taskEntity != null) {
if (taskEntity.getTaskStatus() == EasyTaskStatus.TASK_STATUS_DOWNLOADING ||
taskEntity.getTaskStatus() == EasyTaskStatus.TASK_STATUS_DOWNLOAD_START) {
pauseTask(task);
mExecutor.remove(task);
}
if (mQueue.contains(task)) {
mQueue.remove(task);
}
mCurrentTaskList.remove(taskEntity.getTaskId());
task.cancel();
if (!TextUtils.isEmpty(taskEntity.getSaveDirPath())
&& !TextUtils.isEmpty(taskEntity.getSaveFileName())) {
File temp = new File(taskEntity.getSaveDirPath(), taskEntity.getSaveFileName());
if (temp.exists()) {
if (temp.delete()) {
if (BuildConfig.DEBUG)
Log.d("DownloadManager", "delete temp file!");
}
}
}
}
}
public EasyDownloadTask getTask(String taskId) {
EasyDownloadTask currTask = mCurrentTaskList.get(taskId);
if (currTask == null) {
EasyTaskEntity entity = EasyDaoManager.instance().queryWithId(taskId);
if (entity != null) {
int status = entity.getTaskStatus();
currTask = new EasyDownloadTask(entity);
if (status != EasyTaskStatus.TASK_STATUS_FINISH) {
mCurrentTaskList.put(taskId, currTask);
}
}
}
// 如果下载完成,判断本地是否被删除.
if (currTask != null) {
EasyTaskEntity entity = currTask.getTaskEntity();
int status = entity.getTaskStatus();
if (status == EasyTaskStatus.TASK_STATUS_FINISH) {
String saveDirPath = entity.getSaveDirPath();
String saveFileName = entity.getSaveFileName();
if (TextUtils.isEmpty(saveDirPath) || TextUtils.isEmpty(saveFileName)) {
return currTask;
}
File file = new File(saveDirPath, saveFileName);
if (!file.exists()) {
mCurrentTaskList.remove(taskId);
EasyDaoManager.instance().delete(entity);
}
}
}
return currTask;
}
public boolean isPauseTask(String id) {
EasyTaskEntity entity = EasyDaoManager.instance().queryWithId(id);
if (entity != null) {
File file = new File(entity.getSaveDirPath(), entity.getSaveFileName());
if (file.exists()) {
long totalSize = entity.getTotalSize();
return totalSize > 0 && file.length() < totalSize;
}
}
return false;
}
public boolean isFinishTask(String id) {
EasyTaskEntity entity = EasyDaoManager.instance().queryWithId(id);
if (entity != null) {
File file = new File(entity.getSaveDirPath(), entity.getSaveFileName());
if (file.exists()) {
return file.length() == entity.getTotalSize();
}
}
return false;
}
private void recoveryTaskState() {
List<EasyTaskEntity> entities = EasyDaoManager.instance().queryAll();
for (EasyTaskEntity entity : entities) {
long completedSize = entity.getCompletedSize();
long totalSize = entity.getTotalSize();
if (completedSize > 0 &&
completedSize < totalSize &&
entity.getTaskStatus() != EasyTaskStatus.TASK_STATUS_PAUSE) {
entity.setTaskStatus(EasyTaskStatus.TASK_STATUS_PAUSE);
EasyDaoManager.instance().update(entity);
}
}
}
}