Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3024b85091 | ||
|
|
c78fa1b66a | ||
|
|
428fbab9d2 | ||
|
|
07a1f45f1e | ||
|
|
22a3b61dbf | ||
|
|
eccbb37647 | ||
|
|
ab358e7dbf | ||
|
|
86aeac0ad8 | ||
|
|
ff0796c580 | ||
|
|
fed2b4111f | ||
|
|
1a04a6d221 | ||
|
|
5f60b9ed57 | ||
|
|
9d8bf579b6 | ||
|
|
bebc9b926d | ||
|
|
ae1a9e3870 | ||
|
|
288dcf633e | ||
|
|
fed6ae55e1 | ||
|
|
41bae31d6a | ||
|
|
8787030fa6 | ||
|
|
b5cbbd9d3d | ||
|
|
1241bc5991 | ||
|
|
a3df4016ff | ||
|
|
981917fa52 | ||
|
|
023f648d07 | ||
|
|
9a174311d9 | ||
|
|
3edf40f533 | ||
|
|
46c10f6ffd | ||
|
|
32cb6152dd | ||
|
|
f657bbcc53 | ||
|
|
e6f5c4f472 | ||
|
|
b7e0f6f0e8 | ||
|
|
0bc083fa98 | ||
|
|
d931b75800 | ||
|
|
418ec74b7b |
8
.github/FUNDING.yml
vendored
Normal file
8
.github/FUNDING.yml
vendored
Normal 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
19
.github/stale.yml
vendored
Normal 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
|
||||
@@ -23,6 +23,10 @@ android {
|
||||
dataBinding {
|
||||
enabled = true
|
||||
}
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -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)");
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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())) {
|
||||
// 检查路径冲突
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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> {
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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> {
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置密钥文件的保存路径
|
||||
*
|
||||
|
||||
@@ -98,6 +98,7 @@ class DNormalConfigHandler<TARGET extends AbsTarget> implements IConfigHandler {
|
||||
|
||||
void setUrl(String url) {
|
||||
mEntity.setUrl(url);
|
||||
mWrapper.setTempUrl(url);
|
||||
}
|
||||
|
||||
String getUrl() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -49,5 +49,11 @@ public interface IReceiver {
|
||||
*
|
||||
* @return {@link ReceiverType}
|
||||
*/
|
||||
String getType();
|
||||
ReceiverType getType();
|
||||
|
||||
/**
|
||||
* 判断是否是fragment,如果是fragment,在activity销毁时,需要将其从receiver中移除
|
||||
*/
|
||||
boolean isFragment();
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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> {
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
23
DEV_LOG.md
23
DEV_LOG.md
@@ -1,4 +1,27 @@
|
||||
## 开发日志
|
||||
+ 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
|
||||
|
||||
@@ -1,292 +1,173 @@
|
||||
# Aria
|
||||
</br>
|
||||
</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
|
||||
|
||||

|
||||
|
||||
* Speed limit
|
||||
|
||||

|
||||
|
||||
* Multi-file package download
|
||||
|
||||
<img src="https://github.com/AriaLyy/DownloadUtil/blob/master/img/group_task.gif" width="360" height="640"/>
|
||||
|
||||
* m3u8 download
|
||||
|
||||

|
||||
|
||||
## Lib
|
||||
[](https://github.com/AriaLyy/Aria/blob/master/LICENSE)
|
||||
[](https://github.com/AriaLyy/Aria)
|
||||
[](https://github.com/AriaLyy/Aria)
|
||||
[](https://github.com/AriaLyy/Aria)
|
||||
[](https://github.com/AriaLyy/Aria)
|
||||
[](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
|
||||
[](https://bintray.com/arialyy/maven/AriaApi/_latestVersion)
|
||||
[](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
|
||||

|
||||

|
||||
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
|
||||

|
||||
__⚠️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 example,only 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 special,need 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 don’t 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
|
||||
-------
|
||||
|
||||
|
||||
@@ -20,6 +20,10 @@ android {
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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服务器,错误码为:%s,msg:%s", reply, client.getReplyString())), false);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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("获取文件信息错误,错误码为:%s,msg:%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("获取流失败,错误码为:%s,msg:%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) {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
com.arialyy.aria.ftp.download.FtpDLoaderUtil
|
||||
com.arialyy.aria.ftp.download.FtpDGLoaderUtil
|
||||
com.arialyy.aria.ftp.upload.FtpULoaderUtil
|
||||
@@ -19,6 +19,10 @@ android {
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
com.arialyy.aria.http.download.HttpDLoaderUtil
|
||||
com.arialyy.aria.http.download.HttpDGLoaderUtil
|
||||
com.arialyy.aria.http.upload.HttpULoaderUtil
|
||||
@@ -20,6 +20,10 @@ android {
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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错误码:%s,url:%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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
com.arialyy.aria.m3u8.live.M3U8LiveUtil
|
||||
com.arialyy.aria.m3u8.vod.M3U8VodUtil
|
||||
@@ -0,0 +1 @@
|
||||
com.arialyy.aria.m3u8.M3U8Listener
|
||||
@@ -20,6 +20,11 @@ android {
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -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)}
|
||||
|
||||
@@ -51,6 +51,8 @@ public class SubThreadConfig {
|
||||
public long updateInterval = 1000;
|
||||
// 扩展数据
|
||||
public Object obj;
|
||||
// 忽略失败
|
||||
public boolean ignoreFailure = false;
|
||||
|
||||
/**
|
||||
* 转换线程任务类型
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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, "没有下一子任务");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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("开始执行子任务:%s,key: %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, "子任务中没有缓存任务");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
* 获取任务标志
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,如按钮的状态
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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} 重新刷新下载信息
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
Reference in New Issue
Block a user