diff --git a/Aria/src/main/java/com/arialyy/aria/core/ConfigHelper.java b/Aria/src/main/java/com/arialyy/aria/core/ConfigHelper.java index d6cb98ec..f9113622 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/ConfigHelper.java +++ b/Aria/src/main/java/com/arialyy/aria/core/ConfigHelper.java @@ -59,9 +59,6 @@ class ConfigHelper extends DefaultHandler { String value = attributes.getValue("value"); switch (qName) { - case "openDynamicFile": - loadOpenDynamicFile(value); - break; case "threadNum": loadThreadNum(value); break; @@ -117,12 +114,6 @@ class ConfigHelper extends DefaultHandler { } } - private void loadOpenDynamicFile(String value) { - if (isDownloadConfig) { - mDownloadConfig.openDynamicFile = checkBoolean(value) ? Boolean.valueOf(value) : false; - } - } - private void loadNotNetRetry(String value) { if (isDownloadConfig) { mDownloadConfig.notNetRetry = checkBoolean(value) ? Boolean.valueOf(value) : false; diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java b/Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java index bef04a0c..a8af4f7d 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java @@ -44,8 +44,11 @@ import java.util.concurrent.Executors; */ public abstract class AbsFileer> implements Runnable, IUtil { - public static final String STATE = "_state_"; - public static final String RECORD = "_record_"; + private static final String STATE = "_state_"; + private static final String RECORD = "_record_"; + /** + * 小于1m的文件不启用多线程 + */ protected static final long SUB_LEN = 1024 * 1024; private final String TAG = "AbsFileer"; @@ -57,16 +60,14 @@ public abstract class AbsFileer mTask = new SparseArray<>(); - /** - * 小于1m的文件不启用多线程 - */ + private Timer mTimer; @Deprecated private File mConfigFile; @@ -74,7 +75,7 @@ public abstract class AbsFileer(); mRecord.isGroupRecord = mTaskEntity.getEntity().isGroupChild(); - mRecord.isOpenDynamicFile = - AriaManager.getInstance(AriaManager.APP).getDownloadConfig().isOpenDynamicFile(); if (mRecord.isGroupRecord) { if (mTaskEntity.getEntity() instanceof DownloadEntity) { mRecord.dGroupName = ((DownloadEntity) mTaskEntity.getEntity()).getGroupName(); diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/StateConstance.java b/Aria/src/main/java/com/arialyy/aria/core/common/StateConstance.java index 25db8ea6..8aca4910 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/StateConstance.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/StateConstance.java @@ -30,6 +30,11 @@ public class StateConstance { public boolean isCancel = false; public boolean isStop = false; public TaskRecord TASK_RECORD; + /** + * 是否是使用虚拟文件下载的 + * {@code true}是,{@code false}不是 + */ + public boolean isOpenDynamicFile = false; public StateConstance() { } diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/TaskRecord.java b/Aria/src/main/java/com/arialyy/aria/core/common/TaskRecord.java index cc0cc3fd..ea928de3 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/TaskRecord.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/TaskRecord.java @@ -73,10 +73,4 @@ public class TaskRecord extends DbEntity { @Ignore @Deprecated public String uGroupName; - - /** - * 是否是使用虚拟文件下载的 - * {@code true}是,{@code false}不是 - */ - public boolean isOpenDynamicFile = false; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java b/Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java index 3e1be934..56216403 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java @@ -19,8 +19,6 @@ import android.os.Handler; import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.common.TaskRecord; import com.arialyy.aria.core.inf.AbsEntity; -import com.arialyy.aria.core.inf.AbsGroupEntity; -import com.arialyy.aria.core.inf.AbsNormalEntity; import com.arialyy.aria.core.inf.AbsTask; import com.arialyy.aria.core.inf.AbsTaskEntity; import com.arialyy.aria.core.inf.IDownloadListener; @@ -158,14 +156,16 @@ class BaseDListener { } @Override protected int setNewTaskThreadNum() { + int threadNum = AriaManager.getInstance(mContext).getDownloadConfig().getThreadNum(); return // 小于1m的文件或是任务组的子任务、使用虚拟文件,线程数都是1 mEntity.getFileSize() <= SUB_LEN || mTaskEntity.getRequestType() == AbsTaskEntity.D_FTP_DIR || mTaskEntity.getRequestType() == AbsTaskEntity.DG_HTTP - || mRecord.isOpenDynamicFile + || threadNum == 1 ? 1 - : AriaManager.getInstance(mContext).getDownloadConfig().getThreadNum(); + : threadNum; } @Override protected boolean handleNewTask() { CommonUtil.createFile(mTempFile.getPath()); BufferedRandomAccessFile file = null; try { - file = new BufferedRandomAccessFile(new File(mTempFile.getPath()), "rwd", 8192); - //设置文件长度 - file.setLength(mRecord.isOpenDynamicFile ? 1 : mEntity.getFileSize()); + if (mTotalThreadNum > 1) { + file = new BufferedRandomAccessFile(new File(mTempFile.getPath()), "rwd", 8192); + //设置文件长度 + file.setLength(mEntity.getFileSize()); + } return true; } catch (IOException e) { failDownload("下载失败【downloadUrl:" diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpThreadTask.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpThreadTask.java index 125c4422..d0f17778 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpThreadTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpThreadTask.java @@ -24,8 +24,13 @@ import com.arialyy.aria.core.download.DownloadTaskEntity; import com.arialyy.aria.core.inf.IDownloadListener; import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.BufferedRandomAccessFile; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPReply; @@ -36,10 +41,6 @@ import org.apache.commons.net.ftp.FTPReply; class FtpThreadTask extends AbsFtpThreadTask { private final String TAG = "FtpThreadTask"; private boolean isOpenDynamicFile; - /** - * 2M的动态长度 - */ - private final int LEN_INTERVAL = 1024 * 1024 * 2; FtpThreadTask(StateConstance constance, IDownloadListener listener, SubThreadConfig downloadInfo) { @@ -49,7 +50,7 @@ class FtpThreadTask extends AbsFtpThreadTask mReadTimeOut = manager.getDownloadConfig().getIOTimeOut(); mBufSize = manager.getDownloadConfig().getBuffSize(); isNotNetRetry = manager.getDownloadConfig().isNotNetRetry(); - isOpenDynamicFile = STATE.TASK_RECORD.isOpenDynamicFile; + isOpenDynamicFile = STATE.isOpenDynamicFile; setMaxSpeed(manager.getDownloadConfig().getMaxSpeed()); } @@ -58,7 +59,7 @@ class FtpThreadTask extends AbsFtpThreadTask mChildCurrentLocation = mConfig.START_LOCATION; FTPClient client = null; InputStream is = null; - BufferedRandomAccessFile file = null; + try { ALog.d(TAG, "任务【" + mConfig.TEMP_FILE.getName() @@ -94,31 +95,12 @@ class FtpThreadTask extends AbsFtpThreadTask return; } - file = new BufferedRandomAccessFile(mConfig.TEMP_FILE, "rwd", mBufSize); - file.seek(mConfig.START_LOCATION); - byte[] buffer = new byte[mBufSize]; - int len; - - while ((len = is.read(buffer)) != -1) { - if (STATE.isCancel || STATE.isStop) { - break; - } - if (mSleepTime > 0) Thread.sleep(mSleepTime); - if (isOpenDynamicFile) { - file.setLength( - STATE.CURRENT_LOCATION + LEN_INTERVAL < mEntity.getFileSize() ? STATE.CURRENT_LOCATION - + LEN_INTERVAL : mEntity.getFileSize()); - } - if (mChildCurrentLocation + len >= mConfig.END_LOCATION) { - len = (int) (mConfig.END_LOCATION - mChildCurrentLocation); - file.write(buffer, 0, len); - progress(len); - break; - } else { - file.write(buffer, 0, len); - progress(len); - } + if (isOpenDynamicFile) { + readDynamicFile(is); + } else { + readNormal(is); } + if (STATE.isCancel || STATE.isStop) return; ALog.i(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】线程__" + mConfig.THREAD_ID + "__下载完毕"); writeConfig(true, 1); @@ -138,9 +120,6 @@ class FtpThreadTask extends AbsFtpThreadTask fail(mChildCurrentLocation, "获取流失败", e); } finally { try { - if (file != null) { - file.close(); - } if (is != null) { is.close(); } @@ -153,6 +132,92 @@ class FtpThreadTask extends AbsFtpThreadTask } } + /** + * 动态长度文件读取方式 + */ + private void readDynamicFile(InputStream is) { + FileOutputStream fos = null; + FileChannel foc = null; + ReadableByteChannel fic = null; + try { + int len; + fos = new FileOutputStream(mConfig.TEMP_FILE, true); + foc = fos.getChannel(); + fic = Channels.newChannel(is); + ByteBuffer bf = ByteBuffer.allocate(mBufSize); + while ((len = fic.read(bf)) != -1) { + if (STATE.isCancel || STATE.isStop) { + break; + } + if (mSleepTime > 0) { + Thread.sleep(mSleepTime); + } + bf.flip(); + foc.write(bf); + bf.compact(); + progress(len); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (IOException e) { + fail(mChildCurrentLocation, "下载失败【" + mConfig.URL + "】", e); + } finally { + try { + if (fos != null) { + fos.close(); + } + if (foc != null) { + foc.close(); + } + if (fic != null) { + fic.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * 多线程写文件方式 + */ + private void readNormal(InputStream is) { + BufferedRandomAccessFile file = null; + try { + file = new BufferedRandomAccessFile(mConfig.TEMP_FILE, "rwd", mBufSize); + file.seek(mConfig.START_LOCATION); + byte[] buffer = new byte[mBufSize]; + int len; + while ((len = is.read(buffer)) != -1) { + if (STATE.isCancel || STATE.isStop) { + break; + } + if (mSleepTime > 0) Thread.sleep(mSleepTime); + if (mChildCurrentLocation + len >= mConfig.END_LOCATION) { + len = (int) (mConfig.END_LOCATION - mChildCurrentLocation); + file.write(buffer, 0, len); + progress(len); + break; + } else { + file.write(buffer, 0, len); + progress(len); + } + } + } catch (IOException e) { + fail(mChildCurrentLocation, "下载失败【" + mConfig.URL + "】", e); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + try { + if (file != null) { + file.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + @Override protected String getTaskType() { return "FTP_DOWNLOAD"; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java index b3a99db6..74d50cfb 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java @@ -26,11 +26,16 @@ import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.BufferedRandomAccessFile; import com.arialyy.aria.util.CommonUtil; import java.io.BufferedInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.FileChannel; +import java.nio.channels.ReadableByteChannel; /** * Created by lyy on 2017/1/18. @@ -38,10 +43,6 @@ import java.net.URL; */ final class HttpThreadTask extends AbsThreadTask { private final String TAG = "HttpThreadTask"; - /** - * 2M的动态长度 - */ - private final int LEN_INTERVAL = 1024 * 1024 * 2; private boolean isOpenDynamicFile; HttpThreadTask(StateConstance constance, IDownloadListener listener, @@ -52,7 +53,7 @@ final class HttpThreadTask extends AbsThreadTask 0) { + Thread.sleep(mSleepTime); + } + bf.flip(); + foc.write(bf); + bf.compact(); + progress(len); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (IOException e) { + fail(mChildCurrentLocation, "下载失败【" + mConfig.URL + "】", e); + } finally { + try { + if (fos != null) { + fos.close(); + } + if (foc != null) { + foc.close(); + } + if (fic != null) { + fic.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + /** * 读取chunk模式的文件流 * @@ -148,11 +198,6 @@ final class HttpThreadTask extends AbsThreadTask 0) { Thread.sleep(mSleepTime); } - if (isOpenDynamicFile) { - file.setLength( - STATE.CURRENT_LOCATION + LEN_INTERVAL < mEntity.getFileSize() ? STATE.CURRENT_LOCATION - + LEN_INTERVAL : mEntity.getFileSize()); - } file.write(buffer, 0, len); progress(len); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java index c4857df5..13dcad08 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java @@ -311,7 +311,9 @@ abstract class AbsSchedulers - + diff --git a/app/src/main/assets/aria_config.xml b/app/src/main/assets/aria_config.xml index 186611b1..de9e2732 100644 --- a/app/src/main/assets/aria_config.xml +++ b/app/src/main/assets/aria_config.xml @@ -11,17 +11,17 @@ - - - - + diff --git a/app/src/main/java/com/arialyy/simple/test/AnyRunActivity.java b/app/src/main/java/com/arialyy/simple/test/AnyRunActivity.java index 4ef74def..d99c955e 100644 --- a/app/src/main/java/com/arialyy/simple/test/AnyRunActivity.java +++ b/app/src/main/java/com/arialyy/simple/test/AnyRunActivity.java @@ -15,9 +15,9 @@ public class AnyRunActivity extends BaseActivity { AnyRunnModule module; String[] urls; int index = 0; - //String URL = "http://static.gaoshouyou.com/d/12/0d/7f120f50c80d2e7b8c4ba24ece4f9cdd.apk"; + String URL = "http://static.gaoshouyou.com/d/12/0d/7f120f50c80d2e7b8c4ba24ece4f9cdd.apk"; //String URL = "http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk"; - private final String URL = "ftp://192.168.29.140:21/download/AriaPrj.rar"; + //private final String URL = "ftp://192.168.29.140:21/download/AriaPrj.rar"; //String URL = "https://dl.genymotion.com/releases/genymotion-2.12.1/genymotion-2.12.1-vbox.exe"; @Override protected int setLayoutId() { @@ -42,7 +42,8 @@ public class AnyRunActivity extends BaseActivity { //} //for (int i = 0; i < 10; i++) { - module.startFtp(URL); + //module.startFtp(URL); + module.start(URL); //} //List list = Aria.download(this).getTotalTaskList(); //ALog.d(TAG, "size ==> " + list.size()); diff --git a/app/src/main/java/com/arialyy/simple/test/AnyRunnModule.java b/app/src/main/java/com/arialyy/simple/test/AnyRunnModule.java index 7d276022..19dd6b8a 100644 --- a/app/src/main/java/com/arialyy/simple/test/AnyRunnModule.java +++ b/app/src/main/java/com/arialyy/simple/test/AnyRunnModule.java @@ -68,7 +68,7 @@ public class AnyRunnModule { .load(url) //.addHeader("Accept-Encoding", "gzip") .setRequestMode(RequestEnum.GET) - .setFilePath(Environment.getExternalStorageDirectory().getPath() + "/ggsg123456.apk") + .setFilePath(Environment.getExternalStorageDirectory().getPath() + "/ggsg1234567.apk") //.resetState() .start(); //String[] urls = new String[] { diff --git a/aria/src/main/java/com/arialyy/aria/core/Configuration.java b/aria/src/main/java/com/arialyy/aria/core/Configuration.java index 85b71691..51539db5 100644 --- a/aria/src/main/java/com/arialyy/aria/core/Configuration.java +++ b/aria/src/main/java/com/arialyy/aria/core/Configuration.java @@ -366,6 +366,11 @@ class Configuration { String caName; /** * 下载线程数,下载线程数不能小于1 + * 注意: + * 1、线程下载数改变后,新的下载任务才会生效; + * 2、如果任务大小小于1m,该设置不会生效; + * 3、从3.4.1开始,如果线程数为1,文件初始化时将不再预占用对应长度的空间,下载多少byte,则占多大的空间; + * 对于采用多线程的任务或旧任务,依然采用原来的文件空间占用方式; */ int threadNum = 3; @@ -374,26 +379,6 @@ class Configuration { */ int maxSpeed = 0; - /** - * 是否开启动态文件,开启动态文件后初始化时将不占用磁盘空间,下载多少byte,占多少空间,效果见chrome的下载 - * 注意: - * 1、使用该功能,将自动关闭多线程下载; - * 2、对于已经采用了多线程的任务,依然采用原来的下载方式; - * 3、原本参数是true,任务没下载完成,就参数改为false,那么没下载完成的任务还是会按照参数修改前的方式下载,只有新任务才会根据参数调用不同的下载方式 - * {@code true}使用 - */ - boolean openDynamicFile = true; - - public DownloadConfig setOpenDynamicFile(boolean openDynamicFile) { - this.openDynamicFile = openDynamicFile; - saveKey("openDynamicFile", String.valueOf(openDynamicFile)); - return this; - } - - public boolean isOpenDynamicFile() { - return openDynamicFile; - } - public DownloadConfig setMaxTaskNum(int maxTaskNum) { oldMaxTaskNum = this.maxTaskNum; this.maxTaskNum = maxTaskNum;