m3u8点播下载新增创建ts索引功能

v3.7
laoyuyu 5 years ago
commit 202e664530
  1. 4
      Aria/jcenter.gradle
  2. 8
      Aria/src/main/java/com/arialyy/aria/core/Aria.java
  3. 4
      Aria/src/main/java/com/arialyy/aria/core/common/AbsStartTarget.java
  4. 8
      Aria/src/main/java/com/arialyy/aria/core/common/AbsThreadTask.java
  5. 3
      Aria/src/main/java/com/arialyy/aria/core/common/RecordHandler.java
  6. 2
      Aria/src/main/java/com/arialyy/aria/core/common/Suggest.java
  7. 4
      Aria/src/main/java/com/arialyy/aria/core/common/ThreadStateManager.java
  8. 2
      Aria/src/main/java/com/arialyy/aria/core/common/controller/ControllerType.java
  9. 2
      Aria/src/main/java/com/arialyy/aria/core/common/controller/FeatureController.java
  10. 4
      Aria/src/main/java/com/arialyy/aria/core/common/controller/IStartFeature.java
  11. 2
      Aria/src/main/java/com/arialyy/aria/core/common/controller/StartController.java
  12. 2
      Aria/src/main/java/com/arialyy/aria/core/common/ftp/IFtpUploadInterceptor.java
  13. 6
      Aria/src/main/java/com/arialyy/aria/core/config/BaseConfig.java
  14. 10
      Aria/src/main/java/com/arialyy/aria/core/config/Configuration.java
  15. 4
      Aria/src/main/java/com/arialyy/aria/core/download/CheckDEntityUtil.java
  16. 5
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadEntity.java
  17. 8
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java
  18. 4
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/SimpleDownloadUtil.java
  19. 12
      Aria/src/main/java/com/arialyy/aria/core/download/group/AbsGroupUtil.java
  20. 5
      Aria/src/main/java/com/arialyy/aria/core/download/group/DGroupUtil.java
  21. 4
      Aria/src/main/java/com/arialyy/aria/core/download/group/FtpDirDownloadUtil.java
  22. 4
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/BaseM3U8Loader.java
  23. 5
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/ITsMergeHandler.java
  24. 7
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8Delegate.java
  25. 95
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8Entity.java
  26. 89
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8InfoThread.java
  27. 77
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8KeyInfo.java
  28. 5
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8LiveLoader.java
  29. 25
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8TaskConfig.java
  30. 70
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8VodLoader.java
  31. 10
      Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8VodUtil.java
  32. 4
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java
  33. 12
      Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java
  34. 31
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/DGLoadExecutePool.java
  35. 16
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/DGLoadSharePool.java
  36. 4
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/DLoadExecutePool.java
  37. 41
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/DLoadSharePool.java
  38. 4
      Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java
  39. 2
      Aria/src/main/java/com/arialyy/aria/orm/DBConfig.java
  40. 4
      Aria/src/main/java/com/arialyy/aria/orm/DelegateCommon.java
  41. 12
      Aria/src/main/java/com/arialyy/aria/orm/DelegateFind.java
  42. 8
      Aria/src/main/java/com/arialyy/aria/orm/DelegateUpdate.java
  43. 12
      Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java
  44. 2
      Aria/src/main/java/com/arialyy/aria/util/BufferedRandomAccessFile.java
  45. 21
      Aria/src/main/java/com/arialyy/aria/util/CheckUtil.java
  46. 232
      Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java
  47. 4
      Aria/src/main/java/com/arialyy/aria/util/ErrorHelp.java
  48. 239
      Aria/src/main/java/com/arialyy/aria/util/FileUtil.java
  49. 3
      Aria/src/main/java/com/arialyy/aria/util/RecordUtil.java
  50. 11
      DEV_LOG.md
  51. 15
      README.md
  52. 4
      app/src/main/assets/aria_config.xml
  53. 7
      app/src/main/assets/help_code/HttpDownload.java
  54. 31
      app/src/main/java/com/arialyy/simple/core/download/DownloadDialog.java
  55. 2
      app/src/main/java/com/arialyy/simple/core/download/DownloadDialogFragment.java
  56. 30
      app/src/main/java/com/arialyy/simple/core/download/DownloadPopupWindow.java
  57. 4
      app/src/main/java/com/arialyy/simple/core/download/FtpDownloadActivity.java
  58. 2
      app/src/main/java/com/arialyy/simple/core/download/KotlinDownloadActivity.kt
  59. 4
      app/src/main/java/com/arialyy/simple/core/download/SimpleNotification.java
  60. 2
      app/src/main/java/com/arialyy/simple/core/download/SingleTaskActivity.java
  61. 34
      app/src/main/java/com/arialyy/simple/core/download/fragment_download/DownloadFragment.java
  62. 4
      app/src/main/java/com/arialyy/simple/core/download/group/DownloadGroupActivity.java
  63. 2
      app/src/main/java/com/arialyy/simple/core/download/group/FTPDirDownloadActivity.java
  64. 2
      app/src/main/java/com/arialyy/simple/core/download/m3u8/M3U8LiveDLoadActivity.java
  65. 9
      app/src/main/java/com/arialyy/simple/core/download/m3u8/M3U8VodDLoadActivity.java
  66. 10
      app/src/main/java/com/arialyy/simple/core/download/m3u8/VideoPlayerFragment.java
  67. 8
      app/src/main/java/com/arialyy/simple/core/download/multi_download/DownloadAdapter.java
  68. 4
      app/src/main/java/com/arialyy/simple/core/download/multi_download/FileListAdapter.java
  69. 2
      app/src/main/java/com/arialyy/simple/core/download/multi_download/MultiDownloadActivity.java
  70. 2
      app/src/main/java/com/arialyy/simple/core/download/service_download/DownloadService.java
  71. 4
      app/src/main/java/com/arialyy/simple/core/test/AnyRunActivity.java
  72. 2
      app/src/main/java/com/arialyy/simple/core/upload/FtpUploadActivity.java
  73. 4
      app/src/main/java/com/arialyy/simple/core/upload/HttpUploadActivity.java
  74. 4
      app/src/main/java/com/arialyy/simple/modlue/AnyRunnModule.java
  75. 5
      app/src/main/java/com/arialyy/simple/util/AppUtil.java
  76. 21
      app/src/main/res/values/strings.xml
  77. 2
      build.gradle

@ -5,7 +5,7 @@ apply plugin: 'com.jfrog.bintray'
apply plugin: 'com.github.dcendents.android-maven' apply plugin: 'com.github.dcendents.android-maven'
//gradlew bintray //gradlew bintray
//############################## jarsourcesdoc start ####################################### //############################## jarsourcesdoc create #######################################
task sourcesJar(type: Jar) { task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs from android.sourceSets.main.java.srcDirs
classifier = 'sources' classifier = 'sources'
@ -73,7 +73,7 @@ artifacts {
} }
//############################## jarsourcesdoc end ####################################### //############################## jarsourcesdoc end #######################################
//################################# jcenter start ######################################### //################################# jcenter create #########################################
bintray { bintray {
// user = hasProperty("bintrayUser") ? getProperty("bintrayUser") : getProperty("BINTRAY_USER") // user = hasProperty("bintrayUser") ? getProperty("bintrayUser") : getProperty("BINTRAY_USER")
// groupHash = hasProperty("bintrayKey") ? getProperty("bintrayKey") : getProperty("BINTRAY_KEY") // groupHash = hasProperty("bintrayKey") ? getProperty("bintrayKey") : getProperty("BINTRAY_KEY")

@ -43,7 +43,7 @@ import com.arialyy.aria.util.ALog;
* .load(URL) //下载地址,必填 * .load(URL) //下载地址,必填
* //文件保存路径,必填 * //文件保存路径,必填
* .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk") * .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk")
* .start(); * .create();
* </code> * </code>
* <code> * <code>
* //上传 * //上传
@ -51,7 +51,7 @@ import com.arialyy.aria.util.ALog;
* .load(filePath) //文件路径,必填 * .load(filePath) //文件路径,必填
* .setTempUrl(uploadUrl) //上传路径,必填 * .setTempUrl(uploadUrl) //上传路径,必填
* .setAttachment(fileKey) //服务器读取文件的key,必填 * .setAttachment(fileKey) //服务器读取文件的key,必填
* .start(); * .create();
* </code> * </code>
* </pre> * </pre>
* *
@ -67,7 +67,7 @@ import com.arialyy.aria.util.ALog;
* .load(URL) //下载地址,必填 * .load(URL) //下载地址,必填
* //文件保存路径,必填 * //文件保存路径,必填
* .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk") * .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk")
* .start(); * .create();
* *
* </code> * </code>
* *
@ -113,7 +113,7 @@ import com.arialyy.aria.util.ALog;
if (context == null) { if (context == null) {
throw new NullPointerException( throw new NullPointerException(
"context 无效,在非【Activity、Service、Application、DialogFragment、Fragment、PopupWindow、Dialog】," "context 无效,在非【Activity、Service、Application、DialogFragment、Fragment、PopupWindow、Dialog】,"
+ "请参考【https://aria.laoyuyu.me/aria_doc/start/any_java.html】,参数请使用 download(this) 或 upload(this);" + "请参考【https://aria.laoyuyu.me/aria_doc/create/any_java.html】,参数请使用 download(this) 或 upload(this);"
+ "不要使用 download(getContext()) 或 upload(getContext())"); + "不要使用 download(getContext()) 或 upload(getContext())");
} }
return AriaManager.getInstance(context); return AriaManager.getInstance(context);

@ -50,8 +50,8 @@ public abstract class AbsStartTarget<TARGET extends AbsStartTarget> extends AbsT
* @return 正常启动返回任务id否则返回-1 * @return 正常启动返回任务id否则返回-1
*/ */
@Override @Override
public long start() { public long create() {
return getController().start(); return getController().create();
} }
/** /**

@ -34,8 +34,8 @@ import com.arialyy.aria.core.scheduler.ISchedulers;
import com.arialyy.aria.exception.BaseException; import com.arialyy.aria.exception.BaseException;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.BufferedRandomAccessFile; import com.arialyy.aria.util.BufferedRandomAccessFile;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.ErrorHelp; import com.arialyy.aria.util.ErrorHelp;
import com.arialyy.aria.util.FileUtil;
import com.arialyy.aria.util.NetUtils; import com.arialyy.aria.util.NetUtils;
import java.io.File; import java.io.File;
import java.util.UUID; import java.util.UUID;
@ -201,10 +201,12 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
* @param state {@link IThreadState#STATE_STOP}.. * @param state {@link IThreadState#STATE_STOP}..
* @param bundle 而外数据 * @param bundle 而外数据
*/ */
void sendState(int state, @Nullable Bundle bundle) { synchronized void sendState(int state, @Nullable Bundle bundle) {
Message msg = mStateHandler.obtainMessage(); Message msg = mStateHandler.obtainMessage();
msg.what = state; msg.what = state;
if (state != IThreadState.STATE_UPDATE_PROGRESS) {
msg.obj = this; msg.obj = this;
}
if ((state == IThreadState.STATE_COMPLETE || state == IThreadState.STATE_FAIL) if ((state == IThreadState.STATE_COMPLETE || state == IThreadState.STATE_FAIL)
&& (mTaskWrapper.getRequestType() == AbsTaskWrapper.M3U8_VOD && (mTaskWrapper.getRequestType() == AbsTaskWrapper.M3U8_VOD
@ -384,7 +386,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsNormalEntity, TASK_WRAPPER
ALog.w(TAG, String.format("ts切片【%s】正在重试", getFileName())); ALog.w(TAG, String.format("ts切片【%s】正在重试", getFileName()));
mFailTimes++; mFailTimes++;
mConfig.tempFile.delete(); mConfig.tempFile.delete();
CommonUtil.createFile(mConfig.tempFile.getPath()); FileUtil.createFile(mConfig.tempFile.getPath());
ThreadTaskManager.getInstance().retryThread(this); ThreadTaskManager.getInstance().retryThread(this);
} else { } else {
sendFailMsg(null); sendFailMsg(null);

@ -27,6 +27,7 @@ import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.DbDataHelper; import com.arialyy.aria.util.DbDataHelper;
import com.arialyy.aria.util.FileUtil;
import com.arialyy.aria.util.RecordUtil; import com.arialyy.aria.util.RecordUtil;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
@ -261,7 +262,7 @@ public class RecordHandler {
DbEntity.findRelationData(RecordWrapper.class, "TaskRecord.filePath=?", DbEntity.findRelationData(RecordWrapper.class, "TaskRecord.filePath=?",
getFilePath()); getFilePath());
if (records == null || records.size() == 0) { if (records == null || records.size() == 0) {
Properties pro = CommonUtil.loadConfig(mConfigFile); Properties pro = FileUtil.loadConfig(mConfigFile);
if (pro.isEmpty()) { if (pro.isEmpty()) {
ALog.d(TAG, "老版本的线程记录为空,任务为新任务"); ALog.d(TAG, "老版本的线程记录为空,任务为新任务");
initRecord(true); initRecord(true);

@ -17,7 +17,7 @@ package com.arialyy.aria.core.common;
public interface Suggest { public interface Suggest {
String TASK_CONTROLLER = "after use #add()、#start()、#stop()、#cancel()、#resume()、#save()?"; String TASK_CONTROLLER = "after use #add()、#create()、#stop()、#cancel()、#resume()、#save()?";
String TO_CONTROLLER = "after use #controller()?"; String TO_CONTROLLER = "after use #controller()?";
} }

@ -96,12 +96,14 @@ public class ThreadStateManager implements IThreadState {
} }
break; break;
case STATE_RUNNING: case STATE_RUNNING:
if (msg.obj instanceof Long) {
mProgress += (long) msg.obj; mProgress += (long) msg.obj;
}
break; break;
case STATE_UPDATE_PROGRESS: case STATE_UPDATE_PROGRESS:
if (msg.obj == null) { if (msg.obj == null) {
mProgress = updateBlockProgress(); mProgress = updateBlockProgress();
} else { } else if (msg.obj instanceof Long) {
mProgress = (long) msg.obj; mProgress = (long) msg.obj;
} }
break; break;

@ -20,7 +20,7 @@ import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.SOURCE) public @interface ControllerType { @Retention(RetentionPolicy.SOURCE) public @interface ControllerType {
/** /**
* 仅用于第一次创建任务后续可调用`#start()#add()#setHighestPriority()`方法 * 仅用于第一次创建任务后续可调用`#create()#add()#setHighestPriority()`方法
*/ */
Class<StartController> START_CONTROLLER = StartController.class; Class<StartController> START_CONTROLLER = StartController.class;
/** /**

@ -62,7 +62,7 @@ public abstract class FeatureController {
} }
if (wrapper.getEntity().getId() != -1 && clazz != ControllerType.NORMAL_CONTROLLER) { if (wrapper.getEntity().getId() != -1 && clazz != ControllerType.NORMAL_CONTROLLER) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"对于已存在的任务,只能使用\" ControllerType.NORMAL_CONTROLLER\",请检查是否重复调用#start()方法"); "对于已存在的任务,只能使用\" ControllerType.NORMAL_CONTROLLER\",请检查是否重复调用#create()方法");
} }
Class[] paramTypes = { AbsTaskWrapper.class }; Class[] paramTypes = { AbsTaskWrapper.class };

@ -28,11 +28,11 @@ public interface IStartFeature {
long add(); long add();
/** /**
* 开始任务 * 创建并开始任务
* *
* @return 正常启动返回任务id否则返回-1 * @return 正常启动返回任务id否则返回-1
*/ */
long start(); long create();
/** /**
* 将任务设置为最高优先级任务最高优先级任务有以下特点 * 将任务设置为最高优先级任务最高优先级任务有以下特点

@ -49,7 +49,7 @@ public final class StartController extends FeatureController implements IStartFe
* *
* @return 正常启动返回任务id否则返回-1 * @return 正常启动返回任务id否则返回-1
*/ */
public long start() { public long create() {
if (checkConfig()) { if (checkConfig()) {
EventMsgUtil.getDefault() EventMsgUtil.getDefault()
.post(CommonUtil.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_START, .post(CommonUtil.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_START,

@ -36,7 +36,7 @@ import java.util.List;
* return builder.build(); * return builder.build();
* } * }
* }) * })
* .start(); * .create();
* </code> * </code>
* *
* </pre> * </pre>

@ -3,7 +3,7 @@ package com.arialyy.aria.core.config;
import android.text.TextUtils; import android.text.TextUtils;
import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.FileUtil;
import java.io.Serializable; import java.io.Serializable;
abstract class BaseConfig implements Serializable { abstract class BaseConfig implements Serializable {
@ -42,8 +42,8 @@ abstract class BaseConfig implements Serializable {
} }
if (!TextUtils.isEmpty(path)) { if (!TextUtils.isEmpty(path)) {
String tempPath = String.format("%s%s", basePath, path); String tempPath = String.format("%s%s", basePath, path);
CommonUtil.deleteFile(tempPath); FileUtil.deleteFile(tempPath);
CommonUtil.writeObjToFile(tempPath, this); FileUtil.writeObjToFile(tempPath, this);
} else { } else {
ALog.e(TAG, String.format("保存配置失败,配置类型:%s,原因:路径错误", getType())); ALog.e(TAG, String.format("保存配置失败,配置类型:%s,原因:路径错误", getType()));
} }

@ -16,7 +16,7 @@
package com.arialyy.aria.core.config; package com.arialyy.aria.core.config;
import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.FileUtil;
import java.io.File; import java.io.File;
/** /**
@ -45,28 +45,28 @@ public final class Configuration {
File dgCfg = new File(String.format("%s%s", basePath, DGROUP_CONFIG_FILE)); File dgCfg = new File(String.format("%s%s", basePath, DGROUP_CONFIG_FILE));
// 加载下载配置 // 加载下载配置
if (newDCfg.exists()) { if (newDCfg.exists()) {
downloadCfg = (DownloadConfig) CommonUtil.readObjFromFile(newDCfg.getPath()); downloadCfg = (DownloadConfig) FileUtil.readObjFromFile(newDCfg.getPath());
} }
if (downloadCfg == null) { if (downloadCfg == null) {
downloadCfg = new DownloadConfig(); downloadCfg = new DownloadConfig();
} }
// 加载上传配置 // 加载上传配置
if (newUCfg.exists()) { if (newUCfg.exists()) {
uploadCfg = (UploadConfig) CommonUtil.readObjFromFile(newUCfg.getPath()); uploadCfg = (UploadConfig) FileUtil.readObjFromFile(newUCfg.getPath());
} }
if (uploadCfg == null) { if (uploadCfg == null) {
uploadCfg = new UploadConfig(); uploadCfg = new UploadConfig();
} }
// 加载app配置 // 加载app配置
if (newACfg.exists()) { if (newACfg.exists()) {
appCfg = (AppConfig) CommonUtil.readObjFromFile(newACfg.getPath()); appCfg = (AppConfig) FileUtil.readObjFromFile(newACfg.getPath());
} }
if (appCfg == null) { if (appCfg == null) {
appCfg = new AppConfig(); appCfg = new AppConfig();
} }
// 加载下载类型组合任务的配置 // 加载下载类型组合任务的配置
if (dgCfg.exists()) { if (dgCfg.exists()) {
dGroupCfg = (DGroupConfig) CommonUtil.readObjFromFile(dgCfg.getPath()); dGroupCfg = (DGroupConfig) FileUtil.readObjFromFile(dgCfg.getPath());
} }
if (dGroupCfg == null) { if (dGroupCfg == null) {
dGroupCfg = new DGroupConfig(); dGroupCfg = new DGroupConfig();

@ -74,7 +74,11 @@ public class CheckDEntityUtil implements ICheckEntityUtil {
m3U8Entity.setFilePath(mEntity.getFilePath()); m3U8Entity.setFilePath(mEntity.getFilePath());
m3U8Entity.setPeerIndex(0); m3U8Entity.setPeerIndex(0);
m3U8Entity.setCacheDir(cacheDir); m3U8Entity.setCacheDir(cacheDir);
m3U8Entity.setGenerateIndexFile(mWrapper.asM3U8().isGenerateIndexFileTemp());
m3U8Entity.insert(); m3U8Entity.insert();
} else {
m3U8Entity.setGenerateIndexFile(mWrapper.asM3U8().isGenerateIndexFileTemp());
m3U8Entity.update();
} }
if (mWrapper.getRequestType() == ITaskWrapper.M3U8_VOD) { if (mWrapper.getRequestType() == ITaskWrapper.M3U8_VOD) {
if (mEntity.getFileSize() == 0) { if (mEntity.getFileSize() == 0) {

@ -59,6 +59,11 @@ public class DownloadEntity extends AbsNormalEntity implements Parcelable {
@Ignore @Ignore
private M3U8Entity m3U8Entity; private M3U8Entity m3U8Entity;
/**
* 获取m3u8数据信息
*
* @return 如果m3u8信息为空则返回null
*/
public M3U8Entity getM3U8Entity() { public M3U8Entity getM3U8Entity() {
if (TextUtils.isEmpty(downloadPath)) { if (TextUtils.isEmpty(downloadPath)) {
ALog.e("DownloadEntity", "文件保存路径为空,获取m3u8实体之前需要设置文件保存路径"); ALog.e("DownloadEntity", "文件保存路径为空,获取m3u8实体之前需要设置文件保存路径");

@ -73,7 +73,7 @@ public class DownloadReceiver extends AbsReceiver {
/** /**
* 用于任务停止删除等操作 * 用于任务停止删除等操作
* *
* @param taskId 任务id可从{@link AbsStartTarget#start()}{@link AbsStartTarget#add()}{@link * @param taskId 任务id可从{@link AbsStartTarget#create()}{@link AbsStartTarget#add()}{@link
* AbsEntity#getId()}读取任务id * AbsEntity#getId()}读取任务id
*/ */
@CheckResult @CheckResult
@ -96,7 +96,7 @@ public class DownloadReceiver extends AbsReceiver {
/** /**
* 加载组合任务用于任务停止删除等操作 * 加载组合任务用于任务停止删除等操作
* *
* @param taskId 任务id可从{@link AbsStartTarget#start()}{@link AbsStartTarget#add()}{@link * @param taskId 任务id可从{@link AbsStartTarget#create()}{@link AbsStartTarget#add()}{@link
* * AbsEntity#getId()}读取任务id * * AbsEntity#getId()}读取任务id
*/ */
@CheckResult @CheckResult
@ -117,7 +117,7 @@ public class DownloadReceiver extends AbsReceiver {
/** /**
* 用于任务停止删除等操作 * 用于任务停止删除等操作
* *
* @param taskId 任务id可从{@link AbsStartTarget#start()}{@link AbsStartTarget#add()}{@link * @param taskId 任务id可从{@link AbsStartTarget#create()}{@link AbsStartTarget#add()}{@link
* AbsEntity#getId()}读取任务id * AbsEntity#getId()}读取任务id
*/ */
@CheckResult @CheckResult
@ -138,7 +138,7 @@ public class DownloadReceiver extends AbsReceiver {
/** /**
* 加载ftp文件夹下载地址用于任务停止删除等操作 * 加载ftp文件夹下载地址用于任务停止删除等操作
* *
* @param taskId 任务id可从{@link AbsStartTarget#start()}{@link AbsStartTarget#add()}{@link * @param taskId 任务id可从{@link AbsStartTarget#create()}{@link AbsStartTarget#add()}{@link
* AbsEntity#getId()}读取任务id * AbsEntity#getId()}读取任务id
*/ */
@CheckResult @CheckResult

@ -90,9 +90,9 @@ public class SimpleDownloadUtil implements IUtil {
// || mTaskWrapper.isRefreshInfo() // || mTaskWrapper.isRefreshInfo()
// || mTaskWrapper.getRequestType() == AbsTaskWrapper.D_FTP // || mTaskWrapper.getRequestType() == AbsTaskWrapper.D_FTP
// || mTaskWrapper.getState() == IEntity.STATE_FAIL) { // || mTaskWrapper.getState() == IEntity.STATE_FAIL) {
// new Thread(createInfoThread()).start(); // new Thread(createInfoThread()).create();
//} else { //} else {
// mDownloader.start(); // mDownloader.create();
//} //}
new Thread(createInfoThread()).start(); new Thread(createInfoThread()).start();
} }

@ -207,12 +207,18 @@ public abstract class AbsGroupUtil implements IUtil {
closeTimer(); closeTimer();
return; return;
} }
onPreStart(); if (onPreStart()) {
startRunningFlow(); startRunningFlow();
} }
}
protected void onPreStart() { /**
* 处理启动前的检查获取组合任务大小
*
* @return {@code false} 将不再走后续流程任务介绍
*/
protected boolean onPreStart() {
return false;
} }
synchronized void closeTimer() { synchronized void closeTimer() {

@ -68,7 +68,7 @@ public class DGroupUtil extends AbsGroupUtil implements IUtil {
return false; return false;
} }
@Override protected void onPreStart() { @Override protected boolean onPreStart() {
super.onPreStart(); super.onPreStart();
initState(); initState();
if (mState.getCompleteNum() == mState.getSubSize()) { if (mState.getCompleteNum() == mState.getSubSize()) {
@ -85,6 +85,7 @@ public class DGroupUtil extends AbsGroupUtil implements IUtil {
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }
return getLenComplete;
} else { } else {
for (DTaskWrapper wrapper : mGTWrapper.getSubTaskWrapper()) { for (DTaskWrapper wrapper : mGTWrapper.getSubTaskWrapper()) {
if (wrapper.getState() != IEntity.STATE_COMPLETE) { if (wrapper.getState() != IEntity.STATE_COMPLETE) {
@ -93,6 +94,7 @@ public class DGroupUtil extends AbsGroupUtil implements IUtil {
} }
} }
} }
return true;
} }
/** /**
@ -138,6 +140,7 @@ public class DGroupUtil extends AbsGroupUtil implements IUtil {
*/ */
private void checkGetSizeComplete(int count, int failCount) { private void checkGetSizeComplete(int count, int failCount) {
if (failCount == mGTWrapper.getSubTaskWrapper().size()) { if (failCount == mGTWrapper.getSubTaskWrapper().size()) {
mState.isRunning = false;
mListener.onFail(false, new AriaIOException(TAG, "获取子任务长度失败")); mListener.onFail(false, new AriaIOException(TAG, "获取子任务长度失败"));
notifyLock(); notifyLock();
return; return;

@ -45,8 +45,9 @@ public class FtpDirDownloadUtil extends AbsGroupUtil {
return FTP_DIR; return FTP_DIR;
} }
@Override protected void onPreStart() { @Override protected boolean onPreStart() {
super.onPreStart(); super.onPreStart();
if (mGTWrapper.getEntity().getFileSize() > 1) { if (mGTWrapper.getEntity().getFileSize() > 1) {
startDownload(true); startDownload(true);
} else { } else {
@ -71,6 +72,7 @@ public class FtpDirDownloadUtil extends AbsGroupUtil {
LOCK.unlock(); LOCK.unlock();
} }
} }
return true;
} }
/** /**

@ -19,7 +19,7 @@ import com.arialyy.aria.core.common.AbsFileer;
import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.inf.IEventListener; import com.arialyy.aria.core.inf.IEventListener;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.FileUtil;
import java.io.File; import java.io.File;
public abstract class BaseM3U8Loader extends AbsFileer<DownloadEntity, DTaskWrapper> { public abstract class BaseM3U8Loader extends AbsFileer<DownloadEntity, DTaskWrapper> {
@ -46,7 +46,7 @@ public abstract class BaseM3U8Loader extends AbsFileer<DownloadEntity, DTaskWrap
String getCacheDir() { String getCacheDir() {
String cacheDir = mTaskWrapper.asM3U8().getCacheDir(); String cacheDir = mTaskWrapper.asM3U8().getCacheDir();
if (!new File(cacheDir).exists()) { if (!new File(cacheDir).exists()) {
CommonUtil.createDir(cacheDir); FileUtil.createDir(cacheDir);
} }
return cacheDir; return cacheDir;
} }

@ -26,9 +26,10 @@ public interface ITsMergeHandler {
/** /**
* 合并ts文件 * 合并ts文件
* *
* @param keyInfo 密钥信息如果ts文件不是加密的该字段为空 * @param m3U8Entity m3u8信息可通过{@link M3U8Entity#keyPath}{@link M3U8Entity#keyUrl}
* {@link M3U8Entity#iv}{@link M3U8Entity#method} 获取相应的加密信息
* @param tsPath ts文件列表 * @param tsPath ts文件列表
* @return {@code true} 合并成功 * @return {@code true} 合并成功
*/ */
boolean merge(@Nullable M3U8KeyInfo keyInfo, List<String> tsPath); boolean merge(@Nullable M3U8Entity m3U8Entity, List<String> tsPath);
} }

@ -35,11 +35,12 @@ public class M3U8Delegate<TARGET extends AbsTarget> extends BaseDelegate<TARGET>
} }
/** /**
* 生成m3u8索引文件只有{@link #merge(boolean)}设置为false才会有效 * 生成m3u8索引文件
* 注意创建索引文件{@link #merge(boolean)}方法设置与否都不再合并文件
*/ */
@CheckResult(suggest = Suggest.TO_CONTROLLER) @CheckResult(suggest = Suggest.TO_CONTROLLER)
public M3U8Delegate<TARGET> genetateIndexFile() { public M3U8Delegate<TARGET> generateIndexFile() {
mTaskWrapper.asM3U8().setGenerateIndexFile(true); mTaskWrapper.asM3U8().setGenerateIndexFileTemp(true);
return this; return this;
} }

@ -58,6 +58,71 @@ public class M3U8Entity extends DbEntity implements Parcelable {
*/ */
private String cacheDir; private String cacheDir;
/**
* 生成索引
*/
private boolean generateIndexFile;
/**
* 加密key保存地址
*/
public String keyPath;
/**
* 加密key的下载地址
*/
public String keyUrl;
/**
* 加密算法
*/
public String method;
/**
* key的iv值
*/
public String iv;
public String getKeyPath() {
return keyPath;
}
public void setKeyPath(String keyPath) {
this.keyPath = keyPath;
}
public String getKeyUrl() {
return keyUrl;
}
public void setKeyUrl(String keyUrl) {
this.keyUrl = keyUrl;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getIv() {
return iv;
}
public void setIv(String iv) {
this.iv = iv;
}
public boolean isGenerateIndexFile() {
return generateIndexFile;
}
public void setGenerateIndexFile(boolean generateIndexFile) {
this.generateIndexFile = generateIndexFile;
}
public boolean isLive() { public boolean isLive() {
return isLive; return isLive;
} }
@ -163,6 +228,16 @@ public class M3U8Entity extends DbEntity implements Parcelable {
public M3U8Entity() { public M3U8Entity() {
} }
public static class PeerInfo {
public PeerInfo(int peerId, String peerPath) {
this.peerId = peerId;
this.peerPath = peerPath;
}
public int peerId;
public String peerPath;
}
@Override public int describeContents() { @Override public int describeContents() {
return 0; return 0;
} }
@ -173,6 +248,11 @@ public class M3U8Entity extends DbEntity implements Parcelable {
dest.writeInt(this.peerNum); dest.writeInt(this.peerNum);
dest.writeByte(this.isLive ? (byte) 1 : (byte) 0); dest.writeByte(this.isLive ? (byte) 1 : (byte) 0);
dest.writeString(this.cacheDir); dest.writeString(this.cacheDir);
dest.writeByte(this.generateIndexFile ? (byte) 1 : (byte) 0);
dest.writeString(this.keyPath);
dest.writeString(this.keyUrl);
dest.writeString(this.method);
dest.writeString(this.iv);
} }
protected M3U8Entity(Parcel in) { protected M3U8Entity(Parcel in) {
@ -181,6 +261,11 @@ public class M3U8Entity extends DbEntity implements Parcelable {
this.peerNum = in.readInt(); this.peerNum = in.readInt();
this.isLive = in.readByte() != 0; this.isLive = in.readByte() != 0;
this.cacheDir = in.readString(); this.cacheDir = in.readString();
this.generateIndexFile = in.readByte() != 0;
this.keyPath = in.readString();
this.keyUrl = in.readString();
this.method = in.readString();
this.iv = in.readString();
} }
public static final Creator<M3U8Entity> CREATOR = new Creator<M3U8Entity>() { public static final Creator<M3U8Entity> CREATOR = new Creator<M3U8Entity>() {
@ -192,14 +277,4 @@ public class M3U8Entity extends DbEntity implements Parcelable {
return new M3U8Entity[size]; return new M3U8Entity[size];
} }
}; };
public static class PeerInfo {
public PeerInfo(int peerId, String peerPath) {
this.peerId = peerId;
this.peerPath = peerPath;
}
public int peerId;
public String peerPath;
}
} }

@ -16,6 +16,7 @@
package com.arialyy.aria.core.download.m3u8; package com.arialyy.aria.core.download.m3u8;
import android.net.TrafficStats; import android.net.TrafficStats;
import android.net.Uri;
import android.os.Process; import android.os.Process;
import android.text.TextUtils; import android.text.TextUtils;
import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.AriaManager;
@ -32,15 +33,18 @@ import com.arialyy.aria.exception.TaskException;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CheckUtil; import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.FileUtil;
import com.arialyy.aria.util.Regular; import com.arialyy.aria.util.Regular;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@ -53,6 +57,7 @@ import java.util.regex.Pattern;
* https://blog.csdn.net/Guofengpu/article/details/54922865 * https://blog.csdn.net/Guofengpu/article/details/54922865
*/ */
final class M3U8InfoThread implements Runnable { final class M3U8InfoThread implements Runnable {
public static final String M3U8_INDEX_FORMAT = "%s.index";
private final String TAG = "M3U8InfoThread"; private final String TAG = "M3U8InfoThread";
private DownloadEntity mEntity; private DownloadEntity mEntity;
private DTaskWrapper mTaskWrapper; private DTaskWrapper mTaskWrapper;
@ -64,6 +69,10 @@ final class M3U8InfoThread implements Runnable {
* 是否停止获取切片信息{@code true}停止获取切片信息 * 是否停止获取切片信息{@code true}停止获取切片信息
*/ */
private boolean isStop = false; private boolean isStop = false;
/**
* m3u8文件信息
*/
private List<String> mInfos = new ArrayList<>();
interface OnGetLivePeerCallback { interface OnGetLivePeerCallback {
void onGetPeer(String url); void onGetPeer(String url);
@ -110,16 +119,24 @@ final class M3U8InfoThread implements Runnable {
} }
List<String> extInf = new ArrayList<>(); List<String> extInf = new ArrayList<>();
boolean isLive = mTaskWrapper.getRequestType() == ITaskWrapper.M3U8_LIVE; boolean isLive = mTaskWrapper.getRequestType() == ITaskWrapper.M3U8_LIVE;
boolean isGenerateIndexFile = mTaskWrapper.getEntity().getM3U8Entity().isGenerateIndexFile();
if (isGenerateIndexFile) {
mInfos.add(line);
}
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
if (isStop) { if (isStop) {
break; break;
} }
if (isGenerateIndexFile) {
mInfos.add(line);
}
if (line.startsWith("#EXT-X-ENDLIST")) { if (line.startsWith("#EXT-X-ENDLIST")) {
break; break;
} }
ALog.d(TAG, line); //ALog.d(TAG, line);
if (line.startsWith("#EXTINF")) { if (line.startsWith("#EXTINF")) {
String info = reader.readLine(); String info = reader.readLine();
mInfos.add(info);
if (isLive) { if (isLive) {
if (onGetPeerCallback != null) { if (onGetPeerCallback != null) {
onGetPeerCallback.onGetPeer(info); onGetPeerCallback.onGetPeer(info);
@ -130,6 +147,10 @@ final class M3U8InfoThread implements Runnable {
} else if (line.startsWith("#EXT-X-STREAM-INF")) { } else if (line.startsWith("#EXT-X-STREAM-INF")) {
int setBand = mTaskWrapper.asM3U8().getBandWidth(); int setBand = mTaskWrapper.asM3U8().getBandWidth();
int bandWidth = getBandWidth(line); int bandWidth = getBandWidth(line);
// 多码率的m3u8配置文件,清空信息
if (isGenerateIndexFile && mInfos != null) {
mInfos.clear();
}
if (setBand == 0) { if (setBand == 0) {
handleBandWidth(conn, reader.readLine()); handleBandWidth(conn, reader.readLine());
} else if (bandWidth == setBand) { } else if (bandWidth == setBand) {
@ -153,6 +174,7 @@ final class M3U8InfoThread implements Runnable {
} }
CompleteInfo info = new CompleteInfo(); CompleteInfo info = new CompleteInfo();
info.obj = extInf; info.obj = extInf;
generateIndexFile();
onFileInfoCallback.onComplete(mEntity.getKey(), info); onFileInfoCallback.onComplete(mEntity.getKey(), info);
} else if (code == HttpURLConnection.HTTP_MOVED_TEMP } else if (code == HttpURLConnection.HTTP_MOVED_TEMP
|| code == HttpURLConnection.HTTP_MOVED_PERM || code == HttpURLConnection.HTTP_MOVED_PERM
@ -167,6 +189,43 @@ final class M3U8InfoThread implements Runnable {
} }
} }
/**
* 创建索引文件
*/
private void generateIndexFile() {
if (mTaskWrapper.getEntity().getM3U8Entity().isGenerateIndexFile()) {
String indexPath = String.format(M3U8_INDEX_FORMAT, mEntity.getFilePath());
File indexFile = new File(indexPath);
if (indexFile.exists()) {
FileUtil.deleteFile(indexPath);
}
FileUtil.createFile(indexPath);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(indexFile);
for (String str : mInfos) {
byte[] by = str.concat("\r\n").getBytes(Charset.forName("UTF-8"));
fos.write(by, 0, by.length);
}
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
/** /**
* 是否停止获取切片信息{@code true}停止获取切片信息 * 是否停止获取切片信息{@code true}停止获取切片信息
*/ */
@ -187,20 +246,19 @@ final class M3U8InfoThread implements Runnable {
private void getKeyInfo(String line) { private void getKeyInfo(String line) {
String temp = line.substring(line.indexOf(":") + 1); String temp = line.substring(line.indexOf(":") + 1);
String[] params = temp.split(","); String[] params = temp.split(",");
M3U8KeyInfo keyInfo = new M3U8KeyInfo(); M3U8Entity m3U8Entity = mEntity.getM3U8Entity();
for (String param : params) { for (String param : params) {
if (param.startsWith("METHOD")) { if (param.startsWith("METHOD")) {
keyInfo.method = param.split("=")[1]; m3U8Entity.method = param.split("=")[1];
} else if (param.startsWith("URI")) { } else if (param.startsWith("URI")) {
keyInfo.keyUrl = param.split("=")[1].replaceAll("\"", ""); m3U8Entity.keyUrl = param.split("=")[1].replaceAll("\"", "");
keyInfo.keyPath = new File(mEntity.getFilePath()).getParent() + "/" + CommonUtil.getStrMd5( m3U8Entity.keyPath = new File(mEntity.getFilePath()).getParent() + "/" + CommonUtil.getStrMd5(
keyInfo.keyUrl) + ".key"; m3U8Entity.keyUrl) + ".key";
} else if (param.startsWith("IV")) { } else if (param.startsWith("IV")) {
keyInfo.iv = param.split("=")[1]; m3U8Entity.iv = param.split("=")[1];
} }
} }
mTaskWrapper.asM3U8().setKeyInfo(keyInfo); downloadKey(m3U8Entity);
DownloadKey(keyInfo);
} }
/** /**
@ -220,13 +278,18 @@ final class M3U8InfoThread implements Runnable {
*/ */
private void handleUrlReTurn(HttpURLConnection conn, String newUrl) throws IOException { private void handleUrlReTurn(HttpURLConnection conn, String newUrl) throws IOException {
ALog.d(TAG, "30x跳转,新url为【" + newUrl + "】"); ALog.d(TAG, "30x跳转,新url为【" + newUrl + "】");
if (TextUtils.isEmpty(newUrl) || newUrl.equalsIgnoreCase("null") || !newUrl.startsWith( if (TextUtils.isEmpty(newUrl) || newUrl.equalsIgnoreCase("null")) {
"http")) {
if (onFileInfoCallback != null) { if (onFileInfoCallback != null) {
onFileInfoCallback.onFail(mEntity, new TaskException(TAG, "获取重定向链接失败"), false); onFileInfoCallback.onFail(mEntity, new TaskException(TAG, "获取重定向链接失败"), false);
} }
return; return;
} }
if (newUrl.startsWith("/")) {
Uri uri = Uri.parse(mEntity.getUrl());
newUrl = uri.getHost() + newUrl;
}
if (!CheckUtil.checkUrlNotThrow(newUrl)) { if (!CheckUtil.checkUrlNotThrow(newUrl)) {
failDownload("下载失败,重定向url错误", false); failDownload("下载失败,重定向url错误", false);
return; return;
@ -281,14 +344,14 @@ final class M3U8InfoThread implements Runnable {
/** /**
* 密钥不存在下载密钥 * 密钥不存在下载密钥
*/ */
private void DownloadKey(M3U8KeyInfo info) { private void downloadKey(M3U8Entity info) {
HttpURLConnection conn = null; HttpURLConnection conn = null;
FileOutputStream fos = null; FileOutputStream fos = null;
try { try {
File keyF = new File(info.keyPath); File keyF = new File(info.keyPath);
if (!keyF.exists()) { if (!keyF.exists()) {
ALog.d(TAG, "密钥不存在,下载密钥"); ALog.d(TAG, "密钥不存在,下载密钥");
CommonUtil.createFile(keyF.getPath()); FileUtil.createFile(keyF.getPath());
} else { } else {
return; return;
} }

@ -1,77 +0,0 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.download.m3u8;
import android.os.Parcel;
import android.os.Parcelable;
/**
* m3u8加密密钥信息
*/
public class M3U8KeyInfo implements Parcelable {
/**
* 加密key保存地址
*/
public String keyPath;
/**
* 加密key的下载地址
*/
public String keyUrl;
/**
* 加密算法
*/
public String method;
/**
* key的iv值
*/
public String iv;
@Override public int describeContents() {
return 0;
}
@Override public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.keyPath);
dest.writeString(this.keyUrl);
dest.writeString(this.method);
dest.writeString(this.iv);
}
public M3U8KeyInfo() {
}
protected M3U8KeyInfo(Parcel in) {
this.keyPath = in.readString();
this.keyUrl = in.readString();
this.method = in.readString();
this.iv = in.readString();
}
public static final Parcelable.Creator<M3U8KeyInfo> CREATOR =
new Parcelable.Creator<M3U8KeyInfo>() {
@Override public M3U8KeyInfo createFromParcel(Parcel source) {
return new M3U8KeyInfo(source);
}
@Override public M3U8KeyInfo[] newArray(int size) {
return new M3U8KeyInfo[size];
}
};
}

@ -26,7 +26,6 @@ import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.inf.IEventListener; import com.arialyy.aria.core.inf.IEventListener;
import com.arialyy.aria.core.manager.ThreadTaskManager; import com.arialyy.aria.core.manager.ThreadTaskManager;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.FileUtil; import com.arialyy.aria.util.FileUtil;
import com.arialyy.aria.util.IdGenerator; import com.arialyy.aria.util.IdGenerator;
import java.io.File; import java.io.File;
@ -143,7 +142,7 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
config.stateHandler = mStateHandler; config.stateHandler = mStateHandler;
if (!config.tempFile.exists()) { if (!config.tempFile.exists()) {
CommonUtil.createFile(config.tempFile.getPath()); FileUtil.createFile(config.tempFile.getPath());
} }
return new M3U8ThreadTask(config); return new M3U8ThreadTask(config);
} }
@ -168,7 +167,7 @@ public class M3U8LiveLoader extends BaseM3U8Loader {
boolean isSuccess; boolean isSuccess;
if (mergeHandler != null) { if (mergeHandler != null) {
isSuccess = mergeHandler.merge(mTaskWrapper.asM3U8().getKeyInfo(), partPath); isSuccess = mergeHandler.merge(getEntity().getM3U8Entity(), partPath);
} else { } else {
isSuccess = FileUtil.mergeFile(mEntity.getFilePath(), partPath); isSuccess = FileUtil.mergeFile(mEntity.getFilePath(), partPath);
} }

@ -73,11 +73,6 @@ public class M3U8TaskConfig {
*/ */
private String bandWidthUrl; private String bandWidthUrl;
/**
* ts密钥信息
*/
private M3U8KeyInfo keyInfo;
/** /**
* 直播下载ts url转换器 * 直播下载ts url转换器
*/ */
@ -99,16 +94,16 @@ public class M3U8TaskConfig {
private int jumpIndex; private int jumpIndex;
/** /**
* 生成索引 * 生成索引占位字段
*/ */
private boolean generateIndexFile; private boolean generateIndexFileTemp;
public boolean isGenerateIndexFile() { public boolean isGenerateIndexFileTemp() {
return generateIndexFile; return generateIndexFileTemp;
} }
public void setGenerateIndexFile(boolean generateIndexFile) { public void setGenerateIndexFileTemp(boolean generateIndexFileTemp) {
this.generateIndexFile = generateIndexFile; this.generateIndexFileTemp = generateIndexFileTemp;
} }
public int getJumpIndex() { public int getJumpIndex() {
@ -143,14 +138,6 @@ public class M3U8TaskConfig {
this.liveTsUrlConverter = new WeakReference<>(liveTsUrlConverter); this.liveTsUrlConverter = new WeakReference<>(liveTsUrlConverter);
} }
public M3U8KeyInfo getKeyInfo() {
return keyInfo;
}
public void setKeyInfo(M3U8KeyInfo keyInfo) {
this.keyInfo = keyInfo;
}
public String getBandWidthUrl() { public String getBandWidthUrl() {
return bandWidthUrl; return bandWidthUrl;
} }

@ -35,9 +35,15 @@ import com.arialyy.aria.core.manager.ThreadTaskManager;
import com.arialyy.aria.core.scheduler.ISchedulers; import com.arialyy.aria.core.scheduler.ISchedulers;
import com.arialyy.aria.exception.BaseException; import com.arialyy.aria.exception.BaseException;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.FileUtil; import com.arialyy.aria.util.FileUtil;
import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
@ -422,7 +428,7 @@ public class M3U8VodLoader extends BaseM3U8Loader {
config.stateHandler = mStateHandler; config.stateHandler = mStateHandler;
config.peerIndex = index; config.peerIndex = index;
if (!config.tempFile.exists()) { if (!config.tempFile.exists()) {
CommonUtil.createFile(config.tempFile.getPath()); FileUtil.createFile(config.tempFile.getPath());
} }
return new M3U8ThreadTask(config); return new M3U8ThreadTask(config);
} }
@ -610,6 +616,9 @@ public class M3U8VodLoader extends BaseM3U8Loader {
* @return {@code true} 合并成功{@code false}合并失败 * @return {@code true} 合并成功{@code false}合并失败
*/ */
private boolean mergeFile() { private boolean mergeFile() {
if (getEntity().getM3U8Entity().isGenerateIndexFile()) {
return generateIndexFile();
}
ITsMergeHandler mergeHandler = mTaskWrapper.asM3U8().getMergeHandler(); ITsMergeHandler mergeHandler = mTaskWrapper.asM3U8().getMergeHandler();
String cacheDir = getCacheDir(); String cacheDir = getCacheDir();
List<String> partPath = new ArrayList<>(); List<String> partPath = new ArrayList<>();
@ -618,7 +627,7 @@ public class M3U8VodLoader extends BaseM3U8Loader {
} }
boolean isSuccess; boolean isSuccess;
if (mergeHandler != null) { if (mergeHandler != null) {
isSuccess = mergeHandler.merge(mTaskWrapper.asM3U8().getKeyInfo(), partPath); isSuccess = mergeHandler.merge(getEntity().getM3U8Entity(), partPath);
if (mergeHandler.getClass().isAnonymousClass()) { if (mergeHandler.getClass().isAnonymousClass()) {
mTaskWrapper.asM3U8().setMergeHandler(null); mTaskWrapper.asM3U8().setMergeHandler(null);
@ -646,6 +655,61 @@ public class M3U8VodLoader extends BaseM3U8Loader {
} }
} }
/**
* 创建索引文件
*/
private boolean generateIndexFile() {
File tempFile = new File(M3U8InfoThread.M3U8_INDEX_FORMAT, getEntity().getFilePath());
if (!tempFile.exists()) {
ALog.e(TAG, "源索引文件不存在");
return false;
}
FileInputStream fis = null;
FileOutputStream fos = null;
try {
String cacheDir = getCacheDir();
fis = new FileInputStream(tempFile);
fos = new FileOutputStream(getEntity().getFilePath());
BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
String line;
int i = 0;
while ((line = reader.readLine()) != null) {
byte[] bytes;
if (line.startsWith("EXTINF")) {
String tsPath = getTsFilePath(cacheDir, mRecord.threadRecords.get(i).threadId);
bytes = tsPath.concat("\r\n").getBytes(Charset.forName("UTF-8"));
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,
m3U8Entity.keyPath, m3U8Entity.iv);
bytes = keyInfo.getBytes(Charset.forName("UTF-8"));
} else {
bytes = line.getBytes(Charset.forName("UTF-8"));
}
fos.write(bytes, 0, bytes.length);
}
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
}
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
private static class TempFlag { private static class TempFlag {
AbsThreadTask threadTask; AbsThreadTask threadTask;
int threadId; int threadId;

@ -24,7 +24,7 @@ import com.arialyy.aria.core.download.M3U8Listener;
import com.arialyy.aria.core.inf.AbsEntity; import com.arialyy.aria.core.inf.AbsEntity;
import com.arialyy.aria.exception.BaseException; import com.arialyy.aria.exception.BaseException;
import com.arialyy.aria.exception.M3U8Exception; import com.arialyy.aria.exception.M3U8Exception;
import com.arialyy.aria.util.ALog; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -83,7 +83,15 @@ public class M3U8VodUtil implements IUtil {
return; return;
} }
mListener.onPre(); mListener.onPre();
// peer数量小于0,
M3U8Entity m3U8Entity = mWrapper.getEntity().getM3U8Entity();
if (m3U8Entity.getPeerNum() <= 0 || (m3U8Entity.isGenerateIndexFile() && !new File(
String.format(M3U8InfoThread.M3U8_INDEX_FORMAT,
mWrapper.getEntity().getFilePath())).exists())) {
getVodInfo(); getVodInfo();
} else {
mLoader.start();
}
} }
/** /**

@ -84,10 +84,10 @@ public abstract class AbsTarget<TARGET extends AbsTarget> {
/** /**
* 重置状态将任务状态设置为未开始状态 * 重置状态将任务状态设置为未开始状态
* 注意如果在后续方法调用链中没有调用 {@link NormalController#stop()}{@link NormalController#cancel()} * 注意如果在后续方法调用链中没有调用 {@link NormalController#stop()}{@link NormalController#cancel()}
* {@link NormalController#resume()}{@link StartController#start()}{@link StartController#add()} * {@link NormalController#resume()}{@link StartController#create()}{@link StartController#add()}
* 等操作任务的方法那么你需要调用{@link NormalController#save()}才能将修改保存到数据库 * 等操作任务的方法那么你需要调用{@link NormalController#save()}才能将修改保存到数据库
*/ */
@CheckResult(suggest = "after use #start()、#stop()、#cancel()、#resume()、#save()?") @CheckResult(suggest = "after use #create()、#stop()、#cancel()、#resume()、#save()?")
public TARGET resetState() { public TARGET resetState() {
getTaskWrapper().getEntity().setState(IEntity.STATE_WAIT); getTaskWrapper().getEntity().setState(IEntity.STATE_WAIT);
getTaskWrapper().setRefreshInfo(true); getTaskWrapper().setRefreshInfo(true);

@ -26,7 +26,8 @@ import com.arialyy.aria.core.manager.TaskWrapperManager;
import com.arialyy.aria.core.manager.ThreadTaskManager; import com.arialyy.aria.core.manager.ThreadTaskManager;
import com.arialyy.aria.core.queue.pool.BaseCachePool; import com.arialyy.aria.core.queue.pool.BaseCachePool;
import com.arialyy.aria.core.queue.pool.BaseExecutePool; import com.arialyy.aria.core.queue.pool.BaseExecutePool;
import com.arialyy.aria.core.queue.pool.DownloadSharePool; import com.arialyy.aria.core.queue.pool.DGLoadSharePool;
import com.arialyy.aria.core.queue.pool.DLoadSharePool;
import com.arialyy.aria.core.queue.pool.UploadSharePool; import com.arialyy.aria.core.queue.pool.UploadSharePool;
import com.arialyy.aria.core.upload.UploadTask; import com.arialyy.aria.core.upload.UploadTask;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
@ -47,9 +48,12 @@ public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends Ab
AbsTaskQueue() { AbsTaskQueue() {
switch (getQueueType()) { switch (getQueueType()) {
case TYPE_D_QUEUE: case TYPE_D_QUEUE:
mCachePool = DLoadSharePool.getInstance().cachePool;
mExecutePool = DLoadSharePool.getInstance().executePool;
break;
case TYPE_DG_QUEUE: case TYPE_DG_QUEUE:
mCachePool = DownloadSharePool.getInstance().cachePool; mCachePool = DGLoadSharePool.getInstance().cachePool;
mExecutePool = DownloadSharePool.getInstance().executePool; mExecutePool = DGLoadSharePool.getInstance().executePool;
break; break;
case TYPE_U_QUEUE: case TYPE_U_QUEUE:
mCachePool = UploadSharePool.getInstance().cachePool; mCachePool = UploadSharePool.getInstance().cachePool;
@ -210,7 +214,7 @@ public abstract class AbsTaskQueue<TASK extends AbsTask, TASK_WRAPPER extends Ab
@Override public void startTask(TASK task) { @Override public void startTask(TASK task) {
if (task == null) { if (task == null) {
ALog.w(TAG, "start fail, task is null"); ALog.w(TAG, "create fail, task is null");
} }
if (mExecutePool.taskExits(task.getKey())) { if (mExecutePool.taskExits(task.getKey())) {
ALog.w(TAG, String.format("任务【%s】执行中", task.getKey())); ALog.w(TAG, String.format("任务【%s】执行中", task.getKey()));

@ -0,0 +1,31 @@
/*
* 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.queue.pool;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.inf.AbsTask;
/**
* Created by AriaL on 2017/6/29.
* 单个下载任务的执行池
*/
class DGLoadExecutePool<TASK extends AbsTask> extends DLoadExecutePool<TASK> {
private final String TAG = "DGLoadExecutePool";
@Override protected int getMaxSize() {
return AriaManager.getInstance(AriaManager.APP).getDGroupConfig().getMaxTaskNum();
}
}

@ -19,21 +19,21 @@ package com.arialyy.aria.core.queue.pool;
* Created by Aria.Lao on 2017/7/17. * Created by Aria.Lao on 2017/7/17.
* 下载任务池该池子为简单任务和任务组共用 * 下载任务池该池子为简单任务和任务组共用
*/ */
public class DownloadSharePool { public class DGLoadSharePool {
private static volatile DownloadSharePool INSTANCE; private static volatile DGLoadSharePool INSTANCE;
public DownloadExecutePool executePool; public DGLoadExecutePool executePool;
public BaseCachePool cachePool; public BaseCachePool cachePool;
private DownloadSharePool() { private DGLoadSharePool() {
executePool = new DownloadExecutePool<>(); executePool = new DGLoadExecutePool<>();
cachePool = new BaseCachePool<>(); cachePool = new BaseCachePool<>();
} }
public static DownloadSharePool getInstance() { public static DGLoadSharePool getInstance() {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (DownloadSharePool.class) { synchronized (DGLoadSharePool.class) {
INSTANCE = new DownloadSharePool(); INSTANCE = new DGLoadSharePool();
} }
} }
return INSTANCE; return INSTANCE;

@ -26,7 +26,7 @@ import java.util.concurrent.TimeUnit;
* Created by AriaL on 2017/6/29. * Created by AriaL on 2017/6/29.
* 单个下载任务的执行池 * 单个下载任务的执行池
*/ */
class DownloadExecutePool<TASK extends AbsTask> extends BaseExecutePool<TASK> { class DLoadExecutePool<TASK extends AbsTask> extends BaseExecutePool<TASK> {
private final String TAG = "DownloadExecutePool"; private final String TAG = "DownloadExecutePool";
@Override protected int getMaxSize() { @Override protected int getMaxSize() {
@ -34,7 +34,7 @@ class DownloadExecutePool<TASK extends AbsTask> extends BaseExecutePool<TASK> {
} }
@Override public boolean putTask(TASK task) { @Override public boolean putTask(TASK task) {
synchronized (DownloadExecutePool.class) { synchronized (DLoadExecutePool.class) {
if (task == null) { if (task == null) {
ALog.e(TAG, "任务不能为空!!"); ALog.e(TAG, "任务不能为空!!");
return false; return false;

@ -0,0 +1,41 @@
/*
* 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.queue.pool;
/**
* Created by Aria.Lao on 2017/7/17.
* 下载任务池该池子为简单任务和任务组共用
*/
public class DLoadSharePool {
private static volatile DLoadSharePool INSTANCE;
public DLoadExecutePool executePool;
public BaseCachePool cachePool;
private DLoadSharePool() {
executePool = new DLoadExecutePool<>();
cachePool = new BaseCachePool<>();
}
public static DLoadSharePool getInstance() {
if (INSTANCE == null) {
synchronized (DLoadSharePool.class) {
INSTANCE = new DLoadSharePool();
}
}
return INSTANCE;
}
}

@ -70,7 +70,7 @@ public class UploadReceiver extends AbsReceiver {
/** /**
* 用于任务停止删除等操作 * 用于任务停止删除等操作
* *
* @param taskId 任务id可从{@link AbsStartTarget#start()}{@link AbsStartTarget#add()}{@link * @param taskId 任务id可从{@link AbsStartTarget#create()}{@link AbsStartTarget#add()}{@link
* AbsEntity#getId()}读取任务id * AbsEntity#getId()}读取任务id
*/ */
@CheckResult @CheckResult
@ -93,7 +93,7 @@ public class UploadReceiver extends AbsReceiver {
/** /**
* 加载FTP单文件上传任务用于任务第一次上传如果需要控制任务停止或删除等操作请使用{@link #load(long)} * 加载FTP单文件上传任务用于任务第一次上传如果需要控制任务停止或删除等操作请使用{@link #load(long)}
* *
* @param taskId 任务id可从{@link AbsStartTarget#start()}{@link AbsStartTarget#add()}{@link * @param taskId 任务id可从{@link AbsStartTarget#create()}{@link AbsStartTarget#add()}{@link
* AbsEntity#getId()}读取任务id * AbsEntity#getId()}读取任务id
*/ */
@CheckResult @CheckResult

@ -38,7 +38,7 @@ class DBConfig {
static boolean DEBUG = false; static boolean DEBUG = false;
static Map<String, Class> mapping = new LinkedHashMap<>(); static Map<String, Class> mapping = new LinkedHashMap<>();
static String DB_NAME; static String DB_NAME;
static int VERSION = 52; static int VERSION = 55;
/** /**
* 是否将数据库保存在Sd卡{@code true} * 是否将数据库保存在Sd卡{@code true}

@ -106,7 +106,9 @@ class DelegateCommon extends AbsDelegate {
*/ */
boolean checkDataExist(SQLiteDatabase db, Class clazz, String... expression) { boolean checkDataExist(SQLiteDatabase db, Class clazz, String... expression) {
db = checkDb(db); db = checkDb(db);
CheckUtil.checkSqlExpression(expression); if (!CheckUtil.checkSqlExpression(expression)) {
return false;
}
String sql = String.format("SELECT rowid, * FROM %s WHERE %s ", CommonUtil.getClassName(clazz), String sql = String.format("SELECT rowid, * FROM %s WHERE %s ", CommonUtil.getClassName(clazz),
expression[0]); expression[0]);
sql = sql.replace("?", "%s"); sql = sql.replace("?", "%s");

@ -198,7 +198,9 @@ class DelegateFind extends AbsDelegate {
.append(cTableName.concat(".").concat(m.entityColumn())); .append(cTableName.concat(".").concat(m.entityColumn()));
String sql; String sql;
if (expression != null && expression.length > 0) { if (expression != null && expression.length > 0) {
CheckUtil.checkSqlExpression(expression); if (!CheckUtil.checkSqlExpression(expression)) {
return null;
}
sb.append(" WHERE ").append(expression[0]).append(" "); sb.append(" WHERE ").append(expression[0]).append(" ");
sql = sb.toString(); sql = sb.toString();
sql = sql.replace("?", "%s"); sql = sql.replace("?", "%s");
@ -318,7 +320,9 @@ class DelegateFind extends AbsDelegate {
*/ */
<T extends DbEntity> List<T> findData(SQLiteDatabase db, Class<T> clazz, String... expression) { <T extends DbEntity> List<T> findData(SQLiteDatabase db, Class<T> clazz, String... expression) {
db = checkDb(db); db = checkDb(db);
CheckUtil.checkSqlExpression(expression); if (!CheckUtil.checkSqlExpression(expression)) {
return null;
}
String sql = String.format("SELECT rowid, * FROM %s WHERE %s", CommonUtil.getClassName(clazz), String sql = String.format("SELECT rowid, * FROM %s WHERE %s", CommonUtil.getClassName(clazz),
expression[0]); expression[0]);
String[] params = new String[expression.length - 1]; String[] params = new String[expression.length - 1];
@ -336,7 +340,9 @@ class DelegateFind extends AbsDelegate {
return null; return null;
} }
db = checkDb(db); db = checkDb(db);
CheckUtil.checkSqlExpression(expression); if (!CheckUtil.checkSqlExpression(expression)) {
return null;
}
String sql = String.format("SELECT rowid, * FROM %s WHERE %s LIMIT %s,%s", String sql = String.format("SELECT rowid, * FROM %s WHERE %s LIMIT %s,%s",
CommonUtil.getClassName(clazz), CommonUtil.getClassName(clazz),
expression[0], (page - 1) * num, num); expression[0], (page - 1) * num, num);

@ -40,7 +40,9 @@ class DelegateUpdate extends AbsDelegate {
synchronized <T extends DbEntity> void delData(SQLiteDatabase db, Class<T> clazz, synchronized <T extends DbEntity> void delData(SQLiteDatabase db, Class<T> clazz,
String... expression) { String... expression) {
db = checkDb(db); db = checkDb(db);
CheckUtil.checkSqlExpression(expression); if (!CheckUtil.checkSqlExpression(expression)) {
return;
}
String sql = "DELETE FROM " + CommonUtil.getClassName(clazz) + " WHERE " + expression[0] + " "; String sql = "DELETE FROM " + CommonUtil.getClassName(clazz) + " WHERE " + expression[0] + " ";
sql = sql.replace("?", "%s"); sql = sql.replace("?", "%s");
@ -60,7 +62,7 @@ class DelegateUpdate extends AbsDelegate {
ContentValues values = createValues(dbEntity); ContentValues values = createValues(dbEntity);
if (values != null) { if (values != null) {
db.update(CommonUtil.getClassName(dbEntity), values, "rowid=?", db.update(CommonUtil.getClassName(dbEntity), values, "rowid=?",
new String[] {String.valueOf(dbEntity.rowID)}); new String[] { String.valueOf(dbEntity.rowID) });
} else { } else {
ALog.e(TAG, "更新记录失败,记录没有属性字段"); ALog.e(TAG, "更新记录失败,记录没有属性字段");
} }
@ -84,7 +86,7 @@ class DelegateUpdate extends AbsDelegate {
if (value == null) { if (value == null) {
ALog.e(TAG, "更新记录失败,记录没有属性字段"); ALog.e(TAG, "更新记录失败,记录没有属性字段");
} else { } else {
db.update(table, value, "rowid=?", new String[] {String.valueOf(entity.rowID)}); db.update(table, value, "rowid=?", new String[] { String.valueOf(entity.rowID) });
} }
} }
db.setTransactionSuccessful(); db.setTransactionSuccessful();

@ -100,7 +100,7 @@ final class SqlHelper extends SQLiteOpenHelper {
handle360AriaUpdate(db); handle360AriaUpdate(db);
} else if (oldVersion < 51) { } else if (oldVersion < 51) {
handle365Update(db); handle365Update(db);
} else if (oldVersion < 52) { } else if (oldVersion < 53) {
handle366Update(db); handle366Update(db);
} else { } else {
handleDbUpdate(db, null, null); handleDbUpdate(db, null, null);
@ -240,12 +240,9 @@ final class SqlHelper extends SQLiteOpenHelper {
* 删除重复的repeat数据 * 删除重复的repeat数据
*/ */
private void delRepeatThreadRecord(SQLiteDatabase db) { private void delRepeatThreadRecord(SQLiteDatabase db) {
String repeatSql = String repeatSql = "DELETE FROM ThreadRecord WHERE (rowid) "
"DELETE FROM ThreadRecord WHERE (taskKey, threadId, endLocation) " + "IN (SELECT rowid FROM ThreadRecord GROUP BY taskKey, threadId, endLocation HAVING COUNT(*) > 1) "
+ "IN (SELECT taskKey, threadId, endLocation FROM ThreadRecord GROUP BY taskKey, threadId, endLocation " + "AND rowid NOT IN (SELECT MIN(rowid) FROM ThreadRecord GROUP BY taskKey, threadId, endLocation HAVING COUNT(*)> 1)";
+ "HAVING COUNT(*) > 1) AND rowid "
+ "NOT IN (SELECT MIN(rowid) FROM ThreadRecord GROUP BY taskKey, threadId, endLocation "
+ "HAVING COUNT(*)> 1)";
ALog.d(TAG, repeatSql); ALog.d(TAG, repeatSql);
db.execSQL(repeatSql); db.execSQL(repeatSql);
} }
@ -262,6 +259,7 @@ final class SqlHelper extends SQLiteOpenHelper {
// 执行升级操作 // 执行升级操作
handleDbUpdate(db, modifyMap, null); handleDbUpdate(db, modifyMap, null);
delRepeatThreadRecord(db);
} }
/** /**

@ -208,7 +208,7 @@ public final class BufferedRandomAccessFile extends RandomAccessFile {
if (pos >= this.hi_ || pos < this.lo_) { if (pos >= this.hi_ || pos < this.lo_) {
// seeking outside of current buffer -- flush and read // seeking outside of current buffer -- flush and read
this.flushBuffer(); this.flushBuffer();
this.lo_ = pos & BuffMask_; // start at BuffSz boundary this.lo_ = pos & BuffMask_; // create at BuffSz boundary
this.maxHi_ = this.lo_ + (long) this.buff_.length; this.maxHi_ = this.lo_ + (long) this.buff_.length;
if (this.diskPos_ != this.lo_) { if (this.diskPos_ != this.lo_) {
super.seek(this.lo_); super.seek(this.lo_);

@ -24,6 +24,7 @@ import com.arialyy.aria.core.upload.UTaskWrapper;
import com.arialyy.aria.core.upload.UploadEntity; import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.exception.ParamException; import com.arialyy.aria.exception.ParamException;
import java.io.File; import java.io.File;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -68,17 +69,22 @@ public class CheckUtil {
/** /**
* 检查sql的expression是否合法 * 检查sql的expression是否合法
*
* @return false 不合法
*/ */
public static void checkSqlExpression(String... expression) { public static boolean checkSqlExpression(String... expression) {
if (expression.length == 0) { if (expression.length == 0) {
throw new IllegalArgumentException("sql语句表达式不能为null"); ALog.e(TAG, "sql语句表达式不能为null");
return false;
} }
if (expression.length == 1) { if (expression.length == 1) {
throw new IllegalArgumentException("表达式需要写入参数"); ALog.e(TAG, String.format("表达式需要写入参数,参数信息:%s", Arrays.toString(expression)));
return false;
} }
String where = expression[0]; String where = expression[0];
if (!where.contains("?")) { if (!where.contains("?")) {
throw new IllegalArgumentException("请在where语句的'='后编写?"); ALog.e(TAG, String.format("请在where语句的'='后编写?,参数信息:%s", Arrays.toString(expression)));
return false;
} }
Pattern pattern = Pattern.compile("\\?"); Pattern pattern = Pattern.compile("\\?");
Matcher matcher = pattern.matcher(where); Matcher matcher = pattern.matcher(where);
@ -87,11 +93,14 @@ public class CheckUtil {
count++; count++;
} }
if (count < expression.length - 1) { if (count < expression.length - 1) {
throw new IllegalArgumentException("条件语句的?个数不能小于参数个数"); ALog.e(TAG, String.format("条件语句的?个数不能小于参数个数,参数信息:%s", Arrays.toString(expression)));
return false;
} }
if (count > expression.length - 1) { if (count > expression.length - 1) {
throw new IllegalArgumentException("条件语句的?个数不能大于参数个数"); ALog.e(TAG, String.format("条件语句的?个数不能大于参数个数, 参数信息:%s", Arrays.toString(expression)));
return false;
} }
return true;
} }
/** /**

@ -29,10 +29,10 @@ import com.arialyy.aria.core.FtpUrlEntity;
import com.arialyy.aria.core.command.AbsGroupCmd; import com.arialyy.aria.core.command.AbsGroupCmd;
import com.arialyy.aria.core.command.AbsNormalCmd; import com.arialyy.aria.core.command.AbsNormalCmd;
import com.arialyy.aria.core.command.GroupCmdFactory; import com.arialyy.aria.core.command.GroupCmdFactory;
import com.arialyy.aria.core.command.ICmd;
import com.arialyy.aria.core.command.NormalCmdFactory; import com.arialyy.aria.core.command.NormalCmdFactory;
import com.arialyy.aria.core.inf.AbsGroupTaskWrapper; import com.arialyy.aria.core.inf.AbsGroupTaskWrapper;
import com.arialyy.aria.core.inf.AbsTaskWrapper; import com.arialyy.aria.core.inf.AbsTaskWrapper;
import com.arialyy.aria.core.inf.ITask;
import dalvik.system.DexFile; import dalvik.system.DexFile;
import java.io.File; import java.io.File;
import java.io.FileFilter; import java.io.FileFilter;
@ -41,9 +41,6 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
@ -59,7 +56,6 @@ import java.util.Enumeration;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -99,102 +95,6 @@ public class CommonUtil {
return new String(str.getBytes(charSet), SERVER_CHARSET); return new String(str.getBytes(charSet), SERVER_CHARSET);
} }
/**
* 删除文件
*
* @param path 文件路径
* @return {@code true}删除成功{@code false}删除失败
*/
public static boolean deleteFile(String path) {
if (TextUtils.isEmpty(path)) {
ALog.e(TAG, "删除文件失败,路径为空");
return false;
}
File file = new File(path);
if (file.exists()) {
final File to = new File(file.getAbsolutePath() + System.currentTimeMillis());
if (file.renameTo(to)) {
return to.delete();
} else {
return file.delete();
}
}
return false;
}
/**
* 将对象写入文件
*
* @param filePath 文件路径
* @param data data数据必须实现{@link Serializable}接口
*/
public static void writeObjToFile(String filePath, Object data) {
if (!(data instanceof Serializable)) {
ALog.e(TAG, "对象写入文件失败,data数据必须实现Serializable接口");
return;
}
FileOutputStream ops = null;
try {
if (!createFile(filePath)) {
return;
}
ops = new FileOutputStream(filePath);
ObjectOutputStream oops = new ObjectOutputStream(ops);
oops.writeObject(data);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ops != null) {
try {
ops.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 从文件中读取对象
*
* @param filePath 文件路径
* @return 如果读取成功返回相应的Obj对象读取失败返回null
*/
public static Object readObjFromFile(String filePath) {
if (TextUtils.isEmpty(filePath)) {
ALog.e(TAG, "文件路径为空");
return null;
}
File file = new File(filePath);
if (!file.exists()) {
ALog.e(TAG, String.format("文件【%s】不存在", filePath));
return null;
}
FileInputStream fis = null;
try {
fis = new FileInputStream(filePath);
ObjectInputStream oois = new ObjectInputStream(fis);
return oois.readObject();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
/** /**
* 检查SD内存空间是否充足 * 检查SD内存空间是否充足
* *
@ -409,32 +309,6 @@ public class CommonUtil {
return null; return null;
} }
/**
* 创建文件名如果url链接有后缀名则使用url中的后缀名
*
* @return url hashKey
*/
public static String createFileName(String url) {
int end = url.indexOf("?");
String tempUrl, fileName = "";
if (end > 0) {
tempUrl = url.substring(0, end);
int tempEnd = tempUrl.lastIndexOf("/");
if (tempEnd > 0) {
fileName = tempUrl.substring(tempEnd + 1);
}
} else {
int tempEnd = url.lastIndexOf("/");
if (tempEnd > 0) {
fileName = url.substring(tempEnd + 1);
}
}
if (TextUtils.isEmpty(fileName)) {
fileName = CommonUtil.keyToHashKey(url);
}
return fileName;
}
/** /**
* 分割获取url协议ip/域名端口内容 * 分割获取url协议ip/域名端口内容
* *
@ -720,8 +594,7 @@ public class CommonUtil {
/** /**
* 创建任务命令 * 创建任务命令
* *
* @param taskType {@link ICmd#TASK_TYPE_DOWNLOAD}{@link ICmd#TASK_TYPE_DOWNLOAD_GROUP}{@link * @param taskType {@link ITask#DOWNLOAD}{@link ITask#DOWNLOAD_GROUP}{@link ITask#UPLOAD}
* ICmd#TASK_TYPE_UPLOAD}
*/ */
public static <T extends AbsTaskWrapper> AbsNormalCmd createNormalCmd(T entity, int cmd, public static <T extends AbsTaskWrapper> AbsNormalCmd createNormalCmd(T entity, int cmd,
int taskType) { int taskType) {
@ -939,59 +812,6 @@ public class CommonUtil {
return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "tb"; return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "tb";
} }
/**
* 创建目录 当目录不存在的时候创建文件否则返回false
*/
public static boolean createDir(String path) {
File file = new File(path);
if (!file.exists()) {
if (!file.mkdirs()) {
ALog.d(TAG, "创建失败,请检查路径和是否配置文件权限!");
return false;
}
return true;
}
return false;
}
/**
* 创建文件 当文件不存在的时候就创建一个文件 如果文件存在先删除原文件然后重新创建一个新文件
*
* @return {@code true} 创建成功{@code false} 创建失败
*/
public static boolean createFile(String path) {
if (TextUtils.isEmpty(path)) {
ALog.e(TAG, "文件路径不能为null");
return false;
}
File file = new File(path);
if (file.getParentFile() == null || !file.getParentFile().exists()) {
ALog.d(TAG, "目标文件所在路径不存在,准备创建……");
if (!createDir(file.getParent())) {
ALog.d(TAG, "创建目录文件所在的目录失败!文件路径【" + path + "】");
}
}
// 创建目标文件
if (file.exists()) {
final File to = new File(file.getAbsolutePath() + System.currentTimeMillis());
if (file.renameTo(to)) {
to.delete();
} else {
file.delete();
}
}
try {
if (file.createNewFile()) {
//ALog.d(TAG, "创建文件成功:" + file.getAbsolutePath());
return true;
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
return false;
}
/** /**
* 通过文件名获取下载配置文件路径 * 通过文件名获取下载配置文件路径
* *
@ -1001,52 +821,4 @@ public class CommonUtil {
return AriaManager.APP.getFilesDir().getPath() + (isDownload ? AriaManager.DOWNLOAD_TEMP_DIR return AriaManager.APP.getFilesDir().getPath() + (isDownload ? AriaManager.DOWNLOAD_TEMP_DIR
: AriaManager.UPLOAD_TEMP_DIR) + fileName + ".properties"; : AriaManager.UPLOAD_TEMP_DIR) + fileName + ".properties";
} }
/**
* 读取下载配置文件
*/
public static Properties loadConfig(File file) {
Properties properties = new Properties();
FileInputStream fis = null;
if (!file.exists()) {
createFile(file.getPath());
}
try {
fis = new FileInputStream(file);
properties.load(fis);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return properties;
}
/**
* 保存配置文件
*/
public static void saveConfig(File file, Properties properties) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file, false);
properties.store(fos, null);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.flush();
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
} }

@ -77,8 +77,8 @@ public class ErrorHelp {
PrintWriter writer = null; PrintWriter writer = null;
try { try {
File file = new File(getLogPath()); File file = new File(getLogPath());
if(!file.exists()){ if (!file.exists()) {
CommonUtil.createFile(file.getPath()); FileUtil.createFile(file.getPath());
} }
writer = new PrintWriter(new FileWriter(file.getPath(), true)); writer = new PrintWriter(new FileWriter(file.getPath(), true));
writer.append(stringBuffer); writer.append(stringBuffer);

@ -30,7 +30,10 @@ import java.io.FileOutputStream;
import java.io.FileReader; import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.SequenceInputStream; import java.io.SequenceInputStream;
import java.io.Serializable;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.Channels; import java.nio.channels.Channels;
@ -43,6 +46,7 @@ import java.util.Enumeration;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Properties;
import java.util.Scanner; import java.util.Scanner;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -55,6 +59,181 @@ public class FileUtil {
private static final String EXTERNAL_STORAGE_PATH = private static final String EXTERNAL_STORAGE_PATH =
Environment.getExternalStorageDirectory().getPath(); Environment.getExternalStorageDirectory().getPath();
/**
* 创建目录 当目录不存在的时候创建文件否则返回false
*/
public static boolean createDir(String path) {
File file = new File(path);
if (!file.exists()) {
if (!file.mkdirs()) {
ALog.d(TAG, "创建失败,请检查路径和是否配置文件权限!");
return false;
}
return true;
}
return false;
}
/**
* 创建文件 当文件不存在的时候就创建一个文件 如果文件存在先删除原文件然后重新创建一个新文件
*
* @return {@code true} 创建成功{@code false} 创建失败
*/
public static boolean createFile(String path) {
if (TextUtils.isEmpty(path)) {
ALog.e(TAG, "文件路径不能为null");
return false;
}
File file = new File(path);
if (file.getParentFile() == null || !file.getParentFile().exists()) {
ALog.d(TAG, "目标文件所在路径不存在,准备创建……");
if (!createDir(file.getParent())) {
ALog.d(TAG, "创建目录文件所在的目录失败!文件路径【" + path + "】");
}
}
// 创建目标文件
if (file.exists()) {
final File to = new File(file.getAbsolutePath() + System.currentTimeMillis());
if (file.renameTo(to)) {
to.delete();
} else {
file.delete();
}
}
try {
if (file.createNewFile()) {
//ALog.d(TAG, "创建文件成功:" + file.getAbsolutePath());
return true;
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
return false;
}
/**
* 创建文件名如果url链接有后缀名则使用url中的后缀名
*
* @return url hashKey
*/
public static String createFileName(String url) {
int end = url.indexOf("?");
String tempUrl, fileName = "";
if (end > 0) {
tempUrl = url.substring(0, end);
int tempEnd = tempUrl.lastIndexOf("/");
if (tempEnd > 0) {
fileName = tempUrl.substring(tempEnd + 1);
}
} else {
int tempEnd = url.lastIndexOf("/");
if (tempEnd > 0) {
fileName = url.substring(tempEnd + 1);
}
}
if (TextUtils.isEmpty(fileName)) {
fileName = CommonUtil.keyToHashKey(url);
}
return fileName;
}
/**
* 删除文件
*
* @param path 文件路径
* @return {@code true}删除成功{@code false}删除失败
*/
public static boolean deleteFile(String path) {
if (TextUtils.isEmpty(path)) {
ALog.e(TAG, "删除文件失败,路径为空");
return false;
}
File file = new File(path);
if (file.exists()) {
final File to = new File(file.getAbsolutePath() + System.currentTimeMillis());
if (file.renameTo(to)) {
return to.delete();
} else {
return file.delete();
}
}
return false;
}
/**
* 将对象写入文件
*
* @param filePath 文件路径
* @param data data数据必须实现{@link Serializable}接口
*/
public static void writeObjToFile(String filePath, Object data) {
if (!(data instanceof Serializable)) {
ALog.e(TAG, "对象写入文件失败,data数据必须实现Serializable接口");
return;
}
FileOutputStream ops = null;
try {
if (!createFile(filePath)) {
return;
}
ops = new FileOutputStream(filePath);
ObjectOutputStream oops = new ObjectOutputStream(ops);
oops.writeObject(data);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ops != null) {
try {
ops.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 从文件中读取对象
*
* @param filePath 文件路径
* @return 如果读取成功返回相应的Obj对象读取失败返回null
*/
public static Object readObjFromFile(String filePath) {
if (TextUtils.isEmpty(filePath)) {
ALog.e(TAG, "文件路径为空");
return null;
}
File file = new File(filePath);
if (!file.exists()) {
ALog.e(TAG, String.format("文件【%s】不存在", filePath));
return null;
}
FileInputStream fis = null;
try {
fis = new FileInputStream(filePath);
ObjectInputStream oois = new ObjectInputStream(fis);
return oois.readObject();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
/** /**
* 合并文件 * 合并文件
* *
@ -186,6 +365,54 @@ public class FileUtil {
return paths; return paths;
} }
/**
* 读取下载配置文件
*/
public static Properties loadConfig(File file) {
Properties properties = new Properties();
FileInputStream fis = null;
if (!file.exists()) {
createFile(file.getPath());
}
try {
fis = new FileInputStream(file);
properties.load(fis);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return properties;
}
/**
* 保存配置文件
*/
public static void saveConfig(File file, Properties properties) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file, false);
properties.store(fos, null);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.flush();
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/** /**
* getSDPathList * getSDPathList
*/ */
@ -258,8 +485,10 @@ public class FileUtil {
} }
/** /**
* Raturns all available SD-Cards in the system (include emulated) Warning: Hack! Based on Android source code of version 4.3 * Raturns all available SD-Cards in the system (include emulated) Warning: Hack! Based on Android
* (API 18) Because there is no standard way to get it. TODO: Test on future Android versions 4.2+ * source code of version 4.3
* (API 18) Because there is no standard way to get it. TODO: Test on future Android versions
* 4.2+
* *
* @return paths to all available SD-Cards in the system (include emulated) * @return paths to all available SD-Cards in the system (include emulated)
*/ */
@ -322,9 +551,11 @@ public class FileUtil {
} }
/** /**
* Scan the /proc/mounts file and look for lines like this: /dev/block/vold/179:1 /mnt/sdcard vfat * Scan the /proc/mounts file and look for lines like this: /dev/block/vold/179:1 /mnt/sdcard
* vfat
* rw,dirsync,nosuid,nodev,noexec ,relatime,uid=1000,gid=1015,fmask=0602,dmask=0602,allow_utime=0020, * rw,dirsync,nosuid,nodev,noexec ,relatime,uid=1000,gid=1015,fmask=0602,dmask=0602,allow_utime=0020,
* codepage=cp437,iocharset= iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 0 When one is found, split it into its * codepage=cp437,iocharset= iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 0 When one is
* found, split it into its
* elements and then pull out the path to the that mount point and add it to the arraylist * elements and then pull out the path to the that mount point and add it to the arraylist
*/ */
private static List<String> readMountsFile() { private static List<String> readMountsFile() {

@ -22,6 +22,7 @@ import com.arialyy.aria.core.common.TaskRecord;
import com.arialyy.aria.core.common.ThreadRecord; import com.arialyy.aria.core.common.ThreadRecord;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity; import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.download.m3u8.M3U8Entity;
import com.arialyy.aria.core.inf.AbsEntity; import com.arialyy.aria.core.inf.AbsEntity;
import com.arialyy.aria.core.inf.AbsNormalEntity; import com.arialyy.aria.core.inf.AbsNormalEntity;
import com.arialyy.aria.core.upload.UploadEntity; import com.arialyy.aria.core.upload.UploadEntity;
@ -237,6 +238,8 @@ public class RecordUtil {
ALog.i(TAG, "删除任务记录"); ALog.i(TAG, "删除任务记录");
DbEntity.deleteData(ThreadRecord.class, "taskKey=?", filePath); DbEntity.deleteData(ThreadRecord.class, "taskKey=?", filePath);
DbEntity.deleteData(TaskRecord.class, "filePath=?", filePath); DbEntity.deleteData(TaskRecord.class, "filePath=?", filePath);
// 处理m3u8实体的删除
DbEntity.deleteData(M3U8Entity.class, "filePath=?", filePath);
} }
/** /**

@ -2,7 +2,16 @@
+ v_3.7 + v_3.7
- 适配androidX - 适配androidX
- 修复组合任务,恢复下载,会出现进度显示为0的问题 - 修复组合任务,恢复下载,会出现进度显示为0的问题
+ v_3.6.5 + v_3.6.6
- fix bug https://github.com/AriaLyy/Aria/issues/426
- fix bug https://github.com/AriaLyy/Aria/issues/429
- fix bug https://github.com/AriaLyy/Aria/issues/428
- fix bug https://github.com/AriaLyy/Aria/issues/427
- fix bug https://github.com/AriaLyy/Aria/issues/431
- fix bug https://github.com/AriaLyy/Aria/issues/441
- 修复普通下载任务、组合任务共享执行队列、缓存池的问题
- 修复组合任务启动失败时,`DownloadGroupEntity`的状态变为执行中的问题
+ v_3.6.5 (2019/7/17)
- fix bug https://github.com/AriaLyy/Aria/issues/403 - fix bug https://github.com/AriaLyy/Aria/issues/403
- fix bug https://github.com/AriaLyy/Aria/issues/414 - fix bug https://github.com/AriaLyy/Aria/issues/414
- fix bug https://github.com/AriaLyy/Aria/issues/406 - fix bug https://github.com/AriaLyy/Aria/issues/406

@ -72,12 +72,21 @@ __⚠注意:3.5.4以下版本升级时,需要更新[配置文件](https:/
## 使用Aria ## 使用Aria
### 基本使用 ### 基本使用
例子为单任务下载,只需要很简单的代码,便可以实现下载功能 例子为单任务下载,只需要很简单的代码,便可以实现下载功能。
* 创建任务
```java ```java
Aria.download(this) long taskId = Aria.download(this)
.load(DOWNLOAD_URL) //读取下载地址 .load(DOWNLOAD_URL) //读取下载地址
.setFilePath(DOWNLOAD_PATH) //设置文件保存的完整路径 .setFilePath(DOWNLOAD_PATH) //设置文件保存的完整路径
.start(); //启动下载 .create(); //创建并启动下载
```
* 停止\恢复任务
```java
Aria.download(this)
.load(taskId) //读取任务id
.stop(); // 停止任务
//.resume(); // 恢复任务
``` ```
### 任务状态的获取 ### 任务状态的获取

@ -113,7 +113,7 @@
<dGroup> <dGroup>
<!--组合任务下载队列最大任务数, 默认为2--> <!--组合任务下载队列最大任务数, 默认为2-->
<maxTaskNum value="1"/> <maxTaskNum value="2"/>
<!--设置下载失败,重试次数,默认为10--> <!--设置下载失败,重试次数,默认为10-->
<reTryNum value="1"/> <reTryNum value="1"/>
@ -131,7 +131,7 @@
<!-- =============================以下为子任务的配置====================================--> <!-- =============================以下为子任务的配置====================================-->
<!--能同时下载的子任务最大任务数,默认3--> <!--能同时下载的子任务最大任务数,默认3-->
<subMaxTaskNum value="1"/> <subMaxTaskNum value="5"/>
<!--子任务下载失败时的重试次数,默认为5--> <!--子任务下载失败时的重试次数,默认为5-->
<subReTryNum value="5"/> <subReTryNum value="5"/>

@ -22,16 +22,11 @@ import android.util.Log;
import android.view.View; import android.view.View;
import com.arialyy.annotations.Download; import com.arialyy.annotations.Download;
import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.common.ftp.FtpInterceptHandler;
import com.arialyy.aria.core.common.ftp.IFtpUploadInterceptor;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.upload.UploadTask;
import com.arialyy.frame.util.FileUtil; import com.arialyy.frame.util.FileUtil;
import com.arialyy.frame.util.show.T; import com.arialyy.frame.util.show.T;
import com.arialyy.simple.R; import com.arialyy.simple.R;
import java.io.File; import java.io.File;
import java.util.List;
/** /**
* Created by lyy on 2017/7/28. HTTP 文件下载demo * Created by lyy on 2017/7/28. HTTP 文件下载demo
@ -64,7 +59,7 @@ public class FtpUpload extends Activity {
//.addHeader(key, value) // 添加头 //.addHeader(key, value) // 添加头
//.asPost() //或 asGet() //.asPost() //或 asGet()
//.setParam() // 设置参数 //.setParam() // 设置参数
.start(); .create();
} }
break; break;
case R.id.cancel: case R.id.cancel:

@ -28,7 +28,6 @@ import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.frame.core.AbsDialog; import com.arialyy.frame.core.AbsDialog;
import com.arialyy.simple.R; import com.arialyy.simple.R;
import com.arialyy.simple.util.AppUtil;
import com.arialyy.simple.widget.HorizontalProgressBarWithNumber; import com.arialyy.simple.widget.HorizontalProgressBarWithNumber;
/** /**
@ -40,7 +39,7 @@ public class DownloadDialog extends AbsDialog implements View.OnClickListener {
private Button mCancel; private Button mCancel;
private TextView mSize; private TextView mSize;
private TextView mSpeed; private TextView mSpeed;
private DownloadEntity mEntity; private long mTaskId = -1;
private static final String DOWNLOAD_URL = private static final String DOWNLOAD_URL =
"http://static.gaoshouyou.com/d/4b/d7/e04b308d9cd7f0ad4cac18d1a514544c.apk"; "http://static.gaoshouyou.com/d/4b/d7/e04b308d9cd7f0ad4cac18d1a514544c.apk";
@ -61,13 +60,14 @@ public class DownloadDialog extends AbsDialog implements View.OnClickListener {
mCancel = findViewById(R.id.cancel); mCancel = findViewById(R.id.cancel);
mSize = findViewById(R.id.size); mSize = findViewById(R.id.size);
mSpeed = findViewById(R.id.speed); mSpeed = findViewById(R.id.speed);
mEntity = Aria.download(this).getFirstDownloadEntity(DOWNLOAD_URL); DownloadEntity entity = Aria.download(this).getFirstDownloadEntity(DOWNLOAD_URL);
if (mEntity != null) { if (entity != null) {
mSize.setText(CommonUtil.formatFileSize(mEntity.getFileSize())); mSize.setText(CommonUtil.formatFileSize(entity.getFileSize()));
int p = (int) (mEntity.getCurrentProgress() * 100 / mEntity.getFileSize()); int p = (int) (entity.getCurrentProgress() * 100 / entity.getFileSize());
mPb.setProgress(p); mPb.setProgress(p);
int state = mEntity.getState(); int state = entity.getState();
setBtState(state != DownloadEntity.STATE_RUNNING); setBtState(state != DownloadEntity.STATE_RUNNING);
mTaskId = entity.getId();
} else { } else {
setBtState(true); setBtState(true);
} }
@ -79,28 +79,27 @@ public class DownloadDialog extends AbsDialog implements View.OnClickListener {
public void onClick(View view) { public void onClick(View view) {
switch (view.getId()) { switch (view.getId()) {
case R.id.start: case R.id.start:
if (!AppUtil.chekEntityValid(mEntity)) { if (mTaskId == -1) {
Aria.download(this) mTaskId = Aria.download(this)
.load(DOWNLOAD_URL) .load(DOWNLOAD_URL)
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/飞机大战.apk") .setFilePath(Environment.getExternalStorageDirectory().getPath() + "/飞机大战.apk")
.start(); .create();
mStart.setText(getContext().getString(R.string.stop)); mStart.setText(getContext().getString(R.string.stop));
break; break;
} }
if (Aria.download(this).load(mEntity.getId()).isRunning()) { if (Aria.download(this).load(mTaskId).isRunning()) {
Aria.download(this).load(mEntity.getId()).stop(); Aria.download(this).load(mTaskId).stop();
mStart.setText(getContext().getString(R.string.resume)); mStart.setText(getContext().getString(R.string.resume));
} else { } else {
Aria.download(this).load(mEntity.getId()).resume(); Aria.download(this).load(mTaskId).resume();
mStart.setText(getContext().getString(R.string.stop)); mStart.setText(getContext().getString(R.string.stop));
} }
break; break;
case R.id.cancel: case R.id.cancel:
if (AppUtil.chekEntityValid(mEntity)) { Aria.download(this).load(mTaskId).cancel();
Aria.download(this).load(mEntity.getId()).cancel(); mTaskId = -1;
mStart.setText(getContext().getString(R.string.start)); mStart.setText(getContext().getString(R.string.start));
}
break; break;
} }
} }

@ -106,7 +106,7 @@ import com.arialyy.simple.util.AppUtil;
Aria.download(getContext()) Aria.download(getContext())
.load(DOWNLOAD_URL) .load(DOWNLOAD_URL)
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/放置江湖.apk") .setFilePath(Environment.getExternalStorageDirectory().getPath() + "/放置江湖.apk")
.start(); .create();
getBinding().setStateStr(getString(R.string.stop)); getBinding().setStateStr(getString(R.string.stop));
break; break;
} }

@ -31,7 +31,6 @@ import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.frame.core.AbsPopupWindow; import com.arialyy.frame.core.AbsPopupWindow;
import com.arialyy.simple.R; import com.arialyy.simple.R;
import com.arialyy.simple.util.AppUtil;
import com.arialyy.simple.widget.HorizontalProgressBarWithNumber; import com.arialyy.simple.widget.HorizontalProgressBarWithNumber;
/** /**
@ -43,7 +42,7 @@ public class DownloadPopupWindow extends AbsPopupWindow implements View.OnClickL
private Button mCancel; private Button mCancel;
private TextView mSize; private TextView mSize;
private TextView mSpeed; private TextView mSpeed;
private DownloadEntity mEntity; private long mTaskId = -1;
private static final String DOWNLOAD_URL = private static final String DOWNLOAD_URL =
"http://static.gaoshouyou.com/d/25/57/2e25bd9d4557ba31e9beebacfaf9e804.apk"; "http://static.gaoshouyou.com/d/25/57/2e25bd9d4557ba31e9beebacfaf9e804.apk";
@ -67,15 +66,16 @@ public class DownloadPopupWindow extends AbsPopupWindow implements View.OnClickL
mStart.setOnClickListener(this); mStart.setOnClickListener(this);
mCancel.setOnClickListener(this); mCancel.setOnClickListener(this);
mEntity = Aria.download(this).getFirstDownloadEntity(DOWNLOAD_URL); DownloadEntity entity = Aria.download(this).getFirstDownloadEntity(DOWNLOAD_URL);
if (mEntity != null) { if (entity != null) {
mPb.setProgress(mEntity.getPercent()); mPb.setProgress(entity.getPercent());
mSize.setText(CommonUtil.formatFileSize(mEntity.getFileSize())); mSize.setText(CommonUtil.formatFileSize(entity.getFileSize()));
if (mEntity.getState() == IEntity.STATE_RUNNING) { if (entity.getState() == IEntity.STATE_RUNNING) {
mStart.setText(getContext().getString(R.string.stop)); mStart.setText(getContext().getString(R.string.stop));
} else { } else {
mStart.setText(getContext().getString(R.string.resume)); mStart.setText(getContext().getString(R.string.resume));
} }
mTaskId = entity.getId();
} else { } else {
mStart.setText(getContext().getString(R.string.start)); mStart.setText(getContext().getString(R.string.start));
} }
@ -86,28 +86,28 @@ public class DownloadPopupWindow extends AbsPopupWindow implements View.OnClickL
public void onClick(View view) { public void onClick(View view) {
switch (view.getId()) { switch (view.getId()) {
case R.id.start: case R.id.start:
if (!AppUtil.chekEntityValid(mEntity)) { if (mTaskId != -1) {
Aria.download(this) Aria.download(this)
.load(DOWNLOAD_URL) .load(DOWNLOAD_URL)
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/消消乐.apk") .setFilePath(Environment.getExternalStorageDirectory().getPath() + "/消消乐.apk")
.start(); .create();
mStart.setText(getContext().getString(R.string.stop)); mStart.setText(getContext().getString(R.string.stop));
break; break;
} }
if (Aria.download(this).load(mEntity.getId()).isRunning()) { if (Aria.download(this).load(mTaskId).isRunning()) {
Aria.download(this).load(mEntity.getId()).stop(); Aria.download(this).load(mTaskId).stop();
mStart.setText(getContext().getString(R.string.resume)); mStart.setText(getContext().getString(R.string.resume));
} else { } else {
Aria.download(this).load(mEntity.getId()).resume(); Aria.download(this).load(mTaskId).resume();
mStart.setText(getContext().getString(R.string.stop)); mStart.setText(getContext().getString(R.string.stop));
} }
break; break;
case R.id.cancel: case R.id.cancel:
if (AppUtil.chekEntityValid(mEntity)) {
Aria.download(this).load(mEntity.getId()).cancel(); Aria.download(this).load(mTaskId).cancel();
} mStart.setText(getContext().getResources().getString(R.string.start));
mTaskId = -1;
break; break;
} }
} }

@ -96,7 +96,7 @@ public class FtpDownloadActivity extends BaseActivity<ActivityFtpDownloadBinding
.option() .option()
.login("8L8e", "8guD") .login("8L8e", "8guD")
.controller(ControllerType.START_CONTROLLER) .controller(ControllerType.START_CONTROLLER)
.start(); .create();
getBinding().setStateStr(getString(R.string.stop)); getBinding().setStateStr(getString(R.string.stop));
break; break;
} }
@ -143,7 +143,7 @@ public class FtpDownloadActivity extends BaseActivity<ActivityFtpDownloadBinding
} }
@Download.onTaskStart() void taskStart(DownloadTask task) { @Download.onTaskStart() void taskStart(DownloadTask task) {
L.d(TAG, "ftp task start"); L.d(TAG, "ftp task create");
} }
@Download.onTaskRunning() protected void running(DownloadTask task) { @Download.onTaskRunning() protected void running(DownloadTask task) {

@ -283,7 +283,7 @@ class KotlinDownloadActivity : BaseActivity<ActivitySingleKotlinBinding>() {
//.addHeader("Cookie", "BAIDUID=648E5FF020CC69E8DD6F492D1068AAA9:FG=1; BIDUPSID=648E5FF020CC69E8DD6F492D1068AAA9; PSTM=1519099573; BD_UPN=12314753; locale=zh; BDSVRTM=0") //.addHeader("Cookie", "BAIDUID=648E5FF020CC69E8DD6F492D1068AAA9:FG=1; BIDUPSID=648E5FF020CC69E8DD6F492D1068AAA9; PSTM=1519099573; BD_UPN=12314753; locale=zh; BDSVRTM=0")
.useServerFileName(true) .useServerFileName(true)
.setFilePath(mFilePath!!, true) .setFilePath(mFilePath!!, true)
.start() .create()
} }
override fun onStop() { override fun onStop() {

@ -54,11 +54,11 @@
// Aria.download(this).register(); // Aria.download(this).register();
// } // }
// //
// public void start() { // public void create() {
// Aria.download(this) // Aria.download(this)
// .load(DOWNLOAD_URL) // .load(DOWNLOAD_URL)
// .setFilePath(Environment.getExternalStorageDirectory() + "/Download/消灭星星.apk") // .setFilePath(Environment.getExternalStorageDirectory() + "/Download/消灭星星.apk")
// .start(); // .create();
// } // }
// //
// public void stop() { // public void stop() {

@ -306,7 +306,7 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
.option() .option()
.addHeader("1", "@") .addHeader("1", "@")
.controller(ControllerType.START_CONTROLLER) .controller(ControllerType.START_CONTROLLER)
.start(); .create();
} }
@Override @Override

@ -29,7 +29,6 @@ import com.arialyy.aria.util.CommonUtil;
import com.arialyy.frame.core.AbsFragment; import com.arialyy.frame.core.AbsFragment;
import com.arialyy.simple.R; import com.arialyy.simple.R;
import com.arialyy.simple.databinding.FragmentDownloadBinding; import com.arialyy.simple.databinding.FragmentDownloadBinding;
import com.arialyy.simple.util.AppUtil;
/** /**
* Created by lyy on 2017/1/4. * Created by lyy on 2017/1/4.
@ -38,7 +37,7 @@ public class DownloadFragment extends AbsFragment<FragmentDownloadBinding>
implements View.OnClickListener { implements View.OnClickListener {
Button mStart; Button mStart;
Button mCancel; Button mCancel;
private DownloadEntity mEntity; private long mTaskId = -1;
private static final String DOWNLOAD_URL = private static final String DOWNLOAD_URL =
"https://res5.d.cn/2137e42d610b3488d9420c6421529386eee5bdbfd9be1fafe0a05d6dabaec8c156ddbd00581055bbaeac03904fb63310e80010680235d16bd4c040b50096a0c20dd1c4b0854529a1.apk"; "https://res5.d.cn/2137e42d610b3488d9420c6421529386eee5bdbfd9be1fafe0a05d6dabaec8c156ddbd00581055bbaeac03904fb63310e80010680235d16bd4c040b50096a0c20dd1c4b0854529a1.apk";
@ -49,16 +48,17 @@ public class DownloadFragment extends AbsFragment<FragmentDownloadBinding>
mStart.setOnClickListener(this); mStart.setOnClickListener(this);
mCancel.setOnClickListener(this); mCancel.setOnClickListener(this);
mEntity = Aria.download(this).getFirstDownloadEntity(DOWNLOAD_URL); DownloadEntity entity = Aria.download(this).getFirstDownloadEntity(DOWNLOAD_URL);
if (mEntity != null) { if (entity != null) {
getBinding().setFileSize(CommonUtil.formatFileSize(mEntity.getFileSize())); getBinding().setFileSize(CommonUtil.formatFileSize(entity.getFileSize()));
int state = mEntity.getState(); int state = entity.getState();
getBinding().setProgress(mEntity.getPercent()); getBinding().setProgress(entity.getPercent());
if (mEntity.getState() == IEntity.STATE_RUNNING) { if (entity.getState() == IEntity.STATE_RUNNING) {
getBinding().setStateStr(getString(R.string.stop)); getBinding().setStateStr(getString(R.string.stop));
} else { } else {
getBinding().setStateStr(getString(R.string.resume)); getBinding().setStateStr(getString(R.string.resume));
} }
mTaskId = entity.getId();
} else { } else {
getBinding().setStateStr(getString(R.string.start)); getBinding().setStateStr(getString(R.string.start));
} }
@ -68,27 +68,27 @@ public class DownloadFragment extends AbsFragment<FragmentDownloadBinding>
public void onClick(View view) { public void onClick(View view) {
switch (view.getId()) { switch (view.getId()) {
case R.id.start: case R.id.start:
if (!AppUtil.chekEntityValid(mEntity)) { if (mTaskId == -1) {
Aria.download(this) mTaskId = Aria.download(this)
.load(DOWNLOAD_URL) .load(DOWNLOAD_URL)
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/王者军团.apk") .setFilePath(Environment.getExternalStorageDirectory().getPath() + "/王者军团.apk")
.start(); .create();
getBinding().setStateStr(getString(R.string.stop)); getBinding().setStateStr(getString(R.string.stop));
break; break;
} }
if (Aria.download(this).load(mEntity.getId()).isRunning()) { if (Aria.download(this).load(mTaskId).isRunning()) {
Aria.download(this).load(mEntity.getId()).stop(); Aria.download(this).load(mTaskId).stop();
getBinding().setStateStr(getString(R.string.resume)); getBinding().setStateStr(getString(R.string.resume));
} else { } else {
Aria.download(this).load(mEntity.getId()).resume(); Aria.download(this).load(mTaskId).resume();
getBinding().setStateStr(getString(R.string.stop)); getBinding().setStateStr(getString(R.string.stop));
} }
break; break;
case R.id.cancel: case R.id.cancel:
if (AppUtil.chekEntityValid(mEntity)) { Aria.download(this).load(mTaskId).cancel();
Aria.download(this).load(mEntity.getId()).cancel(); getBinding().setStateStr(getString(R.string.start));
} mTaskId = -1;
break; break;
} }
} }

@ -113,7 +113,7 @@ public class DownloadGroupActivity extends BaseActivity<ActivityDownloadGroupBin
}) })
.setFileSize(114981416) .setFileSize(114981416)
//.updateUrls(temp) //.updateUrls(temp)
.start(); .create();
getBinding().setStateStr(getString(R.string.stop)); getBinding().setStateStr(getString(R.string.stop));
break; break;
} }
@ -150,7 +150,7 @@ public class DownloadGroupActivity extends BaseActivity<ActivityDownloadGroupBin
@DownloadGroup.onTaskStart() void taskStart(DownloadGroupTask task) { @DownloadGroup.onTaskStart() void taskStart(DownloadGroupTask task) {
getBinding().setFileSize(task.getConvertFileSize()); getBinding().setFileSize(task.getConvertFileSize());
L.d(TAG, "group task start"); L.d(TAG, "group task create");
} }
@DownloadGroup.onTaskRunning() protected void running(DownloadGroupTask task) { @DownloadGroup.onTaskRunning() protected void running(DownloadGroupTask task) {

@ -80,7 +80,7 @@ public class FTPDirDownloadActivity extends BaseActivity<ActivityDownloadGroupBi
.option() .option()
.login("8L8e", "8guD") .login("8L8e", "8guD")
.controller(ControllerType.START_CONTROLLER) .controller(ControllerType.START_CONTROLLER)
.start(); .create();
getBinding().setStateStr(getString(R.string.stop)); getBinding().setStateStr(getString(R.string.stop));
break; break;
} }

@ -263,7 +263,7 @@ public class M3U8LiveDLoadActivity extends BaseActivity<ActivityM3u8LiveBinding>
// return newUrls; // return newUrls;
// } // }
//}) //})
.start(); .create();
} }
@Override protected void dataCallback(int result, Object data) { @Override protected void dataCallback(int result, Object data) {

@ -36,7 +36,7 @@ import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.core.download.m3u8.IBandWidthUrlConverter; import com.arialyy.aria.core.download.m3u8.IBandWidthUrlConverter;
import com.arialyy.aria.core.download.m3u8.ITsMergeHandler; import com.arialyy.aria.core.download.m3u8.ITsMergeHandler;
import com.arialyy.aria.core.download.m3u8.IVodTsUrlConverter; import com.arialyy.aria.core.download.m3u8.IVodTsUrlConverter;
import com.arialyy.aria.core.download.m3u8.M3U8KeyInfo; import com.arialyy.aria.core.download.m3u8.M3U8Entity;
import com.arialyy.aria.core.inf.IEntity; import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
@ -169,7 +169,7 @@ public class M3U8VodDLoadActivity extends BaseActivity<ActivityM3u8VodBinding> {
@M3U8.onPeerStart @M3U8.onPeerStart
void onPeerStart(String m3u8Url, String peerPath, int peerIndex) { void onPeerStart(String m3u8Url, String peerPath, int peerIndex) {
//ALog.d(TAG, "peer start, path: " + peerPath + ", index: " + peerIndex); //ALog.d(TAG, "peer create, path: " + peerPath + ", index: " + peerIndex);
} }
@M3U8.onPeerComplete @M3U8.onPeerComplete
@ -335,13 +335,14 @@ public class M3U8VodDLoadActivity extends BaseActivity<ActivityM3u8VodBinding> {
} }
}) })
.setMergeHandler(new ITsMergeHandler() { .setMergeHandler(new ITsMergeHandler() {
public boolean merge(@Nullable M3U8KeyInfo keyInfo, List<String> tsPath) { public boolean merge(@Nullable M3U8Entity m3U8Entity, List<String> tsPath) {
ALog.d(TAG, "合并TS...."); ALog.d(TAG, "合并TS....");
return false; return false;
} }
}) })
.generateIndexFile()
.controller(ControllerType.START_CONTROLLER) .controller(ControllerType.START_CONTROLLER)
.start(); .create();
} }
private Class<StartController> c = StartController.class; private Class<StartController> c = StartController.class;

@ -41,7 +41,11 @@ public class VideoPlayerFragment extends BaseFragment<FragmentVideoPlayerBinding
VideoPlayerFragment(int peerIndex, DownloadEntity entity) { VideoPlayerFragment(int peerIndex, DownloadEntity entity) {
mEntity = entity; mEntity = entity;
mPeerIndex = peerIndex; mPeerIndex = peerIndex;
List<M3U8Entity.PeerInfo> peerInfos = entity.getM3U8Entity().getCompletedPeer(); M3U8Entity m3U8Entity = entity.getM3U8Entity();
if (m3U8Entity == null) {
return;
}
List<M3U8Entity.PeerInfo> peerInfos = m3U8Entity.getCompletedPeer();
if (peerInfos != null) { if (peerInfos != null) {
for (M3U8Entity.PeerInfo info : peerInfos) { for (M3U8Entity.PeerInfo info : peerInfos) {
mPlayers.put(info.peerId, info.peerPath); mPlayers.put(info.peerId, info.peerPath);
@ -72,7 +76,9 @@ public class VideoPlayerFragment extends BaseFragment<FragmentVideoPlayerBinding
} }
} }
}); });
if (mEntity.getM3U8Entity() != null) {
getBinding().seekBar.setMax(mEntity.getM3U8Entity().getPeerNum()); getBinding().seekBar.setMax(mEntity.getM3U8Entity().getPeerNum());
}
getBinding().seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { getBinding().seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
@ -141,8 +147,6 @@ public class VideoPlayerFragment extends BaseFragment<FragmentVideoPlayerBinding
} }
} }
/** /**
* 设置下一个分片 * 设置下一个分片
*/ */

@ -294,16 +294,16 @@ public class DownloadAdapter extends AbsRVAdapter<AbsEntity, DownloadAdapter.Sim
private void start(AbsEntity entity) { private void start(AbsEntity entity) {
switch (entity.getTaskType()) { switch (entity.getTaskType()) {
case AbsTaskWrapper.D_FTP: case AbsTaskWrapper.D_FTP:
//Aria.download(getContext()).loadFtp((DownloadEntity) entity).login("lao", "123456").start(); //Aria.download(getContext()).loadFtp((DownloadEntity) entity).login("lao", "123456").create();
Aria.download(getContext()).loadFtp(entity.getKey()).start(); Aria.download(getContext()).loadFtp(entity.getKey()).create();
break; break;
case AbsTaskWrapper.D_FTP_DIR: case AbsTaskWrapper.D_FTP_DIR:
break; break;
case AbsTaskWrapper.D_HTTP: case AbsTaskWrapper.D_HTTP:
Aria.download(getContext()).load(entity.getKey()).start(); Aria.download(getContext()).load(entity.getKey()).create();
break; break;
case AbsTaskWrapper.DG_HTTP: case AbsTaskWrapper.DG_HTTP:
Aria.download(getContext()).loadGroup(((DownloadGroupEntity) entity).getUrls()).start(); Aria.download(getContext()).loadGroup(((DownloadGroupEntity) entity).getUrls()).create();
break; break;
} }
} }

@ -74,12 +74,12 @@ final class FileListAdapter extends AbsRVAdapter<FileListEntity, FileListAdapter
.setDirPath(item.downloadPath) .setDirPath(item.downloadPath)
.setGroupAlias(item.name) .setGroupAlias(item.name)
.unknownSize() .unknownSize()
.start(); .create();
} else { } else {
Aria.download(getContext()) Aria.download(getContext())
.load(item.key) .load(item.key)
.setFilePath(item.downloadPath) .setFilePath(item.downloadPath)
.start(); .create();
} }
} }
}); });

@ -139,9 +139,11 @@ public class MultiDownloadActivity extends BaseActivity<ActivityMultiDownloadBin
} }
@DownloadGroup.onTaskFail void groupTaskFail(DownloadGroupTask task) { @DownloadGroup.onTaskFail void groupTaskFail(DownloadGroupTask task) {
if (task != null) {
ALog.d(TAG, String.format("group【%s】fail", task.getTaskName())); ALog.d(TAG, String.format("group【%s】fail", task.getTaskName()));
mAdapter.updateState(task.getEntity()); mAdapter.updateState(task.getEntity());
} }
}
@DownloadGroup.onTaskComplete void groupTaskComplete(DownloadGroupTask task) { @DownloadGroup.onTaskComplete void groupTaskComplete(DownloadGroupTask task) {
mAdapter.updateState(task.getEntity()); mAdapter.updateState(task.getEntity());

@ -49,7 +49,7 @@ public class DownloadService extends Service {
Aria.download(this) Aria.download(this)
.load(DOWNLOAD_URL) .load(DOWNLOAD_URL)
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/service_task.apk") .setFilePath(Environment.getExternalStorageDirectory().getPath() + "/service_task.apk")
.start(); .create();
} }
@Override public void onDestroy() { @Override public void onDestroy() {

@ -48,7 +48,7 @@ public class AnyRunActivity extends BaseActivity<ActivityTestBinding> {
public void onClick(View view) { public void onClick(View view) {
switch (view.getId()) { switch (view.getId()) {
case R.id.start: case R.id.start:
//module.start(URL); //module.create(URL);
module.startFtp(URL); module.startFtp(URL);
break; break;
case R.id.stop: case R.id.stop:
@ -62,7 +62,7 @@ public class AnyRunActivity extends BaseActivity<ActivityTestBinding> {
// .updateUrl(newUrl) // .updateUrl(newUrl)
// .login("lao", "123456") // .login("lao", "123456")
// .setFilePath(Environment.getExternalStorageDirectory().getPath() + "/") // .setFilePath(Environment.getExternalStorageDirectory().getPath() + "/")
// .start(); // .create();
break; break;
} }
} }

@ -132,7 +132,7 @@ public class FtpUploadActivity extends BaseActivity<ActivityFtpUploadBinding> {
.option() .option()
.login("8L8e", "8guD") .login("8L8e", "8guD")
.controller(ControllerType.START_CONTROLLER) .controller(ControllerType.START_CONTROLLER)
.start(); .create();
getBinding().setStateStr(getString(R.string.stop)); getBinding().setStateStr(getString(R.string.stop));
break; break;
} }

@ -76,7 +76,7 @@ public class HttpUploadActivity extends BaseActivity<ActivityUploadBinding> {
"http://lib-test.xzxyun.com:8042/Api/upload?data={\"type\":\"1\",\"fileType\":\".apk\"}") "http://lib-test.xzxyun.com:8042/Api/upload?data={\"type\":\"1\",\"fileType\":\".apk\"}")
//.setTempUrl("http://192.168.1.6:8080/upload/sign_file/").setAttachment("file") //.setTempUrl("http://192.168.1.6:8080/upload/sign_file/").setAttachment("file")
//.addHeader("iplanetdirectorypro", "11a09102fb934ad0bc206f9c611d7933") //.addHeader("iplanetdirectorypro", "11a09102fb934ad0bc206f9c611d7933")
.start(); .create();
} }
void stop() { void stop() {
@ -95,7 +95,7 @@ public class HttpUploadActivity extends BaseActivity<ActivityUploadBinding> {
} }
@Upload.onTaskStart public void taskStart(UploadTask task) { @Upload.onTaskStart public void taskStart(UploadTask task) {
L.d(TAG, "upload start,md5:" + FileUtil.getFileMD5(new File(task.getEntity().getFilePath()))); L.d(TAG, "upload create,md5:" + FileUtil.getFileMD5(new File(task.getEntity().getFilePath())));
getBinding().setFileSize(task.getConvertFileSize()); getBinding().setFileSize(task.getConvertFileSize());
} }

@ -92,7 +92,7 @@ public class AnyRunnModule {
.load(url) .load(url)
.setFilePath(path) .setFilePath(path)
.resetState() .resetState()
.start(); .create();
} else { } else {
Aria.download(this).load(mEntity.getId()).resume(); Aria.download(this).load(mEntity.getId()).resume();
} }
@ -114,7 +114,7 @@ public class AnyRunnModule {
.setAlias("www.laoyuyu.me") .setAlias("www.laoyuyu.me")
.setStorePass("123456") .setStorePass("123456")
.controller(ControllerType.START_CONTROLLER) .controller(ControllerType.START_CONTROLLER)
.start(); .create();
} else { } else {
Aria.download(this).load(mEntity.getId()).resume(); Aria.download(this).load(mEntity.getId()).resume();
} }

@ -22,11 +22,12 @@ import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import androidx.core.content.FileProvider;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.core.content.FileProvider;
import com.arialyy.aria.core.inf.AbsEntity; import com.arialyy.aria.core.inf.AbsEntity;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.FileUtil;
import com.arialyy.simple.BuildConfig; import com.arialyy.simple.BuildConfig;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -51,7 +52,7 @@ public class AppUtil {
String path = String.format("%s/code/%s", context.getFilesDir().getPath(), fileName); String path = String.format("%s/code/%s", context.getFilesDir().getPath(), fileName);
File ftpCode = new File(path); File ftpCode = new File(path);
if (!ftpCode.exists()) { if (!ftpCode.exists()) {
CommonUtil.createFile(path); FileUtil.createFile(path);
CommonUtil.createFileFormInputStream(context.getAssets() CommonUtil.createFileFormInputStream(context.getAssets()
.open(String.format("help_code/%s", fileName)), .open(String.format("help_code/%s", fileName)),
path); path);

@ -106,16 +106,13 @@
</string-array> </string-array>
<string-array name="group_urls"> <string-array name="group_urls">
<!--<item>https://res5.d.cn/5a6a3384c1b2be1a65d84b914e6a6fef697637578b6db2eb1056d50b09cf1dcf289d4045df7ef95746e498e3d6a848ab84c89b77aa60194e2c48e5a7cb748265.apk</item>--> <item>https://downs.muzhiwan.com/2019/06/19/com.and.games505.TerrariaPaid5d0a074e451c0.gpk</item>
<!--<item>https://res5.d.cn/5a6a3384c1b2be1a52034c72752e8475414630ebc69318b84ef584115ebf5eaaab945ae07b7fe3596afc72a7940ff328d4a9553f6ae92d6c09ba4bfb533137f6.apk</item>--> <item>https://downs.muzhiwan.com/2017/03/28/com.xyzstudio_58da07426e959.apk</item>
<!--<item>https://res5.d.cn/5a6a3384c1b2be1a426f06bfc69034d69c44ae1a01da180cab8e59bd1a5e1a784bac46ba0c64579d14f0e80a4ce4f068af89b0369a393456f4f449a8829cad5c.apk</item>-->
<item>http://static.gaoshouyou.com/d/12/0d/7f120f50c80d2e7b8c4ba24ece4f9cdd.apk</item>
<!--<item>http://static.ilongyuan.cn/rayark/RayarkFZ_2.0.7.apk</item>-->
</string-array> </string-array>
<string-array name="group_urls_1"> <string-array name="group_urls_1">
<item>http://hzdown.muzhiwan.com/2017/05/08/nl.noio.kingdom_59104935e56f0.apk</item> <item>http://hzdown.muzhiwan.com/2017/05/08/nl.noio.kingdom_59104935e56f0.apk</item>
<item>https://atom-installer.github.com/v1.13.0/AtomSetup.exe1</item> <!--<item>https://atom-installer.github.com/v1.13.0/AtomSetup.exe1</item>-->
<item>http://hzdown.muzhiwan.com/2017/09/05/com.mir.iphone.empire83jie.mzw_59ae6d5a3638d.apk</item> <item>http://hzdown.muzhiwan.com/2017/09/05/com.mir.iphone.empire83jie.mzw_59ae6d5a3638d.apk</item>
</string-array> </string-array>
@ -125,8 +122,8 @@
</string-array> </string-array>
<string-array name="group_urls_3"> <string-array name="group_urls_3">
<item>http://apk500.bce.baidu-mgame.com/game/883000/883227/20170828102306_oem_5502845.apk?r=1</item> <item>https://downs.muzhiwan.com/2019/07/23/com.amazid.me_5d36bade614d9.apk</item>
<item>http://static.gaoshouyou.com/d/92/12/5592a647b8126755647abbe8074fde39.apk</item> <item>https://downs.muzhiwan.com/2019/07/30/com.counter.terrorist.attack.fps.sniper.fight_5d3fe8f0a7edf.apk</item>
</string-array> </string-array>
<string-array name="group_url4"> <string-array name="group_url4">
@ -135,8 +132,8 @@
</string-array> </string-array>
<string-array name="group_names"> <string-array name="group_names">
<item>王者荣耀.apk</item> <item>泰拉瑞亚.apk</item>
<item>战斗吧剑灵.apk</item> <item>疯狂屁股.apk</item>
<!--<item>天魔幻想.apk</item>--> <!--<item>天魔幻想.apk</item>-->
</string-array> </string-array>
@ -151,8 +148,8 @@
</string-array> </string-array>
<string-array name="group_names_3"> <string-array name="group_names_3">
<item>部落冲突.apk</item> <item>神奇的绳索英雄.apk</item>
<item>城堡争霸.apk</item> <item>自由火力反击.apk</item>
</string-array> </string-array>
</resources> </resources>

@ -43,7 +43,7 @@ task clean(type: Delete) {
ext { ext {
userOrg = 'arialyy' userOrg = 'arialyy'
groupId = 'com.arialyy.aria' groupId = 'com.arialyy.aria'
publishVersion = '3.6.6_beta_2' publishVersion = '3.6.6_beta_3'
// publishVersion = '1.0.4' //FTP插件 // publishVersion = '1.0.4' //FTP插件
repoName='maven' repoName='maven'
desc = 'android 下载框架' desc = 'android 下载框架'

Loading…
Cancel
Save