From b3501dc3c3ae3284fc01d15b6e233695a27d8fd9 Mon Sep 17 00:00:00 2001 From: laoyuyu <511455842@qq.com> Date: Mon, 8 Apr 2019 19:56:57 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=B8=8A=E4=BC=A0=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1target=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aria/core/common/ftp/FtpDelegate.java | 140 +- ...{BaseGroupTarget.java => AbsDGTarget.java} | 33 +- .../aria/core/download/AbsDownloadTarget.java | 68 +- .../aria/core/download/BaseNormalTarget.java | 199 -- .../aria/core/download/DNormalDelegate.java | 89 +- .../core/download/DownloadGroupTarget.java | 35 +- .../aria/core/download/DownloadTarget.java | 20 +- .../core/download/FtpDirDownloadTarget.java | 9 +- .../aria/core/download/FtpDownloadTarget.java | 12 +- .../com/arialyy/aria/core/inf/AbsTarget.java | 20 +- .../aria/core/upload/AbsUploadTarget.java | 22 +- .../aria/core/upload/BaseNormalTarget.java | 146 - .../aria/core/upload/FtpUploadTarget.java | 4 +- .../aria/core/upload/UNormalDelegate.java | 23 +- .../aria/core/upload/UploadTarget.java | 2 +- .../core/upload/uploader/FtpThreadTask.java | 393 ++- .../aria/exception/ParamException.java | 24 + .../java/com/arialyy/aria/orm/DbEntity.java | 578 ++-- .../java/com/arialyy/aria/util/CheckUtil.java | 490 ++-- .../com/arialyy/aria/util/CommonUtil.java | 2434 +++++++++-------- DEV_LOG.md | 4 + app/src/main/assets/aria_config.xml | 320 +-- .../core/download/FtpDownloadActivity.java | 4 +- .../download/HighestPriorityActivity.java | 2 +- .../core/download/SingleTaskActivity.java | 21 +- .../core/test/TestMutilTaskSysDownload.java | 160 +- .../simple/core/upload/FtpUploadActivity.java | 226 +- 27 files changed, 2566 insertions(+), 2912 deletions(-) rename Aria/src/main/java/com/arialyy/aria/core/download/{BaseGroupTarget.java => AbsDGTarget.java} (84%) delete mode 100644 Aria/src/main/java/com/arialyy/aria/core/download/BaseNormalTarget.java delete mode 100644 Aria/src/main/java/com/arialyy/aria/core/upload/BaseNormalTarget.java create mode 100644 Aria/src/main/java/com/arialyy/aria/exception/ParamException.java diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/ftp/FtpDelegate.java b/Aria/src/main/java/com/arialyy/aria/core/common/ftp/FtpDelegate.java index 1d6ce711..70759200 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/ftp/FtpDelegate.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/ftp/FtpDelegate.java @@ -1,70 +1,70 @@ -/* - * 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.common.ftp; - -import android.text.TextUtils; -import com.arialyy.aria.core.FtpUrlEntity; -import com.arialyy.aria.core.inf.AbsTarget; -import com.arialyy.aria.core.inf.IFtpTarget; -import com.arialyy.aria.util.ALog; -import java.net.Proxy; - -/** - * Created by laoyuyu on 2018/3/9. - * ftp 委托 - */ -public class FtpDelegate implements IFtpTarget { - private static final String TAG = "FtpDelegate"; - private FtpUrlEntity mUrlEntity; - private TARGET mTarget; - - public FtpDelegate(TARGET target) { - mTarget = target; - mUrlEntity = target.getTaskWrapper().asFtp().getUrlEntity(); - } - - @Override public TARGET charSet(String charSet) { - if (TextUtils.isEmpty(charSet)) { - throw new NullPointerException("字符编码为空"); - } - mTarget.getTaskWrapper().asFtp().setCharSet(charSet); - return mTarget; - } - - @Override public TARGET login(String userName, String password) { - return login(userName, password, null); - } - - @Override public TARGET login(String userName, String password, String account) { - if (TextUtils.isEmpty(userName)) { - ALog.e(TAG, "用户名不能为null"); - return mTarget; - } else if (TextUtils.isEmpty(password)) { - ALog.e(TAG, "密码不能为null"); - return mTarget; - } - mUrlEntity.needLogin = true; - mUrlEntity.user = userName; - mUrlEntity.password = password; - mUrlEntity.account = account; - return mTarget; - } - - @Override public TARGET setProxy(Proxy proxy) { - mTarget.getTaskWrapper().asFtp().setProxy(proxy); - return mTarget; - } -} +/* + * 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.common.ftp; + +import android.text.TextUtils; +import com.arialyy.aria.core.FtpUrlEntity; +import com.arialyy.aria.core.inf.AbsTarget; +import com.arialyy.aria.core.inf.IFtpTarget; +import com.arialyy.aria.util.ALog; +import java.net.Proxy; + +/** + * Created by laoyuyu on 2018/3/9. + * ftp 委托 + */ +public class FtpDelegate implements IFtpTarget { + private static final String TAG = "FtpDelegate"; + private TARGET mTarget; + + public FtpDelegate(TARGET target) { + mTarget = target; + } + + @Override public TARGET charSet(String charSet) { + if (TextUtils.isEmpty(charSet)) { + throw new NullPointerException("字符编码为空"); + } + mTarget.getTaskWrapper().asFtp().setCharSet(charSet); + return mTarget; + } + + @Override public TARGET login(String userName, String password) { + return login(userName, password, null); + } + + @Override public TARGET login(String userName, String password, String account) { + if (TextUtils.isEmpty(userName)) { + ALog.e(TAG, "用户名不能为null"); + return mTarget; + } else if (TextUtils.isEmpty(password)) { + ALog.e(TAG, "密码不能为null"); + return mTarget; + } + // urlEntity 不能在构造函数中获取,因为ftp上传时url是后于构造函数的 + FtpUrlEntity urlEntity = mTarget.getTaskWrapper().asFtp().getUrlEntity(); + urlEntity.needLogin = true; + urlEntity.user = userName; + urlEntity.password = password; + urlEntity.account = account; + return mTarget; + } + + @Override public TARGET setProxy(Proxy proxy) { + mTarget.getTaskWrapper().asFtp().setProxy(proxy); + return mTarget; + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/BaseGroupTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/AbsDGTarget.java similarity index 84% rename from Aria/src/main/java/com/arialyy/aria/core/download/BaseGroupTarget.java rename to Aria/src/main/java/com/arialyy/aria/core/download/AbsDGTarget.java index adb049a4..d5d0257a 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/BaseGroupTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/AbsDGTarget.java @@ -19,6 +19,7 @@ import android.support.annotation.CheckResult; import android.text.TextUtils; import com.arialyy.aria.core.inf.AbsEntity; import com.arialyy.aria.core.inf.AbsTarget; +import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.manager.SubTaskManager; import com.arialyy.aria.core.queue.DownloadGroupTaskQueue; import com.arialyy.aria.orm.DbEntity; @@ -30,8 +31,7 @@ import java.util.List; /** * Created by lyy on 2017/7/26. */ -abstract class BaseGroupTarget - extends AbsTarget { +abstract class AbsDGTarget extends AbsTarget { /** * 组任务名 @@ -61,13 +61,21 @@ abstract class BaseGroupTarget return mSubTaskManager; } + @Override public DownloadGroupEntity getEntity() { + return (DownloadGroupEntity) super.getEntity(); + } + + @Override public DGTaskWrapper getTaskWrapper() { + return (DGTaskWrapper) super.getTaskWrapper(); + } + /** * 设置任务组别名 */ @CheckResult public TARGET setGroupAlias(String alias) { if (TextUtils.isEmpty(alias)) return (TARGET) this; - mEntity.setAlias(alias); + getEntity().setAlias(alias); return (TARGET) this; } @@ -75,18 +83,6 @@ abstract class BaseGroupTarget return DbEntity.checkDataExist(DownloadGroupEntity.class, "groupHash=?", mGroupHash); } - /** - * 设置任务组的文件夹路径,该api后续会删除 - * - * @param groupDirPath 任务组保存文件夹路径 - * @deprecated {@link #setDirPath(String)} 请使用这个api - */ - @Deprecated - @CheckResult - public TARGET setDownloadDirPath(String groupDirPath) { - return setDirPath(groupDirPath); - } - /** * 设置任务组的文件夹路径,在Aria中,任务组的所有子任务都会下载到以任务组组名的文件夹中。 * 如:groupDirPath = "/mnt/sdcard/download/group_test" @@ -113,7 +109,7 @@ abstract class BaseGroupTarget } @Override public boolean isRunning() { - DownloadGroupTask task = DownloadGroupTaskQueue.getInstance().getTask(mEntity.getKey()); + DownloadGroupTask task = DownloadGroupTaskQueue.getInstance().getTask(getEntity().getKey()); return task != null && task.isRunning(); } @@ -160,12 +156,13 @@ abstract class BaseGroupTarget return false; } - if (TextUtils.isEmpty(mEntity.getDirPath()) || !mEntity.getDirPath().equals(mDirPathTemp)) { + if (TextUtils.isEmpty(getEntity().getDirPath()) || !getEntity().getDirPath() + .equals(mDirPathTemp)) { if (!file.exists()) { file.mkdirs(); } needModifyPath = true; - mEntity.setDirPath(mDirPathTemp); + getEntity().setDirPath(mDirPathTemp); ALog.i(TAG, String.format("文件夹路径改变,将更新文件夹路径为:%s", mDirPathTemp)); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/AbsDownloadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/AbsDownloadTarget.java index 2e589d3b..9cca1f8e 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/AbsDownloadTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/AbsDownloadTarget.java @@ -23,22 +23,7 @@ import com.arialyy.aria.util.CommonUtil; /** * Created by lyy on 2017/2/28. */ -abstract class AbsDownloadTarget - extends AbsTarget { - - /** - * 设置的文件保存路径的临时变量 - */ - private String mTempFilePath; - - /** - * {@code true}强制下载,不考虑文件路径是否被占用 - */ - private boolean forceDownload = false; - /** - * 资源地址 - */ - private String mUrl, mNewUrl; +abstract class AbsDownloadTarget extends AbsTarget { /** * 更新下载url @@ -66,56 +51,7 @@ abstract class AbsDownloadTarget } } - /** - * 是否强制下载文件 {@link DownloadTarget#setFilePath(String, boolean)}、 - * {@link FtpDownloadTarget#setFilePath(String, boolean)} - * - * @return {@code true} 强制下载文件 - */ - boolean isForceDownload() { - return forceDownload; - } - - @Override public void setTaskWrapper(DTaskWrapper taskWrapper) { - super.setTaskWrapper(taskWrapper); - } - - /** - * 文件保存路径的临时变量 - */ - String getTempFilePath() { - return mTempFilePath; - } - - void setForceDownload(boolean forceDownload) { - this.forceDownload = forceDownload; - } - - public String getUrl() { - return mUrl; - } - - void setUrl(String url) { - this.mUrl = url; - } - - String getNewUrl() { - return mNewUrl; - } - - void setNewUrl(String newUrl) { - this.mNewUrl = newUrl; - } - - void setTempFilePath(String mTempFilePath) { - this.mTempFilePath = mTempFilePath; - } - - public void setEntity(DownloadEntity entity) { - mEntity = entity; - } - @Override public DownloadEntity getEntity() { - return super.getEntity(); + return (DownloadEntity) super.getEntity(); } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/BaseNormalTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/BaseNormalTarget.java deleted file mode 100644 index b7c7bace..00000000 --- a/Aria/src/main/java/com/arialyy/aria/core/download/BaseNormalTarget.java +++ /dev/null @@ -1,199 +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; -// -//import android.text.TextUtils; -//import com.arialyy.aria.core.manager.TaskWrapperManager; -//import com.arialyy.aria.core.queue.DownloadTaskQueue; -//import com.arialyy.aria.orm.DbEntity; -//import com.arialyy.aria.util.ALog; -//import com.arialyy.aria.util.CommonUtil; -//import java.io.File; -// -///** -// * Created by Aria.Lao on 2017/7/26. -// */ -//abstract class BaseNormalTarget -// extends AbsDownloadTarget { -// -// /** -// * 通过地址初始化target -// */ -// void initTarget(String url, String targetName) { -// setUrl(url); -// setTargetName(targetName); -// setTaskWrapper(TaskWrapperManager.getInstance().getHttpTaskWrapper(DTaskWrapper.class, url)); -// mEntity = getTaskWrapper().getEntity(); -// -// if (mEntity != null) { -// setTempFilePath(mEntity.getDownloadPath()); -// } -// } -// -// /** -// * 更新下载url -// * -// * @param newUrl 新的下载url -// */ -// public TARGET updateUrl(String newUrl) { -// if (TextUtils.isEmpty(newUrl)) { -// ALog.e(TAG, "下载url更新失败,newUrl为null"); -// return (TARGET) this; -// } -// if (getUrl().equals(newUrl)) { -// ALog.e(TAG, "下载url更新失败,新的下载url和旧的url一致"); -// return (TARGET) this; -// } -// setNewUrl(newUrl); -// getTaskWrapper().setRefreshInfo(true); -// return (TARGET) this; -// } -// -// /** -// * 将任务设置为最高优先级任务,最高优先级任务有以下特点: -// * 1、在下载队列中,有且只有一个最高优先级任务 -// * 2、最高优先级任务会一直存在,直到用户手动暂停或任务完成 -// * 3、任务调度器不会暂停最高优先级任务 -// * 4、用户手动暂停或任务完成后,第二次重新执行该任务,该命令将失效 -// * 5、如果下载队列中已经满了,则会停止队尾的任务,当高优先级任务完成后,该队尾任务将自动执行 -// * 6、把任务设置为最高优先级任务后,将自动执行任务,不需要重新调用start()启动任务 -// */ -// @Override public void setHighestPriority() { -// super.setHighestPriority(); -// } -// -// /** -// * 下载任务是否存在 -// * -// * @return {@code true}任务存在 -// */ -// @Override public boolean taskExists() { -// return DbEntity.checkDataExist(DownloadEntity.class, "url=?", getUrl()); -// } -// -// /** -// * 获取下载实体 -// */ -// public DownloadEntity getDownloadEntity() { -// return mEntity; -// } -// -// /** -// * 是否在下载 -// * -// * @return {@code true}任务正在下载 -// */ -// @Override public boolean isRunning() { -// DownloadTask task = DownloadTaskQueue.getInstance().getTask(mEntity.getKey()); -// return task != null && task.isRunning(); -// } -// -// /** -// * 检查下载实体,判断实体是否合法 合法标准为: -// * 1、下载路径不为null,并且下载路径是正常的http或ftp路径 -// * 2、保存路径不为null,并且保存路径是android文件系统路径 -// * 3、保存路径不能重复 -// * -// * @return {@code true}合法 -// */ -// @Override protected boolean checkEntity() { -// boolean b = getTargetType() < GROUP_HTTP && checkUrl() && checkFilePath(); -// if (b) { -// mEntity.save(); -// } -// return b; -// } -// -// /** -// * 检查并设置普通任务的文件保存路径 -// * -// * @return {@code true}保存路径合法 -// */ -// private boolean checkFilePath() { -// String filePath = getTempFilePath(); -// if (TextUtils.isEmpty(filePath)) { -// ALog.e(TAG, "下载失败,文件保存路径为null"); -// return false; -// } else if (!filePath.startsWith("/")) { -// ALog.e(TAG, "下载失败,文件保存路径【" + filePath + "】错误"); -// return false; -// } -// File file = new File(filePath); -// if (file.isDirectory()) { -// if (getTargetType() == HTTP) { -// ALog.e(TAG, "下载失败,保存路径【" + filePath + "】不能为文件夹,路径需要是完整的文件路径,如:/mnt/sdcard/game.zip"); -// return false; -// } else if (getTargetType() == FTP) { -// filePath += mEntity.getFileName(); -// } -// } else { -// // http文件名设置 -// if (TextUtils.isEmpty(mEntity.getFileName())) { -// mEntity.setFileName(file.getName()); -// } -// } -// -// //设置文件保存路径,如果新文件路径和旧文件路径不同,则修改路径 -// if (!filePath.equals(mEntity.getDownloadPath())) { -// // 检查路径冲突 -// if (DbEntity.checkDataExist(DownloadEntity.class, "downloadPath=?", filePath)) { -// if (!isForceDownload()) { -// ALog.e(TAG, "下载失败,保存路径【" + filePath + "】已经被其它任务占用,请设置其它保存路径"); -// return false; -// } else { -// ALog.w(TAG, "保存路径【" + filePath + "】已经被其它任务占用,当前任务将覆盖该路径的文件"); -// CommonUtil.delTaskRecord(filePath, 1); -// setTaskWrapper( -// TaskWrapperManager.getInstance().getHttpTaskWrapper(DTaskWrapper.class, getUrl())); -// } -// } -// File oldFile = new File(mEntity.getDownloadPath()); -// File newFile = new File(filePath); -// mEntity.setDownloadPath(filePath); -// mEntity.setFileName(newFile.getName()); -// if (oldFile.exists()) { -// oldFile.renameTo(newFile); -// CommonUtil.modifyTaskRecord(oldFile.getPath(), newFile.getPath()); -// } -// } -// return true; -// } -// -// /** -// * 检查普通任务的下载地址 -// * -// * @return {@code true}地址合法 -// */ -// private boolean checkUrl() { -// final String url = mEntity.getUrl(); -// if (TextUtils.isEmpty(url)) { -// ALog.e(TAG, "下载失败,url为null"); -// return false; -// } else if (!url.startsWith("http") && !url.startsWith("ftp")) { -// ALog.e(TAG, "下载失败,url【" + url + "】错误"); -// return false; -// } -// int index = url.indexOf("://"); -// if (index == -1) { -// ALog.e(TAG, "下载失败,url【" + url + "】不合法"); -// return false; -// } -// if (!TextUtils.isEmpty(getNewUrl())) { -// mEntity.setUrl(getNewUrl()); -// } -// return true; -// } -//} diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DNormalDelegate.java b/Aria/src/main/java/com/arialyy/aria/core/download/DNormalDelegate.java index d9dd36cc..a4e32c2d 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DNormalDelegate.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DNormalDelegate.java @@ -33,46 +33,60 @@ class DNormalDelegate implements ITargetNormal private final String TAG = "DNormalDelegate"; private DownloadEntity mEntity; - private TARGET target; + private TARGET mTarget; + private String mNewUrl; + /** + * 设置的文件保存路径的临时变量 + */ + private String mTempFilePath; + + /** + * {@code true}强制下载,不考虑文件路径是否被占用 + */ + private boolean forceDownload = false; + /** + * 资源地址 + */ + private String mUrl; DNormalDelegate(TARGET target, String url, String targetName) { - this.target = target; + this.mTarget = target; initTarget(url, targetName); } @Override public void initTarget(String url, String targetName) { - DTaskWrapper taskWrapper = TaskWrapperManager.getInstance().getHttpTaskWrapper(DTaskWrapper.class, url); + DTaskWrapper taskWrapper = + TaskWrapperManager.getInstance().getHttpTaskWrapper(DTaskWrapper.class, url); mEntity = taskWrapper.getEntity(); - target.setUrl(url); - target.setTargetName(targetName); - target.setTaskWrapper(taskWrapper); - target.setEntity(mEntity); + mUrl = url; + mTarget.setTargetName(targetName); + mTarget.setTaskWrapper(taskWrapper); if (mEntity != null) { - target.setTempFilePath(mEntity.getDownloadPath()); + mTempFilePath = mEntity.getDownloadPath(); } } @Override public TARGET updateUrl(String newUrl) { if (TextUtils.isEmpty(newUrl)) { - ALog.e(TAG, "下载url更新失败,newUrl为null"); - return target; + ALog.e(TAG, "url更新失败,newUrl为null"); + return mTarget; } - if (target.getUrl().equals(newUrl)) { - ALog.e(TAG, "下载url更新失败,新的下载url和旧的url一致"); - return target; + if (mUrl.equals(newUrl)) { + ALog.e(TAG, "url更新失败,新的下载url和旧的url一致"); + return mTarget; } - target.setNewUrl(newUrl); - target.getTaskWrapper().setRefreshInfo(true); - return target; + mNewUrl = newUrl; + mTarget.getTaskWrapper().setRefreshInfo(true); + return mTarget; } @Override public DownloadEntity getEntity() { - return target.getEntity(); + return mTarget.getEntity(); } @Override public boolean taskExists() { - return DbEntity.checkDataExist(DownloadEntity.class, "url=?", target.getUrl()); + return DbEntity.checkDataExist(DownloadEntity.class, "url=?", mUrl); } @Override public boolean isRunning() { @@ -89,7 +103,7 @@ class DNormalDelegate implements ITargetNormal } @Override public boolean checkFilePath() { - String filePath = target.getTempFilePath(); + String filePath = mTempFilePath; if (TextUtils.isEmpty(filePath)) { ALog.e(TAG, "下载失败,文件保存路径为null"); return false; @@ -99,10 +113,10 @@ class DNormalDelegate implements ITargetNormal } File file = new File(filePath); if (file.isDirectory()) { - if (target.getTargetType() == ITargetHandler.HTTP) { + if (mTarget.getTargetType() == ITargetHandler.HTTP) { ALog.e(TAG, "下载失败,保存路径【" + filePath + "】不能为文件夹,路径需要是完整的文件路径,如:/mnt/sdcard/game.zip"); return false; - } else if (target.getTargetType() == ITargetHandler.FTP) { + } else if (mTarget.getTargetType() == ITargetHandler.FTP) { filePath += mEntity.getFileName(); } } else { @@ -116,15 +130,15 @@ class DNormalDelegate implements ITargetNormal if (!filePath.equals(mEntity.getDownloadPath())) { // 检查路径冲突 if (DbEntity.checkDataExist(DownloadEntity.class, "downloadPath=?", filePath)) { - if (!target.isForceDownload()) { + if (!forceDownload) { ALog.e(TAG, "下载失败,保存路径【" + filePath + "】已经被其它任务占用,请设置其它保存路径"); return false; } else { ALog.w(TAG, "保存路径【" + filePath + "】已经被其它任务占用,当前任务将覆盖该路径的文件"); CommonUtil.delTaskRecord(filePath, 1); - target.setTaskWrapper( + mTarget.setTaskWrapper( TaskWrapperManager.getInstance() - .getHttpTaskWrapper(DTaskWrapper.class, target.getUrl())); + .getHttpTaskWrapper(DTaskWrapper.class, mUrl)); } } File oldFile = new File(mEntity.getDownloadPath()); @@ -132,8 +146,13 @@ class DNormalDelegate implements ITargetNormal mEntity.setDownloadPath(filePath); mEntity.setFileName(newFile.getName()); if (oldFile.exists()) { - oldFile.renameTo(newFile); + // 处理普通任务的重命名 CommonUtil.modifyTaskRecord(oldFile.getPath(), newFile.getPath()); + ALog.i(TAG, String.format("将任务重命名为:%s", newFile.getName())); + } else if (CommonUtil.blockTaskExists(oldFile.getPath())) { + // 处理分块任务的重命名 + CommonUtil.modifyTaskRecord(oldFile.getPath(), newFile.getPath()); + ALog.i(TAG, String.format("将分块任务重命名为:%s", newFile.getName())); } } return true; @@ -153,9 +172,25 @@ class DNormalDelegate implements ITargetNormal ALog.e(TAG, "下载失败,url【" + url + "】不合法"); return false; } - if (!TextUtils.isEmpty(target.getNewUrl())) { - mEntity.setUrl(target.getNewUrl()); + if (!TextUtils.isEmpty(mNewUrl)) { + mEntity.setUrl(mNewUrl); } return true; } + + void setForceDownload(boolean forceDownload) { + this.forceDownload = forceDownload; + } + + void setUrl(String url) { + this.mUrl = url; + } + + String getUrl() { + return mUrl; + } + + void setTempFilePath(String mTempFilePath) { + this.mTempFilePath = mTempFilePath; + } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTarget.java index 2bf4809c..c43710dd 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTarget.java @@ -26,7 +26,6 @@ import com.arialyy.aria.core.manager.TaskWrapperManager; import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.CommonUtil; -import java.io.File; import java.net.Proxy; import java.util.ArrayList; import java.util.HashSet; @@ -38,7 +37,7 @@ import java.util.Set; * Created by AriaL on 2017/6/29. * 下载任务组 */ -public class DownloadGroupTarget extends BaseGroupTarget implements +public class DownloadGroupTarget extends AbsDGTarget implements IHttpHeaderDelegate { private HttpHeaderDelegate mDelegate; /** @@ -68,9 +67,8 @@ public class DownloadGroupTarget extends BaseGroupTarget im private void init() { mGroupHash = CommonUtil.getMd5Code(mUrls); setTaskWrapper(TaskWrapperManager.getInstance().getDGTaskWrapper(DGTaskWrapper.class, mUrls)); - mEntity = getEntity(); - if (mEntity != null) { - mDirPathTemp = mEntity.getDirPath(); + if (getEntity() != null) { + mDirPathTemp = getEntity().getDirPath(); } mDelegate = new HttpHeaderDelegate<>(this); } @@ -98,10 +96,10 @@ public class DownloadGroupTarget extends BaseGroupTarget im mUrls.clear(); mUrls.addAll(urls); mGroupHash = CommonUtil.getMd5Code(urls); - mEntity.setGroupHash(mGroupHash); - mEntity.update(); - if (mEntity.getSubEntities() != null && !mEntity.getSubEntities().isEmpty()) { - for (DownloadEntity de : mEntity.getSubEntities()) { + getEntity().setGroupHash(mGroupHash); + getEntity().update(); + if (getEntity().getSubEntities() != null && !getEntity().getSubEntities().isEmpty()) { + for (DownloadEntity de : getEntity().getSubEntities()) { de.setGroupHash(mGroupHash); de.update(); } @@ -123,8 +121,8 @@ public class DownloadGroupTarget extends BaseGroupTarget im ALog.e(TAG, "文件大小不能小于 0"); return this; } - if (mEntity.getFileSize() <= 1 || mEntity.getFileSize() != fileSize) { - mEntity.setFileSize(fileSize); + if (getEntity().getFileSize() <= 1 || getEntity().getFileSize() != fileSize) { + getEntity().setFileSize(fileSize); } return this; } @@ -196,7 +194,7 @@ public class DownloadGroupTarget extends BaseGroupTarget im } } - mEntity.save(); + getEntity().save(); if (needModifyPath) { reChangeDirPath(mDirPathTemp); @@ -266,7 +264,7 @@ public class DownloadGroupTarget extends BaseGroupTarget im } } - mEntity.setGroupHash(CommonUtil.getMd5Code(mUrls)); + getEntity().setGroupHash(CommonUtil.getMd5Code(mUrls)); return true; } @@ -277,20 +275,15 @@ public class DownloadGroupTarget extends BaseGroupTarget im private void updateSingleSubFileName(DTaskWrapper taskEntity, String newName) { DownloadEntity entity = taskEntity.getEntity(); if (!newName.equals(entity.getFileName())) { - String oldPath = mEntity.getDirPath() + "/" + entity.getFileName(); - String newPath = mEntity.getDirPath() + "/" + newName; + String oldPath = getEntity().getDirPath() + "/" + entity.getFileName(); + String newPath = getEntity().getDirPath() + "/" + newName; if (DbEntity.checkDataExist(DownloadEntity.class, "downloadPath=? or isComplete='true'", newPath)) { ALog.w(TAG, String.format("更新文件名失败,路径【%s】已存在或文件已下载", newPath)); return; } - File oldFile = new File(oldPath); - if (oldFile.exists()) { - oldFile.renameTo(new File(newPath)); - } - - CommonUtil.modifyTaskRecord(oldFile.getPath(), newPath); + CommonUtil.modifyTaskRecord(oldPath, newPath); entity.setDownloadPath(newPath); entity.setFileName(newName); entity.update(); diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java index 68266865..045d2d89 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java @@ -70,18 +70,6 @@ public class DownloadTarget extends AbsDownloadTarget return this; } - /** - * 设置文件存储路径 - * 该api后续版本会删除 - * - * @param downloadPath 文件保存路径 - * @deprecated {@link #setFilePath(String)} 请使用这个api - */ - @CheckResult - @Deprecated public DownloadTarget setDownloadPath(@NonNull String downloadPath) { - return setFilePath(downloadPath); - } - /** * 设置文件存储路径,如果需要修改新的文件名,修改路径便可。 * 如:原文件路径 /mnt/sdcard/test.zip @@ -91,7 +79,7 @@ public class DownloadTarget extends AbsDownloadTarget */ @CheckResult public DownloadTarget setFilePath(@NonNull String filePath) { - setTempFilePath(filePath); + mNormalDelegate.setTempFilePath(filePath); return this; } @@ -105,8 +93,8 @@ public class DownloadTarget extends AbsDownloadTarget */ @CheckResult public DownloadTarget setFilePath(@NonNull String filePath, boolean forceDownload) { - setTempFilePath(filePath); - setForceDownload(forceDownload); + mNormalDelegate.setTempFilePath(filePath); + mNormalDelegate.setForceDownload(forceDownload); return this; } @@ -114,7 +102,7 @@ public class DownloadTarget extends AbsDownloadTarget * 从header中获取文件描述信息 */ public String getContentDisposition() { - return mEntity.getDisposition(); + return getEntity().getDisposition(); } @Override public DownloadTarget updateUrl(String newUrl) { diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/FtpDirDownloadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/FtpDirDownloadTarget.java index 41be403c..289600c7 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/FtpDirDownloadTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/FtpDirDownloadTarget.java @@ -30,7 +30,7 @@ import java.net.Proxy; * Created by Aria.Lao on 2017/7/26. * ftp文件夹下载 */ -public class FtpDirDownloadTarget extends BaseGroupTarget +public class FtpDirDownloadTarget extends AbsDGTarget implements IFtpTarget { private FtpDelegate mDelegate; @@ -43,9 +43,8 @@ public class FtpDirDownloadTarget extends BaseGroupTarget mGroupHash = key; setTaskWrapper(TaskWrapperManager.getInstance().getFtpTaskWrapper(DGTaskWrapper.class, key)); getTaskWrapper().setRequestType(AbsTaskWrapper.D_FTP_DIR); - mEntity = getEntity(); - if (mEntity != null) { - mDirPathTemp = mEntity.getDirPath(); + if (getEntity() != null) { + mDirPathTemp = getEntity().getDirPath(); } mDelegate = new FtpDelegate<>(this); } @@ -57,7 +56,7 @@ public class FtpDirDownloadTarget extends BaseGroupTarget @Override protected boolean checkEntity() { boolean b = getTargetType() == GROUP_FTP_DIR && checkDirPath() && checkUrl(); if (b) { - mEntity.save(); + getEntity().save(); if (getTaskWrapper().getSubTaskWrapper() != null) { //初始化子项的登录信息 FtpUrlEntity tUrlEntity = getTaskWrapper().asFtp().getUrlEntity(); 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 3ba5a82e..8cd35c31 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 @@ -45,9 +45,9 @@ public class FtpDownloadTarget extends AbsDownloadTarget } private void init() { - int lastIndex = getUrl().lastIndexOf("/"); - mEntity.setFileName(getUrl().substring(lastIndex + 1)); - getTaskWrapper().asFtp().setUrlEntity(CommonUtil.getFtpUrlInfo(getUrl())); + int lastIndex = mNormalDelegate.getUrl().lastIndexOf("/"); + getEntity().setFileName(mNormalDelegate.getUrl().substring(lastIndex + 1)); + getTaskWrapper().asFtp().setUrlEntity(CommonUtil.getFtpUrlInfo(mNormalDelegate.getUrl())); getTaskWrapper().setRequestType(AbsTaskWrapper.D_FTP); mFtpDelegate = new FtpDelegate<>(this); @@ -106,7 +106,7 @@ public class FtpDownloadTarget extends AbsDownloadTarget */ @CheckResult public FtpDownloadTarget setFilePath(@NonNull String filePath) { - setTempFilePath(filePath); + mNormalDelegate.setTempFilePath(filePath); return this; } @@ -120,8 +120,8 @@ public class FtpDownloadTarget extends AbsDownloadTarget */ @CheckResult public FtpDownloadTarget setFilePath(@NonNull String filePath, boolean forceDownload) { - setTempFilePath(filePath); - setForceDownload(forceDownload); + mNormalDelegate.setTempFilePath(filePath); + mNormalDelegate.setForceDownload(forceDownload); return this; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java index 9b380196..4493164e 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java @@ -36,18 +36,22 @@ import java.util.List; /** * Created by AriaL on 2017/7/3. */ -public abstract class AbsTarget - implements ITargetHandler { +public abstract class AbsTarget implements ITargetHandler { protected String TAG; - protected ENTITY mEntity; - private TASK_WRAPPER mTaskWrapper; + private AbsEntity mEntity; + private AbsTaskWrapper mTaskWrapper; private String mTargetName; protected AbsTarget() { TAG = CommonUtil.getClassName(this); } + public void setTaskWrapper(AbsTaskWrapper wrapper) { + mTaskWrapper = wrapper; + mEntity = wrapper.getEntity(); + } + /** * 重置状态,将任务状态设置为未开始状态 * 注意:如果在后续方法调用链中没有调用 {@link #start()}、{@link #stop()}、{@link #cancel()}、{@link #resume()} @@ -83,14 +87,10 @@ public abstract class AbsTarget - extends AbsTarget { +abstract class AbsUploadTarget extends AbsTarget { - /** - * 上传路径 - */ - private String mTempUrl; - @Override public void setTaskWrapper(UTaskWrapper mTaskWrapper) { - super.setTaskWrapper(mTaskWrapper); - } - - String getTempUrl() { - return mTempUrl; - } - - void setTempUrl(String tempUrl) { - this.mTempUrl = tempUrl; - } - - void setEntity(UploadEntity entity) { - this.mEntity = entity; - } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/BaseNormalTarget.java b/Aria/src/main/java/com/arialyy/aria/core/upload/BaseNormalTarget.java deleted file mode 100644 index 7b095415..00000000 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/BaseNormalTarget.java +++ /dev/null @@ -1,146 +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.upload; -// -//import android.support.annotation.CheckResult; -//import android.support.annotation.NonNull; -//import android.text.TextUtils; -//import com.arialyy.aria.core.manager.TaskWrapperManager; -//import com.arialyy.aria.core.queue.UploadTaskQueue; -//import com.arialyy.aria.orm.DbEntity; -//import com.arialyy.aria.util.ALog; -//import java.io.File; -// -///** -// * Created by AriaL on 2018/3/9. -// */ -//abstract class BaseNormalTarget -// extends AbsUploadTarget { -// -// protected String mTempUrl; -// -// void initTarget(String filePath) { -// mTaskWrapper = -// TaskWrapperManager.getInstance().getHttpTaskWrapper(UTaskWrapper.class, filePath); -// mEntity = mTaskWrapper.getEntity(); -// File file = new File(filePath); -// mEntity.setFileName(file.getName()); -// mEntity.setFileSize(file.length()); -// mTempUrl = mEntity.getUrl(); -// } -// -// /** -// * 设置上传路径 -// * -// * @param uploadUrl 上传路径 -// */ -// @CheckResult -// public TARGET setTempUrl(@NonNull String uploadUrl) { -// mTempUrl = uploadUrl; -// return (TARGET) this; -// } -// -// /** -// * 上传任务是否存在 -// * -// * @return {@code true}存在 -// */ -// @Override public boolean taskExists() { -// return DbEntity.checkDataExist(UploadEntity.class, "key=?", mEntity.getFilePath()); -// } -// -// /** -// * 是否在上传 -// * -// * @deprecated {@link #isRunning()} -// */ -// public boolean isUploading() { -// return isRunning(); -// } -// -// @Override public boolean isRunning() { -// UploadTask task = UploadTaskQueue.getInstance().getTask(mEntity.getKey()); -// return task != null && task.isRunning(); -// } -// -// @Override protected boolean checkEntity() { -// boolean b = checkUrl() && checkFilePath(); -// if (b) { -// mEntity.save(); -// } -// if (mTaskWrapper.asFtp().getUrlEntity() != null && mTaskWrapper.asFtp().getUrlEntity().isFtps) { -// //if (TextUtils.isEmpty(mTaskWrapper.getUrlEntity().storePath)) { -// // ALog.e(TAG, "证书路径为空"); -// // return false; -// //} -// if (TextUtils.isEmpty(mTaskWrapper.asFtp().getUrlEntity().keyAlias)) { -// ALog.e(TAG, "证书别名为空"); -// return false; -// } -// } -// return b; -// } -// -// /** -// * 检查上传文件路径是否合法 -// * -// * @return {@code true} 合法 -// */ -// private boolean checkFilePath() { -// String filePath = mEntity.getFilePath(); -// if (TextUtils.isEmpty(filePath)) { -// ALog.e(TAG, "上传失败,文件路径为null"); -// return false; -// } else if (!filePath.startsWith("/")) { -// ALog.e(TAG, "上传失败,文件路径【" + filePath + "】不合法"); -// return false; -// } -// -// File file = new File(mEntity.getFilePath()); -// if (!file.exists()) { -// ALog.e(TAG, "上传失败,文件【" + filePath + "】不存在"); -// return false; -// } -// if (file.isDirectory()) { -// ALog.e(TAG, "上传失败,文件【" + filePath + "】不能是文件夹"); -// return false; -// } -// return true; -// } -// -// /** -// * 检查普通任务的下载地址 -// * -// * @return {@code true}地址合法 -// */ -// protected boolean checkUrl() { -// final String url = mTempUrl; -// if (TextUtils.isEmpty(url)) { -// ALog.e(TAG, "上传失败,url为null"); -// return false; -// } else if (!url.startsWith("http") && !url.startsWith("ftp")) { -// ALog.e(TAG, "上传失败,url【" + url + "】错误"); -// return false; -// } -// int index = url.indexOf("://"); -// if (index == -1) { -// ALog.e(TAG, "上传失败,url【" + url + "】不合法"); -// return false; -// } -// mEntity.setUrl(url); -// return true; -// } -//} diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/FtpUploadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/upload/FtpUploadTarget.java index 18ecf446..122465d9 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/FtpUploadTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/FtpUploadTarget.java @@ -21,6 +21,7 @@ import com.arialyy.aria.core.common.ftp.FTPSDelegate; import com.arialyy.aria.core.common.ftp.FtpDelegate; import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.IFtpTarget; +import com.arialyy.aria.util.CheckUtil; import java.net.Proxy; /** @@ -48,7 +49,7 @@ public class FtpUploadTarget extends AbsUploadTarget * @param tempUrl 上传路径 */ public FtpUploadTarget setUploadUrl(String tempUrl) { - setTempUrl(tempUrl); + mNormalDelegate.setTempUrl(tempUrl); return this; } @@ -77,6 +78,7 @@ public class FtpUploadTarget extends AbsUploadTarget } @Override public FtpUploadTarget login(String userName, String password, String account) { + CheckUtil.checkFtpUploadUrl(mNormalDelegate.getTempUrl()); return mFtpDelegate.login(userName, password, account); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UNormalDelegate.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UNormalDelegate.java index 359e7937..f296177c 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/UNormalDelegate.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UNormalDelegate.java @@ -22,16 +22,21 @@ import com.arialyy.aria.core.manager.TaskWrapperManager; import com.arialyy.aria.core.queue.UploadTaskQueue; import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.util.ALog; +import com.arialyy.aria.util.CommonUtil; import java.io.File; /** * Created by Aria.Lao on 2019/4/5. * 普通上传任务通用功能处理 */ -public class UNormalDelegate implements ITargetNormal { +class UNormalDelegate implements ITargetNormal { private String TAG = "UNormalDelegate"; private UploadEntity mEntity; private TARGET mTarget; + /** + * 上传路径 + */ + private String mTempUrl; UNormalDelegate(TARGET target, String filePath, String targetName) { mTarget = target; @@ -47,12 +52,11 @@ public class UNormalDelegate implements ITargetN mEntity.setFileSize(file.length()); mTarget.setTargetName(targetName); mTarget.setTaskWrapper(taskWrapper); - mTarget.setEntity(mEntity); - mTarget.setTempUrl(mEntity.getUrl()); + mTempUrl = mEntity.getUrl(); } @Override public TARGET updateUrl(String newUrl) { - mTarget.setTempUrl(mEntity.getUrl()); + mTempUrl = newUrl; return mTarget; } @@ -113,7 +117,7 @@ public class UNormalDelegate implements ITargetN @Override public boolean checkUrl() { - final String url = mTarget.getTempUrl(); + final String url = mTempUrl; if (TextUtils.isEmpty(url)) { ALog.e(TAG, "上传失败,url为null"); return false; @@ -129,4 +133,13 @@ public class UNormalDelegate implements ITargetN mEntity.setUrl(url); return true; } + + void setTempUrl(String tempUrl) { + this.mTempUrl = tempUrl; + mTarget.getTaskWrapper().asFtp().setUrlEntity(CommonUtil.getFtpUrlInfo(tempUrl)); + } + + public String getTempUrl() { + return mTempUrl; + } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java index c6f40c0e..542536fd 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java @@ -51,7 +51,7 @@ public class UploadTarget extends AbsUploadTarget * @param tempUrl 上传路径 */ public UploadTarget setUploadUrl(String tempUrl) { - setTempUrl(tempUrl); + mNormalDelegate.setTempUrl(tempUrl); return this; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpThreadTask.java b/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpThreadTask.java index 06c929f2..ed4e8ca2 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpThreadTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpThreadTask.java @@ -1,199 +1,194 @@ -/* - * 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.upload.uploader; - -import aria.apache.commons.net.ftp.FTPClient; -import aria.apache.commons.net.ftp.FTPReply; -import aria.apache.commons.net.ftp.OnFtpInputStreamListener; -import com.arialyy.aria.core.common.StateConstance; -import com.arialyy.aria.core.common.SubThreadConfig; -import com.arialyy.aria.core.common.ftp.AbsFtpThreadTask; -import com.arialyy.aria.core.config.BaseTaskConfig; -import com.arialyy.aria.core.config.DownloadConfig; -import com.arialyy.aria.core.config.UploadConfig; -import com.arialyy.aria.core.inf.IEventListener; -import com.arialyy.aria.core.upload.UploadEntity; -import com.arialyy.aria.core.upload.UTaskWrapper; -import com.arialyy.aria.exception.AriaIOException; -import com.arialyy.aria.exception.TaskException; -import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.BufferedRandomAccessFile; -import java.io.IOException; -import java.io.UnsupportedEncodingException; - -/** - * Created by Aria.Lao on 2017/7/28. FTP 单线程上传任务,需要FTP 服务器给用户打开append和write的权限 - */ -class FtpThreadTask extends AbsFtpThreadTask { - private final String TAG = "FtpThreadTask"; - private String dir, remotePath; - - FtpThreadTask(StateConstance constance, IEventListener listener, - SubThreadConfig info) { - super(constance, listener, info); - } - - @Override public int getMaxSpeed() { - return getTaskConfig().getMaxSpeed(); - } - - @Override protected UploadConfig getTaskConfig() { - return mTaskWrapper.getConfig(); - } - - @Override public FtpThreadTask call() throws Exception { - super.call(); - //当前子线程的下载位置 - mChildCurrentLocation = mConfig.START_LOCATION; - FTPClient client = null; - BufferedRandomAccessFile file = null; - try { - ALog.d(TAG, - String.format("任务【%s】线程__%s__开始上传【开始位置 : %s,结束位置:%s】", mConfig.TEMP_FILE.getName(), - mConfig.THREAD_ID, mConfig.START_LOCATION, mConfig.END_LOCATION)); - client = createClient(); - if (client == null) { - return this; - } - initPath(); - client.makeDirectory(dir); - client.changeWorkingDirectory(dir); - client.setRestartOffset(mConfig.START_LOCATION); - int reply = client.getReplyCode(); - if (!FTPReply.isPositivePreliminary(reply) && reply != FTPReply.FILE_ACTION_OK) { - fail(mChildCurrentLocation, - new AriaIOException(TAG, - String.format("文件上传错误,错误码为:%s, msg:%s, filePath: %s", reply, - client.getReplyString(), mEntity.getFilePath()))); - client.disconnect(); - return this; - } - - file = new BufferedRandomAccessFile(mConfig.TEMP_FILE, "rwd", getTaskConfig().getBuffSize()); - if (mConfig.START_LOCATION != 0) { - //file.skipBytes((int) mConfig.START_LOCATION); - file.seek(mConfig.START_LOCATION); - } - boolean complete = upload(client, file); - if (!complete || isBreak()) { - return this; - } - ALog.i(TAG, - String.format("任务【%s】线程__%s__上传完毕", mConfig.TEMP_FILE.getName(), mConfig.THREAD_ID)); - writeConfig(true, mConfig.END_LOCATION); - STATE.COMPLETE_THREAD_NUM++; - if (STATE.isComplete()) { - STATE.TASK_RECORD.deleteData(); - STATE.isRunning = false; - mListener.onComplete(); - } - if (STATE.isFail()) { - STATE.isRunning = false; - mListener.onFail(false, new TaskException(TAG, - String.format("上传失败,filePath: %s, uploadUrl: %s", mEntity.getFilePath(), mConfig.URL))); - } - } catch (IOException e) { - fail(mChildCurrentLocation, new AriaIOException(TAG, - String.format("上传失败,filePath: %s, uploadUrl: %s", mEntity.getFilePath(), mConfig.URL))); - } catch (Exception e) { - fail(mChildCurrentLocation, new AriaIOException(TAG, null, e)); - } finally { - try { - if (file != null) { - file.close(); - } - if (client != null && client.isConnected()) { - client.disconnect(); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - return this; - } - - private void initPath() throws UnsupportedEncodingException { - dir = new String(mTaskWrapper.asFtp().getUrlEntity().remotePath.getBytes(charSet), - SERVER_CHARSET); - remotePath = new String( - ("/" - + mTaskWrapper.asFtp().getUrlEntity().remotePath - + "/" - + mEntity.getFileName()).getBytes( - charSet), - SERVER_CHARSET); - } - - /** - * 上传 - * - * @return {@code true}上传成功、{@code false} 上传失败 - */ - private boolean upload(final FTPClient client, final BufferedRandomAccessFile bis) - throws IOException { - - try { - ALog.d(TAG, String.format("remotePath: %s", remotePath)); - client.storeFile(remotePath, new FtpFISAdapter(bis), new OnFtpInputStreamListener() { - boolean isStoped = false; - - @Override public void onFtpInputStream(FTPClient client, long totalBytesTransferred, - int bytesTransferred, long streamSize) { - try { - if (isBreak() && !isStoped) { - isStoped = true; - client.abor(); - } - if (mSpeedBandUtil != null) { - mSpeedBandUtil.limitNextBytes(bytesTransferred); - } - progress(bytesTransferred); - } catch (IOException e) { - e.printStackTrace(); - } - } - }); - } catch (IOException e) { - String msg = String.format("文件上传错误,错误码为:%s, msg:%s, filePath: %s", client.getReplyCode(), - client.getReplyString(), mEntity.getFilePath()); - if (client.isConnected()) { - client.disconnect(); - } - if (e.getMessage().contains("AriaIOException caught while copying")) { - e.printStackTrace(); - } else { - fail(mChildCurrentLocation, - new AriaIOException(TAG, msg, e)); - } - return false; - } - - int reply = client.getReplyCode(); - if (!FTPReply.isPositiveCompletion(reply)) { - if (reply != FTPReply.TRANSFER_ABORTED) { - fail(mChildCurrentLocation, - new AriaIOException(TAG, - String.format("文件上传错误,错误码为:%s, msg:%s, filePath: %s", reply, - client.getReplyString(), mEntity.getFilePath()))); - } - if (client.isConnected()) { - client.disconnect(); - } - return false; - } - return true; - } -} +/* + * 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.upload.uploader; + +import aria.apache.commons.net.ftp.FTPClient; +import aria.apache.commons.net.ftp.FTPReply; +import aria.apache.commons.net.ftp.OnFtpInputStreamListener; +import com.arialyy.aria.core.common.StateConstance; +import com.arialyy.aria.core.common.SubThreadConfig; +import com.arialyy.aria.core.common.ftp.AbsFtpThreadTask; +import com.arialyy.aria.core.config.BaseTaskConfig; +import com.arialyy.aria.core.config.DownloadConfig; +import com.arialyy.aria.core.config.UploadConfig; +import com.arialyy.aria.core.inf.IEventListener; +import com.arialyy.aria.core.upload.UploadEntity; +import com.arialyy.aria.core.upload.UTaskWrapper; +import com.arialyy.aria.exception.AriaIOException; +import com.arialyy.aria.exception.TaskException; +import com.arialyy.aria.util.ALog; +import com.arialyy.aria.util.BufferedRandomAccessFile; +import java.io.IOException; +import java.io.UnsupportedEncodingException; + +/** + * Created by Aria.Lao on 2017/7/28. FTP 单线程上传任务,需要FTP 服务器给用户打开append和write的权限 + */ +class FtpThreadTask extends AbsFtpThreadTask { + private final String TAG = "FtpThreadTask"; + private String dir, remotePath; + + FtpThreadTask(StateConstance constance, IEventListener listener, + SubThreadConfig info) { + super(constance, listener, info); + } + + @Override public int getMaxSpeed() { + return getTaskConfig().getMaxSpeed(); + } + + @Override protected UploadConfig getTaskConfig() { + return mTaskWrapper.getConfig(); + } + + @Override public FtpThreadTask call() throws Exception { + super.call(); + //当前子线程的下载位置 + mChildCurrentLocation = mConfig.START_LOCATION; + FTPClient client = null; + BufferedRandomAccessFile file = null; + try { + ALog.d(TAG, + String.format("任务【%s】线程__%s__开始上传【开始位置 : %s,结束位置:%s】", mConfig.TEMP_FILE.getName(), + mConfig.THREAD_ID, mConfig.START_LOCATION, mConfig.END_LOCATION)); + client = createClient(); + if (client == null) { + return this; + } + initPath(); + client.makeDirectory(dir); + client.changeWorkingDirectory(dir); + client.setRestartOffset(mConfig.START_LOCATION); + int reply = client.getReplyCode(); + if (!FTPReply.isPositivePreliminary(reply) && reply != FTPReply.FILE_ACTION_OK) { + fail(mChildCurrentLocation, + new AriaIOException(TAG, + String.format("文件上传错误,错误码为:%s, msg:%s, filePath: %s", reply, + client.getReplyString(), mEntity.getFilePath()))); + client.disconnect(); + return this; + } + + file = new BufferedRandomAccessFile(mConfig.TEMP_FILE, "rwd", getTaskConfig().getBuffSize()); + if (mConfig.START_LOCATION != 0) { + //file.skipBytes((int) mConfig.START_LOCATION); + file.seek(mConfig.START_LOCATION); + } + boolean complete = upload(client, file); + if (!complete || isBreak()) { + return this; + } + ALog.i(TAG, + String.format("任务【%s】线程__%s__上传完毕", mConfig.TEMP_FILE.getName(), mConfig.THREAD_ID)); + writeConfig(true, mConfig.END_LOCATION); + STATE.COMPLETE_THREAD_NUM++; + if (STATE.isComplete()) { + STATE.TASK_RECORD.deleteData(); + STATE.isRunning = false; + mListener.onComplete(); + } + if (STATE.isFail()) { + STATE.isRunning = false; + mListener.onFail(false, new TaskException(TAG, + String.format("上传失败,filePath: %s, uploadUrl: %s", mEntity.getFilePath(), mConfig.URL))); + } + } catch (IOException e) { + fail(mChildCurrentLocation, new AriaIOException(TAG, + String.format("上传失败,filePath: %s, uploadUrl: %s", mEntity.getFilePath(), mConfig.URL))); + } catch (Exception e) { + fail(mChildCurrentLocation, new AriaIOException(TAG, null, e)); + } finally { + try { + if (file != null) { + file.close(); + } + if (client != null && client.isConnected()) { + client.disconnect(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + return this; + } + + private void initPath() throws UnsupportedEncodingException { + dir = new String(mTaskWrapper.asFtp().getUrlEntity().remotePath.getBytes(charSet), + SERVER_CHARSET); + remotePath = new String(String.format("%s/%s", mTaskWrapper.asFtp().getUrlEntity().remotePath, + mEntity.getFileName()).getBytes(charSet), SERVER_CHARSET); + } + + /** + * 上传 + * + * @return {@code true}上传成功、{@code false} 上传失败 + */ + private boolean upload(final FTPClient client, final BufferedRandomAccessFile bis) + throws IOException { + + try { + ALog.d(TAG, String.format("remotePath: %s", remotePath)); + client.storeFile(remotePath, new FtpFISAdapter(bis), new OnFtpInputStreamListener() { + boolean isStoped = false; + + @Override public void onFtpInputStream(FTPClient client, long totalBytesTransferred, + int bytesTransferred, long streamSize) { + try { + if (isBreak() && !isStoped) { + isStoped = true; + client.abor(); + } + if (mSpeedBandUtil != null) { + mSpeedBandUtil.limitNextBytes(bytesTransferred); + } + progress(bytesTransferred); + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + } catch (IOException e) { + String msg = String.format("文件上传错误,错误码为:%s, msg:%s, filePath: %s", client.getReplyCode(), + client.getReplyString(), mEntity.getFilePath()); + if (client.isConnected()) { + client.disconnect(); + } + if (e.getMessage().contains("AriaIOException caught while copying")) { + e.printStackTrace(); + } else { + fail(mChildCurrentLocation, + new AriaIOException(TAG, msg, e)); + } + return false; + } + + int reply = client.getReplyCode(); + if (!FTPReply.isPositiveCompletion(reply)) { + if (reply != FTPReply.TRANSFER_ABORTED) { + fail(mChildCurrentLocation, + new AriaIOException(TAG, + String.format("文件上传错误,错误码为:%s, msg:%s, filePath: %s", reply, + client.getReplyString(), mEntity.getFilePath()))); + } + if (client.isConnected()) { + client.disconnect(); + } + return false; + } + return true; + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/exception/ParamException.java b/Aria/src/main/java/com/arialyy/aria/exception/ParamException.java new file mode 100644 index 00000000..fb77a9e0 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/exception/ParamException.java @@ -0,0 +1,24 @@ +/* + * 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.exception; + +public class ParamException extends RuntimeException { + private static final String ARIA_NET_EXCEPTION = "Aria Params Exception:"; + + public ParamException(String message) { + super(String.format("%s%s", ARIA_NET_EXCEPTION, message)); + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/orm/DbEntity.java b/Aria/src/main/java/com/arialyy/aria/orm/DbEntity.java index 1e227f5a..63f8e975 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/DbEntity.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/DbEntity.java @@ -1,290 +1,290 @@ -/* - * 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.orm; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by lyy on 2015/11/2. 所有数据库实体父类 - */ -public abstract class DbEntity { - private static final Object LOCK = new Object(); - protected long rowID = -1; - - protected DbEntity() { - - } - - /** - * 查询关联数据 - * - * DbEntity.findRelationData(DGEntityWrapper.class, "downloadUrl=?", downloadUrl); - * - * - * @param expression 查询条件 - */ - public static List findRelationData(Class clazz, - String... expression) { - return DelegateWrapper.getInstance().findRelationData(clazz, expression); - } - - /** - * 分页查询关联数据 - * - * - * DbEntity.findRelationData(DGEntityWrapper.class, 0, 10, "downloadUrl=?", downloadUrl); - * - * - * @param expression 查询条件 - * @param page 需要查询的页数,从1开始,如果page小于1 或 num 小于1,返回null - * @param num 每页返回的数量 - * @return 没有数据返回null,如果页数大于总页数,返回null - */ - public static List findRelationData(Class clazz, int page, int num, - String... expression) { - if (page < 1 || num < 1) { - return null; - } - return DelegateWrapper.getInstance().findRelationData(clazz, page, num, expression); - } - - /** - * 检查某个字段的值是否存在 - * - * @param expression 字段和值"downloadPath=?" - * @return {@code true}该字段的对应的value已存在 - */ - public static boolean checkDataExist(Class clazz, String... expression) { - return DelegateWrapper.getInstance().checkDataExist(clazz, expression); - } - - /** - * 清空表数据 - */ - public static void clean(Class clazz) { - DelegateWrapper.getInstance().clean(clazz); - } - - /** - * 直接执行sql语句 - */ - public static void exeSql(String sql) { - DelegateWrapper.getInstance().exeSql(sql); - } - - /** - * 查询所有数据 - * - * @return 没有数据返回null - */ - public static List findAllData(Class clazz) { - return DelegateWrapper.getInstance().findAllData(clazz); - } - - /** - * 查询第一条数据 - */ - public static T findFirst(Class clazz) { - List list = findAllData(clazz); - return (list == null || list.size() == 0) ? null : list.get(0); - } - - /** - * 查询一组数据 - * - * DbEntity.findFirst(DownloadEntity.class, "downloadUrl=?", downloadUrl); - * - * - * @return 没有数据返回null - */ - public static List findDatas(Class clazz, String... expression) { - return DelegateWrapper.getInstance().findData(clazz, expression); - } - - /** - * 分页查询数据 - * - * DbEntity.findFirst(DownloadEntity.class, 0, 10, "downloadUrl=?", downloadUrl); - * - * - * @param page 需要查询的页数,从1开始,如果page小于1 或 num 小于1,返回null - * @param num 每页返回的数量 - * @return 没有数据返回null,如果页数大于总页数,返回null - */ - public static List findDatas(Class clazz, int page, int num, - String... expression) { - if (page < 1 || num < 1) { - return null; - } - return DelegateWrapper.getInstance().findData(clazz, page, num, expression); - } - - /** - * 模糊查询一组数据 - * - * DbEntity.findDataByFuzzy(DownloadEntity.class, "downloadUrl like http://"); - * - * - * @return 没有数据返回null - */ - public static List findDataByFuzzy(Class clazz, String conditions) { - return DelegateWrapper.getInstance().findDataByFuzzy(clazz, conditions); - } - - /** - * 模糊查询一组数据 - * - * DbEntity.findDataByFuzzy(DownloadEntity.class, 0, 10, "downloadUrl like http://"); - * - * - * @param page 需要查询的页数,从1开始,如果page小于1 或 num 小于1,返回null - * @param num 每页返回的数量 - * @return 没有数据返回null,如果页数大于总页数,返回null - */ - public static List findDataByFuzzy(Class clazz, int page, int num, - String conditions) { - return DelegateWrapper.getInstance().findDataByFuzzy(clazz, page, num, conditions); - } - - /** - * 查询一行数据 - * - * DbEntity.findFirst(DownloadEntity.class, "downloadUrl=?", downloadUrl); - * - * - * @return 没有数据返回null - */ - public static T findFirst(Class clazz, String... expression) { - DelegateWrapper util = DelegateWrapper.getInstance(); - List datas = util.findData(clazz, expression); - return datas == null ? null : datas.size() > 0 ? datas.get(0) : null; - } - - /** - * 插入多条数据 - */ - public static void insertManyData(List entities) { - checkListData(entities); - DelegateWrapper.getInstance().insertManyData(entities); - } - - /** - * 修改多条数据 - */ - public static void updateManyData(List entities) { - checkListData(entities); - DelegateWrapper.getInstance().updateManyData(entities); - } - - /** - * 保存多条数据,通过rowID来判断记录存在以否,如果数据库已有记录,则更新该记录;如果数据库中没有记录,则保存该记录 - */ - public static void saveAll(List entities) { - checkListData(entities); - List insertD = new ArrayList<>(); - List updateD = new ArrayList<>(); - DelegateWrapper wrapper = DelegateWrapper.getInstance(); - for (DbEntity entity : entities) { - if (entity.rowID == -1) { - insertD.add(entity); - continue; - } - if (wrapper.isExist(entity.getClass(), entity.rowID)) { - insertD.add(entity); - } else { - updateD.add(entity); - } - } - if (!insertD.isEmpty()) { - wrapper.insertManyData(insertD); - } else { - wrapper.updateManyData(updateD); - } - } - - /** - * 检查批量操作的列表数据,如果数据为空,抛出{@link NullPointerException} - */ - private static void checkListData(List entities) { - if (entities == null || entities.isEmpty()) { - throw new NullPointerException("列表数据为空"); - } - } - - /** - * 删除当前数据 - */ - public void deleteData() { - deleteData(getClass(), "rowid=?", rowID + ""); - } - - /** - * 根据条件删除数据 - * - * DbEntity.deleteData(DownloadEntity.class, "downloadUrl=?", downloadUrl); - * - */ - public static void deleteData(Class clazz, String... expression) { - DelegateWrapper util = DelegateWrapper.getInstance(); - util.delData(clazz, expression); - } - - /** - * 修改数据 - */ - public void update() { - DelegateWrapper.getInstance().updateData(this); - } - - /** - * 保存自身,如果表中已经有数据,则更新数据,否则插入数据 只有 target中checkEntity成功后才能保存,创建实体部分也不允许保存 - */ - public void save() { - synchronized (LOCK) { - if (thisIsExist()) { - update(); - } else { - insert(); - } - } - } - - /** - * 查找数据在表中是否存在 - */ - private boolean thisIsExist() { - DelegateWrapper util = DelegateWrapper.getInstance(); - return rowID != -1 && util.isExist(getClass(), rowID); - } - - /** - * 表是否存在 - * - * @return {@code true} 存在 - */ - public static boolean tableExists(Class clazz) { - return DelegateWrapper.getInstance().tableExists(clazz); - } - - /** - * 插入数据,只有 target中checkEntity成功后才能插入,创建实体部分也不允许操作 - */ - public void insert() { - DelegateWrapper.getInstance().insertData(this); - } +/* + * 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.orm; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by lyy on 2015/11/2. 所有数据库实体父类 + */ +public abstract class DbEntity { + private static final Object LOCK = new Object(); + protected long rowID = -1; + + protected DbEntity() { + + } + + /** + * 查询关联数据 + * + * DbEntity.findRelationData(DGEntityWrapper.class, "downloadUrl=?", downloadUrl); + * + * + * @param expression 查询条件 + */ + public static List findRelationData(Class clazz, + String... expression) { + return DelegateWrapper.getInstance().findRelationData(clazz, expression); + } + + /** + * 分页查询关联数据 + * + * + * DbEntity.findRelationData(DGEntityWrapper.class, 0, 10, "downloadUrl=?", downloadUrl); + * + * + * @param expression 查询条件 + * @param page 需要查询的页数,从1开始,如果page小于1 或 num 小于1,返回null + * @param num 每页返回的数量 + * @return 没有数据返回null,如果页数大于总页数,返回null + */ + public static List findRelationData(Class clazz, int page, int num, + String... expression) { + if (page < 1 || num < 1) { + return null; + } + return DelegateWrapper.getInstance().findRelationData(clazz, page, num, expression); + } + + /** + * 检查某个字段的值是否存在 + * + * @param expression 字段和值"downloadPath=?" + * @return {@code true}该字段的对应的value已存在 + */ + public static boolean checkDataExist(Class clazz, String... expression) { + return DelegateWrapper.getInstance().checkDataExist(clazz, expression); + } + + /** + * 清空表数据 + */ + public static void clean(Class clazz) { + DelegateWrapper.getInstance().clean(clazz); + } + + /** + * 直接执行sql语句 + */ + public static void exeSql(String sql) { + DelegateWrapper.getInstance().exeSql(sql); + } + + /** + * 查询所有数据 + * + * @return 没有数据返回null + */ + public static List findAllData(Class clazz) { + return DelegateWrapper.getInstance().findAllData(clazz); + } + + /** + * 查询第一条数据 + */ + public static T findFirst(Class clazz) { + List list = findAllData(clazz); + return (list == null || list.size() == 0) ? null : list.get(0); + } + + /** + * 查询一组数据 + * + * DbEntity.findFirst(DownloadEntity.class, "downloadUrl=?", downloadUrl); + * + * + * @return 没有数据返回null + */ + public static List findDatas(Class clazz, String... expression) { + return DelegateWrapper.getInstance().findData(clazz, expression); + } + + /** + * 分页查询数据 + * + * DbEntity.findFirst(DownloadEntity.class, 0, 10, "downloadUrl=?", downloadUrl); + * + * + * @param page 需要查询的页数,从1开始,如果page小于1 或 num 小于1,返回null + * @param num 每页返回的数量 + * @return 没有数据返回null,如果页数大于总页数,返回null + */ + public static List findDatas(Class clazz, int page, int num, + String... expression) { + if (page < 1 || num < 1) { + return null; + } + return DelegateWrapper.getInstance().findData(clazz, page, num, expression); + } + + /** + * 模糊查询一组数据 + * + * DbEntity.findDataByFuzzy(DownloadEntity.class, "downloadUrl like http://"); + * + * + * @return 没有数据返回null + */ + public static List findDataByFuzzy(Class clazz, String conditions) { + return DelegateWrapper.getInstance().findDataByFuzzy(clazz, conditions); + } + + /** + * 模糊查询一组数据 + * + * DbEntity.findDataByFuzzy(DownloadEntity.class, 0, 10, "downloadUrl like http://"); + * + * + * @param page 需要查询的页数,从1开始,如果page小于1 或 num 小于1,返回null + * @param num 每页返回的数量 + * @return 没有数据返回null,如果页数大于总页数,返回null + */ + public static List findDataByFuzzy(Class clazz, int page, int num, + String conditions) { + return DelegateWrapper.getInstance().findDataByFuzzy(clazz, page, num, conditions); + } + + /** + * 查询一行数据 + * + * DbEntity.findFirst(DownloadEntity.class, "downloadUrl=?", downloadUrl); + * + * + * @return 没有数据返回null + */ + public static T findFirst(Class clazz, String... expression) { + DelegateWrapper util = DelegateWrapper.getInstance(); + List datas = util.findData(clazz, expression); + return datas == null ? null : datas.size() > 0 ? datas.get(0) : null; + } + + /** + * 插入多条数据 + */ + public static void insertManyData(List entities) { + checkListData(entities); + DelegateWrapper.getInstance().insertManyData(entities); + } + + /** + * 修改多条数据 + */ + public static void updateManyData(List entities) { + checkListData(entities); + DelegateWrapper.getInstance().updateManyData(entities); + } + + /** + * 保存多条数据,通过rowID来判断记录存在以否,如果数据库已有记录,则更新该记录;如果数据库中没有记录,则保存该记录 + */ + public static void saveAll(List entities) { + checkListData(entities); + List insertD = new ArrayList<>(); + List updateD = new ArrayList<>(); + DelegateWrapper wrapper = DelegateWrapper.getInstance(); + for (DbEntity entity : entities) { + if (entity.rowID == -1) { + insertD.add(entity); + continue; + } + if (wrapper.isExist(entity.getClass(), entity.rowID)) { + updateD.add(entity); + } else { + insertD.add(entity); + } + } + if (!insertD.isEmpty()) { + wrapper.insertManyData(insertD); + } else { + wrapper.updateManyData(updateD); + } + } + + /** + * 检查批量操作的列表数据,如果数据为空,抛出{@link NullPointerException} + */ + private static void checkListData(List entities) { + if (entities == null || entities.isEmpty()) { + throw new NullPointerException("列表数据为空"); + } + } + + /** + * 删除当前数据 + */ + public void deleteData() { + deleteData(getClass(), "rowid=?", rowID + ""); + } + + /** + * 根据条件删除数据 + * + * DbEntity.deleteData(DownloadEntity.class, "downloadUrl=?", downloadUrl); + * + */ + public static void deleteData(Class clazz, String... expression) { + DelegateWrapper util = DelegateWrapper.getInstance(); + util.delData(clazz, expression); + } + + /** + * 修改数据 + */ + public void update() { + DelegateWrapper.getInstance().updateData(this); + } + + /** + * 保存自身,如果表中已经有数据,则更新数据,否则插入数据 只有 target中checkEntity成功后才能保存,创建实体部分也不允许保存 + */ + public void save() { + synchronized (LOCK) { + if (thisIsExist()) { + update(); + } else { + insert(); + } + } + } + + /** + * 查找数据在表中是否存在 + */ + private boolean thisIsExist() { + DelegateWrapper util = DelegateWrapper.getInstance(); + return rowID != -1 && util.isExist(getClass(), rowID); + } + + /** + * 表是否存在 + * + * @return {@code true} 存在 + */ + public static boolean tableExists(Class clazz) { + return DelegateWrapper.getInstance().tableExists(clazz); + } + + /** + * 插入数据,只有 target中checkEntity成功后才能插入,创建实体部分也不允许操作 + */ + public void insert() { + DelegateWrapper.getInstance().insertData(this); + } } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/util/CheckUtil.java b/Aria/src/main/java/com/arialyy/aria/util/CheckUtil.java index 278ceb89..394b8ddd 100644 --- a/Aria/src/main/java/com/arialyy/aria/util/CheckUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/util/CheckUtil.java @@ -1,238 +1,254 @@ -/* - * 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.util; - -import android.text.TextUtils; -import com.arialyy.aria.core.download.DTaskWrapper; -import com.arialyy.aria.core.download.DownloadEntity; -import com.arialyy.aria.core.inf.AbsTaskWrapper; -import com.arialyy.aria.core.upload.UTaskWrapper; -import com.arialyy.aria.core.upload.UploadEntity; -import java.io.File; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Created by Lyy on 2016/9/23. - * 检查帮助类 - */ -public class CheckUtil { - private static final String TAG = "CheckUtil"; - - /** - * 判空 - */ - public static void checkNull(Object obj) { - if (obj == null) throw new IllegalArgumentException("不能传入空对象"); - } - - /** - * 检查分页数据,需要查询的页数,从1开始,如果page小于1 或 num 小于1,则抛出{@link NullPointerException} - * @param page 从1 开始 - * @param num 每页数量 - */ - public static void checkPageParams(int page, int num){ - if (page < 1 || num < 1) throw new NullPointerException("page和num不能小于1"); - } - - /** - * 检查sql的expression是否合法 - */ - public static void checkSqlExpression(String... expression) { - if (expression.length == 0) { - throw new IllegalArgumentException("sql语句表达式不能为null"); - } - if (expression.length == 1) { - throw new IllegalArgumentException("表达式需要写入参数"); - } - String where = expression[0]; - if (!where.contains("?")) { - throw new IllegalArgumentException("请在where语句的'='后编写?"); - } - Pattern pattern = Pattern.compile("\\?"); - Matcher matcher = pattern.matcher(where); - int count = 0; - while (matcher.find()) { - count++; - } - if (count < expression.length - 1) { - throw new IllegalArgumentException("条件语句的?个数不能小于参数个数"); - } - if (count > expression.length - 1) { - throw new IllegalArgumentException("条件语句的?个数不能大于参数个数"); - } - } - - /** - * 检查下载实体 - */ - public static void checkDownloadEntity(DownloadEntity entity) { - checkUrlInvalidThrow(entity.getUrl()); - entity.setUrl(entity.getUrl()); - checkPath(entity.getDownloadPath()); - } - - /** - * 检测下载链接是否为null - */ - public static void checkPath(String path) { - if (TextUtils.isEmpty(path)) { - throw new IllegalArgumentException("保存路径不能为null"); - } - } - - /** - * 检测url是否合法,如果url不合法,将抛异常 - */ - public static void checkUrlInvalidThrow(String url) { - if (TextUtils.isEmpty(url)) { - throw new IllegalArgumentException("url不能为null"); - } else if (!url.startsWith("http") && !url.startsWith("ftp")) { - throw new IllegalArgumentException("url错误"); - } - int index = url.indexOf("://"); - if (index == -1) { - throw new IllegalArgumentException("url不合法"); - } - } - - /** - * 检测url是否合法 - * - * @return {@code true} 合法,{@code false} 非法 - */ - public static boolean checkUrl(String url) { - if (TextUtils.isEmpty(url)) { - ALog.e(TAG, "url不能为null"); - return false; - } else if (!url.startsWith("http") && !url.startsWith("ftp")) { - ALog.e(TAG, "url【" + url + "】错误"); - return false; - } - int index = url.indexOf("://"); - if (index == -1) { - ALog.e(TAG, "url【" + url + "】不合法"); - } - return true; - } - - /** - * 检测下载链接组是否为null - */ - public static void checkDownloadUrls(List urls) { - if (urls == null || urls.isEmpty()) { - throw new IllegalArgumentException("链接组不能为null"); - } - } - - /** - * 检查下载任务组保存路径 - */ - public static void checkDownloadPaths(List paths) { - if (paths == null || paths.isEmpty()) { - throw new IllegalArgumentException("链接保存路径不能为null"); - } - } - - /** - * 检测上传地址是否为null - */ - public static void checkUploadPath(String uploadPath) { - if (TextUtils.isEmpty(uploadPath)) { - throw new IllegalArgumentException("上传地址不能为null"); - } - File file = new File(uploadPath); - if (!file.exists()) { - throw new IllegalArgumentException("上传文件不存在"); - } - } - - /** - * 检查任务实体 - */ - public static void checkTaskEntity(AbsTaskWrapper entity) { - if (entity instanceof DTaskWrapper) { - checkDownloadTaskEntity(((DTaskWrapper) entity).getEntity()); - } else if (entity instanceof UTaskWrapper) { - checkUploadTaskEntity(((UTaskWrapper) entity).getEntity()); - } - } - - /** - * 检查命令实体 - * - * @param checkType 删除命令和停止命令不需要检查下载链接和保存路径 - * @return {@code false}实体无效 - */ - public static boolean checkCmdEntity(AbsTaskWrapper entity, boolean checkType) { - boolean b = false; - if (entity instanceof DTaskWrapper) { - DownloadEntity entity1 = ((DTaskWrapper) entity).getEntity(); - if (entity1 == null) { - ALog.e(TAG, "下载实体不能为空"); - } else if (checkType && TextUtils.isEmpty(entity1.getUrl())) { - ALog.e(TAG, "下载链接不能为空"); - } else if (checkType && TextUtils.isEmpty(entity1.getDownloadPath())) { - ALog.e(TAG, "保存路径不能为空"); - } else { - b = true; - } - } else if (entity instanceof UTaskWrapper) { - UploadEntity entity1 = ((UTaskWrapper) entity).getEntity(); - if (entity1 == null) { - ALog.e(TAG, "上传实体不能为空"); - } else if (TextUtils.isEmpty(entity1.getFilePath())) { - ALog.e(TAG, "上传文件路径不能为空"); - } else { - b = true; - } - } - return b; - } - - /** - * 检查上传实体是否合法 - */ - private static void checkUploadTaskEntity(UploadEntity entity) { - if (entity == null) { - throw new NullPointerException("上传实体不能为空"); - } else if (TextUtils.isEmpty(entity.getFilePath())) { - throw new IllegalArgumentException("上传文件路径不能为空"); - } else if (TextUtils.isEmpty(entity.getFileName())) { - throw new IllegalArgumentException("上传文件名不能为空"); - } - } - - /** - * 检测下载实体是否合法 - * 合法(true) - * - * @param entity 下载实体 - */ - private static void checkDownloadTaskEntity(DownloadEntity entity) { - if (entity == null) { - throw new NullPointerException("下载实体不能为空"); - } else if (TextUtils.isEmpty(entity.getUrl())) { - throw new IllegalArgumentException("下载链接不能为空"); - } else if (TextUtils.isEmpty(entity.getFileName())) { - throw new NullPointerException("文件名不能为null"); - } else if (TextUtils.isEmpty(entity.getDownloadPath())) { - throw new NullPointerException("文件保存路径不能为null"); - } - } +/* + * 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.util; + +import android.text.TextUtils; +import com.arialyy.aria.core.download.DTaskWrapper; +import com.arialyy.aria.core.download.DownloadEntity; +import com.arialyy.aria.core.inf.AbsTaskWrapper; +import com.arialyy.aria.core.upload.UTaskWrapper; +import com.arialyy.aria.core.upload.UploadEntity; +import com.arialyy.aria.exception.ParamException; +import java.io.File; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Created by Lyy on 2016/9/23. + * 检查帮助类 + */ +public class CheckUtil { + private static final String TAG = "CheckUtil"; + + /** + * 检查ftp上传路径,如果ftp上传路径为空,抛出空指针异常 + * 如果ftp上传路径不是以"ftp"或"sftp",抛出参数异常 + * + * @param ftpUrl ftp上传路径 + */ + public static void checkFtpUploadUrl(String ftpUrl) { + if (TextUtils.isEmpty(ftpUrl)) { + throw new ParamException("ftp上传路径为空"); + } else if (!ftpUrl.startsWith("ftp") || !ftpUrl.startsWith("sftp")) { + throw new ParamException("ftp上传路径无效"); + } + } + + /** + * 判空 + */ + public static void checkNull(Object obj) { + if (obj == null) throw new IllegalArgumentException("不能传入空对象"); + } + + /** + * 检查分页数据,需要查询的页数,从1开始,如果page小于1 或 num 小于1,则抛出{@link NullPointerException} + * + * @param page 从1 开始 + * @param num 每页数量 + */ + public static void checkPageParams(int page, int num) { + if (page < 1 || num < 1) throw new NullPointerException("page和num不能小于1"); + } + + /** + * 检查sql的expression是否合法 + */ + public static void checkSqlExpression(String... expression) { + if (expression.length == 0) { + throw new IllegalArgumentException("sql语句表达式不能为null"); + } + if (expression.length == 1) { + throw new IllegalArgumentException("表达式需要写入参数"); + } + String where = expression[0]; + if (!where.contains("?")) { + throw new IllegalArgumentException("请在where语句的'='后编写?"); + } + Pattern pattern = Pattern.compile("\\?"); + Matcher matcher = pattern.matcher(where); + int count = 0; + while (matcher.find()) { + count++; + } + if (count < expression.length - 1) { + throw new IllegalArgumentException("条件语句的?个数不能小于参数个数"); + } + if (count > expression.length - 1) { + throw new IllegalArgumentException("条件语句的?个数不能大于参数个数"); + } + } + + /** + * 检查下载实体 + */ + public static void checkDownloadEntity(DownloadEntity entity) { + checkUrlInvalidThrow(entity.getUrl()); + entity.setUrl(entity.getUrl()); + checkPath(entity.getDownloadPath()); + } + + /** + * 检测下载链接是否为null + */ + public static void checkPath(String path) { + if (TextUtils.isEmpty(path)) { + throw new IllegalArgumentException("保存路径不能为null"); + } + } + + /** + * 检测url是否合法,如果url不合法,将抛异常 + */ + public static void checkUrlInvalidThrow(String url) { + if (TextUtils.isEmpty(url)) { + throw new IllegalArgumentException("url不能为null"); + } else if (!url.startsWith("http") && !url.startsWith("ftp")) { + throw new IllegalArgumentException("url错误"); + } + int index = url.indexOf("://"); + if (index == -1) { + throw new IllegalArgumentException("url不合法"); + } + } + + /** + * 检测url是否合法 + * + * @return {@code true} 合法,{@code false} 非法 + */ + public static boolean checkUrl(String url) { + if (TextUtils.isEmpty(url)) { + ALog.e(TAG, "url不能为null"); + return false; + } else if (!url.startsWith("http") && !url.startsWith("ftp")) { + ALog.e(TAG, "url【" + url + "】错误"); + return false; + } + int index = url.indexOf("://"); + if (index == -1) { + ALog.e(TAG, "url【" + url + "】不合法"); + } + return true; + } + + /** + * 检测下载链接组是否为null + */ + public static void checkDownloadUrls(List urls) { + if (urls == null || urls.isEmpty()) { + throw new IllegalArgumentException("链接组不能为null"); + } + } + + /** + * 检查下载任务组保存路径 + */ + public static void checkDownloadPaths(List paths) { + if (paths == null || paths.isEmpty()) { + throw new IllegalArgumentException("链接保存路径不能为null"); + } + } + + /** + * 检测上传地址是否为null + */ + public static void checkUploadPath(String uploadPath) { + if (TextUtils.isEmpty(uploadPath)) { + throw new IllegalArgumentException("上传地址不能为null"); + } + File file = new File(uploadPath); + if (!file.exists()) { + throw new IllegalArgumentException("上传文件不存在"); + } + } + + /** + * 检查任务实体 + */ + public static void checkTaskEntity(AbsTaskWrapper entity) { + if (entity instanceof DTaskWrapper) { + checkDownloadTaskEntity(((DTaskWrapper) entity).getEntity()); + } else if (entity instanceof UTaskWrapper) { + checkUploadTaskEntity(((UTaskWrapper) entity).getEntity()); + } + } + + /** + * 检查命令实体 + * + * @param checkType 删除命令和停止命令不需要检查下载链接和保存路径 + * @return {@code false}实体无效 + */ + public static boolean checkCmdEntity(AbsTaskWrapper entity, boolean checkType) { + boolean b = false; + if (entity instanceof DTaskWrapper) { + DownloadEntity entity1 = ((DTaskWrapper) entity).getEntity(); + if (entity1 == null) { + ALog.e(TAG, "下载实体不能为空"); + } else if (checkType && TextUtils.isEmpty(entity1.getUrl())) { + ALog.e(TAG, "下载链接不能为空"); + } else if (checkType && TextUtils.isEmpty(entity1.getDownloadPath())) { + ALog.e(TAG, "保存路径不能为空"); + } else { + b = true; + } + } else if (entity instanceof UTaskWrapper) { + UploadEntity entity1 = ((UTaskWrapper) entity).getEntity(); + if (entity1 == null) { + ALog.e(TAG, "上传实体不能为空"); + } else if (TextUtils.isEmpty(entity1.getFilePath())) { + ALog.e(TAG, "上传文件路径不能为空"); + } else { + b = true; + } + } + return b; + } + + /** + * 检查上传实体是否合法 + */ + private static void checkUploadTaskEntity(UploadEntity entity) { + if (entity == null) { + throw new NullPointerException("上传实体不能为空"); + } else if (TextUtils.isEmpty(entity.getFilePath())) { + throw new IllegalArgumentException("上传文件路径不能为空"); + } else if (TextUtils.isEmpty(entity.getFileName())) { + throw new IllegalArgumentException("上传文件名不能为空"); + } + } + + /** + * 检测下载实体是否合法 + * 合法(true) + * + * @param entity 下载实体 + */ + private static void checkDownloadTaskEntity(DownloadEntity entity) { + if (entity == null) { + throw new NullPointerException("下载实体不能为空"); + } else if (TextUtils.isEmpty(entity.getUrl())) { + throw new IllegalArgumentException("下载链接不能为空"); + } else if (TextUtils.isEmpty(entity.getFileName())) { + throw new NullPointerException("文件名不能为null"); + } else if (TextUtils.isEmpty(entity.getDownloadPath())) { + throw new NullPointerException("文件保存路径不能为null"); + } + } } \ No newline at end of file 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 5a67c6a6..d19c0908 100644 --- a/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java @@ -1,1203 +1,1233 @@ -/* - * 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.util; - -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.net.Uri; -import android.os.Environment; -import android.os.StatFs; -import android.text.TextUtils; -import android.util.Base64; -import com.arialyy.aria.core.AriaManager; -import com.arialyy.aria.core.FtpUrlEntity; -import com.arialyy.aria.core.command.ICmd; -import com.arialyy.aria.core.command.group.AbsGroupCmd; -import com.arialyy.aria.core.command.group.GroupCmdFactory; -import com.arialyy.aria.core.command.normal.AbsNormalCmd; -import com.arialyy.aria.core.command.normal.NormalCmdFactory; -import com.arialyy.aria.core.common.AbsFileer; -import com.arialyy.aria.core.common.TaskRecord; -import com.arialyy.aria.core.download.DownloadEntity; -import com.arialyy.aria.core.download.DownloadGroupEntity; -import com.arialyy.aria.core.inf.AbsGroupTaskWrapper; -import com.arialyy.aria.core.inf.AbsNormalEntity; -import com.arialyy.aria.core.inf.AbsTaskWrapper; -import com.arialyy.aria.core.upload.UploadEntity; -import com.arialyy.aria.orm.DbEntity; -import dalvik.system.DexFile; -import java.io.File; -import java.io.FileFilter; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.Field; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.net.URLEncoder; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Created by lyy on 2016/1/22. 通用工具 - */ -public class CommonUtil { - private static final String TAG = "CommonUtil"; - - /** - * 删除文件 - * @param path 文件路径 - * @return {@code true}删除成功、{@code false}删除失败 - */ - public static boolean deleteFile(String path){ - if (TextUtils.isEmpty(path)){ - ALog.e(TAG, "删除文件失败,路径为空"); - return false; - } - File file = new File(path); - if (file.exists()) { - final File to = new File(file.getAbsolutePath() + System.currentTimeMillis()); - if (file.renameTo(to)) { - return to.delete(); - } else { - return file.delete(); - } - } - return false; - } - - /** - * 将对象写入文件 - * - * @param filePath 文件路径 - * @param data data数据必须实现{@link Serializable}接口 - */ - public static void writeObjToFile(String filePath, Object data) { - if (!(data instanceof Serializable)) { - ALog.e(TAG, "对象写入文件失败,data数据必须实现Serializable接口"); - return; - } - FileOutputStream ops = null; - try { - if (!createFile(filePath)) { - return; - } - ops = new FileOutputStream(filePath); - ObjectOutputStream oops = new ObjectOutputStream(ops); - oops.writeObject(data); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - if (ops != null) { - try { - ops.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - } - - /** - * 从文件中读取对象 - * - * @param filePath 文件路径 - * @return 如果读取成功,返回相应的Obj对象,读取失败,返回null - */ - public static Object readObjFromFile(String filePath) { - if (TextUtils.isEmpty(filePath)) { - ALog.e(TAG, "文件路径为空"); - return null; - } - File file = new File(filePath); - if (!file.exists()) { - ALog.e(TAG, String.format("文件【%s】不存在", filePath)); - return null; - } - FileInputStream fis = null; - try { - fis = new FileInputStream(filePath); - ObjectInputStream oois = new ObjectInputStream(fis); - return oois.readObject(); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } finally { - if (fis != null) { - try { - fis.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - return null; - } - - /** - * 获取分块文件的快大小 - * - * @param fileLen 文件总长度 - * @param blockId 分块id - * @param blockNum 分块数量 - * @return 分块长度 - */ - public static long getBlockLen(long fileLen, int blockId, int blockNum) { - final long averageLen = fileLen / blockNum; - return blockId == blockNum - 1 ? (fileLen - blockId * averageLen) : averageLen; - } - - /** - * 检查SD内存空间是否充足 - * - * @param filePath 文件保存路径 - * @param fileSize 文件大小 - * @return {@code false} 内存空间不足,{@code true}内存空间足够 - */ - public static boolean checkSDMemorySpace(String filePath, long fileSize) { - List dirs = FileUtil.getSDPathList(AriaManager.APP); - if (dirs == null || dirs.isEmpty()) { - return true; - } - for (String path : dirs) { - if (filePath.contains(path)) { - if (fileSize > 0 && fileSize > getAvailableExternalMemorySize(path)) { - return false; - } - } - } - return true; - } - - /** - * sdcard 可用大小 - * - * @param sdcardPath sdcard 根路径 - * @return 单位为:byte - */ - public static long getAvailableExternalMemorySize(String sdcardPath) { - StatFs stat = new StatFs(sdcardPath); - long blockSize = stat.getBlockSize(); - long availableBlocks = stat.getAvailableBlocks(); - return availableBlocks * blockSize; - } - - /** - * sdcard 总大小 - * - * @param sdcardPath sdcard 根路径 - * @return 单位为:byte - */ - public static long getTotalExternalMemorySize(String sdcardPath) { - StatFs stat = new StatFs(sdcardPath); - long blockSize = stat.getBlockSize(); - long totalBlocks = stat.getBlockCount(); - return totalBlocks * blockSize; - } - - /** - * 获取某包下所有类 - * - * @param className 过滤的类名 - * @return 类的完整名称 - */ - public static List getPkgClassNames(Context context, String className) { - List classNameList = new ArrayList<>(); - String pPath = context.getPackageCodePath(); - File dir = new File(pPath).getParentFile(); - String[] paths = dir.list(); - if (paths == null) { - classNameList.addAll(getPkgClassName(pPath, className)); - } else { - String dPath = dir.getPath(); - for (String path : dir.list()) { - String fPath = dPath + "/" + path; - if (!fPath.endsWith(".apk")) { - continue; - } - classNameList.addAll(getPkgClassName(fPath, className)); - } - } - return classNameList; - } - - /** - * 获取指定包名下的所有类 - * - * @param path dex路径 - * @param filterClass 需要过滤的类 - */ - public static List getPkgClassName(String path, String filterClass) { - List list = new ArrayList<>(); - try { - File file = new File(path); - if (!file.exists()) { - ALog.w(TAG, String.format("路径【%s】下的Dex文件不存在", path)); - return list; - } - - DexFile df = new DexFile(path);//通过DexFile查找当前的APK中可执行文件 - Enumeration enumeration = df.entries();//获取df中的元素 这里包含了所有可执行的类名 该类名包含了包名+类名的方式 - while (enumeration.hasMoreElements()) { - String _className = enumeration.nextElement(); - if (!_className.contains(filterClass)) { - continue; - } - if (_className.contains(filterClass)) { - list.add(_className); - } - } - df.close(); - } catch (IOException e) { - e.printStackTrace(); - } - return list; - } - - /** - * 拦截window.location.replace数据 - * - * @return 重定向url - */ - public static String getWindowReplaceUrl(String text) { - if (TextUtils.isEmpty(text)) { - ALog.e(TAG, "拦截数据为null"); - return null; - } - String reg = Regular.REG_WINLOD_REPLACE; - Pattern p = Pattern.compile(reg); - Matcher m = p.matcher(text); - if (m.find()) { - String s = m.group(); - s = s.substring(9, s.length() - 2); - return s; - } - return null; - } - - /** - * 获取sdcard app的缓存目录 - * - * @return "/mnt/sdcard/Android/data/{package_name}/files/" - */ - public static String getAppPath(Context context) { - //判断是否存在sd卡 - boolean sdExist = android.os.Environment.MEDIA_MOUNTED.equals( - android.os.Environment.getExternalStorageState()); - if (!sdExist) { - return null; - } else { - //获取sd卡路径 - File file = context.getExternalFilesDir(null); - String dir; - if (file != null) { - dir = file.getPath() + "/"; - } else { - dir = Environment.getExternalStorageDirectory().getPath() - + "/Android/data/" - + context.getPackageName() - + "/files/"; - } - return dir; - } - } - - /** - * 获取map泛型类型 - * - * @param map list类型字段 - * @return 泛型类型 - */ - public static Class[] getMapParamType(Field map) { - Class type = map.getType(); - if (!type.isAssignableFrom(Map.class)) { - ALog.d(TAG, "字段类型不是Map"); - return null; - } - - Type fc = map.getGenericType(); - - if (fc == null) { - ALog.d(TAG, "该字段没有泛型参数"); - return null; - } - - if (fc instanceof ParameterizedType) { - ParameterizedType pt = (ParameterizedType) fc; - Type[] types = pt.getActualTypeArguments(); - Class[] clazz = new Class[2]; - clazz[0] = (Class) types[0]; - clazz[1] = (Class) types[1]; - return clazz; - } - return null; - } - - /** - * 获取list泛型类型 - * - * @param list list类型字段 - * @return 泛型类型 - */ - - public static Class getListParamType(Field list) { - Class type = list.getType(); - if (!type.isAssignableFrom(List.class)) { - ALog.d(TAG, "字段类型不是List"); - return null; - } - - Type fc = list.getGenericType(); // 关键的地方,如果是List类型,得到其Generic的类型 - - if (fc == null) { - ALog.d(TAG, "该字段没有泛型参数"); - return null; - } - - if (fc instanceof ParameterizedType) { //如果是泛型参数的类型 - ParameterizedType pt = (ParameterizedType) fc; - return (Class) pt.getActualTypeArguments()[0]; //得到泛型里的class类型对象。 - } - return null; - } - - /** - * 创建文件名,如果url链接有后缀名,则使用url中的后缀名 - * - * @return url 的 hashKey - */ - public static String createFileName(String url) { - int end = url.indexOf("?"); - String tempUrl, fileName = ""; - if (end > 0) { - tempUrl = url.substring(0, end); - int tempEnd = tempUrl.lastIndexOf("/"); - if (tempEnd > 0) { - fileName = tempUrl.substring(tempEnd + 1, tempUrl.length()); - } - } else { - int tempEnd = url.lastIndexOf("/"); - if (tempEnd > 0) { - fileName = url.substring(tempEnd + 1, url.length()); - } - } - if (TextUtils.isEmpty(fileName)) { - fileName = CommonUtil.keyToHashKey(url); - } - return fileName; - } - - /** - * 分割获取url,协议,ip/域名,端口,内容 - * - * @param url 输入的url{@code String url = "ftp://z:z@dygod18.com:21211/[电影天堂www.dy2018.com]猩球崛起3:终极之战BD国英双语中英双字.mkv";} - */ - public static FtpUrlEntity getFtpUrlInfo(String url) { - Uri uri = Uri.parse(url); - - String userInfo = uri.getUserInfo(), remotePath = uri.getPath(); - ALog.d(TAG, - String.format("scheme = %s, user = %s, host = %s, port = %s, path = %s", uri.getScheme(), - userInfo, uri.getHost(), uri.getPort(), remotePath)); - - FtpUrlEntity entity = new FtpUrlEntity(); - entity.url = url; - entity.hostName = uri.getHost(); - entity.port = uri.getPort() == -1 ? "21" : String.valueOf(uri.getPort()); - if (!TextUtils.isEmpty(userInfo)) { - String[] temp = userInfo.split(":"); - if (temp.length == 2) { - entity.user = temp[0]; - entity.password = temp[1]; - } else { - entity.user = userInfo; - } - } - entity.scheme = uri.getScheme(); - entity.remotePath = TextUtils.isEmpty(remotePath) ? "/" : remotePath; - return entity; - } - - /** - * 转换Url - * - * @param url 原地址 - * @return 转换后的地址 - */ - public static String convertUrl(String url) { - Uri uri = Uri.parse(url); - url = uri.toString(); - if (hasDoubleCharacter(url)) { - //预先处理空格,URLEncoder只会把空格转换为+ - url = url.replaceAll(" ", "%20"); - //匹配双字节字符(包括汉字在内) - String regex = Regular.REG_DOUBLE_CHAR_AND_SPACE; - Pattern p = Pattern.compile(regex); - Matcher m = p.matcher(url); - Set strs = new HashSet<>(); - while (m.find()) { - strs.add(m.group()); - } - try { - for (String str : strs) { - url = url.replaceAll(str, URLEncoder.encode(str, "UTF-8")); - } - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - } - return url; - } - - /** - * 判断是否有双字节字符(包括汉字在内) 和空格、制表符、回车 - * - * @param chineseStr 需要进行判断的字符串 - * @return {@code true}有双字节字符,{@code false} 无双字节字符 - */ - public static boolean hasDoubleCharacter(String chineseStr) { - char[] charArray = chineseStr.toCharArray(); - for (char aCharArray : charArray) { - if (((aCharArray >= 0x0391) && (aCharArray <= 0xFFE5)) || (aCharArray == 0x0d) || (aCharArray - == 0x0a) || (aCharArray == 0x20)) { - return true; - } - } - return false; - } - - /** - * base64 解密字符串 - * - * @param str 被加密的字符串 - * @return 解密后的字符串 - */ - public static String decryptBASE64(String str) { - return new String(Base64.decode(str.getBytes(), Base64.DEFAULT)); - } - - /** - * base64 加密字符串 - * - * @param str 需要加密的字符串 - * @return 加密后的字符串 - */ - public static String encryptBASE64(String str) { - return Base64.encodeToString(str.getBytes(), Base64.DEFAULT); - } - - /** - * 字符串编码转换 - */ - public static String strCharSetConvert(String oldStr, String charSet) { - try { - return new String(oldStr.getBytes(), charSet); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - return null; - } - - /** - * 根据下载任务组的url创建key - * - * @return urls 为 null 或者 size为0,返回"" - */ - public static String getMd5Code(List urls) { - if (urls == null || urls.size() < 1) return ""; - String md5 = ""; - StringBuilder sb = new StringBuilder(); - for (String url : urls) { - sb.append(url); - } - try { - MessageDigest md = MessageDigest.getInstance("MD5"); - md.update(sb.toString().getBytes()); - md5 = new BigInteger(1, md.digest()).toString(16); - } catch (NoSuchAlgorithmException e) { - ALog.e(TAG, e.getMessage()); - } - return md5; - } - - /** - * 获取字符串的md5 - * - * @return 字符串为空或获取md5失败,则返回"" - */ - public static String getStrMd5(String str) { - if (TextUtils.isEmpty(str)) return ""; - try { - MessageDigest md = MessageDigest.getInstance("MD5"); - md.update(str.getBytes()); - return new BigInteger(1, md.digest()).toString(16); - } catch (NoSuchAlgorithmException e) { - ALog.e(TAG, e.getMessage()); - } - return ""; - } - - /** - * 删除任务组记录 - * - * @param removeFile {@code true} 不仅删除任务数据库记录,还会删除已经删除完成的文件 {@code false}如果任务已经完成,只删除任务数据库记录 - */ - public static void delGroupTaskRecord(boolean removeFile, DownloadGroupEntity groupEntity) { - if (groupEntity == null) { - ALog.e(TAG, "删除下载任务组记录失败,任务组实体为null"); - return; - } - List records = - DbEntity.findDatas(TaskRecord.class, "dGroupHash=?", groupEntity.getGroupHash()); - - if (records == null || records.isEmpty()) { - ALog.w(TAG, "组任务记录删除失败,记录为null"); - } else { - for (TaskRecord record : records) { - // 删除分块文件 - if (record.isBlock) { - for (int i = 0, len = record.threadNum; i < len; i++) { - File partFile = new File(String.format(AbsFileer.SUB_PATH, record.filePath, i)); - if (partFile.exists()) { - partFile.delete(); - } - } - } - record.deleteData(); - } - } - - List subs = groupEntity.getSubEntities(); - if (subs != null) { - for (DownloadEntity sub : subs) { - File file = new File(sub.getDownloadPath()); - if (file.exists() && (removeFile || !sub.isComplete())) { - file.delete(); - } - } - } - - if (!TextUtils.isEmpty(groupEntity.getDirPath())) { - File dir = new File(groupEntity.getDirPath()); - if (dir.exists() && (removeFile || !groupEntity.isComplete())) { - dir.delete(); - } - groupEntity.deleteData(); - } - } - - /** - * 删除任务记录 - * - * @param removeFile {@code true} 不仅删除任务数据库记录,还会删除已经完成的文件 {@code false}如果任务已经完成,只删除任务数据库记录 - */ - public static void delTaskRecord(TaskRecord record, boolean removeFile, AbsNormalEntity dEntity) { - if (dEntity == null) return; - File file; - if (dEntity instanceof DownloadEntity) { - file = new File(((DownloadEntity) dEntity).getDownloadPath()); - } else if (dEntity instanceof UploadEntity) { - file = new File(((UploadEntity) dEntity).getFilePath()); - } else { - ALog.w(TAG, "删除记录失败,未知类型"); - return; - } - if (removeFile || !dEntity.isComplete()) { - // 删除分块文件 - if (record.isBlock) { - for (int i = 0, len = record.threadNum; i < len; i++) { - File partFile = new File(String.format(AbsFileer.SUB_PATH, record.filePath, i)); - if (partFile.exists()) { - partFile.delete(); - } - } - } - if (file.exists()) { - file.delete(); - } - } - - if (record != null) { - record.deleteData(); - } - //下载任务实体和下载实体为一对一关系,下载实体删除,任务实体自动删除 - dEntity.deleteData(); - } - - /** - * 删除任务记录,默认删除文件 - * - * @param filePath 文件路径 - * @param removeFile {@code true} 不仅删除任务数据库记录,还会删除已经删除完成的文件 {@code false}如果任务已经完成,只删除任务数据库记录 - * @param type {@code 1}下载任务的记录,{@code 2} 上传任务的记录 {@code false}如果任务已经完成,只删除任务数据库记录 - */ - public static void delTaskRecord(String filePath, int type, boolean removeFile) { - if (TextUtils.isEmpty(filePath)) { - throw new NullPointerException("删除记录失败,文件路径为空"); - } - if (type != 1 && type != 2) { - throw new IllegalArgumentException("任务记录类型错误"); - } - TaskRecord record = DbEntity.findFirst(TaskRecord.class, "filePath=?", filePath); - File file = new File(filePath); - if (record == null) { - ALog.w(TAG, "记录为空"); - } else { - // 删除分块文件 - if (record.isBlock) { - for (int i = 0, len = record.threadNum; i < len; i++) { - File partFile = new File(String.format(AbsFileer.SUB_PATH, record.filePath, i)); - if (partFile.exists()) { - partFile.delete(); - } - } - } - - record.deleteData(); - } - if (file.exists() && removeFile) { - file.delete(); - } - //下载任务实体和下载实体为一对一关系,下载实体删除,任务实体自动删除 - if (type == 1) { - DbEntity.deleteData(DownloadEntity.class, "downloadPath=?", filePath); - } else { - DbEntity.deleteData(UploadEntity.class, "filePath=?", filePath); - } - } - - /** - * 删除任务记录,默认删除文件 - * - * @param filePath 文件路径 - * @param type {@code 1}下载任务的记录,{@code 2} 上传任务的记录 {@code false}如果任务已经完成,只删除任务数据库记录 - */ - public static void delTaskRecord(String filePath, int type) { - delTaskRecord(filePath, type, false); - } - - /** - * 获取CPU核心数 - */ - public static int getCoresNum() { - //Private Class to display only CPU devices in the directory listing - class CpuFilter implements FileFilter { - @Override public boolean accept(File pathname) { - //Check if filename is "cpu", followed by a single digit number - return Pattern.matches("cpu[0-9]", pathname.getName()); - } - } - - try { - //Get directory containing CPU info - File dir = new File("/sys/devices/system/cpu/"); - //Filter to only list the devices we care about - File[] files = dir.listFiles(new CpuFilter()); - ALog.d(TAG, "CPU Count: " + files.length); - //Return the number of cores (virtual CPU devices) - return files.length; - } catch (Exception e) { - //Print exception - ALog.d(TAG, "CPU Count: Failed."); - e.printStackTrace(); - //Default to return 1 core - return 1; - } - } - - /** - * 通过流创建文件 - */ - public static void createFileFormInputStream(InputStream is, String path) { - try { - FileOutputStream fos = new FileOutputStream(path); - byte[] buf = new byte[1024]; - int len; - while ((len = is.read(buf)) > 0) { - fos.write(buf, 0, len); - } - is.close(); - fos.flush(); - fos.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * 校验文件MD5码 - */ - public static boolean checkMD5(String md5, File updateFile) { - if (TextUtils.isEmpty(md5) || updateFile == null) { - ALog.e(TAG, "MD5 string empty or updateFile null"); - return false; - } - - String calculatedDigest = getFileMD5(updateFile); - if (calculatedDigest == null) { - ALog.e(TAG, "calculatedDigest null"); - return false; - } - return calculatedDigest.equalsIgnoreCase(md5); - } - - /** - * 校验文件MD5码 - */ - public static boolean checkMD5(String md5, InputStream is) { - if (TextUtils.isEmpty(md5) || is == null) { - ALog.e(TAG, "MD5 string empty or updateFile null"); - return false; - } - - String calculatedDigest = getFileMD5(is); - if (calculatedDigest == null) { - ALog.e(TAG, "calculatedDigest null"); - return false; - } - return calculatedDigest.equalsIgnoreCase(md5); - } - - /** - * 获取文件MD5码 - */ - public static String getFileMD5(File updateFile) { - InputStream is; - try { - is = new FileInputStream(updateFile); - } catch (FileNotFoundException e) { - ALog.e(TAG, e); - return null; - } - - return getFileMD5(is); - } - - /** - * 获取文件MD5码 - */ - public static String getFileMD5(InputStream is) { - MessageDigest digest; - try { - digest = MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException e) { - ALog.e(TAG, e); - return null; - } - - byte[] buffer = new byte[8192]; - int read; - try { - while ((read = is.read(buffer)) > 0) { - digest.update(buffer, 0, read); - } - byte[] md5sum = digest.digest(); - BigInteger bigInt = new BigInteger(1, md5sum); - String output = bigInt.toString(16); - // Fill to 32 chars - output = String.format("%32s", output).replace(' ', '0'); - return output; - } catch (IOException e) { - throw new RuntimeException("Unable to process file for MD5", e); - } finally { - try { - is.close(); - } catch (IOException e) { - ALog.e(TAG, e); - } - } - } - - /** - * 创建任务命令 - * - * @param taskType {@link ICmd#TASK_TYPE_DOWNLOAD}、{@link ICmd#TASK_TYPE_DOWNLOAD_GROUP}、{@link - * ICmd#TASK_TYPE_UPLOAD} - */ - public static AbsNormalCmd createNormalCmd(T entity, int cmd, - int taskType) { - return NormalCmdFactory.getInstance().createCmd(entity, cmd, taskType); - } - - /** - * 创建任务组命令 - * - * @param childUrl 子任务url - */ - public static AbsGroupCmd createGroupCmd(String target, T entity, - int cmd, String childUrl) { - return GroupCmdFactory.getInstance().createCmd(target, entity, cmd, childUrl); - } - - /** - * 创建隐性的Intent - */ - public static Intent createIntent(String packageName, String action) { - Uri.Builder builder = new Uri.Builder(); - builder.scheme(packageName); - Uri uri = builder.build(); - Intent intent = new Intent(action); - intent.setData(uri); - return intent; - } - - /** - * 存储字符串到配置文件 - * - * @param preName 配置文件名 - * @param key 存储的键值 - * @param value 需要存储的字符串 - * @return 成功标志 - */ - public static Boolean putString(String preName, Context context, String key, String value) { - SharedPreferences pre = context.getSharedPreferences(preName, Context.MODE_PRIVATE); - SharedPreferences.Editor editor = pre.edit(); - editor.putString(key, value); - return editor.commit(); - } - - /** - * 从配置文件读取字符串 - * - * @param preName 配置文件名 - * @param key 字符串键值 - * @return 键值对应的字符串, 默认返回"" - */ - public static String getString(String preName, Context context, String key) { - SharedPreferences pre = context.getSharedPreferences(preName, Context.MODE_PRIVATE); - return pre.getString(key, ""); - } - - /** - * 获取所有字段,包括父类的字段 - */ - public static List getAllFields(Class clazz) { - List fields = new ArrayList<>(); - Class personClazz = clazz.getSuperclass(); - if (personClazz != null) { - Class rootClazz = personClazz.getSuperclass(); - if (rootClazz != null) { - Collections.addAll(fields, rootClazz.getDeclaredFields()); - } - Collections.addAll(fields, personClazz.getDeclaredFields()); - } - Collections.addAll(fields, clazz.getDeclaredFields()); - return fields; - } - - /** - * 获取当前类里面的所在字段 - */ - public static Field[] getFields(Class clazz) { - Field[] fields = null; - fields = clazz.getDeclaredFields(); - if (fields == null || fields.length == 0) { - Class superClazz = clazz.getSuperclass(); - if (superClazz != null) { - fields = getFields(superClazz); - } - } - return fields; - } - - /** - * 获取类里面的指定对象,如果该类没有则从父类查询 - */ - public static Field getField(Class clazz, String name) { - Field field = null; - try { - field = clazz.getDeclaredField(name); - } catch (NoSuchFieldException e) { - try { - field = clazz.getField(name); - } catch (NoSuchFieldException e1) { - if (clazz.getSuperclass() == null) { - return field; - } else { - field = getField(clazz.getSuperclass(), name); - } - } - } - if (field != null) { - field.setAccessible(true); - } - return field; - } - - /** - * 字符串转hashcode - */ - public static int keyToHashCode(String str) { - int total = 0; - for (int i = 0; i < str.length(); i++) { - char ch = str.charAt(i); - if (ch == '-') ch = (char) 28; // does not contain the same last 5 bits as any letter - if (ch == '\'') ch = (char) 29; // nor this - total = (total * 33) + (ch & 0x1F); - } - return total; - } - - /** - * 将key转换为16进制码 - * - * @param key 缓存的key - * @return 转换后的key的值, 系统便是通过该key来读写缓存 - */ - public static String keyToHashKey(String key) { - String cacheKey; - try { - final MessageDigest mDigest = MessageDigest.getInstance("MD5"); - mDigest.update(key.getBytes()); - cacheKey = bytesToHexString(mDigest.digest()); - } catch (NoSuchAlgorithmException e) { - cacheKey = String.valueOf(key.hashCode()); - } - return cacheKey; - } - - /** - * 将普通字符串转换为16位进制字符串 - */ - public static String bytesToHexString(byte[] src) { - StringBuilder stringBuilder = new StringBuilder("0x"); - if (src == null || src.length <= 0) { - return null; - } - char[] buffer = new char[2]; - for (byte aSrc : src) { - buffer[0] = Character.forDigit((aSrc >>> 4) & 0x0F, 16); - buffer[1] = Character.forDigit(aSrc & 0x0F, 16); - stringBuilder.append(buffer); - } - return stringBuilder.toString(); - } - - /** - * 获取对象名 - * - * @param obj 对象 - * @return 对象名 - */ - public static String getClassName(Object obj) { - String arrays[] = obj.getClass().getName().split("\\."); - return arrays[arrays.length - 1]; - } - - /** - * 获取对象名 - * - * @param clazz clazz - * @return 对象名 - */ - public static String getClassName(Class clazz) { - String arrays[] = clazz.getName().split("\\."); - return arrays[arrays.length - 1]; - } - - /** - * 格式化文件大小 - * - * @param size file.length() 获取文件大小 - */ - public static String formatFileSize(double size) { - if (size < 0) { - return "0kb"; - } - double kiloByte = size / 1024; - if (kiloByte < 1) { - return size + "b"; - } - - double megaByte = kiloByte / 1024; - if (megaByte < 1) { - BigDecimal result1 = new BigDecimal(Double.toString(kiloByte)); - return result1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "kb"; - } - - double gigaByte = megaByte / 1024; - if (gigaByte < 1) { - BigDecimal result2 = new BigDecimal(Double.toString(megaByte)); - return result2.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "mb"; - } - - double teraBytes = gigaByte / 1024; - if (teraBytes < 1) { - BigDecimal result3 = new BigDecimal(Double.toString(gigaByte)); - return result3.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "gb"; - } - BigDecimal result4 = new BigDecimal(teraBytes); - return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "tb"; - } - - /** - * 创建目录 当目录不存在的时候创建文件,否则返回false - */ - public static boolean createDir(String path) { - File file = new File(path); - if (!file.exists()) { - if (!file.mkdirs()) { - ALog.d(TAG, "创建失败,请检查路径和是否配置文件权限!"); - return false; - } - return true; - } - return false; - } - - /** - * 创建文件 当文件不存在的时候就创建一个文件。 如果文件存在,先删除原文件,然后重新创建一个新文件 - * - * @return {@code true} 创建成功、{@code false} 创建失败 - */ - public static boolean createFile(String path) { - if (TextUtils.isEmpty(path)) { - ALog.e(TAG, "文件路径不能为null"); - return false; - } - File file = new File(path); - if (file.getParentFile() == null || !file.getParentFile().exists()) { - ALog.d(TAG, "目标文件所在路径不存在,准备创建……"); - if (!createDir(file.getParent())) { - ALog.d(TAG, "创建目录文件所在的目录失败!文件路径【" + path + "】"); - } - } - // 创建目标文件 - if (file.exists()) { - final File to = new File(file.getAbsolutePath() + System.currentTimeMillis()); - if (file.renameTo(to)) { - to.delete(); - } else { - file.delete(); - } - } - try { - if (file.createNewFile()) { - ALog.d(TAG, "创建文件成功:" + file.getAbsolutePath()); - return true; - } - } catch (IOException e) { - e.printStackTrace(); - return false; - } - return false; - } - - /** - * 通过文件名获取下载配置文件路径 - * - * @param fileName 文件名 - */ - public static String getFileConfigPath(boolean isDownload, String fileName) { - return AriaManager.APP.getFilesDir().getPath() + (isDownload ? AriaManager.DOWNLOAD_TEMP_DIR - : AriaManager.UPLOAD_TEMP_DIR) + fileName + ".properties"; - } - - /** - * 更新任务记录 - * - * @param oldPath 旧的文件路径 - * @param newPath 新的文件路径 - */ - public static void modifyTaskRecord(String oldPath, String newPath) { - if (oldPath.equals(newPath)) { - ALog.w(TAG, "修改任务记录失败,新文件路径和旧文件路径一致"); - return; - } - TaskRecord record = DbDataHelper.getTaskRecord(oldPath); - if (record == null) { - if (new File(oldPath).exists()) { - ALog.w(TAG, "修改任务记录失败,文件【" + oldPath + "】对应的任务记录不存在"); - } - return; - } - record.filePath = newPath; - record.update(); - } - - /** - * 读取下载配置文件 - */ - public static Properties loadConfig(File file) { - Properties properties = new Properties(); - FileInputStream fis = null; - if (!file.exists()) { - createFile(file.getPath()); - } - try { - fis = new FileInputStream(file); - properties.load(fis); - } catch (Exception e) { - e.printStackTrace(); - } finally { - try { - if (fis != null) { - fis.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - return properties; - } - - /** - * 保存配置文件 - */ - public static void saveConfig(File file, Properties properties) { - FileOutputStream fos = null; - try { - fos = new FileOutputStream(file, false); - properties.store(fos, null); - } catch (Exception e) { - e.printStackTrace(); - } finally { - try { - if (fos != null) { - fos.flush(); - fos.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - } +/* + * 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.util; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.net.Uri; +import android.os.Environment; +import android.os.StatFs; +import android.text.TextUtils; +import android.util.Base64; +import com.arialyy.aria.core.AriaManager; +import com.arialyy.aria.core.FtpUrlEntity; +import com.arialyy.aria.core.command.ICmd; +import com.arialyy.aria.core.command.group.AbsGroupCmd; +import com.arialyy.aria.core.command.group.GroupCmdFactory; +import com.arialyy.aria.core.command.normal.AbsNormalCmd; +import com.arialyy.aria.core.command.normal.NormalCmdFactory; +import com.arialyy.aria.core.common.AbsFileer; +import com.arialyy.aria.core.common.TaskRecord; +import com.arialyy.aria.core.common.ThreadRecord; +import com.arialyy.aria.core.download.DownloadEntity; +import com.arialyy.aria.core.download.DownloadGroupEntity; +import com.arialyy.aria.core.inf.AbsGroupTaskWrapper; +import com.arialyy.aria.core.inf.AbsNormalEntity; +import com.arialyy.aria.core.inf.AbsTaskWrapper; +import com.arialyy.aria.core.upload.UploadEntity; +import com.arialyy.aria.orm.DbEntity; +import dalvik.system.DexFile; +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.net.URLEncoder; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Created by lyy on 2016/1/22. 通用工具 + */ +public class CommonUtil { + private static final String TAG = "CommonUtil"; + + /** + * 检查分块任务是否存在 + * + * @param filePath 文件保存路径 + * @return {@code true} 分块文件存在 + */ + public static boolean blockTaskExists(String filePath) { + return new File(String.format(AbsFileer.SUB_PATH, filePath, 0)).exists(); + } + + /** + * 删除文件 + * + * @param path 文件路径 + * @return {@code true}删除成功、{@code false}删除失败 + */ + public static boolean deleteFile(String path) { + if (TextUtils.isEmpty(path)) { + ALog.e(TAG, "删除文件失败,路径为空"); + return false; + } + File file = new File(path); + if (file.exists()) { + final File to = new File(file.getAbsolutePath() + System.currentTimeMillis()); + if (file.renameTo(to)) { + return to.delete(); + } else { + return file.delete(); + } + } + return false; + } + + /** + * 将对象写入文件 + * + * @param filePath 文件路径 + * @param data data数据必须实现{@link Serializable}接口 + */ + public static void writeObjToFile(String filePath, Object data) { + if (!(data instanceof Serializable)) { + ALog.e(TAG, "对象写入文件失败,data数据必须实现Serializable接口"); + return; + } + FileOutputStream ops = null; + try { + if (!createFile(filePath)) { + return; + } + ops = new FileOutputStream(filePath); + ObjectOutputStream oops = new ObjectOutputStream(ops); + oops.writeObject(data); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (ops != null) { + try { + ops.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + /** + * 从文件中读取对象 + * + * @param filePath 文件路径 + * @return 如果读取成功,返回相应的Obj对象,读取失败,返回null + */ + public static Object readObjFromFile(String filePath) { + if (TextUtils.isEmpty(filePath)) { + ALog.e(TAG, "文件路径为空"); + return null; + } + File file = new File(filePath); + if (!file.exists()) { + ALog.e(TAG, String.format("文件【%s】不存在", filePath)); + return null; + } + FileInputStream fis = null; + try { + fis = new FileInputStream(filePath); + ObjectInputStream oois = new ObjectInputStream(fis); + return oois.readObject(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } finally { + if (fis != null) { + try { + fis.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return null; + } + + /** + * 获取分块文件的快大小 + * + * @param fileLen 文件总长度 + * @param blockId 分块id + * @param blockNum 分块数量 + * @return 分块长度 + */ + public static long getBlockLen(long fileLen, int blockId, int blockNum) { + final long averageLen = fileLen / blockNum; + return blockId == blockNum - 1 ? (fileLen - blockId * averageLen) : averageLen; + } + + /** + * 检查SD内存空间是否充足 + * + * @param filePath 文件保存路径 + * @param fileSize 文件大小 + * @return {@code false} 内存空间不足,{@code true}内存空间足够 + */ + public static boolean checkSDMemorySpace(String filePath, long fileSize) { + List dirs = FileUtil.getSDPathList(AriaManager.APP); + if (dirs == null || dirs.isEmpty()) { + return true; + } + for (String path : dirs) { + if (filePath.contains(path)) { + if (fileSize > 0 && fileSize > getAvailableExternalMemorySize(path)) { + return false; + } + } + } + return true; + } + + /** + * sdcard 可用大小 + * + * @param sdcardPath sdcard 根路径 + * @return 单位为:byte + */ + public static long getAvailableExternalMemorySize(String sdcardPath) { + StatFs stat = new StatFs(sdcardPath); + long blockSize = stat.getBlockSize(); + long availableBlocks = stat.getAvailableBlocks(); + return availableBlocks * blockSize; + } + + /** + * sdcard 总大小 + * + * @param sdcardPath sdcard 根路径 + * @return 单位为:byte + */ + public static long getTotalExternalMemorySize(String sdcardPath) { + StatFs stat = new StatFs(sdcardPath); + long blockSize = stat.getBlockSize(); + long totalBlocks = stat.getBlockCount(); + return totalBlocks * blockSize; + } + + /** + * 获取某包下所有类 + * + * @param className 过滤的类名 + * @return 类的完整名称 + */ + public static List getPkgClassNames(Context context, String className) { + List classNameList = new ArrayList<>(); + String pPath = context.getPackageCodePath(); + File dir = new File(pPath).getParentFile(); + String[] paths = dir.list(); + if (paths == null) { + classNameList.addAll(getPkgClassName(pPath, className)); + } else { + String dPath = dir.getPath(); + for (String path : dir.list()) { + String fPath = dPath + "/" + path; + if (!fPath.endsWith(".apk")) { + continue; + } + classNameList.addAll(getPkgClassName(fPath, className)); + } + } + return classNameList; + } + + /** + * 获取指定包名下的所有类 + * + * @param path dex路径 + * @param filterClass 需要过滤的类 + */ + public static List getPkgClassName(String path, String filterClass) { + List list = new ArrayList<>(); + try { + File file = new File(path); + if (!file.exists()) { + ALog.w(TAG, String.format("路径【%s】下的Dex文件不存在", path)); + return list; + } + + DexFile df = new DexFile(path);//通过DexFile查找当前的APK中可执行文件 + Enumeration enumeration = df.entries();//获取df中的元素 这里包含了所有可执行的类名 该类名包含了包名+类名的方式 + while (enumeration.hasMoreElements()) { + String _className = enumeration.nextElement(); + if (!_className.contains(filterClass)) { + continue; + } + if (_className.contains(filterClass)) { + list.add(_className); + } + } + df.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return list; + } + + /** + * 拦截window.location.replace数据 + * + * @return 重定向url + */ + public static String getWindowReplaceUrl(String text) { + if (TextUtils.isEmpty(text)) { + ALog.e(TAG, "拦截数据为null"); + return null; + } + String reg = Regular.REG_WINLOD_REPLACE; + Pattern p = Pattern.compile(reg); + Matcher m = p.matcher(text); + if (m.find()) { + String s = m.group(); + s = s.substring(9, s.length() - 2); + return s; + } + return null; + } + + /** + * 获取sdcard app的缓存目录 + * + * @return "/mnt/sdcard/Android/data/{package_name}/files/" + */ + public static String getAppPath(Context context) { + //判断是否存在sd卡 + boolean sdExist = android.os.Environment.MEDIA_MOUNTED.equals( + android.os.Environment.getExternalStorageState()); + if (!sdExist) { + return null; + } else { + //获取sd卡路径 + File file = context.getExternalFilesDir(null); + String dir; + if (file != null) { + dir = file.getPath() + "/"; + } else { + dir = Environment.getExternalStorageDirectory().getPath() + + "/Android/data/" + + context.getPackageName() + + "/files/"; + } + return dir; + } + } + + /** + * 获取map泛型类型 + * + * @param map list类型字段 + * @return 泛型类型 + */ + public static Class[] getMapParamType(Field map) { + Class type = map.getType(); + if (!type.isAssignableFrom(Map.class)) { + ALog.d(TAG, "字段类型不是Map"); + return null; + } + + Type fc = map.getGenericType(); + + if (fc == null) { + ALog.d(TAG, "该字段没有泛型参数"); + return null; + } + + if (fc instanceof ParameterizedType) { + ParameterizedType pt = (ParameterizedType) fc; + Type[] types = pt.getActualTypeArguments(); + Class[] clazz = new Class[2]; + clazz[0] = (Class) types[0]; + clazz[1] = (Class) types[1]; + return clazz; + } + return null; + } + + /** + * 获取list泛型类型 + * + * @param list list类型字段 + * @return 泛型类型 + */ + + public static Class getListParamType(Field list) { + Class type = list.getType(); + if (!type.isAssignableFrom(List.class)) { + ALog.d(TAG, "字段类型不是List"); + return null; + } + + Type fc = list.getGenericType(); // 关键的地方,如果是List类型,得到其Generic的类型 + + if (fc == null) { + ALog.d(TAG, "该字段没有泛型参数"); + return null; + } + + if (fc instanceof ParameterizedType) { //如果是泛型参数的类型 + ParameterizedType pt = (ParameterizedType) fc; + return (Class) pt.getActualTypeArguments()[0]; //得到泛型里的class类型对象。 + } + return null; + } + + /** + * 创建文件名,如果url链接有后缀名,则使用url中的后缀名 + * + * @return url 的 hashKey + */ + public static String createFileName(String url) { + int end = url.indexOf("?"); + String tempUrl, fileName = ""; + if (end > 0) { + tempUrl = url.substring(0, end); + int tempEnd = tempUrl.lastIndexOf("/"); + if (tempEnd > 0) { + fileName = tempUrl.substring(tempEnd + 1, tempUrl.length()); + } + } else { + int tempEnd = url.lastIndexOf("/"); + if (tempEnd > 0) { + fileName = url.substring(tempEnd + 1, url.length()); + } + } + if (TextUtils.isEmpty(fileName)) { + fileName = CommonUtil.keyToHashKey(url); + } + return fileName; + } + + /** + * 分割获取url,协议,ip/域名,端口,内容 + * + * @param url 输入的url{@code String url = "ftp://z:z@dygod18.com:21211/[电影天堂www.dy2018.com]猩球崛起3:终极之战BD国英双语中英双字.mkv";} + */ + public static FtpUrlEntity getFtpUrlInfo(String url) { + Uri uri = Uri.parse(url); + + String userInfo = uri.getUserInfo(), remotePath = uri.getPath(); + ALog.d(TAG, + String.format("scheme = %s, user = %s, host = %s, port = %s, path = %s", uri.getScheme(), + userInfo, uri.getHost(), uri.getPort(), remotePath)); + + FtpUrlEntity entity = new FtpUrlEntity(); + entity.url = url; + entity.hostName = uri.getHost(); + entity.port = uri.getPort() == -1 ? "21" : String.valueOf(uri.getPort()); + if (!TextUtils.isEmpty(userInfo)) { + String[] temp = userInfo.split(":"); + if (temp.length == 2) { + entity.user = temp[0]; + entity.password = temp[1]; + } else { + entity.user = userInfo; + } + } + entity.scheme = uri.getScheme(); + entity.remotePath = TextUtils.isEmpty(remotePath) ? "/" : remotePath; + return entity; + } + + /** + * 转换Url + * + * @param url 原地址 + * @return 转换后的地址 + */ + public static String convertUrl(String url) { + Uri uri = Uri.parse(url); + url = uri.toString(); + if (hasDoubleCharacter(url)) { + //预先处理空格,URLEncoder只会把空格转换为+ + url = url.replaceAll(" ", "%20"); + //匹配双字节字符(包括汉字在内) + String regex = Regular.REG_DOUBLE_CHAR_AND_SPACE; + Pattern p = Pattern.compile(regex); + Matcher m = p.matcher(url); + Set strs = new HashSet<>(); + while (m.find()) { + strs.add(m.group()); + } + try { + for (String str : strs) { + url = url.replaceAll(str, URLEncoder.encode(str, "UTF-8")); + } + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + return url; + } + + /** + * 判断是否有双字节字符(包括汉字在内) 和空格、制表符、回车 + * + * @param chineseStr 需要进行判断的字符串 + * @return {@code true}有双字节字符,{@code false} 无双字节字符 + */ + public static boolean hasDoubleCharacter(String chineseStr) { + char[] charArray = chineseStr.toCharArray(); + for (char aCharArray : charArray) { + if (((aCharArray >= 0x0391) && (aCharArray <= 0xFFE5)) || (aCharArray == 0x0d) || (aCharArray + == 0x0a) || (aCharArray == 0x20)) { + return true; + } + } + return false; + } + + /** + * base64 解密字符串 + * + * @param str 被加密的字符串 + * @return 解密后的字符串 + */ + public static String decryptBASE64(String str) { + return new String(Base64.decode(str.getBytes(), Base64.DEFAULT)); + } + + /** + * base64 加密字符串 + * + * @param str 需要加密的字符串 + * @return 加密后的字符串 + */ + public static String encryptBASE64(String str) { + return Base64.encodeToString(str.getBytes(), Base64.DEFAULT); + } + + /** + * 字符串编码转换 + */ + public static String strCharSetConvert(String oldStr, String charSet) { + try { + return new String(oldStr.getBytes(), charSet); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 根据下载任务组的url创建key + * + * @return urls 为 null 或者 size为0,返回"" + */ + public static String getMd5Code(List urls) { + if (urls == null || urls.size() < 1) return ""; + String md5 = ""; + StringBuilder sb = new StringBuilder(); + for (String url : urls) { + sb.append(url); + } + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(sb.toString().getBytes()); + md5 = new BigInteger(1, md.digest()).toString(16); + } catch (NoSuchAlgorithmException e) { + ALog.e(TAG, e.getMessage()); + } + return md5; + } + + /** + * 获取字符串的md5 + * + * @return 字符串为空或获取md5失败,则返回"" + */ + public static String getStrMd5(String str) { + if (TextUtils.isEmpty(str)) return ""; + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + md.update(str.getBytes()); + return new BigInteger(1, md.digest()).toString(16); + } catch (NoSuchAlgorithmException e) { + ALog.e(TAG, e.getMessage()); + } + return ""; + } + + /** + * 删除任务组记录 + * + * @param removeFile {@code true} 不仅删除任务数据库记录,还会删除已经删除完成的文件 {@code false}如果任务已经完成,只删除任务数据库记录 + */ + public static void delGroupTaskRecord(boolean removeFile, DownloadGroupEntity groupEntity) { + if (groupEntity == null) { + ALog.e(TAG, "删除下载任务组记录失败,任务组实体为null"); + return; + } + List records = + DbEntity.findDatas(TaskRecord.class, "dGroupHash=?", groupEntity.getGroupHash()); + + if (records == null || records.isEmpty()) { + ALog.w(TAG, "组任务记录删除失败,记录为null"); + } else { + for (TaskRecord record : records) { + // 删除分块文件 + if (record.isBlock) { + for (int i = 0, len = record.threadNum; i < len; i++) { + File partFile = new File(String.format(AbsFileer.SUB_PATH, record.filePath, i)); + if (partFile.exists()) { + partFile.delete(); + } + } + } + record.deleteData(); + } + } + + List subs = groupEntity.getSubEntities(); + if (subs != null) { + for (DownloadEntity sub : subs) { + File file = new File(sub.getDownloadPath()); + if (file.exists() && (removeFile || !sub.isComplete())) { + file.delete(); + } + } + } + + if (!TextUtils.isEmpty(groupEntity.getDirPath())) { + File dir = new File(groupEntity.getDirPath()); + if (dir.exists() && (removeFile || !groupEntity.isComplete())) { + dir.delete(); + } + groupEntity.deleteData(); + } + } + + /** + * 删除任务记录 + * + * @param removeFile {@code true} 不仅删除任务数据库记录,还会删除已经完成的文件 {@code false}如果任务已经完成,只删除任务数据库记录 + */ + public static void delTaskRecord(TaskRecord record, boolean removeFile, AbsNormalEntity dEntity) { + if (dEntity == null) return; + File file; + if (dEntity instanceof DownloadEntity) { + file = new File(((DownloadEntity) dEntity).getDownloadPath()); + } else if (dEntity instanceof UploadEntity) { + file = new File(((UploadEntity) dEntity).getFilePath()); + } else { + ALog.w(TAG, "删除记录失败,未知类型"); + return; + } + if (removeFile || !dEntity.isComplete()) { + // 删除分块文件 + if (record.isBlock) { + for (int i = 0, len = record.threadNum; i < len; i++) { + File partFile = new File(String.format(AbsFileer.SUB_PATH, record.filePath, i)); + if (partFile.exists()) { + partFile.delete(); + } + } + } + if (file.exists()) { + file.delete(); + } + } + + if (record != null) { + record.deleteData(); + } + //下载任务实体和下载实体为一对一关系,下载实体删除,任务实体自动删除 + dEntity.deleteData(); + } + + /** + * 删除任务记录,默认删除文件 + * + * @param filePath 文件路径 + * @param removeFile {@code true} 不仅删除任务数据库记录,还会删除已经删除完成的文件 {@code false}如果任务已经完成,只删除任务数据库记录 + * @param type {@code 1}下载任务的记录,{@code 2} 上传任务的记录 {@code false}如果任务已经完成,只删除任务数据库记录 + */ + public static void delTaskRecord(String filePath, int type, boolean removeFile) { + if (TextUtils.isEmpty(filePath)) { + throw new NullPointerException("删除记录失败,文件路径为空"); + } + if (type != 1 && type != 2) { + throw new IllegalArgumentException("任务记录类型错误"); + } + TaskRecord record = DbEntity.findFirst(TaskRecord.class, "filePath=?", filePath); + File file = new File(filePath); + if (record == null) { + ALog.w(TAG, "记录为空"); + } else { + // 删除分块文件 + if (record.isBlock) { + for (int i = 0, len = record.threadNum; i < len; i++) { + File partFile = new File(String.format(AbsFileer.SUB_PATH, record.filePath, i)); + if (partFile.exists()) { + partFile.delete(); + } + } + } + + record.deleteData(); + } + if (file.exists() && removeFile) { + file.delete(); + } + //下载任务实体和下载实体为一对一关系,下载实体删除,任务实体自动删除 + if (type == 1) { + DbEntity.deleteData(DownloadEntity.class, "downloadPath=?", filePath); + } else { + DbEntity.deleteData(UploadEntity.class, "filePath=?", filePath); + } + } + + /** + * 删除任务记录,默认删除文件 + * + * @param filePath 文件路径 + * @param type {@code 1}下载任务的记录,{@code 2} 上传任务的记录 {@code false}如果任务已经完成,只删除任务数据库记录 + */ + public static void delTaskRecord(String filePath, int type) { + delTaskRecord(filePath, type, false); + } + + /** + * 获取CPU核心数 + */ + public static int getCoresNum() { + //Private Class to display only CPU devices in the directory listing + class CpuFilter implements FileFilter { + @Override public boolean accept(File pathname) { + //Check if filename is "cpu", followed by a single digit number + return Pattern.matches("cpu[0-9]", pathname.getName()); + } + } + + try { + //Get directory containing CPU info + File dir = new File("/sys/devices/system/cpu/"); + //Filter to only list the devices we care about + File[] files = dir.listFiles(new CpuFilter()); + ALog.d(TAG, "CPU Count: " + files.length); + //Return the number of cores (virtual CPU devices) + return files.length; + } catch (Exception e) { + //Print exception + ALog.d(TAG, "CPU Count: Failed."); + e.printStackTrace(); + //Default to return 1 core + return 1; + } + } + + /** + * 通过流创建文件 + */ + public static void createFileFormInputStream(InputStream is, String path) { + try { + FileOutputStream fos = new FileOutputStream(path); + byte[] buf = new byte[1024]; + int len; + while ((len = is.read(buf)) > 0) { + fos.write(buf, 0, len); + } + is.close(); + fos.flush(); + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 校验文件MD5码 + */ + public static boolean checkMD5(String md5, File updateFile) { + if (TextUtils.isEmpty(md5) || updateFile == null) { + ALog.e(TAG, "MD5 string empty or updateFile null"); + return false; + } + + String calculatedDigest = getFileMD5(updateFile); + if (calculatedDigest == null) { + ALog.e(TAG, "calculatedDigest null"); + return false; + } + return calculatedDigest.equalsIgnoreCase(md5); + } + + /** + * 校验文件MD5码 + */ + public static boolean checkMD5(String md5, InputStream is) { + if (TextUtils.isEmpty(md5) || is == null) { + ALog.e(TAG, "MD5 string empty or updateFile null"); + return false; + } + + String calculatedDigest = getFileMD5(is); + if (calculatedDigest == null) { + ALog.e(TAG, "calculatedDigest null"); + return false; + } + return calculatedDigest.equalsIgnoreCase(md5); + } + + /** + * 获取文件MD5码 + */ + public static String getFileMD5(File updateFile) { + InputStream is; + try { + is = new FileInputStream(updateFile); + } catch (FileNotFoundException e) { + ALog.e(TAG, e); + return null; + } + + return getFileMD5(is); + } + + /** + * 获取文件MD5码 + */ + public static String getFileMD5(InputStream is) { + MessageDigest digest; + try { + digest = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException e) { + ALog.e(TAG, e); + return null; + } + + byte[] buffer = new byte[8192]; + int read; + try { + while ((read = is.read(buffer)) > 0) { + digest.update(buffer, 0, read); + } + byte[] md5sum = digest.digest(); + BigInteger bigInt = new BigInteger(1, md5sum); + String output = bigInt.toString(16); + // Fill to 32 chars + output = String.format("%32s", output).replace(' ', '0'); + return output; + } catch (IOException e) { + throw new RuntimeException("Unable to process file for MD5", e); + } finally { + try { + is.close(); + } catch (IOException e) { + ALog.e(TAG, e); + } + } + } + + /** + * 创建任务命令 + * + * @param taskType {@link ICmd#TASK_TYPE_DOWNLOAD}、{@link ICmd#TASK_TYPE_DOWNLOAD_GROUP}、{@link + * ICmd#TASK_TYPE_UPLOAD} + */ + public static AbsNormalCmd createNormalCmd(T entity, int cmd, + int taskType) { + return NormalCmdFactory.getInstance().createCmd(entity, cmd, taskType); + } + + /** + * 创建任务组命令 + * + * @param childUrl 子任务url + */ + public static AbsGroupCmd createGroupCmd(String target, T entity, + int cmd, String childUrl) { + return GroupCmdFactory.getInstance().createCmd(target, entity, cmd, childUrl); + } + + /** + * 创建隐性的Intent + */ + public static Intent createIntent(String packageName, String action) { + Uri.Builder builder = new Uri.Builder(); + builder.scheme(packageName); + Uri uri = builder.build(); + Intent intent = new Intent(action); + intent.setData(uri); + return intent; + } + + /** + * 存储字符串到配置文件 + * + * @param preName 配置文件名 + * @param key 存储的键值 + * @param value 需要存储的字符串 + * @return 成功标志 + */ + public static Boolean putString(String preName, Context context, String key, String value) { + SharedPreferences pre = context.getSharedPreferences(preName, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = pre.edit(); + editor.putString(key, value); + return editor.commit(); + } + + /** + * 从配置文件读取字符串 + * + * @param preName 配置文件名 + * @param key 字符串键值 + * @return 键值对应的字符串, 默认返回"" + */ + public static String getString(String preName, Context context, String key) { + SharedPreferences pre = context.getSharedPreferences(preName, Context.MODE_PRIVATE); + return pre.getString(key, ""); + } + + /** + * 获取所有字段,包括父类的字段 + */ + public static List getAllFields(Class clazz) { + List fields = new ArrayList<>(); + Class personClazz = clazz.getSuperclass(); + if (personClazz != null) { + Class rootClazz = personClazz.getSuperclass(); + if (rootClazz != null) { + Collections.addAll(fields, rootClazz.getDeclaredFields()); + } + Collections.addAll(fields, personClazz.getDeclaredFields()); + } + Collections.addAll(fields, clazz.getDeclaredFields()); + return fields; + } + + /** + * 获取当前类里面的所在字段 + */ + public static Field[] getFields(Class clazz) { + Field[] fields = null; + fields = clazz.getDeclaredFields(); + if (fields == null || fields.length == 0) { + Class superClazz = clazz.getSuperclass(); + if (superClazz != null) { + fields = getFields(superClazz); + } + } + return fields; + } + + /** + * 获取类里面的指定对象,如果该类没有则从父类查询 + */ + public static Field getField(Class clazz, String name) { + Field field = null; + try { + field = clazz.getDeclaredField(name); + } catch (NoSuchFieldException e) { + try { + field = clazz.getField(name); + } catch (NoSuchFieldException e1) { + if (clazz.getSuperclass() == null) { + return field; + } else { + field = getField(clazz.getSuperclass(), name); + } + } + } + if (field != null) { + field.setAccessible(true); + } + return field; + } + + /** + * 字符串转hashcode + */ + public static int keyToHashCode(String str) { + int total = 0; + for (int i = 0; i < str.length(); i++) { + char ch = str.charAt(i); + if (ch == '-') ch = (char) 28; // does not contain the same last 5 bits as any letter + if (ch == '\'') ch = (char) 29; // nor this + total = (total * 33) + (ch & 0x1F); + } + return total; + } + + /** + * 将key转换为16进制码 + * + * @param key 缓存的key + * @return 转换后的key的值, 系统便是通过该key来读写缓存 + */ + public static String keyToHashKey(String key) { + String cacheKey; + try { + final MessageDigest mDigest = MessageDigest.getInstance("MD5"); + mDigest.update(key.getBytes()); + cacheKey = bytesToHexString(mDigest.digest()); + } catch (NoSuchAlgorithmException e) { + cacheKey = String.valueOf(key.hashCode()); + } + return cacheKey; + } + + /** + * 将普通字符串转换为16位进制字符串 + */ + public static String bytesToHexString(byte[] src) { + StringBuilder stringBuilder = new StringBuilder("0x"); + if (src == null || src.length <= 0) { + return null; + } + char[] buffer = new char[2]; + for (byte aSrc : src) { + buffer[0] = Character.forDigit((aSrc >>> 4) & 0x0F, 16); + buffer[1] = Character.forDigit(aSrc & 0x0F, 16); + stringBuilder.append(buffer); + } + return stringBuilder.toString(); + } + + /** + * 获取对象名 + * + * @param obj 对象 + * @return 对象名 + */ + public static String getClassName(Object obj) { + String arrays[] = obj.getClass().getName().split("\\."); + return arrays[arrays.length - 1]; + } + + /** + * 获取对象名 + * + * @param clazz clazz + * @return 对象名 + */ + public static String getClassName(Class clazz) { + String arrays[] = clazz.getName().split("\\."); + return arrays[arrays.length - 1]; + } + + /** + * 格式化文件大小 + * + * @param size file.length() 获取文件大小 + */ + public static String formatFileSize(double size) { + if (size < 0) { + return "0kb"; + } + double kiloByte = size / 1024; + if (kiloByte < 1) { + return size + "b"; + } + + double megaByte = kiloByte / 1024; + if (megaByte < 1) { + BigDecimal result1 = new BigDecimal(Double.toString(kiloByte)); + return result1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "kb"; + } + + double gigaByte = megaByte / 1024; + if (gigaByte < 1) { + BigDecimal result2 = new BigDecimal(Double.toString(megaByte)); + return result2.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "mb"; + } + + double teraBytes = gigaByte / 1024; + if (teraBytes < 1) { + BigDecimal result3 = new BigDecimal(Double.toString(gigaByte)); + return result3.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "gb"; + } + BigDecimal result4 = new BigDecimal(teraBytes); + return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "tb"; + } + + /** + * 创建目录 当目录不存在的时候创建文件,否则返回false + */ + public static boolean createDir(String path) { + File file = new File(path); + if (!file.exists()) { + if (!file.mkdirs()) { + ALog.d(TAG, "创建失败,请检查路径和是否配置文件权限!"); + return false; + } + return true; + } + return false; + } + + /** + * 创建文件 当文件不存在的时候就创建一个文件。 如果文件存在,先删除原文件,然后重新创建一个新文件 + * + * @return {@code true} 创建成功、{@code false} 创建失败 + */ + public static boolean createFile(String path) { + if (TextUtils.isEmpty(path)) { + ALog.e(TAG, "文件路径不能为null"); + return false; + } + File file = new File(path); + if (file.getParentFile() == null || !file.getParentFile().exists()) { + ALog.d(TAG, "目标文件所在路径不存在,准备创建……"); + if (!createDir(file.getParent())) { + ALog.d(TAG, "创建目录文件所在的目录失败!文件路径【" + path + "】"); + } + } + // 创建目标文件 + if (file.exists()) { + final File to = new File(file.getAbsolutePath() + System.currentTimeMillis()); + if (file.renameTo(to)) { + to.delete(); + } else { + file.delete(); + } + } + try { + if (file.createNewFile()) { + ALog.d(TAG, "创建文件成功:" + file.getAbsolutePath()); + return true; + } + } catch (IOException e) { + e.printStackTrace(); + return false; + } + return false; + } + + /** + * 通过文件名获取下载配置文件路径 + * + * @param fileName 文件名 + */ + public static String getFileConfigPath(boolean isDownload, String fileName) { + return AriaManager.APP.getFilesDir().getPath() + (isDownload ? AriaManager.DOWNLOAD_TEMP_DIR + : AriaManager.UPLOAD_TEMP_DIR) + fileName + ".properties"; + } + + /** + * 修改任务路径,修改文件路径和任务记录信息。如果是分块任务,则修改分块文件的路径。 + * + * @param oldPath 旧的文件路径 + * @param newPath 新的文件路径 + */ + public static void modifyTaskRecord(String oldPath, String newPath) { + if (oldPath.equals(newPath)) { + ALog.w(TAG, "修改任务记录失败,新文件路径和旧文件路径一致"); + return; + } + TaskRecord record = DbDataHelper.getTaskRecord(oldPath); + if (record == null) { + if (new File(oldPath).exists()) { + ALog.w(TAG, "修改任务记录失败,文件【" + oldPath + "】对应的任务记录不存在"); + } + return; + } + if (!record.isBlock) { + File oldFile = new File(oldPath); + if (oldFile.exists()) { + oldFile.renameTo(new File(newPath)); + } + } + + record.filePath = newPath; + record.update(); + // 修改线程记录 + if (record.threadRecords != null && !record.threadRecords.isEmpty()) { + for (ThreadRecord tr : record.threadRecords) { + tr.key = newPath; + File blockFile = new File(String.format(AbsFileer.SUB_PATH, oldPath, tr.threadId)); + if (blockFile.exists()){ + blockFile.renameTo(new File(String.format(AbsFileer.SUB_PATH, newPath, tr.threadId))); + } + } + DbEntity.saveAll(record.threadRecords); + } + } + + /** + * 读取下载配置文件 + */ + public static Properties loadConfig(File file) { + Properties properties = new Properties(); + FileInputStream fis = null; + if (!file.exists()) { + createFile(file.getPath()); + } + try { + fis = new FileInputStream(file); + properties.load(fis); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (fis != null) { + fis.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + return properties; + } + + /** + * 保存配置文件 + */ + public static void saveConfig(File file, Properties properties) { + FileOutputStream fos = null; + try { + fos = new FileOutputStream(file, false); + properties.store(fos, null); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (fos != null) { + fos.flush(); + fos.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } } \ No newline at end of file diff --git a/DEV_LOG.md b/DEV_LOG.md index 897e344c..a4b01c9c 100644 --- a/DEV_LOG.md +++ b/DEV_LOG.md @@ -1,4 +1,8 @@ ## 开发日志 + + v_3.6.4 + - 优化任务接收器的代码结构 + - 修复`DbEntity.saveAll()`失败的问题 + - 修复分块任务重命名失败的问题 + v_3.6.3 (2019/4/2) - fix bug https://github.com/AriaLyy/Aria/issues/377 + v_3.6.2 (2019/4/1) diff --git a/app/src/main/assets/aria_config.xml b/app/src/main/assets/aria_config.xml index eabeec56..40e41cb1 100644 --- a/app/src/main/assets/aria_config.xml +++ b/app/src/main/assets/aria_config.xml @@ -1,161 +1,161 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/arialyy/simple/core/download/FtpDownloadActivity.java b/app/src/main/java/com/arialyy/simple/core/download/FtpDownloadActivity.java index fe6fa41f..8130ec4c 100644 --- a/app/src/main/java/com/arialyy/simple/core/download/FtpDownloadActivity.java +++ b/app/src/main/java/com/arialyy/simple/core/download/FtpDownloadActivity.java @@ -35,9 +35,9 @@ import java.io.File; * Ftp下载测试 */ public class FtpDownloadActivity extends BaseActivity { - //private final String URL = "ftp://192.168.1.9:21/下载/AriaPrj.zip"; + private final String URL = "ftp://9.9.9.205:2121/Cyberduck-6.9.4.30164.zip"; //private final String URL = "ftp://182.92.180.213:21/video/572fed5c2ad48_1024.jpg"; - private final String URL = "ftp://182.92.180.213:21/DATA/20180205/rar/1111.rar"; + //private final String URL = "ftp://182.92.180.213:21/DATA/20180205/rar/1111.rar"; //private final String URL = "ftp://d:d@dygodj8.com:12311/咖啡风暴HD大陆公映意语中字[飘花www.piaohua.com].mp4"; @Override protected void init(Bundle savedInstanceState) { diff --git a/app/src/main/java/com/arialyy/simple/core/download/HighestPriorityActivity.java b/app/src/main/java/com/arialyy/simple/core/download/HighestPriorityActivity.java index a400e26d..8cec1211 100644 --- a/app/src/main/java/com/arialyy/simple/core/download/HighestPriorityActivity.java +++ b/app/src/main/java/com/arialyy/simple/core/download/HighestPriorityActivity.java @@ -147,7 +147,7 @@ public class HighestPriorityActivity extends BaseActivity { int i = 1; private void startD() { - //Aria.get(this).setLogLevel(ALog.LOG_CLOSE); - //Aria.download(this).load("aaaa.apk"); - String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/ggsg11.mp4"; - //String path = String.format("/sdcard/ggsg11(%s).mp4", i); - //if (new File(path).exists()) { - // - // i++; - // path = String.format("/sdcard/ggsg11(%s).mp4", i); - //} - //File file = new File(path); - //if (file.exists()){ - // file.delete(); - //} - //Aria.download(SingleTaskActivity.this).load(DOWNLOAD_URL).resetState().save(); - Map params = new HashMap<>(); - params.put("key", "value"); - params.put("filename", "CentOS-7-x86_64-Minimal-1804.iso"); + String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/ggsg14.apk"; + //Map params = new HashMap<>(); + //params.put("key", "value"); + //params.put("filename", "CentOS-7-x86_64-Minimal-1804.iso"); Aria.download(SingleTaskActivity.this) .load(DOWNLOAD_URL) //.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8") diff --git a/app/src/main/java/com/arialyy/simple/core/test/TestMutilTaskSysDownload.java b/app/src/main/java/com/arialyy/simple/core/test/TestMutilTaskSysDownload.java index d1e4a206..a3dd437b 100644 --- a/app/src/main/java/com/arialyy/simple/core/test/TestMutilTaskSysDownload.java +++ b/app/src/main/java/com/arialyy/simple/core/test/TestMutilTaskSysDownload.java @@ -1,80 +1,80 @@ -package com.arialyy.simple.core.test; - -import android.os.Environment; -import android.view.View; -import com.arialyy.aria.core.Aria; -import com.arialyy.aria.core.common.QueueMod; -import com.arialyy.simple.R; -import com.arialyy.simple.base.BaseActivity; -import com.arialyy.simple.databinding.TestActivityMultiBinding; - -/** - * Created by AriaL on 2017/6/15. - */ - -public class TestMutilTaskSysDownload extends BaseActivity { - - @Override protected int setLayoutId() { - return R.layout.test_activity_multi; - } - - public void onClick(View view) { - String baseUrl = "http://file.bmob.cn/"; - String[] urlArray = { - "M02/3B/A4/oYYBAFaOeUSAc1QiAAFTbmA7AHs052.jpg", - "M02/3B/A4/oYYBAFaOeUaAfYC-AAFD8zf9NXc879.jpg", - "M02/3B/A4/oYYBAFaOeUuAOxhnAACSdmbqSac702.jpg", - "M02/3B/A4/oYYBAFaOeU2AFAIGAAFICximvXc924.jpg", - "M02/3B/A4/oYYBAFaOeVCAPWMQAAFm2KWCq_E721.jpg", - "M02/3B/A4/oYYBAFaOeVOAbiv9AAFfCTTgr94948.jpg", - "M02/3B/A4/oYYBAFaOeVaAMR3tAAFf3yTuuCM577.jpg", - "M02/3B/A4/oYYBAFaOeVmACEWhAAEt72ecbpg468.jpg", - "M02/3B/A4/oYYBAFaOeVyAHHt4AAFg9e9bRio507.jpg", - "M02/3B/A4/oYYBAFaOeV-AClYXAAESLGY0gag424.jpg", - "M02/3B/A4/oYYBAFaOeWKAA7N0AAF3omYOJUI703.jpg", - "M02/3B/A4/oYYBAFaOeWWAD2lrAAFN7eRFxBs575.jpg", - "M02/3B/A4/oYYBAFaOeWiAdCVEAAFg4273Dus313.jpg", - "M02/3B/A4/oYYBAFaOeWyAJDm5AAF8JVoGVb0705.jpg", - "M02/3B/A4/oYYBAFaOeW-AUoA8AAGjKiHkXUo181.jpg", - "M02/3B/A4/oYYBAFaOeXKABIamAAFU7J7vraE265.jpg", - "M02/3B/A5/oYYBAFaOeXaAW09jAAFf37qdwDA457.jpg", - "M02/3B/A5/oYYBAFaOeXmAWmS7AAFtLNpWjgo967.jpg", - "M02/3B/A5/oYYBAFaOeX2AQf9cAAF2fhwS2UE145.jpg", - "M02/3B/A5/oYYBAFaOeYCAKGnLAAFVAzks-qU937.jpg", - "M02/3B/A5/oYYBAFaOeYOAMODNAAF6HjTTMq4819.jpg", - "M02/3B/A5/oYYBAFaOeYeAbn8uAAFLSQLw48Q042.jpg", - "M02/3B/A5/oYYBAFaOeYqAMJThAAFtrNe4UNM047.jpg", - "M02/3B/A5/oYYBAFaOeY2AbnQvAAFNSXWn0Dc026.jpg", - "M02/3B/A5/oYYBAFaOeZCAIsr0AAFHZFEVhPc682.jpg", - "M02/3B/A5/oYYBAFaOeZOAGvITAAFqPmfcc9c471.jpg", - "M02/3B/A5/oYYBAFaOeZaATvjbAAFHDmALnhE003.jpg", - "M02/3B/A5/oYYBAFaOeZmAJPuVAAFfPJC2wsE319.jpg", - "M02/3B/A5/oYYBAFaOeZyAXtAmAAFfArJNwtM371.jpg", - "M02/3B/A5/oYYBAFaOeZ-AGZN0AAFgqwYYCS8004.jpg", - "M02/3B/A5/oYYBAFaOeaOAbbrGAAFcq59JjUo205.jpg", - "M02/3B/A5/oYYBAFaOeaSAdFyoAACaxVxgUJA092.jpg" - }; - int maxNum = Aria.get(this).getDownloadConfig().getMaxTaskNum(); - Aria.get(this).setDownloadQueueMod(QueueMod.NOW); - for (int i = 0; i < urlArray.length; i++) { - Aria.download(this) - .load(baseUrl + urlArray[i]) - .setDownloadPath(Environment.getExternalStorageDirectory() + "/test/" + i + ".jpg") - //.addHeader("Accept-Encoding", "gzip,deflate,sdcn") - .start(); - //if (i < maxNum) { - // Aria.download(this) - // .load(baseUrl + urlArray[i]) - // .setDownloadPath(Environment.getExternalStorageDirectory() + "/test/" + i + ".jpg") - // //.addHeader("Accept-Encoding", "gzip,deflate,sdcn") - // .start(); - //} else { - // Aria.download(this) - // .load(baseUrl + urlArray[i]) - // .setDownloadPath(Environment.getExternalStorageDirectory() + "/test/" + i + ".jpg") - // //.addHeader("Accept-Encoding", "gzip,deflate,sdcn") - // .add(); - //} - } - } -} +package com.arialyy.simple.core.test; + +import android.os.Environment; +import android.view.View; +import com.arialyy.aria.core.Aria; +import com.arialyy.aria.core.common.QueueMod; +import com.arialyy.simple.R; +import com.arialyy.simple.base.BaseActivity; +import com.arialyy.simple.databinding.TestActivityMultiBinding; + +/** + * Created by AriaL on 2017/6/15. + */ + +public class TestMutilTaskSysDownload extends BaseActivity { + + @Override protected int setLayoutId() { + return R.layout.test_activity_multi; + } + + public void onClick(View view) { + String baseUrl = "http://file.bmob.cn/"; + String[] urlArray = { + "M02/3B/A4/oYYBAFaOeUSAc1QiAAFTbmA7AHs052.jpg", + "M02/3B/A4/oYYBAFaOeUaAfYC-AAFD8zf9NXc879.jpg", + "M02/3B/A4/oYYBAFaOeUuAOxhnAACSdmbqSac702.jpg", + "M02/3B/A4/oYYBAFaOeU2AFAIGAAFICximvXc924.jpg", + "M02/3B/A4/oYYBAFaOeVCAPWMQAAFm2KWCq_E721.jpg", + "M02/3B/A4/oYYBAFaOeVOAbiv9AAFfCTTgr94948.jpg", + "M02/3B/A4/oYYBAFaOeVaAMR3tAAFf3yTuuCM577.jpg", + "M02/3B/A4/oYYBAFaOeVmACEWhAAEt72ecbpg468.jpg", + "M02/3B/A4/oYYBAFaOeVyAHHt4AAFg9e9bRio507.jpg", + "M02/3B/A4/oYYBAFaOeV-AClYXAAESLGY0gag424.jpg", + "M02/3B/A4/oYYBAFaOeWKAA7N0AAF3omYOJUI703.jpg", + "M02/3B/A4/oYYBAFaOeWWAD2lrAAFN7eRFxBs575.jpg", + "M02/3B/A4/oYYBAFaOeWiAdCVEAAFg4273Dus313.jpg", + "M02/3B/A4/oYYBAFaOeWyAJDm5AAF8JVoGVb0705.jpg", + "M02/3B/A4/oYYBAFaOeW-AUoA8AAGjKiHkXUo181.jpg", + "M02/3B/A4/oYYBAFaOeXKABIamAAFU7J7vraE265.jpg", + "M02/3B/A5/oYYBAFaOeXaAW09jAAFf37qdwDA457.jpg", + "M02/3B/A5/oYYBAFaOeXmAWmS7AAFtLNpWjgo967.jpg", + "M02/3B/A5/oYYBAFaOeX2AQf9cAAF2fhwS2UE145.jpg", + "M02/3B/A5/oYYBAFaOeYCAKGnLAAFVAzks-qU937.jpg", + "M02/3B/A5/oYYBAFaOeYOAMODNAAF6HjTTMq4819.jpg", + "M02/3B/A5/oYYBAFaOeYeAbn8uAAFLSQLw48Q042.jpg", + "M02/3B/A5/oYYBAFaOeYqAMJThAAFtrNe4UNM047.jpg", + "M02/3B/A5/oYYBAFaOeY2AbnQvAAFNSXWn0Dc026.jpg", + "M02/3B/A5/oYYBAFaOeZCAIsr0AAFHZFEVhPc682.jpg", + "M02/3B/A5/oYYBAFaOeZOAGvITAAFqPmfcc9c471.jpg", + "M02/3B/A5/oYYBAFaOeZaATvjbAAFHDmALnhE003.jpg", + "M02/3B/A5/oYYBAFaOeZmAJPuVAAFfPJC2wsE319.jpg", + "M02/3B/A5/oYYBAFaOeZyAXtAmAAFfArJNwtM371.jpg", + "M02/3B/A5/oYYBAFaOeZ-AGZN0AAFgqwYYCS8004.jpg", + "M02/3B/A5/oYYBAFaOeaOAbbrGAAFcq59JjUo205.jpg", + "M02/3B/A5/oYYBAFaOeaSAdFyoAACaxVxgUJA092.jpg" + }; + int maxNum = Aria.get(this).getDownloadConfig().getMaxTaskNum(); + Aria.get(this).setDownloadQueueMod(QueueMod.NOW); + for (int i = 0; i < urlArray.length; i++) { + Aria.download(this) + .load(baseUrl + urlArray[i]) + .setFilePath(Environment.getExternalStorageDirectory() + "/test/" + i + ".jpg") + //.addHeader("Accept-Encoding", "gzip,deflate,sdcn") + .start(); + //if (i < maxNum) { + // Aria.download(this) + // .load(baseUrl + urlArray[i]) + // .setDownloadPath(Environment.getExternalStorageDirectory() + "/test/" + i + ".jpg") + // //.addHeader("Accept-Encoding", "gzip,deflate,sdcn") + // .start(); + //} else { + // Aria.download(this) + // .load(baseUrl + urlArray[i]) + // .setDownloadPath(Environment.getExternalStorageDirectory() + "/test/" + i + ".jpg") + // //.addHeader("Accept-Encoding", "gzip,deflate,sdcn") + // .add(); + //} + } + } +} diff --git a/app/src/main/java/com/arialyy/simple/core/upload/FtpUploadActivity.java b/app/src/main/java/com/arialyy/simple/core/upload/FtpUploadActivity.java index 07e4139f..cfc4bebc 100644 --- a/app/src/main/java/com/arialyy/simple/core/upload/FtpUploadActivity.java +++ b/app/src/main/java/com/arialyy/simple/core/upload/FtpUploadActivity.java @@ -1,113 +1,113 @@ -/* - * 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.simple.core.upload; - -import android.os.Bundle; -import android.util.Log; -import android.view.View; -import com.arialyy.annotations.Upload; -import com.arialyy.aria.core.Aria; -import com.arialyy.aria.core.upload.UploadEntity; -import com.arialyy.aria.core.upload.UploadTask; -import com.arialyy.aria.util.CommonUtil; -import com.arialyy.frame.util.FileUtil; -import com.arialyy.frame.util.show.T; -import com.arialyy.simple.R; -import com.arialyy.simple.base.BaseActivity; -import com.arialyy.simple.databinding.ActivityFtpUploadBinding; -import java.io.File; - -/** - * Created by lyy on 2017/7/28. Ftp 文件上传demo - */ -public class FtpUploadActivity extends BaseActivity { - private final String FILE_PATH = "/mnt/sdcard/AriaPrj.rar"; - private final String URL = "ftp://9.9.9.50:21/aa/你好"; - - @Override protected void init(Bundle savedInstanceState) { - setTile("D_FTP 文件上传"); - super.init(savedInstanceState); - Aria.upload(this).register(); - UploadEntity entity = Aria.upload(this).getUploadEntity(FILE_PATH); - if (entity != null) { - getBinding().setFileSize(CommonUtil.formatFileSize(entity.getFileSize())); - getBinding().setProgress(entity.isComplete() ? 100 - : (int) (entity.getCurrentProgress() * 100 / entity.getFileSize())); - } - } - - @Override protected int setLayoutId() { - return R.layout.activity_ftp_upload; - } - - public void onClick(View view) { - switch (view.getId()) { - case R.id.start: - Aria.upload(this).loadFtp(FILE_PATH).setUploadUrl(URL).login("lao", "123456").start(); - break; - case R.id.stop: - Aria.upload(this).loadFtp(FILE_PATH).stop(); - break; - case R.id.cancel: - Aria.upload(this).loadFtp(FILE_PATH).cancel(); - break; - } - } - - @Upload.onWait void onWait(UploadTask task) { - Log.d(TAG, task.getTaskName() + "_wait"); - } - - @Upload.onPre public void onPre(UploadTask task) { - getBinding().setFileSize(task.getConvertFileSize()); - } - - @Upload.onTaskStart public void taskStart(UploadTask task) { - Log.d(TAG, "开始上传,md5:" + FileUtil.getFileMD5(new File(task.getEntity().getFilePath()))); - } - - @Upload.onTaskResume public void taskResume(UploadTask task) { - Log.d(TAG, "恢复上传"); - } - - @Upload.onTaskStop public void taskStop(UploadTask task) { - getBinding().setSpeed(""); - Log.d(TAG, "停止上传"); - } - - @Upload.onTaskCancel public void taskCancel(UploadTask task) { - getBinding().setSpeed(""); - getBinding().setFileSize(""); - getBinding().setProgress(0); - Log.d(TAG, "删除任务"); - } - - @Upload.onTaskFail public void taskFail(UploadTask task) { - Log.d(TAG, "上传失败"); - } - - @Upload.onTaskRunning public void taskRunning(UploadTask task) { - Log.d(TAG, "PP = " + task.getPercent()); - getBinding().setProgress(task.getPercent()); - getBinding().setSpeed(task.getConvertSpeed()); - } - - @Upload.onTaskComplete public void taskComplete(UploadTask task) { - getBinding().setProgress(100); - getBinding().setSpeed(""); - T.showShort(this, "文件:" + task.getEntity().getFileName() + ",上传完成"); - } -} +/* + * 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.simple.core.upload; + +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import com.arialyy.annotations.Upload; +import com.arialyy.aria.core.Aria; +import com.arialyy.aria.core.upload.UploadEntity; +import com.arialyy.aria.core.upload.UploadTask; +import com.arialyy.aria.util.CommonUtil; +import com.arialyy.frame.util.FileUtil; +import com.arialyy.frame.util.show.T; +import com.arialyy.simple.R; +import com.arialyy.simple.base.BaseActivity; +import com.arialyy.simple.databinding.ActivityFtpUploadBinding; +import java.io.File; + +/** + * Created by lyy on 2017/7/28. Ftp 文件上传demo + */ +public class FtpUploadActivity extends BaseActivity { + private final String FILE_PATH = "/mnt/sdcard/AriaPrj.rar"; + private final String URL = "ftp://9.9.9.205:2121/aa/你好"; + + @Override protected void init(Bundle savedInstanceState) { + setTile("D_FTP 文件上传"); + super.init(savedInstanceState); + Aria.upload(this).register(); + UploadEntity entity = Aria.upload(this).getUploadEntity(FILE_PATH); + if (entity != null) { + getBinding().setFileSize(CommonUtil.formatFileSize(entity.getFileSize())); + getBinding().setProgress(entity.isComplete() ? 100 + : (int) (entity.getCurrentProgress() * 100 / entity.getFileSize())); + } + } + + @Override protected int setLayoutId() { + return R.layout.activity_ftp_upload; + } + + public void onClick(View view) { + switch (view.getId()) { + case R.id.start: + Aria.upload(this).loadFtp(FILE_PATH).setUploadUrl(URL).login("lao", "123456").start(); + break; + case R.id.stop: + Aria.upload(this).loadFtp(FILE_PATH).stop(); + break; + case R.id.cancel: + Aria.upload(this).loadFtp(FILE_PATH).cancel(); + break; + } + } + + @Upload.onWait void onWait(UploadTask task) { + Log.d(TAG, task.getTaskName() + "_wait"); + } + + @Upload.onPre public void onPre(UploadTask task) { + getBinding().setFileSize(task.getConvertFileSize()); + } + + @Upload.onTaskStart public void taskStart(UploadTask task) { + Log.d(TAG, "开始上传,md5:" + FileUtil.getFileMD5(new File(task.getEntity().getFilePath()))); + } + + @Upload.onTaskResume public void taskResume(UploadTask task) { + Log.d(TAG, "恢复上传"); + } + + @Upload.onTaskStop public void taskStop(UploadTask task) { + getBinding().setSpeed(""); + Log.d(TAG, "停止上传"); + } + + @Upload.onTaskCancel public void taskCancel(UploadTask task) { + getBinding().setSpeed(""); + getBinding().setFileSize(""); + getBinding().setProgress(0); + Log.d(TAG, "删除任务"); + } + + @Upload.onTaskFail public void taskFail(UploadTask task) { + Log.d(TAG, "上传失败"); + } + + @Upload.onTaskRunning public void taskRunning(UploadTask task) { + Log.d(TAG, "PP = " + task.getPercent()); + getBinding().setProgress(task.getPercent()); + getBinding().setSpeed(task.getConvertSpeed()); + } + + @Upload.onTaskComplete public void taskComplete(UploadTask task) { + getBinding().setProgress(100); + getBinding().setSpeed(""); + T.showShort(this, "文件:" + task.getEntity().getFileName() + ",上传完成"); + } +}