diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadStateConstance.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadStateConstance.java index 7d33b597..e8b69bad 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadStateConstance.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadStateConstance.java @@ -20,20 +20,19 @@ package com.arialyy.aria.core.download; * 下载状态常量 */ final class DownloadStateConstance { - int CANCEL_NUM = 0; - int STOP_NUM = 0; - int FAIL_NUM = 0; - int CONNECT_TIME_OUT = 5000 * 4; //连接超时时间 - int READ_TIME_OUT = 1000 * 20; //流读取的超时时间 - int COMPLETE_THREAD_NUM = 0; - int THREAD_NUM = 3; - long CURRENT_LOCATION = 0; - boolean isDownloading = false; - boolean isCancel = false; - boolean isStop = false; + int CANCEL_NUM = 0; + int STOP_NUM = 0; + int FAIL_NUM = 0; + int CONNECT_TIME_OUT = 5000 * 4; //连接超时时间 + int READ_TIME_OUT = 1000 * 20; //流读取的超时时间 + int COMPLETE_THREAD_NUM = 0; + int THREAD_NUM = 3; + long CURRENT_LOCATION = 0; + boolean isDownloading = false; + boolean isCancel = false; + boolean isStop = false; - DownloadStateConstance(int num) { - THREAD_NUM = num; + DownloadStateConstance() { } void cleanState() { @@ -46,7 +45,7 @@ final class DownloadStateConstance { FAIL_NUM = 0; } - void setThreadNum(int threadNum){ + void setThreadNum(int threadNum) { THREAD_NUM = threadNum; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadUtil.java index 38d76f38..6e67efb8 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadUtil.java @@ -39,20 +39,23 @@ final class DownloadUtil implements IDownloadUtil, Runnable { /** * 线程数 */ - private final int THREAD_NUM; - private static final long SUB_LEN = 1024 * 100; + private int THREAD_NUM; + /** + * 小于1m的文件不启用多线程 + */ + private static final long SUB_LEN = 1024 * 1024; //下载监听 private IDownloadListener mListener; - private int mConnectTimeOut = 5000 * 4; //连接超时时间 - private int mReadTimeOut = 5000 * 20; //流读取的超时时间 - private boolean isNewTask = true; + private int mConnectTimeOut = 5000 * 4; //连接超时时间 + private int mReadTimeOut = 5000 * 20; //流读取的超时时间 + private boolean isNewTask = true; private boolean isSupportBreakpoint = true; - private Context mContext; - private DownloadEntity mDownloadEntity; + private Context mContext; + private DownloadEntity mDownloadEntity; private DownloadTaskEntity mDownloadTaskEntity; - private ExecutorService mFixedThreadPool; - private File mDownloadFile; //下载的文件 - private File mConfigFile;//下载信息配置文件 + private ExecutorService mFixedThreadPool; + private File mDownloadFile; //下载的文件 + private File mConfigFile;//下载信息配置文件 private SparseArray mTask = new SparseArray<>(); private DownloadStateConstance mConstance; @@ -69,7 +72,7 @@ final class DownloadUtil implements IDownloadUtil, Runnable { mListener = downloadListener; THREAD_NUM = threadNum; mFixedThreadPool = Executors.newFixedThreadPool(Integer.MAX_VALUE); - mConstance = new DownloadStateConstance(THREAD_NUM); + mConstance = new DownloadStateConstance(); init(); } @@ -246,51 +249,17 @@ final class DownloadUtil implements IDownloadUtil, Runnable { * 处理断点 */ private void handleBreakpoint(HttpURLConnection conn) throws IOException { - //不支持断点只能单线程下载 if (!isSupportBreakpoint) { - ConfigEntity entity = new ConfigEntity(); - long len = conn.getContentLength(); - entity.FILE_SIZE = len; - entity.DOWNLOAD_URL = mDownloadEntity.getDownloadUrl(); - entity.TEMP_FILE = mDownloadFile; - entity.THREAD_ID = 0; - entity.START_LOCATION = 0; - entity.END_LOCATION = entity.FILE_SIZE; - entity.CONFIG_FILE_PATH = mConfigFile.getPath(); - entity.isSupportBreakpoint = isSupportBreakpoint; - entity.DOWNLOAD_TASK_ENTITY = mDownloadTaskEntity; - SingleThreadTask task = new SingleThreadTask(mConstance, mListener, entity); - mFixedThreadPool.execute(task); - mListener.onPostPre(len); - mListener.onStart(0); + handleNoSupportBreakpointDownload(conn); return; } int fileLength = conn.getContentLength(); - //必须建一个文件 - CommonUtil.createFile(mDownloadFile.getPath()); - BufferedRandomAccessFile file = - new BufferedRandomAccessFile(new File(mDownloadFile.getPath()), "rwd", 8192); - //设置文件长度 - file.setLength(fileLength); - mListener.onPostPre(fileLength); - //分配每条线程的下载区间 - Properties pro = null; - pro = CommonUtil.loadConfig(mConfigFile); - if (pro.isEmpty()) { - isNewTask = true; - } else { - for (int i = 0; i < THREAD_NUM; i++) { - if (pro.getProperty(mDownloadFile.getName() + "_record_" + i) == null) { - Object state = pro.getProperty(mDownloadFile.getName() + "_state_" + i); - if (state != null && Integer.parseInt(state + "") == 1) { - continue; - } - isNewTask = true; - break; - } - } + if (fileLength < SUB_LEN) { + THREAD_NUM = 1; + mConstance.THREAD_NUM = THREAD_NUM; } + Properties pro = createConfigFile(fileLength); int blockSize = fileLength / THREAD_NUM; int[] recordL = new int[THREAD_NUM]; int rl = 0; @@ -301,19 +270,7 @@ final class DownloadUtil implements IDownloadUtil, Runnable { long startL = i * blockSize, endL = (i + 1) * blockSize; Object state = pro.getProperty(mDownloadFile.getName() + "_state_" + i); if (state != null && Integer.parseInt(state + "") == 1) { //该线程已经完成 - mConstance.CURRENT_LOCATION += endL - startL; - Log.d(TAG, "++++++++++ 线程_" + i + "_已经下载完成 ++++++++++"); - mConstance.COMPLETE_THREAD_NUM++; - mConstance.STOP_NUM++; - mConstance.CANCEL_NUM++; - if (mConstance.isComplete()) { - if (mConfigFile.exists()) { - mConfigFile.delete(); - } - mListener.onComplete(); - mConstance.isDownloading = false; - return; - } + if (resumeRecordLocation(i, startL, endL)) return; continue; } //分配下载位置 @@ -338,19 +295,107 @@ final class DownloadUtil implements IDownloadUtil, Runnable { //如果整个文件的大小不为线程个数的整数倍,则最后一个线程的结束位置即为文件的总长度 endL = fileLength; } - ConfigEntity entity = new ConfigEntity(); - entity.FILE_SIZE = fileLength; - entity.DOWNLOAD_URL = mDownloadEntity.getDownloadUrl(); - entity.TEMP_FILE = mDownloadFile; - entity.THREAD_ID = i; - entity.START_LOCATION = startL; - entity.END_LOCATION = endL; - entity.CONFIG_FILE_PATH = mConfigFile.getPath(); - entity.isSupportBreakpoint = isSupportBreakpoint; - entity.DOWNLOAD_TASK_ENTITY = mDownloadTaskEntity; - SingleThreadTask task = new SingleThreadTask(mConstance, mListener, entity); - mTask.put(i, task); + addSingleTask(i, startL, endL, fileLength); } + startSingleTask(recordL); + } + + /** + * 处理不支持断点的下载 + */ + private void handleNoSupportBreakpointDownload(HttpURLConnection conn){ + ConfigEntity entity = new ConfigEntity(); + long len = conn.getContentLength(); + entity.FILE_SIZE = len; + entity.DOWNLOAD_URL = mDownloadEntity.getDownloadUrl(); + entity.TEMP_FILE = mDownloadFile; + entity.THREAD_ID = 0; + entity.START_LOCATION = 0; + entity.END_LOCATION = entity.FILE_SIZE; + entity.CONFIG_FILE_PATH = mConfigFile.getPath(); + entity.isSupportBreakpoint = isSupportBreakpoint; + entity.DOWNLOAD_TASK_ENTITY = mDownloadTaskEntity; + SingleThreadTask task = new SingleThreadTask(mConstance, mListener, entity); + mFixedThreadPool.execute(task); + mListener.onPostPre(len); + mListener.onStart(0); + } + + /** + * 创建配置文件 + */ + private Properties createConfigFile(long fileLength) throws IOException { + Properties pro = null; + //必须建一个文件 + CommonUtil.createFile(mDownloadFile.getPath()); + BufferedRandomAccessFile file = + new BufferedRandomAccessFile(new File(mDownloadFile.getPath()), "rwd", 8192); + //设置文件长度 + file.setLength(fileLength); + mListener.onPostPre(fileLength); + //分配每条线程的下载区间 + pro = CommonUtil.loadConfig(mConfigFile); + if (pro.isEmpty()) { + isNewTask = true; + } else { + for (int i = 0; i < THREAD_NUM; i++) { + if (pro.getProperty(mDownloadFile.getName() + "_record_" + i) == null) { + Object state = pro.getProperty(mDownloadFile.getName() + "_state_" + i); + if (state != null && Integer.parseInt(state + "") == 1) { + continue; + } + isNewTask = true; + break; + } + } + } + return pro; + } + + /** + * 恢复记录地址 + * + * @return true 表示下载完成 + */ + private boolean resumeRecordLocation(int i, long startL, long endL) { + mConstance.CURRENT_LOCATION += endL - startL; + Log.d(TAG, "++++++++++ 线程_" + i + "_已经下载完成 ++++++++++"); + mConstance.COMPLETE_THREAD_NUM++; + mConstance.STOP_NUM++; + mConstance.CANCEL_NUM++; + if (mConstance.isComplete()) { + if (mConfigFile.exists()) { + mConfigFile.delete(); + } + mListener.onComplete(); + mConstance.isDownloading = false; + return true; + } + return false; + } + + /** + * 创建单线程任务 + */ + private void addSingleTask(int i, long startL, long endL, long fileLength) { + ConfigEntity entity = new ConfigEntity(); + entity.FILE_SIZE = fileLength; + entity.DOWNLOAD_URL = mDownloadEntity.getDownloadUrl(); + entity.TEMP_FILE = mDownloadFile; + entity.THREAD_ID = i; + entity.START_LOCATION = startL; + entity.END_LOCATION = endL; + entity.CONFIG_FILE_PATH = mConfigFile.getPath(); + entity.isSupportBreakpoint = isSupportBreakpoint; + entity.DOWNLOAD_TASK_ENTITY = mDownloadTaskEntity; + SingleThreadTask task = new SingleThreadTask(mConstance, mListener, entity); + mTask.put(i, task); + } + + /** + * 启动单线程下载任务 + */ + private void startSingleTask(int[] recordL) { if (mConstance.CURRENT_LOCATION > 0) { mListener.onResume(mConstance.CURRENT_LOCATION); } else { @@ -370,14 +415,14 @@ final class DownloadUtil implements IDownloadUtil, Runnable { */ final static class ConfigEntity { //文件大小 - long FILE_SIZE; - String DOWNLOAD_URL; - int THREAD_ID; - long START_LOCATION; - long END_LOCATION; - File TEMP_FILE; - boolean isSupportBreakpoint = true; - String CONFIG_FILE_PATH; + int THREAD_ID; + long FILE_SIZE; + long START_LOCATION; + long END_LOCATION; + File TEMP_FILE; + String DOWNLOAD_URL; + String CONFIG_FILE_PATH; DownloadTaskEntity DOWNLOAD_TASK_ENTITY; + boolean isSupportBreakpoint = true; } } \ No newline at end of file