35 Commits

Author SHA1 Message Date
laoyuyu
3024b85091 3.8.12 2020-08-15 13:38:41 +08:00
laoyuyu
c78fa1b66a 修复删除加密的m3u8文件时,key没有被删除的问题 https://github.com/AriaLyy/Aria/issues/735#issuecomment-673958845 2020-08-14 17:39:52 +08:00
laoyuyu
428fbab9d2 修复加密的m3u8下载,并且使用索引模式时,key的uri没有使用双引号的问题 https://github.com/AriaLyy/Aria/issues/731
修复删除m3u8索引文件后,下载完成回调无法触发的问题
2020-08-14 11:11:55 +08:00
laoyuyu
07a1f45f1e 修复m3u8任务地址错误时,无法删除实体的问题 https://github.com/AriaLyy/Aria/issues/712
修复0kb的文件不可下载的问题 https://github.com/AriaLyy/Aria/issues/711
2020-08-14 11:11:14 +08:00
laoyuyu
22a3b61dbf Merge branch 'master' of github.com:AriaLyy/Aria 2020-08-13 16:42:31 +08:00
lyy
eccbb37647 Update FUNDING.yml 2020-08-13 16:29:25 +08:00
laoyuyu
ab358e7dbf 修复http表单上传,本地md5和上传的服务的的文件md5不一致的问题 https://github.com/AriaLyy/Aria/issues/730 2020-08-13 13:58:19 +08:00
laoyuyu
86aeac0ad8 修复m3u8gzip的问题,https://github.com/AriaLyy/Aria/issues/639
m3u8使用`ignoreFailureTs`后将不会自动重试失败的切片 https://github.com/AriaLyy/Aria/issues/662
2020-08-13 10:06:28 +08:00
laoyuyu
ff0796c580 Merge branch 'master' of github.com:AriaLyy/Aria 2020-08-12 18:32:12 +08:00
laoyuyu
fed2b4111f 增加允许不使用apt直接通过实现监听器来回调下载进度更新,该功能由[chenfei0928](https://github.com/chenfei0928)提交,感谢他的pr。如果注解不生效,只需要实现接口便可
修复m3u8任务地址错误时,无法删除实体的问题 https://github.com/AriaLyy/Aria/issues/71://github.com/AriaLyy/Aria/issues/712
2020-08-12 18:31:26 +08:00
lyy
1a04a6d221 Update FUNDING.yml 2020-08-12 08:52:00 +08:00
laoyuyu
5f60b9ed57 现在http文件下载将使用HEAD请求获取文件大小,配置文件增加 <useHeadRequest value=false/> 2020-07-27 19:16:09 +08:00
laoyuyu
9d8bf579b6 修复一个匿名内部类中的内存溢出的问题 https://github.com/AriaLyy/Aria/issues/705
m3u8密钥下载地址转换器增加ts列表的url地址https://github.com/AriaLyy/Aria/issues/718
2020-07-27 13:21:45 +08:00
lyy
bebc9b926d Merge pull request #716 from chmod4755/fix-encoding-plus-character
fix regex of character +
2020-07-22 15:14:39 +08:00
wangshang
ae1a9e3870 fix regex of character + 2020-07-22 14:24:10 +08:00
laoyuyu
288dcf633e 使用spi机制优化组件的加载 2020-07-12 11:29:32 +08:00
lyy
fed6ae55e1 Update README.md 2020-07-09 14:14:41 +08:00
lyy
41bae31d6a Merge pull request #709 from chenfei0928/master
允许不使用apt直接通过实现监听器来回调下载进度更新
2020-07-08 09:30:17 +08:00
陈斐
8787030fa6 调整下载任务监听器父类接口名 2020-07-07 17:13:50 +08:00
陈斐
b5cbbd9d3d 修复类型转换错误 2020-07-07 17:10:58 +08:00
陈斐
1241bc5991 通过广播发送下载进度事件时,限制在当前包发送广播 2020-07-07 16:08:56 +08:00
陈斐
a3df4016ff 添加通过父类接口判断来检查是某种下载任务类型 2020-07-07 15:29:44 +08:00
laoyuyu
981917fa52 修改dialogfragment实现 2020-07-05 12:27:02 +08:00
laoyuyu
023f648d07 fix bug https://github.com/AriaLyy/Aria/issues/695 2020-06-26 15:53:28 +08:00
laoyuyu
9a174311d9 fix bug https://github.com/AriaLyy/Aria/issues/703
fix bug https://github.com/AriaLyy/Aria/issues/702
优化异常提示
2020-06-26 13:32:54 +08:00
lyy
3edf40f533 Update FUNDING.yml 2020-06-26 11:11:08 +08:00
lyy
46c10f6ffd Update FUNDING.yml 2020-06-26 11:09:03 +08:00
lyy
32cb6152dd Update FUNDING.yml 2020-06-26 11:06:13 +08:00
lyy
f657bbcc53 Update FUNDING.yml 2020-06-26 11:05:37 +08:00
lyy
e6f5c4f472 Update FUNDING.yml 2020-06-26 11:04:03 +08:00
lyy
b7e0f6f0e8 Update FUNDING.yml 2020-06-26 11:02:33 +08:00
lyy
0bc083fa98 Update FUNDING.yml 2020-06-26 10:58:38 +08:00
lyy
d931b75800 Create FUNDING.yml 2020-06-26 10:57:36 +08:00
laoyuyu
418ec74b7b fix bug https://github.com/AriaLyy/Aria/issues/688
fix bug https://github.com/AriaLyy/Aria/issues/690
m3u8任务增加`setUseDefConvert()`方法,用于处理默认的m3u8任务
2020-06-14 15:03:15 +08:00
laoyuyu
29f9bdcdbd - 修复设置了cancel(false),文件还是被删除的问题 https://github.com/AriaLyy/Aria/issues/686
- 修复错误url的下载任务,无法删除的问题 https://github.com/AriaLyy/Aria/issues/684
2020-06-07 10:35:23 +08:00
152 changed files with 2381 additions and 1312 deletions

8
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,8 @@
# These are supported funding model platforms
# https://help.github.com/cn/github/administering-a-repository/displaying-a-sponsor-button-in-your-repository
# github: ["AriaLyy"]
# patreon: AriaLyy
# liberapay: Aria
open_collective: Aria
custom: ["https://paypal.me/arialyy"]

19
.github/stale.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 7
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- bug
- adaptation
- new features
- suggest
# Label to use when marking an issue as stale
staleLabel: wontfix
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

View File

@@ -23,6 +23,10 @@ android {
dataBinding {
enabled = true
}
lintOptions {
abortOnError false
}
}
dependencies {

View File

@@ -27,6 +27,7 @@ import android.widget.PopupWindow;
import com.arialyy.aria.core.download.DownloadReceiver;
import com.arialyy.aria.core.upload.UploadReceiver;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
/**
* Created by lyy on 2016/12/1.
@@ -130,15 +131,20 @@ import com.arialyy.aria.util.ALog;
private static Context convertContext(Object obj) {
if (obj instanceof Application) {
return (Application) obj;
} else if (obj instanceof Service) {
}
if (obj instanceof Service) {
return (Service) obj;
} else if (obj instanceof Activity) {
}
if (obj instanceof Activity) {
return (Activity) obj;
} else if (AriaManager.isFragment(obj.getClass())) {
return AriaManager.getFragmentActivity(obj);
} else if (obj instanceof Dialog) {
}
if (CommonUtil.isFragment(obj.getClass())) {
return CommonUtil.getFragmentActivity(obj);
}
if (obj instanceof Dialog) {
return ((Dialog) obj).getContext();
} else if (obj instanceof PopupWindow) {
}
if (obj instanceof PopupWindow) {
return ((PopupWindow) obj).getContentView().getContext();
}
ALog.e("Aria", "请使用download(this)或upload(this)");

View File

@@ -19,11 +19,10 @@ import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Application;
import android.app.Dialog;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.widget.PopupWindow;
import android.util.Log;
import com.arialyy.aria.core.command.CommandManager;
import com.arialyy.aria.core.common.QueueMod;
import com.arialyy.aria.core.config.AppConfig;
@@ -35,23 +34,21 @@ import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.download.DownloadReceiver;
import com.arialyy.aria.core.inf.AbsReceiver;
import com.arialyy.aria.core.inf.IReceiver;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.inf.ReceiverType;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.upload.UploadReceiver;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.orm.DelegateWrapper;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.AriaCrashHandler;
import com.arialyy.aria.util.DeleteDGRecord;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.DeleteURecord;
import com.arialyy.aria.util.RecordUtil;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -63,35 +60,12 @@ import java.util.concurrent.ConcurrentHashMap;
private static final String TAG = "AriaManager";
private static final Object LOCK = new Object();
/**
* android、androidx、support的fragment、dialogFragment类名
*/
private static List<String> mFragmentClassName = new ArrayList<>();
private static List<String> mDialogFragmentClassName = new ArrayList<>();
@SuppressLint("StaticFieldLeak") private static volatile AriaManager INSTANCE = null;
private Map<String, AbsReceiver> mReceivers = new ConcurrentHashMap<>();
/**
* activity 和其Dialog、Fragment的映射表
*/
private Map<String, List<String>> mSubClass = new ConcurrentHashMap<>();
private static Context APP;
private DelegateWrapper mDbWrapper;
private AriaConfig mConfig;
static {
mFragmentClassName.add("androidx.fragment.app.Fragment");
mFragmentClassName.add("androidx.fragment.app.DialogFragment");
mFragmentClassName.add("android.app.Fragment");
mFragmentClassName.add("android.app.DialogFragment");
mFragmentClassName.add("android.support.v4.app.Fragment");
mFragmentClassName.add("android.support.v4.app.DialogFragment");
mDialogFragmentClassName.add("androidx.fragment.app.DialogFragment");
mDialogFragmentClassName.add("android.app.DialogFragment");
mDialogFragmentClassName.add("android.support.v4.app.DialogFragment");
}
private AriaManager(Context context) {
APP = context.getApplicationContext();
}
@@ -253,6 +227,7 @@ import java.util.concurrent.ConcurrentHashMap;
* 处理下载操作
*/
DownloadReceiver download(Object obj) {
IReceiver receiver = mReceivers.get(getKey(ReceiverType.DOWNLOAD, obj));
if (receiver == null) {
receiver = putReceiver(ReceiverType.DOWNLOAD, obj);
@@ -292,138 +267,19 @@ import java.util.concurrent.ConcurrentHashMap;
}
}
private IReceiver putReceiver(String type, Object obj) {
private IReceiver putReceiver(ReceiverType type, Object obj) {
final String key = getKey(type, obj);
IReceiver receiver = mReceivers.get(key);
boolean needRmReceiver = false;
// 监控Dialog、fragment、popupWindow的生命周期
final WidgetLiftManager widgetLiftManager = new WidgetLiftManager();
Context subParenActivity = null;
if (obj instanceof Dialog) {
needRmReceiver = widgetLiftManager.handleDialogLift((Dialog) obj);
subParenActivity = ((Dialog) obj).getOwnerActivity();
} else if (obj instanceof PopupWindow) {
needRmReceiver = widgetLiftManager.handlePopupWindowLift((PopupWindow) obj);
subParenActivity = ((PopupWindow) obj).getContentView().getContext();
} else if (isDialogFragment(obj.getClass())) {
needRmReceiver = widgetLiftManager.handleDialogFragmentLift(getDialog(obj));
subParenActivity = getFragmentActivity(obj);
} else if (isFragment(obj.getClass())) {
subParenActivity = getFragmentActivity(obj);
}
if (subParenActivity instanceof Activity) {
relateSubClass(type, obj, (Activity) subParenActivity);
}
if (receiver == null) {
AbsReceiver absReceiver =
type.equals(ReceiverType.DOWNLOAD) ? new DownloadReceiver() : new UploadReceiver();
absReceiver.targetName = obj.getClass().getName();
AbsReceiver.OBJ_MAP.put(absReceiver.getKey(), obj);
absReceiver.needRmListener = needRmReceiver;
type.equals(ReceiverType.DOWNLOAD) ? new DownloadReceiver(obj) : new UploadReceiver(obj);
mReceivers.put(key, absReceiver);
receiver = absReceiver;
}
return receiver;
}
/**
* 获取fragment的activity
*
* @return 获取失败返回null
*/
static Activity getFragmentActivity(Object obj) {
try {
Method method = obj.getClass().getMethod("getActivity");
return (Activity) method.invoke(obj);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
/**
* 判断注解对象是否是fragment
*
* @return true 对象是fragment
*/
static boolean isFragment(Class subClazz) {
Class parentClass = subClazz.getSuperclass();
if (parentClass == null) {
return false;
} else {
String parentName = parentClass.getName();
if (mFragmentClassName.contains(parentName)) {
return true;
} else {
return isFragment(parentClass);
}
}
}
/**
* 判断对象是否是DialogFragment
*
* @return true 对象是DialogFragment
*/
private boolean isDialogFragment(Class subClazz) {
Class parentClass = subClazz.getSuperclass();
if (parentClass == null) {
return false;
} else {
String parentName = parentClass.getName();
if (mDialogFragmentClassName.contains(parentName)) {
return true;
} else {
return isDialogFragment(parentClass);
}
}
}
/**
* 获取DialogFragment的dialog
*
* @return 获取失败返回null
*/
private Dialog getDialog(Object obj) {
try {
Method method = obj.getClass().getMethod("getDialog");
return (Dialog) method.invoke(obj);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
/**
* 关联Activity类和Fragment间的关系
*
* @param sub Fragment或dialog类
* @param activity activity寄主类
*/
private void relateSubClass(String type, Object sub, Activity activity) {
String key = getKey(type, activity);
List<String> subClass = mSubClass.get(key);
if (subClass == null) {
subClass = new ArrayList<>();
mSubClass.put(key, subClass);
}
subClass.add(getKey(type, sub));
if (mReceivers.get(key) == null) { // 将activity填充进去
mReceivers.put(key, new DownloadReceiver());
}
}
/**
* 根据功能类型和控件类型获取对应的key
*
@@ -432,8 +288,8 @@ import java.util.concurrent.ConcurrentHashMap;
* @return key的格式为{@code String.format("%s_%s_%s", obj.getClass().getName(), type,
* obj.hashCode());}
*/
private String getKey(String type, Object obj) {
return String.format("%s_%s_%s", obj.getClass().getName(), type, obj.hashCode());
private String getKey(ReceiverType type, Object obj) {
return String.format("%s_%s_%s", CommonUtil.getTargetName(obj), type.name(), obj.hashCode());
}
/**
@@ -455,40 +311,47 @@ import java.util.concurrent.ConcurrentHashMap;
ALog.e(TAG, "target obj is null");
return;
}
List<String> temp = new ArrayList<>();
// 移除寄主的receiver
for (Iterator<Map.Entry<String, AbsReceiver>> iter = mReceivers.entrySet().iterator();
iter.hasNext(); ) {
Map.Entry<String, AbsReceiver> entry = iter.next();
String key = entry.getKey();
if (key.equals(getKey(ReceiverType.DOWNLOAD, obj)) || key.equals(
getKey(ReceiverType.UPLOAD, obj))) {
AbsReceiver receiver = mReceivers.get(key);
List<String> subNames = mSubClass.get(key);
if (subNames != null && !subNames.isEmpty()) {
temp.addAll(subNames);
}
if (receiver != null) {
receiver.destroy();
AbsReceiver receiver = entry.getValue();
if (receiver.isFragment()){
Method method = CommonUtil.getMethod(receiver.obj.getClass(), "getActivity");
if (method != null){
try {
Activity ac = (Activity) method.invoke(receiver.obj);
if (ac == obj){
receiver.destroy();
iter.remove();
continue;
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
// 处理内部类的
String objClsName = obj.getClass().getName();
if (receiver.isLocalOrAnonymousClass && key.startsWith(objClsName)) {
receiver.destroy();
iter.remove();
continue;
}
if (key.equals(getKey(ReceiverType.DOWNLOAD, obj))
|| key.equals(getKey(ReceiverType.UPLOAD, obj))
) {
receiver.destroy();
iter.remove();
}
}
// 移除寄生的receiver
if (!temp.isEmpty()) {
for (Iterator<Map.Entry<String, AbsReceiver>> iter = mReceivers.entrySet().iterator();
iter.hasNext(); ) {
Map.Entry<String, AbsReceiver> entry = iter.next();
if (temp.contains(entry.getKey())) {
AbsReceiver receiver = mReceivers.get(entry.getKey());
if (receiver != null) {
receiver.destroy();
}
iter.remove();
}
}
}
Log.d(TAG, "debug");
}
/**

View File

@@ -29,20 +29,20 @@ import java.lang.reflect.Field;
* Created by lyy on 2017/2/7.
* 为组件添加生命周期
*/
final class WidgetLiftManager {
public final class WidgetLiftManager {
private final String TAG = "WidgetLiftManager";
/**
* 处理DialogFragment事件
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB) boolean handleDialogFragmentLift(Dialog dialog) {
@TargetApi(Build.VERSION_CODES.HONEYCOMB) public boolean handleDialogFragmentLift(Dialog dialog) {
return handleDialogLift(dialog);
}
/**
* 处理悬浮框取消或dismiss事件
*/
boolean handlePopupWindowLift(PopupWindow popupWindow) {
public boolean handlePopupWindowLift(PopupWindow popupWindow) {
try {
Field dismissField = CommonUtil.getField(popupWindow.getClass(), "mOnDismissListener");
PopupWindow.OnDismissListener listener =
@@ -76,7 +76,7 @@ final class WidgetLiftManager {
*
* @return true 设置了dialog的销毁事件。false 没有设置dialog的销毁事件
*/
boolean handleDialogLift(Dialog dialog) {
public boolean handleDialogLift(Dialog dialog) {
if (dialog == null) {
ALog.w(TAG,
"dialog 为空没有设置自动销毁事件为了防止内存泄露请在dismiss方法中调用Aria.download(this).unRegister();来注销事件\n"

View File

@@ -16,6 +16,13 @@
package com.arialyy.aria.core.common;
import com.arialyy.annotations.TaskEnum;
import com.arialyy.aria.core.download.DownloadGroupTaskListener;
import com.arialyy.aria.core.download.DownloadTaskListener;
import com.arialyy.aria.core.scheduler.TaskInternalListenerInterface;
import com.arialyy.aria.core.scheduler.M3U8PeerTaskListener;
import com.arialyy.aria.core.scheduler.SubTaskListener;
import com.arialyy.aria.core.upload.UploadTaskListener;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@@ -69,12 +76,25 @@ public class ProxyHelper {
* @return {@link #PROXY_TYPE_DOWNLOAD}如果没有实体对象则返回空的list
*/
public Set<Integer> checkProxyType(Class clazz) {
final String className = clazz.getName();
Set<Integer> result = mProxyCache.get(clazz.getName());
if (result != null) {
return result;
}
result = new HashSet<>();
result = checkProxyTypeByInterface(clazz);
if (result != null) {
return result;
}
result = checkProxyTypeByProxyClass(clazz);
if (!result.isEmpty()) {
mProxyCache.put(clazz.getName(), result);
}
return result;
}
private Set<Integer> checkProxyTypeByProxyClass(Class clazz) {
final String className = clazz.getName();
Set<Integer> result = new HashSet<>();
if (checkProxyExist(className, TaskEnum.DOWNLOAD_GROUP.proxySuffix)) {
result.add(PROXY_TYPE_DOWNLOAD_GROUP);
}
@@ -93,9 +113,31 @@ public class ProxyHelper {
if (checkProxyExist(className, TaskEnum.DOWNLOAD_GROUP_SUB.proxySuffix)) {
result.add(PROXY_TYPE_DOWNLOAD_GROUP_SUB);
}
return result;
}
if (!result.isEmpty()) {
mProxyCache.put(clazz.getName(), result);
private Set<Integer> checkProxyTypeByInterface(Class clazz) {
if (!TaskInternalListenerInterface.class.isAssignableFrom(clazz)) {
return null;
}
Set<Integer> result = new HashSet<>();
if (DownloadGroupTaskListener.class.isAssignableFrom(clazz)) {
result.add(PROXY_TYPE_DOWNLOAD_GROUP);
}
if (DownloadTaskListener.class.isAssignableFrom(clazz)) {
result.add(PROXY_TYPE_DOWNLOAD);
}
if (UploadTaskListener.class.isAssignableFrom(clazz)) {
result.add(PROXY_TYPE_UPLOAD);
}
if (M3U8PeerTaskListener.class.isAssignableFrom(clazz)) {
result.add(PROXY_TYPE_M3U8_PEER);
}
if (SubTaskListener.class.isAssignableFrom(clazz)) {
result.add(PROXY_TYPE_DOWNLOAD_GROUP_SUB);
}
return result;
}

View File

@@ -21,6 +21,7 @@ import com.arialyy.aria.core.inf.ICheckEntityUtil;
import com.arialyy.aria.core.inf.IOptionConstant;
import com.arialyy.aria.core.inf.ITargetHandler;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.CommonUtil;
@@ -135,8 +136,16 @@ public class CheckDEntityUtil implements ICheckEntityUtil {
/**
* 检查路径冲突
* @return true 路径没有冲突
*/
private boolean checkPathConflicts(String filePath) {
DownloadEntity de = DbEntity.findFirst(DownloadEntity.class, "downloadPath=?", filePath);
if (de != null && de.getUrl().equals(mEntity.getUrl())){
mEntity.rowID = de.rowID;
mEntity.setFilePath(filePath);
mEntity.setFileName(new File(filePath).getName());
return true;
}
//设置文件保存路径,如果新文件路径和旧文件路径不同,则修改路径
if (!filePath.equals(mEntity.getFilePath())) {
// 检查路径冲突

View File

@@ -123,6 +123,12 @@ public class CheckDGEntityUtil implements ICheckEntityUtil {
* @return false 任务不再执行true 任务继续执行
*/
private boolean checkGroupHash(boolean isIgnoreTaskOccupy, String groupHash) {
DownloadGroupEntity dge = DbEntity.findFirst(DownloadGroupEntity.class, "groupHash=?", groupHash);
if (dge != null && dge.getGroupHash().equals(mEntity.getGroupHash())){
mEntity.rowID = dge.rowID;
return true;
}
if (DbEntity.checkDataExist(DownloadGroupEntity.class, "groupHash=?", groupHash)) {
if (!isIgnoreTaskOccupy) {
ALog.e(TAG, String.format("下载失败数据库中已存在相同的url的组任务groupHash = %s", groupHash));

View File

@@ -0,0 +1,26 @@
/*
* 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 com.arialyy.aria.core.scheduler.NormalTaskListenerInterface;
import com.arialyy.aria.core.task.DownloadGroupTask;
/**
* @author ChenFei(chenfei0928 @ gmail.com)
* @date 2020-07-07 14:12
*/
public interface DownloadGroupTaskListener extends NormalTaskListenerInterface<DownloadGroupTask> {
}

View File

@@ -38,6 +38,9 @@ import com.arialyy.aria.core.inf.AbsReceiver;
import com.arialyy.aria.core.inf.ReceiverType;
import com.arialyy.aria.core.queue.DGroupTaskQueue;
import com.arialyy.aria.core.queue.DTaskQueue;
import com.arialyy.aria.core.scheduler.M3U8PeerTaskListener;
import com.arialyy.aria.core.scheduler.SubTaskListener;
import com.arialyy.aria.core.scheduler.TaskInternalListenerInterface;
import com.arialyy.aria.core.scheduler.TaskSchedulers;
import com.arialyy.aria.core.task.ITask;
import com.arialyy.aria.orm.DbEntity;
@@ -55,7 +58,10 @@ import java.util.Set;
* 下载功能接收器
*/
public class DownloadReceiver extends AbsReceiver {
private final String TAG = "DownloadReceiver";
public DownloadReceiver(Object obj) {
super(obj);
}
/**
* 设置最大下载速度单位kb
@@ -164,11 +170,26 @@ public class DownloadReceiver extends AbsReceiver {
* 将当前类注册到Aria
*/
public void register() {
Object obj = OBJ_MAP.get(getKey());
if (obj == null) {
ALog.e(TAG, String.format("【%s】观察者为空", getTargetName()));
ALog.e(TAG, String.format("register【%s】观察者为空", getTargetName()));
return;
}
if (obj instanceof TaskInternalListenerInterface){
if (obj instanceof DownloadTaskListener){
TaskSchedulers.getInstance().register(obj, TaskEnum.DOWNLOAD);
}
if (obj instanceof DownloadGroupTaskListener){
TaskSchedulers.getInstance().register(obj, TaskEnum.DOWNLOAD_GROUP);
}
if (obj instanceof M3U8PeerTaskListener){
TaskSchedulers.getInstance().register(obj, TaskEnum.M3U8_PEER);
}
if (obj instanceof SubTaskListener){
TaskSchedulers.getInstance().register(obj, TaskEnum.DOWNLOAD_GROUP_SUB);
}
return;
}
Set<Integer> set = ProxyHelper.getInstance().checkProxyType(obj.getClass());
if (set != null && !set.isEmpty()) {
for (Integer type : set) {
@@ -199,20 +220,19 @@ public class DownloadReceiver extends AbsReceiver {
* @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) {
if (isNeedRmListener()) {
unRegisterListener();
}
AriaManager.getInstance().removeReceiver(OBJ_MAP.get(getKey()));
AriaManager.getInstance().removeReceiver(obj);
}
@Override public String getType() {
@Override public ReceiverType getType() {
return ReceiverType.DOWNLOAD;
}
@Override protected void unRegisterListener() {
Object obj = OBJ_MAP.get(getKey());
if (obj == null) {
ALog.e(TAG, String.format("【%s】观察者为空", getTargetName()));
ALog.e(TAG, String.format("unRegister【%s】观察者为空", getTargetName()));
return;
}
Set<Integer> set = ProxyHelper.getInstance().mProxyCache.get(obj.getClass().getName());
@@ -220,7 +240,9 @@ public class DownloadReceiver extends AbsReceiver {
for (Integer integer : set) {
if (integer == ProxyHelper.PROXY_TYPE_DOWNLOAD) {
TaskSchedulers.getInstance().unRegister(obj);
} else if (integer == ProxyHelper.PROXY_TYPE_DOWNLOAD_GROUP) {
continue;
}
if (integer == ProxyHelper.PROXY_TYPE_DOWNLOAD_GROUP) {
TaskSchedulers.getInstance().unRegister(obj);
}
}
@@ -417,7 +439,7 @@ public class DownloadReceiver extends AbsReceiver {
* @return 如果没有任务组列表则返回null
*/
public List<DownloadGroupEntity> getGroupTaskList() {
return getGroupTaskList(1,10);
return getGroupTaskList(1, 10);
}
/**

View File

@@ -0,0 +1,26 @@
/*
* 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 com.arialyy.aria.core.scheduler.NormalTaskListenerInterface;
import com.arialyy.aria.core.task.DownloadTask;
/**
* @author ChenFei(chenfei0928 @ gmail.com)
* @date 2020-07-07 14:12
*/
public interface DownloadTaskListener extends NormalTaskListenerInterface<DownloadTask> {
}

View File

@@ -37,12 +37,23 @@ public class M3U8Option<OP extends M3U8Option> extends BaseOption {
private IKeyUrlConverter keyUrlConverter;
private boolean ignoreFailureTs = false;
private String keyPath;
private boolean useDefConvert = true;
M3U8Option() {
super();
ComponentUtil.getInstance().checkComponentExist(ComponentUtil.COMPONENT_TYPE_M3U8);
}
/**
* 设置使用默认的码率转换器和TS转换器默认打开
* @param useDefConvert true 使用默认的转换器false 关闭默认的转换器
*/
public OP setUseDefConvert(boolean useDefConvert) {
this.useDefConvert = useDefConvert;
ALog.d(TAG, "使用默认的码率转换器和TS转换器如果无法下载请参考https://github.com/AriaLyy/Aria/issues/597 定制转换器");
return (OP) this;
}
/**
* 设置密钥文件的保存路径
*

View File

@@ -98,6 +98,7 @@ class DNormalConfigHandler<TARGET extends AbsTarget> implements IConfigHandler {
void setUrl(String url) {
mEntity.setUrl(url);
mWrapper.setTempUrl(url);
}
String getUrl() {

View File

@@ -16,31 +16,119 @@
package com.arialyy.aria.core.inf;
import android.app.Dialog;
import android.util.Log;
import android.widget.PopupWindow;
import com.arialyy.aria.core.WidgetLiftManager;
import com.arialyy.aria.core.queue.DGroupTaskQueue;
import com.arialyy.aria.core.queue.DTaskQueue;
import com.arialyy.aria.core.queue.UTaskQueue;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.arialyy.aria.util.CommonUtil;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Created by AriaL on 2017/6/27.
* 接收器
*/
public abstract class AbsReceiver implements IReceiver {
protected String TAG = getClass().getSimpleName();
/**
* 观察者对象map
* key 由 {@link #getKey(IReceiver)}指定
* 观察者对象
*/
public static final Map<String, Object> OBJ_MAP = new ConcurrentHashMap<>();
public Object obj;
/**
* 观察者对象类的完整名称
*/
public String targetName;
private String targetName;
/**
* 当dialog、dialogFragment、popupwindow已经被用户使用了Dismiss事件或Cancel事件需要手动移除receiver
*/
public boolean needRmListener = false;
private boolean needRmReceiver = false;
private boolean isFragment = false;
public boolean isLocalOrAnonymousClass = false;
public AbsReceiver(Object obj) {
this.obj = obj;
initParams();
}
private void initParams() {
try {
targetName = CommonUtil.getTargetName(obj);
Class clazz = obj.getClass();
if (CommonUtil.isLocalOrAnonymousClass(clazz)) {
isLocalOrAnonymousClass = true;
String parentName = CommonUtil.getTargetName(obj);
Class parentClazz = Class.forName(parentName);
handleFragmentOrDialogParam(parentClazz, true);
return;
}
handleFragmentOrDialogParam(clazz, false);
} catch (Exception e) {
e.printStackTrace();
}
}
private void handleFragmentOrDialogParam(Class clazz, boolean isLocalOrAnonymousClass) {
final WidgetLiftManager widgetLiftManager = new WidgetLiftManager();
if (obj instanceof Dialog) {
needRmReceiver = widgetLiftManager.handleDialogLift((Dialog) obj);
return;
}
if (obj instanceof PopupWindow) {
needRmReceiver = widgetLiftManager.handlePopupWindowLift((PopupWindow) obj);
return;
}
if (CommonUtil.isFragment(clazz)){
isFragment = true;
}
if (CommonUtil.isDialogFragment(clazz)) {
isFragment = true;
if (isLocalOrAnonymousClass) {
Log.e(TAG, String.format(
"%s 是匿名内部类无法获取到dialog对象为了防止内存泄漏请在dismiss方法中调用Aria.download(this).unRegister();来注销事件",
obj.getClass().getName()
));
return;
}
needRmReceiver = widgetLiftManager.handleDialogFragmentLift(getDialog(obj));
}
}
/**
* 获取DialogFragment的dialog
*
* @return 获取失败返回null
*/
private Dialog getDialog(Object obj) {
try {
Method method = obj.getClass().getMethod("getDialog");
return (Dialog) method.invoke(obj);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
protected boolean isNeedRmListener() {
return needRmReceiver;
}
@Override public boolean isFragment() {
return isFragment;
}
/**
* 创建观察者对象map的key生成规则
@@ -69,14 +157,7 @@ public abstract class AbsReceiver implements IReceiver {
* 移除观察者对象
*/
private void removeObj() {
for (Iterator<Map.Entry<String, Object>> iter = OBJ_MAP.entrySet().iterator();
iter.hasNext(); ) {
Map.Entry<String, Object> entry = iter.next();
String key = entry.getKey();
if (key.equals(getKey())) {
iter.remove();
}
}
obj = null;
}
@Override public void destroy() {

View File

@@ -49,5 +49,11 @@ public interface IReceiver {
*
* @return {@link ReceiverType}
*/
String getType();
ReceiverType getType();
/**
* 判断是否是fragment如果是fragment在activity销毁时需要将其从receiver中移除
*/
boolean isFragment();
}

View File

@@ -18,7 +18,15 @@ package com.arialyy.aria.core.inf;
/**
* {@link AbsReceiver}类型
*/
public interface ReceiverType {
String DOWNLOAD = "download";
String UPLOAD = "upload";
public enum ReceiverType {
DOWNLOAD(1, "download"),
UPLOAD(2, "upload");
String name;
int type;
ReceiverType(int type, String name) {
this.type = type;
this.name = name;
}
}

View File

@@ -28,7 +28,7 @@ import java.util.List;
* 子任务管理器
*/
public class SubTaskManager {
private String TAG = "SubTaskManager";
private final String TAG = getClass().getSimpleName();
private DGTaskWrapper mEntity;
public SubTaskManager(DGTaskWrapper entity) {

View File

@@ -0,0 +1,36 @@
/*
* 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.scheduler;
/**
* Created by Aria.Lao on 2019/6/26.
* m3u8切片事件回调类
*/
public class AptM3U8PeerTaskListener implements M3U8PeerTaskListener, ISchedulerListener{
@Override public void onPeerStart(final String m3u8Url, final String peerPath, final int peerIndex) {
}
@Override public void onPeerComplete(final String m3u8Url, final String peerPath, final int peerIndex) {
}
@Override public void onPeerFail(final String m3u8Url, final String peerPath, final int peerIndex) {
}
@Override public void setListener(Object obj) {
}
}

View File

@@ -24,12 +24,12 @@ import com.arialyy.aria.core.task.UploadTask;
* Created by Aria.Lao on 2017/6/7.
* 普通任务事件{@link DownloadTask}{@link UploadTask}{@link DownloadGroupTask}回调类
*/
public class NormalTaskListener<TASK extends ITask> implements ISchedulerListener {
public class AptNormalTaskListener<TASK extends ITask> implements NormalTaskListenerInterface<TASK>, ISchedulerListener {
/**
* 队列已经满了继续创建任务将会回调该方法
*/
public void onWait(TASK task) {
@Override public void onWait(TASK task) {
}
@@ -37,42 +37,42 @@ public class NormalTaskListener<TASK extends ITask> implements ISchedulerListene
* 预处理有时有些地址链接比较慢这时可以先在这个地方出来一些界面上的UI如按钮的状态
* 在这个回调中任务是获取不到文件大小下载速度等参数
*/
public void onPre(TASK task) {
@Override public void onPre(TASK task) {
}
/**
* 任务预加载完成
*/
public void onTaskPre(TASK task) {
@Override public void onTaskPre(TASK task) {
}
/**
* 任务恢复下载
*/
public void onTaskResume(TASK task) {
@Override public void onTaskResume(TASK task) {
}
/**
* 任务开始
*/
public void onTaskStart(TASK task) {
@Override public void onTaskStart(TASK task) {
}
/**
* 任务停止
*/
public void onTaskStop(TASK task) {
@Override public void onTaskStop(TASK task) {
}
/**
* 任务取消
*/
public void onTaskCancel(TASK task) {
@Override public void onTaskCancel(TASK task) {
}
@@ -88,25 +88,25 @@ public class NormalTaskListener<TASK extends ITask> implements ISchedulerListene
/**
* 任务失败
*/
public void onTaskFail(TASK task, Exception e) {
@Override public void onTaskFail(TASK task, Exception e) {
}
/**
* 任务完成
*/
public void onTaskComplete(TASK task) {
@Override public void onTaskComplete(TASK task) {
}
/**
* 任务执行中
*/
public void onTaskRunning(TASK task) {
@Override public void onTaskRunning(TASK task) {
}
public void onNoSupportBreakPoint(TASK task) {
@Override public void onNoSupportBreakPoint(TASK task) {
}

View File

@@ -0,0 +1,68 @@
/*
* 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.scheduler;
import com.arialyy.aria.core.common.AbsNormalEntity;
import com.arialyy.aria.core.task.ITask;
/**
* Created by Aria.Lao on 2019/6/26.
* 子任务事件回调类
*/
public class AptSubTaskListener<TASK extends ITask, SUB_ENTITY extends AbsNormalEntity>
implements SubTaskListener<TASK, SUB_ENTITY>, ISchedulerListener {
@Override public void onNoSupportBreakPoint(TASK task) {
}
@Override public void onSubTaskPre(TASK task, SUB_ENTITY subTask) {
}
@Override public void onSubTaskStart(TASK task, SUB_ENTITY subTask) {
}
@Override public void onSubTaskStop(TASK task, SUB_ENTITY subTask) {
}
@Override public void onSubTaskCancel(TASK task, SUB_ENTITY subTask) {
}
@Override public void onSubTaskComplete(TASK task, SUB_ENTITY subTask) {
}
@Deprecated
public void onSubTaskFail(TASK task, SUB_ENTITY subTask) {
}
@Override public void onSubTaskFail(TASK task, SUB_ENTITY subTask, Exception e) {
}
@Override public void onSubTaskRunning(TASK task, SUB_ENTITY subTask) {
}
@Override public void setListener(Object obj) {
}
}

View File

@@ -19,18 +19,11 @@ package com.arialyy.aria.core.scheduler;
* Created by Aria.Lao on 2019/6/26.
* m3u8切片事件回调类
*/
public class M3U8PeerTaskListener implements ISchedulerListener {
public interface M3U8PeerTaskListener extends TaskInternalListenerInterface {
public void onPeerStart(final String m3u8Url, final String peerPath, final int peerIndex) {
}
public void onPeerStart(final String m3u8Url, final String peerPath, final int peerIndex);
public void onPeerComplete(final String m3u8Url, final String peerPath, final int peerIndex) {
}
public void onPeerComplete(final String m3u8Url, final String peerPath, final int peerIndex);
public void onPeerFail(final String m3u8Url, final String peerPath, final int peerIndex) {
}
@Override public void setListener(Object obj) {
}
public void onPeerFail(final String m3u8Url, final String peerPath, final int peerIndex);
}

View File

@@ -0,0 +1,82 @@
/*
* 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.scheduler;
import com.arialyy.aria.core.task.DownloadGroupTask;
import com.arialyy.aria.core.task.DownloadTask;
import com.arialyy.aria.core.task.ITask;
import com.arialyy.aria.core.task.UploadTask;
/**
* Created by Aria.Lao on 2017/6/7.
* 普通任务事件{@link DownloadTask}、{@link UploadTask}、{@link DownloadGroupTask}回调类
*/
public interface NormalTaskListenerInterface<TASK extends ITask> extends
TaskInternalListenerInterface {
/**
* 队列已经满了,继续创建任务,将会回调该方法
*/
public void onWait(TASK task);
/**
* 预处理有时有些地址链接比较慢这时可以先在这个地方出来一些界面上的UI如按钮的状态。
* 在这个回调中,任务是获取不到文件大小,下载速度等参数
*/
public void onPre(TASK task);
/**
* 任务预加载完成
*/
public void onTaskPre(TASK task);
/**
* 任务恢复下载
*/
public void onTaskResume(TASK task);
/**
* 任务开始
*/
public void onTaskStart(TASK task);
/**
* 任务停止
*/
public void onTaskStop(TASK task);
/**
* 任务取消
*/
public void onTaskCancel(TASK task);
/**
* 任务失败
*/
public void onTaskFail(TASK task, Exception e);
/**
* 任务完成
*/
public void onTaskComplete(TASK task);
/**
* 任务执行中
*/
public void onTaskRunning(TASK task);
public void onNoSupportBreakPoint(TASK task);
}

View File

@@ -22,47 +22,22 @@ import com.arialyy.aria.core.task.ITask;
* Created by Aria.Lao on 2019/6/26.
* 子任务事件回调类
*/
public class SubTaskListener<TASK extends ITask, SUB_ENTITY extends AbsNormalEntity>
implements ISchedulerListener {
public interface SubTaskListener<TASK extends ITask, SUB_ENTITY extends AbsNormalEntity> extends
TaskInternalListenerInterface {
public void onNoSupportBreakPoint(TASK task) {
public void onNoSupportBreakPoint(TASK task);
}
public void onSubTaskPre(TASK task, SUB_ENTITY subTask);
public void onSubTaskPre(TASK task, SUB_ENTITY subTask) {
public void onSubTaskStart(TASK task, SUB_ENTITY subTask);
}
public void onSubTaskStop(TASK task, SUB_ENTITY subTask);
public void onSubTaskStart(TASK task, SUB_ENTITY subTask) {
public void onSubTaskCancel(TASK task, SUB_ENTITY subTask);
}
public void onSubTaskComplete(TASK task, SUB_ENTITY subTask);
public void onSubTaskStop(TASK task, SUB_ENTITY subTask) {
public void onSubTaskFail(TASK task, SUB_ENTITY subTask, Exception e);
}
public void onSubTaskCancel(TASK task, SUB_ENTITY subTask) {
}
public void onSubTaskComplete(TASK task, SUB_ENTITY subTask) {
}
@Deprecated
public void onSubTaskFail(TASK task, SUB_ENTITY subTask) {
}
public void onSubTaskFail(TASK task, SUB_ENTITY subTask, Exception e) {
}
public void onSubTaskRunning(TASK task, SUB_ENTITY subTask) {
}
@Override public void setListener(Object obj) {
}
public void onSubTaskRunning(TASK task, SUB_ENTITY subTask);
}

View File

@@ -0,0 +1,25 @@
/*
* 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.scheduler;
/**
* 直接实现监听器回调接口的基类,不对外部直接开放,仅作为内部监听器的父接口使用
*
* @author ChenFei(chenfei0928 @ gmail.com)
* @date 2020-07-07 15:18
*/
public interface TaskInternalListenerInterface {
}

View File

@@ -18,7 +18,6 @@ package com.arialyy.aria.core.scheduler;
import android.content.Intent;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;
import com.arialyy.annotations.TaskEnum;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.common.AbsEntity;
@@ -54,7 +53,7 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
private static volatile TaskSchedulers INSTANCE;
private static FailureTaskHandler mFailureTaskHandler;
private Map<String, Map<TaskEnum, ISchedulerListener>> mObservers = new ConcurrentHashMap<>();
private Map<String, Map<TaskEnum, Object>> mObservers = new ConcurrentHashMap<>();
private AriaConfig mAriaConfig;
private TaskSchedulers() {
@@ -99,15 +98,19 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
*/
public void register(Object obj, TaskEnum taskEnum) {
String targetName = obj.getClass().getName();
Map<TaskEnum, ISchedulerListener> listeners = mObservers.get(getKey(obj));
Map<TaskEnum, Object> listeners = mObservers.get(getKey(obj));
if (listeners == null) {
listeners = new ConcurrentHashMap<>();
mObservers.put(getKey(obj), listeners);
}
String proxyClassName = targetName + taskEnum.proxySuffix;
if (!hasProxyListener(listeners, taskEnum)) {
if (obj instanceof TaskInternalListenerInterface) {
listeners.put(taskEnum, obj);
return;
}
String proxyClassName = targetName + taskEnum.proxySuffix;
ISchedulerListener listener = createListener(proxyClassName);
if (listener != null) {
listener.setListener(obj);
@@ -124,7 +127,7 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
* @param taskEnum 代理类类型
* @return true已注册代理类false没有注册代理类
*/
private boolean hasProxyListener(Map<TaskEnum, ISchedulerListener> listeners, TaskEnum taskEnum) {
private boolean hasProxyListener(Map<TaskEnum, Object> listeners, TaskEnum taskEnum) {
return !listeners.isEmpty() && listeners.get(taskEnum) != null;
}
@@ -137,9 +140,9 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
if (!mObservers.containsKey(getKey(obj))) {
return;
}
for (Iterator<Map.Entry<String, Map<TaskEnum, ISchedulerListener>>> iter =
for (Iterator<Map.Entry<String, Map<TaskEnum, Object>>> iter =
mObservers.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry<String, Map<TaskEnum, ISchedulerListener>> entry = iter.next();
Map.Entry<String, Map<TaskEnum, Object>> entry = iter.next();
if (entry.getKey().equals(getKey(obj))) {
iter.remove();
@@ -202,7 +205,7 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
if (mObservers.size() > 0) {
Set<String> keys = mObservers.keySet();
for (String key : keys) {
Map<TaskEnum, ISchedulerListener> listeners = mObservers.get(key);
Map<TaskEnum, Object> listeners = mObservers.get(key);
if (listeners == null || listeners.isEmpty()) {
continue;
}
@@ -235,6 +238,7 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
boolean canSend = mAriaConfig.getAConfig().isUseBroadcast();
if (canSend) {
Intent intent = new Intent(ISchedulers.ARIA_TASK_INFO_ACTION);
intent.setPackage(mAriaConfig.getAPP().getPackageName());
intent.putExtras(data);
mAriaConfig.getAPP().sendBroadcast(intent);
}
@@ -250,7 +254,7 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
if (mObservers.size() > 0) {
Set<String> keys = mObservers.keySet();
for (String key : keys) {
Map<TaskEnum, ISchedulerListener> listeners = mObservers.get(key);
Map<TaskEnum, Object> listeners = mObservers.get(key);
if (listeners == null || listeners.isEmpty()) {
continue;
}
@@ -358,6 +362,7 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
boolean canSend = mAriaConfig.getAConfig().isUseBroadcast();
if (canSend) {
Intent intent = new Intent(ISchedulers.ARIA_TASK_INFO_ACTION);
intent.setPackage(mAriaConfig.getAPP().getPackageName());
Bundle b = new Bundle();
b.putInt(ISchedulers.TASK_TYPE, taskType);
b.putInt(ISchedulers.TASK_STATE, ISchedulers.FAIL);
@@ -368,18 +373,18 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
if (mObservers.size() > 0) {
Set<String> keys = mObservers.keySet();
for (String key : keys) {
Map<TaskEnum, ISchedulerListener> listeners = mObservers.get(key);
Map<TaskEnum, Object> listeners = mObservers.get(key);
if (listeners == null || listeners.isEmpty()) {
continue;
}
NormalTaskListener<TASK> listener = null;
NormalTaskListenerInterface<TASK> listener = null;
if (mObservers.get(key) != null) {
if (taskType == ITask.DOWNLOAD) {
listener = (NormalTaskListener<TASK>) listeners.get(TaskEnum.DOWNLOAD);
listener = (NormalTaskListenerInterface<TASK>) listeners.get(TaskEnum.DOWNLOAD);
} else if (taskType == ITask.DOWNLOAD_GROUP) {
listener = (NormalTaskListener<TASK>) listeners.get(TaskEnum.DOWNLOAD_GROUP);
listener = (NormalTaskListenerInterface<TASK>) listeners.get(TaskEnum.DOWNLOAD_GROUP);
} else if (taskType == ITask.DOWNLOAD_GROUP) {
listener = (NormalTaskListener<TASK>) listeners.get(TaskEnum.UPLOAD);
listener = (NormalTaskListenerInterface<TASK>) listeners.get(TaskEnum.UPLOAD);
}
}
if (listener != null) {
@@ -399,18 +404,18 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
if (mObservers.size() > 0) {
Set<String> keys = mObservers.keySet();
for (String key : keys) {
Map<TaskEnum, ISchedulerListener> listeners = mObservers.get(key);
Map<TaskEnum, Object> listeners = mObservers.get(key);
if (listeners == null || listeners.isEmpty()) {
continue;
}
NormalTaskListener<TASK> listener = null;
NormalTaskListenerInterface<TASK> listener = null;
if (mObservers.get(key) != null) {
if (task instanceof DownloadTask) {
listener = (NormalTaskListener<TASK>) listeners.get(TaskEnum.DOWNLOAD);
listener = (NormalTaskListenerInterface<TASK>) listeners.get(TaskEnum.DOWNLOAD);
} else if (task instanceof DownloadGroupTask) {
listener = (NormalTaskListener<TASK>) listeners.get(TaskEnum.DOWNLOAD_GROUP);
listener = (NormalTaskListenerInterface<TASK>) listeners.get(TaskEnum.DOWNLOAD_GROUP);
} else if (task instanceof UploadTask) {
listener = (NormalTaskListener<TASK>) listeners.get(TaskEnum.UPLOAD);
listener = (NormalTaskListenerInterface<TASK>) listeners.get(TaskEnum.UPLOAD);
}
}
if (listener != null) {
@@ -420,7 +425,7 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
}
}
private void normalTaskCallback(int state, TASK task, NormalTaskListener<TASK> listener) {
private void normalTaskCallback(int state, TASK task, NormalTaskListenerInterface<TASK> listener) {
if (listener != null) {
if (task == null && state != ISchedulers.CHECK_FAIL) {
ALog.e(TAG, "TASK 为null回调失败");
@@ -497,6 +502,7 @@ public class TaskSchedulers<TASK extends ITask> implements ISchedulers {
*/
private Intent createData(int taskState, int taskType, AbsEntity entity) {
Intent intent = new Intent(ISchedulers.ARIA_TASK_INFO_ACTION);
intent.setPackage(mAriaConfig.getAPP().getPackageName());
Bundle b = new Bundle();
b.putInt(ISchedulers.TASK_TYPE, taskType);
b.putInt(ISchedulers.TASK_STATE, taskState);

View File

@@ -29,6 +29,7 @@ import com.arialyy.aria.core.event.EventMsgUtil;
import com.arialyy.aria.core.inf.AbsReceiver;
import com.arialyy.aria.core.inf.ReceiverType;
import com.arialyy.aria.core.queue.UTaskQueue;
import com.arialyy.aria.core.scheduler.TaskInternalListenerInterface;
import com.arialyy.aria.core.scheduler.TaskSchedulers;
import com.arialyy.aria.core.task.ITask;
import com.arialyy.aria.core.upload.target.FtpBuilderTarget;
@@ -48,7 +49,9 @@ import java.util.Set;
* 上传功能接收器
*/
public class UploadReceiver extends AbsReceiver {
private static final String TAG = "UploadReceiver";
public UploadReceiver(Object obj) {
super(obj);
}
/**
* 设置最大上传速度单位kb
@@ -264,11 +267,17 @@ public class UploadReceiver extends AbsReceiver {
* 将当前类注册到Aria
*/
public void register() {
Object obj = OBJ_MAP.get(getKey());
if (obj == null) {
ALog.e(TAG, String.format("【%s】观察者为空", getTargetName()));
return;
}
if (obj instanceof TaskInternalListenerInterface){
if (obj instanceof UploadTaskListener){
TaskSchedulers.getInstance().register(obj, TaskEnum.UPLOAD);
}
return;
}
Set<Integer> set = ProxyHelper.getInstance().checkProxyType(obj.getClass());
if (set != null && !set.isEmpty()) {
for (Integer type : set) {
@@ -286,18 +295,17 @@ public class UploadReceiver extends AbsReceiver {
* 如果是Dialog或popupwindow需要你在撤销界面时调用该方法
*/
@Override public void unRegister() {
if (needRmListener) {
if (isNeedRmListener()) {
unRegisterListener();
}
AriaManager.getInstance().removeReceiver(OBJ_MAP.get(getKey()));
AriaManager.getInstance().removeReceiver(obj);
}
@Override public String getType() {
@Override public ReceiverType getType() {
return ReceiverType.UPLOAD;
}
@Override protected void unRegisterListener() {
Object obj = OBJ_MAP.get(getKey());
if (obj == null) {
ALog.e(TAG, String.format("【%s】观察者为空", getTargetName()));
return;

View File

@@ -0,0 +1,28 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.upload;
import com.arialyy.aria.core.scheduler.NormalTaskListenerInterface;
import com.arialyy.aria.core.task.UploadTask;
/**
* 上传任务接口
*
* @author ChenFei(chenfei0928 @ gmail.com)
* @date 2020-07-07 13:23
*/
public interface UploadTaskListener extends NormalTaskListenerInterface<UploadTask> {
}

View File

@@ -21,15 +21,15 @@ package com.arialyy.annotations;
*/
public enum TaskEnum {
DOWNLOAD("com.arialyy.aria.core.task", "DownloadTask", "$$DownloadListenerProxy",
"NormalTaskListener"),
"AptNormalTaskListener"),
DOWNLOAD_GROUP("com.arialyy.aria.core.task", "DownloadGroupTask",
"$$DownloadGroupListenerProxy", "NormalTaskListener"),
"$$DownloadGroupListenerProxy", "AptNormalTaskListener"),
DOWNLOAD_GROUP_SUB("com.arialyy.aria.core.task", "DownloadGroupTask",
"$$DGSubListenerProxy", "SubTaskListener"),
"$$DGSubListenerProxy", "AptSubTaskListener"),
UPLOAD("com.arialyy.aria.core.task", "UploadTask", "$$UploadListenerProxy",
"NormalTaskListener"),
"AptNormalTaskListener"),
M3U8_PEER("com.arialyy.aria.core.task", "DownloadTask", "$$M3U8PeerListenerProxy",
"M3U8PeerTaskListener");
"AptM3U8PeerTaskListener");
public String pkg, className, proxySuffix, proxySuperClass;

View File

@@ -1,4 +1,30 @@
## 开发日志
+ v_3.8.12 (2020/8/15)
- 修复一个正则表达式导致的文件名保存号异常问题 https://github.com/AriaLyy/Aria/issues/715
- 修复一个匿名内部类中的内存溢出的问题 https://github.com/AriaLyy/Aria/issues/705
- 修复同一个url地址的任务提示路径冲突的问题
- 修复m3u8任务地址错误时无法删除实体的问题 https://github.com/AriaLyy/Aria/issues/712
- 修复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
+ v_3.8.10 (2020/6/26)
- fix bug https://github.com/AriaLyy/Aria/issues/703
- fix bug https://github.com/AriaLyy/Aria/issues/702
- fix bug https://github.com/AriaLyy/Aria/issues/695
+ v_3.8.9 (2020/6/14)
- fix bug https://github.com/AriaLyy/Aria/issues/688
- fix bug https://github.com/AriaLyy/Aria/issues/690
- m3u8任务增加`setUseDefConvert()`方法用于处理默认的m3u8任务
+ v_3.8.8 (2020/6/7)
- 修复设置了cancel(false),文件还是被删除的问题 https://github.com/AriaLyy/Aria/issues/686
- 修复错误url的下载任务无法删除的问题 https://github.com/AriaLyy/Aria/issues/684
+ v_3.8.7 (2020/5/25)
- 修复组合任务单个子任务失败后,重新恢复组合任务,组合任务状态变为完成的问题
- 修复40x错误会继续重试并且无法重试成功的问题 https://github.com/AriaLyy/Aria/issues/619

View File

@@ -1,292 +1,173 @@
# Aria
![图标](https://github.com/AriaLyy/DownloadUtil/blob/master/app/src/main/res/mipmap-hdpi/ic_launcher.png)</br>
![图标](https://github.com/AriaLyy/DownloadUtil/blob/master/img/ic_launcher.png)</br>
## [ENGLISH DOC](https://github.com/AriaLyy/Aria/blob/master/ENGLISH_README.md)</br>
## [中文文档](https://aria.laoyuyu.me/aria_doc)
The Aria project originated from the need for file download management encountered in work. At that time, the pain of being downloaded was unhappy. Since then, a simple and easy-to-use, stable and efficient download framework has emerged. Aria has experienced 1.0 to 3.0 development. , It is getting closer and closer to the goal set at the beginning.
## [中文文档](https://github.com/AriaLyy/Aria/blob/master/CHINESE_README.md)
Aria project is from the moment taht the work encountered in a file download management needs adn i was tortured at the time of the pain.</br>
Since then i have a idea which is to program a simple and easy to use,stable and efficient download framework.
Aria experienced 1.0 to 3.0 development, be more and more close to the original set by the target.
Aria has the following characteristics
+ simple and convenient
- can be used in Activity, Service, Fragment, Dialog, popupWindow, Notification and other components
- support the task of automatic scheduling, the user does not need to care about the state of the task switch logic
- [Through the Aria event, it is easy to get the download status of the current download task](#status)
- [a code plus can get the current download speed](#interface)
- [a code can be dynamically set the maximum number of downloads](#parameters)
- [code to achieve speed limit](#interface)
- [It is easy to modify the number of download threads by modifying the configuration file](https://github.com/AriaLyy/Aria/blob/master/app/src/main/assets/aria_config.xml)
- [priority to download a task](#interface)
Aria has the following characteristics:
+ Simple and convenient
- Can be used in Activity, Service, Fragment, Dialog, popupWindow, Notification and other components
- Support HTTP\FTP resumable download, multi-task automatic scheduling
- Support multi-file package download, multi-file sharing the same progress (eg: video + cover + subtitles)
- Support downloading FTP folder
- Support HTTP form upload
- Support file FTP resumable upload
- Support FTPS resumable upload, [see](https://aria.laoyuyu.me/aria_doc/api/ftp_params.html#%E4%BA%8C%E3%80%81ftps)
- Support SFTP resumable upload, [sftp download](https://aria.laoyuyu.me/aria_doc/download/sftp_normal.html), [sftp upload](https://aria.laoyuyu.me/aria_doc/upload /sftp_normal.html)
+ Support https address download
- It is easy to set the CA certificate information in the configuration file
+ Support 300,301,302 redirect download link download
+ Support upload operation
+ Support [Multi-threaded download in blocks](https://aria.laoyuyu.me/aria_doc/start/config.html), which can more effectively play the machine IO performance
+ Support 300, 301, 302 redirect download link download
+ Support file download of m3u8 and hls protocol [m3u8 download](https://aria.laoyuyu.me/aria_doc/download/m3u8.html)
+ Support m3u8 download support, [click to view details](https://aria.laoyuyu.me/aria_doc/download/m3u8_vod.html)
+ The download support file length increases dynamically, and the file download initialization will no longer occupy too much memory space, see [Dynamic Length Configuration](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)
How do we to use Aria?
* [download](#Using)
* [upload](#Upload) s
[How to use Aria?] (#use)
If you think Aria is helpful to you, your star and issues will be my greatest support. Of course, you are also very welcome to PR, [PR Method](https://www.zhihu.com/question/21682976/answer /79489643)`^_^`
## Example
* Multitask download
![Multitask download](https://github.com/AriaLyy/DownloadUtil/blob/master/img/download_img.gif)
* Speed limit
![网速下载限制](https://github.com/AriaLyy/DownloadUtil/blob/master/img/max_speed.gif)
* Multi-file package download
<img src="https://github.com/AriaLyy/DownloadUtil/blob/master/img/group_task.gif" width="360" height="640"/>
* m3u8 download
![m3u8点播文件边下边看](https://github.com/AriaLyy/Aria/blob/master/img/m3u8VodDownload.gif)
## Lib
[![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.10-blue)](https://github.com/AriaLyy/Aria)
[![Compiler](https://img.shields.io/badge/Compiler-3.8.10-blue)](https://github.com/AriaLyy/Aria)
[![FtpComponent](https://img.shields.io/badge/FtpComponent-3.8.10-orange)](https://github.com/AriaLyy/Aria)
[![FtpComponent](https://img.shields.io/badge/SFtpComponent-3.8.10-orange)](https://github.com/AriaLyy/Aria)
[![M3U8Component](https://img.shields.io/badge/M3U8Component-3.8.10-orange)](https://github.com/AriaLyy/Aria)
If you feel that Aria is helpful to you, your star and issues will be the greatest support for me.`^_^`
## Download
[![Download](https://api.bintray.com/packages/arialyy/maven/AriaApi/images/download.svg)](https://bintray.com/arialyy/maven/AriaApi/_latestVersion)
[![Download](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.2.0'
annotationProcessor 'com.arialyy.aria:aria-compiler:3.2.0'
implementation 'com.arialyy.aria:core:3.8.10'
annotationProcessor 'com.arialyy.aria:compiler:3.8.10'
implementation 'com.arialyy.aria:ftpComponent:3.8.10' # If you need to use ftp, please add this component
implementation 'com.arialyy.aria:sftpComponent:3.8.10' # If you need to use sftp, please add this component
implementation 'com.arialyy.aria:m3u8Component:3.8.10' # If you need to use the m3u8 download function, please add this component
```
## For example
![Multi-task download](https://github.com/AriaLyy/DownloadUtil/blob/master/img/download_img.gif)
![download speed limit](https://github.com/AriaLyy/DownloadUtil/blob/master/img/max_speed.gif)
If you are using Kotlin, please use the official method provided by Kotlin to configure apt, [kotlin kapt official configuration portal](https://www.kotlincn.net/docs/reference/kapt.html)
## performance
![Performance display](https://github.com/AriaLyy/DownloadUtil/blob/master/img/performance.png)
__Note: When the version below 3.5.4 is upgraded, the [configuration file] needs to be updated(https://aria.laoyuyu.me/aria_doc/start/config.html)__
__Note: Version 3.8 and above have been adapted to AndroidX and support libraries can be used
***
## Using
Since Aria involves the operation of files and networks, you need to add the following permissions to the manifest file.
## Use
Because Aria involves file and network operations, you need to add the following permissions to the manifest file. If you want to use Aria in a system above 6.0, you need to dynamically apply for file system read and write permissions to the Android system, [How to use Android system permissions](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.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
```
## Use Aria to download
* Add a task (do not download), when other download tasks are completed, will automatically download the waiting task
## Use Aria
### Basic use
The example is a single-task download, only a very simple code is needed to realize the download function.
* Create task
```java
long taskId = Aria.download(this)
.load(DOWNLOAD_URL) //Read download address
.setFilePath(DOWNLOAD_PATH) //Set the full path where the file is saved
.create(); //Create and start download
```
* Stop\Resume task
```java
Aria.download(this)
.load(DOWNLOAD_URL)
.setDownloadPath(DOWNLOAD_PATH) //file save path
.add();
.load(taskId) //task id
.stop(); // stop task
//.resume(); // resume task
```
* download
```java
Aria.download(this)
.load(DOWNLOAD_URL) //load download url
.setDownloadPath(DOWNLOAD_PATH) //file save path
.start(); //start download
```
* Pause
```java
Aria.download(this).load(DOWNLOAD_URL).pause();
```
* Resume download
```java
Aria.download(this).load(DOWNLOAD_URL).resume();
```
* Cancel download
```java
Aria.download(this).load(DOWNLOAD_URL).cancel();
```
### status
If you want to read the download progress or download the information, then you need to create an event class and register the event class into the Aria manager in the onResume (Activity, Fragment) or constructor (Dialog, PopupWindow).
### Obtaining task status
Based on the consideration of decoupling, the download function of Aria is separated from the state acquisition, and the state acquisition will not be integrated into the chain code, but Aria provides another simpler and more flexible solution.
Through annotations, you can easily get all the status of the task.
1. Register the object to Aria
`Aria.download(this).register();` or `Aria.upload(this).register();`
```java
@Override
protected void onCreate(Bundle savedInstanceState) {
```java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Aria.download(this).register();
}
```
2. Use`@Download` or `@Upload` to annotate your function<br>
**note**
- Annotation is done by using `Apt`, so you do not need to worry that this will affect your machine's performance
- The annotated method**can not be modified by private**
- The annotated method**can have only one argument, and the parameter type must be either`DownloadTask` or `UploadTask`**
- Method name can be any string
3. In addition to using annotation methods in widget (Activity, Fragment, Dialog, Popupwindow), you can also use annotation functions in components such as Service, Notification, and so on.
```java
@Download.onPre(DOWNLOAD_URL)
protected void onPre(DownloadTask task) {}
@Download.onTaskStart
void taskStart(DownloadTask task) {}
@Download.onTaskRunning
protected void running(DownloadTask task) {}
@Download.onTaskResume
void taskResume(DownloadTask task) {}
@Download.onTaskStop
void taskStop(DownloadTask task) {}
@Download.onTaskCancel
void taskCancel(DownloadTask task) {}
@Download.onTaskFail
void taskFail(DownloadTask task) {}
@Download.onTaskComplete
void taskComplete(DownloadTask task) {}
@Download.onNoSupportBreakPoint
public void onNoSupportBreakPoint(DownloadTask task) {}
```
4. If you want to set up a listener for a single task, or for some specific task.<br>
**Adding a download address for a task in an annotation means that only the task triggers the annotated method.**
```java
@Download.onTaskRunning({
"https://test.xx.apk",
"http://test.xx2.apk"
}) void taskRunning(DownloadTask task) {
mAdapter.setProgress(task.getDownloadEntity());
}
```
In the above exampleonly the download address is`https://test.xx.apk` and `http://test.xx2.apk`will trigger the`taskRunning(DownloadTask task)`method。
### parameters
#### [Configuration file setting parameters](https://github.com/AriaLyy/Aria/blob/master/app/src/main/assets/aria_config.xml)
#### Set the parameters in the code
In addition to the file mode to modify the Aria parameter, the same, you can also modify the code in the Aria parameters</br>
Get the configuration file directly through`Aria.get(this).getDownloadConfig()`or`Aria.get(this).getUploadConfig()`</br>
and then modify the parameters
```java
// 修改最大下载数,调用完成后,立即生效
// 如当前下载任务数是4修改完成后当前任务数会被Aria自动调度任务数
Aria.get(this).getDownloadConfig().setMaxTaskNum(3);
```
### interface
* Stop all tasks
```java
Aria.download(this).stopAllTask();
```
* Restore all stopped tasks
```java
Aria.download(this).resumeAllTask();
```
* Delete all tasks
```java
Aria.download(this).removeAllTask();
```
* Maximum download speed limit
```java
//单位为 kb
Aria.download(this).setMaxSpeed(speed);
```
* Get download speed for current tasks<br>
Speed parameters a bit specialneed to [download the event support](#status)
``` java
@Override public void onTaskRunning(DownloadTask task) {
//If you turn on the speed unit conversion configuration, you can get the download speed with units in the following ways, such as: 1 mb/s
String convertSpeed = task.getConvertSpeed();
//If you have your own unit format, you can get the original byte length by the following method
long speed = task.getSpeed();
}
```
* Get the downloaded file size, the current progress percentage</br>
Likewise, you can also get the downloaded file size in the DownloadTask object
```
@Override public void onTaskRunning(DownloadTask task) {
 //Get the file size
long fileSize = task.getFileSize();
//Get the file size after conversion
String fileSize1 = task.getConvertFileSize();
//The current percentage of progress
int percent = task.getPercent();
2. Obtain task execution status through annotations
**Note: **
- Annotation back is implemented using Apt, so you dont need to worry about this affecting the performance of your machine
- Annotated methods **cannot be modified by private**
- The annotated method ** can only have one parameter, and the parameter type must be `DownloadTask` or `UploadTask` or `DownloadGroupTask`**
- Method name can be any string
```java
//Process the status of the task execution here, such as the refresh of the progress bar
@Download.onTaskRunning protected void running(DownloadTask task) {
if(task.getKey().eques(url)){
....
You can judge whether it is the callback of the specified task by url
}
int p = task.getPercent(); //Task progress percentage
String speed = task.getConvertSpeed(); //Download speed after unit conversion, unit conversion needs to be opened in the configuration file
String speed1 = task.getSpeed(); //Original byte length speed
}
@Download.onTaskComplete void taskComplete(DownloadTask task) {
//Process the status of task completion here
}
```
* Set the high priority task<br>
If you want to give priority to download a task, you can
``` java
Aria.download(this).load(DOWNLOAD_URL).setDownloadPath(PATH).setHighestPriority();
```
### [Document address](https://aria.laoyuyu.me/aria_doc/)
* Set the extension field<br>
Sometimes, you may want to store some of your own data when you download it</br>
**TIP**: If you have more data, or the data is more complex, you can first convert the data to JSON, and then save it to Aria's download entity
```java
Aria.download(this).load(DOWNLOAD_URL).setExtendField(str)
```
## Upload
### Version Log
+ v_3.8.10 (2020/6/26)
- fix bug https://github.com/AriaLyy/Aria/issues/703
- fix bug https://github.com/AriaLyy/Aria/issues/702
- fix bug https://github.com/AriaLyy/Aria/issues/695
* Add a task (add only, do not upload)
[More Version Log](https://github.com/AriaLyy/Aria/blob/master/DEV_LOG.md)
```java
Aria.upload(this)
.load(filePath) //file path
.setUploadUrl(uploadUrl) // upload the path
.setAttachment(fileKey) //The server reads the file's key
.add();
```
* Upload
```java
Aria.upload(this)
.load(filePath) //file path
.setUploadUrl(uploadUrl) //upload the path
.setAttachment(fileKey) //The server reads the file's key
.start();
```
* cancel upload
```java
Aria.upload(this).load(filePath).cancel();
```
## Confused configuration
## Confusion configuration
```
-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>;
}
```
## others
Have any questions that can give me a message in the[issues](https://github.com/AriaLyy/Aria/issues)
## Other
If you have any questions, you can leave me a feedback at [issues](https://github.com/AriaLyy/Aria/issues). </br>
Before submitting an issue, I hope you have checked [wiki](https://aria.laoyuyu.me/aria_doc/) or searched [issues](https://github.com/AriaLyy/Aria/issues). </br>
## Donate
https://paypal.me/arialyy
***
## 后续版本开发规划
* ~~http、scoket断点上传~~
* ~~实现上传队列调度功能~~
## Development log
+ v_3.1.9 Repair the stopAll queue without task when the problem of collapse, increase the function for a single task monitor
+ v_3.1.7 repair some files can not download the bug, increase the apt annotation method, the incident is more simple
+ v_3.1.6 When the task is canceled ontaskCancel callback twice
+ v_3.1.5 Optimize the code structure, increase the priority download task function.
+ v_3.1.4 Repair the fast switching, pause, and restore functions, the probability of re-download problems, add onPre () callback, onPre () used to request the interface before the implementation of interface UI update operation.
+ v_3.1.0 Add the Aria configuration file to optimize the code
+ v_3.0.3 Repair the pause after deleting the task, flashing the problem, add the api to delete the record
+ v_3.0.2 supports 30x redirect link download
+ v_3.0.0 add upload task support to fix some bugs that have been discovered
License
-------

View File

@@ -20,6 +20,10 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError false
}
}
dependencies {

View File

@@ -328,7 +328,7 @@ public abstract class AbsFtpInfoTask<ENTITY extends AbsEntity, TASK_WRAPPER exte
needRetry = needRetry && !CheckUtil.ftpIsBadRequest(client.getReplyCode());
}
callback.onFail(mEntity, new AriaFTPException(TAG, msg), needRetry);
callback.onFail(mEntity, new AriaFTPException(msg), needRetry);
}
}

View File

@@ -105,7 +105,7 @@ public abstract class BaseFtpThreadTaskAdapter extends AbsThreadTaskAdapter {
int reply = client.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
client.disconnect();
fail(new AriaFTPException(TAG,
fail(new AriaFTPException(
String.format("无法连接到ftp服务器错误码为%smsg:%s", reply, client.getReplyString())), false);
return null;
}

View File

@@ -41,7 +41,7 @@ final class FtpDFileInfoTask extends AbsFtpInfoTask<DownloadEntity, DTaskWrapper
@Override protected void handleFile(String remotePath, FTPFile ftpFile) {
super.handleFile(remotePath, ftpFile);
if (!FileUtil.checkMemorySpace(mEntity.getFilePath(), ftpFile.getSize())) {
callback.onFail(mEntity, new AriaFTPException(TAG,
callback.onFail(mEntity, new AriaFTPException(
String.format("获取ftp文件信息失败内存空间不足, filePath: %s", mEntity.getFilePath())),
false);
}

View File

@@ -45,7 +45,9 @@ final class FtpDGLoader extends AbsGroupLoader {
@Override
protected AbsSubDLoadUtil createSubLoader(DTaskWrapper wrapper, boolean needGetFileInfo) {
return new FtpSubDLoaderUtil(wrapper, getScheduler(), needGetFileInfo, getKey());
FtpSubDLoaderUtil subUtil = new FtpSubDLoaderUtil(getScheduler(), needGetFileInfo, getKey());
subUtil.setParams(wrapper, null);
return subUtil;
}
/**

View File

@@ -18,7 +18,6 @@ package com.arialyy.aria.ftp.download;
import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.group.AbsGroupLoader;
import com.arialyy.aria.core.group.AbsGroupLoaderUtil;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.loader.LoaderStructure;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.ftp.FtpTaskOption;
@@ -29,13 +28,12 @@ import com.arialyy.aria.ftp.FtpTaskOption;
*/
public final class FtpDGLoaderUtil extends AbsGroupLoaderUtil {
public FtpDGLoaderUtil(AbsTaskWrapper wrapper, IEventListener listener) {
super(wrapper, listener);
wrapper.generateTaskOption(FtpTaskOption.class);
}
@Override protected AbsGroupLoader getLoader() {
return mLoader == null ? new FtpDGLoader(getTaskWrapper(), getListener()) : mLoader;
if (mLoader == null) {
((AbsTaskWrapper) getTaskWrapper()).generateTaskOption(FtpTaskOption.class);
mLoader = new FtpDGLoader((AbsTaskWrapper) getTaskWrapper(), getListener());
}
return mLoader;
}
@Override protected LoaderStructure buildLoaderStructure() {

View File

@@ -16,14 +16,12 @@
package com.arialyy.aria.ftp.download;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.loader.AbsNormalLoader;
import com.arialyy.aria.core.loader.AbsNormalLoaderUtil;
import com.arialyy.aria.core.loader.LoaderStructure;
import com.arialyy.aria.core.loader.NormalLoader;
import com.arialyy.aria.core.loader.NormalTTBuilder;
import com.arialyy.aria.core.loader.NormalThreadStateManager;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.ftp.FtpTaskOption;
/**
@@ -32,13 +30,12 @@ import com.arialyy.aria.ftp.FtpTaskOption;
*/
public final class FtpDLoaderUtil extends AbsNormalLoaderUtil {
public FtpDLoaderUtil(AbsTaskWrapper wrapper, IEventListener listener) {
super(wrapper, listener);
wrapper.generateTaskOption(FtpTaskOption.class);
}
@Override public AbsNormalLoader getLoader() {
return mLoader == null ? new NormalLoader(getTaskWrapper(), getListener()) : mLoader;
if (mLoader == null){
getTaskWrapper().generateTaskOption(FtpTaskOption.class);
mLoader = new NormalLoader(getTaskWrapper(), getListener());
}
return mLoader ;
}
public LoaderStructure BuildLoaderStructure() {

View File

@@ -56,7 +56,7 @@ final class FtpDThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
getThreadRecord().endLocation));
client = createClient();
if (client == null) {
fail(new AriaFTPException(TAG, "ftp client 创建失败"), false);
fail(new AriaFTPException("ftp client 创建失败"), false);
return;
}
if (getThreadRecord().startLocation > 0) {
@@ -65,7 +65,7 @@ final class FtpDThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
//发送第二次指令时,还需要再做一次判断
int reply = client.getReplyCode();
if (!FTPReply.isPositivePreliminary(reply) && reply != FTPReply.COMMAND_OK) {
fail(new AriaFTPException(TAG,
fail(new AriaFTPException(
String.format("获取文件信息错误,错误码为:%smsg%s", reply, client.getReplyString())), false);
client.disconnect();
return;
@@ -76,7 +76,7 @@ final class FtpDThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
is = client.retrieveFileStream(remotePath);
reply = client.getReplyCode();
if (!FTPReply.isPositivePreliminary(reply)) {
fail(new AriaFTPException(TAG,
fail(new AriaFTPException(
String.format("获取流失败,错误码为:%smsg%s", reply, client.getReplyString())), true);
client.disconnect();
return;
@@ -89,9 +89,9 @@ final class FtpDThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
handleComplete();
}
} catch (IOException e) {
fail(new AriaFTPException(TAG, String.format("下载失败【%s】", getThreadConfig().url), e), true);
fail(new AriaFTPException(String.format("下载失败【%s】", getThreadConfig().url), e), true);
} catch (Exception e) {
fail(new AriaFTPException(TAG, String.format("下载失败【%s】", getThreadConfig().url), e), false);
fail(new AriaFTPException(String.format("下载失败【%s】", getThreadConfig().url), e), false);
} finally {
try {
if (is != null) {
@@ -153,7 +153,7 @@ final class FtpDThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
}
handleComplete();
} catch (IOException e) {
fail(new AriaFTPException(TAG, String.format("下载失败【%s】", getThreadConfig().url), e), true);
fail(new AriaFTPException(String.format("下载失败【%s】", getThreadConfig().url), e), true);
} finally {
try {
if (fos != null) {
@@ -203,7 +203,7 @@ final class FtpDThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
}
}
} catch (IOException e) {
fail(new AriaFTPException(TAG, String.format("下载失败【%s】", getThreadConfig().url), e), true);
fail(new AriaFTPException(String.format("下载失败【%s】", getThreadConfig().url), e), true);
} finally {
try {
if (file != null) {

View File

@@ -32,9 +32,8 @@ final class FtpSubDLoaderUtil extends AbsSubDLoadUtil {
* @param schedulers 调度器
* @param needGetInfo {@code true} 需要获取文件信息。{@code false} 不需要获取文件信息
*/
FtpSubDLoaderUtil(DTaskWrapper taskWrapper, Handler schedulers, boolean needGetInfo,
String parentKey) {
super(taskWrapper, schedulers, needGetInfo, parentKey);
FtpSubDLoaderUtil(Handler schedulers, boolean needGetInfo, String parentKey) {
super(schedulers, needGetInfo, parentKey);
}
@Override protected SubLoader getLoader() {

View File

@@ -17,7 +17,6 @@ package com.arialyy.aria.ftp.upload;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.common.SubThreadConfig;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.loader.AbsNormalLoader;
import com.arialyy.aria.core.loader.AbsNormalLoaderUtil;
import com.arialyy.aria.core.loader.AbsNormalTTBuilderAdapter;
@@ -26,7 +25,6 @@ import com.arialyy.aria.core.loader.NormalTTBuilder;
import com.arialyy.aria.core.loader.NormalThreadStateManager;
import com.arialyy.aria.core.task.IThreadTaskAdapter;
import com.arialyy.aria.core.upload.UTaskWrapper;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.ftp.FtpTaskOption;
/**
@@ -35,14 +33,12 @@ import com.arialyy.aria.ftp.FtpTaskOption;
*/
public final class FtpULoaderUtil extends AbsNormalLoaderUtil {
public FtpULoaderUtil(AbsTaskWrapper wrapper, IEventListener listener) {
super(wrapper, listener);
wrapper.generateTaskOption(FtpTaskOption.class);
}
@Override public AbsNormalLoader getLoader() {
return mLoader == null ? new FtpULoader((UTaskWrapper) getTaskWrapper(), getListener())
: mLoader;
if (mLoader == null) {
getTaskWrapper().generateTaskOption(FtpTaskOption.class);
mLoader = new FtpULoader((UTaskWrapper) getTaskWrapper(), getListener());
}
return mLoader;
}
@Override public LoaderStructure BuildLoaderStructure() {

View File

@@ -67,7 +67,7 @@ final class FtpUThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
client.setRestartOffset(getThreadRecord().startLocation);
int reply = client.getReplyCode();
if (!FTPReply.isPositivePreliminary(reply) && reply != FTPReply.FILE_ACTION_OK) {
fail(new AriaFTPException(TAG,
fail(new AriaFTPException(
String.format("文件上传错误,错误码为:%s, msg%s, filePath: %s", reply,
client.getReplyString(), getEntity().getFilePath())), false);
client.disconnect();
@@ -85,7 +85,7 @@ final class FtpUThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
return;
}
if (!complete) {
fail(new AriaFTPException(TAG, "ftp文件上传失败"), false);
fail(new AriaFTPException("ftp文件上传失败"), false);
return;
}
ALog.i(TAG,
@@ -93,11 +93,11 @@ final class FtpUThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
complete();
} catch (IOException e) {
e.printStackTrace();
fail(new AriaFTPException(TAG,
fail(new AriaFTPException(
String.format("上传失败filePath: %s, uploadUrl: %s", getEntity().getFilePath(),
getThreadConfig().url)), true);
} catch (Exception e) {
fail(new AriaFTPException(TAG, null, e), false);
fail(new AriaFTPException(null, e), false);
} finally {
try {
if (file != null) {
@@ -136,7 +136,7 @@ final class FtpUThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
@Override public void run() {
try {
if (isTimeOut) {
fail(new AriaFTPException(TAG, "socket连接失败该问题一般出现于网络断开客户端重新连接"
fail(new AriaFTPException("socket连接失败该问题一般出现于网络断开客户端重新连接"
+ "但是服务器端无法创建socket缺没有返回错误码的情况。"), false);
if (fa != null) {
fa.close();
@@ -199,7 +199,7 @@ final class FtpUThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
if (e.getMessage().contains("AriaIOException caught while copying")) {
e.printStackTrace();
} else {
fail(new AriaFTPException(TAG, msg, e), !storeSuccess);
fail(new AriaFTPException(msg, e), !storeSuccess);
}
return false;
} finally {
@@ -208,7 +208,7 @@ final class FtpUThreadTaskAdapter extends BaseFtpThreadTaskAdapter {
int reply = client.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
if (reply != FTPReply.TRANSFER_ABORTED) {
fail(new AriaFTPException(TAG,
fail(new AriaFTPException(
String.format("文件上传错误,错误码为:%s, msg%s, filePath: %s", reply, client.getReplyString(),
getEntity().getFilePath())), false);
}

View File

@@ -0,0 +1,3 @@
com.arialyy.aria.ftp.download.FtpDLoaderUtil
com.arialyy.aria.ftp.download.FtpDGLoaderUtil
com.arialyy.aria.ftp.upload.FtpULoaderUtil

View File

@@ -19,6 +19,10 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError false
}
}
dependencies {

View File

@@ -19,6 +19,7 @@ import android.net.TrafficStats;
import android.net.Uri;
import android.os.Process;
import android.text.TextUtils;
import android.util.Log;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.core.common.RequestEnum;
@@ -80,11 +81,15 @@ final class HttpDFileInfoTask implements IInfoTask, Runnable {
conn = ConnectionHelp.handleConnection(url, taskOption);
ConnectionHelp.setConnectParam(taskOption, conn);
conn.setRequestProperty("Range", "bytes=" + 0 + "-");
if (AriaConfig.getInstance().getDConfig().isUseHeadRequest()){
ALog.d(TAG, "head请求");
conn.setRequestMethod("HEAD");
}
conn.setConnectTimeout(mConnectTimeOut);
conn.connect();
handleConnect(conn);
} catch (IOException e) {
failDownload(new AriaHTTPException(TAG,
failDownload(new AriaHTTPException(
String.format("下载失败filePath: %s, url: %s", mEntity.getFilePath(), mEntity.getUrl()),
e), true);
} finally {
@@ -133,7 +138,7 @@ final class HttpDFileInfoTask implements IInfoTask, Runnable {
long len = lenAdapter.handleFileLen(conn.getHeaderFields());
if (!FileUtil.checkMemorySpace(mEntity.getFilePath(), len)) {
failDownload(new AriaHTTPException(TAG,
failDownload(new AriaHTTPException(
String.format("下载失败内存空间不足filePath: %s, url: %s", mEntity.getFilePath(),
mEntity.getUrl())), false);
return;
@@ -183,8 +188,7 @@ final class HttpDFileInfoTask implements IInfoTask, Runnable {
if (!checkLen(len) && !isChunked) {
if (len < 0) {
failDownload(
new AriaHTTPException(TAG,
String.format("任务下载失败文件长度小于0 url: %s", mEntity.getUrl())),
new AriaHTTPException(String.format("任务下载失败文件长度小于0 url: %s", mEntity.getUrl())),
false);
}
return;
@@ -211,7 +215,7 @@ final class HttpDFileInfoTask implements IInfoTask, Runnable {
} else if (!checkLen(len) && !isChunked) {
if (len < 0) {
failDownload(
new AriaHTTPException(TAG,
new AriaHTTPException(
String.format("任务下载失败文件长度小于0 url: %s", mEntity.getUrl())),
false);
}
@@ -228,11 +232,16 @@ final class HttpDFileInfoTask implements IInfoTask, Runnable {
|| code == HttpURLConnection.HTTP_CREATED // 201 跳转
|| code == 307) {
handleUrlReTurn(conn, conn.getHeaderField("Location"));
}else if (code == 416){ // 处理0k长度的文件的情况
ALog.w(TAG, "文件长度为0不支持断点");
mTaskWrapper.setSupportBP(false);
mTaskWrapper.setNewTask(true);
end = true;
} else if (code >= HttpURLConnection.HTTP_BAD_REQUEST) {
failDownload(new AriaHTTPException(TAG,
failDownload(new AriaHTTPException(
String.format("任务下载失败errorCode%s, url: %s", code, mEntity.getUrl())), false);
} else {
failDownload(new AriaHTTPException(TAG,
failDownload(new AriaHTTPException(
String.format("任务下载失败errorCode%s, errorMsg: %s, url: %s", code,
conn.getResponseMessage(), mEntity.getUrl())), !CheckUtil.httpIsBadRequest(code));
}
@@ -311,7 +320,7 @@ final class HttpDFileInfoTask implements IInfoTask, Runnable {
ALog.d(TAG, "30x跳转新url为【" + newUrl + "");
if (TextUtils.isEmpty(newUrl) || newUrl.equalsIgnoreCase("null")) {
if (callback != null) {
callback.onFail(mEntity, new AriaHTTPException(TAG, "获取重定向链接失败"), false);
callback.onFail(mEntity, new AriaHTTPException("获取重定向链接失败"), false);
}
return;
}
@@ -321,7 +330,7 @@ final class HttpDFileInfoTask implements IInfoTask, Runnable {
}
if (!CheckUtil.checkUrl(newUrl)) {
failDownload(new AriaHTTPException(TAG, "下载失败重定向url错误"), false);
failDownload(new AriaHTTPException("下载失败重定向url错误"), false);
return;
}
taskOption.setRedirectUrl(newUrl);
@@ -334,6 +343,9 @@ final class HttpDFileInfoTask implements IInfoTask, Runnable {
ConnectionHelp.setConnectParam(taskOption, conn);
conn.setRequestProperty("Cookie", cookies);
conn.setRequestProperty("Range", "bytes=" + 0 + "-");
if (AriaConfig.getInstance().getDConfig().isUseHeadRequest()){
conn.setRequestMethod("HEAD");
}
conn.setConnectTimeout(mConnectTimeOut);
conn.connect();
handleConnect(conn);

View File

@@ -60,7 +60,7 @@ public final class HttpDGInfoTask implements IInfoTask {
ALog.e(TAG, String.format("获取文件信息失败url%s", ((DownloadEntity) entity).getUrl()));
count.getAndIncrement();
failCount.getAndIncrement();
listener.onSubFail((DownloadEntity) entity, new AriaHTTPException(TAG,
listener.onSubFail((DownloadEntity) entity, new AriaHTTPException(
String.format("子任务获取文件长度失败url%s", ((DownloadEntity) entity).getUrl())));
checkGetSizeComplete(count.get(), failCount.get());
}
@@ -111,7 +111,7 @@ public final class HttpDGInfoTask implements IInfoTask {
DownloadEntity subEntity = dTaskWrapper.getEntity();
if (subEntity.getFileSize() > 0) {
count.getAndIncrement();
if (subEntity.getCurrentProgress() < subEntity.getFileSize()){
if (subEntity.getCurrentProgress() < subEntity.getFileSize()) {
// 如果没有完成需要拷贝一份数据
cloneHeader(dTaskWrapper);
}
@@ -132,7 +132,7 @@ public final class HttpDGInfoTask implements IInfoTask {
*/
private void checkGetSizeComplete(int count, int failCount) {
if (failCount == wrapper.getSubTaskWrapper().size()) {
callback.onFail(wrapper.getEntity(), new AriaHTTPException(TAG, "获取子任务长度失败"), false);
callback.onFail(wrapper.getEntity(), new AriaHTTPException("获取子任务长度失败"), false);
notifyLock();
return;
}

View File

@@ -45,7 +45,9 @@ final class HttpDGLoader extends AbsGroupLoader {
@Override
protected AbsSubDLoadUtil createSubLoader(DTaskWrapper wrapper, boolean needGetFileInfo) {
return new HttpSubDLoaderUtil(wrapper, getScheduler(), needGetFileInfo, getKey());
HttpSubDLoaderUtil subUtil = new HttpSubDLoaderUtil(getScheduler(), needGetFileInfo, getKey());
subUtil.setParams(wrapper, null);
return subUtil;
}
private void startSub() {

View File

@@ -19,9 +19,7 @@ import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.group.AbsGroupLoader;
import com.arialyy.aria.core.group.AbsGroupLoaderUtil;
import com.arialyy.aria.core.listener.DownloadGroupListener;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.loader.LoaderStructure;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.http.HttpTaskOption;
/**
@@ -30,14 +28,12 @@ import com.arialyy.aria.http.HttpTaskOption;
*/
public final class HttpDGLoaderUtil extends AbsGroupLoaderUtil {
public HttpDGLoaderUtil(AbsTaskWrapper taskWrapper, IEventListener listener) {
super(taskWrapper, listener);
taskWrapper.generateTaskOption(HttpTaskOption.class);
}
@Override protected AbsGroupLoader getLoader() {
return mLoader == null ? new HttpDGLoader(getTaskWrapper(),
(DownloadGroupListener) getListener()) : mLoader;
if (mLoader == null) {
getTaskWrapper().generateTaskOption(HttpTaskOption.class);
mLoader = new HttpDGLoader(getTaskWrapper(), (DownloadGroupListener) getListener());
}
return mLoader;
}
@Override protected LoaderStructure buildLoaderStructure() {

View File

@@ -24,6 +24,7 @@ import com.arialyy.aria.core.loader.NormalLoader;
import com.arialyy.aria.core.loader.NormalTTBuilder;
import com.arialyy.aria.core.loader.NormalThreadStateManager;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.http.HttpRecordHandler;
import com.arialyy.aria.http.HttpTaskOption;
@@ -32,13 +33,13 @@ import com.arialyy.aria.http.HttpTaskOption;
* @Date 2019-09-21
*/
public final class HttpDLoaderUtil extends AbsNormalLoaderUtil {
public HttpDLoaderUtil(AbsTaskWrapper wrapper, IEventListener listener) {
super(wrapper, listener);
wrapper.generateTaskOption(HttpTaskOption.class);
}
@Override public AbsNormalLoader getLoader() {
return mLoader == null ? new NormalLoader(getTaskWrapper(), getListener()) : mLoader;
if (mLoader == null){
getTaskWrapper().generateTaskOption(HttpTaskOption.class);
mLoader = new NormalLoader(getTaskWrapper(), getListener());
}
return mLoader;
}
public LoaderStructure BuildLoaderStructure() {

View File

@@ -117,21 +117,17 @@ final class HttpDThreadTaskAdapter extends BaseHttpThreadTaskAdapter {
handleComplete();
}
} catch (MalformedURLException e) {
fail(new AriaHTTPException(TAG,
String.format("任务【%s】下载失败filePath: %s, url: %s", getFileName(),
getEntity().getFilePath(), getEntity().getUrl()), e), false);
fail(new AriaHTTPException(String.format("任务【%s】下载失败filePath: %s, url: %s", getFileName(),
getEntity().getFilePath(), getEntity().getUrl()), e), false);
} catch (IOException e) {
fail(new AriaHTTPException(TAG,
String.format("任务【%s】下载失败filePath: %s, url: %s", getFileName(),
getEntity().getFilePath(), getEntity().getUrl()), e), true);
fail(new AriaHTTPException(String.format("任务【%s】下载失败filePath: %s, url: %s", getFileName(),
getEntity().getFilePath(), getEntity().getUrl()), e), true);
} catch (ArrayIndexOutOfBoundsException e) {
fail(new AriaHTTPException(TAG,
String.format("任务【%s】下载失败filePath: %s, url: %s", getFileName(),
getEntity().getFilePath(), getEntity().getUrl()), e), false);
fail(new AriaHTTPException(String.format("任务【%s】下载失败filePath: %s, url: %s", getFileName(),
getEntity().getFilePath(), getEntity().getUrl()), e), false);
} catch (Exception e) {
fail(new AriaHTTPException(TAG,
String.format("任务【%s】下载失败filePath: %s, url: %s", getFileName(),
getEntity().getFilePath(), getEntity().getUrl()), e), false);
fail(new AriaHTTPException(String.format("任务【%s】下载失败filePath: %s, url: %s", getFileName(),
getEntity().getFilePath(), getEntity().getUrl()), e), false);
} finally {
try {
if (file != null) {
@@ -171,7 +167,7 @@ final class HttpDThreadTaskAdapter extends BaseHttpThreadTaskAdapter {
}
handleComplete();
} catch (IOException e) {
fail(new AriaHTTPException(TAG,
fail(new AriaHTTPException(
String.format("文件下载失败savePath: %s, url: %s", getEntity().getFilePath(),
getThreadConfig().url), e), true);
} finally {
@@ -224,8 +220,7 @@ final class HttpDThreadTaskAdapter extends BaseHttpThreadTaskAdapter {
}
handleComplete();
} catch (IOException e) {
fail(new AriaHTTPException(TAG,
String.format("文件下载失败savePath: %s, url: %s", getEntity().getFilePath(),
fail(new AriaHTTPException(String.format("文件下载失败savePath: %s, url: %s", getEntity().getFilePath(),
getThreadConfig().url), e), true);
} finally {
try {

View File

@@ -33,9 +33,8 @@ final class HttpSubDLoaderUtil extends AbsSubDLoadUtil {
* @param schedulers 调度器
* @param needGetInfo {@code true} 需要获取文件信息。{@code false} 不需要获取文件信息
*/
HttpSubDLoaderUtil(DTaskWrapper taskWrapper, Handler schedulers, boolean needGetInfo,
String parentKey) {
super(taskWrapper, schedulers, needGetInfo, parentKey);
HttpSubDLoaderUtil( Handler schedulers, boolean needGetInfo, String parentKey) {
super(schedulers, needGetInfo, parentKey);
}
@Override protected SubLoader getLoader() {

View File

@@ -62,7 +62,7 @@ final class HttpULoader extends AbsNormalLoader<UTaskWrapper> {
new Handler(looper, mStateManager.getHandlerCallback()));
if (tt == null || tt.isEmpty()) {
ALog.e(TAG, "创建线程任务失败");
getListener().onFail(false, new AriaHTTPException(TAG, "创建线程任务失败"));
getListener().onFail(false, new AriaHTTPException("创建线程任务失败"));
return;
}

View File

@@ -17,7 +17,6 @@ package com.arialyy.aria.http.upload;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.common.SubThreadConfig;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.loader.AbsNormalLoader;
import com.arialyy.aria.core.loader.AbsNormalLoaderUtil;
import com.arialyy.aria.core.loader.AbsNormalTTBuilderAdapter;
@@ -26,7 +25,6 @@ import com.arialyy.aria.core.loader.NormalTTBuilder;
import com.arialyy.aria.core.loader.NormalThreadStateManager;
import com.arialyy.aria.core.task.IThreadTaskAdapter;
import com.arialyy.aria.core.upload.UTaskWrapper;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.http.HttpRecordHandler;
import com.arialyy.aria.http.HttpTaskOption;
@@ -35,14 +33,13 @@ import com.arialyy.aria.http.HttpTaskOption;
* @Date 2019-09-19
*/
public final class HttpULoaderUtil extends AbsNormalLoaderUtil {
public HttpULoaderUtil(AbsTaskWrapper wrapper, IEventListener listener) {
super(wrapper, listener);
wrapper.generateTaskOption(HttpTaskOption.class);
}
@Override public AbsNormalLoader getLoader() {
return mLoader == null ? new HttpULoader((UTaskWrapper) getTaskWrapper(), getListener())
: mLoader;
if (mLoader == null) {
getTaskWrapper().generateTaskOption(HttpTaskOption.class);
mLoader = new HttpULoader((UTaskWrapper) getTaskWrapper(), getListener());
}
return mLoader;
}
@Override public LoaderStructure BuildLoaderStructure() {

View File

@@ -20,11 +20,13 @@ import com.arialyy.aria.core.common.SubThreadConfig;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.exception.AriaHTTPException;
import com.arialyy.aria.http.BaseHttpThreadTaskAdapter;
import com.arialyy.aria.http.ConnectionHelp;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
@@ -54,7 +56,7 @@ final class HttpUThreadTaskAdapter extends BaseHttpThreadTaskAdapter {
@Override protected void handlerThreadTask() {
File uploadFile = new File(getEntity().getFilePath());
if (!uploadFile.exists()) {
fail(new AriaHTTPException(TAG,
fail(new AriaHTTPException(
String.format("上传失败文件不存在filePath: %s, url: %s", getEntity().getFilePath(),
getEntity().getUrl())));
return;
@@ -74,7 +76,6 @@ final class HttpUThreadTaskAdapter extends BaseHttpThreadTaskAdapter {
mHttpConn.setRequestProperty("User-Agent", getUserAgent());
mHttpConn.setConnectTimeout(getTaskConfig().getConnectTimeOut());
mHttpConn.setReadTimeout(getTaskConfig().getIOTimeOut());
//mHttpConn.setRequestProperty("Range", "bytes=" + 0 + "-" + "100");
//内部缓冲区---分段上传防止oom
mHttpConn.setChunkedStreamingMode(getTaskConfig().getBuffSize());
@@ -104,7 +105,7 @@ final class HttpUThreadTaskAdapter extends BaseHttpThreadTaskAdapter {
getEntity().setResponseStr(finish(writer));
} catch (Exception e) {
e.printStackTrace();
fail(new AriaHTTPException(TAG,
fail(new AriaHTTPException(
String.format("上传失败filePath: %s, url: %s", getEntity().getFilePath(),
getEntity().getUrl()), e));
}
@@ -122,9 +123,10 @@ final class HttpUThreadTaskAdapter extends BaseHttpThreadTaskAdapter {
}
private String getContentType() {
return (mTaskOption.getHeaders() == null || TextUtils.isEmpty(
mTaskOption.getHeaders().get("Content-Type"))) ? "multipart/form-data"
: mTaskOption.getHeaders().get("Content-Type");
//return (mTaskOption.getHeaders() == null || TextUtils.isEmpty(
// mTaskOption.getHeaders().get("Content-Type"))) ? "multipart/form-data"
// : mTaskOption.getHeaders().get("Content-Type");
return "multipart/form-data";
}
private String getUserAgent() {
@@ -175,23 +177,23 @@ final class HttpUThreadTaskAdapter extends BaseHttpThreadTaskAdapter {
FileInputStream inputStream = new FileInputStream(uploadFile);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
progress(bytesRead);
mOutputStream.write(buffer, 0, bytesRead);
int bytesLen;
while ((bytesLen = inputStream.read(buffer)) != -1) {
mOutputStream.write(buffer, 0, bytesLen);
progress(bytesLen);
if (getThreadTask().isBreak()) {
break;
}
if (mSpeedBandUtil != null) {
mSpeedBandUtil.limitNextBytes(bytesRead);
mSpeedBandUtil.limitNextBytes(bytesLen);
}
}
mOutputStream.flush();
//outputStream.close(); //不能调用,否则服务器端异常
inputStream.close();
writer.append(LINE_END);
writer.flush();
writer.append(LINE_END).flush();
// 保证上传的文件和本地的一致https://www.cnblogs.com/tugenhua0707/p/8975121.html
writer.append(PREFIX).append(BOUNDARY).append(PREFIX).append(LINE_END).flush();
}
/**
@@ -201,15 +203,11 @@ final class HttpUThreadTaskAdapter extends BaseHttpThreadTaskAdapter {
*/
private String finish(PrintWriter writer) throws IOException {
StringBuilder response = new StringBuilder();
writer.append(LINE_END).flush();
writer.append(PREFIX).append(BOUNDARY).append(PREFIX).append(LINE_END);
writer.flush();
int status = mHttpConn.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(mHttpConn.getInputStream()));
BufferedReader reader =
new BufferedReader(new InputStreamReader(ConnectionHelp.convertInputStream(mHttpConn)));
String line;
while (getThreadTask().isLive() && (line = reader.readLine()) != null) {
response.append(line);
@@ -220,7 +218,8 @@ final class HttpUThreadTaskAdapter extends BaseHttpThreadTaskAdapter {
} else {
String msg = "response msg: " + mHttpConn.getResponseMessage() + "code: " + status;
ALog.e(TAG, msg);
fail(new AriaHTTPException(TAG, msg), false);
fail(new AriaHTTPException(msg), false);
response.append(status);
}
writer.flush();
writer.close();

View File

@@ -0,0 +1,3 @@
com.arialyy.aria.http.download.HttpDLoaderUtil
com.arialyy.aria.http.download.HttpDGLoaderUtil
com.arialyy.aria.http.upload.HttpULoaderUtil

View File

@@ -20,6 +20,10 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError false
}
}
dependencies {

View File

@@ -0,0 +1,29 @@
/*
* 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.m3u8;
import com.arialyy.aria.core.processor.IBandWidthUrlConverter;
/**
* 点播文件默认的码率转换器
*/
class BandWidthDefConverter implements IBandWidthUrlConverter {
@Override public String convert(String m3u8Url, String bandWidthUrl) {
int index = m3u8Url.lastIndexOf("/");
return m3u8Url.substring(0, index + 1) + bandWidthUrl;
}
}

View File

@@ -95,7 +95,7 @@ public abstract class BaseM3U8Loader extends AbsNormalLoader<DTaskWrapper> {
i++;
} else if (line.startsWith("#EXT-X-KEY")) {
M3U8Entity m3U8Entity = getEntity().getM3U8Entity();
String keyInfo = String.format("#EXT-X-KEY:METHOD=%s,URI=%s,IV=%s\r\n", m3U8Entity.method,
String keyInfo = String.format("#EXT-X-KEY:METHOD=%s,URI=\"%s\",IV=%s\r\n", m3U8Entity.method,
m3U8Entity.keyPath, m3U8Entity.iv);
bytes = keyInfo.getBytes(Charset.forName("UTF-8"));
} else {

View File

@@ -101,7 +101,7 @@ final public class M3U8InfoTask implements IInfoTask {
ConnectionHelp.setConnectParam(mHttpOption, conn);
conn.setConnectTimeout(mConnectTimeOut);
conn.connect();
handleConnect(conn);
handleConnect(mEntity.getUrl(), conn);
} catch (IOException e) {
failDownload(e.getMessage(), false);
} finally {
@@ -115,10 +115,11 @@ final public class M3U8InfoTask implements IInfoTask {
mCallback = callback;
}
private void handleConnect(HttpURLConnection conn) throws IOException {
private void handleConnect(String tsListUrl, HttpURLConnection conn) throws IOException {
int code = conn.getResponseCode();
if (code == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
BufferedReader reader =
new BufferedReader(new InputStreamReader(ConnectionHelp.convertInputStream(conn)));
String line = reader.readLine();
if (TextUtils.isEmpty(line) || !line.equalsIgnoreCase("#EXTM3U")) {
failDownload("读取M3U8信息失败读取不到#EXTM3U标签", false);
@@ -140,7 +141,7 @@ final public class M3U8InfoTask implements IInfoTask {
}
fos = new FileOutputStream(indexFile);
ALog.d(TAG, line);
addIndexInfo(isGenerateIndexFile, fos, line);
addIndexInfo(true, fos, line);
}
while ((line = reader.readLine()) != null) {
if (isStop) {
@@ -151,7 +152,9 @@ final public class M3U8InfoTask implements IInfoTask {
// 点播文件的下载写入结束标志,直播文件的下载在停止时才写入结束标志
addIndexInfo(isGenerateIndexFile && !isLive, fos, line);
break;
} else if (line.startsWith("#EXTINF")) {
}
if (line.startsWith("#EXTINF")) {
String url = reader.readLine();
if (isLive) {
if (onGetPeerCallback != null) {
@@ -163,7 +166,10 @@ final public class M3U8InfoTask implements IInfoTask {
ALog.d(TAG, url);
addIndexInfo(isGenerateIndexFile && !isLive, fos, line);
addIndexInfo(isGenerateIndexFile && !isLive, fos, url);
} else if (line.startsWith("#EXT-X-STREAM-INF")) {
continue;
}
if (line.startsWith("#EXT-X-STREAM-INF")) {
addIndexInfo(isGenerateIndexFile, fos, line);
int setBand = mM3U8Option.getBandWidth();
int bandWidth = getBandWidth(line);
@@ -179,12 +185,14 @@ final public class M3U8InfoTask implements IInfoTask {
failDownload(String.format("【%s】码率不存在", setBand), false);
}
return;
} else if (line.startsWith("#EXT-X-KEY")) {
addIndexInfo(isGenerateIndexFile, fos, line);
getKeyInfo(line);
} else {
addIndexInfo(isGenerateIndexFile, fos, line);
}
if (line.startsWith("#EXT-X-KEY")) {
addIndexInfo(isGenerateIndexFile, fos, line);
getKeyInfo(tsListUrl, line);
continue;
}
addIndexInfo(isGenerateIndexFile, fos, line);
}
if (!isLive && extInf.isEmpty()) {
@@ -248,7 +256,7 @@ final public class M3U8InfoTask implements IInfoTask {
/**
* 获取加密的密钥信息
*/
private void getKeyInfo(String line) {
private void getKeyInfo(String tsListUrl, String line) {
String temp = line.substring(line.indexOf(":") + 1);
String[] params = temp.split(",");
M3U8Entity m3U8Entity = mEntity.getM3U8Entity();
@@ -273,7 +281,7 @@ final public class M3U8InfoTask implements IInfoTask {
m3U8Entity.keyFormatVersion = param.split("=")[1];
}
}
downloadKey(m3U8Entity);
downloadKey(tsListUrl, m3U8Entity);
}
/**
@@ -295,7 +303,7 @@ final public class M3U8InfoTask implements IInfoTask {
ALog.d(TAG, "30x跳转新url为【" + newUrl + "");
if (TextUtils.isEmpty(newUrl) || newUrl.equalsIgnoreCase("null")) {
if (mCallback != null) {
mCallback.onFail(mEntity, new AriaM3U8Exception(TAG, "获取重定向链接失败"), false);
mCallback.onFail(mEntity, new AriaM3U8Exception("获取重定向链接失败"), false);
}
return;
}
@@ -320,7 +328,7 @@ final public class M3U8InfoTask implements IInfoTask {
conn.setRequestProperty("Cookie", cookies);
conn.setConnectTimeout(mConnectTimeOut);
conn.connect();
handleConnect(conn);
handleConnect(newUrl, conn);
conn.disconnect();
}
@@ -328,9 +336,10 @@ final public class M3U8InfoTask implements IInfoTask {
* 处理码率
*/
private void handleBandWidth(HttpURLConnection conn, String bandWidthM3u8Url) throws IOException {
IBandWidthUrlConverter converter = mM3U8Option.getBandWidthUrlConverter();
IBandWidthUrlConverter converter = mM3U8Option.isUseDefConvert() ? new BandWidthDefConverter()
: mM3U8Option.getBandWidthUrlConverter();
if (converter != null) {
bandWidthM3u8Url = converter.convert(bandWidthM3u8Url);
bandWidthM3u8Url = converter.convert(mEntity.getUrl(), bandWidthM3u8Url);
if (!bandWidthM3u8Url.startsWith("http")) {
failDownload(String.format("码率转换器转换后的url地址无效转换后的url%s", bandWidthM3u8Url), false);
return;
@@ -348,18 +357,18 @@ final public class M3U8InfoTask implements IInfoTask {
conn.setRequestProperty("Cookie", cookies);
conn.setConnectTimeout(mConnectTimeOut);
conn.connect();
handleConnect(conn);
handleConnect(bandWidthM3u8Url, conn);
conn.disconnect();
}
private void failDownload(String errorInfo, boolean needRetry) {
mCallback.onFail(mEntity, new AriaM3U8Exception(TAG, errorInfo), needRetry);
mCallback.onFail(mEntity, new AriaM3U8Exception(errorInfo), needRetry);
}
/**
* 密钥不存在,下载密钥
*/
private void downloadKey(M3U8Entity info) {
private void downloadKey(String tsListUr, M3U8Entity info) {
HttpURLConnection conn = null;
FileOutputStream fos = null;
try {
@@ -374,7 +383,7 @@ final public class M3U8InfoTask implements IInfoTask {
IKeyUrlConverter keyUrlConverter = mM3U8Option.getKeyUrlConverter();
String keyUrl = info.keyUrl;
if (keyUrlConverter != null) {
keyUrl = keyUrlConverter.convert(mEntity.getUrl(), keyUrl);
keyUrl = keyUrlConverter.convert(mEntity.getUrl(), tsListUr, keyUrl);
}
if (TextUtils.isEmpty(keyUrl)) {
ALog.e(TAG, "m3u8密钥key url 为空");
@@ -386,7 +395,7 @@ final public class M3U8InfoTask implements IInfoTask {
ConnectionHelp.setConnectParam(mHttpOption, conn);
conn.setConnectTimeout(mConnectTimeOut);
conn.connect();
InputStream is = conn.getInputStream();
InputStream is = ConnectionHelp.convertInputStream(conn);
fos = new FileOutputStream(keyF);
byte[] buffer = new byte[1024];
int len;

View File

@@ -16,29 +16,20 @@
package com.arialyy.aria.m3u8;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.listener.BaseListener;
import com.arialyy.aria.core.listener.IDLoadListener;
import com.arialyy.aria.core.listener.ISchedulers;
import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.core.task.DownloadTask;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.DeleteM3u8Record;
/**
* 下载监听类
*/
public final class M3U8Listener
extends BaseListener<DownloadEntity, DTaskWrapper, AbsTask<DTaskWrapper>>
implements IDLoadListener {
public M3U8Listener(AbsTask<DTaskWrapper> task, Handler outHandler) {
super(task, outHandler);
}
public final class M3U8Listener extends BaseListener implements IDLoadListener {
@Override
public void onPostPre(long fileSize) {
@@ -88,7 +79,7 @@ public final class M3U8Listener
}
@Override protected void handleCancel() {
int sType = getTask().getSchedulerType();
int sType = getTask(DownloadTask.class).getSchedulerType();
if (sType == TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY) {
mEntity.setComplete(false);
mEntity.setState(IEntity.STATE_WAIT);

View File

@@ -120,6 +120,19 @@ public final class M3U8TaskOption implements ITaskOption {
*/
private String keyPath;
/**
* 是否使用默认的码率转换器和Ts转换器
*/
private boolean useDefConvert = false;
public boolean isUseDefConvert() {
return useDefConvert;
}
public void setUseDefConvert(boolean useDefConvert) {
this.useDefConvert = useDefConvert;
}
public String getKeyPath() {
return keyPath;
}

View File

@@ -91,15 +91,15 @@ public final class M3U8ThreadTaskAdapter extends AbsThreadTaskAdapter {
handleConn(conn);
} catch (MalformedURLException e) {
fail(new AriaM3U8Exception(TAG,
fail(new AriaM3U8Exception(
String.format("分片【%s】下载失败filePath: %s, url: %s", getThreadRecord().threadId,
getThreadConfig().tempFile.getPath(), getEntity().getUrl()), e), false);
} catch (IOException e) {
fail(new AriaM3U8Exception(TAG,
fail(new AriaM3U8Exception(
String.format("分片【%s】下载失败filePath: %s, url: %s", getThreadRecord().threadId,
getThreadConfig().tempFile.getPath(), getEntity().getUrl()), e), true);
} catch (Exception e) {
fail(new AriaM3U8Exception(TAG,
fail(new AriaM3U8Exception(
String.format("分片【%s】下载失败filePath: %s, url: %s", getThreadRecord().threadId,
getThreadConfig().tempFile.getPath(), getEntity().getUrl()), e), false);
} finally {
@@ -137,7 +137,7 @@ public final class M3U8ThreadTaskAdapter extends AbsThreadTaskAdapter {
|| code == 307) {
handleUrlReTurn(conn, conn.getHeaderField("Location"));
} else {
fail(new AriaM3U8Exception(TAG,
fail(new AriaM3U8Exception(
String.format("连接错误http错误码%surl%s", code, getThreadConfig().url)),
false);
}
@@ -150,7 +150,7 @@ public final class M3U8ThreadTaskAdapter extends AbsThreadTaskAdapter {
private void handleUrlReTurn(HttpURLConnection conn, String newUrl) throws IOException {
ALog.d(TAG, "30x跳转新url为【" + newUrl + "");
if (TextUtils.isEmpty(newUrl) || newUrl.equalsIgnoreCase("null")) {
fail(new AriaM3U8Exception(TAG, "下载失败重定向url为空"), false);
fail(new AriaM3U8Exception("下载失败重定向url为空"), false);
return;
}
@@ -160,7 +160,7 @@ public final class M3U8ThreadTaskAdapter extends AbsThreadTaskAdapter {
}
if (!CheckUtil.checkUrl(newUrl)) {
fail(new AriaM3U8Exception(TAG, "下载失败重定向url错误"), false);
fail(new AriaM3U8Exception("下载失败重定向url错误"), false);
return;
}
String cookies = conn.getHeaderField("Set-Cookie");
@@ -198,7 +198,7 @@ public final class M3U8ThreadTaskAdapter extends AbsThreadTaskAdapter {
}
handleComplete();
} catch (IOException e) {
fail(new AriaM3U8Exception(TAG,
fail(new AriaM3U8Exception(
String.format("文件下载失败savePath: %s, url: %s", getThreadConfig().tempFile.getPath(),
getThreadConfig().url), e), true);
} finally {
@@ -241,7 +241,7 @@ public final class M3U8ThreadTaskAdapter extends AbsThreadTaskAdapter {
}
handleComplete();
} catch (IOException e) {
fail(new AriaM3U8Exception(TAG,
fail(new AriaM3U8Exception(
String.format("文件下载失败savePath: %s, url: %s", getThreadConfig().tempFile.getPath(),
getThreadConfig().url), e), true);
} finally {

View File

@@ -0,0 +1,29 @@
/*
* 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.m3u8.live;
import com.arialyy.aria.core.processor.ILiveTsUrlConverter;
/**
* 默认的m3u8 ts转换器
*/
class LiveTsDefConverter implements ILiveTsUrlConverter {
@Override public String convert(String m3u8Url, String tsUrl) {
int index = m3u8Url.lastIndexOf("/");
String parentUrl = m3u8Url.substring(0, index + 1);
return parentUrl + tsUrl;
}
}

View File

@@ -32,8 +32,8 @@ import com.arialyy.aria.core.processor.ILiveTsUrlConverter;
import com.arialyy.aria.core.processor.ITsMergeHandler;
import com.arialyy.aria.core.task.ThreadTask;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.exception.AriaM3U8Exception;
import com.arialyy.aria.exception.AriaException;
import com.arialyy.aria.exception.AriaM3U8Exception;
import com.arialyy.aria.m3u8.BaseM3U8Loader;
import com.arialyy.aria.m3u8.IdGenerator;
import com.arialyy.aria.m3u8.M3U8InfoTask;
@@ -196,6 +196,7 @@ final class M3U8LiveLoader extends BaseM3U8Loader {
config.peerIndex = indexId;
config.threadType = SubThreadConfig.getThreadType(ITaskWrapper.M3U8_LIVE);
config.updateInterval = SubThreadConfig.getUpdateInterval(ITaskWrapper.M3U8_LIVE);
config.ignoreFailure = mM3U8Option.isIgnoreFailureTs();
if (!config.tempFile.exists()) {
FileUtil.createFile(config.tempFile);
}
@@ -265,7 +266,9 @@ final class M3U8LiveLoader extends BaseM3U8Loader {
return;
}
mPeerUrls.add(url);
ILiveTsUrlConverter converter = mM3U8Option.getLiveTsUrlConverter();
ILiveTsUrlConverter converter = mM3U8Option.isUseDefConvert() ?
new LiveTsDefConverter() :
mM3U8Option.getLiveTsUrlConverter();
if (converter != null) {
if (TextUtils.isEmpty(mM3U8Option.getBandWidthUrl())) {
url = converter.convert(getEntity().getUrl(), url);
@@ -274,7 +277,7 @@ final class M3U8LiveLoader extends BaseM3U8Loader {
}
}
if (TextUtils.isEmpty(url) || !url.startsWith("http")) {
fail(new AriaM3U8Exception(TAG, String.format("ts地址错误url%s", url)), false);
fail(new AriaM3U8Exception(String.format("ts地址错误url%s", url)), false);
return;
}
offerPeer(new M3U8LiveLoader.ExtInfo(url, extInf));
@@ -295,13 +298,13 @@ final class M3U8LiveLoader extends BaseM3U8Loader {
if (generateIndexFile(true)) {
getListener().onComplete();
} else {
getListener().onFail(false, new AriaM3U8Exception(TAG, "创建索引文件失败"));
getListener().onFail(false, new AriaM3U8Exception("创建索引文件失败"));
}
} else if (mM3U8Option.isMergeFile()) {
if (mergeFile()) {
getListener().onComplete();
} else {
getListener().onFail(false, new AriaM3U8Exception(TAG, "合并文件失败"));
getListener().onFail(false, new AriaM3U8Exception("合并文件失败"));
}
} else {
getListener().onComplete();

View File

@@ -16,10 +16,8 @@
package com.arialyy.aria.m3u8.live;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.loader.AbsNormalLoaderUtil;
import com.arialyy.aria.core.loader.LoaderStructure;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.http.HttpTaskOption;
import com.arialyy.aria.m3u8.M3U8InfoTask;
import com.arialyy.aria.m3u8.M3U8Listener;
@@ -36,8 +34,7 @@ import com.arialyy.aria.m3u8.M3U8TaskOption;
*/
public class M3U8LiveUtil extends AbsNormalLoaderUtil {
public M3U8LiveUtil(AbsTaskWrapper wrapper, IEventListener listener) {
super(wrapper, listener);
public M3U8LiveUtil() {
}
@Override public DTaskWrapper getTaskWrapper() {
@@ -45,11 +42,12 @@ public class M3U8LiveUtil extends AbsNormalLoaderUtil {
}
@Override public M3U8LiveLoader getLoader() {
getTaskWrapper().generateM3u8Option(M3U8TaskOption.class);
getTaskWrapper().generateTaskOption(HttpTaskOption.class);
return
mLoader == null ? new M3U8LiveLoader(getTaskWrapper(), (M3U8Listener) getListener())
: (M3U8LiveLoader) mLoader;
if (mLoader == null) {
getTaskWrapper().generateM3u8Option(M3U8TaskOption.class);
getTaskWrapper().generateTaskOption(HttpTaskOption.class);
mLoader = new M3U8LiveLoader(getTaskWrapper(), (M3U8Listener) getListener());
}
return (M3U8LiveLoader) mLoader;
}
@Override public LoaderStructure BuildLoaderStructure() {

View File

@@ -18,6 +18,7 @@ package com.arialyy.aria.m3u8.vod;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.common.AbsEntity;
@@ -160,6 +161,11 @@ final class M3U8VodLoader extends BaseM3U8Loader {
// 启动定时器
startTimer();
if (getStateManager().isComplete()){
Log.d(TAG, "任务已完成");
getStateManager().handleTaskComplete();
return;
}
// 启动线程开始下载ts切片
Thread th = new Thread(new Runnable() {
@@ -486,6 +492,7 @@ final class M3U8VodLoader extends BaseM3U8Loader {
config.peerIndex = index;
config.threadType = SubThreadConfig.getThreadType(ITaskWrapper.M3U8_LIVE);
config.updateInterval = SubThreadConfig.getUpdateInterval(ITaskWrapper.M3U8_LIVE);
config.ignoreFailure = mM3U8Option.isIgnoreFailureTs();
if (!config.tempFile.exists()) {
FileUtil.createFile(config.tempFile);
}
@@ -504,7 +511,9 @@ final class M3U8VodLoader extends BaseM3U8Loader {
final List<String> urls = new ArrayList<>();
mInfoTask.setCallback(new IInfoTask.Callback() {
@Override public void onSucceed(String key, CompleteInfo info) {
IVodTsUrlConverter converter = mM3U8Option.getVodUrlConverter();
IVodTsUrlConverter converter = mM3U8Option.isUseDefConvert() ?
new VodTsDefConverter() :
mM3U8Option.getVodUrlConverter();
if (converter != null) {
if (TextUtils.isEmpty(mM3U8Option.getBandWidthUrl())) {
urls.addAll(
@@ -517,10 +526,10 @@ final class M3U8VodLoader extends BaseM3U8Loader {
urls.addAll((Collection<? extends String>) info.obj);
}
if (urls.isEmpty()) {
fail(new AriaM3U8Exception(TAG, "获取地址失败"), false);
fail(new AriaM3U8Exception("获取地址失败"), false);
return;
} else if (!urls.get(0).startsWith("http")) {
fail(new AriaM3U8Exception(TAG, "地址错误请使用IVodTsUrlConverter处理你的url信息"), false);
fail(new AriaM3U8Exception("地址错误请使用IVodTsUrlConverter处理你的url信息"), false);
return;
}
mM3U8Option.setUrls(urls);

View File

@@ -16,11 +16,9 @@
package com.arialyy.aria.m3u8.vod;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.loader.AbsNormalLoader;
import com.arialyy.aria.core.loader.AbsNormalLoaderUtil;
import com.arialyy.aria.core.loader.LoaderStructure;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.http.HttpTaskOption;
import com.arialyy.aria.m3u8.M3U8InfoTask;
import com.arialyy.aria.m3u8.M3U8Listener;
@@ -36,8 +34,7 @@ import com.arialyy.aria.m3u8.M3U8TaskOption;
*/
public final class M3U8VodUtil extends AbsNormalLoaderUtil {
public M3U8VodUtil(AbsTaskWrapper wrapper, IEventListener listener) {
super(wrapper, listener);
public M3U8VodUtil() {
}
@Override public DTaskWrapper getTaskWrapper() {
@@ -45,10 +42,12 @@ public final class M3U8VodUtil extends AbsNormalLoaderUtil {
}
@Override public AbsNormalLoader getLoader() {
getTaskWrapper().generateM3u8Option(M3U8TaskOption.class);
getTaskWrapper().generateTaskOption(HttpTaskOption.class);
return mLoader == null ? new M3U8VodLoader(getTaskWrapper(), (M3U8Listener) getListener())
: mLoader;
if (mLoader == null) {
getTaskWrapper().generateM3u8Option(M3U8TaskOption.class);
getTaskWrapper().generateTaskOption(HttpTaskOption.class);
mLoader = new M3U8VodLoader(getTaskWrapper(), (M3U8Listener) getListener());
}
return mLoader;
}
@Override public LoaderStructure BuildLoaderStructure() {

View File

@@ -139,28 +139,7 @@ public final class VodStateManager implements IThreadStateManager {
loader.notifyWaitLock(true);
}
if (isComplete()) {
ALog.d(TAG, String.format(
"startThreadNum = %s, stopNum = %s, cancelNum = %s, failNum = %s, completeNum = %s, flagQueueSize = %s",
startThreadNum, stopNum, cancelNum, failNum, loader.getCompleteNum(),
loader.getCurrentFlagSize()));
ALog.d(TAG, String.format("vod任务【%s】完成", loader.getTempFile().getName()));
if (m3U8Option.isGenerateIndexFile()) {
if (loader.generateIndexFile(false)) {
listener.onComplete();
} else {
listener.onFail(false, new AriaM3U8Exception(TAG, "创建索引文件失败"));
}
} else if (m3U8Option.isMergeFile()) {
if (mergeFile()) {
listener.onComplete();
} else {
listener.onFail(false, null);
}
} else {
listener.onComplete();
}
quitLooper();
handleTaskComplete();
}
break;
case STATE_RUNNING:
@@ -175,6 +154,34 @@ public final class VodStateManager implements IThreadStateManager {
}
};
/**
* 处理m3u8以完成
*/
void handleTaskComplete() {
ALog.d(TAG, String.format(
"startThreadNum = %s, stopNum = %s, cancelNum = %s, failNum = %s, completeNum = %s, flagQueueSize = %s",
startThreadNum, stopNum, cancelNum, failNum, loader.getCompleteNum(),
loader.getCurrentFlagSize()));
ALog.d(TAG, String.format("vod任务【%s】完成", loader.getTempFile().getName()));
if (m3U8Option.isGenerateIndexFile()) {
if (loader.generateIndexFile(false)) {
listener.onComplete();
} else {
listener.onFail(false, new AriaM3U8Exception("创建索引文件失败"));
}
} else if (m3U8Option.isMergeFile()) {
if (mergeFile()) {
listener.onComplete();
} else {
listener.onFail(false, null);
}
} else {
listener.onComplete();
}
quitLooper();
}
void updateStateCount() {
cancelNum.set(0);
stopNum.set(0);

View File

@@ -0,0 +1,36 @@
/*
* 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.m3u8.vod;
import com.arialyy.aria.core.processor.IVodTsUrlConverter;
import java.util.ArrayList;
import java.util.List;
/**
* 默认的m3u8 ts转换器
*/
class VodTsDefConverter implements IVodTsUrlConverter {
@Override public List<String> convert(String m3u8Url, List<String> tsUrls) {
int index = m3u8Url.lastIndexOf("/");
List<String> convertedTsUrl = new ArrayList<>();
String parentUrl = m3u8Url.substring(0, index + 1);
for (String temp : tsUrls) {
convertedTsUrl.add(parentUrl + temp);
}
return convertedTsUrl;
}
}

View File

@@ -0,0 +1,2 @@
com.arialyy.aria.m3u8.live.M3U8LiveUtil
com.arialyy.aria.m3u8.vod.M3U8VodUtil

View File

@@ -0,0 +1 @@
com.arialyy.aria.m3u8.M3U8Listener

View File

@@ -20,6 +20,11 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError false
}
}
dependencies {

View File

@@ -86,6 +86,17 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable,
*/
private long stopTime = 0;
@Ignore
private int netCode = 200;
public int getNetCode() {
return netCode;
}
public void setNetCode(int netCode) {
this.netCode = netCode;
}
/**
* 获取剩余时间单位s
* 如果是m3u8任务无法获取剩余时间m2u8任务如果需要获取剩余时间请设置文件长度{@link #setFileSize(long)}

View File

@@ -51,6 +51,8 @@ public class SubThreadConfig {
public long updateInterval = 1000;
// 扩展数据
public Object obj;
// 忽略失败
public boolean ignoreFailure = false;
/**
* 转换线程任务类型

View File

@@ -15,6 +15,7 @@
*/
package com.arialyy.aria.core.config;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.event.DGMaxNumEvent;
import com.arialyy.aria.core.event.DSpeedEvent;
import com.arialyy.aria.core.event.EventMsgUtil;
@@ -63,22 +64,7 @@ public class DGroupConfig extends BaseTaskConfig implements Serializable {
}
public DownloadConfig getSubConfig() {
if (subConfig == null) {
subConfig = new DownloadConfig();
subConfig.threadNum = 1;
subConfig.useBlock = false;
subConfig.buffSize = buffSize;
subConfig.caName = caName;
subConfig.caPath = caPath;
subConfig.connectTimeOut = connectTimeOut;
subConfig.iOTimeOut = iOTimeOut;
subConfig.isConvertSpeed = isConvertSpeed;
subConfig.maxSpeed = maxSpeed;
subConfig.queueMod = "now";
subConfig.reTryInterval = subReTryInterval;
subConfig.reTryNum = subReTryNum;
subConfig.updateInterval = updateInterval;
}
subConfig = AriaConfig.getInstance().getDConfig();
return subConfig;
}

View File

@@ -44,6 +44,21 @@ public class DownloadConfig extends BaseTaskConfig implements Serializable {
*/
boolean useBlock = true;
/**
* 设置http下载获取文件大小是否使用Head请求。true使用head请求false使用默认的get请求
*/
boolean useHeadRequest = false;
public boolean isUseHeadRequest() {
return useHeadRequest;
}
public DownloadConfig setUseHeadRequest(boolean useHeadRequest) {
this.useHeadRequest = useHeadRequest;
save();
return this;
}
public boolean isUseBlock() {
return useBlock;
}

View File

@@ -146,7 +146,7 @@ public class XMLReader extends DefaultHandler {
break;
case "subFailAsStop": // 子任务失败时回调stop
setField("subFailAsStop", checkBoolean(value) ? Boolean.valueOf(value) : false,
ConfigType.D_GROUP);
ConfigType.D_GROUP);
break;
case "subReTryNum": // 子任务重试次数
int subReTryNum = checkInt(value) ? Integer.parseInt(value) : 5;
@@ -156,6 +156,10 @@ public class XMLReader extends DefaultHandler {
int subReTryInterval = checkInt(value) ? Integer.parseInt(value) : 2000;
setField("subReTryInterval", subReTryInterval, ConfigType.D_GROUP);
break;
case "useHeadRequest": // 是否使用head请求
boolean useHeadRequest = checkBoolean(value) ? Boolean.valueOf(value) : false;
setField("useHeadRequest", useHeadRequest, ConfigType.DOWNLOAD);
break;
}
} else if (mType == ConfigType.APP) {
String value = attributes.getValue("value");

View File

@@ -19,6 +19,7 @@ import com.arialyy.aria.core.inf.IUtil;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.loader.LoaderStructure;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
@@ -34,10 +35,12 @@ public abstract class AbsGroupLoaderUtil implements IUtil {
private AbsTaskWrapper mTaskWrapper;
private boolean isStop = false, isCancel = false;
protected AbsGroupLoaderUtil(AbsTaskWrapper wrapper, IEventListener listener) {
mTaskWrapper = wrapper;
@Override public IUtil setParams(AbsTaskWrapper taskWrapper, IEventListener listener) {
mTaskWrapper = taskWrapper;
mListener = listener;
mLoader = getLoader();
return this;
}
protected abstract AbsGroupLoader getLoader();

View File

@@ -15,20 +15,16 @@
*/
package com.arialyy.aria.core.group;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.inf.IThreadStateManager;
import com.arialyy.aria.core.inf.IUtil;
import com.arialyy.aria.core.listener.IDLoadListener;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.listener.ISchedulers;
import com.arialyy.aria.core.loader.LoaderStructure;
import com.arialyy.aria.core.loader.SubLoader;
import com.arialyy.aria.exception.AriaException;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
@@ -49,12 +45,16 @@ public abstract class AbsSubDLoadUtil implements IUtil, Runnable {
* @param schedulers 调度器
* @param needGetInfo {@code true} 需要获取文件信息。{@code false} 不需要获取文件信息
*/
protected AbsSubDLoadUtil(DTaskWrapper taskWrapper, Handler schedulers, boolean needGetInfo, String parentKey) {
mWrapper = taskWrapper;
protected AbsSubDLoadUtil(Handler schedulers, boolean needGetInfo, String parentKey) {
mSchedulers = schedulers;
this.parentKey = parentKey;
this.needGetInfo = needGetInfo;
}
@Override public IUtil setParams(AbsTaskWrapper taskWrapper, IEventListener listener) {
mWrapper = (DTaskWrapper) taskWrapper;
mDLoader = getLoader();
return this;
}
/**

View File

@@ -19,12 +19,14 @@ package com.arialyy.aria.core.group;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.config.Configuration;
import com.arialyy.aria.core.inf.IThreadStateManager;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.manager.ThreadTaskManager;
import com.arialyy.aria.exception.AriaException;
import com.arialyy.aria.exception.ExceptionFactory;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.NetUtils;
@@ -71,7 +73,7 @@ final class SimpleSchedulers implements Handler.Callback {
mGState.listener.onSubRunning(loaderUtil.getEntity(), range);
break;
case IThreadStateManager.STATE_PRE:
mGState.listener.onSubPre(loaderUtil.getEntity( ));
mGState.listener.onSubPre(loaderUtil.getEntity());
mGState.updateCount(loaderUtil.getKey());
break;
case IThreadStateManager.STATE_START:
@@ -103,8 +105,11 @@ final class SimpleSchedulers implements Handler.Callback {
* @param needRetry true 需要重试false 不需要重试
*/
private synchronized void handleFail(final AbsSubDLoadUtil loaderUtil, boolean needRetry) {
Configuration config = Configuration.getInstance();
Log.d(TAG, String.format("handleFail, size = %s, completeNum = %s, failNum = %s, stopNum = %s",
mGState.getSubSize(), mGState.getCompleteNum(), mGState.getFailNum(),
mGState.getSubSize()));
Configuration config = Configuration.getInstance();
int num = config.dGroupCfg.getSubReTryNum();
boolean isNotNetRetry = config.appCfg.isNotNetRetry();
@@ -113,25 +118,27 @@ final class SimpleSchedulers implements Handler.Callback {
|| loaderUtil.getLoader() == null // 如果获取不到文件信息loader为空
|| loaderUtil.getEntity().getFailNum() > num) {
mQueue.removeTaskFromExecQ(loaderUtil);
mGState.listener.onSubFail(loaderUtil.getEntity(), new AriaException(TAG,
String.format("任务组子任务【%s】下载失败下载地址【%s】", loaderUtil.getEntity().getFileName(),
loaderUtil.getEntity().getUrl())));
mGState.listener.onSubFail(loaderUtil.getEntity(),
ExceptionFactory.getException(ExceptionFactory.TYPE_GROUP,
String.format("任务组子任务【%s】下载失败下载地址【%s】", loaderUtil.getEntity().getFileName(),
loaderUtil.getEntity().getUrl()), null));
mGState.countFailNum(loaderUtil.getKey());
if (mGState.getFailNum() == mGState.getSubSize()
|| mGState.getStopNum() + mGState.getFailNum() + mGState.getCompleteNum()
== mGState.getSubSize()) {
mQueue.clear();
mGState.isRunning.set(false);
if (mGState.getCompleteNum() > 0&&Configuration.getInstance().dGroupCfg.isSubFailAsStop()) {
if (mGState.getCompleteNum() > 0
&& Configuration.getInstance().dGroupCfg.isSubFailAsStop()) {
ALog.e(TAG, String.format("任务组【%s】停止", mGState.getGroupHash()));
mGState.listener.onStop(mGState.getProgress());
} else {
mGState.listener.onFail(false, new AriaException(TAG,
String.format("任务组【%s】下载失败", mGState.getGroupHash())));
return;
}
} else {
startNext();
mGState.listener.onFail(false,
ExceptionFactory.getException(ExceptionFactory.TYPE_GROUP,
String.format("任务组【%s】下载失败", mGState.getGroupHash()), null));
return;
}
startNext();
return;
}
SimpleSubRetryQueue.getInstance().offer(loaderUtil);
@@ -143,6 +150,10 @@ final class SimpleSchedulers implements Handler.Callback {
* 2、completeNum + failNum + stopNum = subSize则认为组合任务停止
*/
private synchronized void handleStop(AbsSubDLoadUtil loadUtil, long curLocation) {
Log.d(TAG, String.format("handleStop, size = %s, completeNum = %s, failNum = %s, stopNum = %s",
mGState.getSubSize(), mGState.getCompleteNum(), mGState.getFailNum(),
mGState.getSubSize()));
mGState.listener.onSubStop(loadUtil.getEntity(), curLocation);
mGState.countStopNum(loadUtil.getKey());
if (mGState.getStopNum() == mGState.getSubSize()
@@ -151,12 +162,11 @@ final class SimpleSchedulers implements Handler.Callback {
+ mGState.getFailNum()
+ mQueue.getCacheSize()
== mGState.getSubSize()) {
mQueue.clear();
mGState.isRunning.set(false);
mGState.listener.onStop(mGState.getProgress());
} else {
startNext();
return;
}
startNext();
}
/**
@@ -169,32 +179,37 @@ final class SimpleSchedulers implements Handler.Callback {
*/
private synchronized void handleComplete(AbsSubDLoadUtil loader) {
ALog.d(TAG, String.format("子任务【%s】完成", loader.getEntity().getFileName()));
if (loader.getRecord().isBlock) {
Log.d(TAG,
String.format("handleComplete, size = %s, completeNum = %s, failNum = %s, stopNum = %s",
mGState.getSubSize(), mGState.getCompleteNum(), mGState.getFailNum(),
mGState.getSubSize()));
TaskRecord record = loader.getRecord();
if (record != null && record.isBlock) {
File partFile =
new File(String.format(IRecordHandler.SUB_PATH, loader.getRecord().filePath, 0));
partFile.renameTo(new File(loader.getRecord().filePath));
new File(String.format(IRecordHandler.SUB_PATH, record.filePath, 0));
partFile.renameTo(new File(record.filePath));
}
ThreadTaskManager.getInstance().removeTaskThread(loader.getKey());
mGState.listener.onSubComplete(loader.getEntity());
mQueue.removeTaskFromExecQ(loader);
mGState.updateCompleteNum();
ALog.d(TAG, String.format("总任务数:%s完成的任务数%s失败的任务数%s停止的任务数%s", mGState.getSubSize(),
mGState.getCompleteNum(), mGState.getFailNum(), mGState.getStopNum()));
if (mGState.getCompleteNum() + mGState.getFailNum() + mGState.getStopNum()
== mGState.getSubSize()) {
if (mGState.getStopNum() == 0 && mGState.getFailNum() == 0) {
mGState.listener.onComplete();
} else if(mGState.getStopNum() == 0&&!Configuration.getInstance().dGroupCfg.isSubFailAsStop() ){
mGState.listener.onFail(false, new AriaException(TAG,
String.format("任务组【%s】下载失败", mGState.getGroupHash())));
} else if (mGState.getStopNum() == 0
&& !Configuration.getInstance().dGroupCfg.isSubFailAsStop()) {
mGState.listener.onFail(false,
ExceptionFactory.getException(ExceptionFactory.TYPE_GROUP,
String.format("任务组【%s】下载失败", mGState.getGroupHash()), null));
} else {
mGState.listener.onStop(mGState.getProgress());
}
mQueue.clear();
mGState.isRunning.set(false);
} else {
startNext();
return;
}
startNext();
}
/**
@@ -208,8 +223,8 @@ final class SimpleSchedulers implements Handler.Callback {
if (next != null) {
ALog.d(TAG, String.format("启动任务:%s", next.getEntity().getFileName()));
mQueue.startTask(next);
} else {
ALog.i(TAG, "没有下一子任务");
return;
}
ALog.i(TAG, "没有下一子任务");
}
}

View File

@@ -21,10 +21,10 @@ import com.arialyy.aria.util.CommonUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* 组合任务队列,该队列生命周期和{@link AbsGroupLoaderUtil}生命周期一致
@@ -34,11 +34,11 @@ final class SimpleSubQueue implements ISubQueue<AbsSubDLoadUtil> {
/**
* 缓存下载器
*/
private Map<String, AbsSubDLoadUtil> mCache = new LinkedHashMap<>();
private Map<String, AbsSubDLoadUtil> mCache = new ConcurrentHashMap<>();
/**
* 执行中的下载器
*/
private Map<String, AbsSubDLoadUtil> mExec = new LinkedHashMap<>();
private Map<String, AbsSubDLoadUtil> mExec = new ConcurrentHashMap<>();
/**
* 最大执行任务数
@@ -85,12 +85,13 @@ final class SimpleSubQueue implements ISubQueue<AbsSubDLoadUtil> {
if (mExec.size() < mExecSize) {
mCache.remove(fileer.getKey());
mExec.put(fileer.getKey(), fileer);
ALog.d(TAG, String.format("开始执行子任务:%s", fileer.getEntity().getFileName()));
ALog.d(TAG,
String.format("开始执行子任务:%skey: %s", fileer.getEntity().getFileName(), fileer.getKey()));
fileer.run();
} else {
ALog.d(TAG, String.format("执行队列已满任务进入缓存器中key: %s", fileer.getKey()));
addTask(fileer);
return;
}
ALog.d(TAG, String.format("执行队列已满任务进入缓存器中key: %s", fileer.getKey()));
addTask(fileer);
}
@Override public void stopTask(AbsSubDLoadUtil fileer) {
@@ -144,15 +145,16 @@ final class SimpleSubQueue implements ISubQueue<AbsSubDLoadUtil> {
addTask(t);
}
}
} else { // 处理队列变大的情况,该情况下将增加任务
if (mExec.size() < num) {
for (int i = 0; i < diff; i++) {
AbsSubDLoadUtil next = getNextTask();
if (next != null) {
startTask(next);
} else {
ALog.d(TAG, "子任务中没有缓存任务");
}
return;
}
// 处理队列变大的情况,该情况下将增加任务
if (mExec.size() < num) {
for (int i = 0; i < diff; i++) {
AbsSubDLoadUtil next = getNextTask();
if (next != null) {
startTask(next);
} else {
ALog.d(TAG, "子任务中没有缓存任务");
}
}
}

View File

@@ -18,7 +18,9 @@ package com.arialyy.aria.core.inf;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
/**
* Created by lyy on 2016/10/31.
@@ -26,6 +28,8 @@ import com.arialyy.aria.core.upload.UploadEntity;
*/
public interface IUtil {
IUtil setParams(AbsTaskWrapper taskWrapper, IEventListener listener);
/**
* 获取任务标志
*

View File

@@ -15,26 +15,16 @@
*/
package com.arialyy.aria.core.listener;
import android.os.Handler;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.core.task.DownloadTask;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.DeleteDRecord;
import com.arialyy.aria.util.RecordUtil;
/**
* 下载监听类
*/
public class BaseDListener extends BaseListener<DownloadEntity, DTaskWrapper, AbsTask<DTaskWrapper>>
implements IDLoadListener {
public BaseDListener(AbsTask<DTaskWrapper> task, Handler outHandler) {
super(task, outHandler);
}
public class BaseDListener extends BaseListener implements IDLoadListener {
@Override
public void onPostPre(long fileSize) {
@@ -52,7 +42,7 @@ public class BaseDListener extends BaseListener<DownloadEntity, DTaskWrapper, Ab
}
@Override protected void handleCancel() {
int sType = getTask().getSchedulerType();
int sType = getTask(DownloadTask.class).getSchedulerType();
if (sType == TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY) {
mEntity.setComplete(false);
mEntity.setState(IEntity.STATE_WAIT);

View File

@@ -16,7 +16,6 @@
package com.arialyy.aria.core.listener;
import android.os.Handler;
import android.util.Log;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.TaskSchedulerType;
@@ -30,22 +29,20 @@ import com.arialyy.aria.util.ErrorHelp;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
public abstract class BaseListener<ENTITY extends AbsEntity, TASK_WRAPPER extends AbsTaskWrapper<ENTITY>,
TASK extends AbsTask<TASK_WRAPPER>>
implements IEventListener {
protected static String TAG;
protected static final int RUN_SAVE_INTERVAL = 5 * 1000; //5s保存一次下载中的进度
public abstract class BaseListener implements IEventListener {
protected String TAG = getClass().getSimpleName();
static final int RUN_SAVE_INTERVAL = 5 * 1000; //5s保存一次下载中的进度
protected SoftReference<Handler> outHandler;
private long mLastLen; //上一次发送长度
private boolean isFirst = true;
private TASK mTask;
protected long mLastSaveTime;
protected ENTITY mEntity;
protected TASK_WRAPPER mTaskWrapper;
private AbsTask mTask;
long mLastSaveTime;
protected AbsEntity mEntity;
protected AbsTaskWrapper mTaskWrapper;
private boolean isConvertSpeed;
private long mUpdateInterval;
protected BaseListener(TASK task, Handler outHandler) {
@Override public IEventListener setParams(AbsTask task, Handler outHandler) {
this.outHandler = new SoftReference<>(outHandler);
mTask = new WeakReference<>(task).get();
mEntity = mTask.getTaskWrapper().getEntity();
@@ -55,10 +52,11 @@ public abstract class BaseListener<ENTITY extends AbsEntity, TASK_WRAPPER extend
mLastLen = mEntity.getCurrentProgress();
mLastSaveTime = System.currentTimeMillis();
TAG = CommonUtil.getClassName(getClass());
return this;
}
protected TASK getTask() {
return mTask;
protected <TASK extends AbsTask> TASK getTask(Class<TASK> clazz) {
return (TASK) mTask;
}
@Override public void onPre() {
@@ -125,7 +123,7 @@ public abstract class BaseListener<ENTITY extends AbsEntity, TASK_WRAPPER extend
if (e != null) {
String error = ALog.getExceptionString(e);
ALog.e(TAG, error);
ErrorHelp.saveError(e.getTag(), e.getMessage(), error);
ErrorHelp.saveError(e.getMessage(), error);
}
}

View File

@@ -15,26 +15,18 @@
*/
package com.arialyy.aria.core.listener;
import android.os.Handler;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.core.upload.UTaskWrapper;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.task.UploadTask;
import com.arialyy.aria.util.DeleteURecord;
/**
* 下载监听类
*/
public class BaseUListener extends BaseListener<UploadEntity, UTaskWrapper, AbsTask<UTaskWrapper>>
implements IUploadListener {
public BaseUListener(AbsTask<UTaskWrapper> task, Handler outHandler) {
super(task, outHandler);
}
public class BaseUListener extends BaseListener implements IUploadListener {
@Override protected void handleCancel() {
int sType = getTask().getSchedulerType();
int sType = getTask(UploadTask.class).getSchedulerType();
if (sType == TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY) {
mEntity.setComplete(false);
mEntity.setState(IEntity.STATE_WAIT);

View File

@@ -16,7 +16,6 @@
package com.arialyy.aria.core.listener;
import android.os.Handler;
import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.group.GroupSendParams;
@@ -35,15 +34,14 @@ import static com.arialyy.aria.core.task.AbsTask.ERROR_INFO_KEY;
/**
* Created by Aria.Lao on 2017/7/20. 任务组下载事件
*/
public class DownloadGroupListener
extends BaseListener<DownloadGroupEntity, DGTaskWrapper, AbsTask<DGTaskWrapper>>
implements IDGroupListener {
public class DownloadGroupListener extends BaseListener implements IDGroupListener {
private GroupSendParams<DownloadGroupTask, DownloadEntity> mSeedEntity;
public DownloadGroupListener(AbsTask<DGTaskWrapper> task, Handler outHandler) {
super(task, outHandler);
@Override public IEventListener setParams(AbsTask task, Handler outHandler) {
IEventListener listener = super.setParams(task, outHandler);
mSeedEntity = new GroupSendParams<>();
mSeedEntity.groupTask = (DownloadGroupTask) task;
return listener;
}
@Override
@@ -91,7 +89,7 @@ public class DownloadGroupListener
sendInState2Target(ISchedulers.SUB_FAIL, subEntity);
if (e != null) {
e.printStackTrace();
ErrorHelp.saveError(e.getTag(), "", ALog.getExceptionString(e));
ErrorHelp.saveError("", ALog.getExceptionString(e));
}
}
@@ -164,12 +162,13 @@ public class DownloadGroupListener
}
private void saveCurrentLocation() {
if (mEntity.getSubEntities() == null || mEntity.getSubEntities().isEmpty()) {
DownloadGroupEntity dgEntity = (DownloadGroupEntity) mEntity;
if (dgEntity.getSubEntities() == null || dgEntity.getSubEntities().isEmpty()) {
ALog.w(TAG, "保存进度失败子任务为null");
return;
}
long location = 0;
for (DownloadEntity e : mEntity.getSubEntities()) {
for (DownloadEntity e : dgEntity.getSubEntities()) {
location += e.getCurrentProgress();
}
if (location > mEntity.getFileSize()) {
@@ -193,7 +192,7 @@ public class DownloadGroupListener
}
@Override protected void handleCancel() {
int sType = getTask().getSchedulerType();
int sType = getTask(DownloadGroupTask.class).getSchedulerType();
if (sType == TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY) {
mEntity.setComplete(false);
mEntity.setState(IEntity.STATE_WAIT);

View File

@@ -15,6 +15,8 @@
*/
package com.arialyy.aria.core.listener;
import android.os.Handler;
import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.exception.AriaException;
/**
@@ -23,6 +25,8 @@ import com.arialyy.aria.exception.AriaException;
*/
public interface IEventListener {
IEventListener setParams(AbsTask task, Handler outHandler);
/**
* 预处理有时有些地址链接比较慢这时可以先在这个地方出来一些界面上的UI如按钮的状态
*/

View File

@@ -19,6 +19,7 @@ package com.arialyy.aria.core.loader;
import com.arialyy.aria.core.inf.IUtil;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.exception.AriaException;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
@@ -34,10 +35,14 @@ public abstract class AbsNormalLoaderUtil implements IUtil {
private AbsTaskWrapper mTaskWrapper;
private boolean isStop = false, isCancel = false;
protected AbsNormalLoaderUtil(AbsTaskWrapper wrapper, IEventListener listener) {
mTaskWrapper = wrapper;
protected AbsNormalLoaderUtil() {
}
@Override public IUtil setParams(AbsTaskWrapper taskWrapper, IEventListener listener) {
mTaskWrapper = taskWrapper;
mListener = listener;
mLoader = getLoader();
return this;
}
/**

View File

@@ -106,6 +106,11 @@ public final class SubLoader implements ILoader, ILoaderVisitor {
}
record = recordHandler.getRecord(wrapper.getEntity().getFileSize());
if (record == null) {
ALog.d(TAG, "子任务记录为空");
sendFailState(false);
return;
}
if (record.threadRecords != null
&& !TextUtils.isEmpty(record.filePath)
&& new File(record.filePath).exists()
@@ -163,9 +168,9 @@ public final class SubLoader implements ILoader, ILoaderVisitor {
for (IThreadTask iThreadTask : mTask) {
iThreadTask.call();
}
} else {
ALog.e(TAG, "子任务的线程任务为空");
return;
}
ALog.e(TAG, "子任务的线程任务为空");
} catch (Exception e) {
e.printStackTrace();
}
@@ -258,9 +263,9 @@ public final class SubLoader implements ILoader, ILoaderVisitor {
}
if (needGetInfo) {
infoTask.run();
} else {
handlerTask();
return;
}
handlerTask();
}
/**

View File

@@ -27,8 +27,9 @@ public interface IBandWidthUrlConverter extends IEventHandler {
* 转换码率地址为可用的http地址对于某些服务器返回的切片信息有可能是相对地址也可能是处理过的
* 对于这种情况你需要使用url转换器将地址转换为可正常访问的http地址
*
* @param m3u8Url m3u8url地址
* @param bandWidthUrl 原始码率地址
* @return 可正常访问的http地址
*/
String convert(String bandWidthUrl);
String convert(String m3u8Url, String bandWidthUrl);
}

View File

@@ -25,9 +25,10 @@ public interface IKeyUrlConverter extends IEventHandler {
/**
* 将被加密的密钥下载地址转换为可使用的http下载地址
*
* @param m3u8Url m3u8文件的下载地址
* @param m3u8Url m3u8的url地址
* @param tsListUrl m3u8切片列表url地址
* @param keyUrl 加密的url地址
* @return 可正常访问的http地址
*/
String convert(String m3u8Url, String keyUrl);
String convert(String m3u8Url, String tsListUrl, String keyUrl);
}

View File

@@ -30,5 +30,5 @@ public interface ILiveTsUrlConverter extends IEventHandler {
* @param tsUrl ts文件下载地址
* @return 转换后的http地址
*/
public String convert(String m3u8Url, String tsUrl);
String convert(String m3u8Url, String tsUrl);
}

View File

@@ -64,7 +64,7 @@ public abstract class AbsTask<TASK_WRAPPER extends AbsTaskWrapper>
return mOutHandler;
}
protected synchronized IUtil getUtil() {
synchronized IUtil getUtil() {
if (mUtil == null) {
mUtil = ComponentUtil.getInstance().buildUtil(mTaskWrapper, mListener);
}

View File

@@ -20,7 +20,6 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Process;
import android.util.Log;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.common.AbsEntity;
@@ -259,16 +258,15 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
if (mTaskWrapper.getRequestType() == ITaskWrapper.M3U8_VOD) {
writeConfig(false, getConfig().tempFile.length());
ALog.i(TAG, String.format("任务【%s】已停止", getFileName()));
} else {
if (mTaskWrapper.isSupportBP()) {
ALog.d(TAG,
String.format("任务【%s】thread__%s__停止【当前线程停止位置%s】", getFileName(),
mRecord.threadId, stopLocation));
writeConfig(false, stopLocation);
} else {
ALog.i(TAG, String.format("任务【%s】已停止", getFileName()));
}
return;
}
if (mTaskWrapper.isSupportBP()) {
ALog.d(TAG, String.format("任务【%s】thread__%s__停止【当前线程停止位置%s】", getFileName(),
mRecord.threadId, stopLocation));
writeConfig(false, stopLocation);
return;
}
ALog.i(TAG, String.format("任务【%s】已停止", getFileName()));
}
/**
@@ -404,22 +402,29 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
if (mTaskWrapper.getRequestType() == ITaskWrapper.M3U8_VOD) {
writeConfig(false, 0);
retryM3U8Peer(needRetry);
} else {
if (mTaskWrapper.isSupportBP()) {
writeConfig(false, subCurrentLocation);
retryBlockTask(needRetry && mConfig.startThreadNum != 1);
} else {
ALog.e(TAG, String.format("任务【%s】执行失败", getFileName()));
ErrorHelp.saveError(TAG, "", ALog.getExceptionString(ex));
sendFailMsg(null, needRetry);
}
return;
}
if (mTaskWrapper.isSupportBP()) {
writeConfig(false, subCurrentLocation);
retryBlockTask(needRetry);
return;
}
ALog.e(TAG, String.format("任务【%s】执行失败", getFileName()));
ErrorHelp.saveError("", ALog.getExceptionString(ex));
sendFailMsg(null, needRetry);
}
/**
* 重试ts分片
*/
private void retryM3U8Peer(boolean needRetry) {
if (mConfig.ignoreFailure){
ALog.d(TAG, "忽略失败的切片");
sendFailMsg(null, false);
return;
}
boolean isConnected = NetUtils.isConnected(AriaConfig.getInstance().getAPP());
if (!isConnected && !isNotNetRetry) {
ALog.w(TAG, String.format("ts切片【%s】重试失败网络未连接", getFileName()));
@@ -434,9 +439,9 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
FileUtil.deleteFile(mConfig.tempFile);
FileUtil.createFile(mConfig.tempFile);
ThreadTaskManager.getInstance().retryThread(this);
} else {
sendFailMsg(null, false);
return;
}
sendFailMsg(null, false);
}
/**
@@ -456,10 +461,10 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
mFailTimes++;
handleBlockRecord();
ThreadTaskManager.getInstance().retryThread(this);
} else {
ALog.e(TAG, String.format("任务【%s】执行失败", getFileName()));
sendFailMsg(null, needRetry);
return;
}
ALog.e(TAG, String.format("任务【%s】执行失败", getFileName()));
sendFailMsg(null, needRetry);
}
/**
@@ -511,10 +516,8 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
b.putBoolean(IThreadStateManager.DATA_RETRY, needRetry);
if (e != null) {
b.putSerializable(IThreadStateManager.DATA_ERROR_INFO, e);
updateState(IThreadStateManager.STATE_FAIL, b);
} else {
updateState(IThreadStateManager.STATE_FAIL, b);
}
updateState(IThreadStateManager.STATE_FAIL, b);
}
/**

View File

@@ -29,8 +29,7 @@ import com.arialyy.aria.util.ComponentUtil;
/**
* Created by lyy on 2017/2/23. 所有任务实体的父类
*/
public abstract class AbsTaskWrapper<ENTITY extends AbsEntity>
implements ITaskWrapper {
public abstract class AbsTaskWrapper<ENTITY extends AbsEntity> implements ITaskWrapper {
/**
* 刷新信息 {@code true} 重新刷新下载信息

View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.exception;
public class AriaComponentException extends RuntimeException {
public AriaComponentException(String message, Exception e) {
super(message, e);
}
public AriaComponentException(String s) {
super(s);
}
}

View File

@@ -17,20 +17,12 @@ package com.arialyy.aria.exception;
public class AriaException extends Exception {
private String tag;
public AriaException(String tag, String message) {
public AriaException(String message) {
super(message);
this.tag = tag;
}
public AriaException(String tag, String message, Exception e) {
super(String.format("%s, %s\n%s", tag, message == null ? "" : message,
public AriaException(String message, Exception e) {
super(String.format("%s\n%s", message == null ? "" : message,
e == null ? "" : e.getMessage()));
this.tag = tag;
}
public String getTag() {
return tag;
}
}

View File

@@ -18,11 +18,11 @@ package com.arialyy.aria.exception;
public class AriaFTPException extends AriaException {
private static final String FTP_EXCEPTION = "Aria FTP Exception:";
public AriaFTPException(String tag, String message) {
super(tag, String.format("%s\n%s", FTP_EXCEPTION, message));
public AriaFTPException(String message) {
super(String.format("%s\n%s", FTP_EXCEPTION, message));
}
public AriaFTPException(String tag, String message, Exception e) {
super(tag, message, e);
public AriaFTPException(String message, Exception e) {
super(message, e);
}
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.exception;
public class AriaGroupException extends AriaException {
private static final String FTP_EXCEPTION = "Aria Group Exception:";
public AriaGroupException(String message) {
super(String.format("%s\n%s", FTP_EXCEPTION, message));
}
public AriaGroupException(String message, Exception e) {
super(message, e);
}
}

View File

@@ -18,11 +18,11 @@ package com.arialyy.aria.exception;
public class AriaHTTPException extends AriaException {
private static final String HTTP_EXCEPTION = "Aria HTTP Exception:";
public AriaHTTPException(String tag, String message) {
super(tag, String.format("%s\n%s", HTTP_EXCEPTION, message));
public AriaHTTPException( String message) {
super(String.format("%s\n%s", HTTP_EXCEPTION, message));
}
public AriaHTTPException(String tag, String message, Exception e) {
super(tag, message, e);
public AriaHTTPException(String message, Exception e) {
super(message, e);
}
}

Some files were not shown because too many files have changed in this diff Show More