package com.yang.easyhttp.download; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.text.TextUtils; import com.yang.easyhttp.cache.EasyCacheType; import com.yang.easyhttp.db.EasyDaoManager; import com.yang.easyhttp.manager.EasyHttpClientManager; import com.yang.easyhttp.utils.EasyIOUtils; import com.yang.easyhttp.utils.EasyFileUtils; import java.io.BufferedInputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.SocketTimeoutException; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import okhttp3.ResponseBody; /** * Created by yangy on 2017/2/16. */ public class EasyDownloadTask implements Runnable { private OkHttpClient mClient; private EasyDownloadTaskListener mDownloadTaskListener; private EasyTaskEntity mTaskEntity; private Handler mHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { if (mDownloadTaskListener == null) { return; } int code = msg.what; switch (code) { case EasyTaskStatus.TASK_STATUS_INIT: break; case EasyTaskStatus.TASK_STATUS_QUEUE: mDownloadTaskListener.onQueue(EasyDownloadTask.this); break; case EasyTaskStatus.TASK_STATUS_CONNECTING: mDownloadTaskListener.onConnecting(EasyDownloadTask.this); break; case EasyTaskStatus.TASK_STATUS_DOWNLOAD_START: mDownloadTaskListener.onDownloadStart(EasyDownloadTask.this); break; case EasyTaskStatus.TASK_STATUS_DOWNLOADING: mDownloadTaskListener.onDownloading(EasyDownloadTask.this); break; case EasyTaskStatus.TASK_STATUS_PAUSE: mDownloadTaskListener.onPause(EasyDownloadTask.this); break; case EasyTaskStatus.TASK_STATUS_CANCEL: mDownloadTaskListener.onCancel(EasyDownloadTask.this); break; case EasyTaskStatus.TASK_STATUS_REQUEST_ERROR: mDownloadTaskListener.onError(EasyDownloadTask.this, EasyTaskStatus.TASK_STATUS_REQUEST_ERROR); break; case EasyTaskStatus.TASK_STATUS_STORAGE_ERROR: mDownloadTaskListener.onError(EasyDownloadTask.this, EasyTaskStatus.TASK_STATUS_STORAGE_ERROR); break; case EasyTaskStatus.TASK_STATUS_FINISH: mDownloadTaskListener.onFinish(EasyDownloadTask.this); break; default: break; } } }; public EasyDownloadTask(EasyTaskEntity taskEntity) { mClient = EasyHttpClientManager.getInstance().getOkHttpClient(EasyCacheType.CACHE_TYPE_DEFAULT); mTaskEntity = taskEntity; } public void setClient(OkHttpClient client) { this.mClient = client; } public void setDownloadTaskListener(EasyDownloadTaskListener downloadTaskListener) { this.mDownloadTaskListener = downloadTaskListener; } public EasyTaskEntity getTaskEntity() { return mTaskEntity; } @Override public void run() { InputStream inputStream = null; BufferedInputStream bufferedInputStream = null; RandomAccessFile randomAccessFile = null; try { String saveDirPath = mTaskEntity.getSaveDirPath(); if (TextUtils.isEmpty(saveDirPath)) { saveDirPath = EasyFileUtils.getDefaultFilePath(EasyHttpClientManager.getInstance().getContext()); } mTaskEntity.setSaveDirPath(saveDirPath); File file = new File(saveDirPath); if (!file.exists()) { boolean created = file.mkdirs(); if (!created) { throw new FileNotFoundException("save dir path not created"); } } String saveFileName = mTaskEntity.getSaveFileName(); if (TextUtils.isEmpty(saveFileName)) { saveFileName = EasyFileUtils.getFileNameFromUrl(mTaskEntity.getDownloadUrl()); } mTaskEntity.setSaveFileName(saveFileName); File saveFile = new File(saveDirPath, saveFileName); randomAccessFile = new RandomAccessFile(saveFile, "rwd"); mTaskEntity.setTaskStatus(EasyTaskStatus.TASK_STATUS_CONNECTING); mHandler.sendEmptyMessage(EasyTaskStatus.TASK_STATUS_CONNECTING); // 异常检测及下载错误校正. long completedSize = mTaskEntity.getCompletedSize(); long totalSize = mTaskEntity.getTotalSize(); if (randomAccessFile.length() == 0 || completedSize > totalSize) { completedSize = 0; mTaskEntity.setTotalSize(0); mTaskEntity.setCompletedSize(0); if (EasyDaoManager.instance().queryWithId(mTaskEntity.getTaskId()) != null) { EasyDaoManager.instance().delete(mTaskEntity); } } if (EasyDaoManager.instance().queryWithId(mTaskEntity.getTaskId()) != null) { EasyDaoManager.instance().update(mTaskEntity); } Request request = new Request.Builder() .url(mTaskEntity.getDownloadUrl()) .header("RANGE", "bytes=" + completedSize + "-") .build(); randomAccessFile.seek(completedSize); Response response = mClient.newCall(request).execute(); if (response.isSuccessful()) { ResponseBody responseBody = response.body(); if (responseBody != null) { mTaskEntity.setTaskStatus(EasyTaskStatus.TASK_STATUS_DOWNLOAD_START); if (EasyDaoManager.instance().queryWithId(mTaskEntity.getTaskId()) == null) { EasyDaoManager.instance().insertOrReplace(mTaskEntity); mTaskEntity.setTotalSize(responseBody.contentLength()); } double updateSize = mTaskEntity.getTotalSize() / 100; inputStream = responseBody.byteStream(); bufferedInputStream = new BufferedInputStream(inputStream); byte[] buffer = new byte[1024]; int length; int buffOffset = 0; while ( (length = bufferedInputStream.read(buffer)) > 0 && mTaskEntity.getTaskStatus() != EasyTaskStatus.TASK_STATUS_CANCEL && mTaskEntity.getTaskStatus() != EasyTaskStatus.TASK_STATUS_PAUSE) { randomAccessFile.write(buffer, 0, length); completedSize += length; buffOffset += length; mTaskEntity.setCompletedSize(completedSize); //避免一直调用数据库. if (buffOffset >= updateSize) { buffOffset = 0; EasyDaoManager.instance().update(mTaskEntity); mHandler.sendEmptyMessage(EasyTaskStatus.TASK_STATUS_DOWNLOADING); } if (completedSize == mTaskEntity.getTotalSize()) { mHandler.sendEmptyMessage(EasyTaskStatus.TASK_STATUS_DOWNLOADING); mTaskEntity.setTaskStatus(EasyTaskStatus.TASK_STATUS_FINISH); mHandler.sendEmptyMessage(EasyTaskStatus.TASK_STATUS_FINISH); EasyDaoManager.instance().update(mTaskEntity); } } // if (mTaskEntity.getTotalSize() == -1 && completedSize > 0) { // // 返回文件大小未知情况下,直接设为下载完成. // mHandler.sendEmptyMessage(EasyTaskStatus.TASK_STATUS_DOWNLOADING); // mTaskEntity.setTaskStatus(EasyTaskStatus.TASK_STATUS_FINISH); // mHandler.sendEmptyMessage(EasyTaskStatus.TASK_STATUS_FINISH); // EasyDaoManager.instance().update(mTaskEntity); // } } } else { mTaskEntity.setTaskStatus(EasyTaskStatus.TASK_STATUS_REQUEST_ERROR); mHandler.sendEmptyMessage(EasyTaskStatus.TASK_STATUS_REQUEST_ERROR); } } catch (FileNotFoundException e) { mTaskEntity.setTaskStatus(EasyTaskStatus.TASK_STATUS_STORAGE_ERROR); mHandler.sendEmptyMessage(EasyTaskStatus.TASK_STATUS_STORAGE_ERROR); e.printStackTrace(); } catch (SocketTimeoutException e) { mTaskEntity.setTaskStatus(EasyTaskStatus.TASK_STATUS_REQUEST_ERROR); mHandler.sendEmptyMessage(EasyTaskStatus.TASK_STATUS_REQUEST_ERROR); e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { EasyIOUtils.close(bufferedInputStream, inputStream, randomAccessFile); } } public void pause() { mTaskEntity.setTaskStatus(EasyTaskStatus.TASK_STATUS_PAUSE); if (EasyDaoManager.instance().queryWithId(mTaskEntity.getTaskId()) == null) { EasyDaoManager.instance().insertOrReplace(mTaskEntity); } else { EasyDaoManager.instance().update(mTaskEntity); } mHandler.sendEmptyMessage(EasyTaskStatus.TASK_STATUS_PAUSE); } public void queue() { mTaskEntity.setTaskStatus(EasyTaskStatus.TASK_STATUS_QUEUE); mHandler.sendEmptyMessage(EasyTaskStatus.TASK_STATUS_QUEUE); } public void cancel() { mTaskEntity.setTaskStatus(EasyTaskStatus.TASK_STATUS_CANCEL); if (EasyDaoManager.instance().queryWithId(mTaskEntity.getTaskId()) != null) { EasyDaoManager.instance().delete(mTaskEntity); } mHandler.sendEmptyMessage(EasyTaskStatus.TASK_STATUS_CANCEL); } }