From b987c3fcfac2886fc44e8c664d4b3419b2124d5d Mon Sep 17 00:00:00 2001 From: AriaLyy <511455842@qq.com> Date: Mon, 24 Jul 2017 21:26:45 +0800 Subject: [PATCH] =?UTF-8?q?ftp=20=E5=8D=95=E7=BA=BF=E7=A8=8B=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/download/DownloadTaskEntity.java | 2 +- .../aria/core/download/FtpDownloadTarget.java | 25 +- .../downloader/ChildThreadConfigEntity.java | 24 ++ .../downloader/{http => }/StateConstance.java | 38 +- .../downloader/ftp/FtpConfigEntity.java | 38 -- .../downloader/ftp/FtpThreadTask.java | 377 +++++++++++++----- .../http/ChildThreadConfigEntity.java | 24 -- .../download/downloader/http/Downloader.java | 12 +- ...gleThreadTask.java => HttpThreadTask.java} | 68 ++-- .../com/arialyy/aria/util/CommonUtil.java | 22 +- 10 files changed, 397 insertions(+), 233 deletions(-) create mode 100644 Aria/src/main/java/com/arialyy/aria/core/download/downloader/ChildThreadConfigEntity.java rename Aria/src/main/java/com/arialyy/aria/core/download/downloader/{http => }/StateConstance.java (65%) delete mode 100644 Aria/src/main/java/com/arialyy/aria/core/download/downloader/ftp/FtpConfigEntity.java delete mode 100644 Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/ChildThreadConfigEntity.java rename Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/{SingleThreadTask.java => HttpThreadTask.java} (84%) diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java index 0e63cf9c..ba7001fc 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java @@ -28,7 +28,7 @@ public class DownloadTaskEntity extends AbsTaskEntity { /** * 账号和密码 */ - @Ignore public String userName, userPw; + @Ignore public String userName, userPw, account; /** * 下载类型 diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java index 33b1dc0f..52b46fca 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java @@ -18,6 +18,7 @@ package com.arialyy.aria.core.download; import android.text.TextUtils; import android.util.Log; import com.arialyy.aria.core.inf.AbsTaskEntity; +import com.arialyy.aria.util.CommonUtil; /** * Created by lyy on 2016/12/5. @@ -39,8 +40,10 @@ public class FtpDownloadTarget extends DownloadTarget { */ private FtpDownloadTarget(String url, String targetName) { super(url, targetName); + int lastIndex = url.lastIndexOf("/"); mTaskEntity.downloadType = AbsTaskEntity.FTP; mTargetName = targetName; + mEntity.setFileName(url.substring(lastIndex + 1, url.length())); } /** @@ -50,6 +53,17 @@ public class FtpDownloadTarget extends DownloadTarget { * @param password ftp用户密码 */ public FtpDownloadTarget login(String userName, String password) { + return login(userName, password, null); + } + + /** + * ftp 用户登录信息 + * + * @param userName ftp用户名 + * @param password ftp用户密码 + * @param account ftp账号 + */ + public FtpDownloadTarget login(String userName, String password, String account) { if (TextUtils.isEmpty(userName)) { Log.e(TAG, "用户名不能为null"); return this; @@ -59,16 +73,7 @@ public class FtpDownloadTarget extends DownloadTarget { } mTaskEntity.userName = userName; mTaskEntity.userPw = password; - return this; - } - - /** - * 设置下载的文件 - * - * @param filePath ftp服务器上的文件 - */ - public FtpDownloadTarget getFile(String filePath) { - + mTaskEntity.account = account; return this; } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/ChildThreadConfigEntity.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/ChildThreadConfigEntity.java new file mode 100644 index 00000000..2563205b --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/ChildThreadConfigEntity.java @@ -0,0 +1,24 @@ +package com.arialyy.aria.core.download.downloader; + +import com.arialyy.aria.core.download.DownloadTaskEntity; +import java.io.File; + +/** + * 子线程下载信息类 + */ +public class ChildThreadConfigEntity { + //线程Id + public int THREAD_ID; + //下载文件大小 + public long FILE_SIZE; + //子线程启动下载位置 + public long START_LOCATION; + //子线程结束下载位置 + public long END_LOCATION; + //下载路径 + public File TEMP_FILE; + public String DOWNLOAD_URL; + public String CONFIG_FILE_PATH; + public DownloadTaskEntity DOWNLOAD_TASK_ENTITY; + public boolean IS_SUPPORT_BREAK_POINT = true; +} \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/StateConstance.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/StateConstance.java similarity index 65% rename from Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/StateConstance.java rename to Aria/src/main/java/com/arialyy/aria/core/download/downloader/StateConstance.java index a937a725..7161d995 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/StateConstance.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/StateConstance.java @@ -13,29 +13,29 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.arialyy.aria.core.download.downloader.http; +package com.arialyy.aria.core.download.downloader; /** * Created by lyy on 2017/1/18. * 下载状态常量 */ -final class StateConstance { - int CANCEL_NUM = 0; - int STOP_NUM = 0; - int FAIL_NUM = 0; - int CONNECT_TIME_OUT; //连接超时时间 - int READ_TIME_OUT; //流读取的超时时间 - int COMPLETE_THREAD_NUM = 0; - int THREAD_NUM; - long CURRENT_LOCATION = 0; - boolean isDownloading = false; - boolean isCancel = false; - boolean isStop = false; +public class StateConstance { + public int CANCEL_NUM = 0; + public int STOP_NUM = 0; + public int FAIL_NUM = 0; + public int CONNECT_TIME_OUT; //连接超时时间 + public int READ_TIME_OUT; //流读取的超时时间 + public int COMPLETE_THREAD_NUM = 0; + public int THREAD_NUM; + public long CURRENT_LOCATION = 0; + public boolean isDownloading = false; + public boolean isCancel = false; + public boolean isStop = false; - StateConstance() { + public StateConstance() { } - void cleanState() { + public void cleanState() { isCancel = false; isStop = false; isDownloading = true; @@ -48,28 +48,28 @@ final class StateConstance { /** * 所有子线程是否都已经停止下载 */ - boolean isStop() { + public boolean isStop() { return STOP_NUM == THREAD_NUM; } /** * 所有子线程是否都已经下载失败 */ - boolean isFail() { + public boolean isFail() { return FAIL_NUM == THREAD_NUM; } /** * 所有子线程是否都已经完成下载 */ - boolean isComplete() { + public boolean isComplete() { return COMPLETE_THREAD_NUM == THREAD_NUM; } /** * 所有子线程是否都已经取消下载 */ - boolean isCancel() { + public boolean isCancel() { return CANCEL_NUM == THREAD_NUM; } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/ftp/FtpConfigEntity.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/ftp/FtpConfigEntity.java deleted file mode 100644 index 36bcdcf9..00000000 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/ftp/FtpConfigEntity.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.arialyy.aria.core.download.downloader.ftp; - -import com.arialyy.aria.core.download.DownloadTaskEntity; - -/** - * Created by Aria.Lao on 2017/7/24. - * ftp下载信息实体 - */ -class FtpConfigEntity { - //下载文件大小 - long FILE_SIZE; - //子线程启动下载位置 - long START_LOCATION; - //下载路径 - String PATH; - DownloadTaskEntity TASK_ENTITY; - //FTP 服务器地址 - String SERVER_IP; - //FTP 服务器端口 - String PORT; - //FTP服务器地址 - String SERVER_FILE_PATH; -} diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/ftp/FtpThreadTask.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/ftp/FtpThreadTask.java index 176ba7fa..600cefab 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/ftp/FtpThreadTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/ftp/FtpThreadTask.java @@ -1,96 +1,281 @@ -///* -// * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) -// * -// * Licensed under the Apache License, Version 2.0 (the "License"); -// * you may not use this file except in compliance with the License. -// * You may obtain a copy of the License at -// * -// * http://www.apache.org/licenses/LICENSE-2.0 -// * -// * Unless required by applicable law or agreed to in writing, software -// * distributed under the License is distributed on an "AS IS" BASIS, -// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// * See the License for the specific language governing permissions and -// * limitations under the License. -// */ -//package com.arialyy.aria.core.download.downloader.ftp; -// -//import com.arialyy.aria.core.AriaManager; -//import com.arialyy.aria.core.download.DownloadTaskEntity; -//import com.arialyy.aria.core.download.downloader.IDownloadListener; -//import com.arialyy.aria.util.BufferedRandomAccessFile; -//import java.io.File; -//import java.io.IOException; -//import java.io.InputStream; -//import java.math.BigDecimal; -//import org.apache.commons.net.ftp.FTP; -//import org.apache.commons.net.ftp.FTPClient; -//import org.apache.commons.net.ftp.FTPFile; -//import org.apache.commons.net.ftp.FTPReply; -// -///** -// * Created by Aria.Lao on 2017/7/24. -// * Ftp下载任务 -// */ -//class FtpThreadTask implements Runnable { -// -// private FtpConfigEntity mConfig; -// private IDownloadListener mListener; -// private DownloadTaskEntity mTaskEntity; -// private int mBufSize; -// private long mSleepTime = 0; -// -// FtpThreadTask(FtpConfigEntity config, IDownloadListener listener) { -// AriaManager manager = AriaManager.getInstance(AriaManager.APP); -// mConfig = config; -// mListener = listener; -// -// mBufSize = manager.getDownloadConfig().getBuffSize(); -// setMaxSpeed(AriaManager.getInstance(AriaManager.APP).getDownloadConfig().getMsxSpeed()); -// } -// -// void setMaxSpeed(double maxSpeed) { -// if (-0.9999 < maxSpeed && maxSpeed < 0.00001) { -// mSleepTime = 0; -// } else { -// BigDecimal db = new BigDecimal(((mBufSize / 1024) / maxSpeed) * 1000); -// mSleepTime = db.setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); -// } -// } -// -// @Override public void run() { -// try { -// -// FTPClient client = new FTPClient(); -// //ip和端口 -// //String[] temp = mEntity.getDownloadUrl().split("/"); -// //String[] pp = temp[2].split(":"); -// String dir = temp[temp.length - 2]; -// String fileName = temp[temp.length - 1]; -// client.connect(pp[0], Integer.parseInt(pp[1])); -// client.login(mTaskEntity.userName, mTaskEntity.userPw); -// int reply = client.getReplyCode(); -// if (!FTPReply.isPositiveCompletion(reply)) { -// client.disconnect(); -// //failDownload("无法连接到ftp服务器,错误码为:" + reply); -// return; -// } -// client.enterLocalPassiveMode(); -// client.setFileType(FTP.BINARY_FILE_TYPE); -// FTPFile[] files = client.listFiles(fileName); -// files[0].getSize(); -// BufferedRandomAccessFile file = -// new BufferedRandomAccessFile(new File(mConfig.PATH), "rwd", 8192); -// InputStream is = client.retrieveFileStream(fileName); -// -// byte[] buffer = new byte[8192]; -// int len; -// //当前子线程的下载位置 -// while ((len = is.read(buffer)) != -1) { -// file.write(buffer, 0, len); -// } -// }catch (IOException e){ -// -// } -// } -//} +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.download.downloader.ftp; + +import android.os.Build; +import android.text.TextUtils; +import android.util.Log; +import com.arialyy.aria.core.AriaManager; +import com.arialyy.aria.core.download.DownloadEntity; +import com.arialyy.aria.core.download.DownloadTaskEntity; +import com.arialyy.aria.core.download.downloader.ChildThreadConfigEntity; +import com.arialyy.aria.core.download.downloader.IDownloadListener; +import com.arialyy.aria.core.download.downloader.StateConstance; +import com.arialyy.aria.util.BufferedRandomAccessFile; +import com.arialyy.aria.util.CommonUtil; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; +import java.util.Properties; +import org.apache.commons.net.ftp.FTP; +import org.apache.commons.net.ftp.FTPClient; +import org.apache.commons.net.ftp.FTPFile; +import org.apache.commons.net.ftp.FTPReply; + +/** + * Created by Aria.Lao on 2017/7/24. + * Ftp下载任务 + */ +class FtpThreadTask implements Runnable { + private final String TAG = "FtpThreadTask"; + private ChildThreadConfigEntity mConfig; + private String mConfigFPath; + private long mChildCurrentLocation = 0; + private int mBufSize; + private IDownloadListener mListener; + private StateConstance STATE; + private long mSleepTime = 0; + private DownloadTaskEntity mTaskEntity; + private DownloadEntity mEntity; + + FtpThreadTask(StateConstance constance, IDownloadListener listener, + ChildThreadConfigEntity downloadInfo) { + AriaManager manager = AriaManager.getInstance(AriaManager.APP); + STATE = constance; + STATE.CONNECT_TIME_OUT = manager.getDownloadConfig().getConnectTimeOut(); + STATE.READ_TIME_OUT = manager.getDownloadConfig().getIOTimeOut(); + mListener = listener; + this.mConfig = downloadInfo; + mConfigFPath = downloadInfo.CONFIG_FILE_PATH; + mTaskEntity = mConfig.DOWNLOAD_TASK_ENTITY; + mEntity = mTaskEntity.getEntity(); + mBufSize = manager.getDownloadConfig().getBuffSize(); + setMaxSpeed(AriaManager.getInstance(AriaManager.APP).getDownloadConfig().getMsxSpeed()); + } + + void setMaxSpeed(double maxSpeed) { + if (-0.9999 < maxSpeed && maxSpeed < 0.00001) { + mSleepTime = 0; + } else { + BigDecimal db = new BigDecimal( + ((mBufSize / 1024) * (filterVersion() ? 1 : STATE.THREAD_NUM) / maxSpeed) * 1000); + mSleepTime = db.setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); + } + } + + private boolean filterVersion() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; + } + + @Override public void run() { + FTPClient client = null; + InputStream is = null; + BufferedRandomAccessFile file = null; + try { + Log.d(TAG, "任务【" + + mConfig.TEMP_FILE.getName() + + "】线程__" + + mConfig.THREAD_ID + + "__开始下载【开始位置 : " + + mConfig.START_LOCATION + + ",结束位置:" + + mConfig.END_LOCATION + + "】"); + client = new FTPClient(); + //ip和端口 + String[] temp = mEntity.getDownloadUrl().split("/"); + String[] pp = temp[2].split(":"); + String dir = temp[temp.length - 2]; + String fileName = temp[temp.length - 1]; + client.connect(pp[0], Integer.parseInt(pp[1])); + if (!TextUtils.isEmpty(mTaskEntity.account)) { + client.login(mTaskEntity.userName, mTaskEntity.userPw); + } else { + client.login(mTaskEntity.userName, mTaskEntity.userPw, mTaskEntity.account); + } + int reply = client.getReplyCode(); + if (!FTPReply.isPositiveCompletion(reply)) { + client.disconnect(); + failDownload(STATE.CURRENT_LOCATION, "无法连接到ftp服务器,错误码为:" + reply, null); + return; + } + client.enterLocalPassiveMode(); + client.setFileType(FTP.BINARY_FILE_TYPE); + FTPFile[] files = client.listFiles(fileName); + files[0].getSize(); + client.setRestartOffset(mConfig.START_LOCATION); + is = client.retrieveFileStream(fileName); + //创建可设置位置的文件 + file = new BufferedRandomAccessFile(mConfig.TEMP_FILE, "rwd", mBufSize); + //设置每条线程写入文件的位置 + file.seek(mConfig.START_LOCATION); + byte[] buffer = new byte[mBufSize]; + int len; + //当前子线程的下载位置 + mChildCurrentLocation = mConfig.START_LOCATION; + while ((len = is.read(buffer)) != -1) { + if (STATE.isCancel) break; + if (STATE.isStop) break; + if (mSleepTime > 0) Thread.sleep(mSleepTime); + file.write(buffer, 0, len); + progress(len); + } + if (STATE.isCancel) return; + //停止状态不需要删除记录文件 + if (STATE.isStop) return; + //支持断点的处理 + if (mConfig.IS_SUPPORT_BREAK_POINT) { + Log.i(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】线程__" + mConfig.THREAD_ID + "__下载完毕"); + writeConfig(true, 1); + STATE.COMPLETE_THREAD_NUM++; + if (STATE.isComplete()) { + File configFile = new File(mConfigFPath); + if (configFile.exists()) { + configFile.delete(); + } + STATE.isDownloading = false; + mListener.onComplete(); + } + } else { + Log.i(TAG, "下载任务完成"); + STATE.isDownloading = false; + mListener.onComplete(); + } + } catch (IOException e) { + failDownload(mChildCurrentLocation, "下载失败【" + mConfig.DOWNLOAD_URL + "】", e); + } catch (Exception e) { + failDownload(mChildCurrentLocation, "获取流失败", e); + } finally { + try { + if (file != null) { + file.close(); + } + if (is != null) { + is.close(); + } + if (client != null) { + client.logout(); + client.disconnect(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * 停止下载 + */ + protected void stop() { + synchronized (AriaManager.LOCK) { + try { + STATE.STOP_NUM++; + Log.d(TAG, "任务【" + + mConfig.TEMP_FILE.getName() + + "】thread__" + + mConfig.THREAD_ID + + "__停止, stop location ==> " + + mChildCurrentLocation); + writeConfig(false, mChildCurrentLocation); + if (STATE.isStop()) { + Log.d(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】已停止"); + STATE.isDownloading = false; + mListener.onStop(STATE.CURRENT_LOCATION); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * 下载中 + */ + private void progress(long len) { + synchronized (AriaManager.LOCK) { + mChildCurrentLocation += len; + STATE.CURRENT_LOCATION += len; + } + } + + /** + * 取消下载 + */ + protected void cancel() { + synchronized (AriaManager.LOCK) { + STATE.CANCEL_NUM++; + Log.d(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】thread__" + mConfig.THREAD_ID + "__取消下载"); + if (STATE.isCancel()) { + File configFile = new File(mConfigFPath); + if (configFile.exists()) { + configFile.delete(); + } + if (mConfig.TEMP_FILE.exists()) { + mConfig.TEMP_FILE.delete(); + } + Log.d(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】已取消"); + STATE.isDownloading = false; + mListener.onCancel(); + } + } + } + + /** + * 下载失败 + */ + private void failDownload(long currentLocation, String msg, Exception ex) { + synchronized (AriaManager.LOCK) { + try { + STATE.FAIL_NUM++; + STATE.isDownloading = false; + STATE.isStop = true; + if (ex != null) { + Log.e(TAG, msg + "\n" + CommonUtil.getPrintException(ex)); + } + writeConfig(false, currentLocation); + if (STATE.isFail()) { + Log.e(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】下载失败"); + mListener.onFail(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * 将记录写入到配置文件 + */ + private void writeConfig(boolean isComplete, long record) throws IOException { + synchronized (AriaManager.LOCK) { + String key = null, value = null; + if (0 < record && record < mConfig.END_LOCATION) { + key = mConfig.TEMP_FILE.getName() + "_record_" + mConfig.THREAD_ID; + value = String.valueOf(record); + } else if (record >= mConfig.END_LOCATION || isComplete) { + key = mConfig.TEMP_FILE.getName() + "_state_" + mConfig.THREAD_ID; + value = "1"; + } + if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) { + File configFile = new File(mConfigFPath); + Properties pro = CommonUtil.loadConfig(configFile); + pro.setProperty(key, value); + CommonUtil.saveConfig(configFile, pro); + } + } + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/ChildThreadConfigEntity.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/ChildThreadConfigEntity.java deleted file mode 100644 index b6145d8e..00000000 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/ChildThreadConfigEntity.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.arialyy.aria.core.download.downloader.http; - -import com.arialyy.aria.core.download.DownloadTaskEntity; -import java.io.File; - -/** - * 子线程下载信息类 - */ -final class ChildThreadConfigEntity { - //线程Id - 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 IS_SUPPORT_BREAK_POINT = true; -} \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/Downloader.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/Downloader.java index 8126d989..a41cecba 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/Downloader.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/Downloader.java @@ -21,8 +21,10 @@ import android.util.SparseArray; import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadTaskEntity; +import com.arialyy.aria.core.download.downloader.ChildThreadConfigEntity; import com.arialyy.aria.core.download.downloader.IDownloadListener; import com.arialyy.aria.core.download.downloader.IDownloadUtil; +import com.arialyy.aria.core.download.downloader.StateConstance; import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.util.BufferedRandomAccessFile; import com.arialyy.aria.util.CommonUtil; @@ -70,7 +72,7 @@ class Downloader implements Runnable, IDownloadUtil { @Override public void setMaxSpeed(double maxSpeed) { for (int i = 0; i < mThreadNum; i++) { - SingleThreadTask task = (SingleThreadTask) mTask.get(i); + HttpThreadTask task = (HttpThreadTask) mTask.get(i); if (task != null) { task.setMaxSpeed(maxSpeed); } @@ -153,7 +155,7 @@ class Downloader implements Runnable, IDownloadUtil { mFixedThreadPool.shutdown(); } for (int i = 0; i < mThreadNum; i++) { - SingleThreadTask task = (SingleThreadTask) mTask.get(i); + HttpThreadTask task = (HttpThreadTask) mTask.get(i); if (task != null) { task.cancel(); } @@ -170,7 +172,7 @@ class Downloader implements Runnable, IDownloadUtil { mFixedThreadPool.shutdown(); } for (int i = 0; i < mThreadNum; i++) { - SingleThreadTask task = (SingleThreadTask) mTask.get(i); + HttpThreadTask task = (HttpThreadTask) mTask.get(i); if (task != null) { task.stop(); } @@ -294,7 +296,7 @@ class Downloader implements Runnable, IDownloadUtil { entity.CONFIG_FILE_PATH = mConfigFile.getPath(); entity.IS_SUPPORT_BREAK_POINT = mTaskEntity.isSupportBP; entity.DOWNLOAD_TASK_ENTITY = mTaskEntity; - SingleThreadTask task = new SingleThreadTask(mConstance, mListener, entity); + HttpThreadTask task = new HttpThreadTask(mConstance, mListener, entity); mTask.put(i, task); } @@ -406,7 +408,7 @@ class Downloader implements Runnable, IDownloadUtil { entity.CONFIG_FILE_PATH = mConfigFile.getPath(); entity.IS_SUPPORT_BREAK_POINT = mTaskEntity.isSupportBP; entity.DOWNLOAD_TASK_ENTITY = mTaskEntity; - SingleThreadTask task = new SingleThreadTask(mConstance, mListener, entity); + HttpThreadTask task = new HttpThreadTask(mConstance, mListener, entity); mTask.put(0, task); mFixedThreadPool.execute(task); mListener.onPostPre(len); diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/SingleThreadTask.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/HttpThreadTask.java similarity index 84% rename from Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/SingleThreadTask.java rename to Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/HttpThreadTask.java index 5d44e97c..07f006d1 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/SingleThreadTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/HttpThreadTask.java @@ -19,7 +19,9 @@ import android.os.Build; import android.text.TextUtils; import android.util.Log; import com.arialyy.aria.core.AriaManager; +import com.arialyy.aria.core.download.downloader.ChildThreadConfigEntity; import com.arialyy.aria.core.download.downloader.IDownloadListener; +import com.arialyy.aria.core.download.downloader.StateConstance; import com.arialyy.aria.util.BufferedRandomAccessFile; import com.arialyy.aria.util.CommonUtil; import java.io.File; @@ -35,22 +37,22 @@ import java.util.Properties; * Created by lyy on 2017/1/18. * 下载线程 */ -final class SingleThreadTask implements Runnable { - private static final String TAG = "SingleThreadTask"; +final class HttpThreadTask implements Runnable { + private static final String TAG = "HttpThreadTask"; private ChildThreadConfigEntity mConfigEntity; private String mConfigFPath; private long mChildCurrentLocation = 0; private int mBufSize; private IDownloadListener mListener; - private StateConstance CONSTANCE; + private StateConstance STATE; private long mSleepTime = 0; - SingleThreadTask(StateConstance constance, IDownloadListener listener, + HttpThreadTask(StateConstance constance, IDownloadListener listener, ChildThreadConfigEntity downloadInfo) { AriaManager manager = AriaManager.getInstance(AriaManager.APP); - CONSTANCE = constance; - CONSTANCE.CONNECT_TIME_OUT = manager.getDownloadConfig().getConnectTimeOut(); - CONSTANCE.READ_TIME_OUT = manager.getDownloadConfig().getIOTimeOut(); + STATE = constance; + STATE.CONNECT_TIME_OUT = manager.getDownloadConfig().getConnectTimeOut(); + STATE.READ_TIME_OUT = manager.getDownloadConfig().getIOTimeOut(); mListener = listener; this.mConfigEntity = downloadInfo; if (mConfigEntity.IS_SUPPORT_BREAK_POINT) { @@ -65,7 +67,7 @@ final class SingleThreadTask implements Runnable { mSleepTime = 0; } else { BigDecimal db = new BigDecimal( - ((mBufSize / 1024) * (filterVersion() ? 1 : CONSTANCE.THREAD_NUM) / maxSpeed) * 1000); + ((mBufSize / 1024) * (filterVersion() ? 1 : STATE.THREAD_NUM) / maxSpeed) * 1000); mSleepTime = db.setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); } } @@ -98,8 +100,8 @@ final class SingleThreadTask implements Runnable { Log.w(TAG, "该下载不支持断点"); } conn = ConnectionHelp.setConnectParam(mConfigEntity.DOWNLOAD_TASK_ENTITY, conn); - conn.setConnectTimeout(CONSTANCE.CONNECT_TIME_OUT); - conn.setReadTimeout(CONSTANCE.READ_TIME_OUT); //设置读取流的等待时间,必须设置该参数 + conn.setConnectTimeout(STATE.CONNECT_TIME_OUT); + conn.setReadTimeout(STATE.READ_TIME_OUT); //设置读取流的等待时间,必须设置该参数 is = conn.getInputStream(); //创建可设置位置的文件 file = new BufferedRandomAccessFile(mConfigEntity.TEMP_FILE, "rwd", mBufSize); @@ -110,15 +112,15 @@ final class SingleThreadTask implements Runnable { //当前子线程的下载位置 mChildCurrentLocation = mConfigEntity.START_LOCATION; while ((len = is.read(buffer)) != -1) { - if (CONSTANCE.isCancel) break; - if (CONSTANCE.isStop) break; + if (STATE.isCancel) break; + if (STATE.isStop) break; if (mSleepTime > 0) Thread.sleep(mSleepTime); file.write(buffer, 0, len); progress(len); } - if (CONSTANCE.isCancel) return; + if (STATE.isCancel) return; //停止状态不需要删除记录文件 - if (CONSTANCE.isStop) return; + if (STATE.isStop) return; //支持断点的处理 if (mConfigEntity.IS_SUPPORT_BREAK_POINT) { Log.i(TAG, "任务【" @@ -127,18 +129,18 @@ final class SingleThreadTask implements Runnable { + mConfigEntity.THREAD_ID + "__下载完毕"); writeConfig(true, 1); - CONSTANCE.COMPLETE_THREAD_NUM++; - if (CONSTANCE.isComplete()) { + STATE.COMPLETE_THREAD_NUM++; + if (STATE.isComplete()) { File configFile = new File(mConfigFPath); if (configFile.exists()) { configFile.delete(); } - CONSTANCE.isDownloading = false; + STATE.isDownloading = false; mListener.onComplete(); } } else { Log.i(TAG, "下载任务完成"); - CONSTANCE.isDownloading = false; + STATE.isDownloading = false; mListener.onComplete(); } } catch (MalformedURLException e) { @@ -171,7 +173,7 @@ final class SingleThreadTask implements Runnable { synchronized (AriaManager.LOCK) { try { if (mConfigEntity.IS_SUPPORT_BREAK_POINT) { - CONSTANCE.STOP_NUM++; + STATE.STOP_NUM++; Log.d(TAG, "任务【" + mConfigEntity.TEMP_FILE.getName() + "】thread__" @@ -179,15 +181,15 @@ final class SingleThreadTask implements Runnable { + "__停止, stop location ==> " + mChildCurrentLocation); writeConfig(false, mChildCurrentLocation); - if (CONSTANCE.isStop()) { + if (STATE.isStop()) { Log.d(TAG, "任务【" + mConfigEntity.TEMP_FILE.getName() + "】已停止"); - CONSTANCE.isDownloading = false; - mListener.onStop(CONSTANCE.CURRENT_LOCATION); + STATE.isDownloading = false; + mListener.onStop(STATE.CURRENT_LOCATION); } } else { Log.d(TAG, "任务【" + mConfigEntity.TEMP_FILE.getName() + "】已停止"); - CONSTANCE.isDownloading = false; - mListener.onStop(CONSTANCE.CURRENT_LOCATION); + STATE.isDownloading = false; + mListener.onStop(STATE.CURRENT_LOCATION); } } catch (IOException e) { e.printStackTrace(); @@ -201,7 +203,7 @@ final class SingleThreadTask implements Runnable { private void progress(long len) { synchronized (AriaManager.LOCK) { mChildCurrentLocation += len; - CONSTANCE.CURRENT_LOCATION += len; + STATE.CURRENT_LOCATION += len; } } @@ -211,13 +213,13 @@ final class SingleThreadTask implements Runnable { protected void cancel() { synchronized (AriaManager.LOCK) { if (mConfigEntity.IS_SUPPORT_BREAK_POINT) { - CONSTANCE.CANCEL_NUM++; + STATE.CANCEL_NUM++; Log.d(TAG, "任务【" + mConfigEntity.TEMP_FILE.getName() + "】thread__" + mConfigEntity.THREAD_ID + "__取消下载"); - if (CONSTANCE.isCancel()) { + if (STATE.isCancel()) { File configFile = new File(mConfigFPath); if (configFile.exists()) { configFile.delete(); @@ -226,12 +228,12 @@ final class SingleThreadTask implements Runnable { mConfigEntity.TEMP_FILE.delete(); } Log.d(TAG, "任务【" + mConfigEntity.TEMP_FILE.getName() + "】已取消"); - CONSTANCE.isDownloading = false; + STATE.isDownloading = false; mListener.onCancel(); } } else { Log.d(TAG, "任务【" + mConfigEntity.TEMP_FILE.getName() + "】已取消"); - CONSTANCE.isDownloading = false; + STATE.isDownloading = false; mListener.onCancel(); } } @@ -243,15 +245,15 @@ final class SingleThreadTask implements Runnable { private void failDownload(long currentLocation, String msg, Exception ex) { synchronized (AriaManager.LOCK) { try { - CONSTANCE.FAIL_NUM++; - CONSTANCE.isDownloading = false; - CONSTANCE.isStop = true; + STATE.FAIL_NUM++; + STATE.isDownloading = false; + STATE.isStop = true; if (ex != null) { Log.e(TAG, msg + "\n" + CommonUtil.getPrintException(ex)); } if (mConfigEntity.IS_SUPPORT_BREAK_POINT) { writeConfig(false, currentLocation); - if (CONSTANCE.isFail()) { + if (STATE.isFail()) { Log.e(TAG, "任务【" + mConfigEntity.TEMP_FILE.getName() + "】下载失败"); mListener.onFail(); } diff --git a/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java b/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java index 8d605872..769eb2ab 100644 --- a/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java @@ -599,6 +599,16 @@ public class CommonUtil { return err.toString(); } + /** + * 通过文件名获取下载配置文件 + * + * @param fileName 文件名 + */ + public static String getFileConfig(boolean isDownload, String fileName) { + return AriaManager.APP.getFilesDir().getPath() + (isDownload ? AriaManager.DOWNLOAD_TEMP_DIR + : AriaManager.UPLOAD_TEMP_DIR) + fileName + ".properties"; + } + /** * 重命名下载配置文件 * 如果旧的配置文件名不存在,则使用新的配置文件名新创建一个文件,否则将旧的配置文件重命名为新的位置文件名。 @@ -608,8 +618,7 @@ public class CommonUtil { * @param newName 新的下载文件名 */ public static void renameDownloadConfig(String oldName, String newName) { - renameConfig(AriaManager.APP.getFilesDir().getPath() + AriaManager.DOWNLOAD_TEMP_DIR, oldName, - newName); + renameConfig(true, oldName, newName); } /** @@ -621,14 +630,13 @@ public class CommonUtil { * @param newName 新的上传文件名 */ public static void renameUploadConfig(String oldName, String newName) { - renameConfig(AriaManager.APP.getFilesDir().getPath() + AriaManager.UPLOAD_TEMP_DIR, oldName, - newName); + renameConfig(false, oldName, newName); } - private static void renameConfig(String basePath, String oldName, String newName) { + private static void renameConfig(boolean isDownload, String oldName, String newName) { if (oldName.equals(newName)) return; - File oldFile = new File(basePath + oldName + ".properties"); - File newFile = new File(basePath + newName + ".properties"); + File oldFile = new File(getFileConfig(isDownload, oldName)); + File newFile = new File(getFileConfig(isDownload, oldName)); if (!oldFile.exists()) { createFile(newFile.getPath()); } else {