合并 v_3.0代码

pull/330/head
AriaLyy 8 years ago
commit 99d857f338
  1. 1
      .gitignore
  2. 4
      Aria/build.gradle
  3. 76
      Aria/src/main/java/com/arialyy/aria/core/AMReceiver.java
  4. 151
      Aria/src/main/java/com/arialyy/aria/core/AMTarget.java
  5. 8
      Aria/src/main/java/com/arialyy/aria/core/AMUplodReceiver.java
  6. 203
      Aria/src/main/java/com/arialyy/aria/core/Aria.java
  7. 289
      Aria/src/main/java/com/arialyy/aria/core/AriaManager.java
  8. 107
      Aria/src/main/java/com/arialyy/aria/core/DownloadManager.java
  9. 19
      Aria/src/main/java/com/arialyy/aria/core/RequestEnum.java
  10. 10
      Aria/src/main/java/com/arialyy/aria/core/TaskEntity.java
  11. 111
      Aria/src/main/java/com/arialyy/aria/core/WidgetLiftManager.java
  12. 36
      Aria/src/main/java/com/arialyy/aria/core/command/AbsCmd.java
  13. 33
      Aria/src/main/java/com/arialyy/aria/core/command/AddCmd.java
  14. 38
      Aria/src/main/java/com/arialyy/aria/core/command/CancelCmd.java
  15. 79
      Aria/src/main/java/com/arialyy/aria/core/command/CmdFactory.java
  16. 48
      Aria/src/main/java/com/arialyy/aria/core/command/SingleCmd.java
  17. 36
      Aria/src/main/java/com/arialyy/aria/core/command/StartCmd.java
  18. 47
      Aria/src/main/java/com/arialyy/aria/core/command/StopCmd.java
  19. 14
      Aria/src/main/java/com/arialyy/aria/core/download/ConnectionHelp.java
  20. 95
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadEntity.java
  21. 3
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadListener.java
  22. 139
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java
  23. 9
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadStateConstance.java
  24. 113
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java
  25. 146
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadTask.java
  26. 36
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java
  27. 209
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadUtil.java
  28. 4
      Aria/src/main/java/com/arialyy/aria/core/download/IDownloadListener.java
  29. 5
      Aria/src/main/java/com/arialyy/aria/core/download/IDownloadUtil.java
  30. 27
      Aria/src/main/java/com/arialyy/aria/core/download/SingleThreadTask.java
  31. 173
      Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java
  32. 27
      Aria/src/main/java/com/arialyy/aria/core/inf/ICmd.java
  33. 63
      Aria/src/main/java/com/arialyy/aria/core/inf/IEntity.java
  34. 55
      Aria/src/main/java/com/arialyy/aria/core/inf/IReceiver.java
  35. 54
      Aria/src/main/java/com/arialyy/aria/core/inf/ITask.java
  36. 38
      Aria/src/main/java/com/arialyy/aria/core/inf/ITaskEntity.java
  37. 42
      Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java
  38. 89
      Aria/src/main/java/com/arialyy/aria/core/queue/DownloadTaskQueue.java
  39. 69
      Aria/src/main/java/com/arialyy/aria/core/queue/ITaskQueue.java
  40. 93
      Aria/src/main/java/com/arialyy/aria/core/queue/TaskFactory.java
  41. 120
      Aria/src/main/java/com/arialyy/aria/core/queue/UploadTaskQueue.java
  42. 49
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/CachePool.java
  43. 73
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/ExecutePool.java
  44. 15
      Aria/src/main/java/com/arialyy/aria/core/queue/pool/IPool.java
  45. 101
      Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadSchedulers.java
  46. 29
      Aria/src/main/java/com/arialyy/aria/core/scheduler/IDownloadSchedulerListener.java
  47. 20
      Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulerListener.java
  48. 64
      Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulers.java
  49. 186
      Aria/src/main/java/com/arialyy/aria/core/scheduler/UploadSchedulers.java
  50. 62
      Aria/src/main/java/com/arialyy/aria/core/task/TaskFactory.java
  51. 69
      Aria/src/main/java/com/arialyy/aria/core/upload/IUploadListener.java
  52. 141
      Aria/src/main/java/com/arialyy/aria/core/upload/UploadEntity.java
  53. 54
      Aria/src/main/java/com/arialyy/aria/core/upload/UploadListener.java
  54. 130
      Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java
  55. 123
      Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java
  56. 260
      Aria/src/main/java/com/arialyy/aria/core/upload/UploadTask.java
  57. 47
      Aria/src/main/java/com/arialyy/aria/core/upload/UploadTaskEntity.java
  58. 230
      Aria/src/main/java/com/arialyy/aria/core/upload/UploadUtil.java
  59. 15
      Aria/src/main/java/com/arialyy/aria/exception/FileException.java
  60. 14
      Aria/src/main/java/com/arialyy/aria/orm/DbEntity.java
  61. 42
      Aria/src/main/java/com/arialyy/aria/orm/DbUtil.java
  62. 1
      Aria/src/main/java/com/arialyy/aria/orm/Id.java
  63. 1
      Aria/src/main/java/com/arialyy/aria/orm/Ignore.java
  64. 1
      Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java
  65. 21
      Aria/src/main/java/com/arialyy/aria/util/BufferedRandomAccessFile.java
  66. 93
      Aria/src/main/java/com/arialyy/aria/util/CheckUtil.java
  67. 22
      Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java
  68. 48
      Aria/src/main/java/com/arialyy/aria/util/Configuration.java
  69. 119
      Aria/src/main/java/com/arialyy/aria/util/FileUtil.java
  70. 1
      Aria/src/main/java/com/arialyy/aria/util/PathUtil.java
  71. 9
      Aria/src/main/java/com/arialyy/aria/util/SSLContextUtil.java
  72. 44
      Aria/src/main/java/com/arialyy/aria/util/Speed.java
  73. 842
      Aria/src/main/java/com/arialyy/aria/util/WeakHandler.java
  74. 67
      Aria/src/main/java/com/arialyy/aria/window/AriaFileChangeActivity.java
  75. 92
      Aria/src/main/java/com/arialyy/aria/window/FileChangeAdapter.java
  76. 29
      Aria/src/main/java/com/arialyy/aria/window/FileEntity.java
  77. 8
      Aria/src/main/res/layout/item_file.xml
  78. 40
      DownloadApi.md
  79. 185
      README.md
  80. 13
      app/src/main/AndroidManifest.xml
  81. 87
      app/src/main/java/com/arialyy/simple/MainActivity.java
  82. 3
      app/src/main/java/com/arialyy/simple/base/BaseApplication.java
  83. 5
      app/src/main/java/com/arialyy/simple/base/BaseDialog.java
  84. 1
      app/src/main/java/com/arialyy/simple/base/BaseModule.java
  85. 115
      app/src/main/java/com/arialyy/simple/download/DownloadActivity.java
  86. 65
      app/src/main/java/com/arialyy/simple/download/DownloadDialog.java
  87. 20
      app/src/main/java/com/arialyy/simple/download/DownloadModule.java
  88. 65
      app/src/main/java/com/arialyy/simple/download/DownloadPopupWindow.java
  89. 42
      app/src/main/java/com/arialyy/simple/download/SimpleNotification.java
  90. 121
      app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java
  91. 54
      app/src/main/java/com/arialyy/simple/download/fragment_download/DownloadFragment.java
  92. 31
      app/src/main/java/com/arialyy/simple/download/fragment_download/FragmentActivity.java
  93. 34
      app/src/main/java/com/arialyy/simple/download/multi_download/DownloadAdapter.java
  94. 3
      app/src/main/java/com/arialyy/simple/download/multi_download/DownloadNumDialog.java
  95. 27
      app/src/main/java/com/arialyy/simple/download/multi_download/FileListAdapter.java
  96. 25
      app/src/main/java/com/arialyy/simple/download/multi_download/FileListEntity.java
  97. 105
      app/src/main/java/com/arialyy/simple/download/multi_download/MultiDownloadActivity.java
  98. 32
      app/src/main/java/com/arialyy/simple/download/multi_download/MultiTaskActivity.java
  99. 55
      app/src/main/java/com/arialyy/simple/download/service_download/DownloadNotification.java
  100. 102
      app/src/main/java/com/arialyy/simple/download/service_download/DownloadService.java
  101. Some files were not shown because too many files have changed in this diff Show More

1
.gitignore vendored

@ -11,3 +11,4 @@
.idea/misc.xml .idea/misc.xml
.gradle .gradle
/.idea /.idea
.idea

@ -7,8 +7,8 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 9 minSdkVersion 9
targetSdkVersion 23 targetSdkVersion 23
versionCode 86 versionCode 100
versionName "2.4.2" versionName "3.0.0"
} }
buildTypes { buildTypes {
release { release {

@ -1,76 +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;
import android.support.annotation.NonNull;
import com.arialyy.aria.core.scheduler.DownloadSchedulers;
import com.arialyy.aria.core.scheduler.OnSchedulerListener;
import com.arialyy.aria.util.CheckUtil;
/**
* Created by lyy on 2016/12/5.
* AM 接收器
*/
public class AMReceiver {
String targetName;
OnSchedulerListener listener;
Object obj;
/**
* {@link #load(String)}请使用该方法
*/
@Deprecated public AMTarget load(DownloadEntity entity) {
return new AMTarget(entity, targetName);
}
/**
* 读取下载链接
*/
public AMTarget load(@NonNull String downloadUrl) {
CheckUtil.checkDownloadUrl(downloadUrl);
DownloadEntity entity =
DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl);
if (entity == null) {
entity = new DownloadEntity();
}
entity.setDownloadUrl(downloadUrl);
return new AMTarget(entity, targetName);
}
/**
* 添加调度器回调
*/
public AMReceiver addSchedulerListener(OnSchedulerListener listener) {
this.listener = listener;
DownloadSchedulers.getInstance().addSchedulerListener(targetName, listener);
return this;
}
/**
* 移除回调
*/
public AMReceiver removeSchedulerListener() {
if (listener != null) {
DownloadSchedulers.getInstance().removeSchedulerListener(targetName, listener);
}
return this;
}
void destroy() {
targetName = null;
listener = null;
}
}

@ -1,151 +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;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import com.arialyy.aria.core.command.CmdFactory;
import com.arialyy.aria.core.command.IDownloadCmd;
import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.CommonUtil;
import java.util.ArrayList;
import java.util.List;
/**
* Created by lyy on 2016/12/5.
* https://github.com/AriaLyy/Aria
*/
public class AMTarget {
//private AMReceiver mReceiver;
DownloadEntity entity;
String targetName;
AMTarget(DownloadEntity entity, String targetName) {
this.entity = entity;
this.targetName = targetName;
}
/**
* 设置文件存储路径
*/
public AMTarget setDownloadPath(@NonNull String downloadPath) {
if (TextUtils.isEmpty(downloadPath)) {
throw new IllegalArgumentException("文件保持路径不能为null");
}
entity.setDownloadPath(downloadPath);
return this;
}
/**
* 设置文件名
*/
public AMTarget setDownloadName(@NonNull String downloadName) {
if (TextUtils.isEmpty(downloadName)) {
throw new IllegalArgumentException("文件名不能为null");
}
entity.setFileName(downloadName);
return this;
}
/**
* 获取下载文件大小
*/
public long getFileSize() {
DownloadEntity entity = getDownloadEntity(this.entity.getDownloadUrl());
if (entity == null) {
throw new NullPointerException("下载管理器中没有改任务");
}
return entity.getFileSize();
}
/**
* 获取当前下载进度如果下載实体存在则返回当前进度
*/
public long getCurrentProgress() {
DownloadEntity entity = getDownloadEntity(this.entity.getDownloadUrl());
if (entity == null) {
throw new NullPointerException("下载管理器中没有改任务");
}
return entity.getCurrentProgress();
}
private DownloadEntity getDownloadEntity(String downloadUrl) {
CheckUtil.checkDownloadUrl(downloadUrl);
return DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl);
}
/**
* 添加任务
*/
public void add() {
DownloadManager.getInstance()
.setCmd(CommonUtil.createCmd(targetName, entity, CmdFactory.TASK_CREATE))
.exe();
}
/**
* 开始下载
*/
public void start() {
List<IDownloadCmd> cmds = new ArrayList<>();
cmds.add(CommonUtil.createCmd(targetName, entity, CmdFactory.TASK_CREATE));
cmds.add(CommonUtil.createCmd(targetName, entity, CmdFactory.TASK_START));
DownloadManager.getInstance().setCmds(cmds).exe();
cmds.clear();
}
/**
* 停止下载
*/
public void stop() {
DownloadManager.getInstance()
.setCmd(CommonUtil.createCmd(targetName, entity, CmdFactory.TASK_STOP))
.exe();
}
/**
* 恢复下载
*/
public void resume() {
DownloadManager.getInstance()
.setCmd(CommonUtil.createCmd(targetName, entity, CmdFactory.TASK_START))
.exe();
}
/**
* 取消下载
*/
public void cancel() {
DownloadManager.getInstance()
.setCmd(CommonUtil.createCmd(targetName, entity, CmdFactory.TASK_CANCEL))
.exe();
}
/**
* 是否在下载
*/
public boolean isDownloading() {
return DownloadManager.getInstance().getTaskQueue().getTask(entity).isDownloading();
}
/**
* 重新下载
*/
public void reStart() {
cancel();
start();
}
}

@ -1,8 +0,0 @@
package com.arialyy.aria.core;
/**
* Created by Aria.Lao on 2017/1/18.
* AM 上传文件接收器
*/
public class AMUplodReceiver {
}

@ -26,9 +26,12 @@ import android.app.Service;
import android.content.Context; import android.content.Context;
import android.os.Build; import android.os.Build;
import android.widget.PopupWindow; import android.widget.PopupWindow;
import com.arialyy.aria.core.scheduler.OnSchedulerListener; import com.arialyy.aria.core.download.DownloadReceiver;
import com.arialyy.aria.core.task.Task; import com.arialyy.aria.core.scheduler.IDownloadSchedulerListener;
import com.arialyy.aria.util.CheckUtil; import com.arialyy.aria.core.scheduler.ISchedulerListener;
import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.core.upload.UploadReceiver;
import com.arialyy.aria.core.upload.UploadTask;
/** /**
* Created by lyy on 2016/12/1. * Created by lyy on 2016/12/1.
@ -36,17 +39,28 @@ import com.arialyy.aria.util.CheckUtil;
* Aria启动管理全局任务 * Aria启动管理全局任务
* <pre> * <pre>
* <code> * <code>
* //启动下载 * //下载
* Aria.whit(this) * Aria.download(this)
* .load(DOWNLOAD_URL) //下载地址,必填 * .load(DOWNLOAD_URL) //下载地址,必填
* //文件保存路径,必填 * //文件保存路径,必填
* .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk") * .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk")
* .setDownloadName("test.apk") //文件名,必填
* .start(); * .start();
* </code> * </code>
* <code>
* //上传
* Aria.upload(this)
* .load(filePath) //文件路径,必填
* .setUploadUrl(uploadUrl) //上传路径,必填
* .setAttachment(fileKey) //服务器读取文件的key,必填
* .start();
* </code>
* </pre> * </pre>
*/ */
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) public class Aria { @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) public class Aria {
/**
* 不支持断点
*/
public static final String ACTION_SUPPORT_BREAK_POINT = "ACTION_SUPPORT_BREAK_POINT";
/** /**
* 预处理完成 * 预处理完成
*/ */
@ -99,148 +113,135 @@ import com.arialyy.aria.util.CheckUtil;
private Aria() { private Aria() {
} }
/** /**
* 接受ActivityServiceApplication * 初始化下载
*
* @param obj 支持类型有ActivityServiceApplicationDialogFragmentFragmentPopupWindowDialog
*/ */
public static AMReceiver whit(Context context) { public static DownloadReceiver download(Object obj) {
CheckUtil.checkNull(context); return get(obj).download(obj);
if (context instanceof Activity
|| context instanceof Service
|| context instanceof Application) {
return AriaManager.getInstance(context).get(context);
} else {
throw new IllegalArgumentException("这是不支持的context");
}
} }
/** /**
* 处理Fragment * 初始化上传
*
* @param obj 支持类型有ActivityServiceApplicationDialogFragmentFragmentPopupWindowDialog
*/ */
public static AMReceiver whit(Fragment fragment) { public static UploadReceiver upload(Object obj) {
CheckUtil.checkNull(fragment); return get(obj).upload(obj);
return AriaManager.getInstance(
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? fragment.getContext()
: fragment.getActivity()).get(fragment);
} }
/** /**
* 处理Fragment * 处理通用事件
*/ *
public static AMReceiver whit(android.support.v4.app.Fragment fragment) { * @param obj 支持类型有ActivityServiceApplicationDialogFragmentFragmentPopupWindowDialog
CheckUtil.checkNull(fragment); */
return AriaManager.getInstance( public static AriaManager get(Object obj) {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? fragment.getContext() if (obj instanceof Activity || obj instanceof Service || obj instanceof Application) {
: fragment.getActivity()).get(fragment); return AriaManager.getInstance((Context) obj);
} else if (obj instanceof DialogFragment) {
DialogFragment dialog = (DialogFragment) obj;
return AriaManager.getInstance(
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? dialog.getContext()
: dialog.getActivity());
} else if (obj instanceof android.support.v4.app.Fragment) {
android.support.v4.app.Fragment fragment = (android.support.v4.app.Fragment) obj;
return AriaManager.getInstance(
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? fragment.getContext()
: fragment.getActivity());
} else if (obj instanceof Fragment) {
Fragment fragment = (Fragment) obj;
return AriaManager.getInstance(
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? fragment.getContext()
: fragment.getActivity());
} else if (obj instanceof PopupWindow) {
PopupWindow popupWindow = (PopupWindow) obj;
return AriaManager.getInstance(popupWindow.getContentView().getContext());
} else if (obj instanceof Dialog) {
Dialog dialog = (Dialog) obj;
return AriaManager.getInstance(dialog.getContext());
} else {
throw new IllegalArgumentException("不支持的类型");
}
} }
/** /**
* 处理Fragment或者DialogFragment * 上传任务状态监听
*/ */
public static AMReceiver whit(DialogFragment dialog) { public static class UploadSchedulerListener implements ISchedulerListener<UploadTask> {
CheckUtil.checkNull(dialog);
return AriaManager.getInstance(
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? dialog.getContext() : dialog.getActivity())
.get(dialog);
}
/** @Override public void onTaskPre(UploadTask task) {
* 处理popupwindow
*/
public static AMReceiver whit(PopupWindow popupWindow) {
CheckUtil.checkNull(popupWindow);
return AriaManager.getInstance(popupWindow.getContentView().getContext()).get(popupWindow);
}
/** }
* 处理Dialog
*/ @Override public void onTaskResume(UploadTask task) {
public static AMReceiver whit(Dialog dialog) {
CheckUtil.checkNull(dialog);
return AriaManager.getInstance(dialog.getContext()).get(dialog);
}
/**
* 处理通用事件
*/
public static AriaManager get(Context context) {
if (context == null) throw new IllegalArgumentException("context 不能为 null");
if (context instanceof Activity
|| context instanceof Service
|| context instanceof Application) {
return AriaManager.getInstance(context);
} else {
throw new IllegalArgumentException("这是不支持的context");
} }
}
/** @Override public void onTaskStart(UploadTask task) {
* 处理Dialog的通用任务
*/
public static AriaManager get(Dialog dialog) {
CheckUtil.checkNull(dialog);
return AriaManager.getInstance(dialog.getContext());
}
/** }
* 处理Dialog的通用任务
*/
public static AriaManager get(PopupWindow popupWindow) {
CheckUtil.checkNull(popupWindow);
return AriaManager.getInstance(popupWindow.getContentView().getContext());
}
/** @Override public void onTaskStop(UploadTask task) {
* 处理Fragment的通用任务
*/ }
public static AriaManager get(Fragment fragment) {
CheckUtil.checkNull(fragment); @Override public void onTaskCancel(UploadTask task) {
return AriaManager.getInstance(
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? fragment.getContext() }
: fragment.getActivity());
@Override public void onTaskFail(UploadTask task) {
}
@Override public void onTaskComplete(UploadTask task) {
}
@Override public void onTaskRunning(UploadTask task) {
}
} }
/** /**
* 处理Fragment的通用任务 * 下载任务状态监听
*/ */
public static AriaManager get(android.support.v4.app.Fragment fragment) { public static class DownloadSchedulerListener
CheckUtil.checkNull(fragment); implements IDownloadSchedulerListener<DownloadTask> {
return AriaManager.getInstance(
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? fragment.getContext() @Override public void onTaskPre(DownloadTask task) {
: fragment.getActivity());
}
public static class SimpleSchedulerListener implements OnSchedulerListener { }
@Override public void onTaskPre(Task task) { @Override public void onTaskResume(DownloadTask task) {
} }
@Override public void onTaskResume(Task task) { @Override public void onTaskStart(DownloadTask task) {
} }
@Override public void onTaskStart(Task task) { @Override public void onTaskStop(DownloadTask task) {
} }
@Override public void onTaskStop(Task task) { @Override public void onTaskCancel(DownloadTask task) {
} }
@Override public void onTaskCancel(Task task) { @Override public void onTaskFail(DownloadTask task) {
} }
@Override public void onTaskFail(Task task) { @Override public void onTaskComplete(DownloadTask task) {
} }
@Override public void onTaskComplete(Task task) { @Override public void onTaskRunning(DownloadTask task) {
} }
@Override public void onTaskRunning(Task task) { @Override public void onNoSupportBreakPoint(DownloadTask task) {
} }
} }

@ -15,33 +15,36 @@
*/ */
package com.arialyy.aria.core; package com.arialyy.aria.core;
import android.annotation.SuppressLint;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.Activity; import android.app.Activity;
import android.app.Application; import android.app.Application;
import android.app.Dialog; import android.app.Dialog;
import android.app.Service; import android.app.Service;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Message;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.widget.PopupWindow; import android.widget.PopupWindow;
import com.arialyy.aria.core.command.CmdFactory; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadReceiver;
import com.arialyy.aria.core.inf.ICmd;
import com.arialyy.aria.core.inf.IReceiver;
import com.arialyy.aria.core.queue.DownloadTaskQueue;
import com.arialyy.aria.core.queue.UploadTaskQueue;
import com.arialyy.aria.core.upload.UploadReceiver;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.orm.DbUtil;
import com.arialyy.aria.util.CAConfiguration; import com.arialyy.aria.util.CAConfiguration;
import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.core.command.IDownloadCmd;
import com.arialyy.aria.util.Configuration; import com.arialyy.aria.util.Configuration;
import java.lang.reflect.Field; import com.arialyy.aria.util.Speed;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* Created by lyy on 2016/12/1. * Created by lyy on 2016/12/1.
@ -49,19 +52,22 @@ import java.util.Set;
* Aria管理器任务操作在这里执行 * Aria管理器任务操作在这里执行
*/ */
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public class AriaManager { @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public class AriaManager {
private static final String TAG = "AriaManager"; private static final String TAG = "AriaManager";
private static final Object LOCK = new Object(); private static final String DOWNLOAD = "_download";
private static volatile AriaManager INSTANCE = null; private static final String UPLOAD = "_upload";
private Map<String, AMReceiver> mTargets = new HashMap<>(); private static final Object LOCK = new Object();
private DownloadManager mManager; @SuppressLint("StaticFieldLeak") private static volatile AriaManager INSTANCE = null;
private LifeCallback mLifeCallback; private Map<String, IReceiver> mReceivers = new HashMap<>();
public static Context APP;
private List<ICmd> mCommands = new ArrayList<>();
private AriaManager(Context context) { private AriaManager(Context context) {
DbUtil.init(context.getApplicationContext());
APP = context.getApplicationContext();
regAppLifeCallback(context); regAppLifeCallback(context);
mManager = DownloadManager.init(context);
} }
static AriaManager getInstance(Context context) { public static AriaManager getInstance(Context context) {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (LOCK) { synchronized (LOCK) {
INSTANCE = new AriaManager(context); INSTANCE = new AriaManager(context);
@ -70,62 +76,83 @@ import java.util.Set;
return INSTANCE; return INSTANCE;
} }
AMReceiver get(Object obj) { public Map<String, IReceiver> getReceiver() {
return getTarget(obj); return mReceivers;
} }
/** /**
* 设置CA证书信息 * 设置最大下载速度
*
* @param caAlias ca证书别名
* @param caPath assets 文件夹下的ca证书完整路径
*/ */
public void setCAInfo(String caAlias, String caPath) { public void setMaxSpeed(Speed speed) {
if (TextUtils.isEmpty(caAlias)) { Configuration.getInstance().setMaxSpeed(speed);
Log.e(TAG, "ca证书别名不能为null"); }
return;
} else if (TextUtils.isEmpty(caPath)) { /**
Log.e(TAG, "ca证书路径不能为null"); * 设置命令
return; */
public AriaManager setCmd(ICmd command) {
mCommands.add(command);
return this;
}
/**
* 设置一组命令
*/
public <T extends ICmd> AriaManager setCmds(List<T> commands) {
if (commands != null && commands.size() > 0) {
mCommands.addAll(commands);
} }
CAConfiguration.CA_ALIAS = caAlias; return this;
CAConfiguration.CA_PATH = caPath;
} }
/** /**
* 获取下载列表 * 执行所有设置的命令
*/ */
public List<DownloadEntity> getDownloadList() { public synchronized void exe() {
return DownloadEntity.findAllData(DownloadEntity.class); for (ICmd command : mCommands) {
command.executeCmd();
}
mCommands.clear();
} }
/** /**
* 通过下载链接获取下载实体 * 处理下载操作
*/ */
public DownloadEntity getDownloadEntity(String downloadUrl) { DownloadReceiver download(Object obj) {
CheckUtil.checkDownloadUrl(downloadUrl); IReceiver receiver = mReceivers.get(getKey(true, obj));
return DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl); if (receiver == null) {
receiver = putReceiver(true, obj);
}
return (receiver instanceof DownloadReceiver) ? (DownloadReceiver) receiver : null;
} }
/** /**
* 下载任务是否存在 * 处理上传操作
*/ */
public boolean taskExists(String downloadUrl) { UploadReceiver upload(Object obj) {
return DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl) != null; IReceiver receiver = mReceivers.get(getKey(false, obj));
if (receiver == null) {
receiver = putReceiver(false, obj);
}
return (receiver instanceof UploadReceiver) ? (UploadReceiver) receiver : null;
} }
/** /**
* 停止所有正在执行的任务 * 设置CA证书信息
*
* @param caAlias ca证书别名
* @param caPath assets 文件夹下的ca证书完整路径
*/ */
public void stopAllTask() { public void setCAInfo(String caAlias, String caPath) {
List<DownloadEntity> allEntity = mManager.getAllDownloadEntity(); if (TextUtils.isEmpty(caAlias)) {
List<IDownloadCmd> stopCmds = new ArrayList<>(); Log.e(TAG, "ca证书别名不能为null");
for (DownloadEntity entity : allEntity) { return;
if (entity.getState() == DownloadEntity.STATE_DOWNLOAD_ING) { } else if (TextUtils.isEmpty(caPath)) {
stopCmds.add(CommonUtil.createCmd(entity, CmdFactory.TASK_STOP)); Log.e(TAG, "ca证书路径不能为null");
} return;
} }
mManager.setCmds(stopCmds).exe(); CAConfiguration.CA_ALIAS = caAlias;
CAConfiguration.CA_PATH = caPath;
} }
/** /**
@ -137,7 +164,7 @@ import java.util.Set;
} }
/** /**
* 设置下载失败重试次数 * 设置失败重试次数
*/ */
public AriaManager setReTryNum(int reTryNum) { public AriaManager setReTryNum(int reTryNum) {
Configuration.getInstance().setReTryNum(reTryNum); Configuration.getInstance().setReTryNum(reTryNum);
@ -145,7 +172,7 @@ import java.util.Set;
} }
/** /**
* 设置下载失败重试间隔 * 设置失败重试间隔
*/ */
public AriaManager setReTryInterval(int interval) { public AriaManager setReTryInterval(int interval) {
Configuration.getInstance().setReTryInterval(interval); Configuration.getInstance().setReTryInterval(interval);
@ -170,31 +197,41 @@ import java.util.Set;
Log.w(TAG, "最大任务数不能小于 1"); Log.w(TAG, "最大任务数不能小于 1");
return this; return this;
} }
mManager.getTaskQueue().setDownloadNum(maxDownloadNum); DownloadTaskQueue.getInstance().setDownloadNum(maxDownloadNum);
return this; return this;
} }
/** private IReceiver putReceiver(boolean isDownload, Object obj) {
* 删除所有任务 final String key = getKey(isDownload, obj);
*/ IReceiver receiver = mReceivers.get(key);
public void cancelAllTask() { final WidgetLiftManager widgetLiftManager = new WidgetLiftManager();
List<DownloadEntity> allEntity = mManager.getAllDownloadEntity(); if (obj instanceof Dialog) {
List<IDownloadCmd> cancelCmds = new ArrayList<>(); widgetLiftManager.handleDialogLift((Dialog) obj);
for (DownloadEntity entity : allEntity) { } else if (obj instanceof PopupWindow) {
cancelCmds.add(CommonUtil.createCmd(entity, CmdFactory.TASK_CANCEL)); widgetLiftManager.handlePopupWindowLift((PopupWindow) obj);
} }
mManager.setCmds(cancelCmds).exe();
Set<String> keys = mTargets.keySet(); if (receiver == null) {
for (String key : keys) { if (isDownload) {
AMReceiver target = mTargets.get(key); DownloadReceiver dReceiver = new DownloadReceiver();
target.removeSchedulerListener(); dReceiver.targetName = obj.getClass().getName();
mTargets.remove(key); mReceivers.put(key, dReceiver);
receiver = dReceiver;
} else {
UploadReceiver uReceiver = new UploadReceiver();
uReceiver.targetName = obj.getClass().getName();
mReceivers.put(key, uReceiver);
receiver = uReceiver;
}
} }
return receiver;
} }
private AMReceiver putTarget(Object obj) { /**
* 根据功能类型和控件类型获取对应的key
*/
private String getKey(boolean isDownload, Object obj) {
String clsName = obj.getClass().getName(); String clsName = obj.getClass().getName();
AMReceiver target = null;
String key = ""; String key = "";
if (!(obj instanceof Activity)) { if (!(obj instanceof Activity)) {
if (obj instanceof android.support.v4.app.Fragment) { if (obj instanceof android.support.v4.app.Fragment) {
@ -208,7 +245,6 @@ import java.util.Set;
} else { } else {
key = clsName; key = clsName;
} }
handleDialogLift((Dialog) obj);
} else if (obj instanceof PopupWindow) { } else if (obj instanceof PopupWindow) {
Context context = ((PopupWindow) obj).getContentView().getContext(); Context context = ((PopupWindow) obj).getContentView().getContext();
if (context instanceof Activity) { if (context instanceof Activity) {
@ -216,7 +252,6 @@ import java.util.Set;
} else { } else {
key = clsName; key = clsName;
} }
handlePopupWindowLift((PopupWindow) obj);
} else if (obj instanceof Service) { } else if (obj instanceof Service) {
key = clsName; key = clsName;
} else if (obj instanceof Application) { } else if (obj instanceof Application) {
@ -231,76 +266,8 @@ import java.util.Set;
if (TextUtils.isEmpty(key)) { if (TextUtils.isEmpty(key)) {
throw new IllegalArgumentException("未知类型"); throw new IllegalArgumentException("未知类型");
} }
target = mTargets.get(key); key += isDownload ? DOWNLOAD : UPLOAD;
if (target == null) { return key;
target = new AMReceiver();
target.targetName = obj.getClass().getName();
mTargets.put(key, target);
}
return target;
}
/**
* 出来悬浮框取消或dismiss
*/
private void handlePopupWindowLift(PopupWindow popupWindow) {
try {
Field dismissField = CommonUtil.getField(popupWindow.getClass(), "mOnDismissListener");
PopupWindow.OnDismissListener listener =
(PopupWindow.OnDismissListener) dismissField.get(popupWindow);
if (listener != null) {
Log.e(TAG, "你已经对PopupWindow设置了Dismiss事件。为了防止内存泄露,"
+ "请在dismiss方法中调用Aria.whit(this).removeSchedulerListener();来注销事件");
} else {
popupWindow.setOnDismissListener(createPopupWindowListener(popupWindow));
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* 创建popupWindow dismiss事件
*/
private PopupWindow.OnDismissListener createPopupWindowListener(final PopupWindow popupWindow) {
return new PopupWindow.OnDismissListener() {
@Override public void onDismiss() {
destroySchedulerListener(popupWindow);
}
};
}
/**
* 处理对话框取消或dismiss
*/
private void handleDialogLift(Dialog dialog) {
try {
Field dismissField = CommonUtil.getField(dialog.getClass(), "mDismissMessage");
Message dismissMsg = (Message) dismissField.get(dialog);
//如果Dialog已经设置Dismiss事件,则查找cancel事件
if (dismissMsg != null) {
Field cancelField = CommonUtil.getField(dialog.getClass(), "mCancelMessage");
Message cancelMsg = (Message) cancelField.get(dialog);
if (cancelMsg != null) {
Log.e(TAG, "你已经对Dialog设置了Dismiss和cancel事件。为了防止内存泄露,"
+ "请在dismiss方法中调用Aria.whit(this).removeSchedulerListener();来注销事件");
} else {
dialog.setOnCancelListener(createCancelListener());
}
} else {
dialog.setOnDismissListener(createDismissListener());
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
private AMReceiver getTarget(Object obj) {
AMReceiver target = mTargets.get(obj.getClass().getName());
if (target == null) {
target = putTarget(obj);
}
return target;
} }
/** /**
@ -309,50 +276,22 @@ import java.util.Set;
private void regAppLifeCallback(Context context) { private void regAppLifeCallback(Context context) {
Context app = context.getApplicationContext(); Context app = context.getApplicationContext();
if (app instanceof Application) { if (app instanceof Application) {
mLifeCallback = new LifeCallback(); LifeCallback mLifeCallback = new LifeCallback();
((Application) app).registerActivityLifecycleCallbacks(mLifeCallback); ((Application) app).registerActivityLifecycleCallbacks(mLifeCallback);
} }
} }
/**
* 创建Dialog取消事件
*/
private Dialog.OnCancelListener createCancelListener() {
return new Dialog.OnCancelListener() {
@Override public void onCancel(DialogInterface dialog) {
destroySchedulerListener(dialog);
}
};
}
/**
* 创建Dialog dismiss取消事件
*/
private Dialog.OnDismissListener createDismissListener() {
return new Dialog.OnDismissListener() {
@Override public void onDismiss(DialogInterface dialog) {
destroySchedulerListener(dialog);
}
};
}
/** /**
* onDestroy * onDestroy
*/ */
private void destroySchedulerListener(Object obj) { void destroySchedulerListener(Object obj) {
Set<String> keys = mTargets.keySet();
String clsName = obj.getClass().getName(); String clsName = obj.getClass().getName();
for (Iterator<Map.Entry<String, AMReceiver>> iter = mTargets.entrySet().iterator(); for (Iterator<Map.Entry<String, IReceiver>> iter = mReceivers.entrySet().iterator();
iter.hasNext(); ) { iter.hasNext(); ) {
Map.Entry<String, AMReceiver> entry = iter.next(); Map.Entry<String, IReceiver> entry = iter.next();
String key = entry.getKey(); String key = entry.getKey();
if (key.equals(clsName) || key.contains(clsName)) { if (key.contains(clsName)) {
AMReceiver receiver = mTargets.get(key); IReceiver receiver = mReceivers.get(key);
if (receiver.obj != null) {
if (receiver.obj instanceof Application || receiver.obj instanceof Service) break;
}
receiver.removeSchedulerListener(); receiver.removeSchedulerListener();
receiver.destroy(); receiver.destroy();
iter.remove(); iter.remove();

@ -1,107 +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;
import android.content.Context;
import com.arialyy.aria.core.queue.ITaskQueue;
import com.arialyy.aria.orm.DbUtil;
import com.arialyy.aria.core.command.IDownloadCmd;
import com.arialyy.aria.core.queue.DownloadTaskQueue;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.Configuration;
import java.util.ArrayList;
import java.util.List;
/**
* Created by lyy on 2016/8/11.
* 下载管理器通过命令的方式控制下载
*/
public class DownloadManager {
private static final String TAG = "DownloadManager";
private static final Object LOCK = new Object();
private static volatile DownloadManager INSTANCE = null;
private List<IDownloadCmd> mCommands = new ArrayList<>();
public static Context APP;
private ITaskQueue mTaskQueue;
private static Configuration mConfig;
private DownloadManager() {
}
private DownloadManager(Context context) {
APP = context;
DownloadTaskQueue.Builder builder = new DownloadTaskQueue.Builder(context);
mTaskQueue = builder.build();
DbUtil.init(context);
}
static DownloadManager init(Context context) {
if (INSTANCE == null) {
synchronized (LOCK) {
INSTANCE = new DownloadManager(context.getApplicationContext());
}
}
return INSTANCE;
}
public static DownloadManager getInstance() {
if (INSTANCE == null) {
throw new NullPointerException("请在Application中调用init进行下载器注册");
}
return INSTANCE;
}
List<DownloadEntity> getAllDownloadEntity() {
return DbEntity.findAllData(DownloadEntity.class);
}
/**
* 获取任务队列
*/
public ITaskQueue getTaskQueue() {
return mTaskQueue;
}
/**
* 设置命令
*/
DownloadManager setCmd(IDownloadCmd command) {
mCommands.add(command);
return this;
}
/**
* 设置一组命令
*/
DownloadManager setCmds(List<IDownloadCmd> commands) {
if (commands != null && commands.size() > 0) {
mCommands.addAll(commands);
}
return this;
}
/**
* 执行所有设置的命令
*/
synchronized void exe() {
for (IDownloadCmd command : mCommands) {
command.executeCmd();
}
mCommands.clear();
}
}

@ -1,13 +1,28 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core; package com.arialyy.aria.core;
/** /**
* Created by Aria.Lao on 2017/1/23. * Created by Aria.Lao on 2017/1/23.
* url请求方式目前支持GETPOST
*/ */
public enum RequestEnum { public enum RequestEnum {
GET("GET"), POST("POST"); GET("GET"), POST("POST");
String name; public String name;
RequestEnum(String name) { RequestEnum(String name) {
this.name = name; this.name = name;

@ -1,10 +0,0 @@
package com.arialyy.aria.core;
/**
* Created by Aria.Lao on 2017/1/23.
* 任务实体
*/
public class TaskEntity {
public DownloadEntity downloadEntity;
public RequestEnum requestEnum = RequestEnum.GET;
}

@ -0,0 +1,111 @@
/*
* 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;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Message;
import android.util.Log;
import android.widget.PopupWindow;
import com.arialyy.aria.util.CommonUtil;
import java.lang.reflect.Field;
/**
* Created by Aria.Lao on 2017/2/7.
* 为组件添加生命周期
*/
final class WidgetLiftManager {
private final String TAG = "WidgetLiftManager";
/**
* 处理悬浮框取消或dismiss事件
*/
void handlePopupWindowLift(PopupWindow popupWindow) {
try {
Field dismissField = CommonUtil.getField(popupWindow.getClass(), "mOnDismissListener");
PopupWindow.OnDismissListener listener =
(PopupWindow.OnDismissListener) dismissField.get(popupWindow);
if (listener != null) {
Log.e(TAG, "你已经对PopupWindow设置了Dismiss事件。为了防止内存泄露,"
+ "请在dismiss方法中调用Aria.download(this).removeSchedulerListener();来注销事件");
} else {
popupWindow.setOnDismissListener(createPopupWindowListener(popupWindow));
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* 创建popupWindow dismiss事件
*/
private PopupWindow.OnDismissListener createPopupWindowListener(final PopupWindow popupWindow) {
return new PopupWindow.OnDismissListener() {
@Override public void onDismiss() {
AriaManager.getInstance(AriaManager.APP).destroySchedulerListener(popupWindow);
}
};
}
/**
* 处理对话框取消或dismiss
*/
void handleDialogLift(Dialog dialog) {
try {
Field dismissField = CommonUtil.getField(dialog.getClass(), "mDismissMessage");
Message dismissMsg = (Message) dismissField.get(dialog);
//如果Dialog已经设置Dismiss事件,则查找cancel事件
if (dismissMsg != null) {
Field cancelField = CommonUtil.getField(dialog.getClass(), "mCancelMessage");
Message cancelMsg = (Message) cancelField.get(dialog);
if (cancelMsg != null) {
Log.e(TAG, "你已经对Dialog设置了Dismiss和cancel事件。为了防止内存泄露,"
+ "请在dismiss方法中调用Aria.download(this).removeSchedulerListener();来注销事件");
} else {
dialog.setOnCancelListener(createCancelListener());
}
} else {
dialog.setOnDismissListener(createDismissListener());
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* 创建Dialog取消事件
*/
private Dialog.OnCancelListener createCancelListener() {
return new Dialog.OnCancelListener() {
@Override public void onCancel(DialogInterface dialog) {
AriaManager.getInstance(AriaManager.APP).destroySchedulerListener(dialog);
}
};
}
/**
* 创建Dialog dismiss取消事件
*/
private Dialog.OnDismissListener createDismissListener() {
return new Dialog.OnDismissListener() {
@Override public void onDismiss(DialogInterface dialog) {
AriaManager.getInstance(AriaManager.APP).destroySchedulerListener(dialog);
}
};
}
}

@ -16,44 +16,38 @@
package com.arialyy.aria.core.command; package com.arialyy.aria.core.command;
import com.arialyy.aria.core.DownloadManager; import com.arialyy.aria.core.download.DownloadTaskEntity;
import com.arialyy.aria.core.inf.ITaskEntity;
import com.arialyy.aria.core.queue.DownloadTaskQueue;
import com.arialyy.aria.core.queue.ITaskQueue; import com.arialyy.aria.core.queue.ITaskQueue;
import com.arialyy.aria.core.inf.ICmd;
import com.arialyy.aria.core.queue.UploadTaskQueue;
import com.arialyy.aria.core.upload.UploadTaskEntity;
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.core.DownloadEntity;
/** /**
* Created by lyy on 2016/8/22. * Created by lyy on 2016/8/22.
* 下载命令 * 下载命令
*/ */
public abstract class IDownloadCmd { public abstract class AbsCmd<T extends ITaskEntity> implements ICmd {
ITaskQueue mQueue; ITaskQueue mQueue;
DownloadEntity mEntity; T mEntity;
String TAG; String TAG;
String mTargetName; String mTargetName;
/**
* @param entity 下载实体
*/
IDownloadCmd(DownloadEntity entity) {
this(null, entity);
}
/** /**
* @param targetName 产生任务的对象名 * @param targetName 产生任务的对象名
*/ */
IDownloadCmd(String targetName, DownloadEntity entity) { AbsCmd(String targetName, T entity) {
if (!CheckUtil.checkDownloadEntity(entity)) { CheckUtil.checkCmdEntity(entity);
return;
}
mTargetName = targetName; mTargetName = targetName;
mEntity = entity; mEntity = entity;
TAG = CommonUtil.getClassName(this); TAG = CommonUtil.getClassName(this);
mQueue = DownloadManager.getInstance().getTaskQueue(); if (entity instanceof DownloadTaskEntity) {
mQueue = DownloadTaskQueue.getInstance();
} else if (entity instanceof UploadTaskEntity) {
mQueue = UploadTaskQueue.getInstance();
}
} }
/**
* 执行命令
*/
public abstract void executeCmd();
} }

@ -17,29 +17,42 @@
package com.arialyy.aria.core.command; package com.arialyy.aria.core.command;
import android.util.Log; import android.util.Log;
import com.arialyy.aria.core.DownloadEntity; import com.arialyy.aria.core.inf.ITask;
import com.arialyy.aria.core.task.Task; import com.arialyy.aria.core.inf.ITaskEntity;
/** /**
* Created by lyy on 2016/8/22. * Created by lyy on 2016/8/22.
* 添加任务的命令 * 添加任务的命令
*/ */
class AddCmd extends IDownloadCmd { class AddCmd<T extends ITaskEntity> extends AbsCmd<T> {
AddCmd(DownloadEntity entity) { AddCmd(String targetName, T entity) {
super(entity); super(targetName, entity);
}
AddCmd(String target, DownloadEntity entity) {
super(target, entity);
} }
@Override public void executeCmd() { @Override public void executeCmd() {
Task task = mQueue.getTask(mEntity); ITask task = mQueue.getTask(mEntity.getEntity());
if (task == null) { if (task == null) {
mQueue.createTask(mTargetName, mEntity); mQueue.createTask(mTargetName, mEntity);
} else { } else {
Log.w(TAG, "添加命令执行失败,【该任务已经存在】"); Log.w(TAG, "添加命令执行失败,【该任务已经存在】");
} }
} }
//AddCmd(DownloadTaskEntity entity) {
// super(entity);
//}
//
//AddCmd(String targetName, DownloadTaskEntity entity) {
// super(targetName, entity);
//}
//
//@Override public void executeCmd() {
// DownloadTask task = mQueue.getTask(mEntity.downloadEntity);
// if (task == null) {
// mQueue.createTask(mTargetName, mEntity);
// } else {
// Log.w(TAG, "添加命令执行失败,【该任务已经存在】");
// }
//}
} }

@ -16,25 +16,20 @@
package com.arialyy.aria.core.command; package com.arialyy.aria.core.command;
import com.arialyy.aria.core.DownloadEntity; import com.arialyy.aria.core.inf.ITask;
import com.arialyy.aria.core.task.Task; import com.arialyy.aria.core.inf.ITaskEntity;
/** /**
* Created by lyy on 2016/9/20. * Created by lyy on 2016/9/20.
* 取消命令 * 取消命令
*/ */
class CancelCmd extends IDownloadCmd { class CancelCmd<T extends ITaskEntity> extends AbsCmd<T> {
CancelCmd(String targetName, T entity) {
CancelCmd(String target, DownloadEntity entity) { super(targetName, entity);
super(target, entity);
}
CancelCmd(DownloadEntity entity) {
super(entity);
} }
@Override public void executeCmd() { @Override public void executeCmd() {
Task task = mQueue.getTask(mEntity); ITask task = mQueue.getTask(mEntity.getEntity());
if (task == null) { if (task == null) {
task = mQueue.createTask(mTargetName, mEntity); task = mQueue.createTask(mTargetName, mEntity);
} }
@ -45,4 +40,25 @@ class CancelCmd extends IDownloadCmd {
mQueue.cancelTask(task); mQueue.cancelTask(task);
} }
} }
//CancelCmd(DownloadTaskEntity entity) {
// super(entity);
//}
//
//CancelCmd(String targetName, DownloadTaskEntity entity) {
// super(targetName, entity);
//}
//
//@Override public void executeCmd() {
// DownloadTask task = mQueue.getTask(mEntity.downloadEntity);
// if (task == null) {
// task = mQueue.createTask(mTargetName, mEntity);
// }
// if (task != null) {
// if (mTargetName != null) {
// task.setTargetName(mTargetName);
// }
// mQueue.cancelTask(task);
// }
//}
} }

@ -16,7 +16,7 @@
package com.arialyy.aria.core.command; package com.arialyy.aria.core.command;
import com.arialyy.aria.core.DownloadEntity; import com.arialyy.aria.core.inf.ITaskEntity;
/** /**
* Created by Lyy on 2016/9/23. * Created by Lyy on 2016/9/23.
@ -30,7 +30,7 @@ public class CmdFactory {
/** /**
* 启动任务 * 启动任务
*/ */
public static final int TASK_START = 0x123; public static final int TASK_START = 0x123;
/** /**
* 恢复任务 * 恢复任务
*/ */
@ -42,10 +42,10 @@ public class CmdFactory {
/** /**
* 停止任务 * 停止任务
*/ */
public static final int TASK_STOP = 0x125; public static final int TASK_STOP = 0x125;
public static final int TASK_SINGLE = 0x126; public static final int TASK_SINGLE = 0x126;
private static final Object LOCK = new Object(); private static final Object LOCK = new Object();
private static volatile CmdFactory INSTANCE = null; private static volatile CmdFactory INSTANCE = null;
private CmdFactory() { private CmdFactory() {
@ -61,36 +61,13 @@ public class CmdFactory {
return INSTANCE; return INSTANCE;
} }
/**
* @param entity 下载实体
* @param type 命令类型{@link #TASK_CREATE}{@link #TASK_START}{@link #TASK_CANCEL}{@link
* #TASK_STOP}
*/
public IDownloadCmd createCmd(DownloadEntity entity, int type) {
switch (type) {
case TASK_CREATE:
return createAddCmd(entity);
case TASK_RESUME:
case TASK_START:
return createStartCmd(entity);
case TASK_CANCEL:
return createCancelCmd(entity);
case TASK_STOP:
return createStopCmd(entity);
case TASK_SINGLE:
return new SingleCmd(entity);
default:
return null;
}
}
/** /**
* @param target 创建任务的对象 * @param target 创建任务的对象
* @param entity 下载实体 * @param entity 下载实体
* @param type 命令类型{@link #TASK_CREATE}{@link #TASK_START}{@link #TASK_CANCEL}{@link * @param type 命令类型{@link #TASK_CREATE}{@link #TASK_START}{@link #TASK_CANCEL}{@link
* #TASK_STOP} * #TASK_STOP}
*/ */
public IDownloadCmd createCmd(String target, DownloadEntity entity, int type) { public <T extends ITaskEntity> AbsCmd createCmd(String target, T entity, int type) {
switch (type) { switch (type) {
case TASK_CREATE: case TASK_CREATE:
return createAddCmd(target, entity); return createAddCmd(target, entity);
@ -102,7 +79,7 @@ public class CmdFactory {
case TASK_STOP: case TASK_STOP:
return createStopCmd(target, entity); return createStopCmd(target, entity);
case TASK_SINGLE: case TASK_SINGLE:
return new SingleCmd(target, entity); //return new SingleCmd(target, entity);
default: default:
return null; return null;
} }
@ -113,43 +90,25 @@ public class CmdFactory {
* *
* @return {@link StopCmd} * @return {@link StopCmd}
*/ */
private StopCmd createStopCmd(String target, DownloadEntity entity) { private <T extends ITaskEntity> StopCmd createStopCmd(String target, T entity) {
return new StopCmd(target, entity); return new StopCmd(target, entity);
} }
/**
* 创建停止命令
*
* @return {@link StopCmd}
*/
private StopCmd createStopCmd(DownloadEntity entity) {
return new StopCmd(entity);
}
/** /**
* 创建下载任务命令 * 创建下载任务命令
* *
* @return {@link AddCmd} * @return {@link AddCmd}
*/ */
private AddCmd createAddCmd(String target, DownloadEntity entity) { private <T extends ITaskEntity> AddCmd createAddCmd(String target, T entity) {
return new AddCmd(target, entity); return new AddCmd(target, entity);
} }
/**
* 创建下载任务命令
*
* @return {@link AddCmd}
*/
private AddCmd createAddCmd(DownloadEntity entity) {
return new AddCmd(entity);
}
/** /**
* 创建启动下载命令 * 创建启动下载命令
* *
* @return {@link StartCmd} * @return {@link StartCmd}
*/ */
private StartCmd createStartCmd(String target, DownloadEntity entity) { private <T extends ITaskEntity> StartCmd createStartCmd(String target, T entity) {
return new StartCmd(target, entity); return new StartCmd(target, entity);
} }
@ -158,25 +117,7 @@ public class CmdFactory {
* *
* @return {@link StartCmd} * @return {@link StartCmd}
*/ */
private StartCmd createStartCmd(DownloadEntity entity) { private <T extends ITaskEntity> CancelCmd createCancelCmd(String target, T entity) {
return new StartCmd(entity);
}
/**
* 创建 取消下载的命令
*
* @return {@link CancelCmd}
*/
private CancelCmd createCancelCmd(String target, DownloadEntity entity) {
return new CancelCmd(target, entity); return new CancelCmd(target, entity);
} }
/**
* 创建 取消下载的命令
*
* @return {@link CancelCmd}
*/
private CancelCmd createCancelCmd(DownloadEntity entity) {
return new CancelCmd(entity);
}
} }

@ -1,48 +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.command;
import android.util.Log;
import com.arialyy.aria.core.DownloadEntity;
import com.arialyy.aria.core.task.Task;
/**
* Created by lyy on 2016/11/30.
* 获取任务状态命令
*/
class SingleCmd extends IDownloadCmd {
/**
* @param entity 下载实体
*/
SingleCmd(String target, DownloadEntity entity) {
super(target, entity);
}
SingleCmd(DownloadEntity entity) {
super(entity);
}
@Override public void executeCmd() {
Task task = mQueue.getTask(mEntity);
if (task == null) {
task = mQueue.createTask(mTargetName, mEntity);
} else {
Log.w(TAG, "添加命令执行失败,【该任务已经存在】");
}
task.setTargetName(mTargetName);
mQueue.startTask(task);
}
}

@ -16,25 +16,22 @@
package com.arialyy.aria.core.command; package com.arialyy.aria.core.command;
import com.arialyy.aria.core.DownloadEntity; import android.util.Log;
import com.arialyy.aria.core.task.Task; import com.arialyy.aria.core.inf.ITask;
import com.arialyy.aria.core.inf.ITaskEntity;
/** /**
* Created by lyy on 2016/8/22. * Created by lyy on 2016/8/22.
* 开始命令 * 开始命令
*/ */
class StartCmd extends IDownloadCmd { class StartCmd<T extends ITaskEntity> extends AbsCmd<T> {
StartCmd(String target, DownloadEntity entity) { StartCmd(String targetName, T entity) {
super(target, entity); super(targetName, entity);
}
StartCmd(DownloadEntity entity) {
super(entity);
} }
@Override public void executeCmd() { @Override public void executeCmd() {
Task task = mQueue.getTask(mEntity); ITask task = mQueue.getTask(mEntity.getEntity());
if (task == null) { if (task == null) {
task = mQueue.createTask(mTargetName, mEntity); task = mQueue.createTask(mTargetName, mEntity);
} }
@ -43,4 +40,23 @@ class StartCmd extends IDownloadCmd {
mQueue.startTask(task); mQueue.startTask(task);
} }
} }
//StartCmd(DownloadTaskEntity entity) {
// super(entity);
//}
//
//StartCmd(String targetName, DownloadTaskEntity entity) {
// super(targetName, entity);
//}
//
//@Override public void executeCmd() {
// DownloadTask task = mQueue.getTask(mEntity.downloadEntity);
// if (task == null) {
// task = mQueue.createTask(mTargetName, mEntity);
// }
// if (task != null) {
// task.setTargetName(mTargetName);
// mQueue.startTask(task);
// }
//}
} }

@ -18,30 +18,24 @@ package com.arialyy.aria.core.command;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.arialyy.aria.core.DownloadEntity; import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.task.Task; import com.arialyy.aria.core.inf.ITask;
import com.arialyy.aria.core.inf.ITaskEntity;
/** /**
* Created by lyy on 2016/9/20. * Created by lyy on 2016/9/20.
* 停止命令 * 停止命令
*/ */
class StopCmd extends IDownloadCmd { class StopCmd<T extends ITaskEntity> extends AbsCmd<T> {
/** StopCmd(String targetName, T entity) {
* @param entity 下载实体 super(targetName, entity);
*/
StopCmd(String target, DownloadEntity entity) {
super(target, entity);
}
StopCmd(DownloadEntity entity) {
super(entity);
} }
@Override public void executeCmd() { @Override public void executeCmd() {
Task task = mQueue.getTask(mEntity); ITask task = mQueue.getTask(mEntity.getEntity());
if (task == null) { if (task == null) {
if (mEntity.getState() == DownloadEntity.STATE_DOWNLOAD_ING) { if (mEntity.getEntity().getState() == IEntity.STATE_RUNNING) {
task = mQueue.createTask(mTargetName, mEntity); task = mQueue.createTask(mTargetName, mEntity);
mQueue.stopTask(task); mQueue.stopTask(task);
} else { } else {
@ -54,4 +48,29 @@ class StopCmd extends IDownloadCmd {
mQueue.stopTask(task); mQueue.stopTask(task);
} }
} }
//StopCmd(DownloadTaskEntity entity) {
// super(entity);
//}
//
//StopCmd(String targetName, DownloadTaskEntity entity) {
// super(targetName, entity);
//}
//
//@Override public void executeCmd() {
// DownloadTask task = mQueue.getTask(mEntity.downloadEntity);
// if (task == null) {
// if (mEntity.downloadEntity.getState() == DownloadEntity.STATE_RUNNING) {
// task = mQueue.createTask(mTargetName, mEntity);
// mQueue.stopTask(task);
// } else {
// Log.w(TAG, "停止命令执行失败,【调度器中没有该任务】");
// }
// } else {
// if (!TextUtils.isEmpty(mTargetName)) {
// task.setTargetName(mTargetName);
// }
// mQueue.stopTask(task);
// }
//}
} }

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.task; package com.arialyy.aria.core.download;
import com.arialyy.aria.util.CAConfiguration; import com.arialyy.aria.util.CAConfiguration;
import com.arialyy.aria.util.SSLContextUtil; import com.arialyy.aria.util.SSLContextUtil;
@ -22,6 +22,7 @@ import java.net.HttpURLConnection;
import java.net.ProtocolException; import java.net.ProtocolException;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.util.Set;
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.SSLSocketFactory;
@ -60,8 +61,15 @@ class ConnectionHelp {
* *
* @throws ProtocolException * @throws ProtocolException
*/ */
static HttpURLConnection setConnectParam(HttpURLConnection conn) throws ProtocolException { static HttpURLConnection setConnectParam(DownloadTaskEntity entity, HttpURLConnection conn)
conn.setRequestMethod("GET"); throws ProtocolException {
conn.setRequestMethod(entity.requestEnum.name);
if (entity.headers != null && entity.headers.size() > 0) {
Set<String> keys = entity.headers.keySet();
for (String key : keys) {
conn.setRequestProperty(key, entity.headers.get(key));
}
}
conn.setRequestProperty("Charset", "UTF-8"); conn.setRequestProperty("Charset", "UTF-8");
conn.setRequestProperty("User-Agent", conn.setRequestProperty("User-Agent",
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"); "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");

@ -14,11 +14,12 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.download;
package com.arialyy.aria.core;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.ITaskEntity;
import com.arialyy.aria.orm.Ignore; import com.arialyy.aria.orm.Ignore;
import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.orm.DbEntity;
@ -28,43 +29,7 @@ import com.arialyy.aria.orm.DbEntity;
* 注意CREATOR要进行@Ignore注解 * 注意CREATOR要进行@Ignore注解
* 并且需要Parcelable时需要手动填写rowID; * 并且需要Parcelable时需要手动填写rowID;
*/ */
public class DownloadEntity extends DbEntity implements Parcelable { public class DownloadEntity extends DbEntity implements Parcelable, IEntity {
/**
* 其它状态
*/
@Ignore public static final int STATE_OTHER = -1;
/**
* 失败状态
*/
@Ignore public static final int STATE_FAIL = 0;
/**
* 完成状态
*/
@Ignore public static final int STATE_COMPLETE = 1;
/**
* 停止状态
*/
@Ignore public static final int STATE_STOP = 2;
/**
* 未开始状态
*/
@Ignore public static final int STATE_WAIT = 3;
/**
* 下载中
*/
@Ignore public static final int STATE_DOWNLOAD_ING = 4;
/**
* 预处理
*/
@Ignore public static final int STATE_PRE = 5;
/**
* 预处理完成
*/
@Ignore public static final int STATE_POST_PRE = 6;
/**
* 取消下载
*/
@Ignore public static final int STATE_CANCEL = 7;
@Ignore public static final Creator<DownloadEntity> CREATOR = new Creator<DownloadEntity>() { @Ignore public static final Creator<DownloadEntity> CREATOR = new Creator<DownloadEntity>() {
@Override public DownloadEntity createFromParcel(Parcel source) { @Override public DownloadEntity createFromParcel(Parcel source) {
return new DownloadEntity(source); return new DownloadEntity(source);
@ -74,16 +39,16 @@ public class DownloadEntity extends DbEntity implements Parcelable {
return new DownloadEntity[size]; return new DownloadEntity[size];
} }
}; };
@Ignore private long speed = 0; //下载速度 @Ignore private long speed = 0; //下载速度
@Ignore private int failNum = 0; @Ignore private int failNum = 0;
private String downloadUrl = ""; //下载路径 private String downloadUrl = ""; //下载路径
private String downloadPath = ""; //保存路径 private String downloadPath = ""; //保存路径
private String fileName = ""; //文件名 private String fileName = ""; //文件名
private String str = ""; //其它字段 private String str = ""; //其它字段
private long fileSize = 1; private long fileSize = 1;
private int state = STATE_WAIT; private int state = STATE_WAIT;
private boolean isDownloadComplete = false; //是否下载完成 private boolean isDownloadComplete = false; //是否下载完成
private long currentProgress = 0; //当前下载进度 private long currentProgress = 0; //当前下载进度
private long completeTime; //完成时间 private long completeTime; //完成时间
public DownloadEntity() { public DownloadEntity() {
@ -163,7 +128,7 @@ public class DownloadEntity extends DbEntity implements Parcelable {
this.fileSize = fileSize; this.fileSize = fileSize;
} }
public int getState() { @Override public int getState() {
return state; return state;
} }
@ -200,16 +165,26 @@ public class DownloadEntity extends DbEntity implements Parcelable {
} }
@Override public String toString() { @Override public String toString() {
return "DownloadEntity{" + return "DownloadEntity{"
"downloadUrl='" + downloadUrl + '\'' + + "downloadUrl='"
", downloadPath='" + downloadPath + '\'' + + downloadUrl
", completeTime=" + completeTime + + '\''
", fileSize=" + fileSize + + ", downloadPath='"
", state=" + state + + downloadPath
", isDownloadComplete=" + isDownloadComplete + + '\''
", currentProgress=" + currentProgress + + ", completeTime="
", failNum=" + failNum + + completeTime
'}'; + ", fileSize="
+ fileSize
+ ", state="
+ state
+ ", isDownloadComplete="
+ isDownloadComplete
+ ", currentProgress="
+ currentProgress
+ ", failNum="
+ failNum
+ '}';
} }
@Override public int describeContents() { @Override public int describeContents() {

@ -14,8 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.download;
package com.arialyy.aria.core.task;
class DownloadListener implements IDownloadListener { class DownloadListener implements IDownloadListener {

@ -0,0 +1,139 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.download;
import android.support.annotation.NonNull;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.inf.IReceiver;
import com.arialyy.aria.core.command.CmdFactory;
import com.arialyy.aria.core.command.AbsCmd;
import com.arialyy.aria.core.scheduler.DownloadSchedulers;
import com.arialyy.aria.core.scheduler.ISchedulerListener;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.CommonUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* Created by lyy on 2016/12/5.
* 下载功能接收器
*/
public class DownloadReceiver implements IReceiver<DownloadEntity> {
private static final String TAG = "DownloadReceiver";
public String targetName;
public ISchedulerListener<DownloadTask> listener;
/**
* {@link #load(String)}请使用该方法
*/
@Deprecated public DownloadTarget load(DownloadEntity entity) {
return new DownloadTarget(entity, targetName);
}
/**
* 读取下载链接
*/
public DownloadTarget load(@NonNull String downloadUrl) {
CheckUtil.checkDownloadUrl(downloadUrl);
DownloadEntity entity =
DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl);
if (entity == null) {
entity = new DownloadEntity();
}
entity.setDownloadUrl(downloadUrl);
return new DownloadTarget(entity, targetName);
}
/**
* 添加调度器回调
*/
public DownloadReceiver addSchedulerListener(ISchedulerListener<DownloadTask> listener) {
this.listener = listener;
DownloadSchedulers.getInstance().addSchedulerListener(targetName, listener);
return this;
}
/**
* 移除回调
*/
@Override public void removeSchedulerListener() {
if (listener != null) {
DownloadSchedulers.getInstance().removeSchedulerListener(targetName, listener);
}
}
@Override public void destroy() {
targetName = null;
listener = null;
}
/**
* 通过下载链接获取下载实体
*/
public DownloadEntity getDownloadEntity(String downloadUrl) {
CheckUtil.checkDownloadUrl(downloadUrl);
return DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl);
}
/**
* 下载任务是否存在
*/
@Override public boolean taskExists(String downloadUrl) {
return DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl) != null;
}
@Override public List<DownloadEntity> getTaskList() {
return DownloadEntity.findAllData(DownloadEntity.class);
}
/**
* 停止所有正在下载的任务
*/
@Override public void stopAllTask() {
final AriaManager ariaManager = AriaManager.getInstance(AriaManager.APP);
List<DownloadEntity> allEntity = DbEntity.findAllData(DownloadEntity.class);
List<AbsCmd> stopCmds = new ArrayList<>();
for (DownloadEntity entity : allEntity) {
if (entity.getState() == DownloadEntity.STATE_RUNNING) {
stopCmds.add(
CommonUtil.createCmd(targetName, new DownloadTaskEntity(entity), CmdFactory.TASK_STOP));
}
}
ariaManager.setCmds(stopCmds).exe();
}
/**
* 删除所有任务
*/
@Override public void removeAllTask() {
final AriaManager ariaManager = AriaManager.getInstance(AriaManager.APP);
List<DownloadEntity> allEntity = DbEntity.findAllData(DownloadEntity.class);
List<AbsCmd> cancelCmds = new ArrayList<>();
for (DownloadEntity entity : allEntity) {
cancelCmds.add(
CommonUtil.createCmd(targetName, new DownloadTaskEntity(entity), CmdFactory.TASK_CANCEL));
}
ariaManager.setCmds(cancelCmds).exe();
Set<String> keys = ariaManager.getReceiver().keySet();
for (String key : keys) {
IReceiver receiver = ariaManager.getReceiver().get(key);
receiver.removeSchedulerListener();
ariaManager.getReceiver().remove(key);
}
}
}

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.task; package com.arialyy.aria.core.download;
/** /**
* Created by lyy on 2017/1/18. * Created by lyy on 2017/1/18.
@ -32,8 +32,7 @@ final class DownloadStateConstance {
boolean isCancel = false; boolean isCancel = false;
boolean isStop = false; boolean isStop = false;
DownloadStateConstance(int num) { DownloadStateConstance() {
THREAD_NUM = num;
} }
void cleanState() { void cleanState() {
@ -46,6 +45,10 @@ final class DownloadStateConstance {
FAIL_NUM = 0; FAIL_NUM = 0;
} }
void setThreadNum(int threadNum) {
THREAD_NUM = threadNum;
}
/** /**
* 所有子线程是否都已经停止下载 * 所有子线程是否都已经停止下载
*/ */

@ -0,0 +1,113 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.download;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import com.arialyy.aria.core.RequestEnum;
import com.arialyy.aria.core.inf.AbsTarget;
import com.arialyy.aria.core.queue.DownloadTaskQueue;
import com.arialyy.aria.util.CheckUtil;
import java.io.File;
import java.util.Map;
/**
* Created by lyy on 2016/12/5.
* https://github.com/AriaLyy/Aria
*/
public class DownloadTarget extends AbsTarget<DownloadEntity, DownloadTaskEntity> {
DownloadTarget(DownloadEntity entity, String targetName) {
this.entity = entity;
this.targetName = targetName;
taskEntity = new DownloadTaskEntity(entity);
}
@Override public void pause() {
super.pause();
}
@Override public void resume() {
super.resume();
}
/**
* 给url请求添加头部
*
* @param key 头部key
* @param header 头部value
*/
public DownloadTarget addHeader(@NonNull String key, @NonNull String header) {
super._addHeader(key, header);
return this;
}
/**
* 给url请求添加头部
*
* @param headers key为http头部的keyValue为http头对应的配置
*/
public DownloadTarget addHeaders(Map<String, String> headers) {
super._addHeaders(headers);
return this;
}
/**
* 设置请求类型
*
* @param requestEnum {@link RequestEnum}
*/
public DownloadTarget setRequestMode(RequestEnum requestEnum) {
super._setRequestMode(requestEnum);
return this;
}
/**
* 设置文件存储路径
*/
public DownloadTarget setDownloadPath(@NonNull String downloadPath) {
if (TextUtils.isEmpty(downloadPath)) {
throw new IllegalArgumentException("文件保持路径不能为null");
}
File file = new File(downloadPath);
entity.setDownloadPath(downloadPath);
entity.setFileName(file.getName());
return this;
}
/**
* 设置文件名
*/
@Deprecated public DownloadTarget setDownloadName(@NonNull String downloadName) {
if (TextUtils.isEmpty(downloadName)) {
throw new IllegalArgumentException("文件名不能为null");
}
entity.setFileName(downloadName);
return this;
}
private DownloadEntity getDownloadEntity(String downloadUrl) {
CheckUtil.checkDownloadUrl(downloadUrl);
return DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl);
}
/**
* 是否在下载
*/
public boolean isDownloading() {
return DownloadTaskQueue.getInstance().getTask(entity).isRunning();
}
}

@ -14,18 +14,19 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.task; package com.arialyy.aria.core.download;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Handler; import android.os.Handler;
import android.util.Log; import android.util.Log;
import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.DownloadManager; import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.TaskEntity; import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.ITask;
import com.arialyy.aria.core.scheduler.DownloadSchedulers; import com.arialyy.aria.core.scheduler.DownloadSchedulers;
import com.arialyy.aria.core.scheduler.IDownloadSchedulers; import com.arialyy.aria.core.scheduler.ISchedulers;
import com.arialyy.aria.core.DownloadEntity; import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.Configuration; import com.arialyy.aria.util.Configuration;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
@ -34,62 +35,87 @@ import java.lang.ref.WeakReference;
* Created by lyy on 2016/8/11. * Created by lyy on 2016/8/11.
* 下载任务类 * 下载任务类
*/ */
public class Task { public class DownloadTask implements ITask {
public static final String TAG = "Task"; public static final String TAG = "DownloadTask";
/** /**
* 产生该任务对象的hash码 * 产生该任务对象的hash码
*/ */
private String mTargetName; private String mTargetName;
private DownloadEntity mEntity; private DownloadEntity mEntity;
private DownloadTaskEntity mTaskEntity;
private IDownloadListener mListener; private IDownloadListener mListener;
private Handler mOutHandler; private Handler mOutHandler;
private Context mContext; private IDownloadUtil mUtil;
private IDownloadUtil mUtil; private Context mContext;
private Task(Context context, DownloadEntity entity, Handler outHandler) { private DownloadTask(DownloadTaskEntity taskEntity, Handler outHandler) {
mContext = context.getApplicationContext(); mTaskEntity = taskEntity;
mEntity = entity; mEntity = taskEntity.downloadEntity;
mOutHandler = outHandler; mOutHandler = outHandler;
mContext = AriaManager.APP;
init(); init();
} }
private void init() { private void init() {
mListener = new DListener(mContext, this, mOutHandler); mListener = new DListener(mContext, this, mOutHandler);
mUtil = new DownloadUtil(mContext, mEntity, mListener); mUtil = new DownloadUtil(mContext, mTaskEntity, mListener);
} }
/** /**
* 获取下载速度 * 获取下载速度
*/ */
public long getSpeed() { @Override public long getSpeed() {
return mEntity.getSpeed(); return mEntity.getSpeed();
} }
/** /**
* 获取文件大小 * 获取文件大小
*/ */
public long getFileSize() { @Override public long getFileSize() {
return mEntity.getFileSize(); return mEntity.getFileSize();
} }
/** /**
* 获取当前下载进度 * 获取当前下载进度
*/ */
public long getCurrentProgress() { @Override public long getCurrentProgress() {
return mEntity.getCurrentProgress(); return mEntity.getCurrentProgress();
} }
/** /**
* 获取当前下载任务的下载地址 * 获取当前下载任务的下载地址
*
* @see DownloadTask#getKey()
*/ */
public String getDownloadUrl() { @Deprecated public String getDownloadUrl() {
return mEntity.getDownloadUrl(); return mEntity.getDownloadUrl();
} }
@Override public String getKey() {
return getDownloadUrl();
}
/**
* 任务下载状态
*
* @see DownloadTask#isRunning()
*/
@Deprecated public boolean isDownloading() {
return mUtil.isDownloading();
}
@Override public boolean isRunning() {
return isDownloading();
}
@Override public DownloadEntity getEntity() {
return mEntity;
}
/** /**
* 开始下载 * 开始下载
*/ */
public void start() { @Override public void start() {
if (mUtil.isDownloading()) { if (mUtil.isDownloading()) {
Log.d(TAG, "任务正在下载"); Log.d(TAG, "任务正在下载");
} else { } else {
@ -108,14 +134,14 @@ public class Task {
return mTargetName; return mTargetName;
} }
public void setTargetName(String targetName) { @Override public void setTargetName(String targetName) {
this.mTargetName = targetName; this.mTargetName = targetName;
} }
/** /**
* 停止下载 * 停止下载
*/ */
public void stop() { @Override public void stop() {
if (mUtil.isDownloading()) { if (mUtil.isDownloading()) {
mUtil.stopDownload(); mUtil.stopDownload();
} else { } else {
@ -132,17 +158,10 @@ public class Task {
} }
} }
/**
* 任务下载状态
*/
public boolean isDownloading() {
return mUtil.isDownloading();
}
/** /**
* 取消下载 * 取消下载
*/ */
public void cancel() { @Override public void cancel() {
if (mUtil.isDownloading()) { if (mUtil.isDownloading()) {
mUtil.cancelDownload(); mUtil.cancelDownload();
} else { } else {
@ -161,30 +180,24 @@ public class Task {
} }
} }
static class Builder { public static class Builder {
DownloadEntity downloadEntity; DownloadTaskEntity taskEntity;
Handler outHandler; Handler outHandler;
Context context;
int threadNum = 3; int threadNum = 3;
String targetName; String targetName;
IDownloadUtil downloadUtil;
public Builder(Context context, DownloadEntity downloadEntity) { public Builder(String targetName, DownloadTaskEntity taskEntity) {
this("", context, downloadEntity); CheckUtil.checkDownloadTaskEntity(taskEntity.downloadEntity);
}
Builder(String targetName, Context context, DownloadEntity downloadEntity) {
this.targetName = targetName; this.targetName = targetName;
this.context = context; this.taskEntity = taskEntity;
this.downloadEntity = downloadEntity;
} }
/** /**
* 设置自定义Handler处理下载状态时间 * 设置自定义Handler处理下载状态时间
* *
* @param schedulers {@link IDownloadSchedulers} * @param schedulers {@link ISchedulers}
*/ */
Builder setOutHandler(IDownloadSchedulers schedulers) { public Builder setOutHandler(ISchedulers schedulers) {
this.outHandler = new Handler(schedulers); this.outHandler = new Handler(schedulers);
return this; return this;
} }
@ -197,10 +210,10 @@ public class Task {
return this; return this;
} }
public Task build() { public DownloadTask build() {
Task task = new Task(context, downloadEntity, outHandler); DownloadTask task = new DownloadTask(taskEntity, outHandler);
task.setTargetName(targetName); task.setTargetName(targetName);
downloadEntity.save(); taskEntity.downloadEntity.save();
return task; return task;
} }
} }
@ -210,18 +223,18 @@ public class Task {
*/ */
private static class DListener extends DownloadListener { private static class DListener extends DownloadListener {
WeakReference<Handler> outHandler; WeakReference<Handler> outHandler;
WeakReference<Task> wTask; WeakReference<DownloadTask> wTask;
Context context; Context context;
Intent sendIntent; Intent sendIntent;
long INTERVAL = 1024 * 10; //10k大小的间隔 long INTERVAL = 1024 * 10; //10k大小的间隔
long lastLen = 0; //上一次发送长度 long lastLen = 0; //上一次发送长度
long lastTime = 0; long lastTime = 0;
long INTERVAL_TIME = 1000; //1m更新周期 long INTERVAL_TIME = 1000; //1m更新周期
boolean isFirst = true; boolean isFirst = true;
DownloadEntity downloadEntity; DownloadEntity downloadEntity;
Task task; DownloadTask task;
DListener(Context context, Task task, Handler outHandler) { DListener(Context context, DownloadTask task, Handler outHandler) {
this.context = context; this.context = context;
this.outHandler = new WeakReference<>(outHandler); this.outHandler = new WeakReference<>(outHandler);
this.wTask = new WeakReference<>(task); this.wTask = new WeakReference<>(task);
@ -231,6 +244,12 @@ public class Task {
sendIntent.putExtra(Aria.ENTITY, downloadEntity); sendIntent.putExtra(Aria.ENTITY, downloadEntity);
} }
@Override public void supportBreakpoint(boolean support) {
super.supportBreakpoint(support);
sendInState2Target(ISchedulers.SUPPORT_BREAK_POINT);
sendIntent(Aria.ACTION_SUPPORT_BREAK_POINT, -1);
}
@Override public void onPre() { @Override public void onPre() {
super.onPre(); super.onPre();
downloadEntity.setState(DownloadEntity.STATE_PRE); downloadEntity.setState(DownloadEntity.STATE_PRE);
@ -247,14 +266,14 @@ public class Task {
@Override public void onResume(long resumeLocation) { @Override public void onResume(long resumeLocation) {
super.onResume(resumeLocation); super.onResume(resumeLocation);
downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING); downloadEntity.setState(DownloadEntity.STATE_RUNNING);
sendInState2Target(DownloadSchedulers.RESUME); sendInState2Target(DownloadSchedulers.RESUME);
sendIntent(Aria.ACTION_RESUME, resumeLocation); sendIntent(Aria.ACTION_RESUME, resumeLocation);
} }
@Override public void onStart(long startLocation) { @Override public void onStart(long startLocation) {
super.onStart(startLocation); super.onStart(startLocation);
downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING); downloadEntity.setState(DownloadEntity.STATE_RUNNING);
sendInState2Target(DownloadSchedulers.START); sendInState2Target(DownloadSchedulers.START);
sendIntent(Aria.ACTION_START, startLocation); sendIntent(Aria.ACTION_START, startLocation);
} }
@ -328,14 +347,13 @@ public class Task {
downloadEntity.setDownloadComplete(action.equals(Aria.ACTION_COMPLETE)); downloadEntity.setDownloadComplete(action.equals(Aria.ACTION_COMPLETE));
downloadEntity.setCurrentProgress(location); downloadEntity.setCurrentProgress(location);
downloadEntity.update(); downloadEntity.update();
if (!Configuration.isOpenBreadCast) return;
Intent intent = CommonUtil.createIntent(context.getPackageName(), action); Intent intent = CommonUtil.createIntent(context.getPackageName(), action);
intent.putExtra(Aria.ENTITY, downloadEntity); intent.putExtra(Aria.ENTITY, downloadEntity);
if (location != -1) { if (location != -1) {
intent.putExtra(Aria.CURRENT_LOCATION, location); intent.putExtra(Aria.CURRENT_LOCATION, location);
} }
if (Configuration.isOpenBreadCast) { context.sendBroadcast(intent);
context.sendBroadcast(intent);
}
} }
} }
} }

@ -0,0 +1,36 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.download;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.ITaskEntity;
/**
* Created by Aria.Lao on 2017/1/23.
* 下载任务实体
*/
public class DownloadTaskEntity extends ITaskEntity {
public DownloadEntity downloadEntity;
public DownloadTaskEntity(DownloadEntity downloadEntity) {
this.downloadEntity = downloadEntity;
}
@Override public IEntity getEntity() {
return downloadEntity;
}
}

@ -14,17 +14,16 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.task; package com.arialyy.aria.core.download;
import android.content.Context; import android.content.Context;
import android.util.Log; import android.util.Log;
import android.util.SparseArray; import android.util.SparseArray;
import com.arialyy.aria.core.DownloadEntity;
import com.arialyy.aria.util.BufferedRandomAccessFile; import com.arialyy.aria.util.BufferedRandomAccessFile;
import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.util.Properties; import java.util.Properties;
@ -40,7 +39,11 @@ public class DownloadUtil implements IDownloadUtil, Runnable {
/** /**
* 线程数 * 线程数
*/ */
private final int THREAD_NUM; private int THREAD_NUM;
/**
* 小于1m的文件不启用多线程
*/
private static final long SUB_LEN = 1024 * 1024;
//下载监听 //下载监听
private IDownloadListener mListener; private IDownloadListener mListener;
private int mConnectTimeOut = 5000 * 4; //连接超时时间 private int mConnectTimeOut = 5000 * 4; //连接超时时间
@ -49,29 +52,32 @@ public class DownloadUtil implements IDownloadUtil, Runnable {
private boolean isSupportBreakpoint = true; private boolean isSupportBreakpoint = true;
private Context mContext; private Context mContext;
private DownloadEntity mDownloadEntity; private DownloadEntity mDownloadEntity;
private DownloadTaskEntity mDownloadTaskEntity;
private ExecutorService mFixedThreadPool; private ExecutorService mFixedThreadPool;
private File mDownloadFile; //下载的文件 private File mDownloadFile; //下载的文件
private File mConfigFile;//下载信息配置文件 private File mConfigFile;//下载信息配置文件
private SparseArray<Runnable> mTask = new SparseArray<>(); private SparseArray<Runnable> mTask = new SparseArray<>();
private DownloadStateConstance mConstance; private DownloadStateConstance mConstance;
public DownloadUtil(Context context, DownloadEntity entity, IDownloadListener downloadListener) { DownloadUtil(Context context, DownloadTaskEntity entity, IDownloadListener downloadListener) {
this(context, entity, downloadListener, 3); this(context, entity, downloadListener, 3);
} }
DownloadUtil(Context context, DownloadEntity entity, IDownloadListener downloadListener, DownloadUtil(Context context, DownloadTaskEntity entity, IDownloadListener downloadListener,
int threadNum) { int threadNum) {
CheckUtil.checkDownloadTaskEntity(entity.downloadEntity);
mDownloadEntity = entity.downloadEntity;
mContext = context.getApplicationContext(); mContext = context.getApplicationContext();
mDownloadEntity = entity; mDownloadTaskEntity = entity;
mListener = downloadListener; mListener = downloadListener;
THREAD_NUM = threadNum; THREAD_NUM = threadNum;
mFixedThreadPool = Executors.newFixedThreadPool(Integer.MAX_VALUE); mFixedThreadPool = Executors.newFixedThreadPool(Integer.MAX_VALUE);
mConstance = new DownloadStateConstance(THREAD_NUM); mConstance = new DownloadStateConstance();
init(); init();
} }
private void init() { private void init() {
mDownloadFile = new File(mDownloadEntity.getDownloadPath()); mDownloadFile = new File(mDownloadTaskEntity.downloadEntity.getDownloadPath());
//读取已完成的线程数 //读取已完成的线程数
mConfigFile = new File( mConfigFile = new File(
mContext.getFilesDir().getPath() + "/temp/" + mDownloadFile.getName() + ".properties"); mContext.getFilesDir().getPath() + "/temp/" + mDownloadFile.getName() + ".properties");
@ -197,7 +203,7 @@ public class DownloadUtil implements IDownloadUtil, Runnable {
try { try {
URL url = new URL(mDownloadEntity.getDownloadUrl()); URL url = new URL(mDownloadEntity.getDownloadUrl());
HttpURLConnection conn = ConnectionHelp.handleConnection(url); HttpURLConnection conn = ConnectionHelp.handleConnection(url);
conn = ConnectionHelp.setConnectParam(conn); conn = ConnectionHelp.setConnectParam(mDownloadTaskEntity, conn);
conn.setRequestProperty("Range", "bytes=" + 0 + "-"); conn.setRequestProperty("Range", "bytes=" + 0 + "-");
conn.setConnectTimeout(mConnectTimeOut * 4); conn.setConnectTimeout(mConnectTimeOut * 4);
conn.connect(); conn.connect();
@ -225,7 +231,7 @@ public class DownloadUtil implements IDownloadUtil, Runnable {
handleBreakpoint(conn); handleBreakpoint(conn);
} else if (code == HttpURLConnection.HTTP_NOT_FOUND) { } else if (code == HttpURLConnection.HTTP_NOT_FOUND) {
Log.w(TAG, "任务【" + mDownloadEntity.getDownloadUrl() + "】下载失败,错误码:404"); Log.w(TAG, "任务【" + mDownloadEntity.getDownloadUrl() + "】下载失败,错误码:404");
//mListener.onCancel(); mListener.onCancel();
} else { } else {
failDownload("任务【" + mDownloadEntity.getDownloadUrl() + "】下载失败,错误码:" + code); failDownload("任务【" + mDownloadEntity.getDownloadUrl() + "】下载失败,错误码:" + code);
} }
@ -243,53 +249,17 @@ public class DownloadUtil implements IDownloadUtil, Runnable {
* 处理断点 * 处理断点
*/ */
private void handleBreakpoint(HttpURLConnection conn) throws IOException { private void handleBreakpoint(HttpURLConnection conn) throws IOException {
//不支持断点只能单线程下载 //不支持断点只能单线程下载
if (!isSupportBreakpoint) { if (!isSupportBreakpoint) {
ConfigEntity entity = new ConfigEntity(); handleNoSupportBreakpointDownload(conn);
long len = conn.getContentLength();;
entity.FILE_SIZE = len;
entity.DOWNLOAD_URL = mDownloadEntity.getDownloadUrl();
entity.TEMP_FILE = mDownloadFile;
entity.THREAD_ID = 0;
entity.START_LOCATION = 0;
entity.END_LOCATION = entity.FILE_SIZE;
entity.CONFIG_FILE_PATH = mConfigFile.getPath();
entity.isSupportBreakpoint = isSupportBreakpoint;
SingleThreadTask task = new SingleThreadTask(mConstance, mListener, entity);
mFixedThreadPool.execute(task);
mListener.onPostPre(len);
mListener.onStart(0);
return; return;
} }
int fileLength = conn.getContentLength(); int fileLength = conn.getContentLength();
//必须建一个文件 if (fileLength < SUB_LEN) {
CommonUtil.createFile(mDownloadFile.getPath()); THREAD_NUM = 1;
//RandomAccessFile file = new RandomAccessFile(mDownloadFile.getPath(), "rwd"); mConstance.THREAD_NUM = THREAD_NUM;
////设置文件长度
//file.setLength(fileLength);
BufferedRandomAccessFile file =
new BufferedRandomAccessFile(mDownloadFile.getPath(), "rwd", 8192);
//设置文件长度
file.setLength(fileLength);
mListener.onPostPre(fileLength);
//分配每条线程的下载区间
Properties pro = null;
pro = CommonUtil.loadConfig(mConfigFile);
if (pro.isEmpty()) {
isNewTask = true;
} else {
for (int i = 0; i < THREAD_NUM; i++) {
if (pro.getProperty(mDownloadFile.getName() + "_record_" + i) == null) {
Object state = pro.getProperty(mDownloadFile.getName() + "_state_" + i);
if (state != null && Integer.parseInt(state + "") == 1) {
continue;
}
isNewTask = true;
break;
}
}
} }
Properties pro = createConfigFile(fileLength);
int blockSize = fileLength / THREAD_NUM; int blockSize = fileLength / THREAD_NUM;
int[] recordL = new int[THREAD_NUM]; int[] recordL = new int[THREAD_NUM];
int rl = 0; int rl = 0;
@ -300,19 +270,7 @@ public class DownloadUtil implements IDownloadUtil, Runnable {
long startL = i * blockSize, endL = (i + 1) * blockSize; long startL = i * blockSize, endL = (i + 1) * blockSize;
Object state = pro.getProperty(mDownloadFile.getName() + "_state_" + i); Object state = pro.getProperty(mDownloadFile.getName() + "_state_" + i);
if (state != null && Integer.parseInt(state + "") == 1) { //该线程已经完成 if (state != null && Integer.parseInt(state + "") == 1) { //该线程已经完成
mConstance.CURRENT_LOCATION += endL - startL; if (resumeRecordLocation(i, startL, endL)) return;
Log.d(TAG, "++++++++++ 线程_" + i + "_已经下载完成 ++++++++++");
mConstance.COMPLETE_THREAD_NUM++;
mConstance.STOP_NUM++;
mConstance.CANCEL_NUM++;
if (mConstance.isComplete()) {
if (mConfigFile.exists()) {
mConfigFile.delete();
}
mListener.onComplete();
mConstance.isDownloading = false;
return;
}
continue; continue;
} }
//分配下载位置 //分配下载位置
@ -337,18 +295,110 @@ public class DownloadUtil implements IDownloadUtil, Runnable {
//如果整个文件的大小不为线程个数的整数倍,则最后一个线程的结束位置即为文件的总长度 //如果整个文件的大小不为线程个数的整数倍,则最后一个线程的结束位置即为文件的总长度
endL = fileLength; endL = fileLength;
} }
ConfigEntity entity = new ConfigEntity(); addSingleTask(i, startL, endL, fileLength);
entity.FILE_SIZE = fileLength;
entity.DOWNLOAD_URL = mDownloadEntity.getDownloadUrl();
entity.TEMP_FILE = mDownloadFile;
entity.THREAD_ID = i;
entity.START_LOCATION = startL;
entity.END_LOCATION = endL;
entity.CONFIG_FILE_PATH = mConfigFile.getPath();
entity.isSupportBreakpoint = isSupportBreakpoint;
SingleThreadTask task = new SingleThreadTask(mConstance, mListener, entity);
mTask.put(i, task);
} }
startSingleTask(recordL);
}
/**
* 处理不支持断点的下载
*/
private void handleNoSupportBreakpointDownload(HttpURLConnection conn) {
ConfigEntity entity = new ConfigEntity();
long len = conn.getContentLength();
entity.FILE_SIZE = len;
entity.DOWNLOAD_URL = mDownloadEntity.getDownloadUrl();
entity.TEMP_FILE = mDownloadFile;
entity.THREAD_ID = 0;
entity.START_LOCATION = 0;
entity.END_LOCATION = entity.FILE_SIZE;
entity.CONFIG_FILE_PATH = mConfigFile.getPath();
entity.isSupportBreakpoint = isSupportBreakpoint;
entity.DOWNLOAD_TASK_ENTITY = mDownloadTaskEntity;
THREAD_NUM = 1;
mConstance.THREAD_NUM = THREAD_NUM;
SingleThreadTask task = new SingleThreadTask(mConstance, mListener, entity);
mTask.put(0, task);
mFixedThreadPool.execute(task);
mListener.onPostPre(len);
mListener.onStart(0);
}
/**
* 创建配置文件
*/
private Properties createConfigFile(long fileLength) throws IOException {
Properties pro = null;
//必须建一个文件
CommonUtil.createFile(mDownloadFile.getPath());
BufferedRandomAccessFile file =
new BufferedRandomAccessFile(new File(mDownloadFile.getPath()), "rwd", 8192);
//设置文件长度
file.setLength(fileLength);
mListener.onPostPre(fileLength);
//分配每条线程的下载区间
pro = CommonUtil.loadConfig(mConfigFile);
if (pro.isEmpty()) {
isNewTask = true;
} else {
for (int i = 0; i < THREAD_NUM; i++) {
if (pro.getProperty(mDownloadFile.getName() + "_record_" + i) == null) {
Object state = pro.getProperty(mDownloadFile.getName() + "_state_" + i);
if (state != null && Integer.parseInt(state + "") == 1) {
continue;
}
isNewTask = true;
break;
}
}
}
return pro;
}
/**
* 恢复记录地址
*
* @return true 表示下载完成
*/
private boolean resumeRecordLocation(int i, long startL, long endL) {
mConstance.CURRENT_LOCATION += endL - startL;
Log.d(TAG, "++++++++++ 线程_" + i + "_已经下载完成 ++++++++++");
mConstance.COMPLETE_THREAD_NUM++;
mConstance.STOP_NUM++;
mConstance.CANCEL_NUM++;
if (mConstance.isComplete()) {
if (mConfigFile.exists()) {
mConfigFile.delete();
}
mListener.onComplete();
mConstance.isDownloading = false;
return true;
}
return false;
}
/**
* 创建单线程任务
*/
private void addSingleTask(int i, long startL, long endL, long fileLength) {
ConfigEntity entity = new ConfigEntity();
entity.FILE_SIZE = fileLength;
entity.DOWNLOAD_URL = mDownloadEntity.getDownloadUrl();
entity.TEMP_FILE = mDownloadFile;
entity.THREAD_ID = i;
entity.START_LOCATION = startL;
entity.END_LOCATION = endL;
entity.CONFIG_FILE_PATH = mConfigFile.getPath();
entity.isSupportBreakpoint = isSupportBreakpoint;
entity.DOWNLOAD_TASK_ENTITY = mDownloadTaskEntity;
SingleThreadTask task = new SingleThreadTask(mConstance, mListener, entity);
mTask.put(i, task);
}
/**
* 启动单线程下载任务
*/
private void startSingleTask(int[] recordL) {
if (mConstance.CURRENT_LOCATION > 0) { if (mConstance.CURRENT_LOCATION > 0) {
mListener.onResume(mConstance.CURRENT_LOCATION); mListener.onResume(mConstance.CURRENT_LOCATION);
} else { } else {
@ -368,13 +418,14 @@ public class DownloadUtil implements IDownloadUtil, Runnable {
*/ */
final static class ConfigEntity { final static class ConfigEntity {
//文件大小 //文件大小
long FILE_SIZE;
String DOWNLOAD_URL;
int THREAD_ID; int THREAD_ID;
long FILE_SIZE;
long START_LOCATION; long START_LOCATION;
long END_LOCATION; long END_LOCATION;
File TEMP_FILE; File TEMP_FILE;
boolean isSupportBreakpoint = true; String DOWNLOAD_URL;
String CONFIG_FILE_PATH; String CONFIG_FILE_PATH;
DownloadTaskEntity DOWNLOAD_TASK_ENTITY;
boolean isSupportBreakpoint = true;
} }
} }

@ -14,12 +14,12 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.task; package com.arialyy.aria.core.download;
/** /**
* 下载监听 * 下载监听
*/ */
public interface IDownloadListener { interface IDownloadListener {
/** /**
* 支持断点回调 * 支持断点回调

@ -14,14 +14,13 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.download;
package com.arialyy.aria.core.task;
/** /**
* Created by AriaLyy@outlook.com on 2016/10/31. * Created by AriaLyy@outlook.com on 2016/10/31.
* 抽象的下载接口 * 抽象的下载接口
*/ */
public interface IDownloadUtil { interface IDownloadUtil {
/** /**
* 获取当前下载位置 * 获取当前下载位置

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.task; package com.arialyy.aria.core.download;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
@ -21,10 +21,10 @@ import android.os.Message;
import android.util.Log; import android.util.Log;
import com.arialyy.aria.util.BufferedRandomAccessFile; import com.arialyy.aria.util.BufferedRandomAccessFile;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.Configuration;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
@ -39,10 +39,12 @@ final class SingleThreadTask implements Runnable {
// TODO: 2017/2/22 不能使用1024 否则最大速度不能超过3m // TODO: 2017/2/22 不能使用1024 否则最大速度不能超过3m
private static final int BUF_SIZE = 8192; private static final int BUF_SIZE = 8192;
private DownloadUtil.ConfigEntity mConfigEntity; private DownloadUtil.ConfigEntity mConfigEntity;
private String mConfigFPath; private String mConfigFPath;
private long mChildCurrentLocation = 0; private long mChildCurrentLocation = 0;
private static final Object LOCK = new Object(); private static final Object LOCK = new Object();
private IDownloadListener mListener; private int mBufSize = 8192;
//private int mBufSize = 64;
private IDownloadListener mListener;
private DownloadStateConstance mConstance; private DownloadStateConstance mConstance;
SingleThreadTask(DownloadStateConstance constance, IDownloadListener listener, SingleThreadTask(DownloadStateConstance constance, IDownloadListener listener,
@ -53,6 +55,7 @@ final class SingleThreadTask implements Runnable {
if (mConfigEntity.isSupportBreakpoint) { if (mConfigEntity.isSupportBreakpoint) {
mConfigFPath = downloadInfo.CONFIG_FILE_PATH; mConfigFPath = downloadInfo.CONFIG_FILE_PATH;
} }
//mBufSize = Configuration.getInstance().getMaxSpeed();
} }
@Override public void run() { @Override public void run() {
@ -74,19 +77,18 @@ final class SingleThreadTask implements Runnable {
conn.setRequestProperty("Range", conn.setRequestProperty("Range",
"bytes=" + mConfigEntity.START_LOCATION + "-" + mConfigEntity.END_LOCATION); "bytes=" + mConfigEntity.START_LOCATION + "-" + mConfigEntity.END_LOCATION);
} else { } else {
Log.w(TAG, "该下载不支持断点,即将重新下载"); Log.w(TAG, "该下载不支持断点");
} }
conn = ConnectionHelp.setConnectParam(conn); conn = ConnectionHelp.setConnectParam(mConfigEntity.DOWNLOAD_TASK_ENTITY, conn);
conn.setConnectTimeout(mConstance.CONNECT_TIME_OUT); conn.setConnectTimeout(mConstance.CONNECT_TIME_OUT);
conn.setReadTimeout(mConstance.READ_TIME_OUT); //设置读取流的等待时间,必须设置该参数 conn.setReadTimeout(mConstance.READ_TIME_OUT); //设置读取流的等待时间,必须设置该参数
is = conn.getInputStream(); is = conn.getInputStream();
//创建可设置位置的文件 //创建可设置位置的文件
BufferedRandomAccessFile file = BufferedRandomAccessFile file =
new BufferedRandomAccessFile(mConfigEntity.TEMP_FILE, "rwd", BUF_SIZE); new BufferedRandomAccessFile(mConfigEntity.TEMP_FILE, "rwd", mBufSize);
//设置文件长度 //设置每条线程写入文件的位置
file.seek(mConfigEntity.START_LOCATION); file.seek(mConfigEntity.START_LOCATION);
byte[] buffer = new byte[mBufSize];
byte[] buffer = new byte[BUF_SIZE];
int len; int len;
//当前子线程的下载位置 //当前子线程的下载位置
mChildCurrentLocation = mConfigEntity.START_LOCATION; mChildCurrentLocation = mConfigEntity.START_LOCATION;
@ -95,7 +97,6 @@ final class SingleThreadTask implements Runnable {
break; break;
} }
if (mConstance.isStop) { if (mConstance.isStop) {
Log.i(TAG, "stop");
break; break;
} }
//把下载数据数据写入文件 //把下载数据数据写入文件

@ -0,0 +1,173 @@
/*
* 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.inf;
import android.support.annotation.NonNull;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.RequestEnum;
import com.arialyy.aria.core.command.AbsCmd;
import com.arialyy.aria.core.command.CmdFactory;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.CommonUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Created by Aria.Lao on 2017/2/28.
*/
public class AbsTarget<ENTITY extends IEntity, TASK_ENTITY extends ITaskEntity> {
protected ENTITY entity;
protected TASK_ENTITY taskEntity;
protected String targetName;
/**
* 获取任务文件大小
*
* @return -1没有找到该任务
*/
public long getFileSize() {
if (entity instanceof DownloadEntity) {
DownloadEntity entity = DbEntity.findData(DownloadEntity.class, "downloadUrl=?",
((DownloadEntity) this.entity).getDownloadUrl());
if (entity == null) {
throw new NullPointerException("没有找到该任务");
}
return entity.getFileSize();
} else if (entity instanceof UploadEntity) {
UploadEntity entity = DbEntity.findData(UploadEntity.class, "filePath=?",
((UploadEntity) this.entity).getFilePath());
if (entity == null) {
throw new NullPointerException("没有找到该任务");
}
return entity.getFileSize();
}
return -1;
}
/**
* 获取当前任务进度如果任务存在则返回当前进度
*
* @return -1没有找到该任务
*/
public long getCurrentProgress() {
if (entity instanceof DownloadEntity) {
DownloadEntity entity = DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?",
((DownloadEntity) this.entity).getDownloadUrl());
if (entity == null) {
throw new NullPointerException("下载管理器中没有该任务");
}
return entity.getCurrentProgress();
} else if (entity instanceof UploadEntity) {
UploadEntity entity = DbEntity.findData(UploadEntity.class, "filePath=?",
((UploadEntity) this.entity).getFilePath());
if (entity == null) {
throw new NullPointerException("没有找到该任务");
}
return entity.getCurrentProgress();
}
return -1;
}
/**
* 给url请求添加头部
*
* @param key 头部key
* @param header 头部value
*/
protected void _addHeader(@NonNull String key, @NonNull String header) {
taskEntity.headers.put(key, header);
}
/**
* 给url请求添加头部
*/
protected void _addHeaders(Map<String, String> headers) {
if (headers != null && headers.size() > 0) {
Set<String> keys = headers.keySet();
for (String key : keys) {
taskEntity.headers.put(key, headers.get(key));
}
}
}
/**
* 设置请求类型
*
* @param requestEnum {@link RequestEnum}
*/
protected void _setRequestMode(RequestEnum requestEnum) {
taskEntity.requestEnum = requestEnum;
}
/**
* 添加任务
*/
public void add() {
AriaManager.getInstance(AriaManager.APP)
.setCmd(CommonUtil.createCmd(targetName, taskEntity, CmdFactory.TASK_CREATE))
.exe();
}
/**
* 开始下载
*/
public void start() {
List<AbsCmd> cmds = new ArrayList<>();
cmds.add(CommonUtil.createCmd(targetName, taskEntity, CmdFactory.TASK_CREATE));
cmds.add(CommonUtil.createCmd(targetName, taskEntity, CmdFactory.TASK_START));
AriaManager.getInstance(AriaManager.APP).setCmds(cmds).exe();
cmds.clear();
}
/**
* 停止下载
*/
protected void pause() {
AriaManager.getInstance(AriaManager.APP)
.setCmd(CommonUtil.createCmd(targetName, taskEntity, CmdFactory.TASK_STOP))
.exe();
}
/**
* 恢复下载
*/
protected void resume() {
AriaManager.getInstance(AriaManager.APP)
.setCmd(CommonUtil.createCmd(targetName, taskEntity, CmdFactory.TASK_START))
.exe();
}
/**
* 取消下载
*/
public void cancel() {
AriaManager.getInstance(AriaManager.APP)
.setCmd(CommonUtil.createCmd(targetName, taskEntity, CmdFactory.TASK_CANCEL))
.exe();
}
/**
* 重新下载
*/
void reStart() {
cancel();
start();
}
}

@ -0,0 +1,27 @@
/*
* 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.inf;
/**
* Created by Aria.Lao on 2017/2/9.
*/
public interface ICmd {
/**
* 执行命令
*/
public abstract void executeCmd();
}

@ -0,0 +1,63 @@
/*
* 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.inf;
import com.arialyy.aria.orm.Ignore;
/**
* Created by Aria.Lao on 2017/2/23.
*/
public interface IEntity {
/**
* 其它状态
*/
@Ignore public static final int STATE_OTHER = -1;
/**
* 失败状态
*/
@Ignore public static final int STATE_FAIL = 0;
/**
* 完成状态
*/
@Ignore public static final int STATE_COMPLETE = 1;
/**
* 停止状态
*/
@Ignore public static final int STATE_STOP = 2;
/**
* 未开始状态
*/
@Ignore public static final int STATE_WAIT = 3;
/**
* 下载中
*/
@Ignore public static final int STATE_RUNNING = 4;
/**
* 预处理
*/
@Ignore public static final int STATE_PRE = 5;
/**
* 预处理完成
*/
@Ignore public static final int STATE_POST_PRE = 6;
/**
* 取消下载
*/
@Ignore public static final int STATE_CANCEL = 7;
public int getState();
}

@ -0,0 +1,55 @@
/*
* 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.inf;
import java.util.List;
/**
* Created by Aria.Lao on 2017/2/6.
*/
public interface IReceiver<ENTITY extends IEntity> {
/**
* Receiver 销毁
*/
public void destroy();
/**
* 移除事件回调
*/
public void removeSchedulerListener();
/**
* 停止所有任务
*/
public void stopAllTask();
/**
* 删除所有任务
*/
public void removeAllTask();
/**
* 任务是否存在
*
* @param key 下载时为下载路径上传时为文件路径
*/
public boolean taskExists(String key);
/**
* 获取任务列表
*/
public List<ENTITY> getTaskList();
}

@ -0,0 +1,54 @@
/*
* 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.inf;
/**
* Created by Aria.Lao on 2017/2/13.
*/
public interface ITask {
/**
* 唯一标识符DownloadTask 为下载地址UploadTask 为文件路径
*/
public String getKey();
/**
* 是否真正执行
*
* @return true正在执行
*/
public boolean isRunning();
/**
* 获取工具实体
*/
public IEntity getEntity();
public void start();
public void stop();
public void cancel();
public long getSpeed();
public long getFileSize();
public long getCurrentProgress();
public void setTargetName(String targetName);
}

@ -0,0 +1,38 @@
/*
* 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.inf;
import com.arialyy.aria.core.RequestEnum;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Aria.Lao on 2017/2/23.
*/
public abstract class ITaskEntity {
/**
* http 请求头
*/
public Map<String, String> headers = new HashMap<>();
/**
* 网络请求类型
*/
public RequestEnum requestEnum = RequestEnum.GET;
public abstract IEntity getEntity();
}

@ -14,41 +14,19 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.queue; package com.arialyy.aria.core.queue;
import com.arialyy.aria.core.task.Task; import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.ITask;
import com.arialyy.aria.core.inf.ITaskEntity;
import com.arialyy.aria.core.queue.pool.CachePool;
import com.arialyy.aria.core.queue.pool.ExecutePool;
/** /**
* Created by lyy on 2016/8/16. * Created by Aria.Lao on 2017/2/23.
* 下载功能接口
*/ */
public interface IDownloader { abstract class AbsTaskQueue<TASK extends ITask, TASK_ENTITY extends ITaskEntity, ENTITY extends IEntity>
/** implements ITaskQueue<TASK, TASK_ENTITY, ENTITY> {
* 开始任务 CachePool<TASK> mCachePool = new CachePool<>();
* ExecutePool<TASK> mExecutePool = new ExecutePool<>();
* @param task {@link Task}
*/
public void startTask(Task task);
/**
* 停止任务
*
* @param task {@link Task}
*/
public void stopTask(Task task);
/**
* 取消任务
*
* @param task {@link Task}
*/
public void cancelTask(Task task);
/**
* 重试下载
*
* @param task {@link Task}
*/
public void reTryStart(Task task);
} }

@ -16,35 +16,37 @@
package com.arialyy.aria.core.queue; package com.arialyy.aria.core.queue;
import android.content.Context;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.arialyy.aria.core.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.core.download.DownloadTaskEntity;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.queue.pool.CachePool; import com.arialyy.aria.core.queue.pool.CachePool;
import com.arialyy.aria.core.queue.pool.ExecutePool; import com.arialyy.aria.core.queue.pool.ExecutePool;
import com.arialyy.aria.core.scheduler.DownloadSchedulers; import com.arialyy.aria.core.scheduler.DownloadSchedulers;
import com.arialyy.aria.core.scheduler.IDownloadSchedulers;
import com.arialyy.aria.core.task.Task;
import com.arialyy.aria.core.task.TaskFactory;
import com.arialyy.aria.util.Configuration; import com.arialyy.aria.util.Configuration;
/** /**
* Created by lyy on 2016/8/17. * Created by lyy on 2016/8/17.
* 下载任务队列 * 下载任务队列
*/ */
public class DownloadTaskQueue implements ITaskQueue { public class DownloadTaskQueue
private static final String TAG = "DownloadTaskQueue"; extends AbsTaskQueue<DownloadTask, DownloadTaskEntity, DownloadEntity> {
private CachePool mCachePool = CachePool.getInstance(); private static final String TAG = "DownloadTaskQueue";
private ExecutePool mExecutePool = ExecutePool.getInstance(); private static volatile DownloadTaskQueue INSTANCE = null;
private Context mContext; private static final Object LOCK = new Object();
//private IDownloadSchedulers mSchedulers;
public static DownloadTaskQueue getInstance() {
private DownloadTaskQueue() { if (INSTANCE == null) {
synchronized (LOCK) {
INSTANCE = new DownloadTaskQueue();
}
}
return INSTANCE;
} }
private DownloadTaskQueue(Context context) { private DownloadTaskQueue() {
super();
mContext = context;
} }
/** /**
@ -79,7 +81,7 @@ public class DownloadTaskQueue implements ITaskQueue {
return mCachePool.size(); return mCachePool.size();
} }
@Override public void startTask(Task task) { @Override public void startTask(DownloadTask task) {
if (mExecutePool.putTask(task)) { if (mExecutePool.putTask(task)) {
mCachePool.removeTask(task); mCachePool.removeTask(task);
task.getDownloadEntity().setFailNum(0); task.getDownloadEntity().setFailNum(0);
@ -87,8 +89,8 @@ public class DownloadTaskQueue implements ITaskQueue {
} }
} }
@Override public void stopTask(Task task) { @Override public void stopTask(DownloadTask task) {
if (!task.isDownloading()) Log.w(TAG, "停止任务失败,【任务已经停止】"); if (!task.isRunning()) Log.w(TAG, "停止任务失败,【任务已经停止】");
if (mExecutePool.removeTask(task)) { if (mExecutePool.removeTask(task)) {
task.stop(); task.stop();
} else { } else {
@ -97,16 +99,16 @@ public class DownloadTaskQueue implements ITaskQueue {
} }
} }
@Override public void cancelTask(Task task) { @Override public void cancelTask(DownloadTask task) {
task.cancel(); task.cancel();
} }
@Override public void reTryStart(Task task) { @Override public void reTryStart(DownloadTask task) {
if (task == null) { if (task == null) {
Log.w(TAG, "重试下载失败,task 为null"); Log.w(TAG, "重试下载失败,task 为null");
return; return;
} }
if (!task.isDownloading()) { if (!task.isRunning()) {
task.start(); task.start();
} else { } else {
Log.w(TAG, "任务没有完全停止,重试下载失败"); Log.w(TAG, "任务没有完全停止,重试下载失败");
@ -128,7 +130,7 @@ public class DownloadTaskQueue implements ITaskQueue {
//设置的任务数小于配置任务数 //设置的任务数小于配置任务数
if (diff <= -1 && mExecutePool.size() >= size) { if (diff <= -1 && mExecutePool.size() >= size) {
for (int i = 0, len = Math.abs(diff); i < len; i++) { for (int i = 0, len = Math.abs(diff); i < len; i++) {
Task eTask = mExecutePool.pollTask(); DownloadTask eTask = mExecutePool.pollTask();
if (eTask != null) { if (eTask != null) {
stopTask(eTask); stopTask(eTask);
} }
@ -137,30 +139,28 @@ public class DownloadTaskQueue implements ITaskQueue {
mExecutePool.setDownloadNum(downloadNum); mExecutePool.setDownloadNum(downloadNum);
if (diff >= 1) { if (diff >= 1) {
for (int i = 0; i < diff; i++) { for (int i = 0; i < diff; i++) {
Task nextTask = getNextTask(); DownloadTask nextTask = getNextTask();
if (nextTask != null if (nextTask != null && nextTask.getDownloadEntity().getState() == IEntity.STATE_WAIT) {
&& nextTask.getDownloadEntity().getState() == DownloadEntity.STATE_WAIT) {
startTask(nextTask); startTask(nextTask);
} }
} }
} }
} }
@Override public Task createTask(String target, DownloadEntity entity) { @Override public DownloadTask createTask(String target, DownloadTaskEntity entity) {
Task task; DownloadTask task = null;
if (TextUtils.isEmpty(target)) { if (!TextUtils.isEmpty(target)) {
task = task = (DownloadTask) TaskFactory.getInstance()
TaskFactory.getInstance().createTask(mContext, entity, DownloadSchedulers.getInstance()); .createTask(target, entity, DownloadSchedulers.getInstance());
mCachePool.putTask(task);
} else { } else {
task = TaskFactory.getInstance() Log.e(TAG, "target name 为 null是!!");
.createTask(target, mContext, entity, DownloadSchedulers.getInstance());
} }
mCachePool.putTask(task);
return task; return task;
} }
@Override public Task getTask(DownloadEntity entity) { @Override public DownloadTask getTask(DownloadEntity entity) {
Task task = mExecutePool.getTask(entity.getDownloadUrl()); DownloadTask task = mExecutePool.getTask(entity.getDownloadUrl());
if (task == null) { if (task == null) {
task = mCachePool.getTask(entity.getDownloadUrl()); task = mCachePool.getTask(entity.getDownloadUrl());
} }
@ -168,7 +168,7 @@ public class DownloadTaskQueue implements ITaskQueue {
} }
@Override public void removeTask(DownloadEntity entity) { @Override public void removeTask(DownloadEntity entity) {
Task task = mExecutePool.getTask(entity.getDownloadUrl()); DownloadTask task = mExecutePool.getTask(entity.getDownloadUrl());
if (task != null) { if (task != null) {
Log.d(TAG, "从执行池删除任务,删除" + (mExecutePool.removeTask(task) ? "成功" : "失败")); Log.d(TAG, "从执行池删除任务,删除" + (mExecutePool.removeTask(task) ? "成功" : "失败"));
} }
@ -178,20 +178,7 @@ public class DownloadTaskQueue implements ITaskQueue {
} }
} }
@Override public Task getNextTask() { @Override public DownloadTask getNextTask() {
return mCachePool.pollTask(); return mCachePool.pollTask();
} }
public static class Builder {
Context context;
public Builder(Context context) {
this.context = context.getApplicationContext();
}
public DownloadTaskQueue build() {
DownloadTaskQueue queue = new DownloadTaskQueue(context);
return queue;
}
}
} }

@ -16,20 +16,49 @@
package com.arialyy.aria.core.queue; package com.arialyy.aria.core.queue;
import com.arialyy.aria.core.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.scheduler.IDownloadSchedulers; import com.arialyy.aria.core.download.DownloadTaskEntity;
import com.arialyy.aria.core.task.Task; import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.ITask;
import com.arialyy.aria.core.inf.ITaskEntity;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.upload.UploadTask;
import com.arialyy.aria.core.upload.UploadTaskEntity;
/** /**
* Created by lyy on 2016/8/16. * Created by lyy on 2016/8/16.
* 任务功能接口 * 任务功能接口
*/ */
public interface ITaskQueue extends IDownloader { public interface ITaskQueue<TASK extends ITask, TASK_ENTITY extends ITaskEntity, ENTITY extends IEntity> {
///** /**
// * 获取调度器 * 开始任务
// */ *
//public IDownloadSchedulers getDownloadSchedulers(); * @param task {@link DownloadTask}{@link UploadTask}
*/
public void startTask(TASK task);
/**
* 停止任务
*
* @param task {@link DownloadTask}{@link UploadTask}
*/
public void stopTask(TASK task);
/**
* 取消任务
*
* @param task {@link DownloadTask}{@link UploadTask}
*/
public void cancelTask(TASK task);
/**
* 重试下载
*
* @param task {@link DownloadTask}{@link UploadTask}
*/
public void reTryStart(TASK task);
/** /**
* 任务池队列大小 * 任务池队列大小
@ -44,33 +73,33 @@ public interface ITaskQueue extends IDownloader {
public void setDownloadNum(int downloadNum); public void setDownloadNum(int downloadNum);
/** /**
* 创建一个新的下载任务创建时只是将新任务存储到缓存池 * 创建一个新的任务创建时只是将新任务存储到缓存池
* *
* @param entity 下载实体{@link DownloadEntity} * @param entity 任务实体{@link DownloadTaskEntity}{@link UploadTaskEntity}
* @param targetName 生成该任务的对象 * @param targetName 生成该任务的对象
* @return {@link Task} * @return {@link DownloadTask}{@link UploadTask}
*/ */
public Task createTask(String targetName, DownloadEntity entity); public TASK createTask(String targetName, TASK_ENTITY entity);
/** /**
* 通过下载链接从缓存池或任务池搜索下载任务如果缓存池或任务池都没有任务则创建新任务 * 通过工作实体缓存池或任务池搜索下载任务如果缓存池或任务池都没有任务则创建新任务
* *
* @param entity 下载实体{@link DownloadEntity} * @param entity 工作实体{@link DownloadEntity}{@link UploadEntity}
* @return {@link Task} * @return {@link DownloadTask}{@link UploadTask}
*/ */
public Task getTask(DownloadEntity entity); public TASK getTask(ENTITY entity);
/** /**
* 通过下载链接删除任务 * 通过工作实体删除任务
* *
* @param entity 下载实体{@link DownloadEntity} * @param entity 工作实体{@link DownloadEntity}{@link UploadEntity}
*/ */
public void removeTask(DownloadEntity entity); public void removeTask(ENTITY entity);
/** /**
* 获取缓存池的下一个任务 * 获取缓存池的下一个任务
* *
* @return 下载任务 or null * @return 下载任务 or null
*/ */
public Task getNextTask(); public TASK getNextTask();
} }

@ -0,0 +1,93 @@
/*
* 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;
import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.core.download.DownloadTaskEntity;
import com.arialyy.aria.core.inf.ITask;
import com.arialyy.aria.core.inf.ITaskEntity;
import com.arialyy.aria.core.scheduler.DownloadSchedulers;
import com.arialyy.aria.core.scheduler.ISchedulers;
import com.arialyy.aria.core.upload.UploadTask;
import com.arialyy.aria.core.upload.UploadTaskEntity;
/**
* Created by lyy on 2016/8/18.
* 任务工厂
*/
public class TaskFactory {
private static final String TAG = "TaskFactory";
private static final Object LOCK = new Object();
private static volatile TaskFactory INSTANCE = null;
private TaskFactory() {
}
public static TaskFactory getInstance() {
if (INSTANCE == null) {
synchronized (LOCK) {
INSTANCE = new TaskFactory();
}
}
return INSTANCE;
}
/**
* 创建任务
*
* @param entity 下载实体
* @param schedulers 对应的任务调度器
* @param <ENTITY> {@link DownloadTaskEntity}{@link UploadTaskEntity}
* @param <SCHEDULER> {@link DownloadSchedulers}
* @return {@link DownloadTask}{@link UploadTask}
*/
<ENTITY extends ITaskEntity, SCHEDULER extends ISchedulers> ITask createTask(String targetName,
ENTITY entity, SCHEDULER schedulers) {
if (entity instanceof DownloadTaskEntity) {
return createDownloadTask(targetName, (DownloadTaskEntity) entity, schedulers);
} else if (entity instanceof UploadTaskEntity) {
return createUploadTask(targetName, (UploadTaskEntity) entity, schedulers);
}
return null;
}
/**
* @param entity 上传任务实体{@link UploadTaskEntity}
* @param schedulers {@link ISchedulers}
*/
private UploadTask createUploadTask(String targetName, UploadTaskEntity entity,
ISchedulers schedulers) {
UploadTask.Builder builder = new UploadTask.Builder();
builder.setTargetName(targetName);
builder.setUploadTaskEntity(entity);
builder.setOutHandler(schedulers);
return builder.build();
}
/**
* @param entity 下载任务实体{@link DownloadTaskEntity}
* @param schedulers {@link ISchedulers}
*/
private DownloadTask createDownloadTask(String targetName, DownloadTaskEntity entity,
ISchedulers schedulers) {
DownloadTask.Builder builder = new DownloadTask.Builder(targetName, entity);
builder.setOutHandler(schedulers);
return builder.build();
}
}

@ -0,0 +1,120 @@
/*
* 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;
import android.text.TextUtils;
import android.util.Log;
import com.arialyy.aria.core.scheduler.UploadSchedulers;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.upload.UploadTask;
import com.arialyy.aria.core.upload.UploadTaskEntity;
/**
* Created by Aria.Lao on 2017/2/27.
* 上传任务队列
*/
public class UploadTaskQueue extends AbsTaskQueue<UploadTask, UploadTaskEntity, UploadEntity> {
private static final String TAG = "UploadTaskQueue";
private static volatile UploadTaskQueue INSTANCE = null;
private static final Object LOCK = new Object();
public static UploadTaskQueue getInstance() {
if (INSTANCE == null) {
synchronized (LOCK) {
INSTANCE = new UploadTaskQueue();
}
}
return INSTANCE;
}
@Override public void startTask(UploadTask task) {
if (mExecutePool.putTask(task)) {
mCachePool.removeTask(task);
//task.getEntity().setFailNum(0);
task.start();
}
}
@Override public void stopTask(UploadTask task) {
if (!task.isRunning()) Log.w(TAG, "停止任务失败,【任务已经停止】");
if (mExecutePool.removeTask(task)) {
task.stop();
} else {
task.stop();
Log.w(TAG, "停止任务失败,【任务已经停止】");
}
}
@Override public void cancelTask(UploadTask task) {
task.cancel();
}
@Override public void reTryStart(UploadTask task) {
if (task == null) {
Log.w(TAG, "重试下载失败,task 为null");
return;
}
if (!task.isRunning()) {
task.start();
} else {
Log.w(TAG, "任务没有完全停止,重试下载失败");
}
}
@Override public int size() {
return mExecutePool.size();
}
@Override public void setDownloadNum(int downloadNum) {
}
@Override public UploadTask createTask(String targetName, UploadTaskEntity entity) {
UploadTask task = null;
if (!TextUtils.isEmpty(targetName)) {
task = (UploadTask) TaskFactory.getInstance()
.createTask(targetName, entity, UploadSchedulers.getInstance());
mCachePool.putTask(task);
} else {
Log.e(TAG, "target name 为 null是!!");
}
return task;
}
@Override public UploadTask getTask(UploadEntity entity) {
UploadTask task = mExecutePool.getTask(entity.getFilePath());
if (task == null) {
task = mCachePool.getTask(entity.getFilePath());
}
return task;
}
@Override public void removeTask(UploadEntity entity) {
UploadTask task = mExecutePool.getTask(entity.getFilePath());
if (task != null) {
Log.d(TAG, "从执行池删除任务,删除" + (mExecutePool.removeTask(task) ? "成功" : "失败"));
}
task = mCachePool.getTask(entity.getFilePath());
if (task != null) {
Log.d(TAG, "从缓存池删除任务,删除" + (mCachePool.removeTask(task) ? "成功" : "失败"));
}
}
@Override public UploadTask getNextTask() {
return mCachePool.pollTask();
}
}

@ -18,9 +18,8 @@ package com.arialyy.aria.core.queue.pool;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.arialyy.aria.core.queue.IPool; import com.arialyy.aria.core.inf.ITask;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.core.task.Task;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
@ -30,36 +29,26 @@ import java.util.concurrent.TimeUnit;
* Created by lyy on 2016/8/14. * Created by lyy on 2016/8/14.
* 任务缓存池所有下载任务最先缓存在这个池中 * 任务缓存池所有下载任务最先缓存在这个池中
*/ */
public class CachePool implements IPool { public class CachePool<TASK extends ITask> implements IPool<TASK> {
private static final String TAG = "CachePool"; private static final String TAG = "CachePool";
private static final Object LOCK = new Object(); private static final Object LOCK = new Object();
private static final int MAX_NUM = Integer.MAX_VALUE; //最大下载任务数 private static final int MAX_NUM = Integer.MAX_VALUE; //最大下载任务数
private static volatile CachePool INSTANCE = null; private static final long TIME_OUT = 1000;
private static final long TIME_OUT = 1000; private Map<String, TASK> mCacheArray;
private Map<String, Task> mCacheArray; private LinkedBlockingQueue<TASK> mCacheQueue;
private LinkedBlockingQueue<Task> mCacheQueue;
private CachePool() { public CachePool() {
mCacheQueue = new LinkedBlockingQueue<>(MAX_NUM); mCacheQueue = new LinkedBlockingQueue<>(MAX_NUM);
mCacheArray = new HashMap<>(); mCacheArray = new HashMap<>();
} }
public static CachePool getInstance() { @Override public boolean putTask(TASK task) {
if (INSTANCE == null) {
synchronized (LOCK) {
INSTANCE = new CachePool();
}
}
return INSTANCE;
}
@Override public boolean putTask(Task task) {
synchronized (LOCK) { synchronized (LOCK) {
if (task == null) { if (task == null) {
Log.e(TAG, "下载任务不能为空!!"); Log.e(TAG, "下载任务不能为空!!");
return false; return false;
} }
String url = task.getDownloadEntity().getDownloadUrl(); String url = task.getKey();
if (mCacheQueue.contains(task)) { if (mCacheQueue.contains(task)) {
Log.w(TAG, "队列中已经包含了该任务,任务下载链接【" + url + "】"); Log.w(TAG, "队列中已经包含了该任务,任务下载链接【" + url + "】");
return false; return false;
@ -74,13 +63,13 @@ public class CachePool implements IPool {
} }
} }
@Override public Task pollTask() { @Override public TASK pollTask() {
synchronized (LOCK) { synchronized (LOCK) {
try { try {
Task task = null; TASK task = null;
task = mCacheQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS); task = mCacheQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS);
if (task != null) { if (task != null) {
String url = task.getDownloadEntity().getDownloadUrl(); String url = task.getKey();
mCacheArray.remove(CommonUtil.keyToHashKey(url)); mCacheArray.remove(CommonUtil.keyToHashKey(url));
} }
return task; return task;
@ -91,7 +80,7 @@ public class CachePool implements IPool {
return null; return null;
} }
@Override public Task getTask(String downloadUrl) { @Override public TASK getTask(String downloadUrl) {
synchronized (LOCK) { synchronized (LOCK) {
if (TextUtils.isEmpty(downloadUrl)) { if (TextUtils.isEmpty(downloadUrl)) {
Log.e(TAG, "请传入有效的下载链接"); Log.e(TAG, "请传入有效的下载链接");
@ -102,13 +91,13 @@ public class CachePool implements IPool {
} }
} }
@Override public boolean removeTask(Task task) { @Override public boolean removeTask(TASK task) {
synchronized (LOCK) { synchronized (LOCK) {
if (task == null) { if (task == null) {
Log.e(TAG, "任务不能为空"); Log.e(TAG, "任务不能为空");
return false; return false;
} else { } else {
String key = CommonUtil.keyToHashKey(task.getDownloadEntity().getDownloadUrl()); String key = CommonUtil.keyToHashKey(task.getKey());
mCacheArray.remove(key); mCacheArray.remove(key);
return mCacheQueue.remove(task); return mCacheQueue.remove(task);
} }
@ -121,8 +110,8 @@ public class CachePool implements IPool {
Log.e(TAG, "请传入有效的下载链接"); Log.e(TAG, "请传入有效的下载链接");
return false; return false;
} }
String key = CommonUtil.keyToHashKey(downloadUrl); String key = CommonUtil.keyToHashKey(downloadUrl);
Task task = mCacheArray.get(key); TASK task = mCacheArray.get(key);
mCacheArray.remove(key); mCacheArray.remove(key);
return mCacheQueue.remove(task); return mCacheQueue.remove(task);
} }

@ -18,9 +18,8 @@ package com.arialyy.aria.core.queue.pool;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.arialyy.aria.core.inf.ITask;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.core.queue.IPool;
import com.arialyy.aria.core.task.Task;
import com.arialyy.aria.util.Configuration; import com.arialyy.aria.util.Configuration;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -31,39 +30,29 @@ import java.util.concurrent.TimeUnit;
* Created by lyy on 2016/8/15. * Created by lyy on 2016/8/15.
* 任务执行池所有当前下载任务都该任务池中默认下载大小为2 * 任务执行池所有当前下载任务都该任务池中默认下载大小为2
*/ */
public class ExecutePool implements IPool { public class ExecutePool<TASK extends ITask> implements IPool<TASK> {
private static final String TAG = "ExecutePool"; private static final String TAG = "ExecutePool";
private static final Object LOCK = new Object(); private static final Object LOCK = new Object();
private static final long TIME_OUT = 1000; private static final long TIME_OUT = 1000;
private static volatile ExecutePool INSTANCE = null; private ArrayBlockingQueue<TASK> mExecuteQueue;
private ArrayBlockingQueue<Task> mExecuteQueue; private Map<String, TASK> mExecuteArray;
private Map<String, Task> mExecuteArray; private int mSize;
private int mSize;
private ExecutePool() { public ExecutePool() {
mSize = Configuration.getInstance().getDownloadNum(); mSize = Configuration.getInstance().getDownloadNum();
mExecuteQueue = new ArrayBlockingQueue<>(mSize); mExecuteQueue = new ArrayBlockingQueue<>(mSize);
mExecuteArray = new HashMap<>(); mExecuteArray = new HashMap<>();
} }
public static ExecutePool getInstance() { @Override public boolean putTask(TASK task) {
if (INSTANCE == null) {
synchronized (LOCK) {
INSTANCE = new ExecutePool();
}
}
return INSTANCE;
}
@Override public boolean putTask(Task task) {
synchronized (LOCK) { synchronized (LOCK) {
if (task == null) { if (task == null) {
Log.e(TAG, "下载任务不能为空!!"); Log.e(TAG, "任务不能为空!!");
return false; return false;
} }
String url = task.getDownloadEntity().getDownloadUrl(); String url = task.getKey();
if (mExecuteQueue.contains(task)) { if (mExecuteQueue.contains(task)) {
Log.e(TAG, "队列中已经包含了该任务,任务下载链接【" + url + "】"); Log.e(TAG, "队列中已经包含了该任务,任务key【" + url + "】");
return false; return false;
} else { } else {
if (mExecuteQueue.size() >= mSize) { if (mExecuteQueue.size() >= mSize) {
@ -85,8 +74,8 @@ public class ExecutePool implements IPool {
*/ */
public void setDownloadNum(int downloadNum) { public void setDownloadNum(int downloadNum) {
try { try {
ArrayBlockingQueue<Task> temp = new ArrayBlockingQueue<>(downloadNum); ArrayBlockingQueue<TASK> temp = new ArrayBlockingQueue<>(downloadNum);
Task task; TASK task;
while ((task = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS)) != null) { while ((task = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS)) != null) {
temp.offer(task); temp.offer(task);
} }
@ -103,12 +92,11 @@ public class ExecutePool implements IPool {
* *
* @param newTask 新下载任务 * @param newTask 新下载任务
*/ */
private boolean putNewTask(Task newTask) { private boolean putNewTask(TASK newTask) {
String url = newTask.getDownloadEntity().getDownloadUrl(); String url = newTask.getKey();
boolean s = mExecuteQueue.offer(newTask); boolean s = mExecuteQueue.offer(newTask);
Log.w(TAG, "任务添加" + (s ? "成功" : "失败,【" + url + "】")); Log.w(TAG, "任务添加" + (s ? "成功" : "失败,【" + url + "】"));
if (s) { if (s) {
newTask.start();
mExecuteArray.put(CommonUtil.keyToHashKey(url), newTask); mExecuteArray.put(CommonUtil.keyToHashKey(url), newTask);
} }
return s; return s;
@ -119,14 +107,13 @@ public class ExecutePool implements IPool {
*/ */
private boolean pollFirstTask() { private boolean pollFirstTask() {
try { try {
Task oldTask = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS); TASK oldTask = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS);
if (oldTask == null) { if (oldTask == null) {
Log.e(TAG, "移除任务失败"); Log.e(TAG, "移除任务失败");
return false; return false;
} }
oldTask.stop(); oldTask.stop();
// wait(200); String key = CommonUtil.keyToHashKey(oldTask.getKey());
String key = CommonUtil.keyToHashKey(oldTask.getDownloadEntity().getDownloadUrl());
mExecuteArray.remove(key); mExecuteArray.remove(key);
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
@ -135,13 +122,13 @@ public class ExecutePool implements IPool {
return true; return true;
} }
@Override public Task pollTask() { @Override public TASK pollTask() {
synchronized (LOCK) { synchronized (LOCK) {
try { try {
Task task = null; TASK task = null;
task = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS); task = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS);
if (task != null) { if (task != null) {
String url = task.getDownloadEntity().getDownloadUrl(); String url = task.getKey();
mExecuteArray.remove(CommonUtil.keyToHashKey(url)); mExecuteArray.remove(CommonUtil.keyToHashKey(url));
} }
return task; return task;
@ -152,10 +139,10 @@ public class ExecutePool implements IPool {
} }
} }
@Override public Task getTask(String downloadUrl) { @Override public TASK getTask(String downloadUrl) {
synchronized (LOCK) { synchronized (LOCK) {
if (TextUtils.isEmpty(downloadUrl)) { if (TextUtils.isEmpty(downloadUrl)) {
Log.e(TAG, "请传入有效的下载链接"); Log.e(TAG, "请传入有效的任务key");
return null; return null;
} }
String key = CommonUtil.keyToHashKey(downloadUrl); String key = CommonUtil.keyToHashKey(downloadUrl);
@ -163,13 +150,13 @@ public class ExecutePool implements IPool {
} }
} }
@Override public boolean removeTask(Task task) { @Override public boolean removeTask(TASK task) {
synchronized (LOCK) { synchronized (LOCK) {
if (task == null) { if (task == null) {
Log.e(TAG, "任务不能为空"); Log.e(TAG, "任务不能为空");
return false; return false;
} else { } else {
String key = CommonUtil.keyToHashKey(task.getDownloadEntity().getDownloadUrl()); String key = CommonUtil.keyToHashKey(task.getKey());
mExecuteArray.remove(key); mExecuteArray.remove(key);
return mExecuteQueue.remove(task); return mExecuteQueue.remove(task);
} }
@ -179,11 +166,11 @@ public class ExecutePool implements IPool {
@Override public boolean removeTask(String downloadUrl) { @Override public boolean removeTask(String downloadUrl) {
synchronized (LOCK) { synchronized (LOCK) {
if (TextUtils.isEmpty(downloadUrl)) { if (TextUtils.isEmpty(downloadUrl)) {
Log.e(TAG, "请传入有效的下载链接"); Log.e(TAG, "请传入有效的任务key");
return false; return false;
} }
String key = CommonUtil.keyToHashKey(downloadUrl); String key = CommonUtil.keyToHashKey(downloadUrl);
Task task = mExecuteArray.get(key); TASK task = mExecuteArray.get(key);
mExecuteArray.remove(key); mExecuteArray.remove(key);
return mExecuteQueue.remove(task); return mExecuteQueue.remove(task);
} }

@ -14,27 +14,26 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.queue.pool;
package com.arialyy.aria.core.queue; import com.arialyy.aria.core.inf.ITask;
import com.arialyy.aria.core.task.Task;
/** /**
* Created by lyy on 2016/8/14. * Created by lyy on 2016/8/14.
* 任务池 * 任务池
*/ */
public interface IPool { public interface IPool<T extends ITask> {
/** /**
* 将下载任务添加到任务池中 * 将下载任务添加到任务池中
*/ */
public boolean putTask(Task task); public boolean putTask(T task);
/** /**
* 按照队列原则取出下载任务 * 按照队列原则取出下载任务
* *
* @return 返回null或者下载任务 * @return 返回null或者下载任务
*/ */
public Task pollTask(); public T pollTask();
/** /**
* 通过下载链接获取下载任务当任务不为空时队列将删除该下载任务 * 通过下载链接获取下载任务当任务不为空时队列将删除该下载任务
@ -42,7 +41,7 @@ public interface IPool {
* @param downloadUrl 下载链接 * @param downloadUrl 下载链接
* @return 返回null或者下载任务 * @return 返回null或者下载任务
*/ */
public Task getTask(String downloadUrl); public T getTask(String downloadUrl);
/** /**
* 删除任务池中的下载任务 * 删除任务池中的下载任务
@ -50,7 +49,7 @@ public interface IPool {
* @param task 下载任务 * @param task 下载任务
* @return true:移除成功 * @return true:移除成功
*/ */
public boolean removeTask(Task task); public boolean removeTask(T task);
/** /**
* 通过下载链接移除下载任务 * 通过下载链接移除下载任务

@ -18,12 +18,10 @@ package com.arialyy.aria.core.scheduler;
import android.os.CountDownTimer; import android.os.CountDownTimer;
import android.os.Message; import android.os.Message;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.arialyy.aria.core.DownloadManager; import com.arialyy.aria.core.queue.DownloadTaskQueue;
import com.arialyy.aria.core.queue.ITaskQueue; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.DownloadEntity; import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.core.task.Task;
import com.arialyy.aria.util.Configuration; import com.arialyy.aria.util.Configuration;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
@ -34,83 +32,50 @@ import java.util.concurrent.ConcurrentHashMap;
* Created by lyy on 2016/8/16. * Created by lyy on 2016/8/16.
* 任务下载器提供抽象的方法供具体的实现类操作 * 任务下载器提供抽象的方法供具体的实现类操作
*/ */
public class DownloadSchedulers implements IDownloadSchedulers { public class DownloadSchedulers implements ISchedulers<DownloadTask> {
/**
* 任务预加载 private static final String TAG = "DownloadSchedulers";
*/ private static final Object LOCK = new Object();
public static final int PRE = 0;
/**
* 任务开始
*/
public static final int START = 1;
/**
* 任务停止
*/
public static final int STOP = 2;
/**
* 任务失败
*/
public static final int FAIL = 3;
/**
* 任务取消
*/
public static final int CANCEL = 4;
/**
* 任务完成
*/
public static final int COMPLETE = 5;
/**
* 下载中
*/
public static final int RUNNING = 6;
/**
* 恢复下载
*/
public static final int RESUME = 7;
private static final String TAG = "DownloadSchedulers";
private static final Object LOCK = new Object();
private static volatile DownloadSchedulers INSTANCE = null; private static volatile DownloadSchedulers INSTANCE = null;
/** /**
* 下载器任务监听 * 下载器任务监听
*/ */
Map<String, OnSchedulerListener> mSchedulerListeners = new ConcurrentHashMap<>(); private Map<String, IDownloadSchedulerListener<DownloadTask>> mSchedulerListeners =
DownloadManager mManager = DownloadManager.getInstance(); new ConcurrentHashMap<>();
ITaskQueue mQueue; private DownloadTaskQueue mQueue;
private DownloadSchedulers() { private DownloadSchedulers() {
mQueue = mManager.getTaskQueue(); mQueue = DownloadTaskQueue.getInstance();
} }
public static DownloadSchedulers getInstance() { public static DownloadSchedulers getInstance() {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (LOCK) { synchronized (LOCK) {
//INSTANCE = new DownloadSchedulers(queue);
INSTANCE = new DownloadSchedulers(); INSTANCE = new DownloadSchedulers();
} }
} }
return INSTANCE; return INSTANCE;
} }
@Override @Override public void addSchedulerListener(String targetName,
public void addSchedulerListener(String targetName, OnSchedulerListener schedulerListener) { ISchedulerListener<DownloadTask> schedulerListener) {
mSchedulerListeners.put(targetName, schedulerListener); mSchedulerListeners.put(targetName,
(IDownloadSchedulerListener<DownloadTask>) schedulerListener);
} }
@Override @Override public void removeSchedulerListener(String targetName,
public void removeSchedulerListener(String targetName, OnSchedulerListener schedulerListener) { ISchedulerListener<DownloadTask> schedulerListener) {
//OnSchedulerListener listener = mSchedulerListeners.get(target.getClass().getName());
//mSchedulerListeners.remove(listener);
//该内存溢出解决方案:http://stackoverflow.com/questions/14585829/how-safe-is-to-delete-already-removed-concurrenthashmap-element //该内存溢出解决方案:http://stackoverflow.com/questions/14585829/how-safe-is-to-delete-already-removed-concurrenthashmap-element
for (Iterator<Map.Entry<String, OnSchedulerListener>> iter = for (Iterator<Map.Entry<String, IDownloadSchedulerListener<DownloadTask>>> iter =
mSchedulerListeners.entrySet().iterator(); iter.hasNext(); ) { mSchedulerListeners.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry<String, OnSchedulerListener> entry = iter.next(); Map.Entry<String, IDownloadSchedulerListener<DownloadTask>> entry = iter.next();
if (entry.getKey().equals(targetName)) iter.remove(); if (entry.getKey().equals(targetName)) iter.remove();
} }
} }
@Override public boolean handleMessage(Message msg) { @Override public boolean handleMessage(Message msg) {
Task task = (Task) msg.obj; DownloadTask task = (DownloadTask) msg.obj;
if (task == null) { if (task == null) {
Log.e(TAG, "请传入下载任务"); Log.e(TAG, "请传入下载任务");
return true; return true;
@ -122,12 +87,12 @@ public class DownloadSchedulers implements IDownloadSchedulers {
case CANCEL: case CANCEL:
mQueue.removeTask(entity); mQueue.removeTask(entity);
if (mQueue.size() < Configuration.getInstance().getDownloadNum()) { if (mQueue.size() < Configuration.getInstance().getDownloadNum()) {
startNextTask(entity); startNextTask();
} }
break; break;
case COMPLETE: case COMPLETE:
mQueue.removeTask(entity); mQueue.removeTask(entity);
startNextTask(entity); startNextTask();
break; break;
case FAIL: case FAIL:
handleFailTask(task); handleFailTask(task);
@ -141,7 +106,7 @@ public class DownloadSchedulers implements IDownloadSchedulers {
* *
* @param state 状态 * @param state 状态
*/ */
private void callback(int state, Task task) { private void callback(int state, DownloadTask task) {
if (mSchedulerListeners.size() > 0) { if (mSchedulerListeners.size() > 0) {
//if (!TextUtils.isEmpty(task.getTargetName())) { //if (!TextUtils.isEmpty(task.getTargetName())) {
// callback(state, task, mSchedulerListeners.get(task.getTargetName())); // callback(state, task, mSchedulerListeners.get(task.getTargetName()));
@ -153,7 +118,8 @@ public class DownloadSchedulers implements IDownloadSchedulers {
} }
} }
private void callback(int state, Task task, OnSchedulerListener listener) { private void callback(int state, DownloadTask task,
IDownloadSchedulerListener<DownloadTask> listener) {
if (listener != null) { if (listener != null) {
if (task == null) { if (task == null) {
Log.e(TAG, "TASK 为null,回调失败"); Log.e(TAG, "TASK 为null,回调失败");
@ -184,6 +150,9 @@ public class DownloadSchedulers implements IDownloadSchedulers {
case FAIL: case FAIL:
listener.onTaskFail(task); listener.onTaskFail(task);
break; break;
case SUPPORT_BREAK_POINT:
listener.onNoSupportBreakPoint(task);
break;
} }
} }
} }
@ -193,7 +162,7 @@ public class DownloadSchedulers implements IDownloadSchedulers {
* *
* @param task 下载任务 * @param task 下载任务
*/ */
@Override public void handleFailTask(final Task task) { private void handleFailTask(final DownloadTask task) {
final Configuration config = Configuration.getInstance(); final Configuration config = Configuration.getInstance();
CountDownTimer timer = new CountDownTimer(config.getReTryInterval(), 1000) { CountDownTimer timer = new CountDownTimer(config.getReTryInterval(), 1000) {
@Override public void onTick(long millisUntilFinished) { @Override public void onTick(long millisUntilFinished) {
@ -202,8 +171,8 @@ public class DownloadSchedulers implements IDownloadSchedulers {
@Override public void onFinish() { @Override public void onFinish() {
DownloadEntity entity = task.getDownloadEntity(); DownloadEntity entity = task.getDownloadEntity();
if (entity.getFailNum() <= config.getReTryNum()) { if (entity.getFailNum() < config.getReTryNum()) {
Task task = mQueue.getTask(entity); DownloadTask task = mQueue.getTask(entity);
mQueue.reTryStart(task); mQueue.reTryStart(task);
try { try {
Thread.sleep(config.getReTryInterval()); Thread.sleep(config.getReTryInterval());
@ -212,7 +181,7 @@ public class DownloadSchedulers implements IDownloadSchedulers {
} }
} else { } else {
mQueue.removeTask(entity); mQueue.removeTask(entity);
startNextTask(entity); startNextTask();
} }
} }
}; };
@ -221,11 +190,9 @@ public class DownloadSchedulers implements IDownloadSchedulers {
/** /**
* 启动下一个任务条件任务停止取消下载任务完成 * 启动下一个任务条件任务停止取消下载任务完成
*
* @param entity 通过Handler传递的下载实体
*/ */
@Override public void startNextTask(DownloadEntity entity) { private void startNextTask() {
Task newTask = mQueue.getNextTask(); DownloadTask newTask = mQueue.getNextTask();
if (newTask == null) { if (newTask == null) {
Log.w(TAG, "没有下一任务"); Log.w(TAG, "没有下一任务");
return; return;

@ -0,0 +1,29 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.scheduler;
import com.arialyy.aria.core.inf.ITask;
/**
* Created by Aria.Lao on 2017/4/5.
*/
public interface IDownloadSchedulerListener<TASK extends ITask> extends ISchedulerListener<TASK> {
/**
* 支持断点的回调
*/
public void onNoSupportBreakPoint(TASK task);
}

@ -15,49 +15,49 @@
*/ */
package com.arialyy.aria.core.scheduler; package com.arialyy.aria.core.scheduler;
import com.arialyy.aria.core.task.Task; import com.arialyy.aria.core.inf.ITask;
/** /**
* Target处理任务监听 * Target处理任务监听
*/ */
public interface OnSchedulerListener { public interface ISchedulerListener<TASK extends ITask> {
/** /**
* 任务预加载 * 任务预加载
*/ */
public void onTaskPre(Task task); public void onTaskPre(TASK task);
/** /**
* 任务恢复下载 * 任务恢复下载
*/ */
public void onTaskResume(Task task); public void onTaskResume(TASK task);
/** /**
* 任务开始 * 任务开始
*/ */
public void onTaskStart(Task task); public void onTaskStart(TASK task);
/** /**
* 任务停止 * 任务停止
*/ */
public void onTaskStop(Task task); public void onTaskStop(TASK task);
/** /**
* 任务取消 * 任务取消
*/ */
public void onTaskCancel(Task task); public void onTaskCancel(TASK task);
/** /**
* 任务下载失败 * 任务下载失败
*/ */
public void onTaskFail(Task task); public void onTaskFail(TASK task);
/** /**
* 任务完成 * 任务完成
*/ */
public void onTaskComplete(Task task); public void onTaskComplete(TASK task);
/** /**
* 任务执行中 * 任务执行中
*/ */
public void onTaskRunning(Task task); public void onTaskRunning(TASK task);
} }

@ -17,40 +17,62 @@
package com.arialyy.aria.core.scheduler; package com.arialyy.aria.core.scheduler;
import android.os.Handler; import android.os.Handler;
import com.arialyy.aria.core.DownloadEntity; import com.arialyy.aria.core.inf.ITask;
import com.arialyy.aria.core.task.Task;
/** /**
* Created by AriaLyy@outlook.com on 2016/11/2. * Created by AriaLyy@outlook.com on 2016/11/2.
* 下载调度器接口 * 调度器功能接口
*/ */
public interface IDownloadSchedulers extends Handler.Callback { public interface ISchedulers<Task extends ITask> extends Handler.Callback {
/** /**
* 注册下载器监听一个观察者只能注册一次监听 * 断点支持
*
* @param targetName 观察者创建该监听器的对象类名
* @param schedulerListener {@link OnSchedulerListener}
*/ */
public void addSchedulerListener(String targetName, OnSchedulerListener schedulerListener); public static final int SUPPORT_BREAK_POINT = 8;
/** /**
* @param targetName 观察者创建该监听器的对象类名 * 任务预加载
* 取消注册监听器 */
public static final int PRE = 0;
/**
* 任务开始
*/
public static final int START = 1;
/**
* 任务停止
*/
public static final int STOP = 2;
/**
* 任务失败
*/ */
public void removeSchedulerListener(String targetName, OnSchedulerListener schedulerListener); public static final int FAIL = 3;
/**
* 任务取消
*/
public static final int CANCEL = 4;
/**
* 任务完成
*/
public static final int COMPLETE = 5;
/**
* 任务处理中
*/
public static final int RUNNING = 6;
/**
* 恢复任务
*/
public static final int RESUME = 7;
/** /**
* 处理下载任务下载失败的情形 * 注册下载器监听一个观察者只能注册一次监听
* *
* @param task 下载任务 * @param targetName 观察者创建该监听器的对象类名
* @param schedulerListener {@link ISchedulerListener}
*/ */
public void handleFailTask(Task task); public void addSchedulerListener(String targetName, ISchedulerListener<Task> schedulerListener);
/** /**
* 启动下一个任务条件任务停止取消下载任务完成 * @param targetName 观察者创建该监听器的对象类名
* * 取消注册监听器
* @param entity 通过Handler传递的下载实体
*/ */
public void startNextTask(DownloadEntity entity); public void removeSchedulerListener(String targetName,
ISchedulerListener<Task> schedulerListener);
} }

@ -0,0 +1,186 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.scheduler;
import android.os.CountDownTimer;
import android.os.Message;
import android.util.Log;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.queue.UploadTaskQueue;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.upload.UploadTask;
import com.arialyy.aria.util.Configuration;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* Created by Aria.Lao on 2017/2/27.
* 上传任务调度器
*/
public class UploadSchedulers implements ISchedulers<UploadTask> {
private static final String TAG = "UploadSchedulers";
private static final Object LOCK = new Object();
private static volatile UploadSchedulers INSTANCE = null;
private Map<String, ISchedulerListener<UploadTask>> mSchedulerListeners =
new ConcurrentHashMap<>();
private UploadTaskQueue mQueue;
private UploadSchedulers() {
mQueue = UploadTaskQueue.getInstance();
}
public static UploadSchedulers getInstance() {
if (INSTANCE == null) {
synchronized (LOCK) {
INSTANCE = new UploadSchedulers();
}
}
return INSTANCE;
}
@Override public void addSchedulerListener(String targetName,
ISchedulerListener<UploadTask> schedulerListener) {
mSchedulerListeners.put(targetName, schedulerListener);
}
@Override public void removeSchedulerListener(String targetName,
ISchedulerListener<UploadTask> schedulerListener) {
for (Iterator<Map.Entry<String, ISchedulerListener<UploadTask>>> iter =
mSchedulerListeners.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry<String, ISchedulerListener<UploadTask>> entry = iter.next();
if (entry.getKey().equals(targetName)) iter.remove();
}
}
private void handleFailTask(final UploadTask task) {
final Configuration config = Configuration.getInstance();
CountDownTimer timer = new CountDownTimer(config.getReTryInterval(), 1000) {
@Override public void onTick(long millisUntilFinished) {
}
@Override public void onFinish() {
UploadEntity entity = task.getUploadEntity();
if (entity.getFailNum() <= config.getReTryNum()) {
UploadTask task = mQueue.getTask(entity);
mQueue.reTryStart(task);
try {
Thread.sleep(config.getReTryInterval());
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
mQueue.removeTask(entity);
startNextTask();
}
}
};
timer.start();
}
private void startNextTask() {
UploadTask newTask = mQueue.getNextTask();
if (newTask == null) {
Log.w(TAG, "没有下一任务");
return;
}
if (newTask.getUploadEntity().getState() == IEntity.STATE_WAIT) {
mQueue.startTask(newTask);
}
}
/**
* 回调
*
* @param state 状态
*/
private void callback(int state, UploadTask task) {
if (mSchedulerListeners.size() > 0) {
//if (!TextUtils.isEmpty(task.getTargetName())) {
// callback(state, task, mSchedulerListeners.get(task.getTargetName()));
//}
Set<String> keys = mSchedulerListeners.keySet();
for (String key : keys) {
callback(state, task, mSchedulerListeners.get(key));
}
}
}
private void callback(int state, UploadTask task, ISchedulerListener<UploadTask> listener) {
if (listener != null) {
if (task == null) {
Log.e(TAG, "TASK 为null,回调失败");
return;
}
switch (state) {
case RUNNING:
listener.onTaskRunning(task);
break;
case START:
listener.onTaskStart(task);
break;
case STOP:
listener.onTaskStop(task);
break;
case RESUME:
listener.onTaskResume(task);
break;
case PRE:
listener.onTaskPre(task);
break;
case CANCEL:
listener.onTaskCancel(task);
break;
case COMPLETE:
listener.onTaskComplete(task);
break;
case FAIL:
listener.onTaskFail(task);
break;
}
}
}
@Override public boolean handleMessage(Message msg) {
UploadTask task = (UploadTask) msg.obj;
if (task == null) {
Log.e(TAG, "请传入上传任务");
return true;
}
callback(msg.what, task);
UploadEntity entity = task.getUploadEntity();
switch (msg.what) {
case STOP:
case CANCEL:
mQueue.removeTask(entity);
if (mQueue.size() < Configuration.getInstance().getDownloadNum()) {
startNextTask();
}
break;
case COMPLETE:
mQueue.removeTask(entity);
startNextTask();
break;
case FAIL:
handleFailTask(task);
break;
}
return true;
}
}

@ -1,62 +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.task;
import android.content.Context;
import com.arialyy.aria.core.DownloadEntity;
import com.arialyy.aria.core.scheduler.IDownloadSchedulers;
/**
* Created by lyy on 2016/8/18.
* 任务工厂
*/
public class TaskFactory {
private static final String TAG = "TaskFactory";
private static final Object LOCK = new Object();
private static volatile TaskFactory INSTANCE = null;
private TaskFactory() {
}
public static TaskFactory getInstance() {
if (INSTANCE == null) {
synchronized (LOCK) {
INSTANCE = new TaskFactory();
}
}
return INSTANCE;
}
/**
* 创建普通下载任务
*
* @param entity 下载实体
* @param schedulers {@link IDownloadSchedulers}
*/
public Task createTask(Context context, DownloadEntity entity, IDownloadSchedulers schedulers) {
return createTask("", context, entity, schedulers);
}
public Task createTask(String targetName, Context context, DownloadEntity entity,
IDownloadSchedulers schedulers) {
Task.Builder builder = new Task.Builder(targetName, context, entity);
builder.setOutHandler(schedulers);
return builder.build();
}
}

@ -0,0 +1,69 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.upload;
/**
* Created by Aria.Lao on 2017/2/9.
* 上传监听
*/
public interface IUploadListener {
/**
* 预处理
*/
public void onPre();
/**
* 开始上传
*/
public void onStart(long fileSize);
/**
* 恢复上传
*
* @param resumeLocation 上次上传停止位置
*/
public void onResume(long resumeLocation);
/**
* 停止上传
*
* @param stopLocation 上传停止位置
*/
public void onStop(long stopLocation);
/**
* 上传进度
*
* @param currentLocation 当前进度
*/
public void onProgress(long currentLocation);
/**
* 取消上传
*/
public void onCancel();
/**
* 上传成功
*/
public void onComplete();
/**
* 上传失败
*/
public void onFail();
}

@ -0,0 +1,141 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.upload;
import android.os.Parcel;
import android.os.Parcelable;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.orm.Ignore;
/**
* Created by Aria.Lao on 2017/2/9.
* 上传文件实体
*/
public class UploadEntity extends DbEntity implements IEntity, Parcelable {
private String filePath; //文件路径
private String fileName; //文件名
private long fileSize; //文件大小
private int state = STATE_WAIT;
private long currentProgress = 0;
private boolean isComplete = false;
@Ignore private long speed = 0; //下载速度
@Ignore private int failNum = 0;
public boolean isComplete() {
return isComplete;
}
public void setComplete(boolean complete) {
isComplete = complete;
}
public long getCurrentProgress() {
return currentProgress;
}
public void setCurrentProgress(long currentProgress) {
this.currentProgress = currentProgress;
}
public long getFileSize() {
return fileSize;
}
public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}
public long getSpeed() {
return speed;
}
public void setSpeed(long speed) {
this.speed = speed;
}
public int getFailNum() {
return failNum;
}
public void setFailNum(int failNum) {
this.failNum = failNum;
}
@Override public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public UploadEntity() {
}
@Override public int describeContents() {
return 0;
}
@Override public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.filePath);
dest.writeString(this.fileName);
dest.writeLong(this.fileSize);
dest.writeInt(this.state);
dest.writeLong(this.currentProgress);
dest.writeByte(this.isComplete ? (byte) 1 : (byte) 0);
dest.writeLong(this.speed);
dest.writeInt(this.failNum);
}
protected UploadEntity(Parcel in) {
this.filePath = in.readString();
this.fileName = in.readString();
this.fileSize = in.readLong();
this.state = in.readInt();
this.currentProgress = in.readLong();
this.isComplete = in.readByte() != 0;
this.speed = in.readLong();
this.failNum = in.readInt();
}
@Ignore public static final Creator<UploadEntity> CREATOR = new Creator<UploadEntity>() {
@Override public UploadEntity createFromParcel(Parcel source) {
return new UploadEntity(source);
}
@Override public UploadEntity[] newArray(int size) {
return new UploadEntity[size];
}
};
}

@ -0,0 +1,54 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.upload;
/**
* Created by Aria.Lao on 2017/2/23.
*/
public class UploadListener implements IUploadListener {
@Override public void onPre() {
}
@Override public void onStart(long fileSize) {
}
@Override public void onResume(long resumeLocation) {
}
@Override public void onStop(long stopLocation) {
}
@Override public void onProgress(long currentLocation) {
}
@Override public void onCancel() {
}
@Override public void onComplete() {
}
@Override public void onFail() {
}
}

@ -0,0 +1,130 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.upload;
import android.support.annotation.NonNull;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.command.AbsCmd;
import com.arialyy.aria.core.command.CmdFactory;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.IReceiver;
import com.arialyy.aria.core.scheduler.ISchedulerListener;
import com.arialyy.aria.core.scheduler.UploadSchedulers;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.CommonUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
/**
* Created by Aria.Lao on 2017/2/6.
* 上传功能接收器
*/
public class UploadReceiver implements IReceiver<UploadEntity> {
private static final String TAG = "DownloadReceiver";
public String targetName;
public ISchedulerListener<UploadTask> listener;
/**
* 加载任务
*
* @param filePath 文件地址
*/
public UploadTarget load(@NonNull String filePath) {
CheckUtil.checkUploadPath(filePath);
UploadEntity entity = UploadEntity.findData(UploadEntity.class, "filePath=?", filePath);
if (entity == null) {
entity = new UploadEntity();
}
String regex = "[/|\\\\|//]";
Pattern p = Pattern.compile(regex);
String[] strs = p.split(filePath);
String fileName = strs[strs.length - 1];
entity.setFileName(fileName);
entity.setFilePath(filePath);
return new UploadTarget(entity, targetName);
}
/**
* 通过上传路径获取上传实体
*/
public UploadEntity getUploadEntity(String filePath) {
CheckUtil.checkUploadPath(filePath);
return DbEntity.findData(UploadEntity.class, "filePath=?", filePath);
}
/**
* 下载任务是否存在
*/
@Override public boolean taskExists(String filePath) {
return DbEntity.findData(UploadEntity.class, "filePath=?", filePath) != null;
}
@Override public List<UploadEntity> getTaskList() {
return DbEntity.findAllData(UploadEntity.class);
}
@Override public void stopAllTask() {
List<UploadEntity> allEntity = DbEntity.findAllData(UploadEntity.class);
List<AbsCmd> stopCmds = new ArrayList<>();
for (UploadEntity entity : allEntity) {
if (entity.getState() == IEntity.STATE_RUNNING) {
stopCmds.add(
CommonUtil.createCmd(targetName, new UploadTaskEntity(entity), CmdFactory.TASK_STOP));
}
}
AriaManager.getInstance(AriaManager.APP).setCmds(stopCmds).exe();
}
@Override public void removeAllTask() {
final AriaManager am = AriaManager.getInstance(AriaManager.APP);
List<UploadEntity> allEntity = DbEntity.findAllData(UploadEntity.class);
List<AbsCmd> cancelCmds = new ArrayList<>();
for (UploadEntity entity : allEntity) {
cancelCmds.add(
CommonUtil.createCmd(targetName, new UploadTaskEntity(entity), CmdFactory.TASK_CANCEL));
}
am.setCmds(cancelCmds).exe();
Set<String> keys = am.getReceiver().keySet();
for (String key : keys) {
IReceiver receiver = am.getReceiver().get(key);
receiver.removeSchedulerListener();
am.getReceiver().remove(key);
}
}
@Override public void destroy() {
targetName = null;
listener = null;
}
/**
* 添加调度器回调
*/
public UploadReceiver addSchedulerListener(ISchedulerListener<UploadTask> listener) {
this.listener = listener;
UploadSchedulers.getInstance().addSchedulerListener(targetName, listener);
return this;
}
@Override public void removeSchedulerListener() {
if (listener != null) {
UploadSchedulers.getInstance().removeSchedulerListener(targetName, listener);
}
}
}

@ -0,0 +1,123 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.upload;
import android.support.annotation.NonNull;
import com.arialyy.aria.core.RequestEnum;
import com.arialyy.aria.core.inf.AbsTarget;
import com.arialyy.aria.core.queue.UploadTaskQueue;
import com.arialyy.aria.orm.DbEntity;
import java.util.Map;
/**
* Created by Aria.Lao on 2017/2/28.
*/
public class UploadTarget extends AbsTarget<UploadEntity, UploadTaskEntity> {
UploadTarget(UploadEntity entity, String targetName) {
this.entity = entity;
this.targetName = targetName;
taskEntity = new UploadTaskEntity(entity);
}
/**
* 设置userAgent
*/
public UploadTarget setUserAngent(@NonNull String userAgent) {
taskEntity.userAgent = userAgent;
return this;
}
/**
* 设置上传路径
*
* @param uploadUrl 上传路径
*/
public UploadTarget setUploadUrl(@NonNull String uploadUrl) {
taskEntity.uploadUrl = uploadUrl;
return this;
}
/**
* 设置服务器需要的附件key
*
* @param attachment 附件key
*/
public UploadTarget setAttachment(@NonNull String attachment) {
taskEntity.attachment = attachment;
return this;
}
/**
* 设置文件名
*/
public UploadTarget setFileName(String fileName) {
entity.setFileName(fileName);
return this;
}
/**
* 设置上传文件类型
*
* @param contentType tipmultipart/form-data
*/
public UploadTarget setContentType(String contentType) {
taskEntity.contentType = contentType;
return this;
}
/**
* 给url请求添加头部
*
* @param key 头部key
* @param header 头部value
*/
public UploadTarget addHeader(@NonNull String key, @NonNull String header) {
super._addHeader(key, header);
return this;
}
/**
* 给url请求添加头部
*
* @param headers key为http头部的keyValue为http头对应的配置
*/
public UploadTarget addHeaders(Map<String, String> headers) {
super._addHeaders(headers);
return this;
}
/**
* 设置请求类型
*
* @param requestEnum {@link RequestEnum}
*/
public UploadTarget setRequestMode(RequestEnum requestEnum) {
super._setRequestMode(requestEnum);
return this;
}
private UploadEntity getDownloadEntity(@NonNull String filePath) {
return DbEntity.findData(UploadEntity.class, "filePath=?", filePath);
}
/**
* 是否在下载
*/
public boolean isUploading() {
return UploadTaskQueue.getInstance().getTask(entity).isRunning();
}
}

@ -0,0 +1,260 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.upload;
import android.content.Intent;
import android.os.Handler;
import android.util.Log;
import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.ITask;
import com.arialyy.aria.core.scheduler.DownloadSchedulers;
import com.arialyy.aria.core.scheduler.ISchedulers;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.Configuration;
import java.lang.ref.WeakReference;
/**
* Created by Aria.Lao on 2017/2/23.
* 上传任务
*/
public class UploadTask implements ITask {
private static final String TAG = "UploadTask";
private Handler mOutHandler;
private UploadTaskEntity mTaskEntity;
private UploadEntity mUploadEntity;
private String mTargetName;
private UploadUtil mUtil;
private UListener mListener;
UploadTask(UploadTaskEntity taskEntity, Handler outHandler) {
mTaskEntity = taskEntity;
mOutHandler = outHandler;
mUploadEntity = mTaskEntity.uploadEntity;
mListener = new UListener(mOutHandler, this);
mUtil = new UploadUtil(mTaskEntity, mListener);
}
@Override public void setTargetName(String targetName) {
mTargetName = targetName;
}
@Override public String getKey() {
return mUploadEntity.getFilePath();
}
@Override public boolean isRunning() {
return mUtil.isRunning();
}
public UploadEntity getUploadEntity() {
return mUploadEntity;
}
@Override public IEntity getEntity() {
return mUploadEntity;
}
@Override public void start() {
if (mUtil.isRunning()) {
Log.d(TAG, "任务正在下载");
} else {
if (mListener == null) {
mListener = new UploadTask.UListener(mOutHandler, this);
}
mUtil.start();
}
}
@Override public void stop() {
}
@Override public void cancel() {
if (mUtil.isRunning()) {
mUtil.cancel();
} else {
// 如果任务不是下载状态
mUtil.cancel();
mUploadEntity.deleteData();
if (mOutHandler != null) {
mOutHandler.obtainMessage(DownloadSchedulers.CANCEL, this).sendToTarget();
}
//发送取消下载的广播
Intent intent = CommonUtil.createIntent(AriaManager.APP.getPackageName(), Aria.ACTION_CANCEL);
intent.putExtra(Aria.ENTITY, mUploadEntity);
AriaManager.APP.sendBroadcast(intent);
}
}
public String getTargetName() {
return mTargetName;
}
@Override public long getSpeed() {
return mUploadEntity.getSpeed();
}
@Override public long getFileSize() {
return mUploadEntity.getFileSize();
}
@Override public long getCurrentProgress() {
return mUploadEntity.getCurrentProgress();
}
private static class UListener extends UploadListener {
WeakReference<Handler> outHandler;
WeakReference<UploadTask> task;
long lastLen = 0; //上一次发送长度
long lastTime = 0;
long INTERVAL_TIME = 1000; //1m更新周期
boolean isFirst = true;
UploadEntity entity;
Intent sendIntent;
UListener(Handler outHandle, UploadTask task) {
this.outHandler = new WeakReference<>(outHandle);
this.task = new WeakReference<>(task);
entity = this.task.get().getUploadEntity();
sendIntent = CommonUtil.createIntent(AriaManager.APP.getPackageName(), Aria.ACTION_RUNNING);
sendIntent.putExtra(Aria.ENTITY, entity);
}
@Override public void onPre() {
entity.setState(IEntity.STATE_PRE);
sendIntent(Aria.ACTION_PRE, -1);
sendInState2Target(ISchedulers.PRE);
}
@Override public void onStart(long fileSize) {
entity.setFileSize(fileSize);
entity.setState(IEntity.STATE_RUNNING);
sendIntent(Aria.ACTION_PRE, -1);
sendInState2Target(ISchedulers.START);
}
@Override public void onResume(long resumeLocation) {
entity.setState(DownloadEntity.STATE_RUNNING);
sendInState2Target(DownloadSchedulers.RESUME);
sendIntent(Aria.ACTION_RESUME, resumeLocation);
}
@Override public void onStop(long stopLocation) {
entity.setState(DownloadEntity.STATE_STOP);
entity.setSpeed(0);
sendInState2Target(DownloadSchedulers.STOP);
sendIntent(Aria.ACTION_STOP, stopLocation);
}
@Override public void onProgress(long currentLocation) {
if (System.currentTimeMillis() - lastTime > INTERVAL_TIME) {
long speed = currentLocation - lastLen;
sendIntent.putExtra(Aria.CURRENT_LOCATION, currentLocation);
sendIntent.putExtra(Aria.CURRENT_SPEED, speed);
lastTime = System.currentTimeMillis();
if (isFirst) {
entity.setSpeed(0);
isFirst = false;
} else {
entity.setSpeed(speed);
}
entity.setCurrentProgress(currentLocation);
lastLen = currentLocation;
sendInState2Target(DownloadSchedulers.RUNNING);
AriaManager.APP.sendBroadcast(sendIntent);
}
}
@Override public void onCancel() {
entity.setState(DownloadEntity.STATE_CANCEL);
sendInState2Target(DownloadSchedulers.CANCEL);
sendIntent(Aria.ACTION_CANCEL, -1);
entity.deleteData();
}
@Override public void onComplete() {
entity.setState(DownloadEntity.STATE_COMPLETE);
entity.setComplete(true);
entity.setSpeed(0);
sendInState2Target(DownloadSchedulers.COMPLETE);
sendIntent(Aria.ACTION_COMPLETE, entity.getFileSize());
}
@Override public void onFail() {
entity.setFailNum(entity.getFailNum() + 1);
entity.setState(DownloadEntity.STATE_FAIL);
entity.setSpeed(0);
sendInState2Target(DownloadSchedulers.FAIL);
sendIntent(Aria.ACTION_FAIL, -1);
}
/**
* 将任务状态发送给下载器
*
* @param state {@link DownloadSchedulers#START}
*/
private void sendInState2Target(int state) {
if (outHandler.get() != null) {
outHandler.get().obtainMessage(state, task.get()).sendToTarget();
}
}
private void sendIntent(String action, long location) {
entity.setComplete(action.equals(Aria.ACTION_COMPLETE));
entity.setCurrentProgress(location);
entity.update();
if (!Configuration.isOpenBreadCast) return;
Intent intent = CommonUtil.createIntent(AriaManager.APP.getPackageName(), action);
intent.putExtra(Aria.ENTITY, entity);
if (location != -1) {
intent.putExtra(Aria.CURRENT_LOCATION, location);
}
AriaManager.APP.sendBroadcast(intent);
}
}
public static class Builder {
private Handler mOutHandler;
private UploadTaskEntity mTaskEntity;
private String mTargetName;
public void setOutHandler(ISchedulers outHandler) {
mOutHandler = new Handler(outHandler);
}
public void setUploadTaskEntity(UploadTaskEntity taskEntity) {
mTaskEntity = taskEntity;
}
public void setTargetName(String targetName) {
mTargetName = targetName;
}
public Builder() {
}
public UploadTask build() {
UploadTask task = new UploadTask(mTaskEntity, mOutHandler);
task.setTargetName(mTargetName);
return task;
}
}
}

@ -0,0 +1,47 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.upload;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.ITaskEntity;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Aria.Lao on 2017/2/9.
* 上传任务实体
*/
public class UploadTaskEntity extends ITaskEntity {
public UploadEntity uploadEntity;
public String uploadUrl; //上传路径
public String attachment; //文件上传需要的key
public String contentType = "multipart/form-data"; //上传的文件类型
public String userAgent = "User-Agent";
public String charset = "utf-8";
/**
* 文件上传表单
*/
public Map<String, String> formFields = new HashMap<>();
public UploadTaskEntity(UploadEntity downloadEntity) {
this.uploadEntity = downloadEntity;
}
@Override public IEntity getEntity() {
return uploadEntity;
}
}

@ -0,0 +1,230 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.upload;
import android.util.Log;
import com.arialyy.aria.util.CheckUtil;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Set;
import java.util.UUID;
/**
* Created by Aria.Lao on 2017/2/9.
* 上传工具
*/
final class UploadUtil implements Runnable {
private static final String TAG = "UploadUtil";
private final String BOUNDARY = UUID.randomUUID().toString(); // 边界标识 随机生成
private final String PREFIX = "--", LINE_END = "\r\n";
private UploadEntity mUploadEntity;
private UploadTaskEntity mTaskEntity;
private IUploadListener mListener;
private HttpURLConnection mHttpConn;
private long mCurrentLocation = 0;
private boolean isCancel = false;
private boolean isRunning = false;
private OutputStream mOutputStream;
UploadUtil(UploadTaskEntity taskEntity, IUploadListener listener) {
mTaskEntity = taskEntity;
CheckUtil.checkUploadTaskEntity(taskEntity.uploadEntity);
mUploadEntity = taskEntity.uploadEntity;
if (listener == null) {
throw new IllegalArgumentException("上传监听不能为空");
}
mListener = listener;
}
public void start() {
isCancel = false;
isRunning = false;
new Thread(this).start();
}
public void cancel() {
isCancel = true;
isRunning = false;
}
@Override public void run() {
File uploadFile = new File(mUploadEntity.getFilePath());
if (!uploadFile.exists()) {
Log.e(TAG, "【" + mUploadEntity.getFilePath() + "】,文件不存在。");
fail();
return;
}
mListener.onPre();
URL url;
try {
url = new URL(mTaskEntity.uploadUrl);
mHttpConn = (HttpURLConnection) url.openConnection();
mHttpConn.setUseCaches(false);
mHttpConn.setDoOutput(true);
mHttpConn.setDoInput(true);
mHttpConn.setRequestProperty("Content-Type",
mTaskEntity.contentType + "; boundary=" + BOUNDARY);
mHttpConn.setRequestProperty("User-Agent", mTaskEntity.userAgent);
//mHttpConn.setRequestProperty("Range", "bytes=" + 0 + "-" + "100");
//内部缓冲区---分段上传防止oom
mHttpConn.setChunkedStreamingMode(1024);
//添加Http请求头部
Set<String> keys = mTaskEntity.headers.keySet();
for (String key : keys) {
mHttpConn.setRequestProperty(key, mTaskEntity.headers.get(key));
}
mOutputStream = mHttpConn.getOutputStream();
PrintWriter writer =
new PrintWriter(new OutputStreamWriter(mOutputStream, mTaskEntity.charset), true);
//添加文件上传表单字段
keys = mTaskEntity.formFields.keySet();
for (String key : keys) {
addFormField(writer, key, mTaskEntity.formFields.get(key));
}
mListener.onStart(uploadFile.length());
uploadFile(writer, mTaskEntity.attachment, uploadFile);
Log.d(TAG, finish(writer) + "");
} catch (IOException e) {
e.printStackTrace();
fail();
}
}
boolean isRunning() {
return isRunning;
}
private void fail() {
try {
mListener.onFail();
if (mOutputStream != null) {
mOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 添加文件上传表单字段
*/
private void addFormField(PrintWriter writer, String name, String value) {
writer.append(PREFIX).append(BOUNDARY).append(LINE_END);
writer.append("Content-Disposition: form-data; name=\"")
.append(name)
.append("\"")
.append(LINE_END);
writer.append("Content-Type: text/plain; charset=")
.append(mTaskEntity.charset)
.append(LINE_END);
writer.append(LINE_END);
writer.append(value).append(LINE_END);
writer.flush();
}
/**
* 上传文件
*
* @param attachment 文件上传attachment
* @throws IOException
*/
private void uploadFile(PrintWriter writer, String attachment, File uploadFile)
throws IOException {
writer.append(PREFIX).append(BOUNDARY).append(LINE_END);
writer.append("Content-Disposition: form-data; name=\"")
.append(attachment)
.append("\"; filename=\"")
.append(mTaskEntity.uploadEntity.getFileName())
.append("\"")
.append(LINE_END);
writer.append("Content-Type: ")
.append(URLConnection.guessContentTypeFromName(mTaskEntity.uploadEntity.getFileName()))
.append(LINE_END);
writer.append("Content-Transfer-Encoding: binary").append(LINE_END);
writer.append(LINE_END);
writer.flush();
FileInputStream inputStream = new FileInputStream(uploadFile);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
mCurrentLocation += bytesRead;
mOutputStream.write(buffer, 0, bytesRead);
if (isCancel) {
break;
}
isRunning = true;
mListener.onProgress(mCurrentLocation);
}
mOutputStream.flush();
//outputStream.close(); //不能调用,否则服务器端异常
inputStream.close();
writer.append(LINE_END);
writer.flush();
isRunning = false;
if (isCancel) {
mListener.onCancel();
return;
}
mListener.onComplete();
}
/**
* 任务结束操作
*
* @throws IOException
*/
private String finish(PrintWriter writer) throws IOException {
StringBuilder response = new StringBuilder();
writer.append(LINE_END).flush();
writer.append(PREFIX).append(BOUNDARY).append(PREFIX).append(LINE_END);
writer.close();
int status = mHttpConn.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(mHttpConn.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
mHttpConn.disconnect();
} else {
Log.w(TAG, "state_code = " + status);
mListener.onFail();
}
writer.flush();
writer.close();
mOutputStream.close();
return response.toString();
}
}

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

@ -27,9 +27,9 @@ import java.util.List;
* 所有数据库实体父类 * 所有数据库实体父类
*/ */
public class DbEntity { public class DbEntity {
private static final Object LOCK = new Object(); private static final Object LOCK = new Object();
protected int rowID = -1; protected int rowID = -1;
private DbUtil mUtil = DbUtil.getInstance(); private DbUtil mUtil = DbUtil.getInstance();
protected DbEntity() { protected DbEntity() {
@ -75,7 +75,7 @@ public class DbEntity {
* @return 没有数据返回null * @return 没有数据返回null
*/ */
public static <T extends DbEntity> T findData(Class<T> clazz, String... expression) { public static <T extends DbEntity> T findData(Class<T> clazz, String... expression) {
DbUtil util = DbUtil.getInstance(); DbUtil util = DbUtil.getInstance();
List<T> datas = util.findData(clazz, expression); List<T> datas = util.findData(clazz, expression);
return datas == null ? null : datas.size() > 0 ? datas.get(0) : null; return datas == null ? null : datas.size() > 0 ? datas.get(0) : null;
} }
@ -150,15 +150,15 @@ public class DbEntity {
private <T extends DbEntity> T findData(Class<T> clazz, @NonNull String[] wheres, private <T extends DbEntity> T findData(Class<T> clazz, @NonNull String[] wheres,
@NonNull String[] values) { @NonNull String[] values) {
DbUtil util = DbUtil.getInstance(); DbUtil util = DbUtil.getInstance();
List<T> list = util.findData(clazz, wheres, values); List<T> list = util.findData(clazz, wheres, values);
return list == null ? null : list.get(0); return list == null ? null : list.get(0);
} }
private void updateRowID() { private void updateRowID() {
try { try {
Field[] fields = CommonUtil.getFields(getClass()); Field[] fields = CommonUtil.getFields(getClass());
List<String> where = new ArrayList<>(); List<String> where = new ArrayList<>();
List<String> values = new ArrayList<>(); List<String> values = new ArrayList<>();
for (Field field : fields) { for (Field field : fields) {
field.setAccessible(true); field.setAccessible(true);

@ -34,19 +34,19 @@ import java.util.List;
* 数据库操作工具 * 数据库操作工具
*/ */
public class DbUtil { public class DbUtil {
private static final String TAG = "DbUtil"; private static final String TAG = "DbUtil";
private static final Object LOCK = new Object(); private static final Object LOCK = new Object();
private volatile static DbUtil INSTANCE = null; private volatile static DbUtil INSTANCE = null;
private int CREATE_TABLE = 0; private int CREATE_TABLE = 0;
private int TABLE_EXISTS = 1; private int TABLE_EXISTS = 1;
private int INSERT_DATA = 2; private int INSERT_DATA = 2;
private int MODIFY_DATA = 3; private int MODIFY_DATA = 3;
private int FIND_DATA = 4; private int FIND_DATA = 4;
private int FIND_ALL_DATA = 5; private int FIND_ALL_DATA = 5;
private int DEL_DATA = 6; private int DEL_DATA = 6;
private int ROW_ID = 7; private int ROW_ID = 7;
private SQLiteDatabase mDb; private SQLiteDatabase mDb;
private SqlHelper mHelper; private SqlHelper mHelper;
private DbUtil() { private DbUtil() {
@ -123,8 +123,8 @@ public class DbUtil {
*/ */
synchronized void modifyData(DbEntity dbEntity) { synchronized void modifyData(DbEntity dbEntity) {
mDb = mHelper.getWritableDatabase(); mDb = mHelper.getWritableDatabase();
Class<?> clazz = dbEntity.getClass(); Class<?> clazz = dbEntity.getClass();
Field[] fields = CommonUtil.getFields(clazz); Field[] fields = CommonUtil.getFields(clazz);
if (fields != null && fields.length > 0) { if (fields != null && fields.length > 0) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("UPDATE ").append(CommonUtil.getClassName(dbEntity)).append(" SET "); sb.append("UPDATE ").append(CommonUtil.getClassName(dbEntity)).append(" SET ");
@ -398,8 +398,8 @@ public class DbUtil {
synchronized int[] getRowId(Class clazz) { synchronized int[] getRowId(Class clazz) {
mDb = mHelper.getReadableDatabase(); mDb = mHelper.getReadableDatabase();
Cursor cursor = mDb.rawQuery("SELECT rowid, * FROM " + CommonUtil.getClassName(clazz), null); Cursor cursor = mDb.rawQuery("SELECT rowid, * FROM " + CommonUtil.getClassName(clazz), null);
int[] ids = new int[cursor.getCount()]; int[] ids = new int[cursor.getCount()];
int i = 0; int i = 0;
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
ids[i] = cursor.getInt(cursor.getColumnIndex("rowid")); ids[i] = cursor.getInt(cursor.getColumnIndex("rowid"));
i++; i++;
@ -430,8 +430,8 @@ public class DbUtil {
i++; i++;
} }
print(ROW_ID, sb.toString()); print(ROW_ID, sb.toString());
Cursor c = mDb.rawQuery(sb.toString(), null); Cursor c = mDb.rawQuery(sb.toString(), null);
int id = c.getColumnIndex("rowid"); int id = c.getColumnIndex("rowid");
c.close(); c.close();
close(); close();
return id; return id;
@ -442,7 +442,7 @@ public class DbUtil {
*/ */
private synchronized <T extends DbEntity> List<T> newInstanceEntity(Class<T> clazz, private synchronized <T extends DbEntity> List<T> newInstanceEntity(Class<T> clazz,
Cursor cursor) { Cursor cursor) {
Field[] fields = CommonUtil.getFields(clazz); Field[] fields = CommonUtil.getFields(clazz);
List<T> entitys = new ArrayList<>(); List<T> entitys = new ArrayList<>();
if (fields != null && fields.length > 0) { if (fields != null && fields.length > 0) {
try { try {
@ -453,8 +453,8 @@ public class DbUtil {
if (ignoreField(field)) { if (ignoreField(field)) {
continue; continue;
} }
Class<?> type = field.getType(); Class<?> type = field.getType();
int column = cursor.getColumnIndex(field.getName()); int column = cursor.getColumnIndex(field.getName());
if (type == String.class) { if (type == String.class) {
field.set(entity, cursor.getString(column)); field.set(entity, cursor.getString(column));
} else if (type == int.class || type == Integer.class) { } else if (type == int.class || type == Integer.class) {

@ -14,7 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.orm; package com.arialyy.aria.orm;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;

@ -14,7 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.orm; package com.arialyy.aria.orm;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;

@ -14,7 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.orm; package com.arialyy.aria.orm;
import android.content.Context; import android.content.Context;

@ -18,7 +18,10 @@
package com.arialyy.aria.util; package com.arialyy.aria.util;
import java.io.*; import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays; import java.util.Arrays;
//import org.apache.log4j.Logger; //import org.apache.log4j.Logger;
@ -38,9 +41,9 @@ import java.util.Arrays;
public final class BufferedRandomAccessFile extends RandomAccessFile { public final class BufferedRandomAccessFile extends RandomAccessFile {
//private static final Logger logger_ = Logger.getLogger(BufferedRandomAccessFile.class); //private static final Logger logger_ = Logger.getLogger(BufferedRandomAccessFile.class);
static final int LogBuffSz_ = 16; // 64K buffer static final int LogBuffSz_ = 16; // 64K buffer
public static final int BuffSz_ = (1 << LogBuffSz_); public static final int BuffSz_ = (1 << LogBuffSz_);
static final long BuffMask_ = ~(((long) BuffSz_) - 1L); static final long BuffMask_ = ~(((long) BuffSz_) - 1L);
/* /*
* This implementation is based on the buffer implementation in Modula-3's * This implementation is based on the buffer implementation in Modula-3's
@ -48,12 +51,12 @@ public final class BufferedRandomAccessFile extends RandomAccessFile {
*/ */
private boolean dirty_; // true iff unflushed bytes exist private boolean dirty_; // true iff unflushed bytes exist
private boolean closed_; // true iff the file is closed private boolean closed_; // true iff the file is closed
private long curr_; // current position in file private long curr_; // current position in file
private long lo_, hi_; // bounds on characters in "buff" private long lo_, hi_; // bounds on characters in "buff"
private byte[] buff_; // local buffer private byte[] buff_; // local buffer
private long maxHi_; // this.lo + this.buff.length private long maxHi_; // this.lo + this.buff.length
private boolean hitEOF_; // buffer contains last file block? private boolean hitEOF_; // buffer contains last file block?
private long diskPos_; // disk position private long diskPos_; // disk position
/* /*
* To describe the above fields, we introduce the following abstractions for * To describe the above fields, we introduce the following abstractions for

@ -17,10 +17,12 @@
package com.arialyy.aria.util; package com.arialyy.aria.util;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.DownloadEntity; import com.arialyy.aria.core.download.DownloadTaskEntity;
import com.arialyy.aria.core.inf.ITaskEntity;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.upload.UploadTaskEntity;
import com.arialyy.aria.exception.FileException; import com.arialyy.aria.exception.FileException;
import java.io.File;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -31,6 +33,9 @@ import java.util.regex.Pattern;
public class CheckUtil { public class CheckUtil {
private static final String TAG = "CheckUtil"; private static final String TAG = "CheckUtil";
/**
* 判空
*/
public static void checkNull(Object obj) { public static void checkNull(Object obj) {
if (obj == null) throw new IllegalArgumentException("不能传入空对象"); if (obj == null) throw new IllegalArgumentException("不能传入空对象");
} }
@ -51,14 +56,14 @@ public class CheckUtil {
} }
Pattern pattern = Pattern.compile("\\?"); Pattern pattern = Pattern.compile("\\?");
Matcher matcher = pattern.matcher(where); Matcher matcher = pattern.matcher(where);
int count = 0; int count = 0;
while (matcher.find()) { while (matcher.find()) {
count++; count++;
} }
if (count < expression.length - 1){ if (count < expression.length - 1) {
throw new IllegalArgumentException("条件语句的?个数不能小于参数个数"); throw new IllegalArgumentException("条件语句的?个数不能小于参数个数");
} }
if (count > expression.length - 1){ if (count > expression.length - 1) {
throw new IllegalArgumentException("条件语句的?个数不能大于参数个数"); throw new IllegalArgumentException("条件语句的?个数不能大于参数个数");
} }
} }
@ -70,35 +75,75 @@ public class CheckUtil {
if (TextUtils.isEmpty(downloadUrl)) throw new IllegalArgumentException("下载链接不能为null"); if (TextUtils.isEmpty(downloadUrl)) throw new IllegalArgumentException("下载链接不能为null");
} }
/**
* 检测上传地址是否为null
*/
public static void checkUploadPath(String uploadPath) {
if (TextUtils.isEmpty(uploadPath)) throw new IllegalArgumentException("上传地址不能为null");
}
/**
* 检查任务实体
*/
public static void checkTaskEntity(ITaskEntity entity) {
if (entity instanceof DownloadTaskEntity) {
checkDownloadTaskEntity(((DownloadTaskEntity) entity).downloadEntity);
} else if (entity instanceof UploadTaskEntity) {
checkUploadTaskEntity(((UploadTaskEntity) entity).uploadEntity);
}
}
/**
* 检查命令实体
*/
public static void checkCmdEntity(ITaskEntity entity) {
if (entity instanceof DownloadTaskEntity) {
DownloadEntity entity1 = ((DownloadTaskEntity) entity).downloadEntity;
if (entity1 == null) {
throw new NullPointerException("下载实体不能为空");
} else if (TextUtils.isEmpty(entity1.getDownloadUrl())) {
throw new IllegalArgumentException("下载链接不能为空");
} else if (TextUtils.isEmpty(entity1.getDownloadPath())) {
throw new IllegalArgumentException("保存路径不能为空");
}
} else if (entity instanceof UploadTaskEntity) {
UploadEntity entity1 = ((UploadTaskEntity) entity).uploadEntity;
if (entity1 == null) {
throw new NullPointerException("上传实体不能为空");
} else if (TextUtils.isEmpty(entity1.getFilePath())) {
throw new IllegalArgumentException("上传文件路径不能为空");
}
}
}
/**
* 检查上传实体是否合法
*/
public static void checkUploadTaskEntity(UploadEntity entity) {
if (entity == null) {
throw new NullPointerException("上传实体不能为空");
} else if (TextUtils.isEmpty(entity.getFilePath())) {
throw new IllegalArgumentException("上传文件路径不能为空");
} else if (TextUtils.isEmpty(entity.getFileName())) {
throw new IllegalArgumentException("上传文件名不能为空");
}
}
/** /**
* 检测下载实体是否合法 * 检测下载实体是否合法
* 合法(true)
* *
* @param entity 下载实体 * @param entity 下载实体
* @return 合法(true)
*/ */
public static boolean checkDownloadEntity(DownloadEntity entity) { public static void checkDownloadTaskEntity(DownloadEntity entity) {
if (entity == null) { if (entity == null) {
Log.w(TAG, "下载实体不能为空"); throw new NullPointerException("下载实体不能为空");
return false;
} else if (TextUtils.isEmpty(entity.getDownloadUrl())) { } else if (TextUtils.isEmpty(entity.getDownloadUrl())) {
Log.w(TAG, "下载链接不能为空"); throw new IllegalArgumentException("下载链接不能为空");
return false;
} else if (TextUtils.isEmpty(entity.getFileName())) { } else if (TextUtils.isEmpty(entity.getFileName())) {
//Log.w(TAG, "文件名不能为空");
throw new FileException("文件名不能为null"); throw new FileException("文件名不能为null");
} else if (TextUtils.isEmpty(entity.getDownloadPath())) { } else if (TextUtils.isEmpty(entity.getDownloadPath())) {
throw new FileException("文件保存路径不能为null"); throw new FileException("文件保存路径不能为null");
} }
String fileName = entity.getFileName();
if (fileName.contains(" ")) {
fileName = fileName.replace(" ", "_");
}
String dPath = entity.getDownloadPath();
File file = new File(dPath);
if (file.isDirectory()) {
dPath += fileName;
entity.setDownloadPath(dPath);
}
return true;
} }
} }

@ -22,8 +22,8 @@ import android.content.SharedPreferences;
import android.net.Uri; import android.net.Uri;
import android.util.Log; import android.util.Log;
import com.arialyy.aria.core.command.CmdFactory; import com.arialyy.aria.core.command.CmdFactory;
import com.arialyy.aria.core.DownloadEntity; import com.arialyy.aria.core.command.AbsCmd;
import com.arialyy.aria.core.command.IDownloadCmd; import com.arialyy.aria.core.inf.ITaskEntity;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -40,21 +40,17 @@ import java.util.Properties;
public class CommonUtil { public class CommonUtil {
private static final String TAG = "util"; private static final String TAG = "util";
public static IDownloadCmd createCmd(String target, DownloadEntity entity, int cmd) { public static <T extends ITaskEntity> AbsCmd createCmd(String target, T entity, int cmd) {
return CmdFactory.getInstance().createCmd(target, entity, cmd); return CmdFactory.getInstance().createCmd(target, entity, cmd);
} }
public static IDownloadCmd createCmd(DownloadEntity entity, int cmd) {
return CmdFactory.getInstance().createCmd(entity, cmd);
}
/** /**
* 创建隐性的Intent * 创建隐性的Intent
*/ */
public static Intent createIntent(String packageName, String action) { public static Intent createIntent(String packageName, String action) {
Uri.Builder builder = new Uri.Builder(); Uri.Builder builder = new Uri.Builder();
builder.scheme(packageName); builder.scheme(packageName);
Uri uri = builder.build(); Uri uri = builder.build();
Intent intent = new Intent(action); Intent intent = new Intent(action);
intent.setData(uri); intent.setData(uri);
return intent; return intent;
@ -69,7 +65,7 @@ public class CommonUtil {
* @return 成功标志 * @return 成功标志
*/ */
public static Boolean putString(String preName, Context context, String key, String value) { public static Boolean putString(String preName, Context context, String key, String value) {
SharedPreferences pre = context.getSharedPreferences(preName, Context.MODE_PRIVATE); SharedPreferences pre = context.getSharedPreferences(preName, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = pre.edit(); SharedPreferences.Editor editor = pre.edit();
editor.putString(key, value); editor.putString(key, value);
return editor.commit(); return editor.commit();
@ -302,9 +298,11 @@ public class CommonUtil {
* 读取下载配置文件 * 读取下载配置文件
*/ */
public static Properties loadConfig(File file) { public static Properties loadConfig(File file) {
Properties properties = new Properties(); Properties properties = new Properties();
FileInputStream fis = null; FileInputStream fis = null;
if (!file.exists()) {
createFile(file.getPath());
}
try { try {
fis = new FileInputStream(file); fis = new FileInputStream(file);
properties.load(fis); properties.load(fis);

@ -16,7 +16,7 @@
package com.arialyy.aria.util; package com.arialyy.aria.util;
import android.util.Log; import android.util.Log;
import com.arialyy.aria.core.DownloadManager; import com.arialyy.aria.core.AriaManager;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Map; import java.util.Map;
@ -29,33 +29,38 @@ import java.util.WeakHashMap;
* 信息配置 * 信息配置
*/ */
public class Configuration { public class Configuration {
private static final String TAG = "Configuration"; private static final String TAG = "Configuration";
private static final String CONFIG_FILE = "/Aria/ADConfig.properties"; private static final String CONFIG_FILE = "/Aria/ADConfig.properties";
/** /**
* 当前调度器最大下载数默认最大下载数为 2 * 当前调度器最大下载数默认最大下载数为 2
*/ */
private static final String DOWNLOAD_NUM = "DOWNLOAD_NUM"; private static final String DOWNLOAD_NUM = "DOWNLOAD_NUM";
/** /**
* 失败重试次数默认最多重试 10 * 失败重试次数默认最多重试 10
*/ */
private static final String RE_TRY_NUM = "RE_TRY_NUM"; private static final String RE_TRY_NUM = "RE_TRY_NUM";
/** /**
* 是否打开下载广播默认 false * 是否打开下载广播默认 false
*/ */
private static final String OPEN_BROADCAST = "OPEN_BROADCAST"; private static final String OPEN_BROADCAST = "OPEN_BROADCAST";
/** /**
* 失败重试间隔时间默认 4000 ms * 失败重试间隔时间默认 4000 ms
*/ */
private static final String RE_TRY_INTERVAL = "RE_TRY_INTERVAL"; private static final String RE_TRY_INTERVAL = "RE_TRY_INTERVAL";
/** /**
* 超时时间默认 10000 ms * 超时时间默认 10000 ms
*/ */
private static final String DOWNLOAD_TIME_OUT = "DOWNLOAD_TIME_OUT"; private static final String DOWNLOAD_TIME_OUT = "DOWNLOAD_TIME_OUT";
/**
* 设置最大速度
*/
private static final String MAX_SPEED = "MAX_SPEED";
public static boolean isOpenBreadCast = false; public static boolean isOpenBreadCast = false;
private static Configuration INSTANCE = null; private static Configuration INSTANCE = null;
private File mConfigFile = null; private File mConfigFile = null;
private static final Object LOCK = new Object(); private static final Object LOCK = new Object();
public static Configuration getInstance() { public static Configuration getInstance() {
if (INSTANCE == null) { if (INSTANCE == null) {
@ -67,13 +72,13 @@ public class Configuration {
} }
private Configuration() { private Configuration() {
mConfigFile = new File(DownloadManager.APP.getFilesDir().getPath() + CONFIG_FILE); mConfigFile = new File(AriaManager.APP.getFilesDir().getPath() + CONFIG_FILE);
try { try {
if (!mConfigFile.exists()) { if (!mConfigFile.exists()) {
mConfigFile.getParentFile().mkdirs(); mConfigFile.getParentFile().mkdirs();
mConfigFile.createNewFile(); mConfigFile.createNewFile();
init(); init();
}else { } else {
isOpenBreadCast = isOpenBroadcast(); isOpenBreadCast = isOpenBroadcast();
} }
} catch (IOException e) { } catch (IOException e) {
@ -88,6 +93,7 @@ public class Configuration {
config.put(OPEN_BROADCAST, false + ""); config.put(OPEN_BROADCAST, false + "");
config.put(RE_TRY_INTERVAL, 4000 + ""); config.put(RE_TRY_INTERVAL, 4000 + "");
config.put(DOWNLOAD_TIME_OUT, 10000 + ""); config.put(DOWNLOAD_TIME_OUT, 10000 + "");
config.put(MAX_SPEED, 64 + "");
saveConfig(config); saveConfig(config);
} }
@ -95,8 +101,8 @@ public class Configuration {
if (config == null || config.size() == 0) { if (config == null || config.size() == 0) {
return; return;
} }
Properties properties = CommonUtil.loadConfig(mConfigFile); Properties properties = CommonUtil.loadConfig(mConfigFile);
Set<String> keys = config.keySet(); Set<String> keys = config.keySet();
for (String key : keys) { for (String key : keys) {
properties.setProperty(key, config.get(key)); properties.setProperty(key, config.get(key));
} }
@ -109,6 +115,20 @@ public class Configuration {
saveConfig(map); saveConfig(map);
} }
/**
* 设置最大下载速度
*/
public void setMaxSpeed(Speed speed) {
save(MAX_SPEED, speed.buf + "");
}
/**
* 获取最大速度
*/
public int getMaxSpeed() {
return Integer.parseInt(CommonUtil.loadConfig(mConfigFile).getProperty(MAX_SPEED, "8192"));
}
/** /**
* 获取下载超时时间 * 获取下载超时时间
* *

@ -0,0 +1,119 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.util;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import com.arialyy.aria.window.FileEntity;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Aria.Lao on 2017/3/21.
*/
public class FileUtil {
Context mContext;
public FileUtil(Context context) {
mContext = context;
}
/**
* 文件列表
*/
public List<FileEntity> loadFiles(String path) {
File file = new File(path);
File[] files = file.listFiles();
List<FileEntity> list = new ArrayList<>();
for (File f : files) {
FileEntity entity = new FileEntity();
entity.fileName = f.getName();
//entity.fileInfo = getFileType(f.getPath());
//entity.fileDrawable = getApkIcon(mContext, f.getPath());
list.add(entity);
}
return list;
}
/**
* 获取文件类型
*/
public FileType getFileType(String path) {
String exName = getExName(path);
String type = "";
FileType fType = null;
if (exName.equalsIgnoreCase("apk")) {
fType = new FileType("应用", getApkIcon(path));
} else if (exName.equalsIgnoreCase("img")
|| exName.equalsIgnoreCase("png")
|| exName.equalsIgnoreCase("jpg")
|| exName.equalsIgnoreCase("jepg")) {
//fType = new FileType("图片", )
} else if (exName.equalsIgnoreCase("mp3") || exName.equalsIgnoreCase("wm")) {
//fType = new FileType("音乐", );
} else if (exName.equalsIgnoreCase("mp4")
|| exName.equalsIgnoreCase("rm")
|| exName.equalsIgnoreCase("rmvb")) {
//fType = new FileType("视频", );
}
return fType;
}
/**
* 获取扩展名
*/
public String getExName(String path) {
int separatorIndex = path.lastIndexOf(".");
return (separatorIndex < 0) ? path : path.substring(separatorIndex + 1, path.length());
}
/**
* 获取apk文件的icon
*
* @param path apk文件路径
*/
public Drawable getApkIcon(String path) {
PackageManager pm = mContext.getPackageManager();
PackageInfo info = pm.getPackageArchiveInfo(path, PackageManager.GET_ACTIVITIES);
if (info != null) {
ApplicationInfo appInfo = info.applicationInfo;
//android有bug,需要下面这两句话来修复才能获取apk图片
appInfo.sourceDir = path;
appInfo.publicSourceDir = path;
// String packageName = appInfo.packageName; //得到安装包名称
// String version=info.versionName; //得到版本信息
return pm.getApplicationIcon(appInfo);
}
return null;
}
class FileType {
String name;
Drawable icon;
public FileType(String name, Drawable icon) {
this.name = name;
this.icon = icon;
}
}
}

@ -14,7 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.util; package com.arialyy.aria.util;
import android.os.Environment; import android.os.Environment;

@ -16,10 +16,7 @@
package com.arialyy.aria.util; package com.arialyy.aria.util;
import android.text.TextUtils; import android.text.TextUtils;
import com.arialyy.aria.core.DownloadManager; import com.arialyy.aria.core.AriaManager;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.security.KeyManagementException; import java.security.KeyManagementException;
@ -42,8 +39,8 @@ import javax.net.ssl.X509TrustManager;
/** /**
* Created by Aria.Lao on 2017/1/11. * Created by Aria.Lao on 2017/1/11.
* SSL证书工具
*/ */
public class SSLContextUtil { public class SSLContextUtil {
/** /**
@ -61,7 +58,7 @@ public class SSLContextUtil {
CertificateFactory cf = null; CertificateFactory cf = null;
try { try {
cf = CertificateFactory.getInstance("X.509"); cf = CertificateFactory.getInstance("X.509");
InputStream caInput = DownloadManager.APP.getAssets().open(caPath); InputStream caInput = AriaManager.APP.getAssets().open(caPath);
Certificate ca; Certificate ca;
ca = cf.generateCertificate(caInput); ca = cf.generateCertificate(caInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN()); System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());

@ -0,0 +1,44 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.util;
/**
* Created by Aria.Lao on 2017/3/6.
*/
public enum Speed {
/**
* 最大速度为256kb
*/
KB_256(64), /**
* 最大速度为512kb
*/
KB_512(128), /**
* 最大速度为1mb
*/
MB_1(256), /**
* 最大速度为2mb
*/
MB_2(1024), /**
* 最大速度为10mb
*/
MAX(8192);
int buf;
Speed(int buf) {
this.buf = buf;
}
}

@ -47,467 +47,451 @@ import java.util.concurrent.locks.ReentrantLock;
* *
* Created by Dmytro Voronkevych on 17/06/2014. * Created by Dmytro Voronkevych on 17/06/2014.
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused") public class WeakHandler {
public class WeakHandler { private final Handler.Callback mCallback;
private final Handler.Callback mCallback; // hard reference to Callback. We need to keep callback in memory // hard reference to Callback. We need to keep callback in memory
private final ExecHandler mExec; private final ExecHandler mExec;
private Lock mLock = new ReentrantLock(); private Lock mLock = new ReentrantLock();
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions") @VisibleForTesting final ChainedRef mRunnables =
@VisibleForTesting new ChainedRef(mLock, null);
final ChainedRef mRunnables = new ChainedRef(mLock, null);
/**
/** * Default constructor associates this handler with the {@link Looper} for the
* Default constructor associates this handler with the {@link Looper} for the * current thread.
* current thread. *
* * If this thread does not have a looper, this handler won't be able to receive messages
* If this thread does not have a looper, this handler won't be able to receive messages * so an exception is thrown.
* so an exception is thrown. */
*/ public WeakHandler() {
public WeakHandler() { mCallback = null;
mCallback = null; mExec = new ExecHandler();
mExec = new ExecHandler(); }
/**
* Constructor associates this handler with the {@link Looper} for the
* current thread and takes a callback interface in which you can handle
* messages.
*
* If this thread does not have a looper, this handler won't be able to receive messages
* so an exception is thrown.
*
* @param callback The callback interface in which to handle messages, or null.
*/
public WeakHandler(@Nullable Handler.Callback callback) {
mCallback = callback; // Hard referencing body
mExec = new ExecHandler(new WeakReference<>(callback)); // Weak referencing inside ExecHandler
}
/**
* Use the provided {@link Looper} instead of the default one.
*
* @param looper The looper, must not be null.
*/
public WeakHandler(@NonNull Looper looper) {
mCallback = null;
mExec = new ExecHandler(looper);
}
/**
* Use the provided {@link Looper} instead of the default one and take a callback
* interface in which to handle messages.
*
* @param looper The looper, must not be null.
* @param callback The callback interface in which to handle messages, or null.
*/
public WeakHandler(@NonNull Looper looper, @NonNull Handler.Callback callback) {
mCallback = callback;
mExec = new ExecHandler(looper, new WeakReference<>(callback));
}
/**
* Causes the Runnable r to be added to the message queue.
* The runnable will be run on the thread to which this handler is
* attached.
*
* @param r The Runnable that will be executed.
* @return Returns true if the Runnable was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public final boolean post(@NonNull Runnable r) {
return mExec.post(wrapRunnable(r));
}
/**
* Causes the Runnable r to be added to the message queue, to be run
* at a specific time given by <var>uptimeMillis</var>.
* <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
* The runnable will be run on the thread to which this handler is attached.
*
* @param r The Runnable that will be executed.
* @param uptimeMillis The absolute time at which the callback should run,
* using the {@link android.os.SystemClock#uptimeMillis} time-base.
* @return Returns true if the Runnable was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the Runnable will be processed -- if
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis) {
return mExec.postAtTime(wrapRunnable(r), uptimeMillis);
}
/**
* Causes the Runnable r to be added to the message queue, to be run
* at a specific time given by <var>uptimeMillis</var>.
* <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
* The runnable will be run on the thread to which this handler is attached.
*
* @param r The Runnable that will be executed.
* @param uptimeMillis The absolute time at which the callback should run,
* using the {@link android.os.SystemClock#uptimeMillis} time-base.
* @return Returns true if the Runnable was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the Runnable will be processed -- if
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
* @see android.os.SystemClock#uptimeMillis
*/
public final boolean postAtTime(Runnable r, Object token, long uptimeMillis) {
return mExec.postAtTime(wrapRunnable(r), token, uptimeMillis);
}
/**
* Causes the Runnable r to be added to the message queue, to be run
* after the specified amount of time elapses.
* The runnable will be run on the thread to which this handler
* is attached.
*
* @param r The Runnable that will be executed.
* @param delayMillis The delay (in milliseconds) until the Runnable
* will be executed.
* @return Returns true if the Runnable was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the Runnable will be processed --
* if the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
public final boolean postDelayed(Runnable r, long delayMillis) {
return mExec.postDelayed(wrapRunnable(r), delayMillis);
}
/**
* Posts a message to an object that implements Runnable.
* Causes the Runnable r to executed on the next iteration through the
* message queue. The runnable will be run on the thread to which this
* handler is attached.
* <b>This method is only for use in very special circumstances -- it
* can easily starve the message queue, cause ordering problems, or have
* other unexpected side-effects.</b>
*
* @param r The Runnable that will be executed.
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public final boolean postAtFrontOfQueue(Runnable r) {
return mExec.postAtFrontOfQueue(wrapRunnable(r));
}
/**
* Remove any pending posts of Runnable r that are in the message queue.
*/
public final void removeCallbacks(Runnable r) {
final WeakRunnable runnable = mRunnables.remove(r);
if (runnable != null) {
mExec.removeCallbacks(runnable);
} }
}
/**
* Constructor associates this handler with the {@link Looper} for the /**
* current thread and takes a callback interface in which you can handle * Remove any pending posts of Runnable <var>r</var> with Object
* messages. * <var>token</var> that are in the message queue. If <var>token</var> is null,
* * all callbacks will be removed.
* If this thread does not have a looper, this handler won't be able to receive messages */
* so an exception is thrown. public final void removeCallbacks(Runnable r, Object token) {
* final WeakRunnable runnable = mRunnables.remove(r);
* @param callback The callback interface in which to handle messages, or null. if (runnable != null) {
*/ mExec.removeCallbacks(runnable, token);
public WeakHandler(@Nullable Handler.Callback callback) {
mCallback = callback; // Hard referencing body
mExec = new ExecHandler(new WeakReference<>(callback)); // Weak referencing inside ExecHandler
}
/**
* Use the provided {@link Looper} instead of the default one.
*
* @param looper The looper, must not be null.
*/
public WeakHandler(@NonNull Looper looper) {
mCallback = null;
mExec = new ExecHandler(looper);
} }
}
/**
* Use the provided {@link Looper} instead of the default one and take a callback /**
* interface in which to handle messages. * Pushes a message onto the end of the message queue after all pending messages
* * before the current time. It will be received in callback,
* @param looper The looper, must not be null. * in the thread attached to this handler.
* @param callback The callback interface in which to handle messages, or null. *
*/ * @return Returns true if the message was successfully placed in to the
public WeakHandler(@NonNull Looper looper, @NonNull Handler.Callback callback) { * message queue. Returns false on failure, usually because the
mCallback = callback; * looper processing the message queue is exiting.
mExec = new ExecHandler(looper, new WeakReference<>(callback)); */
} public final boolean sendMessage(Message msg) {
return mExec.sendMessage(msg);
/** }
* Causes the Runnable r to be added to the message queue.
* The runnable will be run on the thread to which this handler is /**
* attached. * Sends a Message containing only the what value.
* *
* @param r The Runnable that will be executed. * @return Returns true if the message was successfully placed in to the
* * message queue. Returns false on failure, usually because the
* @return Returns true if the Runnable was successfully placed in to the * looper processing the message queue is exiting.
* message queue. Returns false on failure, usually because the */
* looper processing the message queue is exiting. public final boolean sendEmptyMessage(int what) {
*/ return mExec.sendEmptyMessage(what);
public final boolean post(@NonNull Runnable r) { }
return mExec.post(wrapRunnable(r));
/**
* Sends a Message containing only the what value, to be delivered
* after the specified amount of time elapses.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
* @see #sendMessageDelayed(android.os.Message, long)
*/
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
return mExec.sendEmptyMessageDelayed(what, delayMillis);
}
/**
* Sends a Message containing only the what value, to be delivered
* at a specific time.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
* @see #sendMessageAtTime(android.os.Message, long)
*/
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
return mExec.sendEmptyMessageAtTime(what, uptimeMillis);
}
/**
* Enqueue a message into the message queue after all pending messages
* before (current time + delayMillis). You will receive it in
* callback, in the thread attached to this handler.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the message will be processed -- if
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
public final boolean sendMessageDelayed(Message msg, long delayMillis) {
return mExec.sendMessageDelayed(msg, delayMillis);
}
/**
* Enqueue a message into the message queue after all pending messages
* before the absolute time (in milliseconds) <var>uptimeMillis</var>.
* <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
* You will receive it in callback, in the thread attached
* to this handler.
*
* @param uptimeMillis The absolute time at which the message should be
* delivered, using the
* {@link android.os.SystemClock#uptimeMillis} time-base.
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the message will be processed -- if
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
return mExec.sendMessageAtTime(msg, uptimeMillis);
}
/**
* Enqueue a message at the front of the message queue, to be processed on
* the next iteration of the message loop. You will receive it in
* callback, in the thread attached to this handler.
* <b>This method is only for use in very special circumstances -- it
* can easily starve the message queue, cause ordering problems, or have
* other unexpected side-effects.</b>
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public final boolean sendMessageAtFrontOfQueue(Message msg) {
return mExec.sendMessageAtFrontOfQueue(msg);
}
/**
* Remove any pending posts of messages with code 'what' that are in the
* message queue.
*/
public final void removeMessages(int what) {
mExec.removeMessages(what);
}
/**
* Remove any pending posts of messages with code 'what' and whose obj is
* 'object' that are in the message queue. If <var>object</var> is null,
* all messages will be removed.
*/
public final void removeMessages(int what, Object object) {
mExec.removeMessages(what, object);
}
/**
* Remove any pending posts of callbacks and sent messages whose
* <var>obj</var> is <var>token</var>. If <var>token</var> is null,
* all callbacks and messages will be removed.
*/
public final void removeCallbacksAndMessages(Object token) {
mExec.removeCallbacksAndMessages(token);
}
/**
* Check if there are any pending posts of messages with code 'what' in
* the message queue.
*/
public final boolean hasMessages(int what) {
return mExec.hasMessages(what);
}
/**
* Check if there are any pending posts of messages with code 'what' and
* whose obj is 'object' in the message queue.
*/
public final boolean hasMessages(int what, Object object) {
return mExec.hasMessages(what, object);
}
public final Looper getLooper() {
return mExec.getLooper();
}
private WeakRunnable wrapRunnable(@NonNull Runnable r) {
//noinspection ConstantConditions
if (r == null) {
throw new NullPointerException("Runnable can't be null");
} }
final ChainedRef hardRef = new ChainedRef(mLock, r);
mRunnables.insertAfter(hardRef);
return hardRef.wrapper;
}
/** private static class ExecHandler extends Handler {
* Causes the Runnable r to be added to the message queue, to be run private final WeakReference<Handler.Callback> mCallback;
* at a specific time given by <var>uptimeMillis</var>.
* <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
* The runnable will be run on the thread to which this handler is attached.
*
* @param r The Runnable that will be executed.
* @param uptimeMillis The absolute time at which the callback should run,
* using the {@link android.os.SystemClock#uptimeMillis} time-base.
*
* @return Returns true if the Runnable was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the Runnable will be processed -- if
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis) {
return mExec.postAtTime(wrapRunnable(r), uptimeMillis);
}
/** ExecHandler() {
* Causes the Runnable r to be added to the message queue, to be run mCallback = null;
* at a specific time given by <var>uptimeMillis</var>.
* <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
* The runnable will be run on the thread to which this handler is attached.
*
* @param r The Runnable that will be executed.
* @param uptimeMillis The absolute time at which the callback should run,
* using the {@link android.os.SystemClock#uptimeMillis} time-base.
*
* @return Returns true if the Runnable was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the Runnable will be processed -- if
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*
* @see android.os.SystemClock#uptimeMillis
*/
public final boolean postAtTime(Runnable r, Object token, long uptimeMillis) {
return mExec.postAtTime(wrapRunnable(r), token, uptimeMillis);
} }
/** ExecHandler(WeakReference<Handler.Callback> callback) {
* Causes the Runnable r to be added to the message queue, to be run mCallback = callback;
* after the specified amount of time elapses.
* The runnable will be run on the thread to which this handler
* is attached.
*
* @param r The Runnable that will be executed.
* @param delayMillis The delay (in milliseconds) until the Runnable
* will be executed.
*
* @return Returns true if the Runnable was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the Runnable will be processed --
* if the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
public final boolean postDelayed(Runnable r, long delayMillis) {
return mExec.postDelayed(wrapRunnable(r), delayMillis);
} }
/** ExecHandler(Looper looper) {
* Posts a message to an object that implements Runnable. super(looper);
* Causes the Runnable r to executed on the next iteration through the mCallback = null;
* message queue. The runnable will be run on the thread to which this
* handler is attached.
* <b>This method is only for use in very special circumstances -- it
* can easily starve the message queue, cause ordering problems, or have
* other unexpected side-effects.</b>
*
* @param r The Runnable that will be executed.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public final boolean postAtFrontOfQueue(Runnable r) {
return mExec.postAtFrontOfQueue(wrapRunnable(r));
} }
/** ExecHandler(Looper looper, WeakReference<Handler.Callback> callback) {
* Remove any pending posts of Runnable r that are in the message queue. super(looper);
*/ mCallback = callback;
public final void removeCallbacks(Runnable r) {
final WeakRunnable runnable = mRunnables.remove(r);
if (runnable != null) {
mExec.removeCallbacks(runnable);
}
} }
/** @Override public void handleMessage(@NonNull Message msg) {
* Remove any pending posts of Runnable <var>r</var> with Object if (mCallback == null) {
* <var>token</var> that are in the message queue. If <var>token</var> is null, return;
* all callbacks will be removed. }
*/ final Handler.Callback callback = mCallback.get();
public final void removeCallbacks(Runnable r, Object token) { if (callback == null) { // Already disposed
final WeakRunnable runnable = mRunnables.remove(r); return;
if (runnable != null) { }
mExec.removeCallbacks(runnable, token); callback.handleMessage(msg);
}
} }
}
/** static class WeakRunnable implements Runnable {
* Pushes a message onto the end of the message queue after all pending messages private final WeakReference<Runnable> mDelegate;
* before the current time. It will be received in callback, private final WeakReference<ChainedRef> mReference;
* in the thread attached to this handler.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public final boolean sendMessage(Message msg) {
return mExec.sendMessage(msg);
}
/** WeakRunnable(WeakReference<Runnable> delegate, WeakReference<ChainedRef> reference) {
* Sends a Message containing only the what value. mDelegate = delegate;
* mReference = reference;
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public final boolean sendEmptyMessage(int what) {
return mExec.sendEmptyMessage(what);
} }
/** @Override public void run() {
* Sends a Message containing only the what value, to be delivered final Runnable delegate = mDelegate.get();
* after the specified amount of time elapses. final ChainedRef reference = mReference.get();
* @see #sendMessageDelayed(android.os.Message, long) if (reference != null) {
* reference.remove();
* @return Returns true if the message was successfully placed in to the }
* message queue. Returns false on failure, usually because the if (delegate != null) {
* looper processing the message queue is exiting. delegate.run();
*/ }
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
return mExec.sendEmptyMessageDelayed(what, delayMillis);
} }
}
/** static class ChainedRef {
* Sends a Message containing only the what value, to be delivered @Nullable ChainedRef next;
* at a specific time. @Nullable ChainedRef prev;
* @see #sendMessageAtTime(android.os.Message, long) @NonNull final Runnable runnable;
* @NonNull final WeakRunnable wrapper;
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
return mExec.sendEmptyMessageAtTime(what, uptimeMillis);
}
/** @NonNull Lock lock;
* Enqueue a message into the message queue after all pending messages
* before (current time + delayMillis). You will receive it in
* callback, in the thread attached to this handler.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the message will be processed -- if
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
public final boolean sendMessageDelayed(Message msg, long delayMillis) {
return mExec.sendMessageDelayed(msg, delayMillis);
}
/** public ChainedRef(@NonNull Lock lock, @NonNull Runnable r) {
* Enqueue a message into the message queue after all pending messages this.runnable = r;
* before the absolute time (in milliseconds) <var>uptimeMillis</var>. this.lock = lock;
* <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b> this.wrapper = new WeakRunnable(new WeakReference<>(r), new WeakReference<>(this));
* You will receive it in callback, in the thread attached
* to this handler.
*
* @param uptimeMillis The absolute time at which the message should be
* delivered, using the
* {@link android.os.SystemClock#uptimeMillis} time-base.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the message will be processed -- if
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
return mExec.sendMessageAtTime(msg, uptimeMillis);
} }
/** public WeakRunnable remove() {
* Enqueue a message at the front of the message queue, to be processed on lock.lock();
* the next iteration of the message loop. You will receive it in try {
* callback, in the thread attached to this handler. if (prev != null) {
* <b>This method is only for use in very special circumstances -- it prev.next = next;
* can easily starve the message queue, cause ordering problems, or have
* other unexpected side-effects.</b>
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public final boolean sendMessageAtFrontOfQueue(Message msg) {
return mExec.sendMessageAtFrontOfQueue(msg);
}
/**
* Remove any pending posts of messages with code 'what' that are in the
* message queue.
*/
public final void removeMessages(int what) {
mExec.removeMessages(what);
}
/**
* Remove any pending posts of messages with code 'what' and whose obj is
* 'object' that are in the message queue. If <var>object</var> is null,
* all messages will be removed.
*/
public final void removeMessages(int what, Object object) {
mExec.removeMessages(what, object);
}
/**
* Remove any pending posts of callbacks and sent messages whose
* <var>obj</var> is <var>token</var>. If <var>token</var> is null,
* all callbacks and messages will be removed.
*/
public final void removeCallbacksAndMessages(Object token) {
mExec.removeCallbacksAndMessages(token);
}
/**
* Check if there are any pending posts of messages with code 'what' in
* the message queue.
*/
public final boolean hasMessages(int what) {
return mExec.hasMessages(what);
}
/**
* Check if there are any pending posts of messages with code 'what' and
* whose obj is 'object' in the message queue.
*/
public final boolean hasMessages(int what, Object object) {
return mExec.hasMessages(what, object);
}
public final Looper getLooper() {
return mExec.getLooper();
}
private WeakRunnable wrapRunnable(@NonNull Runnable r) {
//noinspection ConstantConditions
if (r == null) {
throw new NullPointerException("Runnable can't be null");
}
final ChainedRef hardRef = new ChainedRef(mLock, r);
mRunnables.insertAfter(hardRef);
return hardRef.wrapper;
}
private static class ExecHandler extends Handler {
private final WeakReference<Handler.Callback> mCallback;
ExecHandler() {
mCallback = null;
}
ExecHandler(WeakReference<Handler.Callback> callback) {
mCallback = callback;
}
ExecHandler(Looper looper) {
super(looper);
mCallback = null;
} }
if (next != null) {
ExecHandler(Looper looper, WeakReference<Handler.Callback> callback) { next.prev = prev;
super(looper);
mCallback = callback;
}
@Override
public void handleMessage(@NonNull Message msg) {
if (mCallback == null) {
return;
}
final Handler.Callback callback = mCallback.get();
if (callback == null) { // Already disposed
return;
}
callback.handleMessage(msg);
} }
prev = null;
next = null;
} finally {
lock.unlock();
}
return wrapper;
} }
static class WeakRunnable implements Runnable { public void insertAfter(@NonNull ChainedRef candidate) {
private final WeakReference<Runnable> mDelegate; lock.lock();
private final WeakReference<ChainedRef> mReference; try {
if (this.next != null) {
WeakRunnable(WeakReference<Runnable> delegate, WeakReference<ChainedRef> reference) { this.next.prev = candidate;
mDelegate = delegate;
mReference = reference;
} }
@Override candidate.next = this.next;
public void run() { this.next = candidate;
final Runnable delegate = mDelegate.get(); candidate.prev = this;
final ChainedRef reference = mReference.get(); } finally {
if (reference != null) { lock.unlock();
reference.remove(); }
}
if (delegate != null) {
delegate.run();
}
}
} }
static class ChainedRef { @Nullable public WeakRunnable remove(Runnable obj) {
@Nullable lock.lock();
ChainedRef next; try {
@Nullable ChainedRef curr = this.next; // Skipping head
ChainedRef prev; while (curr != null) {
@NonNull if (curr.runnable == obj) { // We do comparison exactly how Handler does inside
final Runnable runnable; return curr.remove();
@NonNull }
final WeakRunnable wrapper; curr = curr.next;
@NonNull
Lock lock;
public ChainedRef(@NonNull Lock lock, @NonNull Runnable r) {
this.runnable = r;
this.lock = lock;
this.wrapper = new WeakRunnable(new WeakReference<>(r), new WeakReference<>(this));
}
public WeakRunnable remove() {
lock.lock();
try {
if (prev != null) {
prev.next = next;
}
if (next != null) {
next.prev = prev;
}
prev = null;
next = null;
} finally {
lock.unlock();
}
return wrapper;
}
public void insertAfter(@NonNull ChainedRef candidate) {
lock.lock();
try {
if (this.next != null) {
this.next.prev = candidate;
}
candidate.next = this.next;
this.next = candidate;
candidate.prev = this;
} finally {
lock.unlock();
}
}
@Nullable
public WeakRunnable remove(Runnable obj) {
lock.lock();
try {
ChainedRef curr = this.next; // Skipping head
while (curr != null) {
if (curr.runnable == obj) { // We do comparison exactly how Handler does inside
return curr.remove();
}
curr = curr.next;
}
} finally {
lock.unlock();
}
return null;
} }
} finally {
lock.unlock();
}
return null;
} }
}
} }

@ -0,0 +1,67 @@
/*
* 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.window;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.widget.AbsListView;
import android.widget.ListView;
import com.arialyy.aria.R;
import com.arialyy.aria.util.FileUtil;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by Aria.Lao on 2017/3/21.
* 文件选择
*/
public class AriaFileChangeActivity extends FragmentActivity {
final String ROOT_PAT = Environment.getExternalStorageDirectory().getPath();
ListView mList;
FileChangeAdapter mAdapter;
Map<String, List<FileEntity>> mData = new HashMap<>();
private String mCurrentPath = ROOT_PAT;
@Override protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_aria_file_shange);
mList = (ListView) findViewById(R.id.list);
mList.setOnScrollListener(new AbsListView.OnScrollListener() {
int state;
@Override public void onScrollStateChanged(AbsListView view, int scrollState) {
state = scrollState;
}
@Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
if (state == AbsListView.OnScrollListener.SCROLL_STATE_IDLE
&& firstVisibleItem + visibleItemCount == totalItemCount) {
loadMore();
}
}
});
}
private void loadMore() {
}
}

@ -0,0 +1,92 @@
/*
* 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.window;
import android.content.Context;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import com.arialyy.aria.R;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Aria.Lao on 2017/3/21.
*/
final class FileChangeAdapter extends BaseAdapter {
List<FileEntity> mData = new ArrayList<>();
SparseBooleanArray mCheck = new SparseBooleanArray();
Context mContext;
public FileChangeAdapter(Context context, List<FileEntity> list) {
mContext = context;
mData.addAll(list);
for (int i = 0, len = mData.size(); i < len; i++) {
mCheck.append(i, false);
}
}
@Override public int getCount() {
return mData.size();
}
@Override public Object getItem(int position) {
return null;
}
@Override public long getItemId(int position) {
return 0;
}
@Override public View getView(int position, View convertView, ViewGroup parent) {
FileChangeHolder holder = null;
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.item_file, null);
holder = new FileChangeHolder(convertView);
convertView.setTag(holder);
} else {
holder = (FileChangeHolder) convertView.getTag();
}
holder.checkBox.setChecked(mCheck.get(position, false));
return convertView;
}
public void setCheck(int position, boolean check) {
if (position >= mData.size()) return;
mCheck.put(position, check);
notifyDataSetChanged();
}
private static class FileChangeHolder {
TextView title, info;
ImageView icon;
CheckBox checkBox;
FileChangeHolder(View view) {
title = (TextView) view.findViewById(R.id.title);
info = (TextView) view.findViewById(R.id.info);
icon = (ImageView) view.findViewById(R.id.icon);
checkBox = (CheckBox) view.findViewById(R.id.checkbox);
}
}
}

@ -0,0 +1,29 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.window;
import android.graphics.drawable.Drawable;
/**
* Created by Aria.Lao on 2017/3/21.
*/
public class FileEntity {
public String fileName;
public String fileInfo;
public int fileIcon;
public Drawable fileDrawable;
}

@ -10,7 +10,9 @@
android:id="@+id/checkbox" android:id="@+id/checkbox"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:clickable="false"
/> />
<ImageView <ImageView
@ -18,8 +20,6 @@
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:layout_toRightOf="@+id/checkbox"
/> />
<TextView <TextView
@ -28,6 +28,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignTop="@+id/img" android:layout_alignTop="@+id/img"
android:layout_marginLeft="10dp" android:layout_marginLeft="10dp"
android:layout_marginRight="5dp"
android:layout_toLeftOf="@+id/checkbox"
android:layout_toRightOf="@+id/img" android:layout_toRightOf="@+id/img"
android:ellipsize="end" android:ellipsize="end"
android:maxLines="1" android:maxLines="1"
@ -41,7 +43,9 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignLeft="@+id/title" android:layout_alignLeft="@+id/title"
android:layout_below="@+id/title" android:layout_below="@+id/title"
android:layout_marginRight="5dp"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:layout_toLeftOf="@+id/checkbox"
/> />
</RelativeLayout> </RelativeLayout>

@ -0,0 +1,40 @@
## 关于Aria,你还需要知道的一些东西
- 设置下载任务数,Aria默认下载任务为**2**
```java
Aria.get(getContext()).setMaxDownloadNum(num);
```
- 停止所有下载
```java
Aria.get(this).stopAllTask();
```
- 设置失败重试次数,从事次数不能少于 1
```java
Aria.get(this).setReTryNum(10);
```
- 设置失败重试间隔,重试间隔不能小于 5000ms
```java
Aria.get(this).setReTryInterval(5000);
```
- 设置是否打开广播,如果你需要在Service后台获取下载完成情况,那么你需要打开Aria广播,[Aria广播配置](https://github.com/AriaLyy/Aria/blob/v_2.0/BroadCast.md)
```java
Aria.get(this).openBroadcast(true);
```
## https证书配置
+ 将你的证书导入`assets`目录
+ 调用以下代码配置ca证书相关信息
```java
/**
* 设置CA证书信息
*
* @param caAlias ca证书别名
* @param caPath assets 文件夹下的ca证书完整路径
*/
Aria.get(this).setCAInfo("caAlias","caPath");
```

@ -1,153 +1,158 @@
# Aria # Aria
![图标](https://github.com/AriaLyy/DownloadUtil/blob/v_2.0/app/src/main/res/mipmap-hdpi/ic_launcher.png)</br> ![图标](https://github.com/AriaLyy/DownloadUtil/blob/v_2.0/app/src/main/res/mipmap-hdpi/ic_launcher.png)</br>
下载不应该是让人感到痛苦的功能,Aria,让下载更简单。</br> Aria,让上传、下载更容易实现</br>
+ Aria有以下特点: + Aria有以下特点:
- 简单 - 简单
- 可在Dialog、popupWindow等组件中使用 - 可在Dialog、popupWindow等组件中使用
- 可自定义是否使用广播
- 支持多线程、多任务下载 - 支持多线程、多任务下载
- 支持任务自动切换 - 支持多任务自动调度
- 支持下载速度直接获取 - 可以直接获取速度
- 支持https地址下载 - 支持https地址下载
- 支持上传操作
[Aria怎样使用?](#使用) Aria怎样使用?
* [下载](#使用)
* [上传](#上传)
如果你觉得Aria对你有帮助,您的star和issues将是对我最大支持.`^_^` 如果你觉得Aria对你有帮助,您的star和issues将是对我最大支持.`^_^`
## 下载 ## 下载
[![Download](https://api.bintray.com/packages/arialyy/maven/Aria/images/download.svg)](https://bintray.com/arialyy/maven/Aria/_latestVersion)</br> [![Download](https://api.bintray.com/packages/arialyy/maven/Aria/images/download.svg)](https://bintray.com/arialyy/maven/Aria/_latestVersion)</br>
```java ```java
compile 'com.arialyy.aria:Aria:2.4.4' compile 'com.arialyy.aria:Aria:3.0.0'
``` ```
## 示例 ## 示例
![多任务下载](https://github.com/AriaLyy/DownloadUtil/blob/v_2.0/img/download_img.gif) ![多任务下载](https://github.com/AriaLyy/DownloadUtil/blob/master/img/download_img.gif)
![Dialog使用](https://github.com/AriaLyy/DownloadUtil/blob/v_2.0/img/dialog_use.gif "") ![上传](https://github.com/AriaLyy/DownloadUtil/blob/master/img/sing_upload.gif)
## 性能 ## 性能
![性能展示](https://github.com/AriaLyy/DownloadUtil/blob/master/img/performance.png) ![性能展示](https://github.com/AriaLyy/DownloadUtil/blob/master/img/performance.png)
*** ***
## 使用 ## 使用
### 一、添加权限 由于Aria涉及到文件和网络的操作,因此需要你在manifest文件中添加以下权限
```xml ```xml
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
``` ```
### 二、只需要以下参数,你便能很简单的使用Aria下载文件了
```java
Aria.whit(this)
.load(DOWNLOAD_URL) //下载地址,必填
.setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk") //文件保存路径,必填
.setDownloadName("test.apk") //文件名,必填
.start();
```
### 三、为了能接收到Aria传递的数据,你需要把你的Activity或fragment注册到Aria管理器中,注册的方式很简单,在onResume
```java
@Override protected void onResume() {
super.onResume();
Aria.whit(this).addSchedulerListener(new MySchedulerListener());
}
```
### 四、通过下载链接,你还能使用Aria执行很多操作,如:
Aria支持https下载,如果你希望使用自己的ca证书,那么你需要进行[Aria https证书配置](#https证书配置)
- 添加任务(不进行下载)
## 使用Aria进行下载
* 添加任务(不进行下载),当其他下载任务完成时,将自动下载等待中的任务
```java ```java
Aria.whit(this).load(DOWNLOAD_URL) Aria.download(this)
.setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk") //文件保存路径,必填 .load(DOWNLOAD_URL)
.setDownloadName("test.apk") //文件名,必填 .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk") //文件保存路径
.add(); .add();
```
- 启动下载
```java
Aria.whit(this).load(DOWNLOAD_URL).start();
``` ```
- 暂停下载
```java * 下载
Aria.whit(this).load(DOWNLOAD_URL).stop();
```
- 恢复下载
```java ```java
Aria.whit(this).load(DOWNLOAD_URL).resume(); Aria.download(this)
.load(DOWNLOAD_URL) //读取下载地址
.setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk") //设置文件保存的完整路径
.start(); //启动下载
``` ```
- 取消下载 * 暂停
```java ```java
Aria.whit(this).load(DOWNLOAD_URL).cancel(); Aria.download(this).load(DOWNLOAD_URL).pause();
``` ```
- 获取当前下载进度 * 恢复下载
```java ```java
Aria.whit(this).load(DOWNLOAD_URL).getCurrentProgress(); Aria.download(this).load(DOWNLOAD_URL).resume();
``` ```
- 获取文件大小 * 取消下载
```java ```java
Aria.whit(this).load(DOWNLOAD_URL).getFileSize(); Aria.download(this).load(DOWNLOAD_URL).cancel();
``` ```
### 五、关于Aria,你还需要知道的一些东西 ### 二、如果你希望读取下载进度或下载信息,那么你需要创建事件类,并在onResume(Activity、Fragment)或构造函数(Dialog、PopupWindow),将该事件类注册到Aria管理器。
- 设置下载任务数,Aria默认下载任务为**2** * 创建事件类
```java ```java
Aria.get(getContext()).setMaxDownloadNum(num); final static class MySchedulerListener extends Aria.DownloadSchedulerListener{
@Override public void onTaskPre(DownloadTask task) {
super.onTaskPre(task);
}
@Override public void onTaskStop(DownloadTask task) {
super.onTaskStop(task);
}
@Override public void onTaskCancel(DownloadTask task) {
super.onTaskCancel(task);
}
@Override public void onTaskRunning(DownloadTask task) {
super.onTaskRunning(task);
}
}
``` ```
- 停止所有下载
```java * 将事件注册到Aria
Aria.get(this).stopAllTask();
```
- 设置失败重试次数,从事次数不能少于 1
```java ```java
Aria.get(this).setReTryNum(10); @Override protected void onResume() {
super.onResume();
Aria.whit(this).addSchedulerListener(new MySchedulerListener());
}
``` ```
- 设置失败重试间隔,重试间隔不能小于 5000ms
```java ### 关于下载的其它api
Aria.get(this).setReTryInterval(5000); [Download API](https://github.com/AriaLyy/Aria/blob/master/DownloadApi.md)
```
- 设置是否打开广播,如果你需要在Service后台获取下载完成情况,那么你需要打开Aria广播,[Aria广播配置](https://github.com/AriaLyy/Aria/blob/v_2.0/BroadCast.md)
```java **tips:为了防止内存泄露的情况,事件类需要使用staic进行修饰**
Aria.get(this).openBroadcast(true);
```
### https证书配置 ## 上传
+ 将你的证书导入`assets`目录 * 添加任务(只添加,不上传)
+ 调用以下代码配置ca证书相关信息
```java ```java
/** Aria.upload(this)
* 设置CA证书信息 .load(filePath) //文件路径
* .setUploadUrl(uploadUrl) //上传路径
* @param caAlias ca证书别名 .setAttachment(fileKey) //服务器读取文件的key
* @param caPath assets 文件夹下的ca证书完整路径 .add();
*/ ```
Aria.get(this).setCAInfo("caAlias","caPath");
```
*** * 上传
## 开发日志 ```java
+ v_2.4.4 修复不支持断点的下载链接拿不到文件大小的问题 Aria.upload(this)
+ v_2.4.3 修复404链接卡顿的问题 .load(filePath) //文件路径
+ v_2.4.2 修复失败重试无效的bug .setUploadUrl(uploadUrl) //上传路径
+ v_2.4.1 修复下载慢的问题,修复application、service 不能使用的问题 .setAttachment(fileKey) //服务器读取文件的key
+ v_2.4.0 支持https链接下载 .start();
+ v_2.3.8 修复数据错乱的bug、添加fragment支持 ```
+ v_2.3.6 添加dialog、popupWindow支持 * 取消上传
+ v_2.3.3 添加断点支持、修改下载逻辑,让使用更加简单、修复一个内存泄露的bug
+ v_2.3.1 重命名为Aria,下载流程简化 ```java
+ v_2.1.1 增加,选择最大下载任务数接口 Aria.upload(this)
.load(filePath)
.cancel();
```
## 其他 ## 其他
有任何问题,可以在[issues](https://github.com/AriaLyy/Aria/issues)给我留言反馈。 有任何问题,可以在[issues](https://github.com/AriaLyy/Aria/issues)给我留言反馈。
***
## 开发日志
+ v_3.0.0 添加上传任务支持,修复一些已发现的bug
+ v_2.4.4 修复不支持断点的下载链接拿不到文件大小的问题
+ v_2.4.3 修复404链接卡顿的问题
+ v_2.4.2 修复失败重试无效的bug
+ v_2.4.1 修复下载慢的问题,修复application、service 不能使用的问题
+ v_2.4.0 支持https链接下载
+ v_2.3.8 修复数据错乱的bug、添加fragment支持
+ v_2.3.6 添加dialog、popupWindow支持
+ v_2.3.3 添加断点支持、修改下载逻辑,让使用更加简单、修复一个内存泄露的bug
+ v_2.3.1 重命名为Aria,下载流程简化
+ v_2.1.1 增加,选择最大下载任务数接口
License License
------- -------

@ -13,7 +13,6 @@
android:label="@string/app_name" android:label="@string/app_name"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme.NoActionBar"> android:theme="@style/AppTheme.NoActionBar">
<!--android:name=".activity.SingleTaskActivity"-->
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:label="@string/app_name"> android:label="@string/app_name">
@ -24,10 +23,14 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".single_task.SingleTaskActivity"/> <activity android:name=".download.DownloadActivity"/>
<activity android:name=".multi_task.MultiTaskActivity"/> <activity android:name=".upload.UploadActivity"/>
<activity android:name=".fragment_task.FragmentActivity"/> <activity android:name=".download.SingleTaskActivity"/>
<activity android:name=".multi_task.DownloadActivity"/> <activity android:name=".download.multi_download.MultiTaskActivity"/>
<activity android:name=".download.fragment_download.FragmentActivity"/>
<activity android:name=".download.multi_download.MultiDownloadActivity"/>
<service android:name=".download.service_download.DownloadService"/>
</application> </application>
</manifest> </manifest>

@ -16,99 +16,38 @@
package com.arialyy.simple; package com.arialyy.simple;
import android.Manifest;
import android.content.Intent; import android.content.Intent;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.view.Gravity;
import android.view.View; import android.view.View;
import android.widget.Button;
import butterknife.Bind; import butterknife.Bind;
import com.arialyy.frame.permission.OnPermissionCallback; import butterknife.OnClick;
import com.arialyy.frame.permission.PermissionManager;
import com.arialyy.frame.util.show.T;
import com.arialyy.simple.base.BaseActivity; import com.arialyy.simple.base.BaseActivity;
import com.arialyy.simple.databinding.ActivityMainBinding; import com.arialyy.simple.databinding.ActivityMainBinding;
import com.arialyy.simple.dialog_task.DownloadDialog; import com.arialyy.simple.download.DownloadActivity;
import com.arialyy.simple.fragment_task.FragmentActivity; import com.arialyy.simple.upload.UploadActivity;
import com.arialyy.simple.multi_task.MultiTaskActivity;
import com.arialyy.simple.notification.SimpleNotification;
import com.arialyy.simple.pop_task.DownloadPopupWindow;
import com.arialyy.simple.single_task.SingleTaskActivity;
/** /**
* Created by Lyy on 2016/10/13. * Created by Aria.Lao on 2017/3/1.
*/ */
public class MainActivity extends BaseActivity<ActivityMainBinding> { public class MainActivity extends BaseActivity<ActivityMainBinding> {
@Bind(R.id.toolbar) Toolbar mBar;
@Bind(R.id.single_task) Button mSigleBt;
@Bind(R.id.multi_task) Button mMultiBt;
@Bind(R.id.dialog_task) Button mDialogBt;
@Bind(R.id.pop_task) Button mPopBt;
@Override protected int setLayoutId() { @Bind(R.id.toolbar) Toolbar mBar;
return R.layout.activity_main;
}
@Override protected void init(Bundle savedInstanceState) { @Override protected void init(Bundle savedInstanceState) {
super.init(savedInstanceState); super.init(savedInstanceState);
setSupportActionBar(mBar); mBar.setTitle("Aria Demo");
mBar.setTitle("多线程多任务下载"); }
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
setEnable(true);
} else { //6.0处理
boolean hasPermission = PermissionManager.getInstance()
.checkPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (hasPermission) {
setEnable(true);
} else {
setEnable(false);
PermissionManager.getInstance().requestPermission(this, new OnPermissionCallback() {
@Override public void onSuccess(String... permissions) {
setEnable(true);
}
@Override public void onFail(String... permissions) { @Override protected int setLayoutId() {
T.showShort(MainActivity.this, "没有文件读写权限"); return R.layout.activity_main;
setEnable(false);
}
}, Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
}
} }
private void setEnable(boolean enable) { @OnClick(R.id.download) public void downloadDemo() {
mSigleBt.setEnabled(enable); startActivity(new Intent(this, DownloadActivity.class));
mMultiBt.setEnabled(enable);
mDialogBt.setEnabled(enable);
mPopBt.setEnabled(enable);
} }
public void onClick(View view) { @OnClick(R.id.upload) public void uploadDemo() {
switch (view.getId()) { startActivity(new Intent(this, UploadActivity.class));
case R.id.single_task:
startActivity(new Intent(this, SingleTaskActivity.class));
break;
case R.id.multi_task:
startActivity(new Intent(this, MultiTaskActivity.class));
break;
case R.id.dialog_task:
DownloadDialog dialog = new DownloadDialog(this);
dialog.show();
break;
case R.id.pop_task:
DownloadPopupWindow pop = new DownloadPopupWindow(this);
//pop.showAsDropDown(mRootView);
pop.showAtLocation(mRootView, Gravity.CENTER_VERTICAL, 0, 0);
break;
case R.id.fragment_task:
startActivity(new Intent(this, FragmentActivity.class));
break;
case R.id.notification:
SimpleNotification notification = new SimpleNotification(this);
notification.start();
break;
}
} }
} }

@ -14,11 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.simple.base; package com.arialyy.simple.base;
import android.app.Application; import android.app.Application;
import com.arialyy.aria.core.DownloadManager;
import com.arialyy.frame.core.AbsFrame; import com.arialyy.frame.core.AbsFrame;
/** /**
@ -28,6 +26,5 @@ public class BaseApplication extends Application {
@Override public void onCreate() { @Override public void onCreate() {
super.onCreate(); super.onCreate();
AbsFrame.init(this); AbsFrame.init(this);
//DownloadManager.init(this);
} }
} }

@ -14,7 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.simple.base; package com.arialyy.simple.base;
import android.databinding.ViewDataBinding; import android.databinding.ViewDataBinding;
@ -24,9 +23,9 @@ import com.arialyy.frame.core.AbsDialogFragment;
/** /**
* Created by AriaLyy@outlook.com on 2016/11/14. * Created by AriaLyy@outlook.com on 2016/11/14.
*/ */
public abstract class BaseDialog<VB extends ViewDataBinding> extends AbsDialogFragment<VB>{ public abstract class BaseDialog<VB extends ViewDataBinding> extends AbsDialogFragment<VB> {
protected BaseDialog(Object obj){ protected BaseDialog(Object obj) {
super(obj); super(obj);
} }

@ -14,7 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.simple.base; package com.arialyy.simple.base;
import android.content.Context; import android.content.Context;

@ -0,0 +1,115 @@
/*
* 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.simple.download;
import android.Manifest;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import butterknife.Bind;
import com.arialyy.frame.permission.OnPermissionCallback;
import com.arialyy.frame.permission.PermissionManager;
import com.arialyy.frame.util.show.T;
import com.arialyy.simple.R;
import com.arialyy.simple.base.BaseActivity;
import com.arialyy.simple.databinding.ActivityDownloadMeanBinding;
import com.arialyy.simple.download.fragment_download.FragmentActivity;
import com.arialyy.simple.download.multi_download.MultiTaskActivity;
import com.arialyy.simple.download.service_download.DownloadService;
/**
* Created by Lyy on 2016/10/13.
*/
public class DownloadActivity extends BaseActivity<ActivityDownloadMeanBinding> {
@Bind(R.id.toolbar) Toolbar mBar;
@Bind(R.id.single_task) Button mSigleBt;
@Bind(R.id.multi_task) Button mMultiBt;
@Bind(R.id.dialog_task) Button mDialogBt;
@Bind(R.id.pop_task) Button mPopBt;
@Override protected int setLayoutId() {
return R.layout.activity_download_mean;
}
@Override protected void init(Bundle savedInstanceState) {
super.init(savedInstanceState);
setSupportActionBar(mBar);
mBar.setTitle("多线程多任务下载");
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
setEnable(true);
} else { //6.0处理
boolean hasPermission = PermissionManager.getInstance()
.checkPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (hasPermission) {
setEnable(true);
} else {
setEnable(false);
PermissionManager.getInstance().requestPermission(this, new OnPermissionCallback() {
@Override public void onSuccess(String... permissions) {
setEnable(true);
}
@Override public void onFail(String... permissions) {
T.showShort(DownloadActivity.this, "没有文件读写权限");
setEnable(false);
}
}, Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
}
}
private void setEnable(boolean enable) {
mSigleBt.setEnabled(enable);
mMultiBt.setEnabled(enable);
mDialogBt.setEnabled(enable);
mPopBt.setEnabled(enable);
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.service:
startService(new Intent(this, DownloadService.class));
break;
case R.id.single_task:
startActivity(new Intent(this, SingleTaskActivity.class));
break;
case R.id.multi_task:
startActivity(new Intent(this, MultiTaskActivity.class));
break;
case R.id.dialog_task:
DownloadDialog dialog = new DownloadDialog(this);
dialog.show();
break;
case R.id.pop_task:
DownloadPopupWindow pop = new DownloadPopupWindow(this);
//pop.showAsDropDown(mRootView);
pop.showAtLocation(mRootView, Gravity.CENTER_VERTICAL, 0, 0);
break;
case R.id.fragment_task:
startActivity(new Intent(this, FragmentActivity.class));
break;
case R.id.notification:
SimpleNotification notification = new SimpleNotification(this);
notification.start();
break;
}
}
}

@ -1,4 +1,20 @@
package com.arialyy.simple.dialog_task; /*
* 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.simple.download;
import android.content.Context; import android.content.Context;
import android.os.Environment; import android.os.Environment;
@ -7,10 +23,10 @@ import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import butterknife.Bind; import butterknife.Bind;
import butterknife.OnClick; import butterknife.OnClick;
import com.arialyy.aria.core.AMTarget; import com.arialyy.aria.core.download.DownloadTarget;
import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.task.Task; 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;
@ -21,11 +37,11 @@ import com.arialyy.simple.widget.HorizontalProgressBarWithNumber;
*/ */
public class DownloadDialog extends AbsDialog { public class DownloadDialog extends AbsDialog {
@Bind(R.id.progressBar) HorizontalProgressBarWithNumber mPb; @Bind(R.id.progressBar) HorizontalProgressBarWithNumber mPb;
@Bind(R.id.start) Button mStart; @Bind(R.id.start) Button mStart;
@Bind(R.id.stop) Button mStop; @Bind(R.id.stop) Button mStop;
@Bind(R.id.cancel) Button mCancel; @Bind(R.id.cancel) Button mCancel;
@Bind(R.id.size) TextView mSize; @Bind(R.id.size) TextView mSize;
@Bind(R.id.speed) TextView mSpeed; @Bind(R.id.speed) TextView mSpeed;
private static final String DOWNLOAD_URL = private static final String DOWNLOAD_URL =
"http://static.gaoshouyou.com/d/3a/93/573ae1db9493a801c24bf66128b11e39.apk"; "http://static.gaoshouyou.com/d/3a/93/573ae1db9493a801c24bf66128b11e39.apk";
@ -40,17 +56,17 @@ public class DownloadDialog extends AbsDialog {
} }
private void init() { private void init() {
if (Aria.get(this).taskExists(DOWNLOAD_URL)) { if (Aria.download(this).taskExists(DOWNLOAD_URL)) {
AMTarget target = Aria.whit(this).load(DOWNLOAD_URL); DownloadTarget target = Aria.download(this).load(DOWNLOAD_URL);
int p = (int) (target.getCurrentProgress() * 100 / target.getFileSize()); int p = (int) (target.getCurrentProgress() * 100 / target.getFileSize());
mPb.setProgress(p); mPb.setProgress(p);
} }
Aria.whit(this).addSchedulerListener(new MyDialogDownloadCallback()); Aria.download(this).addSchedulerListener(new MyDialogDownloadCallback());
DownloadEntity entity = Aria.get(this).getDownloadEntity(DOWNLOAD_URL); DownloadEntity entity = Aria.download(this).getDownloadEntity(DOWNLOAD_URL);
if (entity != null) { if (entity != null) {
mSize.setText(CommonUtil.formatFileSize(entity.getFileSize())); mSize.setText(CommonUtil.formatFileSize(entity.getFileSize()));
int state = entity.getState(); int state = entity.getState();
setBtState(state != DownloadEntity.STATE_DOWNLOAD_ING); setBtState(state != DownloadEntity.STATE_RUNNING);
} else { } else {
setBtState(true); setBtState(true);
} }
@ -59,17 +75,16 @@ public class DownloadDialog extends AbsDialog {
@OnClick({ R.id.start, R.id.stop, R.id.cancel }) public void onClick(View view) { @OnClick({ R.id.start, R.id.stop, R.id.cancel }) public void onClick(View view) {
switch (view.getId()) { switch (view.getId()) {
case R.id.start: case R.id.start:
Aria.whit(this) Aria.download(this)
.load(DOWNLOAD_URL) .load(DOWNLOAD_URL)
.setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/daialog.apk") .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/daialog.apk")
.setDownloadName("daialog.apk")
.start(); .start();
break; break;
case R.id.stop: case R.id.stop:
Aria.whit(this).load(DOWNLOAD_URL).stop(); Aria.download(this).load(DOWNLOAD_URL).pause();
break; break;
case R.id.cancel: case R.id.cancel:
Aria.whit(this).load(DOWNLOAD_URL).cancel(); Aria.download(this).load(DOWNLOAD_URL).cancel();
break; break;
} }
} }
@ -84,31 +99,31 @@ public class DownloadDialog extends AbsDialog {
mStop.setEnabled(!startEnable); mStop.setEnabled(!startEnable);
} }
private class MyDialogDownloadCallback extends Aria.SimpleSchedulerListener { private class MyDialogDownloadCallback extends Aria.DownloadSchedulerListener {
@Override public void onTaskPre(Task task) { @Override public void onTaskPre(DownloadTask task) {
super.onTaskPre(task); super.onTaskPre(task);
mSize.setText(CommonUtil.formatFileSize(task.getFileSize())); mSize.setText(CommonUtil.formatFileSize(task.getFileSize()));
setBtState(false); setBtState(false);
} }
@Override public void onTaskStop(Task task) { @Override public void onTaskStop(DownloadTask task) {
super.onTaskStop(task); super.onTaskStop(task);
setBtState(true); setBtState(true);
mSpeed.setText("0.0kb/s"); mSpeed.setText("0.0kb/s");
} }
@Override public void onTaskCancel(Task task) { @Override public void onTaskCancel(DownloadTask task) {
super.onTaskCancel(task); super.onTaskCancel(task);
setBtState(true); setBtState(true);
mPb.setProgress(0); mPb.setProgress(0);
mSpeed.setText("0.0kb/s"); mSpeed.setText("0.0kb/s");
} }
@Override public void onTaskRunning(Task task) { @Override public void onTaskRunning(DownloadTask task) {
super.onTaskRunning(task); super.onTaskRunning(task);
long current = task.getCurrentProgress(); long current = task.getCurrentProgress();
long len = task.getFileSize(); long len = task.getFileSize();
if (len == 0) { if (len == 0) {
mPb.setProgress(0); mPb.setProgress(0);
} else { } else {

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.simple.module; package com.arialyy.simple.download;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
@ -23,14 +23,13 @@ import android.content.IntentFilter;
import android.os.Environment; import android.os.Environment;
import android.os.Handler; import android.os.Handler;
import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.frame.util.AndroidUtils; import com.arialyy.frame.util.AndroidUtils;
import com.arialyy.frame.util.StringUtil; import com.arialyy.frame.util.StringUtil;
import com.arialyy.frame.util.show.L; import com.arialyy.frame.util.show.L;
import com.arialyy.simple.R; import com.arialyy.simple.R;
import com.arialyy.simple.multi_task.FileListEntity; import com.arialyy.simple.download.multi_download.FileListEntity;
import com.arialyy.simple.single_task.SingleTaskActivity;
import com.arialyy.simple.base.BaseModule; import com.arialyy.simple.base.BaseModule;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
@ -45,9 +44,12 @@ public class DownloadModule extends BaseModule {
public DownloadModule(Context context) { public DownloadModule(Context context) {
super(context); super(context);
mTestDownloadUrl.add("http://static.gaoshouyou.com/d/e6/f5/4de6329f9cf5dc3a1d1e6bbcca0d003c.apk"); mTestDownloadUrl.add(
mTestDownloadUrl.add("http://static.gaoshouyou.com/d/6e/e5/ff6ecaaf45e532e6d07747af82357472.apk"); "http://static.gaoshouyou.com/d/e6/f5/4de6329f9cf5dc3a1d1e6bbcca0d003c.apk");
mTestDownloadUrl.add("http://static.gaoshouyou.com/d/36/69/2d3699acfa69e9632262442c46516ad8.apk"); mTestDownloadUrl.add(
"http://static.gaoshouyou.com/d/6e/e5/ff6ecaaf45e532e6d07747af82357472.apk");
mTestDownloadUrl.add(
"http://static.gaoshouyou.com/d/36/69/2d3699acfa69e9632262442c46516ad8.apk");
} }
public String getRadomUrl() { public String getRadomUrl() {
@ -56,7 +58,7 @@ public class DownloadModule extends BaseModule {
return mTestDownloadUrl.get(i); return mTestDownloadUrl.get(i);
} }
public DownloadEntity createRandomDownloadEntity(){ public DownloadEntity createRandomDownloadEntity() {
return createDownloadEntity(getRadomUrl()); return createDownloadEntity(getRadomUrl());
} }
@ -86,7 +88,7 @@ public class DownloadModule extends BaseModule {
String[] urls = getContext().getResources().getStringArray(R.array.test_apk_download_url); String[] urls = getContext().getResources().getStringArray(R.array.test_apk_download_url);
List<DownloadEntity> list = new ArrayList<>(); List<DownloadEntity> list = new ArrayList<>();
for (String url : urls) { for (String url : urls) {
DownloadEntity entity = Aria.get(getContext()).getDownloadEntity(url); DownloadEntity entity = Aria.download(getContext()).getDownloadEntity(url);
if (entity == null) { if (entity == null) {
entity = createDownloadEntity(url); entity = createDownloadEntity(url);
} }

@ -1,4 +1,20 @@
package com.arialyy.simple.pop_task; /*
* 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.simple.download;
import android.content.Context; import android.content.Context;
import android.graphics.Color; import android.graphics.Color;
@ -9,10 +25,10 @@ import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import butterknife.Bind; import butterknife.Bind;
import butterknife.OnClick; import butterknife.OnClick;
import com.arialyy.aria.core.AMTarget; import com.arialyy.aria.core.download.DownloadTarget;
import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.task.Task; import com.arialyy.aria.core.download.DownloadTask;
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;
@ -23,11 +39,11 @@ import com.arialyy.simple.widget.HorizontalProgressBarWithNumber;
*/ */
public class DownloadPopupWindow extends AbsPopupWindow { public class DownloadPopupWindow extends AbsPopupWindow {
@Bind(R.id.progressBar) HorizontalProgressBarWithNumber mPb; @Bind(R.id.progressBar) HorizontalProgressBarWithNumber mPb;
@Bind(R.id.start) Button mStart; @Bind(R.id.start) Button mStart;
@Bind(R.id.stop) Button mStop; @Bind(R.id.stop) Button mStop;
@Bind(R.id.cancel) Button mCancel; @Bind(R.id.cancel) Button mCancel;
@Bind(R.id.size) TextView mSize; @Bind(R.id.size) TextView mSize;
@Bind(R.id.speed) TextView mSpeed; @Bind(R.id.speed) TextView mSpeed;
private static final String DOWNLOAD_URL = private static final String DOWNLOAD_URL =
"http://static.gaoshouyou.com/d/3a/93/573ae1db9493a801c24bf66128b11e39.apk"; "http://static.gaoshouyou.com/d/3a/93/573ae1db9493a801c24bf66128b11e39.apk";
@ -42,17 +58,17 @@ public class DownloadPopupWindow extends AbsPopupWindow {
} }
private void initWidget() { private void initWidget() {
if (Aria.get(this).taskExists(DOWNLOAD_URL)) { if (Aria.download(this).taskExists(DOWNLOAD_URL)) {
AMTarget target = Aria.whit(this).load(DOWNLOAD_URL); DownloadTarget target = Aria.download(this).load(DOWNLOAD_URL);
int p = (int) (target.getCurrentProgress() * 100 / target.getFileSize()); int p = (int) (target.getCurrentProgress() * 100 / target.getFileSize());
mPb.setProgress(p); mPb.setProgress(p);
} }
Aria.whit(this).addSchedulerListener(new MyDialogDownloadCallback()); Aria.download(this).addSchedulerListener(new MyDialogDownloadCallback());
DownloadEntity entity = Aria.get(this).getDownloadEntity(DOWNLOAD_URL); DownloadEntity entity = Aria.download(this).getDownloadEntity(DOWNLOAD_URL);
if (entity != null) { if (entity != null) {
mSize.setText(CommonUtil.formatFileSize(entity.getFileSize())); mSize.setText(CommonUtil.formatFileSize(entity.getFileSize()));
int state = entity.getState(); int state = entity.getState();
setBtState(state != DownloadEntity.STATE_DOWNLOAD_ING); setBtState(state != DownloadEntity.STATE_RUNNING);
} else { } else {
setBtState(true); setBtState(true);
} }
@ -61,17 +77,16 @@ public class DownloadPopupWindow extends AbsPopupWindow {
@OnClick({ R.id.start, R.id.stop, R.id.cancel }) public void onClick(View view) { @OnClick({ R.id.start, R.id.stop, R.id.cancel }) public void onClick(View view) {
switch (view.getId()) { switch (view.getId()) {
case R.id.start: case R.id.start:
Aria.whit(this) Aria.download(this)
.load(DOWNLOAD_URL) .load(DOWNLOAD_URL)
.setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/daialog.apk") .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/daialog.apk")
.setDownloadName("daialog.apk")
.start(); .start();
break; break;
case R.id.stop: case R.id.stop:
Aria.whit(this).load(DOWNLOAD_URL).stop(); Aria.download(this).load(DOWNLOAD_URL).pause();
break; break;
case R.id.cancel: case R.id.cancel:
Aria.whit(this).load(DOWNLOAD_URL).cancel(); Aria.download(this).load(DOWNLOAD_URL).cancel();
break; break;
} }
} }
@ -86,31 +101,31 @@ public class DownloadPopupWindow extends AbsPopupWindow {
mStop.setEnabled(!startEnable); mStop.setEnabled(!startEnable);
} }
private class MyDialogDownloadCallback extends Aria.SimpleSchedulerListener { private class MyDialogDownloadCallback extends Aria.DownloadSchedulerListener {
@Override public void onTaskPre(Task task) { @Override public void onTaskPre(DownloadTask task) {
super.onTaskPre(task); super.onTaskPre(task);
mSize.setText(CommonUtil.formatFileSize(task.getFileSize())); mSize.setText(CommonUtil.formatFileSize(task.getFileSize()));
setBtState(false); setBtState(false);
} }
@Override public void onTaskStop(Task task) { @Override public void onTaskStop(DownloadTask task) {
super.onTaskStop(task); super.onTaskStop(task);
setBtState(true); setBtState(true);
mSpeed.setText("0.0kb/s"); mSpeed.setText("0.0kb/s");
} }
@Override public void onTaskCancel(Task task) { @Override public void onTaskCancel(DownloadTask task) {
super.onTaskCancel(task); super.onTaskCancel(task);
setBtState(true); setBtState(true);
mPb.setProgress(0); mPb.setProgress(0);
mSpeed.setText("0.0kb/s"); mSpeed.setText("0.0kb/s");
} }
@Override public void onTaskRunning(Task task) { @Override public void onTaskRunning(DownloadTask task) {
super.onTaskRunning(task); super.onTaskRunning(task);
long current = task.getCurrentProgress(); long current = task.getCurrentProgress();
long len = task.getFileSize(); long len = task.getFileSize();
if (len == 0) { if (len == 0) {
mPb.setProgress(0); mPb.setProgress(0);
} else { } else {

@ -1,13 +1,27 @@
package com.arialyy.simple.notification; /*
* 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.simple.download;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.content.Context; import android.content.Context;
import android.os.Environment; import android.os.Environment;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.task.Task; import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.frame.util.show.L;
import com.arialyy.frame.util.show.T;
import com.arialyy.simple.R; import com.arialyy.simple.R;
/** /**
@ -36,11 +50,11 @@ public class SimpleNotification {
.setProgress(100, 0, false) .setProgress(100, 0, false)
.setSmallIcon(R.mipmap.ic_launcher); .setSmallIcon(R.mipmap.ic_launcher);
mManager.notify(mNotifiyId, mBuilder.build()); mManager.notify(mNotifiyId, mBuilder.build());
Aria.whit(mContext).addSchedulerListener(new DownloadCallback(mBuilder, mManager)); Aria.download(mContext).addSchedulerListener(new DownloadCallback(mBuilder, mManager));
} }
public void start() { public void start() {
Aria.whit(mContext) Aria.download(mContext)
.load(DOWNLOAD_URL) .load(DOWNLOAD_URL)
.setDownloadName("notification_test.apk") .setDownloadName("notification_test.apk")
.setDownloadPath( .setDownloadPath(
@ -49,10 +63,10 @@ public class SimpleNotification {
} }
public void stop() { public void stop() {
Aria.whit(mContext).load(DOWNLOAD_URL).stop(); Aria.download(mContext).load(DOWNLOAD_URL).pause();
} }
private static class DownloadCallback extends Aria.SimpleSchedulerListener { private static class DownloadCallback extends Aria.DownloadSchedulerListener {
NotificationCompat.Builder mBuilder; NotificationCompat.Builder mBuilder;
NotificationManager mManager; NotificationManager mManager;
@ -61,19 +75,19 @@ public class SimpleNotification {
mManager = manager; mManager = manager;
} }
@Override public void onTaskStart(Task task) { @Override public void onTaskStart(DownloadTask task) {
super.onTaskStart(task); super.onTaskStart(task);
} }
@Override public void onTaskPre(Task task) { @Override public void onTaskPre(DownloadTask task) {
super.onTaskPre(task); super.onTaskPre(task);
} }
@Override public void onTaskStop(Task task) { @Override public void onTaskStop(DownloadTask task) {
super.onTaskStop(task); super.onTaskStop(task);
} }
@Override public void onTaskRunning(Task task) { @Override public void onTaskRunning(DownloadTask task) {
super.onTaskRunning(task); super.onTaskRunning(task);
long len = task.getFileSize(); long len = task.getFileSize();
int p = (int) (task.getCurrentProgress() * 100 / len); int p = (int) (task.getCurrentProgress() * 100 / len);
@ -83,7 +97,7 @@ public class SimpleNotification {
} }
} }
@Override public void onTaskComplete(Task task) { @Override public void onTaskComplete(DownloadTask task) {
super.onTaskComplete(task); super.onTaskComplete(task);
if (mBuilder != null) { if (mBuilder != null) {
mBuilder.setProgress(100, 100, false); mBuilder.setProgress(100, 100, false);
@ -91,7 +105,7 @@ public class SimpleNotification {
} }
} }
@Override public void onTaskCancel(Task task) { @Override public void onTaskCancel(DownloadTask task) {
super.onTaskCancel(task); super.onTaskCancel(task);
} }
} }

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.simple.single_task; package com.arialyy.simple.download;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
@ -26,46 +26,47 @@ import android.os.Message;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.ImageView; import android.widget.RadioGroup;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import butterknife.Bind; import butterknife.Bind;
import com.arialyy.aria.core.AMTarget; import com.arialyy.aria.core.download.DownloadTarget;
import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.task.DownloadUtil; import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.core.task.IDownloadListener;
import com.arialyy.aria.core.task.Task;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.Speed;
import com.arialyy.frame.util.show.L; import com.arialyy.frame.util.show.L;
import com.arialyy.frame.util.show.T;
import com.arialyy.simple.R; import com.arialyy.simple.R;
import com.arialyy.simple.base.BaseActivity; import com.arialyy.simple.base.BaseActivity;
import com.arialyy.simple.databinding.ActivitySingleBinding; import com.arialyy.simple.databinding.ActivitySingleBinding;
import com.arialyy.simple.widget.HorizontalProgressBarWithNumber; import com.arialyy.simple.widget.HorizontalProgressBarWithNumber;
public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> { public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
public static final int DOWNLOAD_PRE = 0x01; public static final int DOWNLOAD_PRE = 0x01;
public static final int DOWNLOAD_STOP = 0x02; public static final int DOWNLOAD_STOP = 0x02;
public static final int DOWNLOAD_FAILE = 0x03; public static final int DOWNLOAD_FAILE = 0x03;
public static final int DOWNLOAD_CANCEL = 0x04; public static final int DOWNLOAD_CANCEL = 0x04;
public static final int DOWNLOAD_RESUME = 0x05; public static final int DOWNLOAD_RESUME = 0x05;
public static final int DOWNLOAD_COMPLETE = 0x06; public static final int DOWNLOAD_COMPLETE = 0x06;
public static final int DOWNLOAD_RUNNING = 0x07; public static final int DOWNLOAD_RUNNING = 0x07;
private static final String DOWNLOAD_URL = private static final String DOWNLOAD_URL =
//"http://kotlinlang.org/docs/kotlin-docs.pdf"; //"http://kotlinlang.org/docs/kotlin-docs.pdf";
//"https://atom-installer.github.com/v1.13.0/AtomSetup.exe?s=1484074138&ext=.exe"; //"https://atom-installer.github.com/v1.13.0/AtomSetup.exe?s=1484074138&ext=.exe";
"http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk"; //"http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk";
//"http://ox.konsung.net:5555/ksdc-web/download/downloadFile/?fileName=ksdc_1.0.2.apk&rRange=0-"; //不支持断点的链接
"http://ox.konsung.net:5555/ksdc-web/download/downloadFile/?fileName=ksdc_1.0.2.apk&rRange=0-";
@Bind(R.id.progressBar) HorizontalProgressBarWithNumber mPb; @Bind(R.id.progressBar) HorizontalProgressBarWithNumber mPb;
@Bind(R.id.start) Button mStart; @Bind(R.id.start) Button mStart;
@Bind(R.id.stop) Button mStop; @Bind(R.id.stop) Button mStop;
@Bind(R.id.cancel) Button mCancel; @Bind(R.id.cancel) Button mCancel;
@Bind(R.id.size) TextView mSize; @Bind(R.id.size) TextView mSize;
@Bind(R.id.toolbar) Toolbar toolbar; @Bind(R.id.toolbar) Toolbar toolbar;
@Bind(R.id.speed) TextView mSpeed; @Bind(R.id.speed) TextView mSpeed;
@Bind(R.id.img) ImageView mImg; @Bind(R.id.speeds) RadioGroup mRg;
private DownloadEntity mEntity; private DownloadEntity mEntity;
private BroadcastReceiver mReceiver = new BroadcastReceiver() { private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) { @Override public void onReceive(Context context, Intent intent) {
String action = intent.getAction(); String action = intent.getAction();
@ -80,7 +81,7 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
super.handleMessage(msg); super.handleMessage(msg);
switch (msg.what) { switch (msg.what) {
case DOWNLOAD_RUNNING: case DOWNLOAD_RUNNING:
Task task = (Task) msg.obj; DownloadTask task = (DownloadTask) msg.obj;
long current = task.getCurrentProgress(); long current = task.getCurrentProgress();
long len = task.getFileSize(); long len = task.getFileSize();
if (len == 0) { if (len == 0) {
@ -143,7 +144,7 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
@Override protected void onResume() { @Override protected void onResume() {
super.onResume(); super.onResume();
Aria.whit(this).addSchedulerListener(new MySchedulerListener()); Aria.download(this).addSchedulerListener(new MySchedulerListener());
//registerReceiver(mReceiver, getModule(DownloadModule.class).getDownloadFilter()); //registerReceiver(mReceiver, getModule(DownloadModule.class).getDownloadFilter());
} }
@ -165,11 +166,38 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
} }
private void init() { private void init() {
if (Aria.get(this).taskExists(DOWNLOAD_URL)) { if (Aria.download(this).taskExists(DOWNLOAD_URL)) {
AMTarget target = Aria.whit(this).load(DOWNLOAD_URL); DownloadTarget target = Aria.download(this).load(DOWNLOAD_URL);
int p = (int) (target.getCurrentProgress() * 100 / target.getFileSize()); int p = (int) (target.getCurrentProgress() * 100 / target.getFileSize());
mPb.setProgress(p); mPb.setProgress(p);
} }
mRg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case 1:
Aria.get(this).setMaxSpeed(Speed.KB_256);
break;
case 2:
Aria.get(this).setMaxSpeed(Speed.KB_512);
break;
case 3:
Aria.get(this).setMaxSpeed(Speed.MB_1);
break;
case 4:
Aria.get(this).setMaxSpeed(Speed.MB_2);
break;
case 5:
Aria.get(this).setMaxSpeed(Speed.MAX);
break;
}
stop();
new Handler().postDelayed(new Runnable() {
@Override public void run() {
start();
}
}, 2000);
}
});
} }
public void onClick(View view) { public void onClick(View view) {
@ -192,53 +220,58 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
} }
private void resume() { private void resume() {
Aria.whit(this).load(DOWNLOAD_URL).resume(); Aria.download(this).load(DOWNLOAD_URL).resume();
} }
private void start() { private void start() {
Aria.whit(this) Aria.download(this)
.load(DOWNLOAD_URL) .load(DOWNLOAD_URL)
.setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk") .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk")
.setDownloadName("test.apk")
.start(); .start();
} }
private void stop() { private void stop() {
Aria.whit(this).load(DOWNLOAD_URL).stop(); Aria.download(this).load(DOWNLOAD_URL).pause();
} }
private void cancel() { private void cancel() {
Aria.whit(this).load(DOWNLOAD_URL).cancel(); Aria.download(this).load(DOWNLOAD_URL).cancel();
} }
private class MySchedulerListener extends Aria.SimpleSchedulerListener { private class MySchedulerListener extends Aria.DownloadSchedulerListener {
@Override public void onTaskStart(Task task) {
@Override public void onNoSupportBreakPoint(DownloadTask task) {
super.onNoSupportBreakPoint(task);
T.showShort(SingleTaskActivity.this, "该下载链接不支持断点");
}
@Override public void onTaskStart(DownloadTask task) {
mUpdateHandler.obtainMessage(DOWNLOAD_PRE, task.getDownloadEntity().getFileSize()) mUpdateHandler.obtainMessage(DOWNLOAD_PRE, task.getDownloadEntity().getFileSize())
.sendToTarget(); .sendToTarget();
} }
@Override public void onTaskResume(Task task) { @Override public void onTaskResume(DownloadTask task) {
super.onTaskResume(task); super.onTaskResume(task);
mUpdateHandler.obtainMessage(DOWNLOAD_PRE, task.getFileSize()).sendToTarget(); mUpdateHandler.obtainMessage(DOWNLOAD_PRE, task.getFileSize()).sendToTarget();
} }
@Override public void onTaskStop(Task task) { @Override public void onTaskStop(DownloadTask task) {
mUpdateHandler.sendEmptyMessage(DOWNLOAD_STOP); mUpdateHandler.sendEmptyMessage(DOWNLOAD_STOP);
} }
@Override public void onTaskCancel(Task task) { @Override public void onTaskCancel(DownloadTask task) {
mUpdateHandler.sendEmptyMessage(DOWNLOAD_CANCEL); mUpdateHandler.sendEmptyMessage(DOWNLOAD_CANCEL);
} }
@Override public void onTaskFail(Task task) { @Override public void onTaskFail(DownloadTask task) {
mUpdateHandler.sendEmptyMessage(DOWNLOAD_FAILE); mUpdateHandler.sendEmptyMessage(DOWNLOAD_FAILE);
} }
@Override public void onTaskComplete(Task task) { @Override public void onTaskComplete(DownloadTask task) {
mUpdateHandler.sendEmptyMessage(DOWNLOAD_COMPLETE); mUpdateHandler.sendEmptyMessage(DOWNLOAD_COMPLETE);
} }
@Override public void onTaskRunning(Task task) { @Override public void onTaskRunning(DownloadTask task) {
mUpdateHandler.obtainMessage(DOWNLOAD_RUNNING, task).sendToTarget(); mUpdateHandler.obtainMessage(DOWNLOAD_RUNNING, task).sendToTarget();
} }
} }

@ -1,4 +1,20 @@
package com.arialyy.simple.fragment_task; /*
* 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.simple.download.fragment_download;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
@ -7,10 +23,10 @@ import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import butterknife.Bind; import butterknife.Bind;
import butterknife.OnClick; import butterknife.OnClick;
import com.arialyy.aria.core.AMTarget; import com.arialyy.aria.core.download.DownloadTarget;
import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.task.Task; import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.util.CommonUtil; 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;
@ -32,16 +48,16 @@ public class DownloadFragment extends AbsFragment<FragmentDownloadBinding> {
"http://static.gaoshouyou.com/d/3a/93/573ae1db9493a801c24bf66128b11e39.apk"; "http://static.gaoshouyou.com/d/3a/93/573ae1db9493a801c24bf66128b11e39.apk";
@Override protected void init(Bundle savedInstanceState) { @Override protected void init(Bundle savedInstanceState) {
if (Aria.get(this).taskExists(DOWNLOAD_URL)) { if (Aria.download(this).taskExists(DOWNLOAD_URL)) {
AMTarget target = Aria.whit(this).load(DOWNLOAD_URL); DownloadTarget target = Aria.download(this).load(DOWNLOAD_URL);
int p = (int) (target.getCurrentProgress() * 100 / target.getFileSize()); int p = (int) (target.getCurrentProgress() * 100 / target.getFileSize());
mPb.setProgress(p); mPb.setProgress(p);
} }
DownloadEntity entity = Aria.get(this).getDownloadEntity(DOWNLOAD_URL); DownloadEntity entity = Aria.download(this).getDownloadEntity(DOWNLOAD_URL);
if (entity != null) { if (entity != null) {
mSize.setText(CommonUtil.formatFileSize(entity.getFileSize())); mSize.setText(CommonUtil.formatFileSize(entity.getFileSize()));
int state = entity.getState(); int state = entity.getState();
setBtState(state != DownloadEntity.STATE_DOWNLOAD_ING); setBtState(state != DownloadEntity.STATE_RUNNING);
} else { } else {
setBtState(true); setBtState(true);
} }
@ -49,23 +65,23 @@ public class DownloadFragment extends AbsFragment<FragmentDownloadBinding> {
@Override public void onResume() { @Override public void onResume() {
super.onResume(); super.onResume();
Aria.whit(this).addSchedulerListener(new DownloadFragment.MyDialogDownloadCallback()); Aria.download(this).addSchedulerListener(new DownloadFragment.MyDialogDownloadCallback());
} }
@OnClick({ R.id.start, R.id.stop, R.id.cancel }) public void onClick(View view) { @OnClick({ R.id.start, R.id.stop, R.id.cancel }) public void onClick(View view) {
switch (view.getId()) { switch (view.getId()) {
case R.id.start: case R.id.start:
Aria.whit(this) Aria.download(this)
.load(DOWNLOAD_URL) .load(DOWNLOAD_URL)
.setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/daialog.apk") .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/daialog.apk")
.setDownloadName("daialog.apk") .setDownloadName("daialog.apk")
.start(); .start();
break; break;
case R.id.stop: case R.id.stop:
Aria.whit(this).load(DOWNLOAD_URL).stop(); Aria.download(this).load(DOWNLOAD_URL).pause();
break; break;
case R.id.cancel: case R.id.cancel:
Aria.whit(this).load(DOWNLOAD_URL).cancel(); Aria.download(this).load(DOWNLOAD_URL).cancel();
break; break;
} }
} }
@ -88,31 +104,31 @@ public class DownloadFragment extends AbsFragment<FragmentDownloadBinding> {
mStop.setEnabled(!startEnable); mStop.setEnabled(!startEnable);
} }
private class MyDialogDownloadCallback extends Aria.SimpleSchedulerListener { private class MyDialogDownloadCallback extends Aria.DownloadSchedulerListener {
@Override public void onTaskPre(Task task) { @Override public void onTaskPre(DownloadTask task) {
super.onTaskPre(task); super.onTaskPre(task);
mSize.setText(CommonUtil.formatFileSize(task.getFileSize())); mSize.setText(CommonUtil.formatFileSize(task.getFileSize()));
setBtState(false); setBtState(false);
} }
@Override public void onTaskStop(Task task) { @Override public void onTaskStop(DownloadTask task) {
super.onTaskStop(task); super.onTaskStop(task);
setBtState(true); setBtState(true);
mSpeed.setText("0.0kb/s"); mSpeed.setText("0.0kb/s");
} }
@Override public void onTaskCancel(Task task) { @Override public void onTaskCancel(DownloadTask task) {
super.onTaskCancel(task); super.onTaskCancel(task);
setBtState(true); setBtState(true);
mPb.setProgress(0); mPb.setProgress(0);
mSpeed.setText("0.0kb/s"); mSpeed.setText("0.0kb/s");
} }
@Override public void onTaskRunning(Task task) { @Override public void onTaskRunning(DownloadTask task) {
super.onTaskRunning(task); super.onTaskRunning(task);
long current = task.getCurrentProgress(); long current = task.getCurrentProgress();
long len = task.getFileSize(); long len = task.getFileSize();
if (len == 0) { if (len == 0) {
mPb.setProgress(0); mPb.setProgress(0);
} else { } else {

@ -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.simple.download.fragment_download;
import com.arialyy.simple.R;
import com.arialyy.simple.base.BaseActivity;
import com.arialyy.simple.databinding.FragmentDownloadBinding;
/**
* Created by Aria.Lao on 2017/1/4.
*/
public class FragmentActivity extends BaseActivity<FragmentDownloadBinding> {
@Override protected int setLayoutId() {
return R.layout.activity_fragment;
}
}

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.simple.multi_task; package com.arialyy.simple.download.multi_download;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
@ -25,7 +25,7 @@ import butterknife.Bind;
import com.arialyy.absadapter.common.AbsHolder; import com.arialyy.absadapter.common.AbsHolder;
import com.arialyy.absadapter.recycler_view.AbsRVAdapter; import com.arialyy.absadapter.recycler_view.AbsRVAdapter;
import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.simple.R; import com.arialyy.simple.R;
import com.arialyy.simple.widget.HorizontalProgressBarWithNumber; import com.arialyy.simple.widget.HorizontalProgressBarWithNumber;
@ -39,8 +39,8 @@ import java.util.concurrent.ConcurrentHashMap;
* 下载列表适配器 * 下载列表适配器
*/ */
final class DownloadAdapter extends AbsRVAdapter<DownloadEntity, DownloadAdapter.MyHolder> { final class DownloadAdapter extends AbsRVAdapter<DownloadEntity, DownloadAdapter.MyHolder> {
private static final String TAG = "DownloadAdapter"; private static final String TAG = "DownloadAdapter";
private Map<String, Integer> mPositions = new ConcurrentHashMap<>(); private Map<String, Integer> mPositions = new ConcurrentHashMap<>();
DownloadAdapter(Context context, List<DownloadEntity> data) { DownloadAdapter(Context context, List<DownloadEntity> data) {
super(context, data); super(context, data);
@ -125,7 +125,7 @@ final class DownloadAdapter extends AbsRVAdapter<DownloadEntity, DownloadAdapter
break; break;
case DownloadEntity.STATE_PRE: case DownloadEntity.STATE_PRE:
case DownloadEntity.STATE_POST_PRE: case DownloadEntity.STATE_POST_PRE:
case DownloadEntity.STATE_DOWNLOAD_ING: case DownloadEntity.STATE_RUNNING:
str = "暂停"; str = "暂停";
color = android.R.color.holo_red_light; color = android.R.color.holo_red_light;
break; break;
@ -142,7 +142,7 @@ final class DownloadAdapter extends AbsRVAdapter<DownloadEntity, DownloadAdapter
@Override public void onClick(View v) { @Override public void onClick(View v) {
mData.remove(item); mData.remove(item);
notifyDataSetChanged(); notifyDataSetChanged();
Aria.whit(getContext()).load(item).cancel(); Aria.download(getContext()).load(item).cancel();
} }
}); });
} }
@ -176,30 +176,30 @@ final class DownloadAdapter extends AbsRVAdapter<DownloadEntity, DownloadAdapter
case DownloadEntity.STATE_COMPLETE: case DownloadEntity.STATE_COMPLETE:
start(entity); start(entity);
break; break;
case DownloadEntity.STATE_DOWNLOAD_ING: case DownloadEntity.STATE_RUNNING:
stop(entity); stop(entity);
break; break;
} }
} }
private void start(DownloadEntity entity) { private void start(DownloadEntity entity) {
Aria.whit(getContext()).load(entity).start(); Aria.download(getContext()).load(entity).start();
} }
private void stop(DownloadEntity entity) { private void stop(DownloadEntity entity) {
Aria.whit(getContext()).load(entity).stop(); Aria.download(getContext()).load(entity).pause();
} }
} }
class MyHolder extends AbsHolder { class MyHolder extends AbsHolder {
@Bind(R.id.progressBar) HorizontalProgressBarWithNumber progress; @Bind(R.id.progressBar) HorizontalProgressBarWithNumber progress;
@Bind(R.id.bt) Button bt; @Bind(R.id.bt) Button bt;
@Bind(R.id.speed) TextView speed; @Bind(R.id.speed) TextView speed;
@Bind(R.id.fileSize) TextView fileSize; @Bind(R.id.fileSize) TextView fileSize;
@Bind(R.id.del) TextView cancel; @Bind(R.id.del) TextView cancel;
@Bind(R.id.name) TextView name; @Bind(R.id.name) TextView name;
@Bind(R.id.download_url) TextView url; @Bind(R.id.download_url) TextView url;
@Bind(R.id.download_path) TextView path; @Bind(R.id.download_path) TextView path;
MyHolder(View itemView) { MyHolder(View itemView) {
super(itemView); super(itemView);

@ -14,8 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.simple.download.multi_download;
package com.arialyy.simple.multi_task;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.os.Bundle; import android.os.Bundle;

@ -1,7 +1,22 @@
package com.arialyy.simple.multi_task; /*
* 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.simple.download.multi_download;
import android.content.Context; import android.content.Context;
import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
@ -51,7 +66,7 @@ final class FileListAdapter extends AbsRVAdapter<FileListEntity, FileListAdapter
holder.bt.setOnClickListener(new View.OnClickListener() { holder.bt.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) { @Override public void onClick(View v) {
Toast.makeText(getContext(), "开始下载:" + item.name, Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), "开始下载:" + item.name, Toast.LENGTH_SHORT).show();
Aria.whit(getContext()) Aria.download(getContext())
.load(item.downloadUrl) .load(item.downloadUrl)
.setDownloadName(item.name) .setDownloadName(item.name)
.setDownloadPath(item.downloadPath) .setDownloadPath(item.downloadPath)
@ -87,10 +102,10 @@ final class FileListAdapter extends AbsRVAdapter<FileListEntity, FileListAdapter
} }
class FileListHolder extends AbsHolder { class FileListHolder extends AbsHolder {
@Bind(R.id.name) TextView name; @Bind(R.id.name) TextView name;
@Bind(R.id.download_url) TextView url; @Bind(R.id.download_url) TextView url;
@Bind(R.id.download_path) TextView path; @Bind(R.id.download_path) TextView path;
@Bind(R.id.bt) Button bt; @Bind(R.id.bt) Button bt;
FileListHolder(View itemView) { FileListHolder(View itemView) {
super(itemView); super(itemView);

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

@ -0,0 +1,105 @@
/*
* 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.simple.download.multi_download;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import butterknife.Bind;
import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.frame.util.show.L;
import com.arialyy.simple.R;
import com.arialyy.simple.base.BaseActivity;
import com.arialyy.simple.databinding.ActivityMultiDownloadBinding;
/**
* Created by AriaL on 2017/1/6.
*/
public class MultiDownloadActivity extends BaseActivity<ActivityMultiDownloadBinding> {
@Bind(R.id.list) RecyclerView mList;
@Bind(R.id.toolbar) Toolbar mBar;
private DownloadAdapter mAdapter;
@Override protected int setLayoutId() {
return R.layout.activity_multi_download;
}
@Override protected void init(Bundle savedInstanceState) {
super.init(savedInstanceState);
mAdapter = new DownloadAdapter(this, Aria.download(this).getTaskList());
mList.setLayoutManager(new LinearLayoutManager(this));
mList.setAdapter(mAdapter);
mBar.setTitle("多任务下载");
}
@Override protected void dataCallback(int result, Object data) {
}
@Override protected void onResume() {
super.onResume();
Aria.download(this).addSchedulerListener(new MySchedulerListener());
}
private class MySchedulerListener extends Aria.DownloadSchedulerListener {
@Override public void onTaskPre(DownloadTask task) {
super.onTaskPre(task);
L.d(TAG, "download pre");
mAdapter.updateState(task.getDownloadEntity());
}
@Override public void onTaskStart(DownloadTask task) {
super.onTaskStart(task);
L.d(TAG, "download start");
mAdapter.updateState(task.getDownloadEntity());
}
@Override public void onTaskResume(DownloadTask task) {
super.onTaskResume(task);
L.d(TAG, "download resume");
mAdapter.updateState(task.getDownloadEntity());
}
@Override public void onTaskRunning(DownloadTask task) {
super.onTaskRunning(task);
mAdapter.setProgress(task.getDownloadEntity());
}
@Override public void onTaskStop(DownloadTask task) {
super.onTaskStop(task);
mAdapter.updateState(task.getDownloadEntity());
}
@Override public void onTaskCancel(DownloadTask task) {
super.onTaskCancel(task);
mAdapter.updateState(task.getDownloadEntity());
}
@Override public void onTaskComplete(DownloadTask task) {
super.onTaskComplete(task);
mAdapter.updateState(task.getDownloadEntity());
}
@Override public void onTaskFail(DownloadTask task) {
super.onTaskFail(task);
L.d(TAG, "download fail");
}
}
}

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.simple.multi_task; package com.arialyy.simple.download.multi_download;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
@ -24,13 +24,11 @@ import android.support.v7.widget.Toolbar;
import android.view.View; import android.view.View;
import butterknife.Bind; import butterknife.Bind;
import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.DownloadEntity; import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.core.task.Task;
import com.arialyy.frame.util.show.L;
import com.arialyy.simple.R; import com.arialyy.simple.R;
import com.arialyy.simple.base.BaseActivity; import com.arialyy.simple.base.BaseActivity;
import com.arialyy.simple.databinding.ActivityMultiBinding; import com.arialyy.simple.databinding.ActivityMultiBinding;
import com.arialyy.simple.module.DownloadModule; import com.arialyy.simple.download.DownloadModule;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -38,9 +36,9 @@ import java.util.List;
* Created by Lyy on 2016/9/27. * Created by Lyy on 2016/9/27.
*/ */
public class MultiTaskActivity extends BaseActivity<ActivityMultiBinding> { public class MultiTaskActivity extends BaseActivity<ActivityMultiBinding> {
@Bind(R.id.list) RecyclerView mList; @Bind(R.id.list) RecyclerView mList;
@Bind(R.id.toolbar) Toolbar mBar; @Bind(R.id.toolbar) Toolbar mBar;
private FileListAdapter mAdapter; private FileListAdapter mAdapter;
List<FileListEntity> mData = new ArrayList<>(); List<FileListEntity> mData = new ArrayList<>();
@Override protected int setLayoutId() { @Override protected int setLayoutId() {
@ -64,17 +62,17 @@ public class MultiTaskActivity extends BaseActivity<ActivityMultiBinding> {
dialog.show(getSupportFragmentManager(), "download_num"); dialog.show(getSupportFragmentManager(), "download_num");
break; break;
case R.id.stop_all: case R.id.stop_all:
Aria.get(this).stopAllTask(); Aria.download(this).stopAllTask();
break; break;
case R.id.turn: case R.id.turn:
startActivity(new Intent(this, DownloadActivity.class)); startActivity(new Intent(this, MultiDownloadActivity.class));
break; break;
} }
} }
@Override protected void onResume() { @Override protected void onResume() {
super.onResume(); super.onResume();
Aria.whit(this).addSchedulerListener(new DownloadListener()); Aria.download(this).addSchedulerListener(new DownloadListener());
} }
@Override protected void onDestroy() { @Override protected void onDestroy() {
@ -89,28 +87,28 @@ public class MultiTaskActivity extends BaseActivity<ActivityMultiBinding> {
} }
} }
private class DownloadListener extends Aria.SimpleSchedulerListener { private class DownloadListener extends Aria.DownloadSchedulerListener {
@Override public void onTaskStart(Task task) { @Override public void onTaskStart(DownloadTask task) {
super.onTaskStart(task); super.onTaskStart(task);
mAdapter.updateBtState(task.getDownloadUrl(), false); mAdapter.updateBtState(task.getDownloadUrl(), false);
} }
@Override public void onTaskRunning(Task task) { @Override public void onTaskRunning(DownloadTask task) {
super.onTaskRunning(task); super.onTaskRunning(task);
} }
@Override public void onTaskResume(Task task) { @Override public void onTaskResume(DownloadTask task) {
super.onTaskResume(task); super.onTaskResume(task);
mAdapter.updateBtState(task.getDownloadUrl(), false); mAdapter.updateBtState(task.getDownloadUrl(), false);
} }
@Override public void onTaskStop(Task task) { @Override public void onTaskStop(DownloadTask task) {
super.onTaskStop(task); super.onTaskStop(task);
mAdapter.updateBtState(task.getDownloadUrl(), true); mAdapter.updateBtState(task.getDownloadUrl(), true);
} }
@Override public void onTaskComplete(Task task) { @Override public void onTaskComplete(DownloadTask task) {
super.onTaskComplete(task); super.onTaskComplete(task);
mAdapter.updateBtState(task.getDownloadUrl(), true); mAdapter.updateBtState(task.getDownloadUrl(), true);
} }

@ -0,0 +1,55 @@
/*
* 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.simple.download.service_download;
import android.app.NotificationManager;
import android.content.Context;
import android.support.v4.app.NotificationCompat;
import com.arialyy.simple.R;
/**
* Created by Aria.Lao on 2017/1/18.
*/
public class DownloadNotification {
private NotificationManager mManager;
private Context mContext;
private NotificationCompat.Builder mBuilder;
private static final int mNotifiyId = 0;
public DownloadNotification(Context context) {
mContext = context;
init();
}
private void init() {
mManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(mContext);
mBuilder.setContentTitle("Aria Download Test")
.setContentText("进度条")
.setProgress(100, 0, false)
.setSmallIcon(R.mipmap.ic_launcher);
mManager.notify(mNotifiyId, mBuilder.build());
}
public void upload(int progress){
if (mBuilder != null) {
mBuilder.setProgress(100, progress, false);
mManager.notify(mNotifiyId, mBuilder.build());
}
}
}

@ -0,0 +1,102 @@
/*
* 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.simple.download.service_download;
import android.app.Service;
import android.content.Intent;
import android.os.Environment;
import android.os.IBinder;
import android.support.annotation.Nullable;
import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.frame.util.show.T;
/**
* Created by Aria.Lao on 2017/4/5.
* 在服务中使用 Aria进行下载
*/
public class DownloadService extends Service {
private static final String DOWNLOAD_URL =
//"http://kotlinlang.org/docs/kotlin-docs.pdf";
//"https://atom-installer.github.com/v1.13.0/AtomSetup.exe?s=1484074138&ext=.exe";
//"http://static.gaoshouyou.com/d/21/e8/61218d78d0e8b79df68dbc18dd484c97.apk";
//不支持断点的链接
"http://ox.konsung.net:5555/ksdc-web/download/downloadFile/?fileName=ksdc_1.0.2.apk&rRange=0-";
private DownloadNotification mNotify;
@Nullable @Override public IBinder onBind(Intent intent) {
return null;
}
@Override public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override public void onCreate() {
super.onCreate();
mNotify = new DownloadNotification(getApplicationContext());
Aria.download(this).addSchedulerListener(new MySchedulerListener());
Aria.download(this)
.load(DOWNLOAD_URL)
.setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/service_task.apk")
.start();
}
@Override public void onDestroy() {
super.onDestroy();
Aria.download(this).removeSchedulerListener();
}
private class MySchedulerListener extends Aria.DownloadSchedulerListener {
@Override public void onNoSupportBreakPoint(DownloadTask task) {
super.onNoSupportBreakPoint(task);
T.showShort(getApplicationContext(), "该下载链接不支持断点");
}
@Override public void onTaskStart(DownloadTask task) {
T.showShort(getApplicationContext(), task.getDownloadEntity().getFileName() + ",开始下载");
}
@Override public void onTaskResume(DownloadTask task) {
super.onTaskResume(task);
}
@Override public void onTaskStop(DownloadTask task) {
T.showShort(getApplicationContext(), task.getDownloadEntity().getFileName() + ",停止下载");
}
@Override public void onTaskCancel(DownloadTask task) {
T.showShort(getApplicationContext(), task.getDownloadEntity().getFileName() + ",取消下载");
}
@Override public void onTaskFail(DownloadTask task) {
T.showShort(getApplicationContext(), task.getDownloadEntity().getFileName() + ",下载失败");
}
@Override public void onTaskComplete(DownloadTask task) {
T.showShort(getApplicationContext(), task.getDownloadEntity().getFileName() + ",下载完成");
mNotify.upload(100);
}
@Override public void onTaskRunning(DownloadTask task) {
long len = task.getFileSize();
int p = (int) (task.getCurrentProgress() * 100 / len);
mNotify.upload(p);
}
}
}

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

Loading…
Cancel
Save