9 Commits

27 changed files with 330 additions and 87 deletions

3
.github/stale.yml vendored
View File

@@ -8,6 +8,7 @@ exemptLabels:
- adaptation - adaptation
- new features - new features
- suggest - suggest
- pending
# Label to use when marking an issue as stale # Label to use when marking an issue as stale
staleLabel: wontfix staleLabel: wontfix
# Comment to post when marking an issue as stale. Set to `false` to disable # Comment to post when marking an issue as stale. Set to `false` to disable
@@ -16,4 +17,4 @@ markComment: >
recent activity. It will be closed if no further activity occurs. Thank you recent activity. It will be closed if no further activity occurs. Thank you
for your contributions. for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable # Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false closeComment: false

View File

@@ -35,7 +35,7 @@ public class SFtpOption extends BaseOption {
public SFtpOption() { public SFtpOption() {
super(); super();
ComponentUtil.getInstance().checkComponentExist(ComponentUtil.COMPONENT_TYPE_M3U8); ComponentUtil.getInstance().checkComponentExist(ComponentUtil.COMPONENT_TYPE_SFTP);
} }
public SFtpOption charSet(String charSet) { public SFtpOption charSet(String charSet) {

View File

@@ -110,7 +110,12 @@ public class CheckDEntityUtil implements ICheckEntityUtil {
if (TextUtils.isEmpty(filePath)) { if (TextUtils.isEmpty(filePath)) {
ALog.e(TAG, "下载失败文件保存路径为null"); ALog.e(TAG, "下载失败文件保存路径为null");
return false; return false;
} else if (!filePath.startsWith("/")) { }
if (!FileUtil.canWrite(new File(filePath).getParent())){
ALog.e(TAG, String.format("路径【%s】不可写", filePath));
return false;
}
if (!filePath.startsWith("/")) {
ALog.e(TAG, String.format("下载失败,文件保存路径【%s】错误", filePath)); ALog.e(TAG, String.format("下载失败,文件保存路径【%s】错误", filePath));
return false; return false;
} }

View File

@@ -23,6 +23,7 @@ import com.arialyy.aria.core.inf.IOptionConstant;
import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CheckUtil; import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.FileUtil;
import com.arialyy.aria.util.RecordUtil; import com.arialyy.aria.util.RecordUtil;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
@@ -62,33 +63,40 @@ public class CheckDGEntityUtil implements ICheckEntityUtil {
* @return {@code true} 合法 * @return {@code true} 合法
*/ */
private boolean checkDirPath() { private boolean checkDirPath() {
if (TextUtils.isEmpty(mWrapper.getDirPathTemp())) { String dirPath = mWrapper.getDirPathTemp();
if (TextUtils.isEmpty(dirPath)) {
ALog.e(TAG, "文件夹路径不能为null"); ALog.e(TAG, "文件夹路径不能为null");
return false; return false;
} else if (!mWrapper.getDirPathTemp().startsWith("/")) { }
ALog.e(TAG, String.format("文件夹路径【%s】错误", mWrapper.getDirPathTemp())); if (!FileUtil.canWrite(dirPath)){
ALog.e(TAG, String.format("路径【%s】不可写", dirPath));
return false; return false;
} }
File file = new File(mWrapper.getDirPathTemp()); if (!dirPath.startsWith("/")) {
ALog.e(TAG, String.format("文件夹路径【%s】错误", dirPath));
return false;
}
File file = new File(dirPath);
if (file.isFile()) { if (file.isFile()) {
ALog.e(TAG, String.format("路径【%s】是文件请设置文件夹路径", mWrapper.getDirPathTemp())); ALog.e(TAG, String.format("路径【%s】是文件请设置文件夹路径", dirPath));
return false; return false;
} }
// 检查路径冲突 // 检查路径冲突
if (mWrapper.isNewTask() && !CheckUtil.checkDGPathConflicts(mWrapper.isIgnoreFilePathOccupy(), if (mWrapper.isNewTask() && !CheckUtil.checkDGPathConflicts(mWrapper.isIgnoreFilePathOccupy(),
mWrapper.getDirPathTemp())) { dirPath)) {
return false; return false;
} }
if (TextUtils.isEmpty(mEntity.getDirPath()) || !mEntity.getDirPath() if (TextUtils.isEmpty(mEntity.getDirPath()) || !mEntity.getDirPath()
.equals(mWrapper.getDirPathTemp())) { .equals(dirPath)) {
if (!file.exists()) { if (!file.exists()) {
file.mkdirs(); file.mkdirs();
} }
needModifyPath = true; needModifyPath = true;
mEntity.setDirPath(mWrapper.getDirPathTemp()); mEntity.setDirPath(dirPath);
ALog.i(TAG, String.format("文件夹路径改变,将更新文件夹路径为:%s", mWrapper.getDirPathTemp())); ALog.i(TAG, String.format("文件夹路径改变,将更新文件夹路径为:%s", dirPath));
} }
return true; return true;
} }

View File

@@ -45,32 +45,34 @@ public class CheckFtpDirEntityUtil implements ICheckEntityUtil {
* @return {@code true} 合法 * @return {@code true} 合法
*/ */
private boolean checkDirPath() { private boolean checkDirPath() {
if (TextUtils.isEmpty(mWrapper.getDirPathTemp())) { String dirPath = mWrapper.getDirPathTemp();
if (TextUtils.isEmpty(dirPath)) {
ALog.e(TAG, "文件夹路径不能为null"); ALog.e(TAG, "文件夹路径不能为null");
return false; return false;
} else if (!mWrapper.getDirPathTemp().startsWith("/")) { }
ALog.e(TAG, String.format("文件夹路径【%s】错误", mWrapper.getDirPathTemp())); if (!dirPath.startsWith("/")) {
ALog.e(TAG, String.format("文件夹路径【%s】错误", dirPath));
return false; return false;
} }
File file = new File(mWrapper.getDirPathTemp()); File file = new File(dirPath);
if (file.isFile()) { if (file.isFile()) {
ALog.e(TAG, String.format("路径【%s】是文件请设置文件夹路径", mWrapper.getDirPathTemp())); ALog.e(TAG, String.format("路径【%s】是文件请设置文件夹路径", dirPath));
return false; return false;
} }
// 检查路径冲突 // 检查路径冲突
if (mWrapper.isNewTask() && !CheckUtil.checkDGPathConflicts(mWrapper.isIgnoreFilePathOccupy(), if (mWrapper.isNewTask() && !CheckUtil.checkDGPathConflicts(mWrapper.isIgnoreFilePathOccupy(),
mWrapper.getDirPathTemp())) { dirPath)) {
return false; return false;
} }
if (TextUtils.isEmpty(mEntity.getDirPath()) || !mEntity.getDirPath() if (TextUtils.isEmpty(mEntity.getDirPath()) || !mEntity.getDirPath()
.equals(mWrapper.getDirPathTemp())) { .equals(dirPath)) {
if (!file.exists()) { if (!file.exists()) {
file.mkdirs(); file.mkdirs();
} }
mEntity.setDirPath(mWrapper.getDirPathTemp()); mEntity.setDirPath(dirPath);
ALog.i(TAG, String.format("文件夹路径改变,将更新文件夹路径为:%s", mWrapper.getDirPathTemp())); ALog.i(TAG, String.format("文件夹路径改变,将更新文件夹路径为:%s", dirPath));
} }
return true; return true;
} }

View File

@@ -1,4 +1,12 @@
## 开发日志 ## 开发日志
+ v_3.8.15 (2020/11/9)
- 修复不支持断点的连接下载失败问题https://github.com/AriaLyy/Aria/issues/771
- 修复iv不存在时索引文件异常的问题https://github.com/AriaLyy/Aria/issues/780
- fix bug https://github.com/AriaLyy/Aria/issues/799
- fix bug https://github.com/AriaLyy/Aria/issues/798
+ v_3.8.14 (2020/9/23)
- 修复spi机制的兼容问题https://github.com/AriaLyy/Aria/issues/743
- 增加路径不可以写的判断,下载时,如果路径不可写,将执行失败回调 https://github.com/AriaLyy/Aria/issues/750
+ v_3.8.12 (2020/8/15) + v_3.8.12 (2020/8/15)
- 修复一个正则表达式导致的文件名保存号异常问题 https://github.com/AriaLyy/Aria/issues/715 - 修复一个正则表达式导致的文件名保存号异常问题 https://github.com/AriaLyy/Aria/issues/715
- 修复一个匿名内部类中的内存溢出的问题 https://github.com/AriaLyy/Aria/issues/705 - 修复一个匿名内部类中的内存溢出的问题 https://github.com/AriaLyy/Aria/issues/705

View File

@@ -19,6 +19,7 @@ import android.os.Handler;
import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.group.AbsSubDLoadUtil; import com.arialyy.aria.core.group.AbsSubDLoadUtil;
import com.arialyy.aria.core.group.SubRecordHandler; import com.arialyy.aria.core.group.SubRecordHandler;
import com.arialyy.aria.core.loader.GroupSubThreadStateManager;
import com.arialyy.aria.core.loader.LoaderStructure; import com.arialyy.aria.core.loader.LoaderStructure;
import com.arialyy.aria.core.loader.NormalTTBuilder; import com.arialyy.aria.core.loader.NormalTTBuilder;
import com.arialyy.aria.core.loader.SubLoader; import com.arialyy.aria.core.loader.SubLoader;
@@ -48,6 +49,7 @@ final class FtpSubDLoaderUtil extends AbsSubDLoadUtil {
@Override protected LoaderStructure buildLoaderStructure() { @Override protected LoaderStructure buildLoaderStructure() {
LoaderStructure structure = new LoaderStructure(); LoaderStructure structure = new LoaderStructure();
structure.addComponent(new SubRecordHandler(getWrapper())) structure.addComponent(new SubRecordHandler(getWrapper()))
.addComponent(new GroupSubThreadStateManager(getSchedulers(),getKey()))
.addComponent(new NormalTTBuilder(getWrapper(), new FtpDTTBuilderAdapter())) .addComponent(new NormalTTBuilder(getWrapper(), new FtpDTTBuilderAdapter()))
.addComponent(new FtpDFileInfoTask(getWrapper())); .addComponent(new FtpDFileInfoTask(getWrapper()));
structure.accept(getLoader()); structure.accept(getLoader());

View File

@@ -0,0 +1,2 @@
Manifest-Version: 1.0

View File

@@ -0,0 +1,2 @@
Manifest-Version: 1.0

View File

@@ -95,9 +95,21 @@ public abstract class BaseM3U8Loader extends AbsNormalLoader<DTaskWrapper> {
i++; i++;
} else if (line.startsWith("#EXT-X-KEY")) { } else if (line.startsWith("#EXT-X-KEY")) {
M3U8Entity m3U8Entity = getEntity().getM3U8Entity(); M3U8Entity m3U8Entity = getEntity().getM3U8Entity();
String keyInfo = String.format("#EXT-X-KEY:METHOD=%s,URI=\"%s\",IV=%s\r\n", m3U8Entity.method, StringBuilder sb = new StringBuilder("#EXT-X-KEY:");
m3U8Entity.keyPath, m3U8Entity.iv); sb.append("METHOD=").append(m3U8Entity.method);
bytes = keyInfo.getBytes(Charset.forName("UTF-8")); sb.append(",URI=\"").append(m3U8Entity.keyPath).append("\"");
if (!TextUtils.isEmpty(m3U8Entity.iv)) {
sb.append(",IV=").append(m3U8Entity.iv);
}
if (!TextUtils.isEmpty(m3U8Entity.keyFormat)) {
sb.append(",KEYFORMAT=\"").append(m3U8Entity.keyFormat).append("\"");
sb.append(",KEYFORMATVERSIONS=\"")
.append(TextUtils.isEmpty(m3U8Entity.keyFormatVersion) ? "1"
: m3U8Entity.keyFormatVersion)
.append("\"");
}
sb.append("\r\n");
bytes = sb.toString().getBytes(Charset.forName("UTF-8"));
} else { } else {
bytes = line.concat("\r\n").getBytes(Charset.forName("UTF-8")); bytes = line.concat("\r\n").getBytes(Charset.forName("UTF-8"));
} }

View File

@@ -0,0 +1,2 @@
Manifest-Version: 1.0

View File

@@ -70,12 +70,9 @@ public final class NormalTTBuilder implements IThreadTaskBuilder {
private List<IThreadTask> handleNoSupportBP() { private List<IThreadTask> handleNoSupportBP() {
List<IThreadTask> list = new ArrayList<>(); List<IThreadTask> list = new ArrayList<>();
mStartThreadNum = 1; mStartThreadNum = 1;
mRecord.isBlock = false;
mRecord.update();
IThreadTask task = createSingThreadTask(mRecord.threadRecords.get(0), 1); IThreadTask task = createSingThreadTask(mRecord.threadRecords.get(0), 1);
if (task == null) {
ALog.e(TAG, "创建线程任务失败");
return null;
}
list.add(task); list.add(task);
return list; return list;
} }

View File

@@ -32,7 +32,7 @@ import java.util.ServiceLoader;
* 参考{@link ServiceLoader} * 参考{@link ServiceLoader}
*/ */
public class AriaServiceLoader<S> { public class AriaServiceLoader<S> {
private static final String TAG = "AriaServiceLoader";
private static final String PREFIX = "META-INF/services/"; private static final String PREFIX = "META-INF/services/";
// The class or interface representing the service being loaded // The class or interface representing the service being loaded
@@ -177,6 +177,10 @@ public class AriaServiceLoader<S> {
} }
private S loadService(String serviceName) { private S loadService(String serviceName) {
if (pending == null){
ALog.e(TAG, "pending为空");
return null;
}
for (String s : pending) { for (String s : pending) {
if (s.equals(serviceName)) { if (s.equals(serviceName)) {
Class<?> c = null; Class<?> c = null;

View File

@@ -24,9 +24,11 @@ import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.task.AbsTask; import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper; import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.wrapper.ITaskWrapper; import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.exception.AriaComponentException;
import java.lang.ref.SoftReference; import java.lang.ref.SoftReference;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List; import java.util.List;
/** /**
@@ -43,12 +45,9 @@ public class ComponentUtil {
private String TAG = CommonUtil.getClassName(getClass()); private String TAG = CommonUtil.getClassName(getClass());
private static volatile ComponentUtil INSTANCE = null; private static volatile ComponentUtil INSTANCE = null;
private AriaServiceLoader<IUtil> utilLoader;
private AriaServiceLoader<IEventListener> listenerLoader;
private ComponentUtil() { private ComponentUtil() {
utilLoader = AriaServiceLoader.load(IUtil.class);
listenerLoader = AriaServiceLoader.load(IEventListener.class);
} }
public static ComponentUtil getInstance() { public static ComponentUtil getInstance() {
@@ -105,7 +104,8 @@ public class ComponentUtil {
* *
* @return 返回任务工具 * @return 返回任务工具
*/ */
public synchronized IUtil buildUtil(AbsTaskWrapper wrapper, IEventListener listener) { public synchronized <T extends IUtil> T buildUtil(AbsTaskWrapper wrapper,
IEventListener listener) {
int requestType = wrapper.getRequestType(); int requestType = wrapper.getRequestType();
String className = null; String className = null;
switch (requestType) { switch (requestType) {
@@ -140,11 +140,30 @@ public class ComponentUtil {
className = "com.arialyy.aria.sftp.upload.SFtpULoaderUtil"; className = "com.arialyy.aria.sftp.upload.SFtpULoaderUtil";
break; break;
} }
IUtil util = utilLoader.getService(className); if (className == null) {
if (util == null) { ALog.e(TAG, "不识别的类名:" + className);
throw new AriaComponentException("加载工具异常,请求类型:" + wrapper.getRequestType()); return null;
} }
return util.setParams(wrapper, listener); T util = null;
try {
Class<T> clazz = (Class<T>) getClass().getClassLoader().loadClass(className);
Constructor<T> con = clazz.getConstructor();
util = con.newInstance();
Method method =
CommonUtil.getMethod(clazz, "setParams", AbsTaskWrapper.class, IEventListener.class);
method.invoke(util, wrapper, listener);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return util;
} }
/** /**
@@ -153,7 +172,7 @@ public class ComponentUtil {
* @param wrapperType 任务类型{@link ITaskWrapper} * @param wrapperType 任务类型{@link ITaskWrapper}
* @return 返回事件监听如果创建失败返回null * @return 返回事件监听如果创建失败返回null
*/ */
public synchronized IEventListener buildListener(int wrapperType, AbsTask task, public synchronized <T extends IEventListener> T buildListener(int wrapperType, AbsTask task,
Handler outHandler) { Handler outHandler) {
String className = null, errorStr = "请添加FTP插件"; String className = null, errorStr = "请添加FTP插件";
switch (wrapperType) { switch (wrapperType) {
@@ -180,12 +199,26 @@ public class ComponentUtil {
if (className == null) { if (className == null) {
return null; return null;
} }
T listener = null;
IEventListener listener = listenerLoader.getService(className); try {
if (listener == null) { Class<T> clazz = (Class<T>) getClass().getClassLoader().loadClass(className);
throw new AriaComponentException(errorStr); Constructor<T> con = clazz.getConstructor();
listener = con.newInstance();
Method method =
CommonUtil.getMethod(clazz, "setParams", AbsTask.class, Handler.class);
method.invoke(listener, task, outHandler);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException(errorStr);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} }
return listener.setParams(task, outHandler); return listener;
} }
/** /**

View File

@@ -691,7 +691,7 @@ public class FileUtil {
return list; return list;
} }
private static boolean canWrite(String dirPath) { public static boolean canWrite(String dirPath) {
File dir = new File(dirPath); File dir = new File(dirPath);
if (dir.canWrite()) { if (dir.canWrite()) {
return true; return true;

View File

@@ -0,0 +1,2 @@
Manifest-Version: 1.0

View File

@@ -45,19 +45,19 @@ Aria有以下特点
## 引入库 ## 引入库
[![license](http://img.shields.io/badge/license-Apache2.0-brightgreen.svg?style=flat)](https://github.com/AriaLyy/Aria/blob/master/LICENSE) [![license](http://img.shields.io/badge/license-Apache2.0-brightgreen.svg?style=flat)](https://github.com/AriaLyy/Aria/blob/master/LICENSE)
[![Core](https://img.shields.io/badge/Core-3.8.12-blue)](https://github.com/AriaLyy/Aria) [![Core](https://img.shields.io/badge/Core-3.8.15-blue)](https://github.com/AriaLyy/Aria)
[![Compiler](https://img.shields.io/badge/Compiler-3.8.12-blue)](https://github.com/AriaLyy/Aria) [![Compiler](https://img.shields.io/badge/Compiler-3.8.15-blue)](https://github.com/AriaLyy/Aria)
[![FtpComponent](https://img.shields.io/badge/FtpComponent-3.8.12-orange)](https://github.com/AriaLyy/Aria) [![FtpComponent](https://img.shields.io/badge/FtpComponent-3.8.15-orange)](https://github.com/AriaLyy/Aria)
[![FtpComponent](https://img.shields.io/badge/SFtpComponent-3.8.12-orange)](https://github.com/AriaLyy/Aria) [![FtpComponent](https://img.shields.io/badge/SFtpComponent-3.8.15-orange)](https://github.com/AriaLyy/Aria)
[![M3U8Component](https://img.shields.io/badge/M3U8Component-3.8.12-orange)](https://github.com/AriaLyy/Aria) [![M3U8Component](https://img.shields.io/badge/M3U8Component-3.8.15-orange)](https://github.com/AriaLyy/Aria)
```java ```java
implementation 'com.arialyy.aria:core:3.8.12' implementation 'com.arialyy.aria:core:3.8.15'
annotationProcessor 'com.arialyy.aria:compiler:3.8.12' annotationProcessor 'com.arialyy.aria:compiler:3.8.15'
implementation 'com.arialyy.aria:ftpComponent:3.8.12' # 如果需要使用ftp请增加该组件 implementation 'com.arialyy.aria:ftpComponent:3.8.15' # 如果需要使用ftp请增加该组件
implementation 'com.arialyy.aria:sftpComponent:3.8.12' # 如果需要使用ftp请增加该组件 implementation 'com.arialyy.aria:sftpComponent:3.8.15' # 如果需要使用ftp请增加该组件
implementation 'com.arialyy.aria:m3u8Component:3.8.12' # 如果需要使用m3u8下载功能请增加该组件 implementation 'com.arialyy.aria:m3u8Component:3.8.15' # 如果需要使用m3u8下载功能请增加该组件
``` ```
如果你使用的是kotlin请使用kotlin官方提供的方法配置apt[kotlin kapt官方配置传送门](https://www.kotlincn.net/docs/reference/kapt.html) 如果你使用的是kotlin请使用kotlin官方提供的方法配置apt[kotlin kapt官方配置传送门](https://www.kotlincn.net/docs/reference/kapt.html)
@@ -138,22 +138,12 @@ protected void onCreate(Bundle savedInstanceState) {
### 版本日志 ### 版本日志
+ v_3.8.12 (2020/8/15) + v_3.8.15 (2020/11/9)
- 修复一个正则表达式导致的文件名保存号异常问题 https://github.com/AriaLyy/Aria/issues/715 - 修复不支持断点的连接下载失败问题https://github.com/AriaLyy/Aria/issues/771
- 修复一个匿名内部类中的内存溢出的问题 https://github.com/AriaLyy/Aria/issues/705 - 修复iv不存在时索引文件异常的问题https://github.com/AriaLyy/Aria/issues/780
- 修复同一个url地址的任务提示路径冲突的问题 - fix bug https://github.com/AriaLyy/Aria/issues/799
- 修复m3u8任务地址错误时无法删除实体的问题 https://github.com/AriaLyy/Aria/issues/712 - fix bug https://github.com/AriaLyy/Aria/issues/798
- 修复m3u8gzip的问题https://github.com/AriaLyy/Aria/issues/639
- 修复http表单上传本地md5和上传的服务的的文件md5不一致的问题 https://github.com/AriaLyy/Aria/issues/730
- 修复0kb的文件不可下载的问题 https://github.com/AriaLyy/Aria/issues/711
- 修复加密的m3u8下载并且使用索引模式时key的uri没有使用双引号的问题 https://github.com/AriaLyy/Aria/issues/731
- 修复删除m3u8索引文件后下载完成回调无法触发的问题
- 修复删除加密的m3u8文件时key没有被删除的问题 https://github.com/AriaLyy/Aria/issues/735#issuecomment-673958845
- 增加m3u8密钥下载地址转换器增加ts列表的url地址 https://github.com/AriaLyy/Aria/issues/718
- 增加现在http文件下载将使用HEAD请求获取文件大小配置文件增加 <useHeadRequest value="true"/>。慎用并不是所有服务器都支持head请求
- 增加允许不使用apt直接通过实现监听器来回调下载进度更新该功能由[chenfei0928](https://github.com/chenfei0928)提交感谢他的pr。如果注解不生效只需要实现`DownloadListener`接口便可
- 增加m3u8使用`ignoreFailureTs`后将不会自动重试失败的切片 https://github.com/AriaLyy/Aria/issues/662
[更多版本记录](https://github.com/AriaLyy/Aria/blob/master/DEV_LOG.md) [更多版本记录](https://github.com/AriaLyy/Aria/blob/master/DEV_LOG.md)
## 混淆配置 ## 混淆配置
@@ -181,6 +171,7 @@ protected void onCreate(Bundle savedInstanceState) {
## 其他 ## 其他
有任何问题,可以在[issues](https://github.com/AriaLyy/Aria/issues)给我留言反馈。</br> 有任何问题,可以在[issues](https://github.com/AriaLyy/Aria/issues)给我留言反馈。</br>
在提交问题前,希望你已经查看过[wiki](https://aria.laoyuyu.me/aria_doc/)或搜索过[issues](https://github.com/AriaLyy/Aria/issues)。</br> 在提交问题前,希望你已经查看过[wiki](https://aria.laoyuyu.me/aria_doc/)或搜索过[issues](https://github.com/AriaLyy/Aria/issues)。</br>
[我的博客](https://www.laoyuyu.me)
## 捐赠 ## 捐赠
Aria是作业利用业余时间开发的一个项目如果你喜欢我写的软件可以考虑给我捐赠以支持我的工作</br> Aria是作业利用业余时间开发的一个项目如果你喜欢我写的软件可以考虑给我捐赠以支持我的工作</br>

View File

@@ -0,0 +1,2 @@
Manifest-Version: 1.0

View File

@@ -31,8 +31,9 @@ android {
buildTypes { buildTypes {
release { release {
minifyEnabled false zipAlignEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release signingConfig signingConfigs.release
} }
} }
@@ -43,6 +44,7 @@ android {
packagingOptions { packagingOptions {
exclude 'META-INF/services/javax.annotation.processing.Processor' exclude 'META-INF/services/javax.annotation.processing.Processor'
merge 'META-INF/services/com.arialyy.aria.core.inf.IUtil'
} }
lintOptions { lintOptions {
@@ -61,6 +63,7 @@ dependencies {
androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0'
implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.cardview:cardview:1.0.0'
implementation 'com.google.android.material:material:1.0.0' implementation 'com.google.android.material:material:1.0.0'
@@ -70,16 +73,23 @@ dependencies {
implementation 'com.github.bumptech.glide:glide:3.7.0' implementation 'com.github.bumptech.glide:glide:3.7.0'
implementation 'com.pddstudio:highlightjs-android:1.5.0' implementation 'com.pddstudio:highlightjs-android:1.5.0'
implementation 'org.greenrobot:eventbus:3.1.1' implementation 'org.greenrobot:eventbus:3.1.1'
implementation project(':AppFrame')
// aria // aria
kapt project(':AriaCompiler') kapt project(':AriaCompiler')
implementation project(':Aria') implementation project(':Aria')
implementation project(':AppFrame')
implementation project(':M3U8Component') implementation project(':M3U8Component')
implementation project(':FtpComponent') implementation project(':FtpComponent')
implementation project(path: ':AriaAnnotations') implementation project(path: ':AriaAnnotations')
implementation project(path: ':SFtpComponent') implementation project(path: ':SFtpComponent')
// implementation 'com.arialyy.aria:core:3.8.12'
// kapt 'com.arialyy.aria:compiler:3.8.12'
// implementation 'com.arialyy.aria:ftpComponent:3.8.12' // 如果需要使用ftp请增加该组件
// implementation 'com.arialyy.aria:sftpComponent:3.8.12' // 如果需要使用ftp请增加该组件
// implementation 'com.arialyy.aria:m3u8Component:3.8.12' // 如果需要使用m3u8下载功能请增加该组件
debugImplementation 'com.amitshekhar.android:debug-db:1.0.6' debugImplementation 'com.amitshekhar.android:debug-db:1.0.6'
} }
repositories { repositories {

135
app/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,135 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
################################### 混淆配置 start ###########################################
#指定代码的压缩级别
-optimizationpasses 1
#包明不混合大小写
-dontusemixedcaseclassnames
#不去忽略非公共的库类
-dontskipnonpubliclibraryclasses
#优化 不优化输入的类文件
-dontoptimize
#预校验
-dontpreverify
#混淆时是否记录日志
-verbose
# 混淆时所采用的算法
#-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
-optimizations !code/simplification/cast,!field/*,!class/merging/*
#-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#忽略警告
#-ignorewarning
################################### 混淆配置 end ############################################
################## 记录生成的日志数据,gradle build时在本项目根目录输出 #################
####### 输出文件夹 build/outputs/mapping
#apk 包内所有 class 的内部结构
-dump build/outputs/mapping/class_files.txt
#未混淆的类和成员
-printseeds build/outputs/mapping/kpa_seeds.txt
#列出从 apk 中删除的代码
-printusage build/outputs/mapping/kpa_unused.txt
#混淆前后的映射
-printmapping build/outputs/mapping/kpa_mapping.txt
################## 记录生成的日志数据gradle build时 在本项目根目录输出-end #################
################## 常用属性配置-start ##################
# 保护注解
-keepattributes *Annotation*
# 保护support v4 包
-dontwarn android.support.v4.app.**
-keep class android.support.v4.app.**{ *; }
# 保护andorid x
-keep class com.google.android.material.** {*;}
-keep class androidx.** {*;}
-keep public class * extends androidx.**
-keep interface androidx.** {*;}
-dontwarn com.google.android.material.**
-dontnote com.google.android.material.**
-dontwarn androidx.**
# 保护一些奇葩的问题
-dontwarn org.xmlpull.v1.XmlPullParser
-dontwarn org.xmlpull.v1.XmlSerializer
-keep class org.xmlpull.v1.* {*;}
# 保护JS接口
-keepclassmembers class * {
@android.webkit.JavascriptInterface <methods>;
}
##保持 native 方法不被混淆
-keepclasseswithmembernames class * {
native <methods>;
}
##保持 Parcelable 不被混淆
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
##保持 Serializable 不被混淆
-keepnames class * implements java.io.Serializable
#
#保持 Serializable 不被混淆并且enum 类也不被混淆
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
#避免混淆泛型 如果混淆报错建议关掉
#keepattributes Signature
# webview + js
-keepattributes *JavascriptInterface*
################## 常用属性配置-end ##################
################## kotlin-start ##################
-keep class kotlin.** { *; }
-keep class kotlin.Metadata { *; }
-dontwarn kotlin.**
-keepclassmembers class **$WhenMappings {
<fields>;
}
-keepclassmembers class kotlin.Metadata {
public <methods>;
}
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
static void checkParameterIsNotNull(java.lang.Object, java.lang.String);
}
################## kotlin-end ##################
-dontwarn com.arialyy.aria.**
-keep class com.arialyy.aria.**{*;}
-keep class **$$DownloadListenerProxy{ *; }
-keep class **$$UploadListenerProxy{ *; }
-keep class **$$DownloadGroupListenerProxy{ *; }
-keep class **$$DGSubListenerProxy{ *; }
-keepclasseswithmembernames class * {
@Download.* <methods>;
@Upload.* <methods>;
@DownloadGroup.* <methods>;
}
-keep class com.arialyy.aria.ftp.download.FtpDLoaderUtil{*;}
-adaptresourcefilenames **.IUtil
-adaptresourcefilecontents **.IUtil

View File

@@ -33,7 +33,7 @@ public class FtpDownloadModule extends BaseViewModule {
private final String FTP_URL_KEY = "FTP_URL_KEY"; private final String FTP_URL_KEY = "FTP_URL_KEY";
private final String FTP_PATH_KEY = "FTP_PATH_KEY"; private final String FTP_PATH_KEY = "FTP_PATH_KEY";
private final String ftpDefUrl = "ftp://9.9.9.50:2121/Cyberduck-6.9.4.30164.zip"; private final String ftpDefUrl = "ftp://192.168.0.104:2121/qqqq.exe";
private final String ftpDefPath = private final String ftpDefPath =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath(); Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
@@ -46,12 +46,12 @@ public class FtpDownloadModule extends BaseViewModule {
LiveData<DownloadEntity> getFtpDownloadInfo(Context context) { LiveData<DownloadEntity> getFtpDownloadInfo(Context context) {
//String url = AppUtil.getConfigValue(context, FTP_URL_KEY, ftpDefUrl); //String url = AppUtil.getConfigValue(context, FTP_URL_KEY, ftpDefUrl);
//String filePath = AppUtil.getConfigValue(context, FTP_PATH_KEY, ftpDefPath); //String filePath = AppUtil.getConfigValue(context, FTP_PATH_KEY, ftpDefPath);
String url = "ftp://9.9.9.72:2121/Cyberduck-6.9.4.30164.zip"; //String url = "ftp://9.9.9.72:2121/Cyberduck-6.9.4.30164.zip";
singDownloadInfo = Aria.download(context).getFirstDownloadEntity(url); singDownloadInfo = Aria.download(context).getFirstDownloadEntity(ftpDefUrl);
if (singDownloadInfo == null) { if (singDownloadInfo == null) {
singDownloadInfo = new DownloadEntity(); singDownloadInfo = new DownloadEntity();
singDownloadInfo.setUrl(url); singDownloadInfo.setUrl(ftpDefUrl);
String name = getFileName(ftpDefUrl); String name = getFileName(ftpDefUrl);
singDownloadInfo.setFileName(name); singDownloadInfo.setFileName(name);
singDownloadInfo.setFilePath(ftpDefPath + name); singDownloadInfo.setFilePath(ftpDefPath + name);

View File

@@ -51,9 +51,10 @@ public class HttpDownloadModule extends BaseViewModule {
//String url = AppUtil.getConfigValue(context, HTTP_URL_KEY, defUrl); //String url = AppUtil.getConfigValue(context, HTTP_URL_KEY, defUrl);
//String url = "http://fdfs.speedata.cn:9989/group1/M00/00/05/rBGFrl3fdAKAVJwfMtSa9R18wLU139.zip"; //String url = "http://fdfs.speedata.cn:9989/group1/M00/00/05/rBGFrl3fdAKAVJwfMtSa9R18wLU139.zip";
//String url = "http://9.9.9.28:8088/files/update.zip"; //String url = "http://9.9.9.28:8088/files/update.zip";
String url = "https://y.qq.com/download/import/QQMusic-import-1.2.1.zip"; //String url = "https://y.qq.com/download/import/QQMusic-import-1.2.1.zip";
String url = "https://gitee.com/huang-junhua/iptv/raw/master/guonei.m3u8";
//String url = "https://static.runoob.com/images/demo/demo2.jpg"; //String url = "https://static.runoob.com/images/demo/demo2.jpg";
String filePath = "/mnt/sdcard/update.zip"; String filePath = "/mnt/sdcard/xxx.m3u8";
singDownloadInfo = Aria.download(context).getFirstDownloadEntity(url); singDownloadInfo = Aria.download(context).getFirstDownloadEntity(url);
if (singDownloadInfo == null) { if (singDownloadInfo == null) {

View File

@@ -35,12 +35,14 @@ import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.common.HttpOption; import com.arialyy.aria.core.common.HttpOption;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadTaskListener; import com.arialyy.aria.core.download.DownloadTaskListener;
import com.arialyy.aria.core.download.target.HttpNormalTarget;
import com.arialyy.aria.core.listener.ISchedulers; import com.arialyy.aria.core.listener.ISchedulers;
import com.arialyy.aria.core.processor.IHttpFileLenAdapter; import com.arialyy.aria.core.processor.IHttpFileLenAdapter;
import com.arialyy.aria.core.scheduler.NormalTaskListenerInterface; import com.arialyy.aria.core.scheduler.NormalTaskListenerInterface;
import com.arialyy.aria.core.task.DownloadTask; import com.arialyy.aria.core.task.DownloadTask;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.FileUtil;
import com.arialyy.frame.util.show.T; import com.arialyy.frame.util.show.T;
import com.arialyy.simple.R; import com.arialyy.simple.R;
import com.arialyy.simple.base.BaseActivity; import com.arialyy.simple.base.BaseActivity;
@@ -120,6 +122,25 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
@Override public void cancel(View v, AbsEntity entity) { @Override public void cancel(View v, AbsEntity entity) {
Aria.download(this).load(mTaskId).cancel(false); Aria.download(this).load(mTaskId).cancel(false);
// //1. 删除本地文件目录
// File localDirFile = new File(mFilePath);
// if (localDirFile.exists()) {
// FileUtil.deleteDir(localDirFile.getParentFile());
// }
//
// //2. 删除记录
// HttpNormalTarget target = Aria.download(SingleTaskActivity.this).load(mTaskId);
// if (target != null) {
// // target.cancel();
// target.removeRecord();
// }
//
// List<DownloadEntity> notCompleteTask = Aria.download(SingleTaskActivity.this).getAllNotCompleteTask();
// if (notCompleteTask == null){
// Log.d(TAG, "未完成的任务数0");
// return;
// }
// Log.d(TAG, "未完成的任务数:" + notCompleteTask.size());
} }
}); });
} }

View File

@@ -36,7 +36,7 @@ import com.arialyy.simple.widget.SubStateLinearLayout;
* Created by lyy on 2017/7/6. * Created by lyy on 2017/7/6.
*/ */
public class FTPDirDownloadActivity extends BaseActivity<ActivityDownloadGroupBinding> { public class FTPDirDownloadActivity extends BaseActivity<ActivityDownloadGroupBinding> {
private static final String dir = "ftp://9.9.9.72:2121/upload/测试"; private static final String dir = "ftp://192.168.0.104:2121/aab/你好";
private SubStateLinearLayout mChildList; private SubStateLinearLayout mChildList;
private long mTaskId = -1; private long mTaskId = -1;
@@ -51,8 +51,10 @@ public class FTPDirDownloadActivity extends BaseActivity<ActivityDownloadGroupBi
if (entity != null) { if (entity != null) {
mTaskId = entity.getId(); mTaskId = entity.getId();
mChildList.addData(entity.getSubEntities()); mChildList.addData(entity.getSubEntities());
getBinding().pl.setInfo(entity); }else {
entity = new DownloadGroupEntity();
} }
getBinding().pl.setInfo(entity);
getBinding().pl.setBtListener(new ProgressLayout.OnProgressLayoutBtListener() { getBinding().pl.setBtListener(new ProgressLayout.OnProgressLayoutBtListener() {
@Override public void create(View v, AbsEntity entity) { @Override public void create(View v, AbsEntity entity) {
mTaskId = Aria.download(this) mTaskId = Aria.download(this)

View File

@@ -314,7 +314,7 @@ public class M3U8VodDLoadActivity extends BaseActivity<ActivityM3u8VodBinding> {
option.generateIndexFile(); option.generateIndexFile();
//option.setKeyUrlConverter(new KeyUrlConverter()); //option.setKeyUrlConverter(new KeyUrlConverter());
//option.setVodTsUrlConvert(new VodTsUrlConverter()); //option.setVodTsUrlConvert(new VodTsUrlConverter());
//option.setBandWidthUrlConverter(new BandWidthUrlConverter()); option.setBandWidthUrlConverter(new BandWidthUrlConverter());
//option.setUseDefConvert(true); //option.setUseDefConvert(true);
return option; return option;
} }

View File

@@ -35,7 +35,8 @@ public class M3U8VodModule extends BaseViewModule {
//private final String defUrl = "https://www.gaoya123.cn/2019/1557993797897.m3u8"; //private final String defUrl = "https://www.gaoya123.cn/2019/1557993797897.m3u8";
// 多码率地址: // 多码率地址:
//private final String defUrl = "http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"; //private final String defUrl = "http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8";
private final String defUrl = "http://pp3zvsk2n.bkt.clouddn.com/20200806/sd/15967206011811803/38475fadd55e4ecea3.m3u8"; private final String defUrl = "https://5.voooe.cn/cache/youku/4e00b49a6e4f11155967c2cb3385a2ab.m3u8";
//private final String defUrl = "http://pp3zvsk2n.bkt.clouddn.com/20200806/sd/15967206011811803/38475fadd55e4ecea3.m3u8";
//private final String defUrl = "http://youku.cdn7-okzy.com/20200123/16815_fbe419ed/index.m3u8"; //private final String defUrl = "http://youku.cdn7-okzy.com/20200123/16815_fbe419ed/index.m3u8";
//private final String defUrl = "https://cn7.kankia.com/hls/20200108/e1eaec074274c64fe46a3bdb5d2ba487/1578488360/index.m3u8"; //private final String defUrl = "https://cn7.kankia.com/hls/20200108/e1eaec074274c64fe46a3bdb5d2ba487/1578488360/index.m3u8";

View File

@@ -45,7 +45,7 @@ task clean(type: Delete) {
ext { ext {
versionCode = 390 versionCode = 390
versionName = '3.8.12' versionName = '3.8.15'
userOrg = 'arialyy' userOrg = 'arialyy'
groupId = 'com.arialyy.aria' groupId = 'com.arialyy.aria'
publishVersion = versionName publishVersion = versionName