移除`getDownloadTask(String url)`、`getGroupTask(List<String>urls)`、`getFtpDirTask(String path)`等获取任务的api 修复使用`Content-Disposition`的文件名时,第一次下载无法重命名文件的问题 修复使用`Content-Disposition`的文件名时,多次重命名文件的问题v3.6.6
parent
0a447787ea
commit
8c0ef0f879
@ -1,475 +1,458 @@ |
||||
/* |
||||
* 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.support.annotation.CheckResult; |
||||
import android.support.annotation.NonNull; |
||||
import android.text.TextUtils; |
||||
import com.arialyy.aria.core.AriaManager; |
||||
import com.arialyy.aria.core.command.ICmd; |
||||
import com.arialyy.aria.core.command.normal.CancelAllCmd; |
||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory; |
||||
import com.arialyy.aria.core.common.ProxyHelper; |
||||
import com.arialyy.aria.core.inf.AbsEntity; |
||||
import com.arialyy.aria.core.inf.AbsReceiver; |
||||
import com.arialyy.aria.core.inf.ReceiverType; |
||||
import com.arialyy.aria.core.manager.TaskWrapperManager; |
||||
import com.arialyy.aria.core.scheduler.DownloadGroupSchedulers; |
||||
import com.arialyy.aria.core.scheduler.DownloadSchedulers; |
||||
import com.arialyy.aria.orm.DbEntity; |
||||
import com.arialyy.aria.util.ALog; |
||||
import com.arialyy.aria.util.CheckUtil; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* Created by lyy on 2016/12/5. |
||||
* 下载功能接收器 |
||||
*/ |
||||
public class DownloadReceiver extends AbsReceiver { |
||||
private final String TAG = "DownloadReceiver"; |
||||
|
||||
/** |
||||
* 设置最大下载速度,单位:kb |
||||
* |
||||
* @param maxSpeed 为0表示不限速 |
||||
* @deprecated {@code Aria.get(Context).getDownloadConfig().setMaxSpeed(int)} |
||||
*/ |
||||
@Deprecated |
||||
public DownloadReceiver setMaxSpeed(int maxSpeed) { |
||||
AriaManager.getInstance(AriaManager.APP).getDownloadConfig().setMaxSpeed(maxSpeed); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* 使用下载实体执行下载操作 |
||||
* |
||||
* @param entity 下载实体 |
||||
*/ |
||||
@CheckResult |
||||
public DownloadTarget load(DownloadEntity entity) { |
||||
CheckUtil.checkUrlInvalidThrow(entity.getUrl()); |
||||
return new DownloadTarget(entity, targetName); |
||||
} |
||||
|
||||
/** |
||||
* 加载Http、https单任务下载地址 |
||||
* |
||||
* @param url 下载地址 |
||||
*/ |
||||
@CheckResult |
||||
public DownloadTarget load(@NonNull String url) { |
||||
CheckUtil.checkUrlInvalidThrow(url); |
||||
return new DownloadTarget(url, targetName); |
||||
} |
||||
|
||||
/** |
||||
* 加载下载地址,如果任务组的中的下载地址改变了,则任务从新的一个任务组 |
||||
* |
||||
* @param urls 任务组子任务下载地址列表 |
||||
* @deprecated {@link #loadGroup(DownloadGroupEntity)} |
||||
*/ |
||||
@Deprecated |
||||
@CheckResult |
||||
public DownloadGroupTarget load(List<String> urls) { |
||||
return loadGroup(urls); |
||||
} |
||||
|
||||
/** |
||||
* 加载下载地址,如果任务组的中的下载地址改变了,则任务从新的一个任务组 |
||||
*/ |
||||
@CheckResult |
||||
public DownloadGroupTarget loadGroup(List<String> urls) { |
||||
CheckUtil.checkDownloadUrls(urls); |
||||
return new DownloadGroupTarget(urls, targetName); |
||||
} |
||||
|
||||
/** |
||||
* 使用下载实体执行FTP下载操作 |
||||
* |
||||
* @param entity 下载实体 |
||||
*/ |
||||
@CheckResult |
||||
public FtpDownloadTarget loadFtp(DownloadEntity entity) { |
||||
CheckUtil.checkUrlInvalidThrow(entity.getUrl()); |
||||
return new FtpDownloadTarget(entity, targetName); |
||||
} |
||||
|
||||
/** |
||||
* 加载ftp单任务下载地址 |
||||
*/ |
||||
@CheckResult |
||||
public FtpDownloadTarget loadFtp(@NonNull String url) { |
||||
CheckUtil.checkUrlInvalidThrow(url); |
||||
return new FtpDownloadTarget(url, targetName); |
||||
} |
||||
|
||||
/** |
||||
* 使用任务组实体执行任务组的实体执行任务组的下载操作,后续版本会删除该api |
||||
* |
||||
* @param groupEntity 如果加载的任务实体没有子项的下载地址, |
||||
* 那么你需要使用{@link DownloadGroupTarget#setGroupUrl(List)}设置子项的下载地址 |
||||
* @deprecated 请使用 {@link #loadGroup(DownloadGroupEntity)} |
||||
*/ |
||||
@Deprecated |
||||
@CheckResult |
||||
public DownloadGroupTarget load(DownloadGroupEntity groupEntity) { |
||||
CheckUtil.checkDownloadUrls(groupEntity.getUrls()); |
||||
return loadGroup(groupEntity); |
||||
} |
||||
|
||||
/** |
||||
* 使用任务组实体执行任务组的实体执行任务组的下载操作 |
||||
* |
||||
* @param groupEntity 如果加载的任务实体没有子项的下载地址, |
||||
* 那么你需要使用{@link DownloadGroupTarget#setGroupUrl(List)}设置子项的下载地址 |
||||
*/ |
||||
@CheckResult |
||||
public DownloadGroupTarget loadGroup(DownloadGroupEntity groupEntity) { |
||||
CheckUtil.checkDownloadUrls(groupEntity.getUrls()); |
||||
return new DownloadGroupTarget(groupEntity, targetName); |
||||
} |
||||
|
||||
/** |
||||
* 加载ftp文件夹下载地址 |
||||
*/ |
||||
@CheckResult |
||||
public FtpDirDownloadTarget loadFtpDir(@NonNull String dirUrl) { |
||||
CheckUtil.checkUrlInvalidThrow(dirUrl); |
||||
return new FtpDirDownloadTarget(dirUrl, targetName); |
||||
} |
||||
|
||||
/** |
||||
* 将当前类注册到Aria |
||||
*/ |
||||
public void register() { |
||||
if (TextUtils.isEmpty(targetName)) { |
||||
ALog.e(TAG, "download register target null"); |
||||
return; |
||||
} |
||||
Object obj = OBJ_MAP.get(getKey()); |
||||
if (obj == null) { |
||||
ALog.e(TAG, String.format("【%s】观察者为空", targetName)); |
||||
return; |
||||
} |
||||
Set<Integer> set = ProxyHelper.getInstance().checkProxyType(obj.getClass()); |
||||
if (set != null && !set.isEmpty()) { |
||||
for (Integer type : set) { |
||||
if (type == ProxyHelper.PROXY_TYPE_DOWNLOAD) { |
||||
DownloadSchedulers.getInstance().register(obj); |
||||
} else if (type == ProxyHelper.PROXY_TYPE_DOWNLOAD_GROUP) { |
||||
DownloadGroupSchedulers.getInstance().register(obj); |
||||
} |
||||
} |
||||
} else { |
||||
ALog.w(TAG, "没有Aria的注解方法"); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 取消注册,如果是Activity或fragment,Aria会界面销毁时自动调用该方法,不需要你手动调用。 |
||||
* 注意事项: |
||||
* 1、如果在activity中一定要调用该方法,那么请在{@code onDestroy()}中调用 |
||||
* 2、不要在activity的{@code onStop()}中调用改方法 |
||||
* 3、如果是Dialog或popupwindow,需要你在撤销界面时调用该方法 |
||||
* 4、如果你是在Module(非android组件类)中注册了Aria,那么你也需要在Module类中调用该方法,而不是在组件类中 |
||||
* 调用销毁,详情见 |
||||
* |
||||
* @see <a href="https://aria.laoyuyu.me/aria_doc/start/any_java.html#%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9">module类中销毁</a> |
||||
*/ |
||||
@Override public void unRegister() { |
||||
if (needRmListener) { |
||||
unRegisterListener(); |
||||
} |
||||
AriaManager.getInstance(AriaManager.APP).removeReceiver(OBJ_MAP.get(getKey())); |
||||
} |
||||
|
||||
@Override public String getType() { |
||||
return ReceiverType.DOWNLOAD; |
||||
} |
||||
|
||||
@Override protected void unRegisterListener() { |
||||
if (TextUtils.isEmpty(targetName)) { |
||||
ALog.e(TAG, "download unRegisterListener target null"); |
||||
return; |
||||
} |
||||
Object obj = OBJ_MAP.get(getKey()); |
||||
if (obj == null) { |
||||
ALog.e(TAG, String.format("【%s】观察者为空", targetName)); |
||||
return; |
||||
} |
||||
Set<Integer> set = ProxyHelper.getInstance().mProxyCache.get(obj.getClass().getName()); |
||||
if (set != null) { |
||||
for (Integer integer : set) { |
||||
if (integer == ProxyHelper.PROXY_TYPE_DOWNLOAD) { |
||||
DownloadSchedulers.getInstance().unRegister(obj); |
||||
} else if (integer == ProxyHelper.PROXY_TYPE_DOWNLOAD_GROUP) { |
||||
DownloadGroupSchedulers.getInstance().unRegister(obj); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 通过下载链接获取下载实体 |
||||
* |
||||
* @return 如果url错误或查找不到数据,则返回null |
||||
*/ |
||||
public DownloadEntity getDownloadEntity(String downloadUrl) { |
||||
if (!CheckUtil.checkUrl(downloadUrl)) { |
||||
return null; |
||||
} |
||||
return DbEntity.findFirst(DownloadEntity.class, "url=? and isGroupChild='false'", downloadUrl); |
||||
} |
||||
|
||||
/** |
||||
* 通过下载地址和文件保存路径获取下载任务实体 |
||||
* |
||||
* @param downloadUrl 下载地址 |
||||
* @return 如果url错误或查找不到数据,则返回null |
||||
*/ |
||||
public DTaskWrapper getDownloadTask(String downloadUrl) { |
||||
if (!CheckUtil.checkUrl(downloadUrl)) { |
||||
return null; |
||||
} |
||||
if (!taskExists(downloadUrl)) { |
||||
return null; |
||||
} |
||||
return TaskWrapperManager.getInstance().getHttpTaskWrapper(DTaskWrapper.class, downloadUrl); |
||||
} |
||||
|
||||
/** |
||||
* 通过下载链接获取保存在数据库的下载任务组实体 |
||||
* |
||||
* @param urls 任务组子任务下载地址列表 |
||||
* @return 返回对应的任务组实体;如果查找不到对应的数据或子任务列表为null,返回null |
||||
*/ |
||||
public DGTaskWrapper getGroupTask(List<String> urls) { |
||||
if (urls == null || urls.isEmpty()) { |
||||
ALog.e(TAG, "获取任务组实体失败:任务组子任务下载地址列表为null"); |
||||
return null; |
||||
} |
||||
if (!taskExists(urls)) { |
||||
return null; |
||||
} |
||||
return TaskWrapperManager.getInstance().getDGTaskWrapper(DGTaskWrapper.class, urls); |
||||
} |
||||
|
||||
/** |
||||
* 获取FTP文件夹下载任务实体 |
||||
* |
||||
* @param dirUrl FTP文件夹本地下载路径 |
||||
* @return 返回对应的任务组实体;如果查找不到对应的数据或路径为null,返回null |
||||
*/ |
||||
public DGTaskWrapper getFtpDirTask(String dirUrl) { |
||||
if (TextUtils.isEmpty(dirUrl)) { |
||||
ALog.e(TAG, "获取FTP文件夹实体失败:下载路径为null"); |
||||
return null; |
||||
} |
||||
boolean b = |
||||
DownloadGroupEntity.findFirst(DownloadGroupEntity.class, "groupHash=?", dirUrl) != null; |
||||
if (!b) { |
||||
return null; |
||||
} |
||||
return TaskWrapperManager.getInstance().getFtpTaskWrapper(DGTaskWrapper.class, dirUrl); |
||||
} |
||||
|
||||
/** |
||||
* 下载任务是否存在 |
||||
* |
||||
* @return {@code true}存在,{@code false} 不存在 |
||||
*/ |
||||
public boolean taskExists(String downloadUrl) { |
||||
return DbEntity.checkDataExist(DownloadEntity.class, "url=?", downloadUrl); |
||||
} |
||||
|
||||
/** |
||||
* 判断任务组是否存在 |
||||
* |
||||
* @return {@code true} 存在;{@code false} 不存在 |
||||
*/ |
||||
public boolean taskExists(List<String> urls) { |
||||
if (urls == null || urls.isEmpty()) { |
||||
return false; |
||||
} |
||||
String groupHash = CommonUtil.getMd5Code(urls); |
||||
return DbEntity.checkDataExist(DownloadGroupEntity.class, "groupHash=?", groupHash); |
||||
} |
||||
|
||||
/** |
||||
* 获取所有普通下载任务 |
||||
* 获取未完成的普通任务列表{@link #getAllNotCompleteTask()} |
||||
* 获取已经完成的普通任务列表{@link #getAllCompleteTask()} |
||||
*/ |
||||
public List<DownloadEntity> getTaskList() { |
||||
return DbEntity.findDatas(DownloadEntity.class, "isGroupChild=? and downloadPath!=''", |
||||
"false"); |
||||
} |
||||
|
||||
/** |
||||
* 分页获取所有普通下载任务 |
||||
* 获取未完成的普通任务列表{@link #getAllNotCompleteTask()} |
||||
* 获取已经完成的普通任务列表{@link #getAllCompleteTask()} |
||||
* |
||||
* @param page 当前页,不能小于1 |
||||
* @param num 每页数量,不能小于1 |
||||
* @return 如果页数大于总页数,返回null |
||||
*/ |
||||
public List<DownloadEntity> getTaskList(int page, int num) { |
||||
CheckUtil.checkPageParams(page, num); |
||||
return DbEntity.findDatas(DownloadEntity.class, page, num, |
||||
"isGroupChild=? and downloadPath!=''", "false"); |
||||
} |
||||
|
||||
/** |
||||
* 获取所有未完成的普通下载任务 |
||||
*/ |
||||
public List<DownloadEntity> getAllNotCompleteTask() { |
||||
return DbEntity.findDatas(DownloadEntity.class, |
||||
"isGroupChild=? and downloadPath!='' and isComplete=?", "false", "false"); |
||||
} |
||||
|
||||
/** |
||||
* 分页获取所有未完成的普通下载任务 |
||||
* |
||||
* @param page 当前页,不能小于1 |
||||
* @param num 每页数量,不能小于1 |
||||
* @return 如果页数大于总页数,返回null |
||||
*/ |
||||
public List<DownloadEntity> getAllNotCompleteTask(int page, int num) { |
||||
CheckUtil.checkPageParams(page, num); |
||||
return DbEntity.findDatas(DownloadEntity.class, page, num, |
||||
"isGroupChild=? and downloadPath!='' and isComplete=?", "false", "false"); |
||||
} |
||||
|
||||
/** |
||||
* 获取所有已经完成的普通任务 |
||||
*/ |
||||
public List<DownloadEntity> getAllCompleteTask() { |
||||
return DbEntity.findDatas(DownloadEntity.class, |
||||
"isGroupChild=? and downloadPath!='' and isComplete=?", "false", "true"); |
||||
} |
||||
|
||||
/** |
||||
* 分页获取所有已经完成的普通任务 |
||||
* |
||||
* @param page 当前页,不能小于1 |
||||
* @param num 每页数量,不能小于1 |
||||
* @return 如果页数大于总页数,返回null |
||||
*/ |
||||
public List<DownloadEntity> getAllCompleteTask(int page, int num) { |
||||
CheckUtil.checkPageParams(page, num); |
||||
return DbEntity.findDatas(DownloadEntity.class, |
||||
"isGroupChild=? and downloadPath!='' and isComplete=?", "false", "true"); |
||||
} |
||||
|
||||
/** |
||||
* 获取任务组列表 |
||||
* |
||||
* @return 如果没有任务组列表,则返回null |
||||
*/ |
||||
public List<DownloadGroupEntity> getGroupTaskList() { |
||||
List<DGEntityWrapper> wrappers = DbEntity.findRelationData(DGEntityWrapper.class); |
||||
if (wrappers == null || wrappers.isEmpty()) { |
||||
return null; |
||||
} |
||||
List<DownloadGroupEntity> entities = new ArrayList<>(); |
||||
for (DGEntityWrapper wrapper : wrappers) { |
||||
entities.add(wrapper.groupEntity); |
||||
} |
||||
return entities; |
||||
} |
||||
|
||||
/** |
||||
* 分页获取祝贺任务列表 |
||||
* |
||||
* @param page 当前页,不能小于1 |
||||
* @param num 每页数量,不能小于1 |
||||
* @return 如果没有任务组列表,则返回null |
||||
*/ |
||||
public List<DownloadGroupEntity> getGroupTaskList(int page, int num) { |
||||
List<DGEntityWrapper> wrappers = DbEntity.findRelationData(DGEntityWrapper.class, page, num); |
||||
if (wrappers == null || wrappers.isEmpty()) { |
||||
return null; |
||||
} |
||||
List<DownloadGroupEntity> entities = new ArrayList<>(); |
||||
for (DGEntityWrapper wrapper : wrappers) { |
||||
entities.add(wrapper.groupEntity); |
||||
} |
||||
return entities; |
||||
} |
||||
|
||||
/** |
||||
* 获取普通任务和任务组的任务列表 |
||||
*/ |
||||
public List<AbsEntity> getTotalTaskList() { |
||||
List<AbsEntity> list = new ArrayList<>(); |
||||
List<DownloadEntity> simpleTask = getTaskList(); |
||||
List<DownloadGroupEntity> groupTask = getGroupTaskList(); |
||||
if (simpleTask != null && !simpleTask.isEmpty()) { |
||||
list.addAll(simpleTask); |
||||
} |
||||
if (groupTask != null && !groupTask.isEmpty()) { |
||||
list.addAll(groupTask); |
||||
} |
||||
return list; |
||||
} |
||||
|
||||
/** |
||||
* 停止所有正在下载的任务,并清空等待队列。 |
||||
*/ |
||||
public void stopAllTask() { |
||||
AriaManager.getInstance(AriaManager.APP) |
||||
.setCmd(NormalCmdFactory.getInstance() |
||||
.createCmd(new DTaskWrapper(null), NormalCmdFactory.TASK_STOP_ALL, |
||||
ICmd.TASK_TYPE_DOWNLOAD)) |
||||
.exe(); |
||||
} |
||||
|
||||
/** |
||||
* 恢复所有正在下载的任务 |
||||
* 1.如果执行队列没有满,则开始下载任务,直到执行队列满 |
||||
* 2.如果队列执行队列已经满了,则将所有任务添加到等待队列中 |
||||
*/ |
||||
public void resumeAllTask() { |
||||
AriaManager.getInstance(AriaManager.APP) |
||||
.setCmd(NormalCmdFactory.getInstance() |
||||
.createCmd(new DTaskWrapper(null), NormalCmdFactory.TASK_RESUME_ALL, |
||||
ICmd.TASK_TYPE_DOWNLOAD)) |
||||
.exe(); |
||||
} |
||||
|
||||
/** |
||||
* 删除所有任务 |
||||
* |
||||
* @param removeFile {@code true} 删除已经下载完成的任务,不仅删除下载记录,还会删除已经下载完成的文件,{@code false} |
||||
* 如果文件已经下载完成,只删除下载记录 |
||||
*/ |
||||
public void removeAllTask(boolean removeFile) { |
||||
final AriaManager ariaManager = AriaManager.getInstance(AriaManager.APP); |
||||
CancelAllCmd cancelCmd = |
||||
(CancelAllCmd) CommonUtil.createNormalCmd(new DTaskWrapper(null), |
||||
NormalCmdFactory.TASK_CANCEL_ALL, ICmd.TASK_TYPE_DOWNLOAD); |
||||
cancelCmd.removeFile = removeFile; |
||||
ariaManager.setCmd(cancelCmd).exe(); |
||||
Set<String> keys = ariaManager.getReceiver().keySet(); |
||||
for (String key : keys) { |
||||
ariaManager.getReceiver().remove(key); |
||||
} |
||||
} |
||||
/* |
||||
* 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.support.annotation.CheckResult; |
||||
import android.support.annotation.NonNull; |
||||
import android.text.TextUtils; |
||||
import com.arialyy.annotations.DownloadGroup; |
||||
import com.arialyy.aria.core.AriaManager; |
||||
import com.arialyy.aria.core.command.ICmd; |
||||
import com.arialyy.aria.core.command.normal.CancelAllCmd; |
||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory; |
||||
import com.arialyy.aria.core.common.ProxyHelper; |
||||
import com.arialyy.aria.core.inf.AbsEntity; |
||||
import com.arialyy.aria.core.inf.AbsReceiver; |
||||
import com.arialyy.aria.core.inf.ReceiverType; |
||||
import com.arialyy.aria.core.manager.TaskWrapperManager; |
||||
import com.arialyy.aria.core.scheduler.DownloadGroupSchedulers; |
||||
import com.arialyy.aria.core.scheduler.DownloadSchedulers; |
||||
import com.arialyy.aria.orm.DbEntity; |
||||
import com.arialyy.aria.util.ALog; |
||||
import com.arialyy.aria.util.CheckUtil; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import com.arialyy.aria.util.DbDataHelper; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* Created by lyy on 2016/12/5. |
||||
* 下载功能接收器 |
||||
*/ |
||||
public class DownloadReceiver extends AbsReceiver { |
||||
private final String TAG = "DownloadReceiver"; |
||||
|
||||
/** |
||||
* 设置最大下载速度,单位:kb |
||||
* |
||||
* @param maxSpeed 为0表示不限速 |
||||
* @deprecated {@code Aria.get(Context).getDownloadConfig().setMaxSpeed(int)} |
||||
*/ |
||||
@Deprecated |
||||
public DownloadReceiver setMaxSpeed(int maxSpeed) { |
||||
AriaManager.getInstance(AriaManager.APP).getDownloadConfig().setMaxSpeed(maxSpeed); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* 使用下载实体执行下载操作 |
||||
* |
||||
* @param entity 下载实体 |
||||
*/ |
||||
@CheckResult |
||||
public DownloadTarget load(DownloadEntity entity) { |
||||
CheckUtil.checkUrlInvalidThrow(entity.getUrl()); |
||||
return new DownloadTarget(entity, targetName); |
||||
} |
||||
|
||||
/** |
||||
* 加载Http、https单任务下载地址 |
||||
* |
||||
* @param url 下载地址 |
||||
*/ |
||||
@CheckResult |
||||
public DownloadTarget load(@NonNull String url) { |
||||
CheckUtil.checkUrlInvalidThrow(url); |
||||
return new DownloadTarget(url, targetName); |
||||
} |
||||
|
||||
/** |
||||
* 加载下载地址,如果任务组的中的下载地址改变了,则任务从新的一个任务组 |
||||
* |
||||
* @param urls 任务组子任务下载地址列表 |
||||
* @deprecated {@link #loadGroup(DownloadGroupEntity)} |
||||
*/ |
||||
@Deprecated |
||||
@CheckResult |
||||
public DownloadGroupTarget load(List<String> urls) { |
||||
return loadGroup(urls); |
||||
} |
||||
|
||||
/** |
||||
* 加载下载地址,如果任务组的中的下载地址改变了,则任务从新的一个任务组 |
||||
*/ |
||||
@CheckResult |
||||
public DownloadGroupTarget loadGroup(List<String> urls) { |
||||
CheckUtil.checkDownloadUrls(urls); |
||||
return new DownloadGroupTarget(urls, targetName); |
||||
} |
||||
|
||||
/** |
||||
* 使用下载实体执行FTP下载操作 |
||||
* |
||||
* @param entity 下载实体 |
||||
*/ |
||||
@CheckResult |
||||
public FtpDownloadTarget loadFtp(DownloadEntity entity) { |
||||
CheckUtil.checkUrlInvalidThrow(entity.getUrl()); |
||||
return new FtpDownloadTarget(entity, targetName); |
||||
} |
||||
|
||||
/** |
||||
* 加载ftp单任务下载地址 |
||||
*/ |
||||
@CheckResult |
||||
public FtpDownloadTarget loadFtp(@NonNull String url) { |
||||
CheckUtil.checkUrlInvalidThrow(url); |
||||
return new FtpDownloadTarget(url, targetName); |
||||
} |
||||
|
||||
/** |
||||
* 使用任务组实体执行任务组的实体执行任务组的下载操作,后续版本会删除该api |
||||
* |
||||
* @param groupEntity 如果加载的任务实体没有子项的下载地址, |
||||
* 那么你需要使用{@link DownloadGroupTarget#setGroupUrl(List)}设置子项的下载地址 |
||||
* @deprecated 请使用 {@link #loadGroup(DownloadGroupEntity)} |
||||
*/ |
||||
@Deprecated |
||||
@CheckResult |
||||
public DownloadGroupTarget load(DownloadGroupEntity groupEntity) { |
||||
CheckUtil.checkDownloadUrls(groupEntity.getUrls()); |
||||
return loadGroup(groupEntity); |
||||
} |
||||
|
||||
/** |
||||
* 使用任务组实体执行任务组的实体执行任务组的下载操作 |
||||
* |
||||
* @param groupEntity 如果加载的任务实体没有子项的下载地址, |
||||
* 那么你需要使用{@link DownloadGroupTarget#setGroupUrl(List)}设置子项的下载地址 |
||||
*/ |
||||
@CheckResult |
||||
public DownloadGroupTarget loadGroup(DownloadGroupEntity groupEntity) { |
||||
CheckUtil.checkDownloadUrls(groupEntity.getUrls()); |
||||
return new DownloadGroupTarget(groupEntity, targetName); |
||||
} |
||||
|
||||
/** |
||||
* 加载ftp文件夹下载地址 |
||||
*/ |
||||
@CheckResult |
||||
public FtpDirDownloadTarget loadFtpDir(@NonNull String dirUrl) { |
||||
CheckUtil.checkUrlInvalidThrow(dirUrl); |
||||
return new FtpDirDownloadTarget(dirUrl, targetName); |
||||
} |
||||
|
||||
/** |
||||
* 将当前类注册到Aria |
||||
*/ |
||||
public void register() { |
||||
if (TextUtils.isEmpty(targetName)) { |
||||
ALog.e(TAG, "download register target null"); |
||||
return; |
||||
} |
||||
Object obj = OBJ_MAP.get(getKey()); |
||||
if (obj == null) { |
||||
ALog.e(TAG, String.format("【%s】观察者为空", targetName)); |
||||
return; |
||||
} |
||||
Set<Integer> set = ProxyHelper.getInstance().checkProxyType(obj.getClass()); |
||||
if (set != null && !set.isEmpty()) { |
||||
for (Integer type : set) { |
||||
if (type == ProxyHelper.PROXY_TYPE_DOWNLOAD) { |
||||
DownloadSchedulers.getInstance().register(obj); |
||||
} else if (type == ProxyHelper.PROXY_TYPE_DOWNLOAD_GROUP) { |
||||
DownloadGroupSchedulers.getInstance().register(obj); |
||||
} |
||||
} |
||||
} else { |
||||
ALog.w(TAG, "没有Aria的注解方法"); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 取消注册,如果是Activity或fragment,Aria会界面销毁时自动调用该方法,不需要你手动调用。 |
||||
* 注意事项: |
||||
* 1、如果在activity中一定要调用该方法,那么请在{@code onDestroy()}中调用 |
||||
* 2、不要在activity的{@code onStop()}中调用改方法 |
||||
* 3、如果是Dialog或popupwindow,需要你在撤销界面时调用该方法 |
||||
* 4、如果你是在Module(非android组件类)中注册了Aria,那么你也需要在Module类中调用该方法,而不是在组件类中 |
||||
* 调用销毁,详情见 |
||||
* |
||||
* @see <a href="https://aria.laoyuyu.me/aria_doc/start/any_java.html#%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9">module类中销毁</a> |
||||
*/ |
||||
@Override public void unRegister() { |
||||
if (needRmListener) { |
||||
unRegisterListener(); |
||||
} |
||||
AriaManager.getInstance(AriaManager.APP).removeReceiver(OBJ_MAP.get(getKey())); |
||||
} |
||||
|
||||
@Override public String getType() { |
||||
return ReceiverType.DOWNLOAD; |
||||
} |
||||
|
||||
@Override protected void unRegisterListener() { |
||||
if (TextUtils.isEmpty(targetName)) { |
||||
ALog.e(TAG, "download unRegisterListener target null"); |
||||
return; |
||||
} |
||||
Object obj = OBJ_MAP.get(getKey()); |
||||
if (obj == null) { |
||||
ALog.e(TAG, String.format("【%s】观察者为空", targetName)); |
||||
return; |
||||
} |
||||
Set<Integer> set = ProxyHelper.getInstance().mProxyCache.get(obj.getClass().getName()); |
||||
if (set != null) { |
||||
for (Integer integer : set) { |
||||
if (integer == ProxyHelper.PROXY_TYPE_DOWNLOAD) { |
||||
DownloadSchedulers.getInstance().unRegister(obj); |
||||
} else if (integer == ProxyHelper.PROXY_TYPE_DOWNLOAD_GROUP) { |
||||
DownloadGroupSchedulers.getInstance().unRegister(obj); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 通过下载链接获取下载实体 |
||||
* |
||||
* @return 如果url错误或查找不到数据,则返回null |
||||
*/ |
||||
public DownloadEntity getDownloadEntity(String downloadUrl) { |
||||
CheckUtil.checkUrl(downloadUrl); |
||||
return DbEntity.findFirst(DownloadEntity.class, "url=? and isGroupChild='false'", downloadUrl); |
||||
} |
||||
|
||||
/** |
||||
* 获取组合任务实在实体 |
||||
* |
||||
* @param urls 组合任务的url |
||||
* @return 如果实体不存在,返回null |
||||
*/ |
||||
public DownloadGroupEntity getDownloadGroupEntity(List<String> urls) { |
||||
CheckUtil.checkDownloadUrls(urls); |
||||
return DbDataHelper.getDGEntity(CommonUtil.getMd5Code(urls)); |
||||
} |
||||
|
||||
/** |
||||
* 获取组合任务实在实体 |
||||
* |
||||
* @param key 组合任务的key,{@link DownloadGroupEntity#getKey()} |
||||
* @return 如果实体不存在,返回null |
||||
*/ |
||||
public DownloadGroupEntity getDownloadGroupEntity(String key) { |
||||
if (TextUtils.isEmpty(key)) { |
||||
throw new IllegalArgumentException("key为空"); |
||||
} |
||||
return DbDataHelper.getDGEntity(key); |
||||
} |
||||
|
||||
/** |
||||
* 获取Ftp文件夹任务的实体 |
||||
* |
||||
* @param url ftp文件夹下载路径 |
||||
* @return 如果实体不存在,返回null |
||||
*/ |
||||
public DownloadGroupEntity getFtpDirEntity(String url) { |
||||
CheckUtil.checkUrl(url); |
||||
return DbDataHelper.getDGEntity(url); |
||||
} |
||||
|
||||
/** |
||||
* 下载任务是否存在 |
||||
* |
||||
* @return {@code true}存在,{@code false} 不存在 |
||||
*/ |
||||
public boolean taskExists(String downloadUrl) { |
||||
return DbEntity.checkDataExist(DownloadEntity.class, "url=?", downloadUrl); |
||||
} |
||||
|
||||
/** |
||||
* 判断任务组是否存在 |
||||
* |
||||
* @return {@code true} 存在;{@code false} 不存在 |
||||
*/ |
||||
public boolean taskExists(List<String> urls) { |
||||
if (urls == null || urls.isEmpty()) { |
||||
return false; |
||||
} |
||||
String groupHash = CommonUtil.getMd5Code(urls); |
||||
return DbEntity.checkDataExist(DownloadGroupEntity.class, "groupHash=?", groupHash); |
||||
} |
||||
|
||||
/** |
||||
* 获取所有普通下载任务 |
||||
* 获取未完成的普通任务列表{@link #getAllNotCompleteTask()} |
||||
* 获取已经完成的普通任务列表{@link #getAllCompleteTask()} |
||||
*/ |
||||
public List<DownloadEntity> getTaskList() { |
||||
return DbEntity.findDatas(DownloadEntity.class, "isGroupChild=? and downloadPath!=''", |
||||
"false"); |
||||
} |
||||
|
||||
/** |
||||
* 分页获取所有普通下载任务 |
||||
* 获取未完成的普通任务列表{@link #getAllNotCompleteTask()} |
||||
* 获取已经完成的普通任务列表{@link #getAllCompleteTask()} |
||||
* |
||||
* @param page 当前页,不能小于1 |
||||
* @param num 每页数量,不能小于1 |
||||
* @return 如果页数大于总页数,返回null |
||||
*/ |
||||
public List<DownloadEntity> getTaskList(int page, int num) { |
||||
CheckUtil.checkPageParams(page, num); |
||||
return DbEntity.findDatas(DownloadEntity.class, page, num, |
||||
"isGroupChild=? and downloadPath!=''", "false"); |
||||
} |
||||
|
||||
/** |
||||
* 获取所有未完成的普通下载任务 |
||||
*/ |
||||
public List<DownloadEntity> getAllNotCompleteTask() { |
||||
return DbEntity.findDatas(DownloadEntity.class, |
||||
"isGroupChild=? and downloadPath!='' and isComplete=?", "false", "false"); |
||||
} |
||||
|
||||
/** |
||||
* 分页获取所有未完成的普通下载任务 |
||||
* |
||||
* @param page 当前页,不能小于1 |
||||
* @param num 每页数量,不能小于1 |
||||
* @return 如果页数大于总页数,返回null |
||||
*/ |
||||
public List<DownloadEntity> getAllNotCompleteTask(int page, int num) { |
||||
CheckUtil.checkPageParams(page, num); |
||||
return DbEntity.findDatas(DownloadEntity.class, page, num, |
||||
"isGroupChild=? and downloadPath!='' and isComplete=?", "false", "false"); |
||||
} |
||||
|
||||
/** |
||||
* 获取所有已经完成的普通任务 |
||||
*/ |
||||
public List<DownloadEntity> getAllCompleteTask() { |
||||
return DbEntity.findDatas(DownloadEntity.class, |
||||
"isGroupChild=? and downloadPath!='' and isComplete=?", "false", "true"); |
||||
} |
||||
|
||||
/** |
||||
* 分页获取所有已经完成的普通任务 |
||||
* |
||||
* @param page 当前页,不能小于1 |
||||
* @param num 每页数量,不能小于1 |
||||
* @return 如果页数大于总页数,返回null |
||||
*/ |
||||
public List<DownloadEntity> getAllCompleteTask(int page, int num) { |
||||
CheckUtil.checkPageParams(page, num); |
||||
return DbEntity.findDatas(DownloadEntity.class, |
||||
"isGroupChild=? and downloadPath!='' and isComplete=?", "false", "true"); |
||||
} |
||||
|
||||
/** |
||||
* 获取任务组列表 |
||||
* |
||||
* @return 如果没有任务组列表,则返回null |
||||
*/ |
||||
public List<DownloadGroupEntity> getGroupTaskList() { |
||||
List<DGEntityWrapper> wrappers = DbEntity.findRelationData(DGEntityWrapper.class); |
||||
if (wrappers == null || wrappers.isEmpty()) { |
||||
return null; |
||||
} |
||||
List<DownloadGroupEntity> entities = new ArrayList<>(); |
||||
for (DGEntityWrapper wrapper : wrappers) { |
||||
entities.add(wrapper.groupEntity); |
||||
} |
||||
return entities; |
||||
} |
||||
|
||||
/** |
||||
* 分页获取祝贺任务列表 |
||||
* |
||||
* @param page 当前页,不能小于1 |
||||
* @param num 每页数量,不能小于1 |
||||
* @return 如果没有任务组列表,则返回null |
||||
*/ |
||||
public List<DownloadGroupEntity> getGroupTaskList(int page, int num) { |
||||
List<DGEntityWrapper> wrappers = DbEntity.findRelationData(DGEntityWrapper.class, page, num); |
||||
if (wrappers == null || wrappers.isEmpty()) { |
||||
return null; |
||||
} |
||||
List<DownloadGroupEntity> entities = new ArrayList<>(); |
||||
for (DGEntityWrapper wrapper : wrappers) { |
||||
entities.add(wrapper.groupEntity); |
||||
} |
||||
return entities; |
||||
} |
||||
|
||||
/** |
||||
* 获取普通任务和任务组的任务列表 |
||||
*/ |
||||
public List<AbsEntity> getTotalTaskList() { |
||||
List<AbsEntity> list = new ArrayList<>(); |
||||
List<DownloadEntity> simpleTask = getTaskList(); |
||||
List<DownloadGroupEntity> groupTask = getGroupTaskList(); |
||||
if (simpleTask != null && !simpleTask.isEmpty()) { |
||||
list.addAll(simpleTask); |
||||
} |
||||
if (groupTask != null && !groupTask.isEmpty()) { |
||||
list.addAll(groupTask); |
||||
} |
||||
return list; |
||||
} |
||||
|
||||
/** |
||||
* 停止所有正在下载的任务,并清空等待队列。 |
||||
*/ |
||||
public void stopAllTask() { |
||||
AriaManager.getInstance(AriaManager.APP) |
||||
.setCmd(NormalCmdFactory.getInstance() |
||||
.createCmd(new DTaskWrapper(null), NormalCmdFactory.TASK_STOP_ALL, |
||||
ICmd.TASK_TYPE_DOWNLOAD)) |
||||
.exe(); |
||||
} |
||||
|
||||
/** |
||||
* 恢复所有正在下载的任务 |
||||
* 1.如果执行队列没有满,则开始下载任务,直到执行队列满 |
||||
* 2.如果队列执行队列已经满了,则将所有任务添加到等待队列中 |
||||
*/ |
||||
public void resumeAllTask() { |
||||
AriaManager.getInstance(AriaManager.APP) |
||||
.setCmd(NormalCmdFactory.getInstance() |
||||
.createCmd(new DTaskWrapper(null), NormalCmdFactory.TASK_RESUME_ALL, |
||||
ICmd.TASK_TYPE_DOWNLOAD)) |
||||
.exe(); |
||||
} |
||||
|
||||
/** |
||||
* 删除所有任务 |
||||
* |
||||
* @param removeFile {@code true} 删除已经下载完成的任务,不仅删除下载记录,还会删除已经下载完成的文件,{@code false} |
||||
* 如果文件已经下载完成,只删除下载记录 |
||||
*/ |
||||
public void removeAllTask(boolean removeFile) { |
||||
final AriaManager ariaManager = AriaManager.getInstance(AriaManager.APP); |
||||
CancelAllCmd cancelCmd = |
||||
(CancelAllCmd) CommonUtil.createNormalCmd(new DTaskWrapper(null), |
||||
NormalCmdFactory.TASK_CANCEL_ALL, ICmd.TASK_TYPE_DOWNLOAD); |
||||
cancelCmd.removeFile = removeFile; |
||||
ariaManager.setCmd(cancelCmd).exe(); |
||||
Set<String> keys = ariaManager.getReceiver().keySet(); |
||||
for (String key : keys) { |
||||
ariaManager.getReceiver().remove(key); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,101 @@ |
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one |
||||
* or more contributor license agreements. See the NOTICE file |
||||
* distributed with this work for additional information |
||||
* regarding copyright ownership. The ASF licenses this file |
||||
* to you under the Apache License, Version 2.0 (the |
||||
* "License"); you may not use this file except in compliance |
||||
* with the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package com.arialyy.aria.core.download.downloader; |
||||
|
||||
import com.arialyy.aria.util.ALog; |
||||
import java.io.DataInputStream; |
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
|
||||
// Data is expected to be a series of data chunks in the form <chunk size><chunk bytes><chunk size><chunk bytes>
|
||||
// The final data chunk should be a 0-length chunk which will indicate end of input.
|
||||
@Deprecated |
||||
public class ChunkedInputStream extends InputStream { |
||||
private static final String TAG = "ChunkedInputStream"; |
||||
|
||||
private DataInputStream din; |
||||
private int unreadBytes = 0; // Bytes remaining in the current chunk of data
|
||||
private byte[] singleByte = new byte[1]; |
||||
private boolean endOfData = false; |
||||
private String id; |
||||
|
||||
public ChunkedInputStream(InputStream in, String id) { |
||||
din = new DataInputStream(in); |
||||
this.id = id; |
||||
ALog.d(TAG, String.format("Creating chunked input for %s", id)); |
||||
} |
||||
|
||||
@Override |
||||
public void close() throws IOException { |
||||
ALog.d(TAG, String.format("%s: Closing chunked input.", id)); |
||||
din.close(); |
||||
} |
||||
|
||||
@Override |
||||
public int read() throws IOException { |
||||
int bytesRead = read(singleByte, 0, 1); |
||||
return (bytesRead == -1) ? -1 : (int) singleByte[0]; |
||||
} |
||||
|
||||
@Override |
||||
public int read(byte[] b, int off, int len) throws IOException { |
||||
int bytesRead = 0; |
||||
|
||||
if (len < 0) { |
||||
throw new IllegalArgumentException(id + ": Negative read length"); |
||||
} else if (len == 0) { |
||||
return 0; |
||||
} |
||||
|
||||
// If there is a current unread chunk, read from that, or else get the next chunk.
|
||||
if (unreadBytes == 0) { |
||||
try { |
||||
// Find the next chunk size
|
||||
unreadBytes = din.readInt(); |
||||
if (ALog.DEBUG) { |
||||
ALog.d(TAG, String.format("%s: Chunk size %s", id, unreadBytes)); |
||||
} |
||||
if (unreadBytes == 0) { |
||||
ALog.d(TAG, String.format("%s: Hit end of data", id)); |
||||
endOfData = true; |
||||
return -1; |
||||
} |
||||
} catch (IOException err) { |
||||
throw new IOException(id + ": Error while attempting to read chunk length", err); |
||||
} |
||||
} |
||||
|
||||
int bytesToRead = Math.min(len, unreadBytes); |
||||
try { |
||||
din.readFully(b, off, bytesToRead); |
||||
} catch (IOException err) { |
||||
throw new IOException( |
||||
id + ": Error while attempting to read " + bytesToRead + " bytes from current chunk", |
||||
err); |
||||
} |
||||
unreadBytes -= bytesToRead; |
||||
bytesRead += bytesToRead; |
||||
|
||||
return bytesRead; |
||||
} |
||||
|
||||
public boolean isEndOfData() { |
||||
return endOfData; |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -1,257 +1,302 @@ |
||||
/* |
||||
* 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 android.content.Context; |
||||
import android.database.Cursor; |
||||
import android.database.sqlite.SQLiteDatabase; |
||||
import android.database.sqlite.SQLiteOpenHelper; |
||||
import com.arialyy.aria.util.ALog; |
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* Created by lyy on 2015/11/2. |
||||
* sql帮助类 |
||||
*/ |
||||
final class SqlHelper extends SQLiteOpenHelper { |
||||
private static final String TAG = "SqlHelper"; |
||||
static volatile SqlHelper INSTANCE = null; |
||||
|
||||
private DelegateCommon mDelegate; |
||||
|
||||
synchronized static SqlHelper init(Context context) { |
||||
if (INSTANCE == null) { |
||||
synchronized (SqlHelper.class) { |
||||
DelegateCommon delegate = DelegateManager.getInstance().getDelegate(DelegateCommon.class); |
||||
INSTANCE = new SqlHelper(context.getApplicationContext(), delegate); |
||||
SQLiteDatabase db = INSTANCE.getWritableDatabase(); |
||||
db = delegate.checkDb(db); |
||||
// SQLite在3.6.19版本中开始支持外键约束,
|
||||
// 而在Android中 2.1以前的版本使用的SQLite版本是3.5.9, 在2.2版本中使用的是3.6.22.
|
||||
// 但是为了兼容以前的程序,默认并没有启用该功能,如果要启用该功能
|
||||
// 需要使用如下语句:
|
||||
db.execSQL("PRAGMA foreign_keys=ON;"); |
||||
Set<String> tables = DBConfig.mapping.keySet(); |
||||
for (String tableName : tables) { |
||||
Class clazz = DBConfig.mapping.get(tableName); |
||||
|
||||
if (!delegate.tableExists(db, clazz)) { |
||||
delegate.createTable(db, clazz); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return INSTANCE; |
||||
} |
||||
|
||||
private SqlHelper(Context context, DelegateCommon delegate) { |
||||
super(DBConfig.SAVE_IN_SDCARD ? new DatabaseContext(context) : context, DBConfig.DB_NAME, null, |
||||
DBConfig.VERSION); |
||||
mDelegate = delegate; |
||||
} |
||||
|
||||
@Override public void onCreate(SQLiteDatabase db) { |
||||
|
||||
} |
||||
|
||||
@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { |
||||
if (oldVersion < newVersion) { |
||||
if (oldVersion < 31) { |
||||
handle314AriaUpdate(db); |
||||
} else if (oldVersion < 45) { |
||||
handle360AriaUpdate(db); |
||||
} else { |
||||
handleDbUpdate(db, null, null); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { |
||||
if (oldVersion > newVersion) { |
||||
handleDbUpdate(db, null, null); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 处理数据库升级,该段代码无法修改表字段 |
||||
* |
||||
* @param modifyColumns 需要修改的表字段的映射,key为表名, |
||||
* value{@code Map<String, String>}中的Map的key为老字段名称,value为该老字段对应的新字段名称 |
||||
* @param delColumns 需要删除的表字段,key为表名,value{@code List<String>}为需要删除的字段列表 |
||||
*/ |
||||
private void handleDbUpdate(SQLiteDatabase db, Map<String, Map<String, String>> modifyColumns, |
||||
Map<String, List<String>> delColumns) { |
||||
if (db == null) { |
||||
ALog.e("SqlHelper", "db 为 null"); |
||||
return; |
||||
} else if (!db.isOpen()) { |
||||
ALog.e("SqlHelper", "db已关闭"); |
||||
return; |
||||
} |
||||
|
||||
try { |
||||
db.beginTransaction(); |
||||
Set<String> tables = DBConfig.mapping.keySet(); |
||||
for (String tableName : tables) { |
||||
Class clazz = DBConfig.mapping.get(tableName); |
||||
if (mDelegate.tableExists(db, clazz)) { |
||||
db = mDelegate.checkDb(db); |
||||
//修改表名为中介表名
|
||||
String alertSql = String.format("ALTER TABLE %s RENAME TO %s_temp", tableName, tableName); |
||||
db.execSQL(alertSql); |
||||
|
||||
//创建新表
|
||||
mDelegate.createTable(db, clazz); |
||||
|
||||
String sql = String.format("SELECT COUNT(*) FROM %s_temp", tableName); |
||||
Cursor cursor = db.rawQuery(sql, null); |
||||
cursor.moveToFirst(); |
||||
long count = cursor.getLong(0); |
||||
cursor.close(); |
||||
|
||||
if (count > 0) { |
||||
// 获取所有表字段名称
|
||||
Cursor columnC = |
||||
db.rawQuery(String.format("PRAGMA table_info(%s_temp)", tableName), null); |
||||
StringBuilder params = new StringBuilder(); |
||||
|
||||
while (columnC.moveToNext()) { |
||||
String columnName = columnC.getString(columnC.getColumnIndex("name")); |
||||
if (delColumns != null && delColumns.get(tableName) != null) { |
||||
List<String> delColumn = delColumns.get(tableName); |
||||
if (delColumn != null && !delColumn.isEmpty()) { |
||||
if (delColumn.contains(columnName)) { |
||||
continue; |
||||
} |
||||
} |
||||
} |
||||
|
||||
params.append(columnName).append(","); |
||||
} |
||||
columnC.close(); |
||||
|
||||
String oldParamStr = params.toString(); |
||||
oldParamStr = oldParamStr.substring(0, oldParamStr.length() - 1); |
||||
String newParamStr = oldParamStr; |
||||
// 处理字段名称改变
|
||||
if (modifyColumns != null) { |
||||
//newParamStr = params.toString();
|
||||
Map<String, String> columnMap = modifyColumns.get(tableName); |
||||
if (columnMap != null && !columnMap.isEmpty()) { |
||||
Set<String> keys = columnMap.keySet(); |
||||
for (String key : keys) { |
||||
if (newParamStr.contains(key)) { |
||||
newParamStr = newParamStr.replace(key, columnMap.get(key)); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
//恢复数据
|
||||
String insertSql = |
||||
String.format("INSERT INTO %s (%s) SELECT %s FROM %s_temp", tableName, newParamStr, |
||||
oldParamStr, tableName); |
||||
ALog.d(TAG, "insertSql = " + insertSql); |
||||
db.execSQL(insertSql); |
||||
} |
||||
//删除中介表
|
||||
mDelegate.dropTable(db, tableName + "_temp"); |
||||
} |
||||
} |
||||
db.setTransactionSuccessful(); |
||||
} catch (Exception e) { |
||||
ALog.e(TAG, e); |
||||
} finally { |
||||
db.endTransaction(); |
||||
} |
||||
|
||||
mDelegate.close(db); |
||||
} |
||||
|
||||
/** |
||||
* 处理3.6以下版本的数据库升级 |
||||
*/ |
||||
private void handle360AriaUpdate(SQLiteDatabase db) { |
||||
String[] taskTables = |
||||
new String[] { "UploadTaskEntity", "DownloadTaskEntity", "DownloadGroupTaskEntity" }; |
||||
for (String taskTable : taskTables) { |
||||
if (mDelegate.tableExists(db, taskTable)) { |
||||
mDelegate.dropTable(db, taskTable); |
||||
} |
||||
} |
||||
Map<String, Map<String, String>> columnMap = new HashMap<>(); |
||||
Map<String, String> map = new HashMap<>(); |
||||
map.put("groupName", "groupHash"); |
||||
columnMap.put("DownloadEntity", map); |
||||
columnMap.put("DownloadGroupEntity", map); |
||||
handleDbUpdate(db, columnMap, null); |
||||
} |
||||
|
||||
/** |
||||
* 处理3.4版本之前数据库迁移,主要是修改子表外键字段对应的值 |
||||
*/ |
||||
private void handle314AriaUpdate(SQLiteDatabase db) { |
||||
String[] taskTables = |
||||
new String[] { "UploadTaskEntity", "DownloadTaskEntity", "DownloadGroupTaskEntity" }; |
||||
for (String taskTable : taskTables) { |
||||
if (mDelegate.tableExists(db, taskTable)) { |
||||
mDelegate.dropTable(db, taskTable); |
||||
} |
||||
} |
||||
|
||||
//删除所有主键为null和逐渐重复的数据
|
||||
String[] tables = new String[] { "DownloadEntity", "DownloadGroupEntity" }; |
||||
String[] keys = new String[] { "downloadPath", "groupName" }; |
||||
int i = 0; |
||||
for (String tableName : tables) { |
||||
String pColumn = keys[i]; |
||||
String nullSql = |
||||
String.format("DELETE FROM %s WHERE %s='' OR %s IS NULL", tableName, pColumn, pColumn); |
||||
ALog.d(TAG, nullSql); |
||||
db.execSQL(nullSql); |
||||
|
||||
//删除所有主键重复的数据
|
||||
String repeatSql = |
||||
String.format( |
||||
"DELETE FROM %s WHERE %s IN(SELECT %s FROM %s GROUP BY %s HAVING COUNT(%s) > 1)", |
||||
tableName, pColumn, pColumn, tableName, pColumn, pColumn); |
||||
|
||||
ALog.d(TAG, repeatSql); |
||||
db.execSQL(repeatSql); |
||||
i++; |
||||
} |
||||
|
||||
Map<String, Map<String, String>> modifyColumnMap = new HashMap<>(); |
||||
Map<String, String> map = new HashMap<>(); |
||||
map.put("groupName", "groupHash"); |
||||
modifyColumnMap.put("DownloadEntity", map); |
||||
modifyColumnMap.put("DownloadGroupEntity", map); |
||||
|
||||
Map<String, List<String>> delColumnMap = new HashMap<>(); |
||||
List<String> dEntityDel = new ArrayList<>(); |
||||
dEntityDel.add("taskKey"); |
||||
delColumnMap.put("DownloadEntity", dEntityDel); |
||||
List<String> dgEntityDel = new ArrayList<>(); |
||||
dgEntityDel.add("subtask"); |
||||
delColumnMap.put("DownloadGroupEntity", dgEntityDel); |
||||
|
||||
handleDbUpdate(db, modifyColumnMap, delColumnMap); |
||||
} |
||||
/* |
||||
* 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 android.content.Context; |
||||
import android.database.Cursor; |
||||
import android.database.sqlite.SQLiteDatabase; |
||||
import android.database.sqlite.SQLiteOpenHelper; |
||||
import android.os.Build; |
||||
import com.arialyy.aria.util.ALog; |
||||
import java.io.File; |
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
|
||||
/** |
||||
* Created by lyy on 2015/11/2. |
||||
* sql帮助类 |
||||
*/ |
||||
final class SqlHelper extends SQLiteOpenHelper { |
||||
private static final String TAG = "SqlHelper"; |
||||
private static volatile SqlHelper INSTANCE = null; |
||||
private Context mContext; |
||||
|
||||
private DelegateCommon mDelegate; |
||||
|
||||
synchronized static SqlHelper init(Context context) { |
||||
if (INSTANCE == null) { |
||||
synchronized (SqlHelper.class) { |
||||
DelegateCommon delegate = DelegateManager.getInstance().getDelegate(DelegateCommon.class); |
||||
INSTANCE = new SqlHelper(context.getApplicationContext(), delegate); |
||||
} |
||||
} |
||||
return INSTANCE; |
||||
} |
||||
|
||||
static SqlHelper getInstance() { |
||||
return INSTANCE; |
||||
} |
||||
|
||||
private SqlHelper(Context context, DelegateCommon delegate) { |
||||
super(DBConfig.SAVE_IN_SDCARD ? new DatabaseContext(context) : context, DBConfig.DB_NAME, null, |
||||
DBConfig.VERSION); |
||||
mContext = context; |
||||
mDelegate = delegate; |
||||
} |
||||
|
||||
@Override public void onOpen(SQLiteDatabase db) { |
||||
super.onOpen(db); |
||||
} |
||||
|
||||
@Override public void onConfigure(SQLiteDatabase db) { |
||||
super.onConfigure(db); |
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { |
||||
db.setForeignKeyConstraintsEnabled(true); |
||||
} else { |
||||
// SQLite在3.6.19版本中开始支持外键约束,
|
||||
// 而在Android中 2.1以前的版本使用的SQLite版本是3.5.9, 在2.2版本中使用的是3.6.22.
|
||||
// 但是为了兼容以前的程序,默认并没有启用该功能,如果要启用该功能
|
||||
// 需要使用如下语句:
|
||||
db.execSQL("PRAGMA foreign_keys=ON;"); |
||||
} |
||||
if (DBConfig.DEBUG) { |
||||
db.enableWriteAheadLogging(); |
||||
} |
||||
} |
||||
|
||||
@Override public void onCreate(SQLiteDatabase db) { |
||||
DelegateCommon delegate = DelegateManager.getInstance().getDelegate(DelegateCommon.class); |
||||
Set<String> tables = DBConfig.mapping.keySet(); |
||||
for (String tableName : tables) { |
||||
Class clazz = DBConfig.mapping.get(tableName); |
||||
if (!delegate.tableExists(db, clazz)) { |
||||
delegate.createTable(db, clazz); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { |
||||
if (oldVersion < newVersion) { |
||||
if (oldVersion < 31) { |
||||
handle314AriaUpdate(db); |
||||
} else if (oldVersion < 45) { |
||||
handle360AriaUpdate(db); |
||||
} else { |
||||
handleDbUpdate(db, null, null); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { |
||||
if (oldVersion > newVersion) { |
||||
handleDbUpdate(db, null, null); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 获取数据库连接 |
||||
*/ |
||||
SQLiteDatabase getDb() { |
||||
SQLiteDatabase db; |
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { |
||||
SQLiteDatabase.OpenParams params = new SQLiteDatabase.OpenParams.Builder().setOpenFlags( |
||||
SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READWRITE | |
||||
SQLiteDatabase.CREATE_IF_NECESSARY).build(); |
||||
setOpenParams(params); |
||||
db = getWritableDatabase(); |
||||
} else { |
||||
//SQLiteDatabase.openOrCreateDatabase()
|
||||
File dbFile = mContext.getDatabasePath(DBConfig.DB_NAME); |
||||
if (!dbFile.exists()) { |
||||
db = getWritableDatabase(); |
||||
} else { |
||||
// 触发一次SQLiteOpenHelper的流程,再使用NO_LOCALIZED_COLLATORS标志打开数据库
|
||||
db = getReadableDatabase(); |
||||
db.close(); |
||||
db = SQLiteDatabase.openDatabase(dbFile.getPath(), null, |
||||
SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READWRITE | |
||||
SQLiteDatabase.CREATE_IF_NECESSARY); |
||||
} |
||||
} |
||||
return db; |
||||
} |
||||
|
||||
/** |
||||
* 处理数据库升级,该段代码无法修改表字段 |
||||
* |
||||
* @param modifyColumns 需要修改的表字段的映射,key为表名, |
||||
* value{@code Map<String, String>}中的Map的key为老字段名称,value为该老字段对应的新字段名称 |
||||
* @param delColumns 需要删除的表字段,key为表名,value{@code List<String>}为需要删除的字段列表 |
||||
*/ |
||||
private void handleDbUpdate(SQLiteDatabase db, Map<String, Map<String, String>> modifyColumns, |
||||
Map<String, List<String>> delColumns) { |
||||
if (db == null) { |
||||
ALog.e("SqlHelper", "db 为 null"); |
||||
return; |
||||
} else if (!db.isOpen()) { |
||||
ALog.e("SqlHelper", "db已关闭"); |
||||
return; |
||||
} |
||||
|
||||
try { |
||||
db.beginTransaction(); |
||||
Set<String> tables = DBConfig.mapping.keySet(); |
||||
for (String tableName : tables) { |
||||
Class clazz = DBConfig.mapping.get(tableName); |
||||
if (mDelegate.tableExists(db, clazz)) { |
||||
//修改表名为中介表名
|
||||
String alertSql = String.format("ALTER TABLE %s RENAME TO %s_temp", tableName, tableName); |
||||
db.execSQL(alertSql); |
||||
|
||||
//创建新表
|
||||
mDelegate.createTable(db, clazz); |
||||
|
||||
String sql = String.format("SELECT COUNT(*) FROM %s_temp", tableName); |
||||
Cursor cursor = db.rawQuery(sql, null); |
||||
cursor.moveToFirst(); |
||||
long count = cursor.getLong(0); |
||||
cursor.close(); |
||||
|
||||
if (count > 0) { |
||||
// 获取所有表字段名称
|
||||
Cursor columnC = |
||||
db.rawQuery(String.format("PRAGMA table_info(%s_temp)", tableName), null); |
||||
StringBuilder params = new StringBuilder(); |
||||
|
||||
while (columnC.moveToNext()) { |
||||
String columnName = columnC.getString(columnC.getColumnIndex("name")); |
||||
if (delColumns != null && delColumns.get(tableName) != null) { |
||||
List<String> delColumn = delColumns.get(tableName); |
||||
if (delColumn != null && !delColumn.isEmpty()) { |
||||
if (delColumn.contains(columnName)) { |
||||
continue; |
||||
} |
||||
} |
||||
} |
||||
|
||||
params.append(columnName).append(","); |
||||
} |
||||
columnC.close(); |
||||
|
||||
String oldParamStr = params.toString(); |
||||
oldParamStr = oldParamStr.substring(0, oldParamStr.length() - 1); |
||||
String newParamStr = oldParamStr; |
||||
// 处理字段名称改变
|
||||
if (modifyColumns != null) { |
||||
//newParamStr = params.toString();
|
||||
Map<String, String> columnMap = modifyColumns.get(tableName); |
||||
if (columnMap != null && !columnMap.isEmpty()) { |
||||
Set<String> keys = columnMap.keySet(); |
||||
for (String key : keys) { |
||||
if (newParamStr.contains(key)) { |
||||
newParamStr = newParamStr.replace(key, columnMap.get(key)); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
//恢复数据
|
||||
String insertSql = |
||||
String.format("INSERT INTO %s (%s) SELECT %s FROM %s_temp", tableName, newParamStr, |
||||
oldParamStr, tableName); |
||||
ALog.d(TAG, "insertSql = " + insertSql); |
||||
db.execSQL(insertSql); |
||||
} |
||||
//删除中介表
|
||||
mDelegate.dropTable(db, tableName + "_temp"); |
||||
} |
||||
} |
||||
db.setTransactionSuccessful(); |
||||
} catch (Exception e) { |
||||
ALog.e(TAG, e); |
||||
} finally { |
||||
db.endTransaction(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 处理3.6以下版本的数据库升级 |
||||
*/ |
||||
private void handle360AriaUpdate(SQLiteDatabase db) { |
||||
String[] taskTables = |
||||
new String[] { "UploadTaskEntity", "DownloadTaskEntity", "DownloadGroupTaskEntity" }; |
||||
for (String taskTable : taskTables) { |
||||
if (mDelegate.tableExists(db, taskTable)) { |
||||
mDelegate.dropTable(db, taskTable); |
||||
} |
||||
} |
||||
Map<String, Map<String, String>> columnMap = new HashMap<>(); |
||||
Map<String, String> map = new HashMap<>(); |
||||
map.put("groupName", "groupHash"); |
||||
columnMap.put("DownloadEntity", map); |
||||
columnMap.put("DownloadGroupEntity", map); |
||||
handleDbUpdate(db, columnMap, null); |
||||
} |
||||
|
||||
/** |
||||
* 处理3.4版本之前数据库迁移,主要是修改子表外键字段对应的值 |
||||
*/ |
||||
private void handle314AriaUpdate(SQLiteDatabase db) { |
||||
String[] taskTables = |
||||
new String[] { "UploadTaskEntity", "DownloadTaskEntity", "DownloadGroupTaskEntity" }; |
||||
for (String taskTable : taskTables) { |
||||
if (mDelegate.tableExists(db, taskTable)) { |
||||
mDelegate.dropTable(db, taskTable); |
||||
} |
||||
} |
||||
|
||||
//删除所有主键为null和逐渐重复的数据
|
||||
String[] tables = new String[] { "DownloadEntity", "DownloadGroupEntity" }; |
||||
String[] keys = new String[] { "downloadPath", "groupName" }; |
||||
int i = 0; |
||||
for (String tableName : tables) { |
||||
String pColumn = keys[i]; |
||||
String nullSql = |
||||
String.format("DELETE FROM %s WHERE %s='' OR %s IS NULL", tableName, pColumn, pColumn); |
||||
ALog.d(TAG, nullSql); |
||||
db.execSQL(nullSql); |
||||
|
||||
//删除所有主键重复的数据
|
||||
String repeatSql = |
||||
String.format( |
||||
"DELETE FROM %s WHERE %s IN(SELECT %s FROM %s GROUP BY %s HAVING COUNT(%s) > 1)", |
||||
tableName, pColumn, pColumn, tableName, pColumn, pColumn); |
||||
|
||||
ALog.d(TAG, repeatSql); |
||||
db.execSQL(repeatSql); |
||||
i++; |
||||
} |
||||
|
||||
Map<String, Map<String, String>> modifyColumnMap = new HashMap<>(); |
||||
Map<String, String> map = new HashMap<>(); |
||||
map.put("groupName", "groupHash"); |
||||
modifyColumnMap.put("DownloadEntity", map); |
||||
modifyColumnMap.put("DownloadGroupEntity", map); |
||||
|
||||
Map<String, List<String>> delColumnMap = new HashMap<>(); |
||||
List<String> dEntityDel = new ArrayList<>(); |
||||
dEntityDel.add("taskKey"); |
||||
delColumnMap.put("DownloadEntity", dEntityDel); |
||||
List<String> dgEntityDel = new ArrayList<>(); |
||||
dgEntityDel.add("subtask"); |
||||
delColumnMap.put("DownloadGroupEntity", dgEntityDel); |
||||
|
||||
handleDbUpdate(db, modifyColumnMap, delColumnMap); |
||||
} |
||||
} |
@ -1,254 +1,269 @@ |
||||
/* |
||||
* 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<String> urls) { |
||||
if (urls == null || urls.isEmpty()) { |
||||
throw new IllegalArgumentException("链接组不能为null"); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 检查下载任务组保存路径 |
||||
*/ |
||||
public static void checkDownloadPaths(List<String> 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是否合法,如果url不合法,将抛出{@link IllegalArgumentException}异常 |
||||
*/ |
||||
public static void checkUrl(String url) { |
||||
if (TextUtils.isEmpty(url)) { |
||||
throw new NullPointerException("url为空"); |
||||
} else if (!url.startsWith("http") && !url.startsWith("ftp")) { |
||||
throw new IllegalArgumentException(String.format("url【%s】错误", url)); |
||||
} |
||||
int index = url.indexOf("://"); |
||||
if (index == -1) { |
||||
throw new IllegalArgumentException(String.format("url【%s】不合法", url)); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 检测url是否合法 |
||||
* |
||||
* @return {@code true} 合法,{@code false} 非法 |
||||
*/ |
||||
public static boolean checkUrlNotThrow(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<String> urls) { |
||||
if (urls == null || urls.isEmpty()) { |
||||
throw new IllegalArgumentException("链接组不能为null"); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 检查下载任务组保存路径 |
||||
*/ |
||||
public static void checkDownloadPaths(List<String> 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"); |
||||
} |
||||
} |
||||
} |
@ -1,219 +1,226 @@ |
||||
## 开发日志 |
||||
+ 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) |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/368 |
||||
- 增加gradle 5.0支持 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/374 |
||||
- 增加分页功能,详情见:https://aria.laoyuyu.me/aria_doc/api/task_list.html#%E4%BB%BB%E5%8A%A1%E5%88%97%E8%A1%A8%E5%88%86%E9%A1%B5%EF%BC%88362%E4%BB%A5%E4%B8%8A%E7%89%88%E6%9C%AC%E6%94%AF%E6%8C%81%EF%BC%89 |
||||
+ v_3.6.1 (2019/3/5) |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/367 |
||||
+ v_3.6 (2019/2/27) |
||||
- 优化数据库写入\修改的速度 |
||||
- 精减任务实体的存储 |
||||
- 增加下载组合任务的配置 |
||||
- useBroadcast\notNetRetry这两个配置,统一在AppConfig中配置 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/361 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/365 |
||||
+ v_3.5.4 (2019/1/8) |
||||
- 修复不支持断点的下载地址,重复下载出现的数据库主键冲突问题 |
||||
+ v_3.5.3 (2018/12/23) |
||||
- 修复ftps不能加载默认证书的bug https://github.com/AriaLyy/Aria/issues/334 |
||||
- 优化注解性能,移除不必要的判断代码 |
||||
- 增加广播支持,详情见:http://aria.laoyuyu.me/aria_doc/api/use_broadcast.html |
||||
- 增加get参数支持 |
||||
```java |
||||
Aria.download(SingleTaskActivity.this) |
||||
.load(DOWNLOAD_URL) // url 必须是主体url,也就是?前面的内容 |
||||
.setFilePath(path, true) |
||||
.asGet() |
||||
.setParams(params) // 设置参数 |
||||
.start(); |
||||
``` |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/335 |
||||
- 新增进度百分比保存 https://github.com/AriaLyy/Aria/issues/336 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/335 |
||||
+ v_3.5.2 |
||||
- 添加Serializable接口支持 https://github.com/AriaLyy/Aria/issues/320 |
||||
- 失败回调增加错误原因 https://github.com/AriaLyy/Aria/issues/310 |
||||
``` |
||||
@Download.onTaskFail void taskFail(DownloadTask task, Exception e) { |
||||
e.getMessage(); |
||||
... |
||||
} |
||||
``` |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/322 |
||||
- 新增201 重定向支持 https://github.com/AriaLyy/Aria/issues/318 |
||||
- 修复使用`useServerFileName(true)`中含有`"`导致的文件后缀名错误问题 |
||||
- 优化logcat日志提示 |
||||
- 修改下载线程的优先级为`Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);` |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/319 |
||||
- 修复分卡下载失败的问题 https://github.com/AriaLyy/Aria/issues/326 |
||||
- 初始化Aria时会将所有数据库状态为下载中的任务改为已停止,防止应用被kill后,任务状态错误 |
||||
- 初始化时自动判断文件是否被删除,文件被删除的任务将自动重置默认值 |
||||
- 修复刷新url后,文件无法删除的 bug |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/309 |
||||
- 优化配置文件的读取 |
||||
+ v_3.5.1 |
||||
- 优化`taskExists`方法 |
||||
- 添加`post`参数请求支持 |
||||
```java |
||||
Aria.download(SingleTaskActivity.this) |
||||
.load(DOWNLOAD_URL) |
||||
.setFilePath(path) |
||||
.asPost() // post请求 |
||||
.setParam("key", "value") //传递参数 |
||||
//.setParams(Map<String, String>) // 传递多参数 |
||||
.start(); |
||||
``` |
||||
- 增加强制设置文件路径的api, https://github.com/AriaLyy/Aria/issues/311 |
||||
``` |
||||
Aria.download(SingleTaskActivity.this) |
||||
.load(DOWNLOAD_URL) |
||||
.setFilePath(path, true) // true表示忽略路径是否被占用 |
||||
.start(); |
||||
``` |
||||
+ v_3.5 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/302 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/283 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/305 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/306 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/272 (现在,停止所有任务,未开始的任务状态将变为停止) |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/277 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/303 |
||||
- 优化停止任务的速度 |
||||
- 修复组合任务修改子任务文件名失败的问题 |
||||
+ v_3.4.12 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/286 |
||||
- 优化线程池任务 |
||||
+ v_3.4.11 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/288 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/282 |
||||
+ v_3.4.10 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/280 |
||||
+ v_3.4.9 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/276 |
||||
+ v_3.4.8 |
||||
- 组合任务新增`updateUrls(List<String>)`用于修改组合子任务的url,[see](https://aria.laoyuyu.me/aria_doc/api/update_url.html) |
||||
- 出于安全考虑,FTP数据库去掉密码的保存 |
||||
- 增加FTPS支持 [see](https://aria.laoyuyu.me/aria_doc/download/ftps.html) |
||||
- 增加速度限制支持[see](https://aria.laoyuyu.me/aria_doc/api/speed_handle.html) |
||||
- 增加内存空间不足验证 |
||||
+ v_3.4.7 |
||||
- 修复分块任务异常操作导致的问题 |
||||
+ v_3.4.6 |
||||
- 修复android 4.4.4 版本多dex下无法进行回调的问题 |
||||
- 新增`updateUrl(newUrl)`用于修改任务的url,[see](https://aria.laoyuyu.me/aria_doc/api/task_handle.html#%E6%9B%B4%E6%96%B0%E4%BB%BB%E5%8A%A1url) |
||||
- 优化分块下载 |
||||
- 修复了字符串中有特殊字符导致的路径冲突问题;修复ftp分块下载失败问题 |
||||
- 修复连接中有`+`导致的地址呗使用问题。 |
||||
- 修复表重复创建导致的崩溃问题 https://github.com/AriaLyy/Aria/issues/264 |
||||
+ v_3.4.4 |
||||
- 实现[多线程分块下载](https://aria.laoyuyu.me/aria_doc/start/config.html) |
||||
- 修复`stopAll()`和`resumeAll()`导致的进度为0问题 |
||||
- 修复任务组添加header无效的问题 |
||||
+ v_3.4.3 |
||||
- 修复在activity 的onStop中取消注册导致的内存泄露问题 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/258 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/259 |
||||
+ v_3.4.2 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/248 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/247 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/250 |
||||
- 添加任务判断是否存在的api |
||||
- 添加代理api |
||||
- 修复删除所有没有进出等待的问题 |
||||
- 进度有时出错的问题 |
||||
- FTP添加超时处理 |
||||
+ v_3.4.1 |
||||
- 移除记录配置文件,改用数据库记录任务记录 |
||||
- 上传配置添加io超时时间、缓存大小配置 |
||||
- 添加没有网络也会重试的开关 |
||||
- 修复多次删除记录的bug |
||||
- 文件长度现在可动态增加,详情见 https://aria.laoyuyu.me/aria_doc/start/config.html |
||||
- 修复多module同时引用Aria导致打正式包出错的问题 https://github.com/AriaLyy/Aria/issues/240 |
||||
+ v_3.4 |
||||
- 优化大量代码 |
||||
- 重构Aria的ORM模型,提高了数据读取的可靠性和读写速度 |
||||
- 现在可在任意类中使用Aria了,[使用方法](http://aria.laoyuyu.me/aria_doc/start/any_java.html) |
||||
- 添加`window.location.replace("http://xxxx")`类型的网页重定向支持 |
||||
- 支持gzip、deflate 压缩类型的输入流 |
||||
- 添加`useServerFileName`,可使用服务端响应header的`Content-Disposition`携带的文件名 |
||||
+ v_3.3.16 |
||||
- 修复一个activity启动多次,无法进行回掉的bug https://github.com/AriaLyy/Aria/issues/200 |
||||
- 优化target代码结构,移除路径被占用的提示 |
||||
- 添加支持chunked模式的下载 |
||||
- 去掉上一个版本"//"的限制 |
||||
+ v_3.3.14 |
||||
- 修复ftp上传和下载的兼容性问题 |
||||
- 如果url中的path有"//"将替换为"/" |
||||
- 修复http上传成功后,如果服务器没有设置返回码导致上传失败的问题 |
||||
- 上传实体UploadEntity增加responseStr字段,http上传完成后,在被`@Upload.onComplete`注解的方法中,可通过`task.getEntity().getResponseStr())`获取服务器返回的数据 |
||||
- 如果服务器存在已上传了一部分的文件,用户执行删除该FTP上传任务,再次重新上传,会出现550,权限错误;本版本已修复该问题 |
||||
+ v_3.3.13 |
||||
- 添加`@Download.onWait、@Upload.onWait、@DownloadGroup.onWait`三个新注解,队列已经满了,继续创建新任务,任务处于等待中,将会执行被这三个注解标志的方法 |
||||
- app被kill,但是还存在等待中的任务A;第二次重新启动,先创建一个新的任务B,Aria会自动把B放进等待队列中,这时再次创建任务A,会导致重复下载,进度错乱的问题;本版本已修复这个问题 |
||||
+ v_3.3.11 |
||||
- 添加进度更新间隔api,在`aria_config.xml`配置`<updateInterval value="1000"/>`或在代码中调用 |
||||
`AriaManager.getInstance(AriaManager.APP).getDownloadConfig().setUpdateInterval(3000)`便可以改变进度刷新间隔 |
||||
- 修复下载过程中kill进程可能出现的文件错误的问题 https://github.com/AriaLyy/Aria/issues/192 |
||||
- 修复http上传的空指针问题 https://github.com/AriaLyy/Aria/issues/193 |
||||
- 修复下载地址中含有`'`导致的崩溃问题 https://github.com/AriaLyy/Aria/issues/194 |
||||
+ v_3.3.10 |
||||
- 修复地址切换导致下载失败的问题 https://github.com/AriaLyy/Aria/issues/181 |
||||
- 添加重置状态的api,当下载信息不改变,只是替换了服务器的对应的文件,可用`Aria.download(this).load(url).resetState()`重置下载状态 https://github.com/AriaLyy/Aria/issues/182 |
||||
+ v_3.3.9 |
||||
- 添加POST支持 |
||||
- 任务执行的过程中,如果调用removeRecord()方法,将会取消任务 https://github.com/AriaLyy/Aria/issues/174 |
||||
- 修复一个数据库初始化的问题 https://github.com/AriaLyy/Aria/issues/173 |
||||
- 修复head头部信息过长时出现的崩溃问题 https://github.com/AriaLyy/Aria/issues/177 |
||||
+ v_3.3.7 |
||||
- 修复一个线程重启的问题 https://github.com/AriaLyy/Aria/issues/160 |
||||
- 修复配置文件异常问题、格式化速度为0问题 https://github.com/AriaLyy/Aria/issues/161 |
||||
+ v_3.3.6 |
||||
- 增加日志输出级别控制 |
||||
- 修复公网FTP地址不能下载的问题 https://github.com/AriaLyy/Aria/issues/146 |
||||
- 修复http下载地址有空格的时候下载失败的问题 https://github.com/AriaLyy/Aria/issues/131 |
||||
- 修复Activity在`onDestroy()`中调用`Aria.download(this).unRegister();`导致回调失效的问题 |
||||
- 修复Adapter下载FTP任务问题、任务调度问题 https://github.com/AriaLyy/Aria/issues/157 |
||||
- 优化代码,优化了IO性能 |
||||
+ v_3.3.5 修复任务组、上传任务无法启动的bug |
||||
+ v_3.3.4 优化任务代码结构,修复上一个版本暂停后无法自动执行任务的问题 |
||||
+ v_3.3.3 修复进度条错乱的问题,修复同一时间多次调用start导致重复下载的问题 |
||||
+ v_3.3.2 新加reTry(),修复上一个版本不会回调失败事件的问题;增加running状态下5秒钟保存一次数据库的功能;修复FTP断点上传文件不完整的问题 |
||||
+ v_3.3.1 增加网络事件,网络未连接,将不会重试下载,修复删除未开始任务,状态回调错误 |
||||
+ v_3.3.0 增加任务组子任务暂停和开始控制功能、修复5.0系统以上数据库多生成两个字段的bug、去掉addSchedulerListener事件 |
||||
+ v_3.2.26 修复任务组有时注解不起作用的问题 |
||||
+ v_3.2.25 修复删除任务组文件,记录无法删除的问题 |
||||
+ v_3.2.17 修复一个版本兼容性问题,线程中使用Aria出错问题 |
||||
+ v_3.2.15 修复大型文件分段下载失败的问题,修复中文URL乱码问题 |
||||
+ v_3.2.14 修复恢复所有任务的api接口,不能恢复下载组任务的问题 |
||||
+ v_3.2.13 修复某些服务器头文件返回描述文件格式错误的问题、修复有时删除任务,需要两次删除的问题 |
||||
+ v_3.2.12 实现FTP多线程断点续传下载,FTP断点续传上传功能 |
||||
+ v_3.2.9 修复任务组下载完成两次回掉的问题,修复又是获取不到下载状态的问题 |
||||
+ v_3.2.8 修复下载超过2G大小的文件失败的问题 |
||||
+ v_3.2.7 移除设置文件名的api接口,修复断开网络时出现的进度条错误的问题 |
||||
+ v_3.2.6 移除广播事件,增加任务组下载功能 |
||||
+ v_3.1.9 修复stopAll队列没有任务时崩溃的问题,增加针对单个任务监听的功能 |
||||
+ v_3.1.7 修复某些文件下载不了的bug,增加apt注解方法,事件获取更加简单了 |
||||
+ v_3.1.6 取消任务时onTaskCancel回调两次的bug |
||||
+ v_3.1.5 优化代码结构,增加优先下载任务功能。 |
||||
+ v_3.1.4 修复快速切换,暂停、恢复功能时,概率性出现的重新下载问题,添加onPre()回调,onPre()用于请求地址之前执行界面UI更新操作。 |
||||
+ v_3.1.0 添加Aria配置文件,优化代码 |
||||
+ v_3.0.3 修复暂停后删除任务,闪退问题,添加删除记录的api |
||||
+ v_3.0.2 支持30x重定向链接下载 |
||||
+ v_3.0.0 添加上传任务支持,修复一些已发现的bug |
||||
+ v_2.4.4 修复不支持断点的下载链接拿不到文件大小的问题 |
||||
+ v_2.4.3 修复404链接卡顿的问题 |
||||
+ v_2.4.2 修复失败重试无效的bug |
||||
+ v_2.4.1 修复下载慢的问题,修复application、service 不能使用的问题 |
||||
+ v_2.4.0 支持https链接下载 |
||||
+ v_2.3.8 修复数据错乱的bug、添加fragment支持 |
||||
+ v_2.3.6 添加dialog、popupWindow支持 |
||||
+ v_2.3.3 添加断点支持、修改下载逻辑,让使用更加简单、修复一个内存泄露的bug |
||||
+ v_2.3.1 重命名为Aria,下载流程简化 |
||||
## 开发日志 |
||||
+ v_3.6.4 |
||||
- 优化任务接收器的代码结构 |
||||
- 修复`DbEntity.saveAll()`失败的问题 |
||||
- 修复分块任务重命名失败的问题 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/379 |
||||
- 移除`getDownloadTask(String url)`、`getGroupTask(List<String> urls)`、`getFtpDirTask(String path)` |
||||
等获取任务的api,如果你希望获取对应状态,请使用实体的状态判断,如:`getDownloadEntity()`、`getDownloadGroupEntity()` |
||||
`getFtpDirEntity()` |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/388 |
||||
- 修复使用`Content-Disposition`的文件名时,第一次下载无法重命名文件的问题 |
||||
- 修复使用`Content-Disposition`的文件名时,多次重命名文件的问题 |
||||
+ v_3.6.3 (2019/4/2) |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/377 |
||||
+ v_3.6.2 (2019/4/1) |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/368 |
||||
- 增加gradle 5.0支持 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/374 |
||||
- 增加分页功能,详情见:https://aria.laoyuyu.me/aria_doc/api/task_list.html#%E4%BB%BB%E5%8A%A1%E5%88%97%E8%A1%A8%E5%88%86%E9%A1%B5%EF%BC%88362%E4%BB%A5%E4%B8%8A%E7%89%88%E6%9C%AC%E6%94%AF%E6%8C%81%EF%BC%89 |
||||
+ v_3.6.1 (2019/3/5) |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/367 |
||||
+ v_3.6 (2019/2/27) |
||||
- 优化数据库写入\修改的速度 |
||||
- 精减任务实体的存储 |
||||
- 增加下载组合任务的配置 |
||||
- useBroadcast\notNetRetry这两个配置,统一在AppConfig中配置 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/361 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/365 |
||||
+ v_3.5.4 (2019/1/8) |
||||
- 修复不支持断点的下载地址,重复下载出现的数据库主键冲突问题 |
||||
+ v_3.5.3 (2018/12/23) |
||||
- 修复ftps不能加载默认证书的bug https://github.com/AriaLyy/Aria/issues/334 |
||||
- 优化注解性能,移除不必要的判断代码 |
||||
- 增加广播支持,详情见:http://aria.laoyuyu.me/aria_doc/api/use_broadcast.html |
||||
- 增加get参数支持 |
||||
```java |
||||
Aria.download(SingleTaskActivity.this) |
||||
.load(DOWNLOAD_URL) // url 必须是主体url,也就是?前面的内容 |
||||
.setFilePath(path, true) |
||||
.asGet() |
||||
.setParams(params) // 设置参数 |
||||
.start(); |
||||
``` |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/335 |
||||
- 新增进度百分比保存 https://github.com/AriaLyy/Aria/issues/336 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/335 |
||||
+ v_3.5.2 |
||||
- 添加Serializable接口支持 https://github.com/AriaLyy/Aria/issues/320 |
||||
- 失败回调增加错误原因 https://github.com/AriaLyy/Aria/issues/310 |
||||
``` |
||||
@Download.onTaskFail void taskFail(DownloadTask task, Exception e) { |
||||
e.getMessage(); |
||||
... |
||||
} |
||||
``` |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/322 |
||||
- 新增201 重定向支持 https://github.com/AriaLyy/Aria/issues/318 |
||||
- 修复使用`useServerFileName(true)`中含有`"`导致的文件后缀名错误问题 |
||||
- 优化logcat日志提示 |
||||
- 修改下载线程的优先级为`Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);` |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/319 |
||||
- 修复分卡下载失败的问题 https://github.com/AriaLyy/Aria/issues/326 |
||||
- 初始化Aria时会将所有数据库状态为下载中的任务改为已停止,防止应用被kill后,任务状态错误 |
||||
- 初始化时自动判断文件是否被删除,文件被删除的任务将自动重置默认值 |
||||
- 修复刷新url后,文件无法删除的 bug |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/309 |
||||
- 优化配置文件的读取 |
||||
+ v_3.5.1 |
||||
- 优化`taskExists`方法 |
||||
- 添加`post`参数请求支持 |
||||
```java |
||||
Aria.download(SingleTaskActivity.this) |
||||
.load(DOWNLOAD_URL) |
||||
.setFilePath(path) |
||||
.asPost() // post请求 |
||||
.setParam("key", "value") //传递参数 |
||||
//.setParams(Map<String, String>) // 传递多参数 |
||||
.start(); |
||||
``` |
||||
- 增加强制设置文件路径的api, https://github.com/AriaLyy/Aria/issues/311 |
||||
```java |
||||
Aria.download(SingleTaskActivity.this) |
||||
.load(DOWNLOAD_URL) |
||||
.setFilePath(path, true) // true表示忽略路径是否被占用 |
||||
.start(); |
||||
``` |
||||
+ v_3.5 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/302 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/283 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/305 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/306 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/272 (现在,停止所有任务,未开始的任务状态将变为停止) |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/277 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/303 |
||||
- 优化停止任务的速度 |
||||
- 修复组合任务修改子任务文件名失败的问题 |
||||
+ v_3.4.12 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/286 |
||||
- 优化线程池任务 |
||||
+ v_3.4.11 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/288 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/282 |
||||
+ v_3.4.10 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/280 |
||||
+ v_3.4.9 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/276 |
||||
+ v_3.4.8 |
||||
- 组合任务新增`updateUrls(List<String>)`用于修改组合子任务的url,[see](https://aria.laoyuyu.me/aria_doc/api/update_url.html) |
||||
- 出于安全考虑,FTP数据库去掉密码的保存 |
||||
- 增加FTPS支持 [see](https://aria.laoyuyu.me/aria_doc/download/ftps.html) |
||||
- 增加速度限制支持[see](https://aria.laoyuyu.me/aria_doc/api/speed_handle.html) |
||||
- 增加内存空间不足验证 |
||||
+ v_3.4.7 |
||||
- 修复分块任务异常操作导致的问题 |
||||
+ v_3.4.6 |
||||
- 修复android 4.4.4 版本多dex下无法进行回调的问题 |
||||
- 新增`updateUrl(newUrl)`用于修改任务的url,[see](https://aria.laoyuyu.me/aria_doc/api/task_handle.html#%E6%9B%B4%E6%96%B0%E4%BB%BB%E5%8A%A1url) |
||||
- 优化分块下载 |
||||
- 修复了字符串中有特殊字符导致的路径冲突问题;修复ftp分块下载失败问题 |
||||
- 修复连接中有`+`导致的地址呗使用问题。 |
||||
- 修复表重复创建导致的崩溃问题 https://github.com/AriaLyy/Aria/issues/264 |
||||
+ v_3.4.4 |
||||
- 实现[多线程分块下载](https://aria.laoyuyu.me/aria_doc/start/config.html) |
||||
- 修复`stopAll()`和`resumeAll()`导致的进度为0问题 |
||||
- 修复任务组添加header无效的问题 |
||||
+ v_3.4.3 |
||||
- 修复在activity 的onStop中取消注册导致的内存泄露问题 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/258 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/259 |
||||
+ v_3.4.2 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/248 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/247 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/250 |
||||
- 添加任务判断是否存在的api |
||||
- 添加代理api |
||||
- 修复删除所有没有进出等待的问题 |
||||
- 进度有时出错的问题 |
||||
- FTP添加超时处理 |
||||
+ v_3.4.1 |
||||
- 移除记录配置文件,改用数据库记录任务记录 |
||||
- 上传配置添加io超时时间、缓存大小配置 |
||||
- 添加没有网络也会重试的开关 |
||||
- 修复多次删除记录的bug |
||||
- 文件长度现在可动态增加,详情见 https://aria.laoyuyu.me/aria_doc/start/config.html |
||||
- 修复多module同时引用Aria导致打正式包出错的问题 https://github.com/AriaLyy/Aria/issues/240 |
||||
+ v_3.4 |
||||
- 优化大量代码 |
||||
- 重构Aria的ORM模型,提高了数据读取的可靠性和读写速度 |
||||
- 现在可在任意类中使用Aria了,[使用方法](http://aria.laoyuyu.me/aria_doc/start/any_java.html) |
||||
- 添加`window.location.replace("http://xxxx")`类型的网页重定向支持 |
||||
- 支持gzip、deflate 压缩类型的输入流 |
||||
- 添加`useServerFileName`,可使用服务端响应header的`Content-Disposition`携带的文件名 |
||||
+ v_3.3.16 |
||||
- 修复一个activity启动多次,无法进行回掉的bug https://github.com/AriaLyy/Aria/issues/200 |
||||
- 优化target代码结构,移除路径被占用的提示 |
||||
- 添加支持chunked模式的下载 |
||||
- 去掉上一个版本"//"的限制 |
||||
+ v_3.3.14 |
||||
- 修复ftp上传和下载的兼容性问题 |
||||
- 如果url中的path有"//"将替换为"/" |
||||
- 修复http上传成功后,如果服务器没有设置返回码导致上传失败的问题 |
||||
- 上传实体UploadEntity增加responseStr字段,http上传完成后,在被`@Upload.onComplete`注解的方法中,可通过`task.getEntity().getResponseStr())`获取服务器返回的数据 |
||||
- 如果服务器存在已上传了一部分的文件,用户执行删除该FTP上传任务,再次重新上传,会出现550,权限错误;本版本已修复该问题 |
||||
+ v_3.3.13 |
||||
- 添加`@Download.onWait、@Upload.onWait、@DownloadGroup.onWait`三个新注解,队列已经满了,继续创建新任务,任务处于等待中,将会执行被这三个注解标志的方法 |
||||
- app被kill,但是还存在等待中的任务A;第二次重新启动,先创建一个新的任务B,Aria会自动把B放进等待队列中,这时再次创建任务A,会导致重复下载,进度错乱的问题;本版本已修复这个问题 |
||||
+ v_3.3.11 |
||||
- 添加进度更新间隔api,在`aria_config.xml`配置`<updateInterval value="1000"/>`或在代码中调用 |
||||
`AriaManager.getInstance(AriaManager.APP).getDownloadConfig().setUpdateInterval(3000)`便可以改变进度刷新间隔 |
||||
- 修复下载过程中kill进程可能出现的文件错误的问题 https://github.com/AriaLyy/Aria/issues/192 |
||||
- 修复http上传的空指针问题 https://github.com/AriaLyy/Aria/issues/193 |
||||
- 修复下载地址中含有`'`导致的崩溃问题 https://github.com/AriaLyy/Aria/issues/194 |
||||
+ v_3.3.10 |
||||
- 修复地址切换导致下载失败的问题 https://github.com/AriaLyy/Aria/issues/181 |
||||
- 添加重置状态的api,当下载信息不改变,只是替换了服务器的对应的文件,可用`Aria.download(this).load(url).resetState()`重置下载状态 https://github.com/AriaLyy/Aria/issues/182 |
||||
+ v_3.3.9 |
||||
- 添加POST支持 |
||||
- 任务执行的过程中,如果调用removeRecord()方法,将会取消任务 https://github.com/AriaLyy/Aria/issues/174 |
||||
- 修复一个数据库初始化的问题 https://github.com/AriaLyy/Aria/issues/173 |
||||
- 修复head头部信息过长时出现的崩溃问题 https://github.com/AriaLyy/Aria/issues/177 |
||||
+ v_3.3.7 |
||||
- 修复一个线程重启的问题 https://github.com/AriaLyy/Aria/issues/160 |
||||
- 修复配置文件异常问题、格式化速度为0问题 https://github.com/AriaLyy/Aria/issues/161 |
||||
+ v_3.3.6 |
||||
- 增加日志输出级别控制 |
||||
- 修复公网FTP地址不能下载的问题 https://github.com/AriaLyy/Aria/issues/146 |
||||
- 修复http下载地址有空格的时候下载失败的问题 https://github.com/AriaLyy/Aria/issues/131 |
||||
- 修复Activity在`onDestroy()`中调用`Aria.download(this).unRegister();`导致回调失效的问题 |
||||
- 修复Adapter下载FTP任务问题、任务调度问题 https://github.com/AriaLyy/Aria/issues/157 |
||||
- 优化代码,优化了IO性能 |
||||
+ v_3.3.5 修复任务组、上传任务无法启动的bug |
||||
+ v_3.3.4 优化任务代码结构,修复上一个版本暂停后无法自动执行任务的问题 |
||||
+ v_3.3.3 修复进度条错乱的问题,修复同一时间多次调用start导致重复下载的问题 |
||||
+ v_3.3.2 新加reTry(),修复上一个版本不会回调失败事件的问题;增加running状态下5秒钟保存一次数据库的功能;修复FTP断点上传文件不完整的问题 |
||||
+ v_3.3.1 增加网络事件,网络未连接,将不会重试下载,修复删除未开始任务,状态回调错误 |
||||
+ v_3.3.0 增加任务组子任务暂停和开始控制功能、修复5.0系统以上数据库多生成两个字段的bug、去掉addSchedulerListener事件 |
||||
+ v_3.2.26 修复任务组有时注解不起作用的问题 |
||||
+ v_3.2.25 修复删除任务组文件,记录无法删除的问题 |
||||
+ v_3.2.17 修复一个版本兼容性问题,线程中使用Aria出错问题 |
||||
+ v_3.2.15 修复大型文件分段下载失败的问题,修复中文URL乱码问题 |
||||
+ v_3.2.14 修复恢复所有任务的api接口,不能恢复下载组任务的问题 |
||||
+ v_3.2.13 修复某些服务器头文件返回描述文件格式错误的问题、修复有时删除任务,需要两次删除的问题 |
||||
+ v_3.2.12 实现FTP多线程断点续传下载,FTP断点续传上传功能 |
||||
+ v_3.2.9 修复任务组下载完成两次回掉的问题,修复又是获取不到下载状态的问题 |
||||
+ v_3.2.8 修复下载超过2G大小的文件失败的问题 |
||||
+ v_3.2.7 移除设置文件名的api接口,修复断开网络时出现的进度条错误的问题 |
||||
+ v_3.2.6 移除广播事件,增加任务组下载功能 |
||||
+ v_3.1.9 修复stopAll队列没有任务时崩溃的问题,增加针对单个任务监听的功能 |
||||
+ v_3.1.7 修复某些文件下载不了的bug,增加apt注解方法,事件获取更加简单了 |
||||
+ v_3.1.6 取消任务时onTaskCancel回调两次的bug |
||||
+ v_3.1.5 优化代码结构,增加优先下载任务功能。 |
||||
+ v_3.1.4 修复快速切换,暂停、恢复功能时,概率性出现的重新下载问题,添加onPre()回调,onPre()用于请求地址之前执行界面UI更新操作。 |
||||
+ v_3.1.0 添加Aria配置文件,优化代码 |
||||
+ v_3.0.3 修复暂停后删除任务,闪退问题,添加删除记录的api |
||||
+ v_3.0.2 支持30x重定向链接下载 |
||||
+ v_3.0.0 添加上传任务支持,修复一些已发现的bug |
||||
+ v_2.4.4 修复不支持断点的下载链接拿不到文件大小的问题 |
||||
+ v_2.4.3 修复404链接卡顿的问题 |
||||
+ v_2.4.2 修复失败重试无效的bug |
||||
+ v_2.4.1 修复下载慢的问题,修复application、service 不能使用的问题 |
||||
+ v_2.4.0 支持https链接下载 |
||||
+ v_2.3.8 修复数据错乱的bug、添加fragment支持 |
||||
+ v_2.3.6 添加dialog、popupWindow支持 |
||||
+ v_2.3.3 添加断点支持、修改下载逻辑,让使用更加简单、修复一个内存泄露的bug |
||||
+ v_2.3.1 重命名为Aria,下载流程简化 |
||||
+ v_2.1.1 增加,选择最大下载任务数接口 |
@ -1,172 +1,172 @@ |
||||
# Aria |
||||
![图标](https://github.com/AriaLyy/DownloadUtil/blob/v_3.0/app/src/main/res/mipmap-hdpi/ic_launcher.png)</br> |
||||
## [ENGLISH DOC](https://github.com/AriaLyy/Aria/blob/master/ENGLISH_README.md)</br> |
||||
## [中文文档](https://aria.laoyuyu.me/aria_doc) |
||||
Aria项目源于工作中遇到的一个文件下载管理的需求,当时被下载折磨的痛不欲生,从那时起便萌生了编写一个简单易用,稳当高效的下载框架,aria经历了1.0到3.0的开发,算是越来越接近当初所制定的目标了。 |
||||
|
||||
Aria有以下特点: |
||||
+ 简单、方便 |
||||
- 可以在Activity、Service、Fragment、Dialog、popupWindow、Notification等组件中使用 |
||||
- 支持HTTP\FTP断点续传下载、多任务自动调度 |
||||
- 支持多文件打包下载,多文件共享同一进度(如:视频 + 封面 + 字幕) |
||||
- 支持下载FTP文件夹 |
||||
- 支持HTTP表单上传 |
||||
- 支持文件FTP断点续传上传 |
||||
- 支持FTPS/SFTP断点续传,[see](https://aria.laoyuyu.me/aria_doc/download/ftps.html) |
||||
+ 支持https地址下载 |
||||
- 在配置文件中很容易就可以设置CA证书的信息 |
||||
+ 支持[多线程分块下载](https://aria.laoyuyu.me/aria_doc/start/config.html),能更有效的发挥机器IO性能 |
||||
+ 支持300、301、302重定向下载链接下载 |
||||
+ 下载支持文件长度动态增加,文件下载初始化时将不再占用过多的内存空间,见[动态长度配置](https://aria.laoyuyu.me/aria_doc/start/config.html#%E4%B8%8B%E8%BD%BD%E5%8A%A8%E6%80%81%E6%96%87%E4%BB%B6%E8%AF%B4%E6%98%8E) |
||||
|
||||
[怎样使用Aria?](#使用) |
||||
|
||||
如果你觉得Aria对你有帮助,您的star和issues将是对我最大支持.`^_^` |
||||
|
||||
## 示例 |
||||
* 多任务下载 |
||||
|
||||
![多任务下载](https://github.com/AriaLyy/DownloadUtil/blob/master/img/download_img.gif) |
||||
|
||||
* 速度限制 |
||||
|
||||
![网速下载限制](https://github.com/AriaLyy/DownloadUtil/blob/master/img/max_speed.gif) |
||||
|
||||
* 多文件打包下载 |
||||
|
||||
<img src="https://github.com/AriaLyy/DownloadUtil/blob/master/img/group_task.gif" width="360" height="640"/> |
||||
|
||||
|
||||
## 引入库 |
||||
[![Core](https://api.bintray.com/packages/arialyy/maven/AriaApi/images/download.svg)](https://bintray.com/arialyy/maven/AriaApi/_latestVersion) |
||||
[![Compiler](https://api.bintray.com/packages/arialyy/maven/AriaCompiler/images/download.svg)](https://bintray.com/arialyy/maven/AriaCompiler/_latestVersion) |
||||
|
||||
```java |
||||
compile 'com.arialyy.aria:aria-core:3.6.3' |
||||
annotationProcessor 'com.arialyy.aria:aria-compiler:3.6.3' |
||||
``` |
||||
如果出现android support依赖错误,请将 `compile 'com.arialyy.aria:aria-core:<last-version>'`替换为 |
||||
``` |
||||
api('com.arialyy.aria:aria-core:<last-version>'){ |
||||
exclude group: 'com.android.support' |
||||
} |
||||
``` |
||||
如果你使用的是kotlin,请使用kotlin官方提供的方法配置apt,[kotlin kapt官方配置传送门](https://www.kotlincn.net/docs/reference/kapt.html) |
||||
|
||||
__注意:3.5.4以下版本升级时,需要更新[配置文件]!!(https://aria.laoyuyu.me/aria_doc/start/config.html)__ |
||||
|
||||
*** |
||||
## 使用 |
||||
由于Aria涉及到文件和网络的操作,因此需要你在manifest文件中添加以下权限,如果你希望在6.0以上的系统中使用Aria,那么你需要动态向安卓系统申请文件系统读写权限,[如何使用安卓系统权限](https://developer.android.com/training/permissions/index.html?hl=zh-cn) |
||||
```xml |
||||
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> |
||||
<uses-permission android:name="android.permission.INTERNET"/> |
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> |
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> |
||||
``` |
||||
|
||||
## 使用Aria |
||||
### 基本使用 |
||||
例子为单任务下载,只需要很简单的代码,便可以实现下载功能 |
||||
```java |
||||
Aria.download(this) |
||||
.load(DOWNLOAD_URL) //读取下载地址 |
||||
.setDownloadPath(DOWNLOAD_PATH) //设置文件保存的完整路径 |
||||
.start(); //启动下载 |
||||
``` |
||||
|
||||
### 任务状态的获取 |
||||
基于解耦合的考虑,Aria的下载功能是和状态获取相分离的,状态的获取并不会集成到链式代码中,但是Aria提供了另一种更简单更灵活的方案。 |
||||
通过注解,你可以很容易获取任务的所有状态。 |
||||
|
||||
1. 将对象注册到Aria |
||||
```java |
||||
protected void onCreate(Bundle savedInstanceState) { |
||||
super.onCreate(savedInstanceState); |
||||
Aria.download(this).register(); |
||||
} |
||||
``` |
||||
|
||||
2. 通过注解获取任务执行状态 |
||||
**注意:** |
||||
- 注解回掉采用Apt的方式实现,所以,你不需要担心这会影响你机器的性能 |
||||
- 被注解的方法**不能被private修饰** |
||||
- 被注解的方法**只能有一个参数,并且参数类型必须是`DownloadTask`或`UploadTask`或`DownloadGroupTask`** |
||||
- 方法名可以为任意字符串 |
||||
|
||||
```java |
||||
//在这里处理任务执行中的状态,如进度进度条的刷新 |
||||
@Download.onTaskRunning protected void running(DownloadTask task) { |
||||
if(task.getUrl().eques(url)){ |
||||
.... |
||||
可以通过url判断是否是指定任务的回调 |
||||
} |
||||
int p = task.getPercent(); //任务进度百分比 |
||||
String speed = task.getConvertSpeed(); //转换单位后的下载速度,单位转换需要在配置文件中打开 |
||||
String speed1 = task.getSpeed(); //原始byte长度速度 |
||||
} |
||||
|
||||
@Download.onTaskComplete void taskComplete(DownloadTask task) { |
||||
//在这里处理任务完成的状态 |
||||
} |
||||
``` |
||||
|
||||
|
||||
### 版本日志 |
||||
* v3.6.3 (2019/4/2) |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/368 |
||||
- 增加gradle 5.0支持 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/374 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/377 |
||||
- 增加分页获取任务列表api, 详情见:https://aria.laoyuyu.me/aria_doc/api/task_list.html#%E4%BB%BB%E5%8A%A1%E5%88%97%E8%A1%A8%E5%88%86%E9%A1%B5%EF%BC%88362%E4%BB%A5%E4%B8%8A%E7%89%88%E6%9C%AC%E6%94%AF%E6%8C%81%EF%BC%89 |
||||
|
||||
[更多版本记录](https://github.com/AriaLyy/Aria/blob/master/DEV_LOG.md) |
||||
|
||||
## 混淆配置 |
||||
``` |
||||
-dontwarn com.arialyy.aria.** |
||||
-keep class com.arialyy.aria.**{*;} |
||||
-keep class **$$DownloadListenerProxy{ *; } |
||||
-keep class **$$UploadListenerProxy{ *; } |
||||
-keep class **$$DownloadGroupListenerProxy{ *; } |
||||
-keepclasseswithmembernames class * { |
||||
@Download.* <methods>; |
||||
@Upload.* <methods>; |
||||
@DownloadGroup.* <methods>; |
||||
} |
||||
|
||||
``` |
||||
|
||||
## 其他 |
||||
有任何问题,可以在[issues](https://github.com/AriaLyy/Aria/issues)给我留言反馈。</br> |
||||
在提交问题前,希望你已经查看过[wiki](https://aria.laoyuyu.me/aria_doc/)或搜索过[issues](https://github.com/AriaLyy/Aria/issues)。</br> |
||||
交流群:524329160 |
||||
|
||||
*** |
||||
|
||||
License |
||||
------- |
||||
|
||||
Copyright 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. |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Aria |
||||
![图标](https://github.com/AriaLyy/DownloadUtil/blob/v_3.0/app/src/main/res/mipmap-hdpi/ic_launcher.png)</br> |
||||
## [ENGLISH DOC](https://github.com/AriaLyy/Aria/blob/master/ENGLISH_README.md)</br> |
||||
## [中文文档](https://aria.laoyuyu.me/aria_doc) |
||||
Aria项目源于工作中遇到的一个文件下载管理的需求,当时被下载折磨的痛不欲生,从那时起便萌生了编写一个简单易用,稳当高效的下载框架,aria经历了1.0到3.0的开发,算是越来越接近当初所制定的目标了。 |
||||
|
||||
Aria有以下特点: |
||||
+ 简单、方便 |
||||
- 可以在Activity、Service、Fragment、Dialog、popupWindow、Notification等组件中使用 |
||||
- 支持HTTP\FTP断点续传下载、多任务自动调度 |
||||
- 支持多文件打包下载,多文件共享同一进度(如:视频 + 封面 + 字幕) |
||||
- 支持下载FTP文件夹 |
||||
- 支持HTTP表单上传 |
||||
- 支持文件FTP断点续传上传 |
||||
- 支持FTPS/SFTP断点续传,[see](https://aria.laoyuyu.me/aria_doc/download/ftps.html) |
||||
+ 支持https地址下载 |
||||
- 在配置文件中很容易就可以设置CA证书的信息 |
||||
+ 支持[多线程分块下载](https://aria.laoyuyu.me/aria_doc/start/config.html),能更有效的发挥机器IO性能 |
||||
+ 支持300、301、302重定向下载链接下载 |
||||
+ 下载支持文件长度动态增加,文件下载初始化时将不再占用过多的内存空间,见[动态长度配置](https://aria.laoyuyu.me/aria_doc/start/config.html#%E4%B8%8B%E8%BD%BD%E5%8A%A8%E6%80%81%E6%96%87%E4%BB%B6%E8%AF%B4%E6%98%8E) |
||||
|
||||
[怎样使用Aria?](#使用) |
||||
|
||||
如果你觉得Aria对你有帮助,您的star和issues将是对我最大支持.`^_^` |
||||
|
||||
## 示例 |
||||
* 多任务下载 |
||||
|
||||
![多任务下载](https://github.com/AriaLyy/DownloadUtil/blob/master/img/download_img.gif) |
||||
|
||||
* 速度限制 |
||||
|
||||
![网速下载限制](https://github.com/AriaLyy/DownloadUtil/blob/master/img/max_speed.gif) |
||||
|
||||
* 多文件打包下载 |
||||
|
||||
<img src="https://github.com/AriaLyy/DownloadUtil/blob/master/img/group_task.gif" width="360" height="640"/> |
||||
|
||||
|
||||
## 引入库 |
||||
[![Core](https://api.bintray.com/packages/arialyy/maven/AriaApi/images/download.svg)](https://bintray.com/arialyy/maven/AriaApi/_latestVersion) |
||||
[![Compiler](https://api.bintray.com/packages/arialyy/maven/AriaCompiler/images/download.svg)](https://bintray.com/arialyy/maven/AriaCompiler/_latestVersion) |
||||
|
||||
```java |
||||
compile 'com.arialyy.aria:aria-core:3.6.3' |
||||
annotationProcessor 'com.arialyy.aria:aria-compiler:3.6.3' |
||||
``` |
||||
如果出现android support依赖错误,请将 `compile 'com.arialyy.aria:aria-core:<last-version>'`替换为 |
||||
``` |
||||
api('com.arialyy.aria:aria-core:<last-version>'){ |
||||
exclude group: 'com.android.support' |
||||
} |
||||
``` |
||||
如果你使用的是kotlin,请使用kotlin官方提供的方法配置apt,[kotlin kapt官方配置传送门](https://www.kotlincn.net/docs/reference/kapt.html) |
||||
|
||||
__注意:3.5.4以下版本升级时,需要更新[配置文件]!!(https://aria.laoyuyu.me/aria_doc/start/config.html)__ |
||||
|
||||
*** |
||||
## 使用 |
||||
由于Aria涉及到文件和网络的操作,因此需要你在manifest文件中添加以下权限,如果你希望在6.0以上的系统中使用Aria,那么你需要动态向安卓系统申请文件系统读写权限,[如何使用安卓系统权限](https://developer.android.com/training/permissions/index.html?hl=zh-cn) |
||||
```xml |
||||
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> |
||||
<uses-permission android:name="android.permission.INTERNET"/> |
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> |
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> |
||||
``` |
||||
|
||||
## 使用Aria |
||||
### 基本使用 |
||||
例子为单任务下载,只需要很简单的代码,便可以实现下载功能 |
||||
```java |
||||
Aria.download(this) |
||||
.load(DOWNLOAD_URL) //读取下载地址 |
||||
.setDownloadPath(DOWNLOAD_PATH) //设置文件保存的完整路径 |
||||
.start(); //启动下载 |
||||
``` |
||||
|
||||
### 任务状态的获取 |
||||
基于解耦合的考虑,Aria的下载功能是和状态获取相分离的,状态的获取并不会集成到链式代码中,但是Aria提供了另一种更简单更灵活的方案。 |
||||
通过注解,你可以很容易获取任务的所有状态。 |
||||
|
||||
1. 将对象注册到Aria |
||||
```java |
||||
protected void onCreate(Bundle savedInstanceState) { |
||||
super.onCreate(savedInstanceState); |
||||
Aria.download(this).register(); |
||||
} |
||||
``` |
||||
|
||||
2. 通过注解获取任务执行状态 |
||||
**注意:** |
||||
- 注解回掉采用Apt的方式实现,所以,你不需要担心这会影响你机器的性能 |
||||
- 被注解的方法**不能被private修饰** |
||||
- 被注解的方法**只能有一个参数,并且参数类型必须是`DownloadTask`或`UploadTask`或`DownloadGroupTask`** |
||||
- 方法名可以为任意字符串 |
||||
|
||||
```java |
||||
//在这里处理任务执行中的状态,如进度进度条的刷新 |
||||
@Download.onTaskRunning protected void running(DownloadTask task) { |
||||
if(task.getKey().eques(url)){ |
||||
.... |
||||
可以通过url判断是否是指定任务的回调 |
||||
} |
||||
int p = task.getPercent(); //任务进度百分比 |
||||
String speed = task.getConvertSpeed(); //转换单位后的下载速度,单位转换需要在配置文件中打开 |
||||
String speed1 = task.getSpeed(); //原始byte长度速度 |
||||
} |
||||
|
||||
@Download.onTaskComplete void taskComplete(DownloadTask task) { |
||||
//在这里处理任务完成的状态 |
||||
} |
||||
``` |
||||
|
||||
|
||||
### 版本日志 |
||||
* v3.6.3 (2019/4/2) |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/368 |
||||
- 增加gradle 5.0支持 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/374 |
||||
- fix bug https://github.com/AriaLyy/Aria/issues/377 |
||||
- 增加分页获取任务列表api, 详情见:https://aria.laoyuyu.me/aria_doc/api/task_list.html#%E4%BB%BB%E5%8A%A1%E5%88%97%E8%A1%A8%E5%88%86%E9%A1%B5%EF%BC%88362%E4%BB%A5%E4%B8%8A%E7%89%88%E6%9C%AC%E6%94%AF%E6%8C%81%EF%BC%89 |
||||
|
||||
[更多版本记录](https://github.com/AriaLyy/Aria/blob/master/DEV_LOG.md) |
||||
|
||||
## 混淆配置 |
||||
``` |
||||
-dontwarn com.arialyy.aria.** |
||||
-keep class com.arialyy.aria.**{*;} |
||||
-keep class **$$DownloadListenerProxy{ *; } |
||||
-keep class **$$UploadListenerProxy{ *; } |
||||
-keep class **$$DownloadGroupListenerProxy{ *; } |
||||
-keepclasseswithmembernames class * { |
||||
@Download.* <methods>; |
||||
@Upload.* <methods>; |
||||
@DownloadGroup.* <methods>; |
||||
} |
||||
|
||||
``` |
||||
|
||||
## 其他 |
||||
有任何问题,可以在[issues](https://github.com/AriaLyy/Aria/issues)给我留言反馈。</br> |
||||
在提交问题前,希望你已经查看过[wiki](https://aria.laoyuyu.me/aria_doc/)或搜索过[issues](https://github.com/AriaLyy/Aria/issues)。</br> |
||||
交流群:524329160 |
||||
|
||||
*** |
||||
|
||||
License |
||||
------- |
||||
|
||||
Copyright 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. |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,161 +1,161 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<aria> |
||||
<!--注意,修改该配置文件中的属性会覆盖代码中所设置的属性--> |
||||
|
||||
<!--Aria框架配置--> |
||||
<app> |
||||
<!--是否使用AriaCrashHandler来捕获异常,异常日志保存在:/mnt/sdcard/Android/data/{package_name}/files/log/--> |
||||
<useAriaCrashHandler value="true"/> |
||||
<!--设置Aria的日志级别,{@link ALog#LOG_LEVEL_VERBOSE}--> |
||||
<logLevel value="2"/> |
||||
<!-- 是否检查网络 true: 检查网络,false: 不检查网络--> |
||||
<netCheck value="false"/> |
||||
<!--除非无法使用注解,否则不建议使用广播来接受任务状态,true:使用广播接收任务状态,false:不适用广播接收状态 --> |
||||
<!-- http://aria.laoyuyu.me/aria_doc/api/use_broadcast.html --> |
||||
<useBroadcast value="true"/> |
||||
<!--断网的时候是否重试,true:断网也重试;false:断网不重试,直接走失败的回调--> |
||||
<notNetRetry value="true"/> |
||||
</app> |
||||
|
||||
|
||||
<!--普通下载任务--> |
||||
<download> |
||||
|
||||
<!--设置任务最大下载速度,0表示不限速,单位为:kb--> |
||||
<maxSpeed value="128"/> |
||||
|
||||
<!-- |
||||
多线程下载是否使用块下载模式,{@code true}使用,{@code false}不使用 |
||||
注意: |
||||
1、使用分块模式,在I/O性能底下的手机上,合并文件需要的时间会更加长; |
||||
2、优点是使用多线程的块下载,初始化时,文件初始化时将不会预占用对应长度的空间; |
||||
3、只对新的多线程下载任务有效 |
||||
4、只对多线程的任务有效 |
||||
--> |
||||
<useBlock value="true"/> |
||||
|
||||
<!--设置下载线程数,下载线程数不能小于1 |
||||
注意: |
||||
1、线程下载数改变后,新的下载任务才会生效; |
||||
2、如果任务大小小于1m,该设置不会生效; |
||||
3、从3.4.1开始,如果线程数为1,文件初始化时将不再预占用对应长度的空间,下载多少byte,则占多大的空间; |
||||
对于3.4.1之前版本的未完成的老任务,依然采用原来的文件空间占用方式; |
||||
--> |
||||
<threadNum value="1"/> |
||||
|
||||
<!--设置下载队列最大任务数, 默认为2--> |
||||
<maxTaskNum value="1"/> |
||||
|
||||
<!--设置下载失败,重试次数,默认为10--> |
||||
<reTryNum value="1"/> |
||||
|
||||
<!--设置重试间隔,单位为毫秒,默认2000毫秒--> |
||||
<reTryInterval value="5000"/> |
||||
|
||||
<!--设置url连接超时时间,单位为毫秒,默认5000毫秒--> |
||||
<connectTimeOut value="5000"/> |
||||
|
||||
<!--设置IO流读取时间,单位为毫秒,默认20000毫秒,该时间不能少于10000毫秒--> |
||||
<iOTimeOut value="10000"/> |
||||
|
||||
<!--设置写文件buff大小,该数值大小不能小于2048,数值变小,下载速度会变慢--> |
||||
<buffSize value="8192"/> |
||||
|
||||
<!--设置https ca 证书信息;path 为assets目录下的CA证书完整路径,name 为CA证书名--> |
||||
<ca name="" path=""/> |
||||
|
||||
<!--是否需要转换速度单位,转换完成后为:1b/s、1kb/s、1mb/s、1gb/s、1tb/s,如果不需要将返回byte长度--> |
||||
<convertSpeed value="true"/> |
||||
|
||||
<!--执行队列类型,见com.arialyy.aria.core.QueueMod,默认类型为wait--> |
||||
<queueMod value="wait"/> |
||||
|
||||
<!--进度更新更新间隔,默认1000毫秒--> |
||||
<updateInterval value="1000"/> |
||||
|
||||
</download> |
||||
|
||||
<!--普通上传任务--> |
||||
<upload> |
||||
<!--设置任务最大上传速度,0表示不限速,单位为:kb--> |
||||
<maxSpeed value="0"/> |
||||
|
||||
<!--设置IO流读取时间,单位为毫秒,默认20000毫秒,该时间不能少于10000毫秒--> |
||||
<iOTimeOut value="10000"/> |
||||
|
||||
<!--设置写文件buff大小,该数值大小不能小于2048,数值变小,速度会变慢--> |
||||
<buffSize value="8192"/> |
||||
|
||||
<!--是否需要转换速度单位,转换完成后为:1b/s、1kb/s、1mb/s、1gb/s、1tb/s,如果不需要将返回byte长度--> |
||||
<convertSpeed value="true"/> |
||||
|
||||
<!--设置上传队列最大任务数, 默认为2--> |
||||
<maxTaskNum value="2"/> |
||||
|
||||
<!--设置上传失败,重试次数,默认为10--> |
||||
<reTryNum value="3"/> |
||||
|
||||
<!--设置重试间隔,单位为毫秒--> |
||||
<reTryInterval value="2000"/> |
||||
|
||||
<!--设置url连接超时时间,单位为毫秒,默认5000毫秒--> |
||||
<connectTimeOut value="5000"/> |
||||
|
||||
<!--执行队列类型,见com.arialyy.aria.core.QueueMod,默认类型为wait--> |
||||
<queueMod value="wait"/> |
||||
|
||||
<!--进度更新更新间隔,默认1000毫秒--> |
||||
<updateInterval value="1000"/> |
||||
|
||||
</upload> |
||||
|
||||
<!-- 下载类组合任务 --> |
||||
<dGroup> |
||||
|
||||
<!--组合任务下载队列最大任务数, 默认为2--> |
||||
<maxTaskNum value="1"/> |
||||
|
||||
<!--设置下载失败,重试次数,默认为10--> |
||||
<reTryNum value="1"/> |
||||
|
||||
<!--设置重试间隔,单位为毫秒,默认2000毫秒--> |
||||
<reTryInterval value="5000"/> |
||||
|
||||
<!--执行队列类型,见com.arialyy.aria.core.QueueMod,默认类型为wait--> |
||||
<queueMod value="wait"/> |
||||
|
||||
<!--进度更新更新间隔,默认1000毫秒--> |
||||
<updateInterval value="1000"/> |
||||
|
||||
|
||||
<!-- =============================以下为子任务的配置====================================--> |
||||
|
||||
<!--能同时下载的子任务最大任务数,默认3--> |
||||
<subMaxTaskNum value="1"/> |
||||
|
||||
<!--子任务下载失败时的重试次数,默认为5--> |
||||
<subReTryNum value="5"/> |
||||
|
||||
<!--子任务下载失败时的重试间隔,单位为毫秒,默认2000毫秒--> |
||||
<subReTryInterval value="5000"/> |
||||
|
||||
<!--子任务url连接超时时间,单位为毫秒,默认5000毫秒--> |
||||
<connectTimeOut value="5000"/> |
||||
|
||||
<!--子任务IO流读取时间,单位为毫秒,默认20000毫秒,该时间不能少于10000毫秒--> |
||||
<iOTimeOut value="10000"/> |
||||
|
||||
<!--子任务写文件buff大小,该数值大小不能小于2048,数值变小,下载速度会变慢--> |
||||
<buffSize value="8192"/> |
||||
|
||||
<!--子任务 https ca 证书信息;path 为assets目录下的CA证书完整路径,name 为CA证书名--> |
||||
<ca name="" path=""/> |
||||
|
||||
<!--子任务是否需要转换速度单位,转换完成后为:1b/s、1kb/s、1mb/s、1gb/s、1tb/s,如果不需要将返回byte长度--> |
||||
<convertSpeed value="true"/> |
||||
|
||||
<!--子任务的最大下载速度,0表示不限速,单位为:kb; --> |
||||
<maxSpeed value="0"/> |
||||
|
||||
</dGroup> |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<aria> |
||||
<!--注意,修改该配置文件中的属性会覆盖代码中所设置的属性--> |
||||
|
||||
<!--Aria框架配置--> |
||||
<app> |
||||
<!--是否使用AriaCrashHandler来捕获异常,异常日志保存在:/mnt/sdcard/Android/data/{package_name}/files/log/--> |
||||
<useAriaCrashHandler value="true"/> |
||||
<!--设置Aria的日志级别,{@link ALog#LOG_LEVEL_VERBOSE}--> |
||||
<logLevel value="2"/> |
||||
<!-- 是否检查网络 true: 检查网络,false: 不检查网络--> |
||||
<netCheck value="false"/> |
||||
<!--除非无法使用注解,否则不建议使用广播来接受任务状态,true:使用广播接收任务状态,false:不适用广播接收状态 --> |
||||
<!-- http://aria.laoyuyu.me/aria_doc/api/use_broadcast.html --> |
||||
<useBroadcast value="true"/> |
||||
<!--断网的时候是否重试,true:断网也重试;false:断网不重试,直接走失败的回调--> |
||||
<notNetRetry value="true"/> |
||||
</app> |
||||
|
||||
|
||||
<!--普通下载任务--> |
||||
<download> |
||||
|
||||
<!--设置任务最大下载速度,0表示不限速,单位为:kb--> |
||||
<maxSpeed value="128"/> |
||||
|
||||
<!-- |
||||
多线程下载是否使用块下载模式,{@code true}使用,{@code false}不使用 |
||||
注意: |
||||
1、使用分块模式,在I/O性能底下的手机上,合并文件需要的时间会更加长; |
||||
2、优点是使用多线程的块下载,初始化时,文件初始化时将不会预占用对应长度的空间; |
||||
3、只对新的多线程下载任务有效 |
||||
4、只对多线程的任务有效 |
||||
--> |
||||
<useBlock value="true"/> |
||||
|
||||
<!--设置下载线程数,下载线程数不能小于1 |
||||
注意: |
||||
1、线程下载数改变后,新的下载任务才会生效; |
||||
2、如果任务大小小于1m,该设置不会生效; |
||||
3、从3.4.1开始,如果线程数为1,文件初始化时将不再预占用对应长度的空间,下载多少byte,则占多大的空间; |
||||
对于3.4.1之前版本的未完成的老任务,依然采用原来的文件空间占用方式; |
||||
--> |
||||
<threadNum value="3"/> |
||||
|
||||
<!--设置下载队列最大任务数, 默认为2--> |
||||
<maxTaskNum value="1"/> |
||||
|
||||
<!--设置下载失败,重试次数,默认为10--> |
||||
<reTryNum value="1"/> |
||||
|
||||
<!--设置重试间隔,单位为毫秒,默认2000毫秒--> |
||||
<reTryInterval value="5000"/> |
||||
|
||||
<!--设置url连接超时时间,单位为毫秒,默认5000毫秒--> |
||||
<connectTimeOut value="5000"/> |
||||
|
||||
<!--设置IO流读取时间,单位为毫秒,默认20000毫秒,该时间不能少于10000毫秒--> |
||||
<iOTimeOut value="10000"/> |
||||
|
||||
<!--设置写文件buff大小,该数值大小不能小于2048,数值变小,下载速度会变慢--> |
||||
<buffSize value="8192"/> |
||||
|
||||
<!--设置https ca 证书信息;path 为assets目录下的CA证书完整路径,name 为CA证书名--> |
||||
<ca name="" path=""/> |
||||
|
||||
<!--是否需要转换速度单位,转换完成后为:1b/s、1kb/s、1mb/s、1gb/s、1tb/s,如果不需要将返回byte长度--> |
||||
<convertSpeed value="true"/> |
||||
|
||||
<!--执行队列类型,见com.arialyy.aria.core.QueueMod,默认类型为wait--> |
||||
<queueMod value="wait"/> |
||||
|
||||
<!--进度更新更新间隔,默认1000毫秒--> |
||||
<updateInterval value="1000"/> |
||||
|
||||
</download> |
||||
|
||||
<!--普通上传任务--> |
||||
<upload> |
||||
<!--设置任务最大上传速度,0表示不限速,单位为:kb--> |
||||
<maxSpeed value="0"/> |
||||
|
||||
<!--设置IO流读取时间,单位为毫秒,默认20000毫秒,该时间不能少于10000毫秒--> |
||||
<iOTimeOut value="10000"/> |
||||
|
||||
<!--设置写文件buff大小,该数值大小不能小于2048,数值变小,速度会变慢--> |
||||
<buffSize value="8192"/> |
||||
|
||||
<!--是否需要转换速度单位,转换完成后为:1b/s、1kb/s、1mb/s、1gb/s、1tb/s,如果不需要将返回byte长度--> |
||||
<convertSpeed value="true"/> |
||||
|
||||
<!--设置上传队列最大任务数, 默认为2--> |
||||
<maxTaskNum value="2"/> |
||||
|
||||
<!--设置上传失败,重试次数,默认为10--> |
||||
<reTryNum value="3"/> |
||||
|
||||
<!--设置重试间隔,单位为毫秒--> |
||||
<reTryInterval value="2000"/> |
||||
|
||||
<!--设置url连接超时时间,单位为毫秒,默认5000毫秒--> |
||||
<connectTimeOut value="5000"/> |
||||
|
||||
<!--执行队列类型,见com.arialyy.aria.core.QueueMod,默认类型为wait--> |
||||
<queueMod value="wait"/> |
||||
|
||||
<!--进度更新更新间隔,默认1000毫秒--> |
||||
<updateInterval value="1000"/> |
||||
|
||||
</upload> |
||||
|
||||
<!-- 下载类组合任务 --> |
||||
<dGroup> |
||||
|
||||
<!--组合任务下载队列最大任务数, 默认为2--> |
||||
<maxTaskNum value="1"/> |
||||
|
||||
<!--设置下载失败,重试次数,默认为10--> |
||||
<reTryNum value="1"/> |
||||
|
||||
<!--设置重试间隔,单位为毫秒,默认2000毫秒--> |
||||
<reTryInterval value="5000"/> |
||||
|
||||
<!--执行队列类型,见com.arialyy.aria.core.QueueMod,默认类型为wait--> |
||||
<queueMod value="wait"/> |
||||
|
||||
<!--进度更新更新间隔,默认1000毫秒--> |
||||
<updateInterval value="1000"/> |
||||
|
||||
|
||||
<!-- =============================以下为子任务的配置====================================--> |
||||
|
||||
<!--能同时下载的子任务最大任务数,默认3--> |
||||
<subMaxTaskNum value="1"/> |
||||
|
||||
<!--子任务下载失败时的重试次数,默认为5--> |
||||
<subReTryNum value="5"/> |
||||
|
||||
<!--子任务下载失败时的重试间隔,单位为毫秒,默认2000毫秒--> |
||||
<subReTryInterval value="5000"/> |
||||
|
||||
<!--子任务url连接超时时间,单位为毫秒,默认5000毫秒--> |
||||
<connectTimeOut value="5000"/> |
||||
|
||||
<!--子任务IO流读取时间,单位为毫秒,默认20000毫秒,该时间不能少于10000毫秒--> |
||||
<iOTimeOut value="10000"/> |
||||
|
||||
<!--子任务写文件buff大小,该数值大小不能小于2048,数值变小,下载速度会变慢--> |
||||
<buffSize value="8192"/> |
||||
|
||||
<!--子任务 https ca 证书信息;path 为assets目录下的CA证书完整路径,name 为CA证书名--> |
||||
<ca name="" path=""/> |
||||
|
||||
<!--子任务是否需要转换速度单位,转换完成后为:1b/s、1kb/s、1mb/s、1gb/s、1tb/s,如果不需要将返回byte长度--> |
||||
<convertSpeed value="true"/> |
||||
|
||||
<!--子任务的最大下载速度,0表示不限速,单位为:kb; --> |
||||
<maxSpeed value="0"/> |
||||
|
||||
</dGroup> |
||||
</aria> |
@ -1,58 +1,58 @@ |
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules. |
||||
buildscript { |
||||
ext.kotlin_version = '1.3.11' |
||||
repositories { |
||||
jcenter() |
||||
mavenCentral() |
||||
google() |
||||
maven { url 'https://jitpack.io' } |
||||
} |
||||
dependencies { |
||||
// classpath 'com.android.tools.build:gradle:2.3.3' |
||||
classpath 'com.android.tools.build:gradle:3.3.2' |
||||
classpath 'com.novoda:bintray-release:0.9' |
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlin_version}" |
||||
// classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7' |
||||
// classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' |
||||
// NOTE: Do not place your application dependencies here; they belong |
||||
// in the individual module build.gradle files |
||||
} |
||||
} |
||||
|
||||
allprojects { |
||||
repositories { |
||||
jcenter() |
||||
mavenCentral() |
||||
google() |
||||
maven { url 'https://jitpack.io' } |
||||
} |
||||
|
||||
tasks.withType(Javadoc) { |
||||
options { |
||||
encoding "UTF-8" |
||||
charSet 'UTF-8' |
||||
links "http://docs.oracle.com/javase/7/docs/api" |
||||
} |
||||
} |
||||
} |
||||
|
||||
task clean(type: Delete) { |
||||
delete rootProject.buildDir |
||||
} |
||||
|
||||
ext { |
||||
userOrg = 'arialyy' |
||||
groupId = 'com.arialyy.aria' |
||||
publishVersion = '3.6.3' |
||||
// publishVersion = '1.0.4' //FTP插件 |
||||
repoName='maven' |
||||
desc = 'android 下载框架' |
||||
website = 'https://github.com/AriaLyy/Aria' |
||||
licences = ['Apache-2.0'] |
||||
|
||||
compileSdkVersion = 28 |
||||
supportLibVersion = "28.0.0" |
||||
buildToolsVersion = "28.0.3" |
||||
targetSdkVersion = 28 |
||||
minSdkVersion = 15 |
||||
} |
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules. |
||||
buildscript { |
||||
ext.kotlin_version = '1.3.11' |
||||
repositories { |
||||
jcenter() |
||||
mavenCentral() |
||||
google() |
||||
maven { url 'https://jitpack.io' } |
||||
} |
||||
dependencies { |
||||
// classpath 'com.android.tools.build:gradle:2.3.3' |
||||
classpath 'com.android.tools.build:gradle:3.3.2' |
||||
classpath 'com.novoda:bintray-release:0.9' |
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlin_version}" |
||||
// classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7' |
||||
// classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' |
||||
// NOTE: Do not place your application dependencies here; they belong |
||||
// in the individual module build.gradle files |
||||
} |
||||
} |
||||
|
||||
allprojects { |
||||
repositories { |
||||
jcenter() |
||||
mavenCentral() |
||||
google() |
||||
maven { url 'https://jitpack.io' } |
||||
} |
||||
|
||||
tasks.withType(Javadoc) { |
||||
options { |
||||
encoding "UTF-8" |
||||
charSet 'UTF-8' |
||||
links "http://docs.oracle.com/javase/7/docs/api" |
||||
} |
||||
} |
||||
} |
||||
|
||||
task clean(type: Delete) { |
||||
delete rootProject.buildDir |
||||
} |
||||
|
||||
ext { |
||||
userOrg = 'arialyy' |
||||
groupId = 'com.arialyy.aria' |
||||
publishVersion = '3.6.4_dev_1' |
||||
// publishVersion = '1.0.4' //FTP插件 |
||||
repoName='maven' |
||||
desc = 'android 下载框架' |
||||
website = 'https://github.com/AriaLyy/Aria' |
||||
licences = ['Apache-2.0'] |
||||
|
||||
compileSdkVersion = 28 |
||||
supportLibVersion = "28.0.0" |
||||
buildToolsVersion = "28.0.3" |
||||
targetSdkVersion = 28 |
||||
minSdkVersion = 15 |
||||
} |
||||
|
Loading…
Reference in new issue