Merge branch 'v_2.0'
This commit is contained in:
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@ -37,7 +37,7 @@
|
||||
<ConfirmationsSetting value="0" id="Add" />
|
||||
<ConfirmationsSetting value="0" id="Remove" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
@ -7,8 +7,8 @@ android {
|
||||
defaultConfig {
|
||||
minSdkVersion 9
|
||||
targetSdkVersion 23
|
||||
versionCode 80
|
||||
versionName "2.3.2"
|
||||
versionCode 81
|
||||
versionName "2.3.3"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
@ -23,4 +23,4 @@ dependencies {
|
||||
testCompile 'junit:junit:4.12'
|
||||
compile 'com.android.support:appcompat-v7:23.1.1'
|
||||
}
|
||||
//apply from: 'jcenter.gradle'
|
||||
apply from: 'jcenter.gradle'
|
||||
|
@ -3,7 +3,7 @@ version = PROJ_VERSION
|
||||
project.archivesBaseName = PROJ_ARTIFACT_ID
|
||||
apply plugin: 'com.jfrog.bintray'
|
||||
apply plugin: 'com.github.dcendents.android-maven'
|
||||
//输入:gradlew bintrayupload 执行
|
||||
//输入:gradlew bintray 执行
|
||||
|
||||
//############################## jar、sources、doc 打包 start #######################################
|
||||
task sourcesJar(type: Jar) {
|
||||
@ -75,9 +75,10 @@ artifacts {
|
||||
|
||||
//################################# jcenter 上传配置 start #########################################
|
||||
bintray {
|
||||
user = hasProperty("bintrayUser") ? getProperty("bintrayUser") : getProperty("BINTRAY_USER")
|
||||
key = hasProperty("bintrayKey") ? getProperty("bintrayKey") : getProperty("BINTRAY_KEY")
|
||||
|
||||
// user = hasProperty("bintrayUser") ? getProperty("bintrayUser") : getProperty("BINTRAY_USER")
|
||||
// key = hasProperty("bintrayKey") ? getProperty("bintrayKey") : getProperty("BINTRAY_KEY")
|
||||
user = BINTRAY_USER
|
||||
key = BINTRAY_KEY
|
||||
configurations = ['archives']
|
||||
|
||||
pkg {
|
||||
|
@ -15,7 +15,12 @@
|
||||
*/
|
||||
package com.arialyy.aria.core;
|
||||
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
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.
|
||||
@ -25,19 +30,36 @@ public class AMReceiver {
|
||||
Object obj;
|
||||
OnSchedulerListener listener;
|
||||
DownloadEntity entity;
|
||||
DownloadManager manager = DownloadManager.getInstance();
|
||||
|
||||
public AMTarget load(DownloadEntity entity) {
|
||||
/**
|
||||
* {@link #load(String)},请使用该方法
|
||||
*/
|
||||
@Deprecated public AMTarget load(DownloadEntity entity) {
|
||||
this.entity = entity;
|
||||
return new AMTarget(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取下载链接
|
||||
*/
|
||||
public AMTarget load(@NonNull String downloadUrl) {
|
||||
CheckUtil.checkDownloadUrl(downloadUrl);
|
||||
if (entity == null) {
|
||||
entity = DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl);
|
||||
}
|
||||
if (entity == null) {
|
||||
entity = new DownloadEntity();
|
||||
}
|
||||
entity.setDownloadUrl(downloadUrl);
|
||||
return new AMTarget(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加调度器回调
|
||||
*/
|
||||
public AMReceiver addSchedulerListener(OnSchedulerListener listener) {
|
||||
this.listener = listener;
|
||||
manager.getTaskQueue().getDownloadSchedulers().addSchedulerListener(obj, listener);
|
||||
DownloadSchedulers.getInstance().addSchedulerListener(obj, listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -46,8 +68,13 @@ public class AMReceiver {
|
||||
*/
|
||||
public AMReceiver removeSchedulerListener() {
|
||||
if (listener != null) {
|
||||
manager.getTaskQueue().getDownloadSchedulers().removeSchedulerListener(obj, listener);
|
||||
DownloadSchedulers.getInstance().removeSchedulerListener(obj, listener);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
void destroy() {
|
||||
obj = null;
|
||||
listener = null;
|
||||
}
|
||||
}
|
@ -15,10 +15,11 @@
|
||||
*/
|
||||
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.scheduler.OnSchedulerListener;
|
||||
import com.arialyy.aria.core.command.IDownloadCmd;
|
||||
import com.arialyy.aria.core.task.Task;
|
||||
import com.arialyy.aria.util.CheckUtil;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -28,18 +29,68 @@ import java.util.List;
|
||||
* https://github.com/AriaLyy/Aria
|
||||
*/
|
||||
public class AMTarget {
|
||||
private AMReceiver receiver;
|
||||
private AMReceiver mReceiver;
|
||||
|
||||
public AMTarget(AMReceiver receiver) {
|
||||
this.receiver = receiver;
|
||||
AMTarget(AMReceiver receiver) {
|
||||
this.mReceiver = receiver;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置文件存储路径
|
||||
*/
|
||||
public AMTarget setDownloadPath(@NonNull String downloadPath) {
|
||||
if (TextUtils.isEmpty(downloadPath)) {
|
||||
throw new IllegalArgumentException("文件保持路径不能为null");
|
||||
}
|
||||
mReceiver.entity.setDownloadPath(downloadPath);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置文件名
|
||||
*/
|
||||
public AMTarget setDownloadName(@NonNull String downloadName) {
|
||||
if (TextUtils.isEmpty(downloadName)) {
|
||||
throw new IllegalArgumentException("文件名不能为null");
|
||||
}
|
||||
mReceiver.entity.setFileName(downloadName);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下载文件大小
|
||||
*/
|
||||
public long getFileSize() {
|
||||
DownloadEntity entity = getDownloadEntity(mReceiver.entity.getDownloadUrl());
|
||||
if (entity == null) {
|
||||
throw new NullPointerException("下载管理器中没有改任务");
|
||||
}
|
||||
return entity.getFileSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前下载进度,如果下載实体存在,则返回当前进度
|
||||
*/
|
||||
public long getCurrentProgress() {
|
||||
DownloadEntity entity = getDownloadEntity(mReceiver.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() {
|
||||
receiver.manager.setCmd(
|
||||
CommonUtil.createCmd(receiver.obj, receiver.entity, CmdFactory.TASK_CREATE)).exe();
|
||||
DownloadManager.getInstance()
|
||||
.setCmd(CommonUtil.createCmd(mReceiver.obj, mReceiver.entity, CmdFactory.TASK_CREATE))
|
||||
.exe();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -47,67 +98,51 @@ public class AMTarget {
|
||||
*/
|
||||
public void start() {
|
||||
List<IDownloadCmd> cmds = new ArrayList<>();
|
||||
cmds.add(CommonUtil.createCmd(receiver.obj, receiver.entity, CmdFactory.TASK_CREATE));
|
||||
cmds.add(CommonUtil.createCmd(receiver.obj, receiver.entity, CmdFactory.TASK_START));
|
||||
receiver.manager.setCmds(cmds).exe();
|
||||
cmds.add(CommonUtil.createCmd(mReceiver.obj, mReceiver.entity, CmdFactory.TASK_CREATE));
|
||||
cmds.add(CommonUtil.createCmd(mReceiver.obj, mReceiver.entity, CmdFactory.TASK_START));
|
||||
DownloadManager.getInstance().setCmds(cmds).exe();
|
||||
cmds.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止下载
|
||||
*/
|
||||
public void stop() {
|
||||
receiver.manager.setCmd(
|
||||
CommonUtil.createCmd(receiver.obj, receiver.entity, CmdFactory.TASK_STOP)).exe();
|
||||
DownloadManager.getInstance()
|
||||
.setCmd(CommonUtil.createCmd(mReceiver.obj, mReceiver.entity, CmdFactory.TASK_STOP))
|
||||
.exe();
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复下载
|
||||
*/
|
||||
public void resume() {
|
||||
receiver.manager.setCmd(
|
||||
CommonUtil.createCmd(receiver.obj, receiver.entity, CmdFactory.TASK_START)).exe();
|
||||
DownloadManager.getInstance()
|
||||
.setCmd(CommonUtil.createCmd(mReceiver.obj, mReceiver.entity, CmdFactory.TASK_START))
|
||||
.exe();
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消下载
|
||||
*/
|
||||
public void cancel() {
|
||||
receiver.manager.setCmd(
|
||||
CommonUtil.createCmd(receiver.obj, receiver.entity, CmdFactory.TASK_CANCEL)).exe();
|
||||
DownloadManager.getInstance()
|
||||
.setCmd(CommonUtil.createCmd(mReceiver.obj, mReceiver.entity, CmdFactory.TASK_CANCEL))
|
||||
.exe();
|
||||
}
|
||||
|
||||
public static class SimpleSchedulerListener implements OnSchedulerListener {
|
||||
/**
|
||||
* 是否在下载
|
||||
*/
|
||||
public boolean isDownloading() {
|
||||
return DownloadManager.getInstance().getTaskQueue().getTask(mReceiver.entity).isDownloading();
|
||||
}
|
||||
|
||||
@Override public void onTaskPre(Task task) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onTaskResume(Task task) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onTaskStart(Task task) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onTaskStop(Task task) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onTaskCancel(Task task) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onTaskFail(Task task) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onTaskComplete(Task task) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onTaskRunning(Task task) {
|
||||
|
||||
}
|
||||
/**
|
||||
* 重新下载
|
||||
*/
|
||||
public void reStart() {
|
||||
cancel();
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
@ -19,23 +19,90 @@ package com.arialyy.aria.core;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.app.Fragment;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import com.arialyy.aria.core.scheduler.OnSchedulerListener;
|
||||
import com.arialyy.aria.core.task.Task;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2016/12/1.
|
||||
* https://github.com/AriaLyy/Aria
|
||||
* Aria启动,管理全局任务
|
||||
* <pre>
|
||||
* <code>
|
||||
* DownloadEntity mEntity = new DownloadEntity();
|
||||
* mEntity.setFileName(fileName); //设置文件名
|
||||
* mEntity.setDownloadUrl(downloadUrl); //设置下载链接
|
||||
* mEntity.setDownloadPath(downloadPath); //设置存放路径
|
||||
*
|
||||
* //启动下载
|
||||
* Aria.whit(this).load(mEntity).start();
|
||||
* </code>
|
||||
* </pre>
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) public class Aria {
|
||||
/**
|
||||
* 预处理完成
|
||||
*/
|
||||
public static final String ACTION_PRE = "ACTION_PRE";
|
||||
/**
|
||||
* 下载开始前事件
|
||||
*/
|
||||
public static final String ACTION_POST_PRE = "ACTION_POST_PRE";
|
||||
/**
|
||||
* 开始下载事件
|
||||
*/
|
||||
public static final String ACTION_START = "ACTION_START";
|
||||
/**
|
||||
* 恢复下载事件
|
||||
*/
|
||||
public static final String ACTION_RESUME = "ACTION_RESUME";
|
||||
/**
|
||||
* 正在下载事件
|
||||
*/
|
||||
public static final String ACTION_RUNNING = "ACTION_RUNNING";
|
||||
/**
|
||||
* 停止下载事件
|
||||
*/
|
||||
public static final String ACTION_STOP = "ACTION_STOP";
|
||||
/**
|
||||
* 取消下载事件
|
||||
*/
|
||||
public static final String ACTION_CANCEL = "ACTION_CANCEL";
|
||||
/**
|
||||
* 下载完成事件
|
||||
*/
|
||||
public static final String ACTION_COMPLETE = "ACTION_COMPLETE";
|
||||
/**
|
||||
* 下载失败事件
|
||||
*/
|
||||
public static final String ACTION_FAIL = "ACTION_FAIL";
|
||||
/**
|
||||
* 下载实体
|
||||
*/
|
||||
public static final String ENTITY = "DOWNLOAD_ENTITY";
|
||||
/**
|
||||
* 位置
|
||||
*/
|
||||
public static final String CURRENT_LOCATION = "CURRENT_LOCATION";
|
||||
/**
|
||||
* 速度
|
||||
*/
|
||||
public static final String CURRENT_SPEED = "CURRENT_SPEED";
|
||||
|
||||
private Aria() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 接受Activity、Service、Application
|
||||
*/
|
||||
public static AMReceiver whit(Context context) {
|
||||
if (context == null) throw new IllegalArgumentException("context 不能为 null");
|
||||
//if (context == null) throw new IllegalArgumentException("context 不能为 null");
|
||||
checkNull(context);
|
||||
if (context instanceof Activity
|
||||
|| context instanceof Service
|
||||
|| context instanceof Application) {
|
||||
@ -45,12 +112,31 @@ import android.os.Build;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理Fragment、或者DialogFragment
|
||||
*/
|
||||
public static AMReceiver whit(Fragment fragment) {
|
||||
checkNull(fragment);
|
||||
return AriaManager.getInstance(
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? fragment.getContext()
|
||||
: fragment.getActivity()).get(fragment);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理Dialog
|
||||
*/
|
||||
public static AMReceiver whit(Dialog dialog) {
|
||||
checkNull(dialog);
|
||||
return AriaManager.getInstance(dialog.getContext()).get(dialog);
|
||||
}
|
||||
|
||||
private static void checkNull(Object obj) {
|
||||
if (obj == null) throw new IllegalArgumentException("不能传入空对象");
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理通用事件
|
||||
*/
|
||||
public static AriaManager get(Context context) {
|
||||
if (context == null) throw new IllegalArgumentException("context 不能为 null");
|
||||
if (context instanceof Activity
|
||||
@ -61,4 +147,39 @@ import android.os.Build;
|
||||
throw new IllegalArgumentException("这是不支持的context");
|
||||
}
|
||||
}
|
||||
|
||||
public static class SimpleSchedulerListener implements OnSchedulerListener {
|
||||
|
||||
@Override public void onTaskPre(Task task) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onTaskResume(Task task) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onTaskStart(Task task) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onTaskStop(Task task) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onTaskCancel(Task task) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onTaskFail(Task task) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onTaskComplete(Task task) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onTaskRunning(Task task) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,17 +18,23 @@ package com.arialyy.aria.core;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.app.Dialog;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.command.CmdFactory;
|
||||
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 java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -69,7 +75,7 @@ import java.util.Set;
|
||||
/**
|
||||
* 获取下载列表
|
||||
*/
|
||||
public List<DownloadEntity> getDownloadList(){
|
||||
public List<DownloadEntity> getDownloadList() {
|
||||
return DownloadEntity.findAllData(DownloadEntity.class);
|
||||
}
|
||||
|
||||
@ -77,11 +83,15 @@ import java.util.Set;
|
||||
* 通过下载链接获取下载实体
|
||||
*/
|
||||
public DownloadEntity getDownloadEntity(String downloadUrl) {
|
||||
if (TextUtils.isEmpty(downloadUrl)) {
|
||||
throw new IllegalArgumentException("下载链接不能为null");
|
||||
}
|
||||
return DownloadEntity.findData(DownloadEntity.class, new String[] { "downloadUrl" },
|
||||
new String[] { downloadUrl });
|
||||
CheckUtil.checkDownloadUrl(downloadUrl);
|
||||
return DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载任务是否存在
|
||||
*/
|
||||
public boolean taskExists(String downloadUrl) {
|
||||
return DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,8 +111,7 @@ import java.util.Set;
|
||||
/**
|
||||
* 设置下载超时时间
|
||||
*/
|
||||
@Deprecated
|
||||
private AriaManager setTimeOut(int timeOut) {
|
||||
@Deprecated private AriaManager setTimeOut(int timeOut) {
|
||||
Configuration.getInstance().setTimeOut(timeOut);
|
||||
return this;
|
||||
}
|
||||
@ -165,20 +174,61 @@ import java.util.Set;
|
||||
|
||||
private AMReceiver putTarget(Object obj) {
|
||||
String clsName = obj.getClass().getName();
|
||||
AMReceiver target = mTargets.get(clsName);
|
||||
if (target == null) {
|
||||
target = new AMReceiver();
|
||||
target.obj = obj;
|
||||
AMReceiver target = null;
|
||||
String key = "";
|
||||
if (!(obj instanceof Activity)) {
|
||||
if (obj instanceof android.support.v4.app.Fragment) {
|
||||
clsName += "_" + ((Fragment) obj).getActivity().getClass().getName();
|
||||
key = clsName + "_" + ((Fragment) obj).getActivity().getClass().getName();
|
||||
} else if (obj instanceof android.app.Fragment) {
|
||||
clsName += "_" + ((android.app.Fragment) obj).getActivity().getClass().getName();
|
||||
key = clsName + "_" + ((android.app.Fragment) obj).getActivity().getClass().getName();
|
||||
} else if (obj instanceof Dialog) {
|
||||
Activity activity = ((Dialog) obj).getOwnerActivity();
|
||||
if (activity != null) {
|
||||
key = clsName + "_" + activity.getClass().getName();
|
||||
}
|
||||
handleDialogDialogLift((Dialog) obj);
|
||||
}
|
||||
} else {
|
||||
key = clsName;
|
||||
}
|
||||
if (TextUtils.isEmpty(key)) {
|
||||
throw new IllegalArgumentException("未知类型");
|
||||
} else {
|
||||
target = mTargets.get(key);
|
||||
if (target == null) {
|
||||
target = new AMReceiver();
|
||||
target.obj = obj;
|
||||
mTargets.put(key, target);
|
||||
}
|
||||
mTargets.put(clsName, target);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理对话框取消或dismiss
|
||||
*/
|
||||
private void handleDialogDialogLift(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.setCancelMessage(createCancelMessage());
|
||||
}
|
||||
} else {
|
||||
dialog.setCancelMessage(createDismissMessage());
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private AMReceiver getTarget(Object obj) {
|
||||
AMReceiver target = mTargets.get(obj.getClass().getName());
|
||||
if (target == null) {
|
||||
@ -198,6 +248,56 @@ import java.util.Set;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Dialog取消消息
|
||||
*/
|
||||
private Message createCancelMessage() {
|
||||
final Message cancelMsg = new Message();
|
||||
cancelMsg.what = 0x44;
|
||||
cancelMsg.obj = new Dialog.OnCancelListener() {
|
||||
|
||||
@Override public void onCancel(DialogInterface dialog) {
|
||||
destroySchedulerListener(dialog);
|
||||
}
|
||||
};
|
||||
return cancelMsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Dialog dismiss取消消息
|
||||
*/
|
||||
private Message createDismissMessage() {
|
||||
final Message cancelMsg = new Message();
|
||||
cancelMsg.what = 0x43;
|
||||
cancelMsg.obj = new Dialog.OnDismissListener() {
|
||||
|
||||
@Override public void onDismiss(DialogInterface dialog) {
|
||||
destroySchedulerListener(dialog);
|
||||
}
|
||||
};
|
||||
return cancelMsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* onDestroy
|
||||
*/
|
||||
private void destroySchedulerListener(Object obj) {
|
||||
Set<String> keys = mTargets.keySet();
|
||||
String clsName = obj.getClass().getName();
|
||||
for (String key : keys) {
|
||||
if (key.equals(clsName) || key.contains(clsName)) {
|
||||
AMReceiver receiver = mTargets.get(key);
|
||||
if (receiver.obj != null) {
|
||||
if (receiver.obj instanceof Application || receiver.obj instanceof Service) break;
|
||||
receiver.removeSchedulerListener();
|
||||
receiver.destroy();
|
||||
mTargets.remove(key);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Activity生命周期
|
||||
*/
|
||||
@ -228,19 +328,7 @@ import java.util.Set;
|
||||
}
|
||||
|
||||
@Override public void onActivityDestroyed(Activity activity) {
|
||||
Set<String> keys = mTargets.keySet();
|
||||
for (String key : keys) {
|
||||
String clsName = activity.getClass().getName();
|
||||
if (key.equals(clsName) || key.contains(clsName)) {
|
||||
AMReceiver target = mTargets.get(key);
|
||||
if (target.obj != null) {
|
||||
if (target.obj instanceof Application || target.obj instanceof Service) break;
|
||||
target.removeSchedulerListener();
|
||||
mTargets.remove(key);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
destroySchedulerListener(activity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,54 +31,6 @@ import java.util.List;
|
||||
* 下载管理器,通过命令的方式控制下载
|
||||
*/
|
||||
public class DownloadManager {
|
||||
/**
|
||||
* 预处理完成
|
||||
*/
|
||||
public static final String ACTION_PRE = "ACTION_PRE";
|
||||
/**
|
||||
* 下载开始前事件
|
||||
*/
|
||||
public static final String ACTION_POST_PRE = "ACTION_POST_PRE";
|
||||
/**
|
||||
* 开始下载事件
|
||||
*/
|
||||
public static final String ACTION_START = "ACTION_START";
|
||||
/**
|
||||
* 恢复下载事件
|
||||
*/
|
||||
public static final String ACTION_RESUME = "ACTION_RESUME";
|
||||
/**
|
||||
* 正在下载事件
|
||||
*/
|
||||
public static final String ACTION_RUNNING = "ACTION_RUNNING";
|
||||
/**
|
||||
* 停止下载事件
|
||||
*/
|
||||
public static final String ACTION_STOP = "ACTION_STOP";
|
||||
/**
|
||||
* 取消下载事件
|
||||
*/
|
||||
public static final String ACTION_CANCEL = "ACTION_CANCEL";
|
||||
/**
|
||||
* 下载完成事件
|
||||
*/
|
||||
public static final String ACTION_COMPLETE = "ACTION_COMPLETE";
|
||||
/**
|
||||
* 下载失败事件
|
||||
*/
|
||||
public static final String ACTION_FAIL = "ACTION_FAIL";
|
||||
/**
|
||||
* 下载实体
|
||||
*/
|
||||
public static final String ENTITY = "DOWNLOAD_ENTITY";
|
||||
/**
|
||||
* 位置
|
||||
*/
|
||||
public static final String CURRENT_LOCATION = "CURRENT_LOCATION";
|
||||
/**
|
||||
* 速度
|
||||
*/
|
||||
public static final String CURRENT_SPEED = "CURRENT_SPEED";
|
||||
private static final String TAG = "DownloadManager";
|
||||
private static final Object LOCK = new Object();
|
||||
private static volatile DownloadManager INSTANCE = null;
|
||||
|
@ -25,6 +25,7 @@ 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;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2016/8/17.
|
||||
@ -34,8 +35,8 @@ public class DownloadTaskQueue implements ITaskQueue {
|
||||
private static final String TAG = "DownloadTaskQueue";
|
||||
private CachePool mCachePool = CachePool.getInstance();
|
||||
private ExecutePool mExecutePool = ExecutePool.getInstance();
|
||||
private Context mContext;
|
||||
private IDownloadSchedulers mSchedulers;
|
||||
private Context mContext;
|
||||
//private IDownloadSchedulers mSchedulers;
|
||||
|
||||
private DownloadTaskQueue() {
|
||||
}
|
||||
@ -106,6 +107,10 @@ public class DownloadTaskQueue implements ITaskQueue {
|
||||
}
|
||||
|
||||
@Override public void reTryStart(Task task) {
|
||||
if (task == null) {
|
||||
Log.w(TAG, "重试下载失败,task 为null");
|
||||
return;
|
||||
}
|
||||
if (!task.isDownloading()) {
|
||||
task.start();
|
||||
} else {
|
||||
@ -113,25 +118,54 @@ public class DownloadTaskQueue implements ITaskQueue {
|
||||
}
|
||||
}
|
||||
|
||||
@Override public IDownloadSchedulers getDownloadSchedulers() {
|
||||
return mSchedulers;
|
||||
}
|
||||
//@Override public IDownloadSchedulers getDownloadSchedulers() {
|
||||
// return mSchedulers;
|
||||
//}
|
||||
|
||||
@Override public int size() {
|
||||
return mExecutePool.size();
|
||||
}
|
||||
|
||||
@Override public void setDownloadNum(int downloadNum) {
|
||||
//原始长度
|
||||
int size = Configuration.getInstance().getDownloadNum();
|
||||
int diff = downloadNum - size;
|
||||
if (size == downloadNum) {
|
||||
Log.d(TAG, "设置的下载任务数和配置文件的下载任务数一直,跳过");
|
||||
return;
|
||||
}
|
||||
//设置的任务数小于配置任务数
|
||||
if (diff <= -1 && mExecutePool.size() >= size) {
|
||||
for (int i = 0, len = Math.abs(diff); i < len; i++) {
|
||||
Task eTask = mExecutePool.pollTask();
|
||||
if (eTask != null) {
|
||||
stopTask(eTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
mExecutePool.setDownloadNum(downloadNum);
|
||||
if (diff >= 1) {
|
||||
for (int i = 0; i < diff; i++) {
|
||||
Task nextTask = getNextTask();
|
||||
if (nextTask != null
|
||||
&& nextTask.getDownloadEntity().getState() == DownloadEntity.STATE_WAIT) {
|
||||
startTask(nextTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public Task createTask(Object target, DownloadEntity entity) {
|
||||
Task task;
|
||||
if (target == null) {
|
||||
task = TaskFactory.getInstance().createTask(mContext, entity, mSchedulers);
|
||||
//task = TaskFactory.getInstance().createTask(mContext, entity, mSchedulers);
|
||||
task = TaskFactory.getInstance()
|
||||
.createTask(mContext, entity, DownloadSchedulers.getInstance());
|
||||
} else {
|
||||
task = TaskFactory.getInstance()
|
||||
.createTask(target.getClass().getName(), mContext, entity, mSchedulers);
|
||||
//.createTask(target.getClass().getName(), mContext, entity, mSchedulers);
|
||||
.createTask(target.getClass().getName(), mContext, entity,
|
||||
DownloadSchedulers.getInstance());
|
||||
}
|
||||
mCachePool.putTask(task);
|
||||
return task;
|
||||
@ -163,9 +197,9 @@ public class DownloadTaskQueue implements ITaskQueue {
|
||||
return mCachePool.pollTask();
|
||||
}
|
||||
|
||||
@Override public void setScheduler(IDownloadSchedulers schedulers) {
|
||||
mSchedulers = schedulers;
|
||||
}
|
||||
//@Override public void setScheduler(IDownloadSchedulers schedulers) {
|
||||
// mSchedulers = schedulers;
|
||||
//}
|
||||
|
||||
public static class Builder {
|
||||
Context context;
|
||||
@ -175,17 +209,17 @@ public class DownloadTaskQueue implements ITaskQueue {
|
||||
this.context = context.getApplicationContext();
|
||||
}
|
||||
|
||||
public Builder setDownloadSchedulers(IDownloadSchedulers schedulers) {
|
||||
this.schedulers = schedulers;
|
||||
return this;
|
||||
}
|
||||
//public Builder setDownloadSchedulers(IDownloadSchedulers schedulers) {
|
||||
// this.schedulers = schedulers;
|
||||
// return this;
|
||||
//}
|
||||
|
||||
public DownloadTaskQueue build() {
|
||||
DownloadTaskQueue queue = new DownloadTaskQueue(context);
|
||||
if (schedulers == null) {
|
||||
schedulers = DownloadSchedulers.getInstance(queue);
|
||||
}
|
||||
queue.setScheduler(schedulers);
|
||||
//if (schedulers == null) {
|
||||
// schedulers = DownloadSchedulers.getInstance();
|
||||
//}
|
||||
//queue.setScheduler(schedulers);
|
||||
return queue;
|
||||
}
|
||||
}
|
||||
|
@ -26,10 +26,10 @@ import com.arialyy.aria.core.task.Task;
|
||||
*/
|
||||
public interface ITaskQueue extends IDownloader {
|
||||
|
||||
/**
|
||||
* 获取调度器
|
||||
*/
|
||||
public IDownloadSchedulers getDownloadSchedulers();
|
||||
///**
|
||||
// * 获取调度器
|
||||
// */
|
||||
//public IDownloadSchedulers getDownloadSchedulers();
|
||||
|
||||
/**
|
||||
* 任务池队列大小
|
||||
@ -74,10 +74,10 @@ public interface ITaskQueue extends IDownloader {
|
||||
*/
|
||||
public Task getNextTask();
|
||||
|
||||
/**
|
||||
* 设置下载调度器
|
||||
*
|
||||
* @param schedulers 下载调度器{@link IDownloadSchedulers}
|
||||
*/
|
||||
public void setScheduler(IDownloadSchedulers schedulers);
|
||||
///**
|
||||
// * 设置下载调度器
|
||||
// *
|
||||
// * @param schedulers 下载调度器{@link IDownloadSchedulers}
|
||||
// */
|
||||
//public void setScheduler(IDownloadSchedulers schedulers);
|
||||
}
|
@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package com.arialyy.aria.core.queue.pool;
|
||||
|
||||
import android.text.TextUtils;
|
||||
@ -25,6 +24,7 @@ import com.arialyy.aria.core.task.Task;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2016/8/14.
|
||||
@ -35,6 +35,7 @@ public class CachePool implements IPool {
|
||||
private static final Object LOCK = new Object();
|
||||
private static final int MAX_NUM = Integer.MAX_VALUE; //最大下载任务数
|
||||
private static volatile CachePool INSTANCE = null;
|
||||
private static final long TIME_OUT = 1000;
|
||||
private Map<String, Task> mCacheArray;
|
||||
private LinkedBlockingQueue<Task> mCacheQueue;
|
||||
|
||||
@ -75,13 +76,19 @@ public class CachePool implements IPool {
|
||||
|
||||
@Override public Task pollTask() {
|
||||
synchronized (LOCK) {
|
||||
Task task = mCacheQueue.poll();
|
||||
if (task != null) {
|
||||
String url = task.getDownloadEntity().getDownloadUrl();
|
||||
mCacheArray.remove(CommonUtil.keyToHashKey(url));
|
||||
try {
|
||||
Task task = null;
|
||||
task = mCacheQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS);
|
||||
if (task != null) {
|
||||
String url = task.getDownloadEntity().getDownloadUrl();
|
||||
mCacheArray.remove(CommonUtil.keyToHashKey(url));
|
||||
}
|
||||
return task;
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return task;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override public Task getTask(String downloadUrl) {
|
||||
|
@ -137,12 +137,18 @@ public class ExecutePool implements IPool {
|
||||
|
||||
@Override public Task pollTask() {
|
||||
synchronized (LOCK) {
|
||||
Task task = mExecuteQueue.poll();
|
||||
if (task != null) {
|
||||
String url = task.getDownloadEntity().getDownloadUrl();
|
||||
mExecuteArray.remove(CommonUtil.keyToHashKey(url));
|
||||
try {
|
||||
Task task = null;
|
||||
task = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS);
|
||||
if (task != null) {
|
||||
String url = task.getDownloadEntity().getDownloadUrl();
|
||||
mExecuteArray.remove(CommonUtil.keyToHashKey(url));
|
||||
}
|
||||
return task;
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return task;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,12 +19,12 @@ package com.arialyy.aria.core.scheduler;
|
||||
import android.os.Message;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.DownloadManager;
|
||||
import com.arialyy.aria.core.queue.ITaskQueue;
|
||||
import com.arialyy.aria.core.DownloadEntity;
|
||||
import com.arialyy.aria.core.task.Task;
|
||||
import com.arialyy.aria.core.queue.pool.ExecutePool;
|
||||
import com.arialyy.aria.core.queue.DownloadTaskQueue;
|
||||
import com.arialyy.aria.util.Configuration;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@ -69,30 +69,54 @@ public class DownloadSchedulers implements IDownloadSchedulers {
|
||||
private static final Object LOCK = new Object();
|
||||
private static volatile DownloadSchedulers INSTANCE = null;
|
||||
|
||||
/**
|
||||
* 超时时间
|
||||
*/
|
||||
long mTimeOut = 10000;
|
||||
|
||||
/**
|
||||
* 下载器任务监听
|
||||
*/
|
||||
Map<String, OnSchedulerListener> mSchedulerListeners = new ConcurrentHashMap<>();
|
||||
DownloadManager mManager = DownloadManager.getInstance();
|
||||
ITaskQueue mQueue;
|
||||
|
||||
public DownloadSchedulers(ITaskQueue downloadTaskQueue) {
|
||||
mQueue = downloadTaskQueue;
|
||||
private DownloadSchedulers() {
|
||||
mQueue = mManager.getTaskQueue();
|
||||
}
|
||||
|
||||
public static DownloadSchedulers getInstance(DownloadTaskQueue queue) {
|
||||
public static DownloadSchedulers getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (LOCK) {
|
||||
INSTANCE = new DownloadSchedulers(queue);
|
||||
//INSTANCE = new DownloadSchedulers(queue);
|
||||
INSTANCE = new DownloadSchedulers();
|
||||
}
|
||||
}
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override public void addSchedulerListener(Object target, OnSchedulerListener schedulerListener) {
|
||||
if (target == null) {
|
||||
throw new IllegalArgumentException("target 不能为null");
|
||||
}
|
||||
String name = target.getClass().getName();
|
||||
if (mSchedulerListeners.get(name) != null) {
|
||||
Log.w(TAG, "监听器已存在");
|
||||
return;
|
||||
}
|
||||
mSchedulerListeners.put(name, schedulerListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSchedulerListener(Object target, OnSchedulerListener schedulerListener) {
|
||||
if (target == null) {
|
||||
throw new IllegalArgumentException("target 不能为null");
|
||||
}
|
||||
//OnSchedulerListener listener = mSchedulerListeners.get(target.getClass().getName());
|
||||
//mSchedulerListeners.remove(listener);
|
||||
//该内存溢出解决方案:http://stackoverflow.com/questions/14585829/how-safe-is-to-delete-already-removed-concurrenthashmap-element
|
||||
for (Iterator<Map.Entry<String, OnSchedulerListener>> iter =
|
||||
mSchedulerListeners.entrySet().iterator(); iter.hasNext(); ) {
|
||||
Map.Entry<String, OnSchedulerListener> entry = iter.next();
|
||||
if (entry.getKey().equals(target.getClass().getName())) iter.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@Override public boolean handleMessage(Message msg) {
|
||||
Task task = (Task) msg.obj;
|
||||
if (task == null) {
|
||||
@ -104,6 +128,7 @@ public class DownloadSchedulers implements IDownloadSchedulers {
|
||||
switch (msg.what) {
|
||||
case STOP:
|
||||
case CANCEL:
|
||||
mQueue.removeTask(entity);
|
||||
mQueue.removeTask(entity);
|
||||
if (mQueue.size() != Configuration.getInstance().getDownloadNum()) {
|
||||
startNextTask(entity);
|
||||
@ -174,19 +199,23 @@ public class DownloadSchedulers implements IDownloadSchedulers {
|
||||
*
|
||||
* @param entity 失败实体
|
||||
*/
|
||||
@Override public void handleFailTask(DownloadEntity entity) {
|
||||
final Configuration config = Configuration.getInstance();
|
||||
if (entity.getFailNum() <= config.getReTryNum()) {
|
||||
Task task = mQueue.getTask(entity);
|
||||
mQueue.reTryStart(task);
|
||||
try {
|
||||
Thread.currentThread().sleep(config.getReTryInterval());
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
@Override public void handleFailTask(final DownloadEntity entity) {
|
||||
new Thread(new Runnable() {
|
||||
@Override public void run() {
|
||||
final Configuration config = Configuration.getInstance();
|
||||
if (entity.getFailNum() <= config.getReTryNum()) {
|
||||
Task task = mQueue.getTask(entity);
|
||||
mQueue.reTryStart(task);
|
||||
try {
|
||||
Thread.sleep(config.getReTryInterval());
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
startNextTask(entity);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
startNextTask(entity);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -205,24 +234,4 @@ public class DownloadSchedulers implements IDownloadSchedulers {
|
||||
mQueue.startTask(newTask);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void addSchedulerListener(Object target, OnSchedulerListener schedulerListener) {
|
||||
if (target == null) {
|
||||
throw new IllegalArgumentException("target 不能为null");
|
||||
}
|
||||
String name = target.getClass().getName();
|
||||
if (mSchedulerListeners.get(name) != null) {
|
||||
Log.w(TAG, "监听器已存在");
|
||||
return;
|
||||
}
|
||||
mSchedulerListeners.put(name, schedulerListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSchedulerListener(Object target, OnSchedulerListener schedulerListener) {
|
||||
if (target == null) {
|
||||
throw new IllegalArgumentException("target 不能为null");
|
||||
}
|
||||
mSchedulerListeners.remove(target.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,10 @@ class DownloadListener implements IDownloadListener {
|
||||
|
||||
}
|
||||
|
||||
@Override public void supportBreakpoint(boolean support) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onCancel() {
|
||||
|
||||
}
|
||||
|
@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package com.arialyy.aria.core.task;
|
||||
|
||||
import android.content.Context;
|
||||
@ -38,7 +37,7 @@ import java.util.concurrent.Executors;
|
||||
* Created by lyy on 2015/8/25.
|
||||
* 下载工具类
|
||||
*/
|
||||
final class DownloadUtil implements IDownloadUtil {
|
||||
final class DownloadUtil implements IDownloadUtil, Runnable {
|
||||
private static final String TAG = "DownloadUtil";
|
||||
private static final Object LOCK = new Object();
|
||||
/**
|
||||
@ -47,22 +46,26 @@ final class DownloadUtil implements IDownloadUtil {
|
||||
private final int THREAD_NUM;
|
||||
//下载监听
|
||||
private IDownloadListener mListener;
|
||||
private int mConnectTimeOut = 5000 * 4; //连接超时时间
|
||||
private int mReadTimeOut = 5000 * 20; //流读取的超时时间
|
||||
private int mConnectTimeOut = 5000 * 4; //连接超时时间
|
||||
private int mReadTimeOut = 5000 * 20; //流读取的超时时间
|
||||
/**
|
||||
* 已经完成下载任务的线程数量
|
||||
*/
|
||||
private int mCompleteThreadNum = 0;
|
||||
private boolean isDownloading = false;
|
||||
private boolean isStop = false;
|
||||
private boolean isCancel = false;
|
||||
private boolean isNewTask = true;
|
||||
private int mCancelNum = 0;
|
||||
private long mCurrentLocation = 0;
|
||||
private int mStopNum = 0;
|
||||
private boolean isDownloading = false;
|
||||
private boolean isStop = false;
|
||||
private boolean isCancel = false;
|
||||
private boolean isNewTask = true;
|
||||
private boolean isSupportBreakpoint = true;
|
||||
private int mCompleteThreadNum = 0;
|
||||
private int mCancelNum = 0;
|
||||
private long mCurrentLocation = 0;
|
||||
private int mStopNum = 0;
|
||||
private int mFailNum = 0;
|
||||
private Context mContext;
|
||||
private DownloadEntity mDownloadEntity;
|
||||
private ExecutorService mFixedThreadPool;
|
||||
private File mDownloadFile; //下载的文件
|
||||
private File mConfigFile;//下载信息配置文件
|
||||
private SparseArray<Runnable> mTask = new SparseArray<>();
|
||||
|
||||
DownloadUtil(Context context, DownloadEntity entity, IDownloadListener downloadListener) {
|
||||
@ -75,7 +78,26 @@ final class DownloadUtil implements IDownloadUtil {
|
||||
mDownloadEntity = entity;
|
||||
mListener = downloadListener;
|
||||
THREAD_NUM = threadNum;
|
||||
mFixedThreadPool = Executors.newFixedThreadPool(THREAD_NUM);
|
||||
mFixedThreadPool = Executors.newFixedThreadPool(Integer.MAX_VALUE);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
mDownloadFile = new File(mDownloadEntity.getDownloadPath());
|
||||
//读取已完成的线程数
|
||||
mConfigFile = new File(
|
||||
mContext.getFilesDir().getPath() + "/temp/" + mDownloadFile.getName() + ".properties");
|
||||
try {
|
||||
if (!mConfigFile.exists()) { //记录文件被删除,则重新下载
|
||||
isNewTask = true;
|
||||
CommonUtil.createFile(mConfigFile.getPath());
|
||||
} else {
|
||||
isNewTask = !mDownloadFile.exists();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
failDownload("下载失败,记录文件被删除");
|
||||
}
|
||||
}
|
||||
|
||||
public IDownloadListener getListener() {
|
||||
@ -115,7 +137,7 @@ final class DownloadUtil implements IDownloadUtil {
|
||||
isDownloading = false;
|
||||
mFixedThreadPool.shutdown();
|
||||
for (int i = 0; i < THREAD_NUM; i++) {
|
||||
DownLoadTask task = (DownLoadTask) mTask.get(i);
|
||||
SingleThreadTask task = (SingleThreadTask) mTask.get(i);
|
||||
if (task != null) {
|
||||
task.cancel();
|
||||
}
|
||||
@ -130,7 +152,7 @@ final class DownloadUtil implements IDownloadUtil {
|
||||
isDownloading = false;
|
||||
mFixedThreadPool.shutdown();
|
||||
for (int i = 0; i < THREAD_NUM; i++) {
|
||||
DownLoadTask task = (DownLoadTask) mTask.get(i);
|
||||
SingleThreadTask task = (SingleThreadTask) mTask.get(i);
|
||||
if (task != null) {
|
||||
task.stop();
|
||||
}
|
||||
@ -173,142 +195,9 @@ final class DownloadUtil implements IDownloadUtil {
|
||||
isCancel = false;
|
||||
mCancelNum = 0;
|
||||
mStopNum = 0;
|
||||
final String filePath = mDownloadEntity.getDownloadPath();
|
||||
final String downloadUrl = mDownloadEntity.getDownloadUrl();
|
||||
final File dFile = new File(filePath);
|
||||
//读取已完成的线程数
|
||||
final File configFile =
|
||||
new File(mContext.getFilesDir().getPath() + "/temp/" + dFile.getName() + ".properties");
|
||||
try {
|
||||
if (!configFile.exists()) { //记录文件被删除,则重新下载
|
||||
isNewTask = true;
|
||||
CommonUtil.createFile(configFile.getPath());
|
||||
} else {
|
||||
isNewTask = !dFile.exists();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
failDownload("下载失败,记录文件被删除");
|
||||
return;
|
||||
}
|
||||
mFailNum = 0;
|
||||
mListener.onPre();
|
||||
new Thread(new Runnable() {
|
||||
@Override public void run() {
|
||||
try {
|
||||
URL url = new URL(downloadUrl);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
setConnectParam(conn);
|
||||
conn.setConnectTimeout(mConnectTimeOut * 4);
|
||||
conn.connect();
|
||||
int len = conn.getContentLength();
|
||||
if (len < 0) { //网络被劫持时会出现这个问题
|
||||
failDownload("下载失败,网络被劫持");
|
||||
return;
|
||||
}
|
||||
int code = conn.getResponseCode();
|
||||
if (code == 200) {
|
||||
int fileLength = conn.getContentLength();
|
||||
//必须建一个文件
|
||||
CommonUtil.createFile(filePath);
|
||||
RandomAccessFile file = new RandomAccessFile(filePath, "rwd");
|
||||
//设置文件长度
|
||||
file.setLength(fileLength);
|
||||
mListener.onPostPre(fileLength);
|
||||
//分配每条线程的下载区间
|
||||
Properties pro = null;
|
||||
pro = CommonUtil.loadConfig(configFile);
|
||||
if (pro.isEmpty()) {
|
||||
isNewTask = true;
|
||||
} else {
|
||||
for (int i = 0; i < THREAD_NUM; i++) {
|
||||
if (pro.getProperty(dFile.getName() + "_record_" + i) == null) {
|
||||
Object state = pro.getProperty(dFile.getName() + "_state_" + i);
|
||||
if (state != null && Integer.parseInt(state + "") == 1) {
|
||||
continue;
|
||||
}
|
||||
isNewTask = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
int blockSize = fileLength / THREAD_NUM;
|
||||
int[] recordL = new int[THREAD_NUM];
|
||||
int rl = 0;
|
||||
for (int i = 0; i < THREAD_NUM; i++) {
|
||||
recordL[i] = -1;
|
||||
}
|
||||
for (int i = 0; i < THREAD_NUM; i++) {
|
||||
long startL = i * blockSize, endL = (i + 1) * blockSize;
|
||||
Object state = pro.getProperty(dFile.getName() + "_state_" + i);
|
||||
if (state != null && Integer.parseInt(state + "") == 1) { //该线程已经完成
|
||||
mCurrentLocation += endL - startL;
|
||||
Log.d(TAG, "++++++++++ 线程_" + i + "_已经下载完成 ++++++++++");
|
||||
mCompleteThreadNum++;
|
||||
mStopNum++;
|
||||
mCancelNum++;
|
||||
if (mCompleteThreadNum == THREAD_NUM) {
|
||||
if (configFile.exists()) {
|
||||
configFile.delete();
|
||||
}
|
||||
mListener.onComplete();
|
||||
isDownloading = false;
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//分配下载位置
|
||||
Object record = pro.getProperty(dFile.getName() + "_record_" + i);
|
||||
if (!isNewTask
|
||||
&& record != null
|
||||
&& Long.parseLong(record + "") > 0) { //如果有记录,则恢复下载
|
||||
Long r = Long.parseLong(record + "");
|
||||
mCurrentLocation += r - startL;
|
||||
Log.d(TAG, "++++++++++ 线程_" + i + "_恢复下载 ++++++++++");
|
||||
mListener.onChildResume(r);
|
||||
startL = r;
|
||||
recordL[rl] = i;
|
||||
rl++;
|
||||
} else {
|
||||
isNewTask = true;
|
||||
}
|
||||
if (isNewTask) {
|
||||
recordL[rl] = i;
|
||||
rl++;
|
||||
}
|
||||
if (i == (THREAD_NUM - 1)) {
|
||||
//如果整个文件的大小不为线程个数的整数倍,则最后一个线程的结束位置即为文件的总长度
|
||||
endL = fileLength;
|
||||
}
|
||||
ConfigEntity entity =
|
||||
new ConfigEntity(mContext, fileLength, downloadUrl, dFile, i, startL, endL);
|
||||
DownLoadTask task = new DownLoadTask(entity);
|
||||
mTask.put(i, task);
|
||||
}
|
||||
if (mCurrentLocation > 0) {
|
||||
mListener.onResume(mCurrentLocation);
|
||||
} else {
|
||||
mListener.onStart(mCurrentLocation);
|
||||
}
|
||||
for (int l : recordL) {
|
||||
if (l == -1) continue;
|
||||
Runnable task = mTask.get(l);
|
||||
if (task != null) {
|
||||
mFixedThreadPool.execute(task);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
failDownload("下载失败,返回码:" + code);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
failDownload("下载失败【downloadUrl:"
|
||||
+ downloadUrl
|
||||
+ "】\n【filePath:"
|
||||
+ filePath
|
||||
+ "】"
|
||||
+ CommonUtil.getPrintException(e));
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
new Thread(this).start();
|
||||
}
|
||||
|
||||
@Override public void resumeDownload() {
|
||||
@ -331,6 +220,158 @@ final class DownloadUtil implements IDownloadUtil {
|
||||
"image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
|
||||
}
|
||||
|
||||
@Override public void run() {
|
||||
try {
|
||||
URL url = new URL(mDownloadEntity.getDownloadUrl());
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
setConnectParam(conn);
|
||||
conn.setRequestProperty("Range", "bytes=" + 0 + "-");
|
||||
conn.setConnectTimeout(mConnectTimeOut * 4);
|
||||
conn.connect();
|
||||
int len = conn.getContentLength();
|
||||
//if (len < 0) { //网络被劫持时会出现这个问题
|
||||
// failDownload("下载失败,网络被劫持");
|
||||
// return;
|
||||
//}
|
||||
int code = conn.getResponseCode();
|
||||
//https://zh.wikipedia.org/wiki/HTTP%E7%8A%B6%E6%80%81%E7%A0%81
|
||||
//206支持断点
|
||||
if (code == HttpURLConnection.HTTP_PARTIAL) {
|
||||
isSupportBreakpoint = true;
|
||||
mListener.supportBreakpoint(true);
|
||||
handleBreakpoint(conn);
|
||||
} else if (code == HttpURLConnection.HTTP_OK || len < 0) {
|
||||
//在conn.setRequestProperty("Range", "bytes=" + 0 + "-");下,200为不支持断点状态
|
||||
isSupportBreakpoint = false;
|
||||
mListener.supportBreakpoint(false);
|
||||
Log.w(TAG, "该下载链接不支持断点下载");
|
||||
handleBreakpoint(conn);
|
||||
} else {
|
||||
failDownload("下载失败,返回码:" + code);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
failDownload("下载失败【downloadUrl:"
|
||||
+ mDownloadEntity.getDownloadUrl()
|
||||
+ "】\n【filePath:"
|
||||
+ mDownloadFile.getPath()
|
||||
+ "】"
|
||||
+ CommonUtil.getPrintException(e));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理断点
|
||||
*/
|
||||
private void handleBreakpoint(HttpURLConnection conn) throws IOException {
|
||||
//不支持断点只能单线程下载
|
||||
if (!isSupportBreakpoint) {
|
||||
ConfigEntity entity = new ConfigEntity();
|
||||
entity.fileSize = conn.getContentLength();
|
||||
entity.downloadUrl = mDownloadEntity.getDownloadUrl();
|
||||
entity.tempFile = mDownloadFile;
|
||||
entity.threadId = 0;
|
||||
entity.startLocation = 0;
|
||||
entity.endLocation = entity.fileSize;
|
||||
SingleThreadTask task = new SingleThreadTask(entity);
|
||||
mFixedThreadPool.execute(task);
|
||||
mListener.onStart(0);
|
||||
return;
|
||||
}
|
||||
int fileLength = conn.getContentLength();
|
||||
//必须建一个文件
|
||||
CommonUtil.createFile(mDownloadFile.getPath());
|
||||
RandomAccessFile file = new RandomAccessFile(mDownloadFile.getPath(), "rwd");
|
||||
//设置文件长度
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
int blockSize = fileLength / THREAD_NUM;
|
||||
int[] recordL = new int[THREAD_NUM];
|
||||
int rl = 0;
|
||||
for (int i = 0; i < THREAD_NUM; i++) {
|
||||
recordL[i] = -1;
|
||||
}
|
||||
for (int i = 0; i < THREAD_NUM; i++) {
|
||||
long startL = i * blockSize, endL = (i + 1) * blockSize;
|
||||
Object state = pro.getProperty(mDownloadFile.getName() + "_state_" + i);
|
||||
if (state != null && Integer.parseInt(state + "") == 1) { //该线程已经完成
|
||||
mCurrentLocation += endL - startL;
|
||||
Log.d(TAG, "++++++++++ 线程_" + i + "_已经下载完成 ++++++++++");
|
||||
mCompleteThreadNum++;
|
||||
mStopNum++;
|
||||
mCancelNum++;
|
||||
if (mCompleteThreadNum == THREAD_NUM) {
|
||||
if (mConfigFile.exists()) {
|
||||
mConfigFile.delete();
|
||||
}
|
||||
mListener.onComplete();
|
||||
isDownloading = false;
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//分配下载位置
|
||||
Object record = pro.getProperty(mDownloadFile.getName() + "_record_" + i);
|
||||
//如果有记录,则恢复下载
|
||||
if (!isNewTask && record != null && Long.parseLong(record + "") > 0) {
|
||||
Long r = Long.parseLong(record + "");
|
||||
mCurrentLocation += r - startL;
|
||||
Log.d(TAG, "++++++++++ 线程_" + i + "_恢复下载 ++++++++++");
|
||||
mListener.onChildResume(r);
|
||||
startL = r;
|
||||
recordL[rl] = i;
|
||||
rl++;
|
||||
} else {
|
||||
isNewTask = true;
|
||||
}
|
||||
if (isNewTask) {
|
||||
recordL[rl] = i;
|
||||
rl++;
|
||||
}
|
||||
if (i == (THREAD_NUM - 1)) {
|
||||
//如果整个文件的大小不为线程个数的整数倍,则最后一个线程的结束位置即为文件的总长度
|
||||
endL = fileLength;
|
||||
}
|
||||
ConfigEntity entity = new ConfigEntity();
|
||||
entity.fileSize = fileLength;
|
||||
entity.downloadUrl = mDownloadEntity.getDownloadUrl();
|
||||
entity.tempFile = mDownloadFile;
|
||||
entity.threadId = i;
|
||||
entity.startLocation = startL;
|
||||
entity.endLocation = endL;
|
||||
SingleThreadTask task = new SingleThreadTask(entity);
|
||||
mTask.put(i, task);
|
||||
}
|
||||
if (mCurrentLocation > 0) {
|
||||
mListener.onResume(mCurrentLocation);
|
||||
} else {
|
||||
mListener.onStart(mCurrentLocation);
|
||||
}
|
||||
for (int l : recordL) {
|
||||
if (l == -1) continue;
|
||||
Runnable task = mTask.get(l);
|
||||
if (task != null && !mFixedThreadPool.isShutdown()) {
|
||||
mFixedThreadPool.execute(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 子线程下载信息类
|
||||
*/
|
||||
@ -342,68 +383,62 @@ final class DownloadUtil implements IDownloadUtil {
|
||||
long startLocation;
|
||||
long endLocation;
|
||||
File tempFile;
|
||||
Context context;
|
||||
|
||||
private ConfigEntity(Context context, long fileSize, String downloadUrl, File file,
|
||||
int threadId, long startLocation, long endLocation) {
|
||||
this.fileSize = fileSize;
|
||||
this.downloadUrl = downloadUrl;
|
||||
this.tempFile = file;
|
||||
this.threadId = threadId;
|
||||
this.startLocation = startLocation;
|
||||
this.endLocation = endLocation;
|
||||
this.context = context;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 单个线程的下载任务
|
||||
*/
|
||||
private class DownLoadTask implements Runnable {
|
||||
private static final String TAG = "DownLoadTask";
|
||||
private ConfigEntity dEntity;
|
||||
private class SingleThreadTask implements Runnable {
|
||||
private static final String TAG = "SingleThreadTask";
|
||||
private ConfigEntity configEntity;
|
||||
private String configFPath;
|
||||
private long currentLocation = 0;
|
||||
|
||||
private DownLoadTask(ConfigEntity downloadInfo) {
|
||||
this.dEntity = downloadInfo;
|
||||
configFPath = dEntity.context.getFilesDir().getPath()
|
||||
+ "/temp/"
|
||||
+ dEntity.tempFile.getName()
|
||||
+ ".properties";
|
||||
private SingleThreadTask(ConfigEntity downloadInfo) {
|
||||
this.configEntity = downloadInfo;
|
||||
if (isSupportBreakpoint) {
|
||||
configFPath = mContext.getFilesDir().getPath()
|
||||
+ "/temp/"
|
||||
+ configEntity.tempFile.getName()
|
||||
+ ".properties";
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void run() {
|
||||
HttpURLConnection conn = null;
|
||||
InputStream is = null;
|
||||
try {
|
||||
Log.d(TAG, "线程_"
|
||||
+ dEntity.threadId
|
||||
+ "_正在下载【开始位置 : "
|
||||
+ dEntity.startLocation
|
||||
+ ",结束位置:"
|
||||
+ dEntity.endLocation
|
||||
+ "】");
|
||||
URL url = new URL(dEntity.downloadUrl);
|
||||
URL url = new URL(configEntity.downloadUrl);
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
//在头里面请求下载开始位置和结束位置
|
||||
conn.setRequestProperty("Range",
|
||||
"bytes=" + dEntity.startLocation + "-" + dEntity.endLocation);
|
||||
if (isSupportBreakpoint) {
|
||||
Log.d(TAG, "线程_"
|
||||
+ configEntity.threadId
|
||||
+ "_正在下载【开始位置 : "
|
||||
+ configEntity.startLocation
|
||||
+ ",结束位置:"
|
||||
+ configEntity.endLocation
|
||||
+ "】");
|
||||
//在头里面请求下载开始位置和结束位置
|
||||
conn.setRequestProperty("Range",
|
||||
"bytes=" + configEntity.startLocation + "-" + configEntity.endLocation);
|
||||
} else {
|
||||
Log.w(TAG, "该下载不支持断点,即将重新下载");
|
||||
}
|
||||
setConnectParam(conn);
|
||||
conn.setConnectTimeout(mConnectTimeOut);
|
||||
conn.setReadTimeout(mReadTimeOut); //设置读取流的等待时间,必须设置该参数
|
||||
is = conn.getInputStream();
|
||||
//创建可设置位置的文件
|
||||
RandomAccessFile file = new RandomAccessFile(dEntity.tempFile, "rwd");
|
||||
RandomAccessFile file = new RandomAccessFile(configEntity.tempFile, "rwd");
|
||||
//设置每条线程写入文件的位置
|
||||
file.seek(dEntity.startLocation);
|
||||
file.seek(configEntity.startLocation);
|
||||
byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
//当前子线程的下载位置
|
||||
currentLocation = dEntity.startLocation;
|
||||
currentLocation = configEntity.startLocation;
|
||||
while ((len = is.read(buffer)) != -1) {
|
||||
if (isCancel) {
|
||||
Log.d(TAG, "++++++++++ thread_" + dEntity.threadId + "_cancel ++++++++++");
|
||||
Log.d(TAG, "++++++++++ thread_" + configEntity.threadId + "_cancel ++++++++++");
|
||||
break;
|
||||
}
|
||||
if (isStop) {
|
||||
@ -412,7 +447,6 @@ final class DownloadUtil implements IDownloadUtil {
|
||||
//把下载数据数据写入文件
|
||||
file.write(buffer, 0, len);
|
||||
progress(len);
|
||||
currentLocation += len;
|
||||
}
|
||||
file.close();
|
||||
//close 为阻塞的,需要使用线程池来处理
|
||||
@ -420,32 +454,40 @@ final class DownloadUtil implements IDownloadUtil {
|
||||
conn.disconnect();
|
||||
|
||||
if (isCancel) {
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
//停止状态不需要删除记录文件
|
||||
if (isStop) {
|
||||
//stop();
|
||||
return;
|
||||
}
|
||||
Log.i(TAG, "线程【" + dEntity.threadId + "】下载完毕");
|
||||
writeConfig(dEntity.tempFile.getName() + "_state_" + dEntity.threadId, 1 + "");
|
||||
mListener.onChildComplete(dEntity.endLocation);
|
||||
mCompleteThreadNum++;
|
||||
if (mCompleteThreadNum == THREAD_NUM) {
|
||||
File configFile = new File(configFPath);
|
||||
if (configFile.exists()) {
|
||||
configFile.delete();
|
||||
//支持断点的处理
|
||||
if (isSupportBreakpoint) {
|
||||
Log.i(TAG, "线程【" + configEntity.threadId + "】下载完毕");
|
||||
writeConfig(configEntity.tempFile.getName() + "_state_" + configEntity.threadId, 1 + "");
|
||||
mListener.onChildComplete(configEntity.endLocation);
|
||||
mCompleteThreadNum++;
|
||||
if (mCompleteThreadNum == THREAD_NUM) {
|
||||
File configFile = new File(configFPath);
|
||||
if (configFile.exists()) {
|
||||
configFile.delete();
|
||||
}
|
||||
isDownloading = false;
|
||||
mListener.onComplete();
|
||||
}
|
||||
} else {
|
||||
Log.i(TAG, "下载任务完成");
|
||||
isDownloading = false;
|
||||
mListener.onComplete();
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
failDownload(dEntity, currentLocation, "下载链接异常", e);
|
||||
mFailNum++;
|
||||
failDownload(configEntity, currentLocation, "下载链接异常", e);
|
||||
} catch (IOException e) {
|
||||
failDownload(dEntity, currentLocation, "下载失败【" + dEntity.downloadUrl + "】", e);
|
||||
mFailNum++;
|
||||
failDownload(configEntity, currentLocation, "下载失败【" + configEntity.downloadUrl + "】", e);
|
||||
} catch (Exception e) {
|
||||
failDownload(dEntity, currentLocation, "获取流失败", e);
|
||||
mFailNum++;
|
||||
failDownload(configEntity, currentLocation, "获取流失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -455,11 +497,19 @@ final class DownloadUtil implements IDownloadUtil {
|
||||
protected void stop() {
|
||||
synchronized (LOCK) {
|
||||
try {
|
||||
mStopNum++;
|
||||
String location = String.valueOf(currentLocation);
|
||||
Log.i(TAG, "thread_" + dEntity.threadId + "_stop, stop location ==> " + currentLocation);
|
||||
writeConfig(dEntity.tempFile.getName() + "_record_" + dEntity.threadId, location);
|
||||
if (mStopNum == THREAD_NUM) {
|
||||
if (isSupportBreakpoint) {
|
||||
mStopNum++;
|
||||
String location = String.valueOf(currentLocation);
|
||||
Log.i(TAG,
|
||||
"thread_" + configEntity.threadId + "_stop, stop location ==> " + currentLocation);
|
||||
writeConfig(configEntity.tempFile.getName() + "_record_" + configEntity.threadId,
|
||||
location);
|
||||
if (mStopNum == THREAD_NUM) {
|
||||
Log.d(TAG, "++++++++++++++++ onStop +++++++++++++++++");
|
||||
isDownloading = false;
|
||||
mListener.onStop(mCurrentLocation);
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "++++++++++++++++ onStop +++++++++++++++++");
|
||||
isDownloading = false;
|
||||
mListener.onStop(mCurrentLocation);
|
||||
@ -470,20 +520,37 @@ final class DownloadUtil implements IDownloadUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载中
|
||||
*/
|
||||
private void progress(long len) {
|
||||
synchronized (LOCK) {
|
||||
currentLocation += len;
|
||||
mCurrentLocation += len;
|
||||
mListener.onProgress(mCurrentLocation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消下载
|
||||
*/
|
||||
private void cancel() {
|
||||
synchronized (LOCK) {
|
||||
mCancelNum++;
|
||||
if (mCancelNum == THREAD_NUM) {
|
||||
File configFile = new File(configFPath);
|
||||
if (configFile.exists()) {
|
||||
configFile.delete();
|
||||
}
|
||||
if (dEntity.tempFile.exists()) {
|
||||
dEntity.tempFile.delete();
|
||||
if (isSupportBreakpoint) {
|
||||
mCancelNum++;
|
||||
if (mCancelNum == THREAD_NUM) {
|
||||
File configFile = new File(configFPath);
|
||||
if (configFile.exists()) {
|
||||
configFile.delete();
|
||||
}
|
||||
if (configEntity.tempFile.exists()) {
|
||||
configEntity.tempFile.delete();
|
||||
}
|
||||
Log.d(TAG, "++++++++++++++++ onCancel +++++++++++++++++");
|
||||
isDownloading = false;
|
||||
mListener.onCancel();
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "++++++++++++++++ onCancel +++++++++++++++++");
|
||||
isDownloading = false;
|
||||
mListener.onCancel();
|
||||
@ -491,10 +558,34 @@ final class DownloadUtil implements IDownloadUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private void progress(long len) {
|
||||
/**
|
||||
* 下载失败
|
||||
*/
|
||||
private void failDownload(ConfigEntity dEntity, long currentLocation, String msg,
|
||||
Exception ex) {
|
||||
synchronized (LOCK) {
|
||||
mCurrentLocation += len;
|
||||
mListener.onProgress(mCurrentLocation);
|
||||
try {
|
||||
isDownloading = false;
|
||||
isStop = true;
|
||||
if (ex != null) {
|
||||
Log.e(TAG, CommonUtil.getPrintException(ex));
|
||||
}
|
||||
if (isSupportBreakpoint) {
|
||||
if (currentLocation != -1) {
|
||||
String location = String.valueOf(currentLocation);
|
||||
writeConfig(dEntity.tempFile.getName() + "_record_" + dEntity.threadId, location);
|
||||
}
|
||||
if (mFailNum == THREAD_NUM) {
|
||||
Log.d(TAG, "++++++++++++++++ onFail +++++++++++++++++");
|
||||
mListener.onFail();
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "++++++++++++++++ onFail +++++++++++++++++");
|
||||
mListener.onFail();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -507,29 +598,5 @@ final class DownloadUtil implements IDownloadUtil {
|
||||
pro.setProperty(key, record);
|
||||
CommonUtil.saveConfig(configFile, pro);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载失败
|
||||
*/
|
||||
private void failDownload(ConfigEntity dEntity, long currentLocation, String msg,
|
||||
Exception ex) {
|
||||
synchronized (LOCK) {
|
||||
try {
|
||||
isDownloading = false;
|
||||
isStop = true;
|
||||
Log.e(TAG, msg);
|
||||
if (ex != null) {
|
||||
Log.e(TAG, CommonUtil.getPrintException(ex));
|
||||
}
|
||||
if (currentLocation != -1) {
|
||||
String location = String.valueOf(currentLocation);
|
||||
writeConfig(dEntity.tempFile.getName() + "_record_" + dEntity.threadId, location);
|
||||
}
|
||||
mListener.onFail();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -14,13 +14,20 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package com.arialyy.aria.core.task;
|
||||
|
||||
/**
|
||||
* 下载监听
|
||||
*/
|
||||
public interface IDownloadListener {
|
||||
|
||||
/**
|
||||
* 支持断点回调
|
||||
*
|
||||
* @param support true,支持;false 不支持
|
||||
*/
|
||||
public void supportBreakpoint(boolean support);
|
||||
|
||||
/**
|
||||
* 取消下载
|
||||
*/
|
||||
|
@ -18,14 +18,16 @@ package com.arialyy.aria.core.task;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.Aria;
|
||||
import com.arialyy.aria.core.DownloadManager;
|
||||
import com.arialyy.aria.core.scheduler.DownloadSchedulers;
|
||||
import com.arialyy.aria.core.scheduler.IDownloadSchedulers;
|
||||
import com.arialyy.aria.core.DownloadEntity;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import com.arialyy.aria.util.Configuration;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2016/8/11.
|
||||
@ -43,17 +45,39 @@ public class Task {
|
||||
private Context mContext;
|
||||
private IDownloadUtil mUtil;
|
||||
|
||||
private Task(Context context, DownloadEntity entity) {
|
||||
private Task(Context context, DownloadEntity entity, Handler outHandler) {
|
||||
mContext = context.getApplicationContext();
|
||||
mEntity = entity;
|
||||
mOutHandler = outHandler;
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
mListener = new DListener(mContext, mEntity, mOutHandler);
|
||||
mListener = new DListener(mContext, this, mOutHandler);
|
||||
mUtil = new DownloadUtil(mContext, mEntity, mListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下载速度
|
||||
*/
|
||||
public long getSpeed() {
|
||||
return mEntity.getSpeed();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件大小
|
||||
*/
|
||||
public long getFileSize(){
|
||||
return mEntity.getFileSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前下载进度
|
||||
*/
|
||||
public long getCurrentProgress(){
|
||||
return mEntity.getCurrentProgress();
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始下载
|
||||
*/
|
||||
@ -62,7 +86,7 @@ public class Task {
|
||||
Log.d(TAG, "任务正在下载");
|
||||
} else {
|
||||
if (mListener == null) {
|
||||
mListener = new DListener(mContext, mEntity, mOutHandler);
|
||||
mListener = new DListener(mContext, this, mOutHandler);
|
||||
}
|
||||
mUtil.startDownload();
|
||||
}
|
||||
@ -89,23 +113,17 @@ public class Task {
|
||||
} else {
|
||||
mEntity.setState(DownloadEntity.STATE_STOP);
|
||||
mEntity.save();
|
||||
sendInState2Target(DownloadSchedulers.STOP);
|
||||
|
||||
if (mOutHandler != null) {
|
||||
mOutHandler.obtainMessage(DownloadSchedulers.STOP, this).sendToTarget();
|
||||
}
|
||||
// 发送停止下载的广播
|
||||
Intent intent = createIntent(DownloadManager.ACTION_STOP);
|
||||
intent.putExtra(DownloadManager.CURRENT_LOCATION, mEntity.getCurrentProgress());
|
||||
intent.putExtra(DownloadManager.ENTITY, mEntity);
|
||||
Intent intent = CommonUtil.createIntent(mContext.getPackageName(), Aria.ACTION_STOP);
|
||||
intent.putExtra(Aria.CURRENT_LOCATION, mEntity.getCurrentProgress());
|
||||
intent.putExtra(Aria.ENTITY, mEntity);
|
||||
mContext.sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下载工具
|
||||
*/
|
||||
public IDownloadUtil getDownloadUtil() {
|
||||
return mUtil;
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务下载状态
|
||||
*/
|
||||
@ -125,38 +143,16 @@ public class Task {
|
||||
mUtil.delConfigFile();
|
||||
mUtil.delTempFile();
|
||||
mEntity.deleteData();
|
||||
sendInState2Target(DownloadSchedulers.CANCEL);
|
||||
|
||||
if (mOutHandler != null) {
|
||||
mOutHandler.obtainMessage(DownloadSchedulers.CANCEL, this).sendToTarget();
|
||||
}
|
||||
//发送取消下载的广播
|
||||
Intent intent = createIntent(DownloadManager.ACTION_CANCEL);
|
||||
intent.putExtra(DownloadManager.ENTITY, mEntity);
|
||||
Intent intent = CommonUtil.createIntent(mContext.getPackageName(), Aria.ACTION_CANCEL);
|
||||
intent.putExtra(Aria.ENTITY, mEntity);
|
||||
mContext.sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建特定的Intent
|
||||
*/
|
||||
private Intent createIntent(String action) {
|
||||
Uri.Builder builder = new Uri.Builder();
|
||||
builder.scheme(mContext.getPackageName());
|
||||
Uri uri = builder.build();
|
||||
Intent intent = new Intent(action);
|
||||
intent.setData(uri);
|
||||
return intent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将任务状态发送给下载器
|
||||
*
|
||||
* @param state {@link DownloadSchedulers#START}
|
||||
*/
|
||||
private void sendInState2Target(int state) {
|
||||
if (mOutHandler != null) {
|
||||
mOutHandler.obtainMessage(state, this).sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
static class Builder {
|
||||
DownloadEntity downloadEntity;
|
||||
Handler outHandler;
|
||||
@ -169,7 +165,7 @@ public class Task {
|
||||
this("", context, downloadEntity);
|
||||
}
|
||||
|
||||
public Builder(String targetName, Context context, DownloadEntity downloadEntity) {
|
||||
Builder(String targetName, Context context, DownloadEntity downloadEntity) {
|
||||
this.targetName = targetName;
|
||||
this.context = context;
|
||||
this.downloadEntity = downloadEntity;
|
||||
@ -180,7 +176,7 @@ public class Task {
|
||||
*
|
||||
* @param schedulers {@link IDownloadSchedulers}
|
||||
*/
|
||||
public Builder setOutHandler(IDownloadSchedulers schedulers) {
|
||||
Builder setOutHandler(IDownloadSchedulers schedulers) {
|
||||
this.outHandler = new Handler(schedulers);
|
||||
return this;
|
||||
}
|
||||
@ -204,8 +200,7 @@ public class Task {
|
||||
//}
|
||||
|
||||
public Task build() {
|
||||
Task task = new Task(context, downloadEntity);
|
||||
task.mOutHandler = outHandler;
|
||||
Task task = new Task(context, downloadEntity, outHandler);
|
||||
task.setTargetName(targetName);
|
||||
downloadEntity.save();
|
||||
return task;
|
||||
@ -215,29 +210,33 @@ public class Task {
|
||||
/**
|
||||
* 下载监听类
|
||||
*/
|
||||
private class DListener extends DownloadListener {
|
||||
Handler outHandler;
|
||||
Context context;
|
||||
Intent sendIntent;
|
||||
private static class DListener extends DownloadListener {
|
||||
WeakReference<Handler> outHandler;
|
||||
WeakReference<Task> wTask;
|
||||
Context context;
|
||||
Intent sendIntent;
|
||||
long INTERVAL = 1024 * 10; //10k大小的间隔
|
||||
long lastLen = 0; //上一次发送长度
|
||||
long lastTime = 0;
|
||||
long INTERVAL_TIME = 1000; //1m更新周期
|
||||
boolean isFirst = true;
|
||||
DownloadEntity downloadEntity;
|
||||
Task task;
|
||||
|
||||
DListener(Context context, DownloadEntity downloadEntity, Handler outHandler) {
|
||||
DListener(Context context, Task task, Handler outHandler) {
|
||||
this.context = context;
|
||||
this.outHandler = outHandler;
|
||||
this.downloadEntity = downloadEntity;
|
||||
sendIntent = createIntent(DownloadManager.ACTION_RUNNING);
|
||||
sendIntent.putExtra(DownloadManager.ENTITY, downloadEntity);
|
||||
this.outHandler = new WeakReference<>(outHandler);
|
||||
this.wTask = new WeakReference<>(task);
|
||||
this.task = wTask.get();
|
||||
this.downloadEntity = this.task.getDownloadEntity();
|
||||
sendIntent = CommonUtil.createIntent(context.getPackageName(), Aria.ACTION_RUNNING);
|
||||
sendIntent.putExtra(Aria.ENTITY, downloadEntity);
|
||||
}
|
||||
|
||||
@Override public void onPre() {
|
||||
super.onPre();
|
||||
downloadEntity.setState(DownloadEntity.STATE_PRE);
|
||||
sendIntent(DownloadManager.ACTION_PRE, -1);
|
||||
sendIntent(Aria.ACTION_PRE, -1);
|
||||
}
|
||||
|
||||
@Override public void onPostPre(long fileSize) {
|
||||
@ -245,30 +244,29 @@ public class Task {
|
||||
downloadEntity.setFileSize(fileSize);
|
||||
downloadEntity.setState(DownloadEntity.STATE_POST_PRE);
|
||||
sendInState2Target(DownloadSchedulers.PRE);
|
||||
sendIntent(DownloadManager.ACTION_POST_PRE, -1);
|
||||
sendIntent(Aria.ACTION_POST_PRE, -1);
|
||||
}
|
||||
|
||||
@Override public void onResume(long resumeLocation) {
|
||||
super.onResume(resumeLocation);
|
||||
downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING);
|
||||
sendInState2Target(DownloadSchedulers.RESUME);
|
||||
sendIntent(DownloadManager.ACTION_RESUME, resumeLocation);
|
||||
sendIntent(Aria.ACTION_RESUME, resumeLocation);
|
||||
}
|
||||
|
||||
@Override public void onStart(long startLocation) {
|
||||
super.onStart(startLocation);
|
||||
downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING);
|
||||
downloadEntity.setFailNum(0);
|
||||
sendInState2Target(DownloadSchedulers.START);
|
||||
sendIntent(DownloadManager.ACTION_START, startLocation);
|
||||
sendIntent(Aria.ACTION_START, startLocation);
|
||||
}
|
||||
|
||||
@Override public void onProgress(long currentLocation) {
|
||||
super.onProgress(currentLocation);
|
||||
if (System.currentTimeMillis() - lastTime > INTERVAL_TIME) {
|
||||
long speed = currentLocation - lastLen;
|
||||
sendIntent.putExtra(DownloadManager.CURRENT_LOCATION, currentLocation);
|
||||
sendIntent.putExtra(DownloadManager.CURRENT_SPEED, speed);
|
||||
sendIntent.putExtra(Aria.CURRENT_LOCATION, currentLocation);
|
||||
sendIntent.putExtra(Aria.CURRENT_SPEED, speed);
|
||||
lastTime = System.currentTimeMillis();
|
||||
if (isFirst) {
|
||||
downloadEntity.setSpeed(0);
|
||||
@ -288,14 +286,14 @@ public class Task {
|
||||
downloadEntity.setState(DownloadEntity.STATE_STOP);
|
||||
downloadEntity.setSpeed(0);
|
||||
sendInState2Target(DownloadSchedulers.STOP);
|
||||
sendIntent(DownloadManager.ACTION_STOP, stopLocation);
|
||||
sendIntent(Aria.ACTION_STOP, stopLocation);
|
||||
}
|
||||
|
||||
@Override public void onCancel() {
|
||||
super.onCancel();
|
||||
downloadEntity.setState(DownloadEntity.STATE_CANCEL);
|
||||
sendInState2Target(DownloadSchedulers.CANCEL);
|
||||
sendIntent(DownloadManager.ACTION_CANCEL, -1);
|
||||
sendIntent(Aria.ACTION_CANCEL, -1);
|
||||
downloadEntity.deleteData();
|
||||
}
|
||||
|
||||
@ -305,7 +303,7 @@ public class Task {
|
||||
downloadEntity.setDownloadComplete(true);
|
||||
downloadEntity.setSpeed(0);
|
||||
sendInState2Target(DownloadSchedulers.COMPLETE);
|
||||
sendIntent(DownloadManager.ACTION_COMPLETE, downloadEntity.getFileSize());
|
||||
sendIntent(Aria.ACTION_COMPLETE, downloadEntity.getFileSize());
|
||||
}
|
||||
|
||||
@Override public void onFail() {
|
||||
@ -314,17 +312,28 @@ public class Task {
|
||||
downloadEntity.setState(DownloadEntity.STATE_FAIL);
|
||||
downloadEntity.setSpeed(0);
|
||||
sendInState2Target(DownloadSchedulers.FAIL);
|
||||
sendIntent(DownloadManager.ACTION_FAIL, -1);
|
||||
sendIntent(Aria.ACTION_FAIL, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将任务状态发送给下载器
|
||||
*
|
||||
* @param state {@link DownloadSchedulers#START}
|
||||
*/
|
||||
private void sendInState2Target(int state) {
|
||||
if (outHandler.get() != null) {
|
||||
outHandler.get().obtainMessage(state, task).sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
private void sendIntent(String action, long location) {
|
||||
downloadEntity.setDownloadComplete(action.equals(DownloadManager.ACTION_COMPLETE));
|
||||
downloadEntity.setDownloadComplete(action.equals(Aria.ACTION_COMPLETE));
|
||||
downloadEntity.setCurrentProgress(location);
|
||||
downloadEntity.update();
|
||||
Intent intent = createIntent(action);
|
||||
intent.putExtra(DownloadManager.ENTITY, downloadEntity);
|
||||
Intent intent = CommonUtil.createIntent(context.getPackageName(), action);
|
||||
intent.putExtra(Aria.ENTITY, downloadEntity);
|
||||
if (location != -1) {
|
||||
intent.putExtra(DownloadManager.CURRENT_LOCATION, location);
|
||||
intent.putExtra(Aria.CURRENT_LOCATION, location);
|
||||
}
|
||||
if (Configuration.isOpenBreadCast) {
|
||||
context.sendBroadcast(intent);
|
||||
|
@ -55,24 +55,28 @@ public class DbEntity {
|
||||
|
||||
/**
|
||||
* 查询一组数据
|
||||
* <code>
|
||||
* DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl);
|
||||
* </code>
|
||||
*
|
||||
* @return 没有数据返回null
|
||||
*/
|
||||
public static <T extends DbEntity> List<T> findDatas(Class<T> clazz, @NonNull String[] wheres,
|
||||
@NonNull String[] values) {
|
||||
public static <T extends DbEntity> List<T> findDatas(Class<T> clazz, String... expression) {
|
||||
DbUtil util = DbUtil.getInstance();
|
||||
return util.findData(clazz, wheres, values);
|
||||
return util.findData(clazz, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询一行数据
|
||||
* <code>
|
||||
* DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl);
|
||||
* </code>
|
||||
*
|
||||
* @return 没有数据返回null
|
||||
*/
|
||||
public static <T extends DbEntity> T findData(Class<T> clazz, @NonNull String[] wheres,
|
||||
@NonNull String[] values) {
|
||||
public static <T extends DbEntity> T findData(Class<T> clazz, String... expression) {
|
||||
DbUtil util = DbUtil.getInstance();
|
||||
List<T> datas = util.findData(clazz, wheres, values);
|
||||
List<T> datas = util.findData(clazz, expression);
|
||||
return datas == null ? null : datas.size() > 0 ? datas.get(0) : null;
|
||||
}
|
||||
|
||||
@ -94,14 +98,19 @@ public class DbEntity {
|
||||
* 删除当前数据
|
||||
*/
|
||||
public void deleteData() {
|
||||
mUtil.delData(getClass(), new Object[] { "rowid" }, new Object[] { rowID });
|
||||
//mUtil.delData(getClass(), new Object[] { "rowid" }, new Object[] { rowID });
|
||||
deleteData(getClass(), "rowid=?", rowID + "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据条件删除数据
|
||||
* <code>
|
||||
* DownloadEntity.deleteData(DownloadEntity.class, "downloadUrl=?", downloadUrl);
|
||||
* </code>
|
||||
*/
|
||||
public void deleteData(@NonNull Object[] wheres, @NonNull Object[] values) {
|
||||
mUtil.delData(getClass(), wheres, values);
|
||||
public static <T extends DbEntity> void deleteData(Class<T> clazz, String... expression) {
|
||||
DbUtil util = DbUtil.getInstance();
|
||||
util.delData(clazz, expression);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -128,7 +137,7 @@ public class DbEntity {
|
||||
* 查找数据在表中是否存在
|
||||
*/
|
||||
private boolean thisIsExist() {
|
||||
return findData(getClass(), new String[] { "rowid" }, new String[] { rowID + "" }) != null;
|
||||
return findData(getClass(), "rowid=?", rowID + "") != null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -139,6 +148,13 @@ public class DbEntity {
|
||||
updateRowID();
|
||||
}
|
||||
|
||||
private <T extends DbEntity> T findData(Class<T> clazz, @NonNull String[] wheres,
|
||||
@NonNull String[] values) {
|
||||
DbUtil util = DbUtil.getInstance();
|
||||
List<T> list = util.findData(clazz, wheres, values);
|
||||
return list == null ? null : list.get(0);
|
||||
}
|
||||
|
||||
private void updateRowID() {
|
||||
try {
|
||||
Field[] fields = CommonUtil.getFields(getClass());
|
||||
|
@ -22,6 +22,7 @@ import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.util.CheckUtil;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
@ -76,8 +77,8 @@ public class DbUtil {
|
||||
/**
|
||||
* 删除某条数据
|
||||
*/
|
||||
synchronized <T extends DbEntity> void delData(Class<T> clazz, @NonNull Object[] wheres,
|
||||
@NonNull Object[] values) {
|
||||
@Deprecated private synchronized <T extends DbEntity> void delData(Class<T> clazz,
|
||||
@NonNull Object[] wheres, @NonNull Object[] values) {
|
||||
mDb = mHelper.getWritableDatabase();
|
||||
if (wheres.length <= 0 || values.length <= 0) {
|
||||
Log.e(TAG, "输入删除条件");
|
||||
@ -99,6 +100,25 @@ public class DbUtil {
|
||||
close();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除某条数据
|
||||
*/
|
||||
synchronized <T extends DbEntity> void delData(Class<T> clazz, String... expression) {
|
||||
CheckUtil.checkSqlExpression(expression);
|
||||
mDb = mHelper.getWritableDatabase();
|
||||
String sql = "DELETE FROM " + CommonUtil.getClassName(clazz) + " WHERE " + expression[0] + " ";
|
||||
sql = sql.replace("?", "%s");
|
||||
Object[] params = new String[expression.length - 1];
|
||||
for (int i = 0, len = params.length; i < len; i++) {
|
||||
params[i] = "'" + expression[i + 1] + "'";
|
||||
}
|
||||
sql = String.format(sql, params);
|
||||
Log.d(TAG, sql);
|
||||
print(DEL_DATA, sql);
|
||||
mDb.execSQL(sql);
|
||||
close();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改某行数据
|
||||
*/
|
||||
@ -151,8 +171,31 @@ public class DbUtil {
|
||||
/**
|
||||
* 条件查寻数据
|
||||
*/
|
||||
synchronized <T extends DbEntity> List<T> findData(Class<T> clazz, @NonNull String[] wheres,
|
||||
@NonNull String[] values) {
|
||||
synchronized <T extends DbEntity> List<T> findData(Class<T> clazz, String... expression) {
|
||||
if (!tableExists(clazz)) {
|
||||
createTable(clazz);
|
||||
}
|
||||
mDb = mHelper.getReadableDatabase();
|
||||
CheckUtil.checkSqlExpression(expression);
|
||||
String sql =
|
||||
"SELECT rowid, * FROM " + CommonUtil.getClassName(clazz) + " WHERE " + expression[0] + " ";
|
||||
sql = sql.replace("?", "%s");
|
||||
Object[] params = new String[expression.length - 1];
|
||||
for (int i = 0, len = params.length; i < len; i++) {
|
||||
params[i] = "'" + expression[i + 1] + "'";
|
||||
}
|
||||
sql = String.format(sql, params);
|
||||
Log.d(TAG, sql);
|
||||
print(FIND_DATA, sql);
|
||||
Cursor cursor = mDb.rawQuery(sql, null);
|
||||
return cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件查寻数据
|
||||
*/
|
||||
@Deprecated synchronized <T extends DbEntity> List<T> findData(Class<T> clazz,
|
||||
@NonNull String[] wheres, @NonNull String[] values) {
|
||||
if (!tableExists(clazz)) {
|
||||
createTable(clazz);
|
||||
}
|
||||
@ -436,7 +479,7 @@ public class DbUtil {
|
||||
}
|
||||
entity.rowID = cursor.getInt(cursor.getColumnIndex("rowid"));
|
||||
entitys.add(entity);
|
||||
Log.d(TAG, "rowid ==> " + entity.rowID);
|
||||
//Log.d(TAG, "rowid ==> " + entity.rowID);
|
||||
}
|
||||
} catch (InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
|
@ -26,7 +26,7 @@ import android.text.TextUtils;
|
||||
* Created by lyy on 2015/11/2.
|
||||
* sql帮助类
|
||||
*/
|
||||
public class SqlHelper extends SQLiteOpenHelper {
|
||||
final class SqlHelper extends SQLiteOpenHelper {
|
||||
protected static String DB_NAME;
|
||||
protected static int VERSION = -1;
|
||||
|
||||
|
@ -14,13 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package com.arialyy.aria.util;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.DownloadEntity;
|
||||
import java.io.File;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Created by Lyy on 2016/9/23.
|
||||
@ -29,6 +30,41 @@ import java.io.File;
|
||||
public class CheckUtil {
|
||||
private static final String TAG = "CheckUtil";
|
||||
|
||||
/**
|
||||
* 检查sql的expression是否合法
|
||||
*/
|
||||
public static void checkSqlExpression(String... expression) {
|
||||
if (expression.length == 0) {
|
||||
throw new IllegalArgumentException("sql语句表达式不能为null");
|
||||
}
|
||||
if (expression.length == 1) {
|
||||
throw new IllegalArgumentException("表达式需要写入参数");
|
||||
}
|
||||
String where = expression[0];
|
||||
if (!where.contains("?")) {
|
||||
throw new IllegalArgumentException("请在where语句的'='后编写?");
|
||||
}
|
||||
Pattern pattern = Pattern.compile("\\?");
|
||||
Matcher matcher = pattern.matcher(where);
|
||||
int count = 0;
|
||||
while (matcher.find()) {
|
||||
count++;
|
||||
}
|
||||
if (count < expression.length - 1){
|
||||
throw new IllegalArgumentException("条件语句的?个数不能小于参数个数");
|
||||
}
|
||||
if (count > expression.length - 1){
|
||||
throw new IllegalArgumentException("条件语句的?个数不能大于参数个数");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测下载链接是否为null
|
||||
*/
|
||||
public static void checkDownloadUrl(String downloadUrl) {
|
||||
if (TextUtils.isEmpty(downloadUrl)) throw new IllegalArgumentException("下载链接不能为null");
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测下载实体是否合法
|
||||
*
|
||||
@ -43,11 +79,10 @@ public class CheckUtil {
|
||||
Log.w(TAG, "下载链接不能为空");
|
||||
return false;
|
||||
} else if (TextUtils.isEmpty(entity.getFileName())) {
|
||||
Log.w(TAG, "文件名不能为空");
|
||||
return false;
|
||||
//Log.w(TAG, "文件名不能为空");
|
||||
throw new IllegalArgumentException("文件名不能为null");
|
||||
} else if (TextUtils.isEmpty(entity.getDownloadPath())) {
|
||||
Log.w(TAG, "存储地址不能为空");
|
||||
return false;
|
||||
throw new IllegalArgumentException("文件保存路径不能为null");
|
||||
}
|
||||
String fileName = entity.getFileName();
|
||||
if (fileName.contains(" ")) {
|
||||
|
@ -17,7 +17,9 @@
|
||||
package com.arialyy.aria.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.command.CmdFactory;
|
||||
import com.arialyy.aria.core.DownloadEntity;
|
||||
@ -46,6 +48,18 @@ public class CommonUtil {
|
||||
return CmdFactory.getInstance().createCmd(entity, cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建隐性的Intent
|
||||
*/
|
||||
public static Intent createIntent(String packageName, String action) {
|
||||
Uri.Builder builder = new Uri.Builder();
|
||||
builder.scheme(packageName);
|
||||
Uri uri = builder.build();
|
||||
Intent intent = new Intent(action);
|
||||
intent.setData(uri);
|
||||
return intent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 存储字符串到配置文件
|
||||
*
|
||||
|
513
Aria/src/main/java/com/arialyy/aria/util/WeakHandler.java
Normal file
513
Aria/src/main/java/com/arialyy/aria/util/WeakHandler.java
Normal file
@ -0,0 +1,513 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Badoo Trading Limited
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* Portions of documentation in this code are modifications based on work created and
|
||||
* shared by Android Open Source Project and used according to terms described in the
|
||||
* Apache License, Version 2.0
|
||||
*/
|
||||
package com.arialyy.aria.util;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Memory safer implementation of android.os.Handler
|
||||
* Original implementation of Handlers always keeps hard reference to handler in queue of execution.
|
||||
* If you create anonymous handler and post delayed message into it, it will keep all parent class
|
||||
* for that time in memory even if it could be cleaned.
|
||||
* This implementation is trickier, it will keep WeakReferences to runnables and messages,
|
||||
* and GC could collect them once WeakHandler instance is not referenced any more
|
||||
*
|
||||
* @see android.os.Handler
|
||||
*
|
||||
* Created by Dmytro Voronkevych on 17/06/2014.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class WeakHandler {
|
||||
private final Handler.Callback mCallback; // hard reference to Callback. We need to keep callback in memory
|
||||
private final ExecHandler mExec;
|
||||
private Lock mLock = new ReentrantLock();
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@VisibleForTesting
|
||||
final ChainedRef mRunnables = new ChainedRef(mLock, null);
|
||||
|
||||
/**
|
||||
* Default constructor associates this handler with the {@link Looper} for the
|
||||
* current thread.
|
||||
*
|
||||
* If this thread does not have a looper, this handler won't be able to receive messages
|
||||
* so an exception is thrown.
|
||||
*/
|
||||
public WeakHandler() {
|
||||
mCallback = null;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any pending posts of Runnable <var>r</var> with Object
|
||||
* <var>token</var> that are in the message queue. If <var>token</var> is null,
|
||||
* all callbacks will be removed.
|
||||
*/
|
||||
public final void removeCallbacks(Runnable r, Object token) {
|
||||
final WeakRunnable runnable = mRunnables.remove(r);
|
||||
if (runnable != null) {
|
||||
mExec.removeCallbacks(runnable, token);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes a message onto the end of the message queue after all pending messages
|
||||
* before the current time. It will be received 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.
|
||||
*/
|
||||
public final boolean sendMessage(Message msg) {
|
||||
return mExec.sendMessage(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a Message containing only the what value.
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a Message containing only the what value, to be delivered
|
||||
* after the specified amount of time elapses.
|
||||
* @see #sendMessageDelayed(android.os.Message, long)
|
||||
*
|
||||
* @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 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.
|
||||
* @see #sendMessageAtTime(android.os.Message, long)
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
private final WeakReference<Handler.Callback> mCallback;
|
||||
|
||||
ExecHandler() {
|
||||
mCallback = null;
|
||||
}
|
||||
|
||||
ExecHandler(WeakReference<Handler.Callback> callback) {
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
ExecHandler(Looper looper) {
|
||||
super(looper);
|
||||
mCallback = null;
|
||||
}
|
||||
|
||||
ExecHandler(Looper looper, WeakReference<Handler.Callback> callback) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static class WeakRunnable implements Runnable {
|
||||
private final WeakReference<Runnable> mDelegate;
|
||||
private final WeakReference<ChainedRef> mReference;
|
||||
|
||||
WeakRunnable(WeakReference<Runnable> delegate, WeakReference<ChainedRef> reference) {
|
||||
mDelegate = delegate;
|
||||
mReference = reference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
final Runnable delegate = mDelegate.get();
|
||||
final ChainedRef reference = mReference.get();
|
||||
if (reference != null) {
|
||||
reference.remove();
|
||||
}
|
||||
if (delegate != null) {
|
||||
delegate.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class ChainedRef {
|
||||
@Nullable
|
||||
ChainedRef next;
|
||||
@Nullable
|
||||
ChainedRef prev;
|
||||
@NonNull
|
||||
final Runnable runnable;
|
||||
@NonNull
|
||||
final WeakRunnable wrapper;
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
}
|
40
BroadCast.md
40
BroadCast.md
@ -6,32 +6,32 @@ private BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
//可以通过intent获取到下载实体,下载实体中包含了各种下载状态
|
||||
DownloadEntity entity = intent.getParcelableExtra(DownloadManager.ENTITY);
|
||||
DownloadEntity entity = intent.getParcelableExtra(Aria.ENTITY);
|
||||
switch (action) {
|
||||
case DownloadManager.ACTION_PRE: //预处理
|
||||
case Aria.ACTION_PRE: //预处理
|
||||
break;
|
||||
case DownloadManager.ACTION_POST_PRE: //预处理完成
|
||||
case Aria.ACTION_POST_PRE: //预处理完成
|
||||
//预处理完成,便可以获取文件的下载长度了
|
||||
len = entity.getFileSize();
|
||||
break;
|
||||
case DownloadManager.ACTION_START: //开始下载
|
||||
case Aria.ACTION_START: //开始下载
|
||||
L.d(TAG, "download start");
|
||||
break;
|
||||
case DownloadManager.ACTION_RESUME: //恢复下载
|
||||
case Aria.ACTION_RESUME: //恢复下载
|
||||
L.d(TAG, "download resume");
|
||||
long location = intent.getLongExtra(DownloadManager.CURRENT_LOCATION, 1);
|
||||
break;
|
||||
case DownloadManager.ACTION_RUNNING: //下载中
|
||||
case Aria.ACTION_RUNNING: //下载中
|
||||
long current = intent.getLongExtra(DownloadManager.CURRENT_LOCATION, 0);
|
||||
break;
|
||||
case DownloadManager.ACTION_STOP: //停止下载
|
||||
case Aria.ACTION_STOP: //停止下载
|
||||
L.d(TAG, "download stop");
|
||||
break;
|
||||
case DownloadManager.ACTION_COMPLETE: //下载完成
|
||||
case Aria.ACTION_COMPLETE: //下载完成
|
||||
break;
|
||||
case DownloadManager.ACTION_CANCEL: //取消下载
|
||||
case Aria.ACTION_CANCEL: //取消下载
|
||||
break;
|
||||
case DownloadManager.ACTION_FAIL: // 下载失败
|
||||
case Aria.ACTION_FAIL: // 下载失败
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -44,15 +44,15 @@ private BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
super.onResume();
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addDataScheme(getPackageName());
|
||||
filter.addAction(DownloadManager.ACTION_PRE);
|
||||
filter.addAction(DownloadManager.ACTION_POST_PRE);
|
||||
filter.addAction(DownloadManager.ACTION_RESUME);
|
||||
filter.addAction(DownloadManager.ACTION_START);
|
||||
filter.addAction(DownloadManager.ACTION_RUNNING);
|
||||
filter.addAction(DownloadManager.ACTION_STOP);
|
||||
filter.addAction(DownloadManager.ACTION_CANCEL);
|
||||
filter.addAction(DownloadManager.ACTION_COMPLETE);
|
||||
filter.addAction(DownloadManager.ACTION_FAIL);
|
||||
filter.addAction(Aria.ACTION_PRE);
|
||||
filter.addAction(Aria.ACTION_POST_PRE);
|
||||
filter.addAction(Aria.ACTION_RESUME);
|
||||
filter.addAction(Aria.ACTION_START);
|
||||
filter.addAction(Aria.ACTION_RUNNING);
|
||||
filter.addAction(Aria.ACTION_STOP);
|
||||
filter.addAction(Aria.ACTION_CANCEL);
|
||||
filter.addAction(Aria.ACTION_COMPLETE);
|
||||
filter.addAction(Aria.ACTION_FAIL);
|
||||
registerReceiver(mReceiver, filter);
|
||||
}
|
||||
```
|
||||
```
|
||||
|
51
README.md
51
README.md
@ -15,7 +15,7 @@
|
||||
## 下载
|
||||
[](https://bintray.com/arialyy/maven/Aria/_latestVersion)</br>
|
||||
```java
|
||||
compile 'com.arialyy.aria:Aria:2.3.2'
|
||||
compile 'com.arialyy.aria:Aria:2.3.3'
|
||||
```
|
||||
|
||||
|
||||
@ -29,12 +29,13 @@ compile 'com.arialyy.aria:Aria:2.3.2'
|
||||
|
||||
***
|
||||
## 使用
|
||||
### 一、Aria 是实体驱动型的工具,所以,第一步,你需要创建一个下载实体
|
||||
### 一、只需要以下参数,你便能很简单的使用Aria下载文件了
|
||||
```java
|
||||
DownloadEntity mEntity = new DownloadEntity();
|
||||
mEntity.setFileName(fileName); //设置文件名
|
||||
mEntity.setDownloadUrl(downloadUrl); //设置下载链接
|
||||
mEntity.setDownloadPath(downloadPath); //设置存放路径
|
||||
Aria.whit(this)
|
||||
.load(DOWNLOAD_URL) //下载地址,必填
|
||||
.setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk") //文件保存路径,必填
|
||||
.setDownloadName("test.apk") //文件名,必填
|
||||
.start();
|
||||
```
|
||||
### 二、为了能接收到Aria传递的数据,你需要把你的Activity或fragment注册到Aria管理器中,注册的方式很简单,在onResume
|
||||
```java
|
||||
@ -43,26 +44,44 @@ compile 'com.arialyy.aria:Aria:2.3.2'
|
||||
Aria.whit(this).addSchedulerListener(new MySchedulerListener());
|
||||
}
|
||||
```
|
||||
### 三、还记得上面的DownloadEntity吗?现在是时候使用它进行下载了
|
||||
### 三、通过下载链接,你还能使用Aria执行很多操作,如:
|
||||
- 添加任务(不进行下载)
|
||||
|
||||
```java
|
||||
Aria.whit(this).load(DOWNLOAD_URL)
|
||||
.setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk") //文件保存路径,必填
|
||||
.setDownloadName("test.apk") //文件名,必填
|
||||
.add();
|
||||
```
|
||||
- 启动下载
|
||||
|
||||
```java
|
||||
Aria.whit(this).load(mEntity).start();
|
||||
Aria.whit(this).load(DOWNLOAD_URL).start();
|
||||
```
|
||||
- 暂停下载
|
||||
|
||||
```java
|
||||
Aria.whit(this).load(mEntity).stop();
|
||||
Aria.whit(this).load(DOWNLOAD_URL).stop();
|
||||
```
|
||||
- 恢复下载
|
||||
|
||||
```java
|
||||
Aria.whit(this).load(mEntity).resume();
|
||||
Aria.whit(this).load(DOWNLOAD_URL).resume();
|
||||
```
|
||||
- 取消下载
|
||||
|
||||
```java
|
||||
Aria.whit(this).load(mEntity).cancel();
|
||||
Aria.whit(this).load(DOWNLOAD_URL).cancel();
|
||||
```
|
||||
- 获取当前下载进度
|
||||
|
||||
```java
|
||||
Aria.whit(this).load(DOWNLOAD_URL).getCurrentProgress();
|
||||
```
|
||||
- 获取文件大小
|
||||
|
||||
```java
|
||||
Aria.whit(this).load(DOWNLOAD_URL).getFileSize();
|
||||
```
|
||||
|
||||
### 四、关于Aria,你还需要知道的一些东西
|
||||
@ -86,7 +105,7 @@ compile 'com.arialyy.aria:Aria:2.3.2'
|
||||
```java
|
||||
Aria.get(this).setReTryInterval(5000);
|
||||
```
|
||||
- 设置是否打开广播,如果你需要在Service后台获取下载完成情况,那么你需要打开Aria广播,[Aria广播配置](https://github.com/AriaLyy/Aria/blob/v_2.0/BroadCast.md)
|
||||
- 设置是否打开广播,如果你需要在Service后台获取下载完成情况,那么你需要打开Aria广播,[Aria广播配置](https://github.com/AriaLyy/Aria/blob/v_2.0/BroadCast.md)
|
||||
|
||||
```java
|
||||
Aria.get(this).openBroadcast(true);
|
||||
@ -94,9 +113,13 @@ compile 'com.arialyy.aria:Aria:2.3.2'
|
||||
|
||||
***
|
||||
## 开发日志
|
||||
+ v_2.1.0 修复大量bug
|
||||
+ v_2.1.1 增加,选择最大下载任务数接口
|
||||
+ v_2.3.3
|
||||
- 添加断点支持
|
||||
- 修改下载逻辑,让使用更加简单
|
||||
- 修复一个内存泄露的bug
|
||||
+ v_2.3.1 重命名为Aria,下载流程简化
|
||||
+ v_2.1.1 增加,选择最大下载任务数接口
|
||||
+ v_2.1.0 修复大量bug
|
||||
|
||||
License
|
||||
-------
|
||||
|
@ -132,7 +132,7 @@ public class MultiTaskActivity extends BaseActivity<ActivityMultiBinding> {
|
||||
}
|
||||
}
|
||||
|
||||
private class MySchedulerListener extends AMTarget.SimpleSchedulerListener{
|
||||
private class MySchedulerListener extends Aria.SimpleSchedulerListener{
|
||||
@Override public void onTaskPre(Task task) {
|
||||
super.onTaskPre(task);
|
||||
L.d(TAG, "download pre");
|
||||
|
@ -19,6 +19,8 @@ package com.arialyy.simple.activity;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
@ -26,6 +28,7 @@ import android.os.Message;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import butterknife.Bind;
|
||||
@ -53,6 +56,8 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
|
||||
public static final int DOWNLOAD_RUNNING = 0x07;
|
||||
private static final String DOWNLOAD_URL =
|
||||
"http://static.gaoshouyou.com/d/3a/93/573ae1db9493a801c24bf66128b11e39.apk";
|
||||
//private static final String DOWNLOAD_URL =
|
||||
// "http://www.yangqiang.im/wp-content/uploads/2016/10/%E6%8A%BD%E8%B1%A1%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F.png";
|
||||
@Bind(R.id.progressBar) HorizontalProgressBarWithNumber mPb;
|
||||
@Bind(R.id.start) Button mStart;
|
||||
@Bind(R.id.stop) Button mStop;
|
||||
@ -60,11 +65,12 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
|
||||
@Bind(R.id.size) TextView mSize;
|
||||
@Bind(R.id.toolbar) Toolbar toolbar;
|
||||
@Bind(R.id.speed) TextView mSpeed;
|
||||
@Bind(R.id.img) ImageView mImg;
|
||||
private DownloadEntity mEntity;
|
||||
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (action.equals(DownloadManager.ACTION_START)) {
|
||||
if (action.equals(Aria.ACTION_START)) {
|
||||
L.d("START");
|
||||
}
|
||||
}
|
||||
@ -76,14 +82,14 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
|
||||
switch (msg.what) {
|
||||
case DOWNLOAD_RUNNING:
|
||||
Task task = (Task) msg.obj;
|
||||
long current = task.getDownloadEntity().getCurrentProgress();
|
||||
long len = task.getDownloadEntity().getFileSize();
|
||||
long current = task.getCurrentProgress();
|
||||
long len = task.getFileSize();
|
||||
if (len == 0) {
|
||||
mPb.setProgress(0);
|
||||
} else {
|
||||
mPb.setProgress((int) ((current * 100) / len));
|
||||
}
|
||||
mSpeed.setText(CommonUtil.formatFileSize(task.getDownloadEntity().getSpeed()) + "/s");
|
||||
mSpeed.setText(CommonUtil.formatFileSize(task.getSpeed()) + "/s");
|
||||
break;
|
||||
case DOWNLOAD_PRE:
|
||||
mSize.setText(CommonUtil.formatFileSize((Long) msg.obj));
|
||||
@ -117,6 +123,11 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
|
||||
mStart.setText("重新开始?");
|
||||
mCancel.setEnabled(false);
|
||||
setBtState(true);
|
||||
|
||||
//String path = Environment.getExternalStorageDirectory().getPath() + "/test.jpg";
|
||||
//Bitmap bm = BitmapFactory.decodeFile(path);
|
||||
//mImg.setImageBitmap(bm);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -159,21 +170,10 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
|
||||
}
|
||||
|
||||
private void init() {
|
||||
mEntity = Aria.get(this).getDownloadEntity(DOWNLOAD_URL);
|
||||
if (mEntity != null) {
|
||||
mPb.setProgress((int) ((mEntity.getCurrentProgress() * 100) / mEntity.getFileSize()));
|
||||
mSize.setText(CommonUtil.formatFileSize(mEntity.getFileSize()));
|
||||
if (mEntity.getState() == DownloadEntity.STATE_DOWNLOAD_ING) {
|
||||
setBtState(false);
|
||||
} else if (mEntity.isDownloadComplete()) {
|
||||
mStart.setText("重新开始?");
|
||||
setBtState(true);
|
||||
}
|
||||
} else {
|
||||
mEntity = new DownloadEntity();
|
||||
mEntity.setFileName("test.apk");
|
||||
mEntity.setDownloadUrl(DOWNLOAD_URL);
|
||||
mEntity.setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk");
|
||||
if (Aria.get(this).taskExists(DOWNLOAD_URL)) {
|
||||
AMTarget target = Aria.whit(this).load(DOWNLOAD_URL);
|
||||
int p = (int) (target.getCurrentProgress() * 100 / target.getFileSize());
|
||||
mPb.setProgress(p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,22 +197,28 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
|
||||
}
|
||||
|
||||
private void resume() {
|
||||
Aria.whit(this).load(mEntity).resume();
|
||||
Aria.whit(this).load(DOWNLOAD_URL).resume();
|
||||
}
|
||||
|
||||
private void start() {
|
||||
Aria.whit(this).load(mEntity).start();
|
||||
Aria.whit(this)
|
||||
.load(DOWNLOAD_URL)
|
||||
.setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk")
|
||||
.setDownloadName("test.apk")
|
||||
//.setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.jpg")
|
||||
//.setDownloadName("test.jpg")
|
||||
.start();
|
||||
}
|
||||
|
||||
private void stop() {
|
||||
Aria.whit(this).load(mEntity).stop();
|
||||
Aria.whit(this).load(DOWNLOAD_URL).stop();
|
||||
}
|
||||
|
||||
private void cancel() {
|
||||
Aria.whit(this).load(mEntity).cancel();
|
||||
Aria.whit(this).load(DOWNLOAD_URL).cancel();
|
||||
}
|
||||
|
||||
private class MySchedulerListener extends AMTarget.SimpleSchedulerListener {
|
||||
private class MySchedulerListener extends Aria.SimpleSchedulerListener {
|
||||
@Override public void onTaskStart(Task task) {
|
||||
mUpdateHandler.obtainMessage(DOWNLOAD_PRE, task.getDownloadEntity().getFileSize())
|
||||
.sendToTarget();
|
||||
@ -220,8 +226,7 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
|
||||
|
||||
@Override public void onTaskResume(Task task) {
|
||||
super.onTaskResume(task);
|
||||
mUpdateHandler.obtainMessage(DOWNLOAD_PRE, task.getDownloadEntity().getFileSize())
|
||||
.sendToTarget();
|
||||
mUpdateHandler.obtainMessage(DOWNLOAD_PRE, task.getFileSize()).sendToTarget();
|
||||
}
|
||||
|
||||
@Override public void onTaskStop(Task task) {
|
||||
|
@ -19,6 +19,7 @@ package com.arialyy.simple.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
@ -86,8 +86,8 @@ public class DownloadModule extends BaseModule {
|
||||
}
|
||||
|
||||
private DownloadEntity createDownloadEntity(String url) {
|
||||
String fileName = CommonUtil.keyToHashCode(url) + ".apk";
|
||||
DownloadEntity entity = new DownloadEntity();
|
||||
String fileName = CommonUtil.keyToHashCode(url) + ".apk";
|
||||
DownloadEntity entity = new DownloadEntity();
|
||||
entity.setDownloadUrl(url);
|
||||
entity.setDownloadPath(getDownloadPath(url));
|
||||
entity.setFileName(fileName);
|
||||
@ -115,15 +115,15 @@ public class DownloadModule extends BaseModule {
|
||||
public IntentFilter getDownloadFilter() {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addDataScheme(getContext().getPackageName());
|
||||
filter.addAction(DownloadManager.ACTION_PRE);
|
||||
filter.addAction(DownloadManager.ACTION_POST_PRE);
|
||||
filter.addAction(DownloadManager.ACTION_RESUME);
|
||||
filter.addAction(DownloadManager.ACTION_START);
|
||||
filter.addAction(DownloadManager.ACTION_RUNNING);
|
||||
filter.addAction(DownloadManager.ACTION_STOP);
|
||||
filter.addAction(DownloadManager.ACTION_CANCEL);
|
||||
filter.addAction(DownloadManager.ACTION_COMPLETE);
|
||||
filter.addAction(DownloadManager.ACTION_FAIL);
|
||||
filter.addAction(Aria.ACTION_PRE);
|
||||
filter.addAction(Aria.ACTION_POST_PRE);
|
||||
filter.addAction(Aria.ACTION_RESUME);
|
||||
filter.addAction(Aria.ACTION_START);
|
||||
filter.addAction(Aria.ACTION_RUNNING);
|
||||
filter.addAction(Aria.ACTION_STOP);
|
||||
filter.addAction(Aria.ACTION_CANCEL);
|
||||
filter.addAction(Aria.ACTION_COMPLETE);
|
||||
filter.addAction(Aria.ACTION_FAIL);
|
||||
return filter;
|
||||
}
|
||||
|
||||
@ -138,36 +138,36 @@ public class DownloadModule extends BaseModule {
|
||||
@Override public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
switch (action) {
|
||||
case DownloadManager.ACTION_POST_PRE:
|
||||
DownloadEntity entity = intent.getParcelableExtra(DownloadManager.ENTITY);
|
||||
case Aria.ACTION_POST_PRE:
|
||||
DownloadEntity entity = intent.getParcelableExtra(Aria.ENTITY);
|
||||
len = entity.getFileSize();
|
||||
L.d(TAG, "download pre");
|
||||
handler.obtainMessage(SingleTaskActivity.DOWNLOAD_PRE, len).sendToTarget();
|
||||
break;
|
||||
case DownloadManager.ACTION_START:
|
||||
case Aria.ACTION_START:
|
||||
L.d(TAG, "download start");
|
||||
break;
|
||||
case DownloadManager.ACTION_RESUME:
|
||||
case Aria.ACTION_RESUME:
|
||||
L.d(TAG, "download resume");
|
||||
long location = intent.getLongExtra(DownloadManager.CURRENT_LOCATION, 1);
|
||||
long location = intent.getLongExtra(Aria.CURRENT_LOCATION, 1);
|
||||
handler.obtainMessage(SingleTaskActivity.DOWNLOAD_RESUME, location).sendToTarget();
|
||||
break;
|
||||
case DownloadManager.ACTION_RUNNING:
|
||||
long current = intent.getLongExtra(DownloadManager.CURRENT_LOCATION, 0);
|
||||
case Aria.ACTION_RUNNING:
|
||||
long current = intent.getLongExtra(Aria.CURRENT_LOCATION, 0);
|
||||
int progress = len == 0 ? 0 : (int) ((current * 100) / len);
|
||||
handler.obtainMessage(SingleTaskActivity.DOWNLOAD_RUNNING, progress).sendToTarget();
|
||||
break;
|
||||
case DownloadManager.ACTION_STOP:
|
||||
case Aria.ACTION_STOP:
|
||||
L.d(TAG, "download stop");
|
||||
handler.sendEmptyMessage(SingleTaskActivity.DOWNLOAD_STOP);
|
||||
break;
|
||||
case DownloadManager.ACTION_COMPLETE:
|
||||
case Aria.ACTION_COMPLETE:
|
||||
handler.sendEmptyMessage(SingleTaskActivity.DOWNLOAD_COMPLETE);
|
||||
break;
|
||||
case DownloadManager.ACTION_CANCEL:
|
||||
case Aria.ACTION_CANCEL:
|
||||
handler.sendEmptyMessage(SingleTaskActivity.DOWNLOAD_CANCEL);
|
||||
break;
|
||||
case DownloadManager.ACTION_FAIL:
|
||||
case Aria.ACTION_FAIL:
|
||||
handler.sendEmptyMessage(SingleTaskActivity.DOWNLOAD_FAILE);
|
||||
break;
|
||||
}
|
||||
|
@ -35,6 +35,7 @@
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/handle_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/progressBar"
|
||||
@ -79,4 +80,11 @@
|
||||
style="?buttonBarButtonStyle"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/img"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@+id/handle_bar"
|
||||
/>
|
||||
</RelativeLayout>
|
||||
|
Reference in New Issue
Block a user