diff --git a/.gitignore b/.gitignore index cda18dcf..0a7d0a5d 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ .externalNativeBuild .idea/misc.xml .gradle -/.idea \ No newline at end of file +/.idea +.idea \ No newline at end of file diff --git a/Aria/build.gradle b/Aria/build.gradle index 2aa5183d..1fa8d679 100644 --- a/Aria/build.gradle +++ b/Aria/build.gradle @@ -7,8 +7,8 @@ android { defaultConfig { minSdkVersion 9 targetSdkVersion 23 - versionCode 86 - versionName "2.4.2" + versionCode 100 + versionName "3.0.0" } buildTypes { release { diff --git a/Aria/src/main/java/com/arialyy/aria/core/AMReceiver.java b/Aria/src/main/java/com/arialyy/aria/core/AMReceiver.java deleted file mode 100644 index 5ae43a1a..00000000 --- a/Aria/src/main/java/com/arialyy/aria/core/AMReceiver.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.arialyy.aria.core; - -import android.support.annotation.NonNull; -import com.arialyy.aria.core.scheduler.DownloadSchedulers; -import com.arialyy.aria.core.scheduler.OnSchedulerListener; -import com.arialyy.aria.util.CheckUtil; - -/** - * Created by lyy on 2016/12/5. - * AM 接收器 - */ -public class AMReceiver { - String targetName; - OnSchedulerListener listener; - Object obj; - - /** - * {@link #load(String)},请使用该方法 - */ - @Deprecated public AMTarget load(DownloadEntity entity) { - return new AMTarget(entity, targetName); - } - - /** - * 读取下载链接 - */ - public AMTarget load(@NonNull String downloadUrl) { - CheckUtil.checkDownloadUrl(downloadUrl); - DownloadEntity entity = - DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl); - if (entity == null) { - entity = new DownloadEntity(); - } - entity.setDownloadUrl(downloadUrl); - return new AMTarget(entity, targetName); - } - - /** - * 添加调度器回调 - */ - public AMReceiver addSchedulerListener(OnSchedulerListener listener) { - this.listener = listener; - DownloadSchedulers.getInstance().addSchedulerListener(targetName, listener); - return this; - } - - /** - * 移除回调 - */ - public AMReceiver removeSchedulerListener() { - if (listener != null) { - DownloadSchedulers.getInstance().removeSchedulerListener(targetName, listener); - } - return this; - } - - void destroy() { - targetName = null; - listener = null; - } -} \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/AMTarget.java b/Aria/src/main/java/com/arialyy/aria/core/AMTarget.java deleted file mode 100644 index cf7e5742..00000000 --- a/Aria/src/main/java/com/arialyy/aria/core/AMTarget.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.arialyy.aria.core; - -import android.support.annotation.NonNull; -import android.text.TextUtils; -import com.arialyy.aria.core.command.CmdFactory; -import com.arialyy.aria.core.command.IDownloadCmd; -import com.arialyy.aria.util.CheckUtil; -import com.arialyy.aria.util.CommonUtil; -import java.util.ArrayList; -import java.util.List; - -/** - * Created by lyy on 2016/12/5. - * https://github.com/AriaLyy/Aria - */ -public class AMTarget { - //private AMReceiver mReceiver; - DownloadEntity entity; - String targetName; - - AMTarget(DownloadEntity entity, String targetName) { - this.entity = entity; - this.targetName = targetName; - } - - /** - * 设置文件存储路径 - */ - public AMTarget setDownloadPath(@NonNull String downloadPath) { - if (TextUtils.isEmpty(downloadPath)) { - throw new IllegalArgumentException("文件保持路径不能为null"); - } - entity.setDownloadPath(downloadPath); - return this; - } - - /** - * 设置文件名 - */ - public AMTarget setDownloadName(@NonNull String downloadName) { - if (TextUtils.isEmpty(downloadName)) { - throw new IllegalArgumentException("文件名不能为null"); - } - entity.setFileName(downloadName); - return this; - } - - /** - * 获取下载文件大小 - */ - public long getFileSize() { - DownloadEntity entity = getDownloadEntity(this.entity.getDownloadUrl()); - if (entity == null) { - throw new NullPointerException("下载管理器中没有改任务"); - } - return entity.getFileSize(); - } - - /** - * 获取当前下载进度,如果下載实体存在,则返回当前进度 - */ - public long getCurrentProgress() { - DownloadEntity entity = getDownloadEntity(this.entity.getDownloadUrl()); - if (entity == null) { - throw new NullPointerException("下载管理器中没有改任务"); - } - return entity.getCurrentProgress(); - } - - private DownloadEntity getDownloadEntity(String downloadUrl) { - CheckUtil.checkDownloadUrl(downloadUrl); - return DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl); - } - - /** - * 添加任务 - */ - public void add() { - DownloadManager.getInstance() - .setCmd(CommonUtil.createCmd(targetName, entity, CmdFactory.TASK_CREATE)) - .exe(); - } - - /** - * 开始下载 - */ - public void start() { - List cmds = new ArrayList<>(); - cmds.add(CommonUtil.createCmd(targetName, entity, CmdFactory.TASK_CREATE)); - cmds.add(CommonUtil.createCmd(targetName, entity, CmdFactory.TASK_START)); - DownloadManager.getInstance().setCmds(cmds).exe(); - cmds.clear(); - } - - /** - * 停止下载 - */ - public void stop() { - DownloadManager.getInstance() - .setCmd(CommonUtil.createCmd(targetName, entity, CmdFactory.TASK_STOP)) - .exe(); - } - - /** - * 恢复下载 - */ - public void resume() { - DownloadManager.getInstance() - .setCmd(CommonUtil.createCmd(targetName, entity, CmdFactory.TASK_START)) - .exe(); - } - - /** - * 取消下载 - */ - public void cancel() { - DownloadManager.getInstance() - .setCmd(CommonUtil.createCmd(targetName, entity, CmdFactory.TASK_CANCEL)) - .exe(); - } - - /** - * 是否在下载 - */ - public boolean isDownloading() { - return DownloadManager.getInstance().getTaskQueue().getTask(entity).isDownloading(); - } - - /** - * 重新下载 - */ - public void reStart() { - cancel(); - start(); - } -} diff --git a/Aria/src/main/java/com/arialyy/aria/core/AMUplodReceiver.java b/Aria/src/main/java/com/arialyy/aria/core/AMUplodReceiver.java deleted file mode 100644 index 981c5e6d..00000000 --- a/Aria/src/main/java/com/arialyy/aria/core/AMUplodReceiver.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.arialyy.aria.core; - -/** - * Created by Aria.Lao on 2017/1/18. - * AM 上传文件接收器 - */ -public class AMUplodReceiver { -} diff --git a/Aria/src/main/java/com/arialyy/aria/core/Aria.java b/Aria/src/main/java/com/arialyy/aria/core/Aria.java index b3c5a6c9..c1b20207 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/Aria.java +++ b/Aria/src/main/java/com/arialyy/aria/core/Aria.java @@ -26,9 +26,12 @@ import android.app.Service; import android.content.Context; import android.os.Build; import android.widget.PopupWindow; -import com.arialyy.aria.core.scheduler.OnSchedulerListener; -import com.arialyy.aria.core.task.Task; -import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.core.download.DownloadReceiver; +import com.arialyy.aria.core.scheduler.IDownloadSchedulerListener; +import com.arialyy.aria.core.scheduler.ISchedulerListener; +import com.arialyy.aria.core.download.DownloadTask; +import com.arialyy.aria.core.upload.UploadReceiver; +import com.arialyy.aria.core.upload.UploadTask; /** * Created by lyy on 2016/12/1. @@ -36,17 +39,28 @@ import com.arialyy.aria.util.CheckUtil; * Aria启动,管理全局任务 *
  *   
- *   //启动下载
- *   Aria.whit(this)
+ *   //下载
+ *   Aria.download(this)
  *       .load(DOWNLOAD_URL)     //下载地址,必填
  *       //文件保存路径,必填
  *       .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk")
- *       .setDownloadName("test.apk")    //文件名,必填
  *       .start();
  *   
+ *   
+ *    //上传
+ *    Aria.upload(this)
+ *        .load(filePath)     //文件路径,必填
+ *        .setUploadUrl(uploadUrl)  //上传路径,必填
+ *        .setAttachment(fileKey)   //服务器读取文件的key,必填
+ *        .start();
+ *   
  * 
*/ @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) public class Aria { + /** + * 不支持断点 + */ + public static final String ACTION_SUPPORT_BREAK_POINT = "ACTION_SUPPORT_BREAK_POINT"; /** * 预处理完成 */ @@ -99,148 +113,135 @@ import com.arialyy.aria.util.CheckUtil; private Aria() { } - /** - * 接受Activity、Service、Application + * 初始化下载 + * + * @param obj 支持类型有【Activity、Service、Application、DialogFragment、Fragment、PopupWindow、Dialog】 */ - public static AMReceiver whit(Context context) { - CheckUtil.checkNull(context); - if (context instanceof Activity - || context instanceof Service - || context instanceof Application) { - return AriaManager.getInstance(context).get(context); - } else { - throw new IllegalArgumentException("这是不支持的context"); - } + public static DownloadReceiver download(Object obj) { + return get(obj).download(obj); } /** - * 处理Fragment + * 初始化上传 + * + * @param obj 支持类型有【Activity、Service、Application、DialogFragment、Fragment、PopupWindow、Dialog】 */ - public static AMReceiver whit(Fragment fragment) { - CheckUtil.checkNull(fragment); - return AriaManager.getInstance( - Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? fragment.getContext() - : fragment.getActivity()).get(fragment); + public static UploadReceiver upload(Object obj) { + return get(obj).upload(obj); } /** - * 处理Fragment - */ - public static AMReceiver whit(android.support.v4.app.Fragment fragment) { - CheckUtil.checkNull(fragment); - return AriaManager.getInstance( - Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? fragment.getContext() - : fragment.getActivity()).get(fragment); + * 处理通用事件 + * + * @param obj 支持类型有【Activity、Service、Application、DialogFragment、Fragment、PopupWindow、Dialog】 + */ + public static AriaManager get(Object obj) { + if (obj instanceof Activity || obj instanceof Service || obj instanceof Application) { + return AriaManager.getInstance((Context) obj); + } else if (obj instanceof DialogFragment) { + DialogFragment dialog = (DialogFragment) obj; + return AriaManager.getInstance( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? dialog.getContext() + : dialog.getActivity()); + } else if (obj instanceof android.support.v4.app.Fragment) { + android.support.v4.app.Fragment fragment = (android.support.v4.app.Fragment) obj; + return AriaManager.getInstance( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? fragment.getContext() + : fragment.getActivity()); + } else if (obj instanceof Fragment) { + Fragment fragment = (Fragment) obj; + return AriaManager.getInstance( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? fragment.getContext() + : fragment.getActivity()); + } else if (obj instanceof PopupWindow) { + PopupWindow popupWindow = (PopupWindow) obj; + return AriaManager.getInstance(popupWindow.getContentView().getContext()); + } else if (obj instanceof Dialog) { + Dialog dialog = (Dialog) obj; + return AriaManager.getInstance(dialog.getContext()); + } else { + throw new IllegalArgumentException("不支持的类型"); + } } /** - * 处理Fragment、或者DialogFragment + * 上传任务状态监听 */ - public static AMReceiver whit(DialogFragment dialog) { - CheckUtil.checkNull(dialog); - return AriaManager.getInstance( - Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? dialog.getContext() : dialog.getActivity()) - .get(dialog); - } + public static class UploadSchedulerListener implements ISchedulerListener { - /** - * 处理popupwindow - */ - public static AMReceiver whit(PopupWindow popupWindow) { - CheckUtil.checkNull(popupWindow); - return AriaManager.getInstance(popupWindow.getContentView().getContext()).get(popupWindow); - } + @Override public void onTaskPre(UploadTask task) { - /** - * 处理Dialog - */ - public static AMReceiver whit(Dialog dialog) { - CheckUtil.checkNull(dialog); - return AriaManager.getInstance(dialog.getContext()).get(dialog); - } + } + + @Override public void onTaskResume(UploadTask task) { - /** - * 处理通用事件 - */ - public static AriaManager get(Context context) { - if (context == null) throw new IllegalArgumentException("context 不能为 null"); - if (context instanceof Activity - || context instanceof Service - || context instanceof Application) { - return AriaManager.getInstance(context); - } else { - throw new IllegalArgumentException("这是不支持的context"); } - } - /** - * 处理Dialog的通用任务 - */ - public static AriaManager get(Dialog dialog) { - CheckUtil.checkNull(dialog); - return AriaManager.getInstance(dialog.getContext()); - } + @Override public void onTaskStart(UploadTask task) { - /** - * 处理Dialog的通用任务 - */ - public static AriaManager get(PopupWindow popupWindow) { - CheckUtil.checkNull(popupWindow); - return AriaManager.getInstance(popupWindow.getContentView().getContext()); - } + } - /** - * 处理Fragment的通用任务 - */ - public static AriaManager get(Fragment fragment) { - CheckUtil.checkNull(fragment); - return AriaManager.getInstance( - Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? fragment.getContext() - : fragment.getActivity()); + @Override public void onTaskStop(UploadTask task) { + + } + + @Override public void onTaskCancel(UploadTask task) { + + } + + @Override public void onTaskFail(UploadTask task) { + + } + + @Override public void onTaskComplete(UploadTask task) { + + } + + @Override public void onTaskRunning(UploadTask task) { + + } } /** - * 处理Fragment的通用任务 + * 下载任务状态监听 */ - public static AriaManager get(android.support.v4.app.Fragment fragment) { - CheckUtil.checkNull(fragment); - return AriaManager.getInstance( - Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? fragment.getContext() - : fragment.getActivity()); - } + public static class DownloadSchedulerListener + implements IDownloadSchedulerListener { + + @Override public void onTaskPre(DownloadTask task) { - public static class SimpleSchedulerListener implements OnSchedulerListener { + } - @Override public void onTaskPre(Task task) { + @Override public void onTaskResume(DownloadTask task) { } - @Override public void onTaskResume(Task task) { + @Override public void onTaskStart(DownloadTask task) { } - @Override public void onTaskStart(Task task) { + @Override public void onTaskStop(DownloadTask task) { } - @Override public void onTaskStop(Task task) { + @Override public void onTaskCancel(DownloadTask task) { } - @Override public void onTaskCancel(Task task) { + @Override public void onTaskFail(DownloadTask task) { } - @Override public void onTaskFail(Task task) { + @Override public void onTaskComplete(DownloadTask task) { } - @Override public void onTaskComplete(Task task) { + @Override public void onTaskRunning(DownloadTask task) { } - @Override public void onTaskRunning(Task task) { + @Override public void onNoSupportBreakPoint(DownloadTask task) { } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java b/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java index c7062c66..c896c415 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java +++ b/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java @@ -15,33 +15,36 @@ */ package com.arialyy.aria.core; +import android.annotation.SuppressLint; 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 android.widget.PopupWindow; -import com.arialyy.aria.core.command.CmdFactory; +import com.arialyy.aria.core.download.DownloadEntity; +import com.arialyy.aria.core.download.DownloadReceiver; +import com.arialyy.aria.core.inf.ICmd; +import com.arialyy.aria.core.inf.IReceiver; +import com.arialyy.aria.core.queue.DownloadTaskQueue; +import com.arialyy.aria.core.queue.UploadTaskQueue; +import com.arialyy.aria.core.upload.UploadReceiver; +import com.arialyy.aria.orm.DbEntity; +import com.arialyy.aria.orm.DbUtil; import com.arialyy.aria.util.CAConfiguration; -import com.arialyy.aria.util.CheckUtil; -import com.arialyy.aria.util.CommonUtil; -import com.arialyy.aria.core.command.IDownloadCmd; import com.arialyy.aria.util.Configuration; -import java.lang.reflect.Field; +import com.arialyy.aria.util.Speed; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Set; /** * Created by lyy on 2016/12/1. @@ -49,19 +52,22 @@ import java.util.Set; * Aria管理器,任务操作在这里执行 */ @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) public class AriaManager { - private static final String TAG = "AriaManager"; - private static final Object LOCK = new Object(); - private static volatile AriaManager INSTANCE = null; - private Map mTargets = new HashMap<>(); - private DownloadManager mManager; - private LifeCallback mLifeCallback; + private static final String TAG = "AriaManager"; + private static final String DOWNLOAD = "_download"; + private static final String UPLOAD = "_upload"; + private static final Object LOCK = new Object(); + @SuppressLint("StaticFieldLeak") private static volatile AriaManager INSTANCE = null; + private Map mReceivers = new HashMap<>(); + public static Context APP; + private List mCommands = new ArrayList<>(); private AriaManager(Context context) { + DbUtil.init(context.getApplicationContext()); + APP = context.getApplicationContext(); regAppLifeCallback(context); - mManager = DownloadManager.init(context); } - static AriaManager getInstance(Context context) { + public static AriaManager getInstance(Context context) { if (INSTANCE == null) { synchronized (LOCK) { INSTANCE = new AriaManager(context); @@ -70,62 +76,83 @@ import java.util.Set; return INSTANCE; } - AMReceiver get(Object obj) { - return getTarget(obj); + public Map getReceiver() { + return mReceivers; } /** - * 设置CA证书信息 - * - * @param caAlias ca证书别名 - * @param caPath assets 文件夹下的ca证书完整路径 + * 设置最大下载速度 */ - public void setCAInfo(String caAlias, String caPath) { - if (TextUtils.isEmpty(caAlias)) { - Log.e(TAG, "ca证书别名不能为null"); - return; - } else if (TextUtils.isEmpty(caPath)) { - Log.e(TAG, "ca证书路径不能为null"); - return; + public void setMaxSpeed(Speed speed) { + Configuration.getInstance().setMaxSpeed(speed); + } + + /** + * 设置命令 + */ + public AriaManager setCmd(ICmd command) { + mCommands.add(command); + return this; + } + + /** + * 设置一组命令 + */ + public AriaManager setCmds(List commands) { + if (commands != null && commands.size() > 0) { + mCommands.addAll(commands); } - CAConfiguration.CA_ALIAS = caAlias; - CAConfiguration.CA_PATH = caPath; + return this; } /** - * 获取下载列表 + * 执行所有设置的命令 */ - public List getDownloadList() { - return DownloadEntity.findAllData(DownloadEntity.class); + public synchronized void exe() { + for (ICmd command : mCommands) { + command.executeCmd(); + } + mCommands.clear(); } /** - * 通过下载链接获取下载实体 + * 处理下载操作 */ - public DownloadEntity getDownloadEntity(String downloadUrl) { - CheckUtil.checkDownloadUrl(downloadUrl); - return DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl); + DownloadReceiver download(Object obj) { + IReceiver receiver = mReceivers.get(getKey(true, obj)); + if (receiver == null) { + receiver = putReceiver(true, obj); + } + return (receiver instanceof DownloadReceiver) ? (DownloadReceiver) receiver : null; } /** - * 下载任务是否存在 + * 处理上传操作 */ - public boolean taskExists(String downloadUrl) { - return DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl) != null; + UploadReceiver upload(Object obj) { + IReceiver receiver = mReceivers.get(getKey(false, obj)); + if (receiver == null) { + receiver = putReceiver(false, obj); + } + return (receiver instanceof UploadReceiver) ? (UploadReceiver) receiver : null; } /** - * 停止所有正在执行的任务 + * 设置CA证书信息 + * + * @param caAlias ca证书别名 + * @param caPath assets 文件夹下的ca证书完整路径 */ - public void stopAllTask() { - List allEntity = mManager.getAllDownloadEntity(); - List stopCmds = new ArrayList<>(); - for (DownloadEntity entity : allEntity) { - if (entity.getState() == DownloadEntity.STATE_DOWNLOAD_ING) { - stopCmds.add(CommonUtil.createCmd(entity, CmdFactory.TASK_STOP)); - } + public void setCAInfo(String caAlias, String caPath) { + if (TextUtils.isEmpty(caAlias)) { + Log.e(TAG, "ca证书别名不能为null"); + return; + } else if (TextUtils.isEmpty(caPath)) { + Log.e(TAG, "ca证书路径不能为null"); + return; } - mManager.setCmds(stopCmds).exe(); + CAConfiguration.CA_ALIAS = caAlias; + CAConfiguration.CA_PATH = caPath; } /** @@ -137,7 +164,7 @@ import java.util.Set; } /** - * 设置下载失败重试次数 + * 设置失败重试次数 */ public AriaManager setReTryNum(int reTryNum) { Configuration.getInstance().setReTryNum(reTryNum); @@ -145,7 +172,7 @@ import java.util.Set; } /** - * 设置下载失败重试间隔 + * 设置失败重试间隔 */ public AriaManager setReTryInterval(int interval) { Configuration.getInstance().setReTryInterval(interval); @@ -170,31 +197,41 @@ import java.util.Set; Log.w(TAG, "最大任务数不能小于 1"); return this; } - mManager.getTaskQueue().setDownloadNum(maxDownloadNum); + DownloadTaskQueue.getInstance().setDownloadNum(maxDownloadNum); return this; } - /** - * 删除所有任务 - */ - public void cancelAllTask() { - List allEntity = mManager.getAllDownloadEntity(); - List cancelCmds = new ArrayList<>(); - for (DownloadEntity entity : allEntity) { - cancelCmds.add(CommonUtil.createCmd(entity, CmdFactory.TASK_CANCEL)); + private IReceiver putReceiver(boolean isDownload, Object obj) { + final String key = getKey(isDownload, obj); + IReceiver receiver = mReceivers.get(key); + final WidgetLiftManager widgetLiftManager = new WidgetLiftManager(); + if (obj instanceof Dialog) { + widgetLiftManager.handleDialogLift((Dialog) obj); + } else if (obj instanceof PopupWindow) { + widgetLiftManager.handlePopupWindowLift((PopupWindow) obj); } - mManager.setCmds(cancelCmds).exe(); - Set keys = mTargets.keySet(); - for (String key : keys) { - AMReceiver target = mTargets.get(key); - target.removeSchedulerListener(); - mTargets.remove(key); + + if (receiver == null) { + if (isDownload) { + DownloadReceiver dReceiver = new DownloadReceiver(); + dReceiver.targetName = obj.getClass().getName(); + mReceivers.put(key, dReceiver); + receiver = dReceiver; + } else { + UploadReceiver uReceiver = new UploadReceiver(); + uReceiver.targetName = obj.getClass().getName(); + mReceivers.put(key, uReceiver); + receiver = uReceiver; + } } + return receiver; } - private AMReceiver putTarget(Object obj) { + /** + * 根据功能类型和控件类型获取对应的key + */ + private String getKey(boolean isDownload, Object obj) { String clsName = obj.getClass().getName(); - AMReceiver target = null; String key = ""; if (!(obj instanceof Activity)) { if (obj instanceof android.support.v4.app.Fragment) { @@ -208,7 +245,6 @@ import java.util.Set; } else { key = clsName; } - handleDialogLift((Dialog) obj); } else if (obj instanceof PopupWindow) { Context context = ((PopupWindow) obj).getContentView().getContext(); if (context instanceof Activity) { @@ -216,7 +252,6 @@ import java.util.Set; } else { key = clsName; } - handlePopupWindowLift((PopupWindow) obj); } else if (obj instanceof Service) { key = clsName; } else if (obj instanceof Application) { @@ -231,76 +266,8 @@ import java.util.Set; if (TextUtils.isEmpty(key)) { throw new IllegalArgumentException("未知类型"); } - target = mTargets.get(key); - if (target == null) { - target = new AMReceiver(); - target.targetName = obj.getClass().getName(); - mTargets.put(key, target); - } - return target; - } - - /** - * 出来悬浮框取消或dismiss - */ - private void handlePopupWindowLift(PopupWindow popupWindow) { - try { - Field dismissField = CommonUtil.getField(popupWindow.getClass(), "mOnDismissListener"); - PopupWindow.OnDismissListener listener = - (PopupWindow.OnDismissListener) dismissField.get(popupWindow); - if (listener != null) { - Log.e(TAG, "你已经对PopupWindow设置了Dismiss事件。为了防止内存泄露," - + "请在dismiss方法中调用Aria.whit(this).removeSchedulerListener();来注销事件"); - } else { - popupWindow.setOnDismissListener(createPopupWindowListener(popupWindow)); - } - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - - /** - * 创建popupWindow dismiss事件 - */ - private PopupWindow.OnDismissListener createPopupWindowListener(final PopupWindow popupWindow) { - return new PopupWindow.OnDismissListener() { - @Override public void onDismiss() { - destroySchedulerListener(popupWindow); - } - }; - } - - /** - * 处理对话框取消或dismiss - */ - private void handleDialogLift(Dialog dialog) { - try { - Field dismissField = CommonUtil.getField(dialog.getClass(), "mDismissMessage"); - Message dismissMsg = (Message) dismissField.get(dialog); - //如果Dialog已经设置Dismiss事件,则查找cancel事件 - if (dismissMsg != null) { - Field cancelField = CommonUtil.getField(dialog.getClass(), "mCancelMessage"); - Message cancelMsg = (Message) cancelField.get(dialog); - if (cancelMsg != null) { - Log.e(TAG, "你已经对Dialog设置了Dismiss和cancel事件。为了防止内存泄露," - + "请在dismiss方法中调用Aria.whit(this).removeSchedulerListener();来注销事件"); - } else { - dialog.setOnCancelListener(createCancelListener()); - } - } else { - dialog.setOnDismissListener(createDismissListener()); - } - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - - private AMReceiver getTarget(Object obj) { - AMReceiver target = mTargets.get(obj.getClass().getName()); - if (target == null) { - target = putTarget(obj); - } - return target; + key += isDownload ? DOWNLOAD : UPLOAD; + return key; } /** @@ -309,50 +276,22 @@ import java.util.Set; private void regAppLifeCallback(Context context) { Context app = context.getApplicationContext(); if (app instanceof Application) { - mLifeCallback = new LifeCallback(); + LifeCallback mLifeCallback = new LifeCallback(); ((Application) app).registerActivityLifecycleCallbacks(mLifeCallback); } } - /** - * 创建Dialog取消事件 - */ - private Dialog.OnCancelListener createCancelListener() { - return new Dialog.OnCancelListener() { - - @Override public void onCancel(DialogInterface dialog) { - destroySchedulerListener(dialog); - } - }; - } - - /** - * 创建Dialog dismiss取消事件 - */ - private Dialog.OnDismissListener createDismissListener() { - return new Dialog.OnDismissListener() { - - @Override public void onDismiss(DialogInterface dialog) { - destroySchedulerListener(dialog); - } - }; - } - /** * onDestroy */ - private void destroySchedulerListener(Object obj) { - Set keys = mTargets.keySet(); + void destroySchedulerListener(Object obj) { String clsName = obj.getClass().getName(); - for (Iterator> iter = mTargets.entrySet().iterator(); + for (Iterator> iter = mReceivers.entrySet().iterator(); iter.hasNext(); ) { - Map.Entry entry = iter.next(); + Map.Entry entry = iter.next(); String key = entry.getKey(); - 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; - } + if (key.contains(clsName)) { + IReceiver receiver = mReceivers.get(key); receiver.removeSchedulerListener(); receiver.destroy(); iter.remove(); diff --git a/Aria/src/main/java/com/arialyy/aria/core/DownloadManager.java b/Aria/src/main/java/com/arialyy/aria/core/DownloadManager.java deleted file mode 100644 index 12640284..00000000 --- a/Aria/src/main/java/com/arialyy/aria/core/DownloadManager.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.arialyy.aria.core; - -import android.content.Context; -import com.arialyy.aria.core.queue.ITaskQueue; -import com.arialyy.aria.orm.DbUtil; -import com.arialyy.aria.core.command.IDownloadCmd; -import com.arialyy.aria.core.queue.DownloadTaskQueue; -import com.arialyy.aria.orm.DbEntity; -import com.arialyy.aria.util.Configuration; -import java.util.ArrayList; -import java.util.List; - -/** - * Created by lyy on 2016/8/11. - * 下载管理器,通过命令的方式控制下载 - */ -public class DownloadManager { - private static final String TAG = "DownloadManager"; - private static final Object LOCK = new Object(); - private static volatile DownloadManager INSTANCE = null; - private List mCommands = new ArrayList<>(); - public static Context APP; - private ITaskQueue mTaskQueue; - private static Configuration mConfig; - - private DownloadManager() { - - } - - private DownloadManager(Context context) { - APP = context; - DownloadTaskQueue.Builder builder = new DownloadTaskQueue.Builder(context); - mTaskQueue = builder.build(); - DbUtil.init(context); - } - - static DownloadManager init(Context context) { - if (INSTANCE == null) { - synchronized (LOCK) { - INSTANCE = new DownloadManager(context.getApplicationContext()); - } - } - return INSTANCE; - } - - public static DownloadManager getInstance() { - if (INSTANCE == null) { - throw new NullPointerException("请在Application中调用init进行下载器注册"); - } - return INSTANCE; - } - - List getAllDownloadEntity() { - return DbEntity.findAllData(DownloadEntity.class); - } - - /** - * 获取任务队列 - */ - public ITaskQueue getTaskQueue() { - return mTaskQueue; - } - - /** - * 设置命令 - */ - DownloadManager setCmd(IDownloadCmd command) { - mCommands.add(command); - return this; - } - - /** - * 设置一组命令 - */ - DownloadManager setCmds(List commands) { - if (commands != null && commands.size() > 0) { - mCommands.addAll(commands); - } - return this; - } - - /** - * 执行所有设置的命令 - */ - synchronized void exe() { - for (IDownloadCmd command : mCommands) { - command.executeCmd(); - } - mCommands.clear(); - } -} \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/RequestEnum.java b/Aria/src/main/java/com/arialyy/aria/core/RequestEnum.java index 43423f82..4d3766d5 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/RequestEnum.java +++ b/Aria/src/main/java/com/arialyy/aria/core/RequestEnum.java @@ -1,13 +1,28 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.arialyy.aria.core; /** * Created by Aria.Lao on 2017/1/23. + * url请求方式,目前支持GET、POST */ - public enum RequestEnum { GET("GET"), POST("POST"); - String name; + public String name; RequestEnum(String name) { this.name = name; diff --git a/Aria/src/main/java/com/arialyy/aria/core/TaskEntity.java b/Aria/src/main/java/com/arialyy/aria/core/TaskEntity.java deleted file mode 100644 index 0cc6be80..00000000 --- a/Aria/src/main/java/com/arialyy/aria/core/TaskEntity.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.arialyy.aria.core; - -/** - * Created by Aria.Lao on 2017/1/23. - * 任务实体 - */ -public class TaskEntity { - public DownloadEntity downloadEntity; - public RequestEnum requestEnum = RequestEnum.GET; -} diff --git a/Aria/src/main/java/com/arialyy/aria/core/WidgetLiftManager.java b/Aria/src/main/java/com/arialyy/aria/core/WidgetLiftManager.java new file mode 100644 index 00000000..f604c93f --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/WidgetLiftManager.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Message; +import android.util.Log; +import android.widget.PopupWindow; +import com.arialyy.aria.util.CommonUtil; +import java.lang.reflect.Field; + +/** + * Created by Aria.Lao on 2017/2/7. + * 为组件添加生命周期 + */ +final class WidgetLiftManager { + private final String TAG = "WidgetLiftManager"; + + /** + * 处理悬浮框取消或dismiss事件 + */ + void handlePopupWindowLift(PopupWindow popupWindow) { + try { + Field dismissField = CommonUtil.getField(popupWindow.getClass(), "mOnDismissListener"); + PopupWindow.OnDismissListener listener = + (PopupWindow.OnDismissListener) dismissField.get(popupWindow); + if (listener != null) { + Log.e(TAG, "你已经对PopupWindow设置了Dismiss事件。为了防止内存泄露," + + "请在dismiss方法中调用Aria.download(this).removeSchedulerListener();来注销事件"); + } else { + popupWindow.setOnDismissListener(createPopupWindowListener(popupWindow)); + } + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + + /** + * 创建popupWindow dismiss事件 + */ + private PopupWindow.OnDismissListener createPopupWindowListener(final PopupWindow popupWindow) { + return new PopupWindow.OnDismissListener() { + @Override public void onDismiss() { + AriaManager.getInstance(AriaManager.APP).destroySchedulerListener(popupWindow); + } + }; + } + + /** + * 处理对话框取消或dismiss + */ + void handleDialogLift(Dialog dialog) { + try { + Field dismissField = CommonUtil.getField(dialog.getClass(), "mDismissMessage"); + Message dismissMsg = (Message) dismissField.get(dialog); + //如果Dialog已经设置Dismiss事件,则查找cancel事件 + if (dismissMsg != null) { + Field cancelField = CommonUtil.getField(dialog.getClass(), "mCancelMessage"); + Message cancelMsg = (Message) cancelField.get(dialog); + if (cancelMsg != null) { + Log.e(TAG, "你已经对Dialog设置了Dismiss和cancel事件。为了防止内存泄露," + + "请在dismiss方法中调用Aria.download(this).removeSchedulerListener();来注销事件"); + } else { + dialog.setOnCancelListener(createCancelListener()); + } + } else { + dialog.setOnDismissListener(createDismissListener()); + } + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + + /** + * 创建Dialog取消事件 + */ + private Dialog.OnCancelListener createCancelListener() { + return new Dialog.OnCancelListener() { + + @Override public void onCancel(DialogInterface dialog) { + AriaManager.getInstance(AriaManager.APP).destroySchedulerListener(dialog); + } + }; + } + + /** + * 创建Dialog dismiss取消事件 + */ + private Dialog.OnDismissListener createDismissListener() { + return new Dialog.OnDismissListener() { + + @Override public void onDismiss(DialogInterface dialog) { + AriaManager.getInstance(AriaManager.APP).destroySchedulerListener(dialog); + } + }; + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/IDownloadCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/AbsCmd.java similarity index 61% rename from Aria/src/main/java/com/arialyy/aria/core/command/IDownloadCmd.java rename to Aria/src/main/java/com/arialyy/aria/core/command/AbsCmd.java index 0bd6a313..452b0a34 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/IDownloadCmd.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/AbsCmd.java @@ -16,44 +16,38 @@ package com.arialyy.aria.core.command; -import com.arialyy.aria.core.DownloadManager; +import com.arialyy.aria.core.download.DownloadTaskEntity; +import com.arialyy.aria.core.inf.ITaskEntity; +import com.arialyy.aria.core.queue.DownloadTaskQueue; import com.arialyy.aria.core.queue.ITaskQueue; +import com.arialyy.aria.core.inf.ICmd; +import com.arialyy.aria.core.queue.UploadTaskQueue; +import com.arialyy.aria.core.upload.UploadTaskEntity; import com.arialyy.aria.util.CheckUtil; import com.arialyy.aria.util.CommonUtil; -import com.arialyy.aria.core.DownloadEntity; /** * Created by lyy on 2016/8/22. * 下载命令 */ -public abstract class IDownloadCmd { +public abstract class AbsCmd implements ICmd { ITaskQueue mQueue; - DownloadEntity mEntity; + T mEntity; String TAG; String mTargetName; - /** - * @param entity 下载实体 - */ - IDownloadCmd(DownloadEntity entity) { - this(null, entity); - } - /** * @param targetName 产生任务的对象名 */ - IDownloadCmd(String targetName, DownloadEntity entity) { - if (!CheckUtil.checkDownloadEntity(entity)) { - return; - } + AbsCmd(String targetName, T entity) { + CheckUtil.checkCmdEntity(entity); mTargetName = targetName; mEntity = entity; TAG = CommonUtil.getClassName(this); - mQueue = DownloadManager.getInstance().getTaskQueue(); + if (entity instanceof DownloadTaskEntity) { + mQueue = DownloadTaskQueue.getInstance(); + } else if (entity instanceof UploadTaskEntity) { + mQueue = UploadTaskQueue.getInstance(); + } } - - /** - * 执行命令 - */ - public abstract void executeCmd(); } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/AddCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/AddCmd.java index 320d916f..06c12003 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/AddCmd.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/AddCmd.java @@ -17,29 +17,42 @@ package com.arialyy.aria.core.command; import android.util.Log; -import com.arialyy.aria.core.DownloadEntity; -import com.arialyy.aria.core.task.Task; +import com.arialyy.aria.core.inf.ITask; +import com.arialyy.aria.core.inf.ITaskEntity; /** * Created by lyy on 2016/8/22. * 添加任务的命令 */ -class AddCmd extends IDownloadCmd { +class AddCmd extends AbsCmd { - AddCmd(DownloadEntity entity) { - super(entity); - } - - AddCmd(String target, DownloadEntity entity) { - super(target, entity); + AddCmd(String targetName, T entity) { + super(targetName, entity); } @Override public void executeCmd() { - Task task = mQueue.getTask(mEntity); + ITask task = mQueue.getTask(mEntity.getEntity()); if (task == null) { mQueue.createTask(mTargetName, mEntity); } else { Log.w(TAG, "添加命令执行失败,【该任务已经存在】"); } } + + //AddCmd(DownloadTaskEntity entity) { + // super(entity); + //} + // + //AddCmd(String targetName, DownloadTaskEntity entity) { + // super(targetName, entity); + //} + // + //@Override public void executeCmd() { + // DownloadTask task = mQueue.getTask(mEntity.downloadEntity); + // if (task == null) { + // mQueue.createTask(mTargetName, mEntity); + // } else { + // Log.w(TAG, "添加命令执行失败,【该任务已经存在】"); + // } + //} } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/CancelCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/CancelCmd.java index 333e03fc..7024143a 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/CancelCmd.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/CancelCmd.java @@ -16,25 +16,20 @@ package com.arialyy.aria.core.command; -import com.arialyy.aria.core.DownloadEntity; -import com.arialyy.aria.core.task.Task; +import com.arialyy.aria.core.inf.ITask; +import com.arialyy.aria.core.inf.ITaskEntity; /** * Created by lyy on 2016/9/20. * 取消命令 */ -class CancelCmd extends IDownloadCmd { - - CancelCmd(String target, DownloadEntity entity) { - super(target, entity); - } - - CancelCmd(DownloadEntity entity) { - super(entity); +class CancelCmd extends AbsCmd { + CancelCmd(String targetName, T entity) { + super(targetName, entity); } @Override public void executeCmd() { - Task task = mQueue.getTask(mEntity); + ITask task = mQueue.getTask(mEntity.getEntity()); if (task == null) { task = mQueue.createTask(mTargetName, mEntity); } @@ -45,4 +40,25 @@ class CancelCmd extends IDownloadCmd { mQueue.cancelTask(task); } } + + //CancelCmd(DownloadTaskEntity entity) { + // super(entity); + //} + // + //CancelCmd(String targetName, DownloadTaskEntity entity) { + // super(targetName, entity); + //} + // + //@Override public void executeCmd() { + // DownloadTask task = mQueue.getTask(mEntity.downloadEntity); + // if (task == null) { + // task = mQueue.createTask(mTargetName, mEntity); + // } + // if (task != null) { + // if (mTargetName != null) { + // task.setTargetName(mTargetName); + // } + // mQueue.cancelTask(task); + // } + //} } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/CmdFactory.java b/Aria/src/main/java/com/arialyy/aria/core/command/CmdFactory.java index 786fb9dc..a9e7efc9 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/CmdFactory.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/CmdFactory.java @@ -16,7 +16,7 @@ package com.arialyy.aria.core.command; -import com.arialyy.aria.core.DownloadEntity; +import com.arialyy.aria.core.inf.ITaskEntity; /** * Created by Lyy on 2016/9/23. @@ -30,7 +30,7 @@ public class CmdFactory { /** * 启动任务 */ - public static final int TASK_START = 0x123; + public static final int TASK_START = 0x123; /** * 恢复任务 */ @@ -42,10 +42,10 @@ public class CmdFactory { /** * 停止任务 */ - public static final int TASK_STOP = 0x125; + public static final int TASK_STOP = 0x125; public static final int TASK_SINGLE = 0x126; - private static final Object LOCK = new Object(); + private static final Object LOCK = new Object(); private static volatile CmdFactory INSTANCE = null; private CmdFactory() { @@ -61,36 +61,13 @@ public class CmdFactory { return INSTANCE; } - /** - * @param entity 下载实体 - * @param type 命令类型{@link #TASK_CREATE}、{@link #TASK_START}、{@link #TASK_CANCEL}、{@link - * #TASK_STOP} - */ - public IDownloadCmd createCmd(DownloadEntity entity, int type) { - switch (type) { - case TASK_CREATE: - return createAddCmd(entity); - case TASK_RESUME: - case TASK_START: - return createStartCmd(entity); - case TASK_CANCEL: - return createCancelCmd(entity); - case TASK_STOP: - return createStopCmd(entity); - case TASK_SINGLE: - return new SingleCmd(entity); - default: - return null; - } - } - /** * @param target 创建任务的对象 * @param entity 下载实体 * @param type 命令类型{@link #TASK_CREATE}、{@link #TASK_START}、{@link #TASK_CANCEL}、{@link * #TASK_STOP} */ - public IDownloadCmd createCmd(String target, DownloadEntity entity, int type) { + public AbsCmd createCmd(String target, T entity, int type) { switch (type) { case TASK_CREATE: return createAddCmd(target, entity); @@ -102,7 +79,7 @@ public class CmdFactory { case TASK_STOP: return createStopCmd(target, entity); case TASK_SINGLE: - return new SingleCmd(target, entity); + //return new SingleCmd(target, entity); default: return null; } @@ -113,43 +90,25 @@ public class CmdFactory { * * @return {@link StopCmd} */ - private StopCmd createStopCmd(String target, DownloadEntity entity) { + private StopCmd createStopCmd(String target, T entity) { return new StopCmd(target, entity); } - /** - * 创建停止命令 - * - * @return {@link StopCmd} - */ - private StopCmd createStopCmd(DownloadEntity entity) { - return new StopCmd(entity); - } - /** * 创建下载任务命令 * * @return {@link AddCmd} */ - private AddCmd createAddCmd(String target, DownloadEntity entity) { + private AddCmd createAddCmd(String target, T entity) { return new AddCmd(target, entity); } - /** - * 创建下载任务命令 - * - * @return {@link AddCmd} - */ - private AddCmd createAddCmd(DownloadEntity entity) { - return new AddCmd(entity); - } - /** * 创建启动下载命令 * * @return {@link StartCmd} */ - private StartCmd createStartCmd(String target, DownloadEntity entity) { + private StartCmd createStartCmd(String target, T entity) { return new StartCmd(target, entity); } @@ -158,25 +117,7 @@ public class CmdFactory { * * @return {@link StartCmd} */ - private StartCmd createStartCmd(DownloadEntity entity) { - return new StartCmd(entity); - } - - /** - * 创建 取消下载的命令 - * - * @return {@link CancelCmd} - */ - private CancelCmd createCancelCmd(String target, DownloadEntity entity) { + private CancelCmd createCancelCmd(String target, T entity) { return new CancelCmd(target, entity); } - - /** - * 创建 取消下载的命令 - * - * @return {@link CancelCmd} - */ - private CancelCmd createCancelCmd(DownloadEntity entity) { - return new CancelCmd(entity); - } } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/SingleCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/SingleCmd.java deleted file mode 100644 index f7bbe04e..00000000 --- a/Aria/src/main/java/com/arialyy/aria/core/command/SingleCmd.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.arialyy.aria.core.command; - -import android.util.Log; -import com.arialyy.aria.core.DownloadEntity; -import com.arialyy.aria.core.task.Task; - -/** - * Created by lyy on 2016/11/30. - * 获取任务状态命令 - */ -class SingleCmd extends IDownloadCmd { - /** - * @param entity 下载实体 - */ - SingleCmd(String target, DownloadEntity entity) { - super(target, entity); - } - - SingleCmd(DownloadEntity entity) { - super(entity); - } - - @Override public void executeCmd() { - Task task = mQueue.getTask(mEntity); - if (task == null) { - task = mQueue.createTask(mTargetName, mEntity); - } else { - Log.w(TAG, "添加命令执行失败,【该任务已经存在】"); - } - task.setTargetName(mTargetName); - mQueue.startTask(task); - } -} diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/StartCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/StartCmd.java index 11c2dfc2..bec05307 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/StartCmd.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/StartCmd.java @@ -16,25 +16,22 @@ package com.arialyy.aria.core.command; -import com.arialyy.aria.core.DownloadEntity; -import com.arialyy.aria.core.task.Task; +import android.util.Log; +import com.arialyy.aria.core.inf.ITask; +import com.arialyy.aria.core.inf.ITaskEntity; /** * Created by lyy on 2016/8/22. * 开始命令 */ -class StartCmd extends IDownloadCmd { +class StartCmd extends AbsCmd { - StartCmd(String target, DownloadEntity entity) { - super(target, entity); - } - - StartCmd(DownloadEntity entity) { - super(entity); + StartCmd(String targetName, T entity) { + super(targetName, entity); } @Override public void executeCmd() { - Task task = mQueue.getTask(mEntity); + ITask task = mQueue.getTask(mEntity.getEntity()); if (task == null) { task = mQueue.createTask(mTargetName, mEntity); } @@ -43,4 +40,23 @@ class StartCmd extends IDownloadCmd { mQueue.startTask(task); } } + + //StartCmd(DownloadTaskEntity entity) { + // super(entity); + //} + // + //StartCmd(String targetName, DownloadTaskEntity entity) { + // super(targetName, entity); + //} + // + //@Override public void executeCmd() { + // DownloadTask task = mQueue.getTask(mEntity.downloadEntity); + // if (task == null) { + // task = mQueue.createTask(mTargetName, mEntity); + // } + // if (task != null) { + // task.setTargetName(mTargetName); + // mQueue.startTask(task); + // } + //} } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/StopCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/StopCmd.java index 676e8da7..3d617b32 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/StopCmd.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/StopCmd.java @@ -18,30 +18,24 @@ package com.arialyy.aria.core.command; import android.text.TextUtils; import android.util.Log; -import com.arialyy.aria.core.DownloadEntity; -import com.arialyy.aria.core.task.Task; +import com.arialyy.aria.core.inf.IEntity; +import com.arialyy.aria.core.inf.ITask; +import com.arialyy.aria.core.inf.ITaskEntity; /** * Created by lyy on 2016/9/20. * 停止命令 */ -class StopCmd extends IDownloadCmd { +class StopCmd extends AbsCmd { - /** - * @param entity 下载实体 - */ - StopCmd(String target, DownloadEntity entity) { - super(target, entity); - } - - StopCmd(DownloadEntity entity) { - super(entity); + StopCmd(String targetName, T entity) { + super(targetName, entity); } @Override public void executeCmd() { - Task task = mQueue.getTask(mEntity); + ITask task = mQueue.getTask(mEntity.getEntity()); if (task == null) { - if (mEntity.getState() == DownloadEntity.STATE_DOWNLOAD_ING) { + if (mEntity.getEntity().getState() == IEntity.STATE_RUNNING) { task = mQueue.createTask(mTargetName, mEntity); mQueue.stopTask(task); } else { @@ -54,4 +48,29 @@ class StopCmd extends IDownloadCmd { mQueue.stopTask(task); } } + + //StopCmd(DownloadTaskEntity entity) { + // super(entity); + //} + // + //StopCmd(String targetName, DownloadTaskEntity entity) { + // super(targetName, entity); + //} + // + //@Override public void executeCmd() { + // DownloadTask task = mQueue.getTask(mEntity.downloadEntity); + // if (task == null) { + // if (mEntity.downloadEntity.getState() == DownloadEntity.STATE_RUNNING) { + // task = mQueue.createTask(mTargetName, mEntity); + // mQueue.stopTask(task); + // } else { + // Log.w(TAG, "停止命令执行失败,【调度器中没有该任务】"); + // } + // } else { + // if (!TextUtils.isEmpty(mTargetName)) { + // task.setTargetName(mTargetName); + // } + // mQueue.stopTask(task); + // } + //} } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/task/ConnectionHelp.java b/Aria/src/main/java/com/arialyy/aria/core/download/ConnectionHelp.java similarity index 85% rename from Aria/src/main/java/com/arialyy/aria/core/task/ConnectionHelp.java rename to Aria/src/main/java/com/arialyy/aria/core/download/ConnectionHelp.java index 38ee2867..4f1ed6aa 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/task/ConnectionHelp.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/ConnectionHelp.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.arialyy.aria.core.task; +package com.arialyy.aria.core.download; import com.arialyy.aria.util.CAConfiguration; import com.arialyy.aria.util.SSLContextUtil; @@ -22,6 +22,7 @@ import java.net.HttpURLConnection; import java.net.ProtocolException; import java.net.URL; import java.net.URLConnection; +import java.util.Set; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; @@ -60,8 +61,15 @@ class ConnectionHelp { * * @throws ProtocolException */ - static HttpURLConnection setConnectParam(HttpURLConnection conn) throws ProtocolException { - conn.setRequestMethod("GET"); + static HttpURLConnection setConnectParam(DownloadTaskEntity entity, HttpURLConnection conn) + throws ProtocolException { + conn.setRequestMethod(entity.requestEnum.name); + if (entity.headers != null && entity.headers.size() > 0) { + Set keys = entity.headers.keySet(); + for (String key : keys) { + conn.setRequestProperty(key, entity.headers.get(key)); + } + } conn.setRequestProperty("Charset", "UTF-8"); conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"); diff --git a/Aria/src/main/java/com/arialyy/aria/core/DownloadEntity.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadEntity.java similarity index 69% rename from Aria/src/main/java/com/arialyy/aria/core/DownloadEntity.java rename to Aria/src/main/java/com/arialyy/aria/core/download/DownloadEntity.java index 53b69824..3ab34a32 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/DownloadEntity.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadEntity.java @@ -14,11 +14,12 @@ * limitations under the License. */ - -package com.arialyy.aria.core; +package com.arialyy.aria.core.download; import android.os.Parcel; import android.os.Parcelable; +import com.arialyy.aria.core.inf.IEntity; +import com.arialyy.aria.core.inf.ITaskEntity; import com.arialyy.aria.orm.Ignore; import com.arialyy.aria.orm.DbEntity; @@ -28,43 +29,7 @@ import com.arialyy.aria.orm.DbEntity; * !!! 注意:CREATOR要进行@Ignore注解 * !!!并且需要Parcelable时需要手动填写rowID; */ -public class DownloadEntity extends DbEntity implements Parcelable { - /** - * 其它状态 - */ - @Ignore public static final int STATE_OTHER = -1; - /** - * 失败状态 - */ - @Ignore public static final int STATE_FAIL = 0; - /** - * 完成状态 - */ - @Ignore public static final int STATE_COMPLETE = 1; - /** - * 停止状态 - */ - @Ignore public static final int STATE_STOP = 2; - /** - * 未开始状态 - */ - @Ignore public static final int STATE_WAIT = 3; - /** - * 下载中 - */ - @Ignore public static final int STATE_DOWNLOAD_ING = 4; - /** - * 预处理 - */ - @Ignore public static final int STATE_PRE = 5; - /** - * 预处理完成 - */ - @Ignore public static final int STATE_POST_PRE = 6; - /** - * 取消下载 - */ - @Ignore public static final int STATE_CANCEL = 7; +public class DownloadEntity extends DbEntity implements Parcelable, IEntity { @Ignore public static final Creator CREATOR = new Creator() { @Override public DownloadEntity createFromParcel(Parcel source) { return new DownloadEntity(source); @@ -74,16 +39,16 @@ public class DownloadEntity extends DbEntity implements Parcelable { return new DownloadEntity[size]; } }; - @Ignore private long speed = 0; //下载速度 - @Ignore private int failNum = 0; - private String downloadUrl = ""; //下载路径 - private String downloadPath = ""; //保存路径 - private String fileName = ""; //文件名 - private String str = ""; //其它字段 - private long fileSize = 1; - private int state = STATE_WAIT; - private boolean isDownloadComplete = false; //是否下载完成 - private long currentProgress = 0; //当前下载进度 + @Ignore private long speed = 0; //下载速度 + @Ignore private int failNum = 0; + private String downloadUrl = ""; //下载路径 + private String downloadPath = ""; //保存路径 + private String fileName = ""; //文件名 + private String str = ""; //其它字段 + private long fileSize = 1; + private int state = STATE_WAIT; + private boolean isDownloadComplete = false; //是否下载完成 + private long currentProgress = 0; //当前下载进度 private long completeTime; //完成时间 public DownloadEntity() { @@ -163,7 +128,7 @@ public class DownloadEntity extends DbEntity implements Parcelable { this.fileSize = fileSize; } - public int getState() { + @Override public int getState() { return state; } @@ -200,16 +165,26 @@ public class DownloadEntity extends DbEntity implements Parcelable { } @Override public String toString() { - return "DownloadEntity{" + - "downloadUrl='" + downloadUrl + '\'' + - ", downloadPath='" + downloadPath + '\'' + - ", completeTime=" + completeTime + - ", fileSize=" + fileSize + - ", state=" + state + - ", isDownloadComplete=" + isDownloadComplete + - ", currentProgress=" + currentProgress + - ", failNum=" + failNum + - '}'; + return "DownloadEntity{" + + "downloadUrl='" + + downloadUrl + + '\'' + + ", downloadPath='" + + downloadPath + + '\'' + + ", completeTime=" + + completeTime + + ", fileSize=" + + fileSize + + ", state=" + + state + + ", isDownloadComplete=" + + isDownloadComplete + + ", currentProgress=" + + currentProgress + + ", failNum=" + + failNum + + '}'; } @Override public int describeContents() { diff --git a/Aria/src/main/java/com/arialyy/aria/core/task/DownloadListener.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadListener.java similarity index 97% rename from Aria/src/main/java/com/arialyy/aria/core/task/DownloadListener.java rename to Aria/src/main/java/com/arialyy/aria/core/download/DownloadListener.java index bab38eae..b74f48a7 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/task/DownloadListener.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadListener.java @@ -14,8 +14,7 @@ * limitations under the License. */ - -package com.arialyy.aria.core.task; +package com.arialyy.aria.core.download; class DownloadListener implements IDownloadListener { diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java new file mode 100644 index 00000000..d52a18af --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.download; + +import android.support.annotation.NonNull; +import com.arialyy.aria.core.AriaManager; +import com.arialyy.aria.core.inf.IReceiver; +import com.arialyy.aria.core.command.CmdFactory; +import com.arialyy.aria.core.command.AbsCmd; +import com.arialyy.aria.core.scheduler.DownloadSchedulers; +import com.arialyy.aria.core.scheduler.ISchedulerListener; +import com.arialyy.aria.orm.DbEntity; +import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.CommonUtil; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * Created by lyy on 2016/12/5. + * 下载功能接收器 + */ +public class DownloadReceiver implements IReceiver { + private static final String TAG = "DownloadReceiver"; + public String targetName; + public ISchedulerListener listener; + + /** + * {@link #load(String)},请使用该方法 + */ + @Deprecated public DownloadTarget load(DownloadEntity entity) { + return new DownloadTarget(entity, targetName); + } + + /** + * 读取下载链接 + */ + public DownloadTarget load(@NonNull String downloadUrl) { + CheckUtil.checkDownloadUrl(downloadUrl); + DownloadEntity entity = + DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl); + if (entity == null) { + entity = new DownloadEntity(); + } + entity.setDownloadUrl(downloadUrl); + return new DownloadTarget(entity, targetName); + } + + /** + * 添加调度器回调 + */ + public DownloadReceiver addSchedulerListener(ISchedulerListener listener) { + this.listener = listener; + DownloadSchedulers.getInstance().addSchedulerListener(targetName, listener); + return this; + } + + /** + * 移除回调 + */ + @Override public void removeSchedulerListener() { + if (listener != null) { + DownloadSchedulers.getInstance().removeSchedulerListener(targetName, listener); + } + } + + @Override public void destroy() { + targetName = null; + listener = null; + } + + /** + * 通过下载链接获取下载实体 + */ + public DownloadEntity getDownloadEntity(String downloadUrl) { + CheckUtil.checkDownloadUrl(downloadUrl); + return DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl); + } + + /** + * 下载任务是否存在 + */ + @Override public boolean taskExists(String downloadUrl) { + return DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl) != null; + } + + @Override public List getTaskList() { + return DownloadEntity.findAllData(DownloadEntity.class); + } + + /** + * 停止所有正在下载的任务 + */ + @Override public void stopAllTask() { + final AriaManager ariaManager = AriaManager.getInstance(AriaManager.APP); + List allEntity = DbEntity.findAllData(DownloadEntity.class); + List stopCmds = new ArrayList<>(); + for (DownloadEntity entity : allEntity) { + if (entity.getState() == DownloadEntity.STATE_RUNNING) { + stopCmds.add( + CommonUtil.createCmd(targetName, new DownloadTaskEntity(entity), CmdFactory.TASK_STOP)); + } + } + ariaManager.setCmds(stopCmds).exe(); + } + + /** + * 删除所有任务 + */ + @Override public void removeAllTask() { + final AriaManager ariaManager = AriaManager.getInstance(AriaManager.APP); + List allEntity = DbEntity.findAllData(DownloadEntity.class); + List cancelCmds = new ArrayList<>(); + for (DownloadEntity entity : allEntity) { + cancelCmds.add( + CommonUtil.createCmd(targetName, new DownloadTaskEntity(entity), CmdFactory.TASK_CANCEL)); + } + ariaManager.setCmds(cancelCmds).exe(); + Set keys = ariaManager.getReceiver().keySet(); + for (String key : keys) { + IReceiver receiver = ariaManager.getReceiver().get(key); + receiver.removeSchedulerListener(); + ariaManager.getReceiver().remove(key); + } + } +} \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/task/DownloadStateConstance.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadStateConstance.java similarity index 92% rename from Aria/src/main/java/com/arialyy/aria/core/task/DownloadStateConstance.java rename to Aria/src/main/java/com/arialyy/aria/core/download/DownloadStateConstance.java index 00da093b..934ff001 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/task/DownloadStateConstance.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadStateConstance.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.arialyy.aria.core.task; +package com.arialyy.aria.core.download; /** * Created by lyy on 2017/1/18. @@ -32,8 +32,7 @@ final class DownloadStateConstance { boolean isCancel = false; boolean isStop = false; - DownloadStateConstance(int num) { - THREAD_NUM = num; + DownloadStateConstance() { } void cleanState() { @@ -46,6 +45,10 @@ final class DownloadStateConstance { FAIL_NUM = 0; } + void setThreadNum(int threadNum) { + THREAD_NUM = threadNum; + } + /** * 所有子线程是否都已经停止下载 */ diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java new file mode 100644 index 00000000..3e5c0334 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.download; + +import android.support.annotation.NonNull; +import android.text.TextUtils; +import com.arialyy.aria.core.RequestEnum; +import com.arialyy.aria.core.inf.AbsTarget; +import com.arialyy.aria.core.queue.DownloadTaskQueue; +import com.arialyy.aria.util.CheckUtil; +import java.io.File; +import java.util.Map; + +/** + * Created by lyy on 2016/12/5. + * https://github.com/AriaLyy/Aria + */ +public class DownloadTarget extends AbsTarget { + + DownloadTarget(DownloadEntity entity, String targetName) { + this.entity = entity; + this.targetName = targetName; + taskEntity = new DownloadTaskEntity(entity); + } + + @Override public void pause() { + super.pause(); + } + + @Override public void resume() { + super.resume(); + } + + /** + * 给url请求添加头部 + * + * @param key 头部key + * @param header 头部value + */ + public DownloadTarget addHeader(@NonNull String key, @NonNull String header) { + super._addHeader(key, header); + return this; + } + + /** + * 给url请求添加头部 + * + * @param headers key为http头部的key,Value为http头对应的配置 + */ + public DownloadTarget addHeaders(Map headers) { + super._addHeaders(headers); + return this; + } + + /** + * 设置请求类型 + * + * @param requestEnum {@link RequestEnum} + */ + public DownloadTarget setRequestMode(RequestEnum requestEnum) { + super._setRequestMode(requestEnum); + return this; + } + + /** + * 设置文件存储路径 + */ + public DownloadTarget setDownloadPath(@NonNull String downloadPath) { + if (TextUtils.isEmpty(downloadPath)) { + throw new IllegalArgumentException("文件保持路径不能为null"); + } + File file = new File(downloadPath); + entity.setDownloadPath(downloadPath); + entity.setFileName(file.getName()); + return this; + } + + /** + * 设置文件名 + */ + @Deprecated public DownloadTarget setDownloadName(@NonNull String downloadName) { + if (TextUtils.isEmpty(downloadName)) { + throw new IllegalArgumentException("文件名不能为null"); + } + entity.setFileName(downloadName); + return this; + } + + private DownloadEntity getDownloadEntity(String downloadUrl) { + CheckUtil.checkDownloadUrl(downloadUrl); + return DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", downloadUrl); + } + + /** + * 是否在下载 + */ + public boolean isDownloading() { + return DownloadTaskQueue.getInstance().getTask(entity).isRunning(); + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/task/Task.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTask.java similarity index 73% rename from Aria/src/main/java/com/arialyy/aria/core/task/Task.java rename to Aria/src/main/java/com/arialyy/aria/core/download/DownloadTask.java index 016ab8ef..a9c51c90 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/task/Task.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTask.java @@ -14,18 +14,19 @@ * limitations under the License. */ -package com.arialyy.aria.core.task; +package com.arialyy.aria.core.download; import android.content.Context; import android.content.Intent; 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.TaskEntity; +import com.arialyy.aria.core.AriaManager; +import com.arialyy.aria.core.inf.IEntity; +import com.arialyy.aria.core.inf.ITask; import com.arialyy.aria.core.scheduler.DownloadSchedulers; -import com.arialyy.aria.core.scheduler.IDownloadSchedulers; -import com.arialyy.aria.core.DownloadEntity; +import com.arialyy.aria.core.scheduler.ISchedulers; +import com.arialyy.aria.util.CheckUtil; import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.Configuration; import java.lang.ref.WeakReference; @@ -34,62 +35,87 @@ import java.lang.ref.WeakReference; * Created by lyy on 2016/8/11. * 下载任务类 */ -public class Task { - public static final String TAG = "Task"; +public class DownloadTask implements ITask { + public static final String TAG = "DownloadTask"; /** * 产生该任务对象的hash码 */ - private String mTargetName; - private DownloadEntity mEntity; + private String mTargetName; + private DownloadEntity mEntity; + private DownloadTaskEntity mTaskEntity; private IDownloadListener mListener; - private Handler mOutHandler; - private Context mContext; - private IDownloadUtil mUtil; + private Handler mOutHandler; + private IDownloadUtil mUtil; + private Context mContext; - private Task(Context context, DownloadEntity entity, Handler outHandler) { - mContext = context.getApplicationContext(); - mEntity = entity; + private DownloadTask(DownloadTaskEntity taskEntity, Handler outHandler) { + mTaskEntity = taskEntity; + mEntity = taskEntity.downloadEntity; mOutHandler = outHandler; + mContext = AriaManager.APP; init(); } private void init() { mListener = new DListener(mContext, this, mOutHandler); - mUtil = new DownloadUtil(mContext, mEntity, mListener); + mUtil = new DownloadUtil(mContext, mTaskEntity, mListener); } /** * 获取下载速度 */ - public long getSpeed() { + @Override public long getSpeed() { return mEntity.getSpeed(); } /** * 获取文件大小 */ - public long getFileSize() { + @Override public long getFileSize() { return mEntity.getFileSize(); } /** * 获取当前下载进度 */ - public long getCurrentProgress() { + @Override public long getCurrentProgress() { return mEntity.getCurrentProgress(); } /** * 获取当前下载任务的下载地址 + * + * @see DownloadTask#getKey() */ - public String getDownloadUrl() { + @Deprecated public String getDownloadUrl() { return mEntity.getDownloadUrl(); } + @Override public String getKey() { + return getDownloadUrl(); + } + + /** + * 任务下载状态 + * + * @see DownloadTask#isRunning() + */ + @Deprecated public boolean isDownloading() { + return mUtil.isDownloading(); + } + + @Override public boolean isRunning() { + return isDownloading(); + } + + @Override public DownloadEntity getEntity() { + return mEntity; + } + /** * 开始下载 */ - public void start() { + @Override public void start() { if (mUtil.isDownloading()) { Log.d(TAG, "任务正在下载"); } else { @@ -108,14 +134,14 @@ public class Task { return mTargetName; } - public void setTargetName(String targetName) { + @Override public void setTargetName(String targetName) { this.mTargetName = targetName; } /** * 停止下载 */ - public void stop() { + @Override public void stop() { if (mUtil.isDownloading()) { mUtil.stopDownload(); } else { @@ -132,17 +158,10 @@ public class Task { } } - /** - * 任务下载状态 - */ - public boolean isDownloading() { - return mUtil.isDownloading(); - } - /** * 取消下载 */ - public void cancel() { + @Override public void cancel() { if (mUtil.isDownloading()) { mUtil.cancelDownload(); } else { @@ -161,30 +180,24 @@ public class Task { } } - static class Builder { - DownloadEntity downloadEntity; - Handler outHandler; - Context context; + public static class Builder { + DownloadTaskEntity taskEntity; + Handler outHandler; int threadNum = 3; - String targetName; - IDownloadUtil downloadUtil; + String targetName; - public Builder(Context context, DownloadEntity downloadEntity) { - this("", context, downloadEntity); - } - - Builder(String targetName, Context context, DownloadEntity downloadEntity) { + public Builder(String targetName, DownloadTaskEntity taskEntity) { + CheckUtil.checkDownloadTaskEntity(taskEntity.downloadEntity); this.targetName = targetName; - this.context = context; - this.downloadEntity = downloadEntity; + this.taskEntity = taskEntity; } /** * 设置自定义Handler处理下载状态时间 * - * @param schedulers {@link IDownloadSchedulers} + * @param schedulers {@link ISchedulers} */ - Builder setOutHandler(IDownloadSchedulers schedulers) { + public Builder setOutHandler(ISchedulers schedulers) { this.outHandler = new Handler(schedulers); return this; } @@ -197,10 +210,10 @@ public class Task { return this; } - public Task build() { - Task task = new Task(context, downloadEntity, outHandler); + public DownloadTask build() { + DownloadTask task = new DownloadTask(taskEntity, outHandler); task.setTargetName(targetName); - downloadEntity.save(); + taskEntity.downloadEntity.save(); return task; } } @@ -210,18 +223,18 @@ public class Task { */ private static class DListener extends DownloadListener { WeakReference outHandler; - WeakReference wTask; - Context context; - Intent sendIntent; - long INTERVAL = 1024 * 10; //10k大小的间隔 - long lastLen = 0; //上一次发送长度 - long lastTime = 0; - long INTERVAL_TIME = 1000; //1m更新周期 - boolean isFirst = true; + WeakReference 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; + DownloadTask task; - DListener(Context context, Task task, Handler outHandler) { + DListener(Context context, DownloadTask task, Handler outHandler) { this.context = context; this.outHandler = new WeakReference<>(outHandler); this.wTask = new WeakReference<>(task); @@ -231,6 +244,12 @@ public class Task { sendIntent.putExtra(Aria.ENTITY, downloadEntity); } + @Override public void supportBreakpoint(boolean support) { + super.supportBreakpoint(support); + sendInState2Target(ISchedulers.SUPPORT_BREAK_POINT); + sendIntent(Aria.ACTION_SUPPORT_BREAK_POINT, -1); + } + @Override public void onPre() { super.onPre(); downloadEntity.setState(DownloadEntity.STATE_PRE); @@ -247,14 +266,14 @@ public class Task { @Override public void onResume(long resumeLocation) { super.onResume(resumeLocation); - downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING); + downloadEntity.setState(DownloadEntity.STATE_RUNNING); sendInState2Target(DownloadSchedulers.RESUME); sendIntent(Aria.ACTION_RESUME, resumeLocation); } @Override public void onStart(long startLocation) { super.onStart(startLocation); - downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING); + downloadEntity.setState(DownloadEntity.STATE_RUNNING); sendInState2Target(DownloadSchedulers.START); sendIntent(Aria.ACTION_START, startLocation); } @@ -328,14 +347,13 @@ public class Task { downloadEntity.setDownloadComplete(action.equals(Aria.ACTION_COMPLETE)); downloadEntity.setCurrentProgress(location); downloadEntity.update(); + if (!Configuration.isOpenBreadCast) return; Intent intent = CommonUtil.createIntent(context.getPackageName(), action); intent.putExtra(Aria.ENTITY, downloadEntity); if (location != -1) { intent.putExtra(Aria.CURRENT_LOCATION, location); } - if (Configuration.isOpenBreadCast) { - context.sendBroadcast(intent); - } + context.sendBroadcast(intent); } } } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java new file mode 100644 index 00000000..16cc1d93 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.download; + +import com.arialyy.aria.core.inf.IEntity; +import com.arialyy.aria.core.inf.ITaskEntity; + +/** + * Created by Aria.Lao on 2017/1/23. + * 下载任务实体 + */ +public class DownloadTaskEntity extends ITaskEntity { + + public DownloadEntity downloadEntity; + + public DownloadTaskEntity(DownloadEntity downloadEntity) { + this.downloadEntity = downloadEntity; + } + + @Override public IEntity getEntity() { + return downloadEntity; + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/task/DownloadUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadUtil.java similarity index 72% rename from Aria/src/main/java/com/arialyy/aria/core/task/DownloadUtil.java rename to Aria/src/main/java/com/arialyy/aria/core/download/DownloadUtil.java index 94fe1144..ceabcc6f 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/task/DownloadUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadUtil.java @@ -14,17 +14,16 @@ * limitations under the License. */ -package com.arialyy.aria.core.task; +package com.arialyy.aria.core.download; import android.content.Context; import android.util.Log; import android.util.SparseArray; -import com.arialyy.aria.core.DownloadEntity; import com.arialyy.aria.util.BufferedRandomAccessFile; +import com.arialyy.aria.util.CheckUtil; import com.arialyy.aria.util.CommonUtil; import java.io.File; import java.io.IOException; -import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; import java.util.Properties; @@ -40,7 +39,11 @@ public class DownloadUtil implements IDownloadUtil, Runnable { /** * 线程数 */ - private final int THREAD_NUM; + private int THREAD_NUM; + /** + * 小于1m的文件不启用多线程 + */ + private static final long SUB_LEN = 1024 * 1024; //下载监听 private IDownloadListener mListener; private int mConnectTimeOut = 5000 * 4; //连接超时时间 @@ -49,29 +52,32 @@ public class DownloadUtil implements IDownloadUtil, Runnable { private boolean isSupportBreakpoint = true; private Context mContext; private DownloadEntity mDownloadEntity; + private DownloadTaskEntity mDownloadTaskEntity; private ExecutorService mFixedThreadPool; private File mDownloadFile; //下载的文件 private File mConfigFile;//下载信息配置文件 private SparseArray mTask = new SparseArray<>(); private DownloadStateConstance mConstance; - public DownloadUtil(Context context, DownloadEntity entity, IDownloadListener downloadListener) { + DownloadUtil(Context context, DownloadTaskEntity entity, IDownloadListener downloadListener) { this(context, entity, downloadListener, 3); } - DownloadUtil(Context context, DownloadEntity entity, IDownloadListener downloadListener, + DownloadUtil(Context context, DownloadTaskEntity entity, IDownloadListener downloadListener, int threadNum) { + CheckUtil.checkDownloadTaskEntity(entity.downloadEntity); + mDownloadEntity = entity.downloadEntity; mContext = context.getApplicationContext(); - mDownloadEntity = entity; + mDownloadTaskEntity = entity; mListener = downloadListener; THREAD_NUM = threadNum; mFixedThreadPool = Executors.newFixedThreadPool(Integer.MAX_VALUE); - mConstance = new DownloadStateConstance(THREAD_NUM); + mConstance = new DownloadStateConstance(); init(); } private void init() { - mDownloadFile = new File(mDownloadEntity.getDownloadPath()); + mDownloadFile = new File(mDownloadTaskEntity.downloadEntity.getDownloadPath()); //读取已完成的线程数 mConfigFile = new File( mContext.getFilesDir().getPath() + "/temp/" + mDownloadFile.getName() + ".properties"); @@ -197,7 +203,7 @@ public class DownloadUtil implements IDownloadUtil, Runnable { try { URL url = new URL(mDownloadEntity.getDownloadUrl()); HttpURLConnection conn = ConnectionHelp.handleConnection(url); - conn = ConnectionHelp.setConnectParam(conn); + conn = ConnectionHelp.setConnectParam(mDownloadTaskEntity, conn); conn.setRequestProperty("Range", "bytes=" + 0 + "-"); conn.setConnectTimeout(mConnectTimeOut * 4); conn.connect(); @@ -225,7 +231,7 @@ public class DownloadUtil implements IDownloadUtil, Runnable { handleBreakpoint(conn); } else if (code == HttpURLConnection.HTTP_NOT_FOUND) { Log.w(TAG, "任务【" + mDownloadEntity.getDownloadUrl() + "】下载失败,错误码:404"); - //mListener.onCancel(); + mListener.onCancel(); } else { failDownload("任务【" + mDownloadEntity.getDownloadUrl() + "】下载失败,错误码:" + code); } @@ -243,53 +249,17 @@ public class DownloadUtil implements IDownloadUtil, Runnable { * 处理断点 */ private void handleBreakpoint(HttpURLConnection conn) throws IOException { - //不支持断点只能单线程下载 if (!isSupportBreakpoint) { - ConfigEntity entity = new ConfigEntity(); - long len = conn.getContentLength();; - entity.FILE_SIZE = len; - entity.DOWNLOAD_URL = mDownloadEntity.getDownloadUrl(); - entity.TEMP_FILE = mDownloadFile; - entity.THREAD_ID = 0; - entity.START_LOCATION = 0; - entity.END_LOCATION = entity.FILE_SIZE; - entity.CONFIG_FILE_PATH = mConfigFile.getPath(); - entity.isSupportBreakpoint = isSupportBreakpoint; - SingleThreadTask task = new SingleThreadTask(mConstance, mListener, entity); - mFixedThreadPool.execute(task); - mListener.onPostPre(len); - mListener.onStart(0); + handleNoSupportBreakpointDownload(conn); return; } int fileLength = conn.getContentLength(); - //必须建一个文件 - CommonUtil.createFile(mDownloadFile.getPath()); - //RandomAccessFile file = new RandomAccessFile(mDownloadFile.getPath(), "rwd"); - ////设置文件长度 - //file.setLength(fileLength); - BufferedRandomAccessFile file = - new BufferedRandomAccessFile(mDownloadFile.getPath(), "rwd", 8192); - //设置文件长度 - file.setLength(fileLength); - mListener.onPostPre(fileLength); - //分配每条线程的下载区间 - Properties pro = null; - pro = CommonUtil.loadConfig(mConfigFile); - if (pro.isEmpty()) { - isNewTask = true; - } else { - for (int i = 0; i < THREAD_NUM; i++) { - if (pro.getProperty(mDownloadFile.getName() + "_record_" + i) == null) { - Object state = pro.getProperty(mDownloadFile.getName() + "_state_" + i); - if (state != null && Integer.parseInt(state + "") == 1) { - continue; - } - isNewTask = true; - break; - } - } + if (fileLength < SUB_LEN) { + THREAD_NUM = 1; + mConstance.THREAD_NUM = THREAD_NUM; } + Properties pro = createConfigFile(fileLength); int blockSize = fileLength / THREAD_NUM; int[] recordL = new int[THREAD_NUM]; int rl = 0; @@ -300,19 +270,7 @@ public class DownloadUtil implements IDownloadUtil, Runnable { long startL = i * blockSize, endL = (i + 1) * blockSize; Object state = pro.getProperty(mDownloadFile.getName() + "_state_" + i); if (state != null && Integer.parseInt(state + "") == 1) { //该线程已经完成 - mConstance.CURRENT_LOCATION += endL - startL; - Log.d(TAG, "++++++++++ 线程_" + i + "_已经下载完成 ++++++++++"); - mConstance.COMPLETE_THREAD_NUM++; - mConstance.STOP_NUM++; - mConstance.CANCEL_NUM++; - if (mConstance.isComplete()) { - if (mConfigFile.exists()) { - mConfigFile.delete(); - } - mListener.onComplete(); - mConstance.isDownloading = false; - return; - } + if (resumeRecordLocation(i, startL, endL)) return; continue; } //分配下载位置 @@ -337,18 +295,110 @@ public class DownloadUtil implements IDownloadUtil, Runnable { //如果整个文件的大小不为线程个数的整数倍,则最后一个线程的结束位置即为文件的总长度 endL = fileLength; } - ConfigEntity entity = new ConfigEntity(); - entity.FILE_SIZE = fileLength; - entity.DOWNLOAD_URL = mDownloadEntity.getDownloadUrl(); - entity.TEMP_FILE = mDownloadFile; - entity.THREAD_ID = i; - entity.START_LOCATION = startL; - entity.END_LOCATION = endL; - entity.CONFIG_FILE_PATH = mConfigFile.getPath(); - entity.isSupportBreakpoint = isSupportBreakpoint; - SingleThreadTask task = new SingleThreadTask(mConstance, mListener, entity); - mTask.put(i, task); + addSingleTask(i, startL, endL, fileLength); } + startSingleTask(recordL); + } + + /** + * 处理不支持断点的下载 + */ + private void handleNoSupportBreakpointDownload(HttpURLConnection conn) { + ConfigEntity entity = new ConfigEntity(); + long len = conn.getContentLength(); + entity.FILE_SIZE = len; + entity.DOWNLOAD_URL = mDownloadEntity.getDownloadUrl(); + entity.TEMP_FILE = mDownloadFile; + entity.THREAD_ID = 0; + entity.START_LOCATION = 0; + entity.END_LOCATION = entity.FILE_SIZE; + entity.CONFIG_FILE_PATH = mConfigFile.getPath(); + entity.isSupportBreakpoint = isSupportBreakpoint; + entity.DOWNLOAD_TASK_ENTITY = mDownloadTaskEntity; + THREAD_NUM = 1; + mConstance.THREAD_NUM = THREAD_NUM; + SingleThreadTask task = new SingleThreadTask(mConstance, mListener, entity); + mTask.put(0, task); + mFixedThreadPool.execute(task); + mListener.onPostPre(len); + mListener.onStart(0); + } + + /** + * 创建配置文件 + */ + private Properties createConfigFile(long fileLength) throws IOException { + Properties pro = null; + //必须建一个文件 + CommonUtil.createFile(mDownloadFile.getPath()); + BufferedRandomAccessFile file = + new BufferedRandomAccessFile(new File(mDownloadFile.getPath()), "rwd", 8192); + //设置文件长度 + file.setLength(fileLength); + mListener.onPostPre(fileLength); + //分配每条线程的下载区间 + pro = CommonUtil.loadConfig(mConfigFile); + if (pro.isEmpty()) { + isNewTask = true; + } else { + for (int i = 0; i < THREAD_NUM; i++) { + if (pro.getProperty(mDownloadFile.getName() + "_record_" + i) == null) { + Object state = pro.getProperty(mDownloadFile.getName() + "_state_" + i); + if (state != null && Integer.parseInt(state + "") == 1) { + continue; + } + isNewTask = true; + break; + } + } + } + return pro; + } + + /** + * 恢复记录地址 + * + * @return true 表示下载完成 + */ + private boolean resumeRecordLocation(int i, long startL, long endL) { + mConstance.CURRENT_LOCATION += endL - startL; + Log.d(TAG, "++++++++++ 线程_" + i + "_已经下载完成 ++++++++++"); + mConstance.COMPLETE_THREAD_NUM++; + mConstance.STOP_NUM++; + mConstance.CANCEL_NUM++; + if (mConstance.isComplete()) { + if (mConfigFile.exists()) { + mConfigFile.delete(); + } + mListener.onComplete(); + mConstance.isDownloading = false; + return true; + } + return false; + } + + /** + * 创建单线程任务 + */ + private void addSingleTask(int i, long startL, long endL, long fileLength) { + ConfigEntity entity = new ConfigEntity(); + entity.FILE_SIZE = fileLength; + entity.DOWNLOAD_URL = mDownloadEntity.getDownloadUrl(); + entity.TEMP_FILE = mDownloadFile; + entity.THREAD_ID = i; + entity.START_LOCATION = startL; + entity.END_LOCATION = endL; + entity.CONFIG_FILE_PATH = mConfigFile.getPath(); + entity.isSupportBreakpoint = isSupportBreakpoint; + entity.DOWNLOAD_TASK_ENTITY = mDownloadTaskEntity; + SingleThreadTask task = new SingleThreadTask(mConstance, mListener, entity); + mTask.put(i, task); + } + + /** + * 启动单线程下载任务 + */ + private void startSingleTask(int[] recordL) { if (mConstance.CURRENT_LOCATION > 0) { mListener.onResume(mConstance.CURRENT_LOCATION); } else { @@ -368,13 +418,14 @@ public class DownloadUtil implements IDownloadUtil, Runnable { */ final static class ConfigEntity { //文件大小 - long FILE_SIZE; - String DOWNLOAD_URL; int THREAD_ID; + long FILE_SIZE; long START_LOCATION; long END_LOCATION; File TEMP_FILE; - boolean isSupportBreakpoint = true; + String DOWNLOAD_URL; String CONFIG_FILE_PATH; + DownloadTaskEntity DOWNLOAD_TASK_ENTITY; + boolean isSupportBreakpoint = true; } } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/task/IDownloadListener.java b/Aria/src/main/java/com/arialyy/aria/core/download/IDownloadListener.java similarity index 95% rename from Aria/src/main/java/com/arialyy/aria/core/task/IDownloadListener.java rename to Aria/src/main/java/com/arialyy/aria/core/download/IDownloadListener.java index 037bd808..8d60217c 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/task/IDownloadListener.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/IDownloadListener.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package com.arialyy.aria.core.task; +package com.arialyy.aria.core.download; /** * 下载监听 */ -public interface IDownloadListener { +interface IDownloadListener { /** * 支持断点回调 diff --git a/Aria/src/main/java/com/arialyy/aria/core/task/IDownloadUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/IDownloadUtil.java similarity index 94% rename from Aria/src/main/java/com/arialyy/aria/core/task/IDownloadUtil.java rename to Aria/src/main/java/com/arialyy/aria/core/download/IDownloadUtil.java index 5c4e29f6..45b4cc5e 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/task/IDownloadUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/IDownloadUtil.java @@ -14,14 +14,13 @@ * limitations under the License. */ - -package com.arialyy.aria.core.task; +package com.arialyy.aria.core.download; /** * Created by “AriaLyy@outlook.com” on 2016/10/31. * 抽象的下载接口 */ -public interface IDownloadUtil { +interface IDownloadUtil { /** * 获取当前下载位置 diff --git a/Aria/src/main/java/com/arialyy/aria/core/task/SingleThreadTask.java b/Aria/src/main/java/com/arialyy/aria/core/download/SingleThreadTask.java similarity index 93% rename from Aria/src/main/java/com/arialyy/aria/core/task/SingleThreadTask.java rename to Aria/src/main/java/com/arialyy/aria/core/download/SingleThreadTask.java index d09e1ed7..ee298579 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/task/SingleThreadTask.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/SingleThreadTask.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.arialyy.aria.core.task; +package com.arialyy.aria.core.download; import android.os.Handler; import android.os.Looper; @@ -21,10 +21,10 @@ import android.os.Message; import android.util.Log; import com.arialyy.aria.util.BufferedRandomAccessFile; import com.arialyy.aria.util.CommonUtil; +import com.arialyy.aria.util.Configuration; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; @@ -39,10 +39,12 @@ final class SingleThreadTask implements Runnable { // TODO: 2017/2/22 不能使用1024 否则最大速度不能超过3m private static final int BUF_SIZE = 8192; private DownloadUtil.ConfigEntity mConfigEntity; - private String mConfigFPath; - private long mChildCurrentLocation = 0; - private static final Object LOCK = new Object(); - private IDownloadListener mListener; + private String mConfigFPath; + private long mChildCurrentLocation = 0; + private static final Object LOCK = new Object(); + private int mBufSize = 8192; + //private int mBufSize = 64; + private IDownloadListener mListener; private DownloadStateConstance mConstance; SingleThreadTask(DownloadStateConstance constance, IDownloadListener listener, @@ -53,6 +55,7 @@ final class SingleThreadTask implements Runnable { if (mConfigEntity.isSupportBreakpoint) { mConfigFPath = downloadInfo.CONFIG_FILE_PATH; } + //mBufSize = Configuration.getInstance().getMaxSpeed(); } @Override public void run() { @@ -74,19 +77,18 @@ final class SingleThreadTask implements Runnable { conn.setRequestProperty("Range", "bytes=" + mConfigEntity.START_LOCATION + "-" + mConfigEntity.END_LOCATION); } else { - Log.w(TAG, "该下载不支持断点,即将重新下载"); + Log.w(TAG, "该下载不支持断点"); } - conn = ConnectionHelp.setConnectParam(conn); + conn = ConnectionHelp.setConnectParam(mConfigEntity.DOWNLOAD_TASK_ENTITY, conn); conn.setConnectTimeout(mConstance.CONNECT_TIME_OUT); conn.setReadTimeout(mConstance.READ_TIME_OUT); //设置读取流的等待时间,必须设置该参数 is = conn.getInputStream(); //创建可设置位置的文件 BufferedRandomAccessFile file = - new BufferedRandomAccessFile(mConfigEntity.TEMP_FILE, "rwd", BUF_SIZE); - //设置文件长度 + new BufferedRandomAccessFile(mConfigEntity.TEMP_FILE, "rwd", mBufSize); + //设置每条线程写入文件的位置 file.seek(mConfigEntity.START_LOCATION); - - byte[] buffer = new byte[BUF_SIZE]; + byte[] buffer = new byte[mBufSize]; int len; //当前子线程的下载位置 mChildCurrentLocation = mConfigEntity.START_LOCATION; @@ -95,7 +97,6 @@ final class SingleThreadTask implements Runnable { break; } if (mConstance.isStop) { - Log.i(TAG, "stop"); break; } //把下载数据数据写入文件 diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java new file mode 100644 index 00000000..3a4a78a9 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.inf; + +import android.support.annotation.NonNull; +import com.arialyy.aria.core.AriaManager; +import com.arialyy.aria.core.RequestEnum; +import com.arialyy.aria.core.command.AbsCmd; +import com.arialyy.aria.core.command.CmdFactory; +import com.arialyy.aria.core.download.DownloadEntity; +import com.arialyy.aria.core.upload.UploadEntity; +import com.arialyy.aria.orm.DbEntity; +import com.arialyy.aria.util.CommonUtil; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Created by Aria.Lao on 2017/2/28. + */ +public class AbsTarget { + protected ENTITY entity; + protected TASK_ENTITY taskEntity; + protected String targetName; + + /** + * 获取任务文件大小 + * + * @return -1,没有找到该任务 + */ + public long getFileSize() { + if (entity instanceof DownloadEntity) { + DownloadEntity entity = DbEntity.findData(DownloadEntity.class, "downloadUrl=?", + ((DownloadEntity) this.entity).getDownloadUrl()); + if (entity == null) { + throw new NullPointerException("没有找到该任务"); + } + return entity.getFileSize(); + } else if (entity instanceof UploadEntity) { + UploadEntity entity = DbEntity.findData(UploadEntity.class, "filePath=?", + ((UploadEntity) this.entity).getFilePath()); + if (entity == null) { + throw new NullPointerException("没有找到该任务"); + } + return entity.getFileSize(); + } + return -1; + } + + /** + * 获取当前任务进度,如果任务存在,则返回当前进度 + * + * @return -1,没有找到该任务 + */ + public long getCurrentProgress() { + if (entity instanceof DownloadEntity) { + DownloadEntity entity = DownloadEntity.findData(DownloadEntity.class, "downloadUrl=?", + ((DownloadEntity) this.entity).getDownloadUrl()); + if (entity == null) { + throw new NullPointerException("下载管理器中没有该任务"); + } + return entity.getCurrentProgress(); + } else if (entity instanceof UploadEntity) { + UploadEntity entity = DbEntity.findData(UploadEntity.class, "filePath=?", + ((UploadEntity) this.entity).getFilePath()); + if (entity == null) { + throw new NullPointerException("没有找到该任务"); + } + return entity.getCurrentProgress(); + } + return -1; + } + + /** + * 给url请求添加头部 + * + * @param key 头部key + * @param header 头部value + */ + protected void _addHeader(@NonNull String key, @NonNull String header) { + taskEntity.headers.put(key, header); + } + + /** + * 给url请求添加头部 + */ + protected void _addHeaders(Map headers) { + if (headers != null && headers.size() > 0) { + Set keys = headers.keySet(); + for (String key : keys) { + taskEntity.headers.put(key, headers.get(key)); + } + } + } + + /** + * 设置请求类型 + * + * @param requestEnum {@link RequestEnum} + */ + protected void _setRequestMode(RequestEnum requestEnum) { + taskEntity.requestEnum = requestEnum; + } + + /** + * 添加任务 + */ + public void add() { + AriaManager.getInstance(AriaManager.APP) + .setCmd(CommonUtil.createCmd(targetName, taskEntity, CmdFactory.TASK_CREATE)) + .exe(); + } + + /** + * 开始下载 + */ + public void start() { + List cmds = new ArrayList<>(); + cmds.add(CommonUtil.createCmd(targetName, taskEntity, CmdFactory.TASK_CREATE)); + cmds.add(CommonUtil.createCmd(targetName, taskEntity, CmdFactory.TASK_START)); + AriaManager.getInstance(AriaManager.APP).setCmds(cmds).exe(); + cmds.clear(); + } + + /** + * 停止下载 + */ + protected void pause() { + AriaManager.getInstance(AriaManager.APP) + .setCmd(CommonUtil.createCmd(targetName, taskEntity, CmdFactory.TASK_STOP)) + .exe(); + } + + /** + * 恢复下载 + */ + protected void resume() { + AriaManager.getInstance(AriaManager.APP) + .setCmd(CommonUtil.createCmd(targetName, taskEntity, CmdFactory.TASK_START)) + .exe(); + } + + /** + * 取消下载 + */ + public void cancel() { + AriaManager.getInstance(AriaManager.APP) + .setCmd(CommonUtil.createCmd(targetName, taskEntity, CmdFactory.TASK_CANCEL)) + .exe(); + } + + /** + * 重新下载 + */ + void reStart() { + cancel(); + start(); + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/ICmd.java b/Aria/src/main/java/com/arialyy/aria/core/inf/ICmd.java new file mode 100644 index 00000000..8fd5fa9b --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/ICmd.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.inf; + +/** + * Created by Aria.Lao on 2017/2/9. + */ + +public interface ICmd { + /** + * 执行命令 + */ + public abstract void executeCmd(); +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/IEntity.java b/Aria/src/main/java/com/arialyy/aria/core/inf/IEntity.java new file mode 100644 index 00000000..992d21a5 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/IEntity.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.inf; + +import com.arialyy.aria.orm.Ignore; + +/** + * Created by Aria.Lao on 2017/2/23. + */ + +public interface IEntity { + /** + * 其它状态 + */ + @Ignore public static final int STATE_OTHER = -1; + /** + * 失败状态 + */ + @Ignore public static final int STATE_FAIL = 0; + /** + * 完成状态 + */ + @Ignore public static final int STATE_COMPLETE = 1; + /** + * 停止状态 + */ + @Ignore public static final int STATE_STOP = 2; + /** + * 未开始状态 + */ + @Ignore public static final int STATE_WAIT = 3; + /** + * 下载中 + */ + @Ignore public static final int STATE_RUNNING = 4; + /** + * 预处理 + */ + @Ignore public static final int STATE_PRE = 5; + /** + * 预处理完成 + */ + @Ignore public static final int STATE_POST_PRE = 6; + /** + * 取消下载 + */ + @Ignore public static final int STATE_CANCEL = 7; + + public int getState(); +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/IReceiver.java b/Aria/src/main/java/com/arialyy/aria/core/inf/IReceiver.java new file mode 100644 index 00000000..28c5de6f --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/IReceiver.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.inf; + +import java.util.List; + +/** + * Created by Aria.Lao on 2017/2/6. + */ +public interface IReceiver { + /** + * Receiver 销毁 + */ + public void destroy(); + + /** + * 移除事件回调 + */ + public void removeSchedulerListener(); + + /** + * 停止所有任务 + */ + public void stopAllTask(); + + /** + * 删除所有任务 + */ + public void removeAllTask(); + + /** + * 任务是否存在 + * + * @param key 下载时为下载路径,上传时为文件路径 + */ + public boolean taskExists(String key); + + /** + * 获取任务列表 + */ + public List getTaskList(); +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/ITask.java b/Aria/src/main/java/com/arialyy/aria/core/inf/ITask.java new file mode 100644 index 00000000..9e464224 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/ITask.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.inf; + +/** + * Created by Aria.Lao on 2017/2/13. + */ + +public interface ITask { + + /** + * 唯一标识符,DownloadTask 为下载地址,UploadTask 为文件路径 + */ + public String getKey(); + + /** + * 是否真正执行 + * + * @return true,正在执行; + */ + public boolean isRunning(); + + /** + * 获取工具实体 + */ + public IEntity getEntity(); + + public void start(); + + public void stop(); + + public void cancel(); + + public long getSpeed(); + + public long getFileSize(); + + public long getCurrentProgress(); + + public void setTargetName(String targetName); +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/ITaskEntity.java b/Aria/src/main/java/com/arialyy/aria/core/inf/ITaskEntity.java new file mode 100644 index 00000000..e9f621a2 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/ITaskEntity.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.inf; + +import com.arialyy.aria.core.RequestEnum; +import java.util.HashMap; +import java.util.Map; + +/** + * Created by Aria.Lao on 2017/2/23. + */ + +public abstract class ITaskEntity { + /** + * http 请求头 + */ + public Map headers = new HashMap<>(); + + /** + * 网络请求类型 + */ + public RequestEnum requestEnum = RequestEnum.GET; + + public abstract IEntity getEntity(); +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/IDownloader.java b/Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java similarity index 55% rename from Aria/src/main/java/com/arialyy/aria/core/queue/IDownloader.java rename to Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java index 601e54ed..a61b12fe 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/queue/IDownloader.java +++ b/Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java @@ -14,41 +14,19 @@ * limitations under the License. */ - package com.arialyy.aria.core.queue; -import com.arialyy.aria.core.task.Task; +import com.arialyy.aria.core.inf.IEntity; +import com.arialyy.aria.core.inf.ITask; +import com.arialyy.aria.core.inf.ITaskEntity; +import com.arialyy.aria.core.queue.pool.CachePool; +import com.arialyy.aria.core.queue.pool.ExecutePool; /** - * Created by lyy on 2016/8/16. - * 下载功能接口 + * Created by Aria.Lao on 2017/2/23. */ -public interface IDownloader { - /** - * 开始任务 - * - * @param task {@link Task} - */ - public void startTask(Task task); - - /** - * 停止任务 - * - * @param task {@link Task} - */ - public void stopTask(Task task); - - /** - * 取消任务 - * - * @param task {@link Task} - */ - public void cancelTask(Task task); - - /** - * 重试下载 - * - * @param task {@link Task} - */ - public void reTryStart(Task task); -} \ No newline at end of file +abstract class AbsTaskQueue + implements ITaskQueue { + CachePool mCachePool = new CachePool<>(); + ExecutePool mExecutePool = new ExecutePool<>(); +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/DownloadTaskQueue.java b/Aria/src/main/java/com/arialyy/aria/core/queue/DownloadTaskQueue.java index de033a65..7288fde6 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/queue/DownloadTaskQueue.java +++ b/Aria/src/main/java/com/arialyy/aria/core/queue/DownloadTaskQueue.java @@ -16,35 +16,37 @@ package com.arialyy.aria.core.queue; -import android.content.Context; import android.text.TextUtils; import android.util.Log; -import com.arialyy.aria.core.DownloadEntity; +import com.arialyy.aria.core.download.DownloadEntity; +import com.arialyy.aria.core.download.DownloadTask; +import com.arialyy.aria.core.download.DownloadTaskEntity; +import com.arialyy.aria.core.inf.IEntity; import com.arialyy.aria.core.queue.pool.CachePool; import com.arialyy.aria.core.queue.pool.ExecutePool; 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. * 下载任务队列 */ -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 DownloadTaskQueue() { +public class DownloadTaskQueue + extends AbsTaskQueue { + private static final String TAG = "DownloadTaskQueue"; + private static volatile DownloadTaskQueue INSTANCE = null; + private static final Object LOCK = new Object(); + + public static DownloadTaskQueue getInstance() { + if (INSTANCE == null) { + synchronized (LOCK) { + INSTANCE = new DownloadTaskQueue(); + } + } + return INSTANCE; } - private DownloadTaskQueue(Context context) { - super(); - mContext = context; + private DownloadTaskQueue() { } /** @@ -79,7 +81,7 @@ public class DownloadTaskQueue implements ITaskQueue { return mCachePool.size(); } - @Override public void startTask(Task task) { + @Override public void startTask(DownloadTask task) { if (mExecutePool.putTask(task)) { mCachePool.removeTask(task); task.getDownloadEntity().setFailNum(0); @@ -87,8 +89,8 @@ public class DownloadTaskQueue implements ITaskQueue { } } - @Override public void stopTask(Task task) { - if (!task.isDownloading()) Log.w(TAG, "停止任务失败,【任务已经停止】"); + @Override public void stopTask(DownloadTask task) { + if (!task.isRunning()) Log.w(TAG, "停止任务失败,【任务已经停止】"); if (mExecutePool.removeTask(task)) { task.stop(); } else { @@ -97,16 +99,16 @@ public class DownloadTaskQueue implements ITaskQueue { } } - @Override public void cancelTask(Task task) { + @Override public void cancelTask(DownloadTask task) { task.cancel(); } - @Override public void reTryStart(Task task) { + @Override public void reTryStart(DownloadTask task) { if (task == null) { Log.w(TAG, "重试下载失败,task 为null"); return; } - if (!task.isDownloading()) { + if (!task.isRunning()) { task.start(); } else { Log.w(TAG, "任务没有完全停止,重试下载失败"); @@ -128,7 +130,7 @@ public class DownloadTaskQueue implements ITaskQueue { //设置的任务数小于配置任务数 if (diff <= -1 && mExecutePool.size() >= size) { for (int i = 0, len = Math.abs(diff); i < len; i++) { - Task eTask = mExecutePool.pollTask(); + DownloadTask eTask = mExecutePool.pollTask(); if (eTask != null) { stopTask(eTask); } @@ -137,30 +139,28 @@ public class DownloadTaskQueue implements ITaskQueue { 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) { + DownloadTask nextTask = getNextTask(); + if (nextTask != null && nextTask.getDownloadEntity().getState() == IEntity.STATE_WAIT) { startTask(nextTask); } } } } - @Override public Task createTask(String target, DownloadEntity entity) { - Task task; - if (TextUtils.isEmpty(target)) { - task = - TaskFactory.getInstance().createTask(mContext, entity, DownloadSchedulers.getInstance()); + @Override public DownloadTask createTask(String target, DownloadTaskEntity entity) { + DownloadTask task = null; + if (!TextUtils.isEmpty(target)) { + task = (DownloadTask) TaskFactory.getInstance() + .createTask(target, entity, DownloadSchedulers.getInstance()); + mCachePool.putTask(task); } else { - task = TaskFactory.getInstance() - .createTask(target, mContext, entity, DownloadSchedulers.getInstance()); + Log.e(TAG, "target name 为 null是!!"); } - mCachePool.putTask(task); return task; } - @Override public Task getTask(DownloadEntity entity) { - Task task = mExecutePool.getTask(entity.getDownloadUrl()); + @Override public DownloadTask getTask(DownloadEntity entity) { + DownloadTask task = mExecutePool.getTask(entity.getDownloadUrl()); if (task == null) { task = mCachePool.getTask(entity.getDownloadUrl()); } @@ -168,7 +168,7 @@ public class DownloadTaskQueue implements ITaskQueue { } @Override public void removeTask(DownloadEntity entity) { - Task task = mExecutePool.getTask(entity.getDownloadUrl()); + DownloadTask task = mExecutePool.getTask(entity.getDownloadUrl()); if (task != null) { Log.d(TAG, "从执行池删除任务,删除" + (mExecutePool.removeTask(task) ? "成功" : "失败")); } @@ -178,20 +178,7 @@ public class DownloadTaskQueue implements ITaskQueue { } } - @Override public Task getNextTask() { + @Override public DownloadTask getNextTask() { return mCachePool.pollTask(); } - - public static class Builder { - Context context; - - public Builder(Context context) { - this.context = context.getApplicationContext(); - } - - public DownloadTaskQueue build() { - DownloadTaskQueue queue = new DownloadTaskQueue(context); - return queue; - } - } } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/ITaskQueue.java b/Aria/src/main/java/com/arialyy/aria/core/queue/ITaskQueue.java index 68576119..0b9b18af 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/queue/ITaskQueue.java +++ b/Aria/src/main/java/com/arialyy/aria/core/queue/ITaskQueue.java @@ -16,20 +16,49 @@ package com.arialyy.aria.core.queue; -import com.arialyy.aria.core.DownloadEntity; -import com.arialyy.aria.core.scheduler.IDownloadSchedulers; -import com.arialyy.aria.core.task.Task; +import com.arialyy.aria.core.download.DownloadEntity; +import com.arialyy.aria.core.download.DownloadTaskEntity; +import com.arialyy.aria.core.download.DownloadTask; +import com.arialyy.aria.core.inf.IEntity; +import com.arialyy.aria.core.inf.ITask; +import com.arialyy.aria.core.inf.ITaskEntity; +import com.arialyy.aria.core.upload.UploadEntity; +import com.arialyy.aria.core.upload.UploadTask; +import com.arialyy.aria.core.upload.UploadTaskEntity; /** * Created by lyy on 2016/8/16. * 任务功能接口 */ -public interface ITaskQueue extends IDownloader { +public interface ITaskQueue { - ///** - // * 获取调度器 - // */ - //public IDownloadSchedulers getDownloadSchedulers(); + /** + * 开始任务 + * + * @param task {@link DownloadTask}、{@link UploadTask} + */ + public void startTask(TASK task); + + /** + * 停止任务 + * + * @param task {@link DownloadTask}、{@link UploadTask} + */ + public void stopTask(TASK task); + + /** + * 取消任务 + * + * @param task {@link DownloadTask}、{@link UploadTask} + */ + public void cancelTask(TASK task); + + /** + * 重试下载 + * + * @param task {@link DownloadTask}、{@link UploadTask} + */ + public void reTryStart(TASK task); /** * 任务池队列大小 @@ -44,33 +73,33 @@ public interface ITaskQueue extends IDownloader { public void setDownloadNum(int downloadNum); /** - * 创建一个新的下载任务,创建时只是将新任务存储到缓存池 + * 创建一个新的任务,创建时只是将新任务存储到缓存池 * - * @param entity 下载实体{@link DownloadEntity} + * @param entity 任务实体{@link DownloadTaskEntity}、{@link UploadTaskEntity} * @param targetName 生成该任务的对象 - * @return {@link Task} + * @return {@link DownloadTask}、{@link UploadTask} */ - public Task createTask(String targetName, DownloadEntity entity); + public TASK createTask(String targetName, TASK_ENTITY entity); /** - * 通过下载链接从缓存池或任务池搜索下载任务,如果缓存池或任务池都没有任务,则创建新任务 + * 通过工作实体缓存池或任务池搜索下载任务,如果缓存池或任务池都没有任务,则创建新任务 * - * @param entity 下载实体{@link DownloadEntity} - * @return {@link Task} + * @param entity 工作实体{@link DownloadEntity}、{@link UploadEntity} + * @return {@link DownloadTask}、{@link UploadTask} */ - public Task getTask(DownloadEntity entity); + public TASK getTask(ENTITY entity); /** - * 通过下载链接删除任务 + * 通过工作实体删除任务 * - * @param entity 下载实体{@link DownloadEntity} + * @param entity 工作实体{@link DownloadEntity}、{@link UploadEntity} */ - public void removeTask(DownloadEntity entity); + public void removeTask(ENTITY entity); /** * 获取缓存池的下一个任务 * * @return 下载任务 or null */ - public Task getNextTask(); + public TASK getNextTask(); } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/TaskFactory.java b/Aria/src/main/java/com/arialyy/aria/core/queue/TaskFactory.java new file mode 100644 index 00000000..34b6f043 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/queue/TaskFactory.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.arialyy.aria.core.queue; + +import com.arialyy.aria.core.download.DownloadTask; +import com.arialyy.aria.core.download.DownloadTaskEntity; +import com.arialyy.aria.core.inf.ITask; +import com.arialyy.aria.core.inf.ITaskEntity; +import com.arialyy.aria.core.scheduler.DownloadSchedulers; +import com.arialyy.aria.core.scheduler.ISchedulers; +import com.arialyy.aria.core.upload.UploadTask; +import com.arialyy.aria.core.upload.UploadTaskEntity; + +/** + * Created by lyy on 2016/8/18. + * 任务工厂 + */ +public class TaskFactory { + private static final String TAG = "TaskFactory"; + + private static final Object LOCK = new Object(); + private static volatile TaskFactory INSTANCE = null; + + private TaskFactory() { + + } + + public static TaskFactory getInstance() { + if (INSTANCE == null) { + synchronized (LOCK) { + INSTANCE = new TaskFactory(); + } + } + return INSTANCE; + } + + /** + * 创建任务 + * + * @param entity 下载实体 + * @param schedulers 对应的任务调度器 + * @param {@link DownloadTaskEntity}、{@link UploadTaskEntity} + * @param {@link DownloadSchedulers} + * @return {@link DownloadTask}、{@link UploadTask} + */ + ITask createTask(String targetName, + ENTITY entity, SCHEDULER schedulers) { + if (entity instanceof DownloadTaskEntity) { + return createDownloadTask(targetName, (DownloadTaskEntity) entity, schedulers); + } else if (entity instanceof UploadTaskEntity) { + return createUploadTask(targetName, (UploadTaskEntity) entity, schedulers); + } + return null; + } + + /** + * @param entity 上传任务实体{@link UploadTaskEntity} + * @param schedulers {@link ISchedulers} + */ + private UploadTask createUploadTask(String targetName, UploadTaskEntity entity, + ISchedulers schedulers) { + UploadTask.Builder builder = new UploadTask.Builder(); + builder.setTargetName(targetName); + builder.setUploadTaskEntity(entity); + builder.setOutHandler(schedulers); + return builder.build(); + } + + /** + * @param entity 下载任务实体{@link DownloadTaskEntity} + * @param schedulers {@link ISchedulers} + */ + private DownloadTask createDownloadTask(String targetName, DownloadTaskEntity entity, + ISchedulers schedulers) { + DownloadTask.Builder builder = new DownloadTask.Builder(targetName, entity); + builder.setOutHandler(schedulers); + return builder.build(); + } +} \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/UploadTaskQueue.java b/Aria/src/main/java/com/arialyy/aria/core/queue/UploadTaskQueue.java new file mode 100644 index 00000000..9b7c061a --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/queue/UploadTaskQueue.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.arialyy.aria.core.queue; + +import android.text.TextUtils; +import android.util.Log; +import com.arialyy.aria.core.scheduler.UploadSchedulers; +import com.arialyy.aria.core.upload.UploadEntity; +import com.arialyy.aria.core.upload.UploadTask; +import com.arialyy.aria.core.upload.UploadTaskEntity; + +/** + * Created by Aria.Lao on 2017/2/27. + * 上传任务队列 + */ +public class UploadTaskQueue extends AbsTaskQueue { + private static final String TAG = "UploadTaskQueue"; + private static volatile UploadTaskQueue INSTANCE = null; + private static final Object LOCK = new Object(); + + public static UploadTaskQueue getInstance() { + if (INSTANCE == null) { + synchronized (LOCK) { + INSTANCE = new UploadTaskQueue(); + } + } + return INSTANCE; + } + + @Override public void startTask(UploadTask task) { + if (mExecutePool.putTask(task)) { + mCachePool.removeTask(task); + //task.getEntity().setFailNum(0); + task.start(); + } + } + + @Override public void stopTask(UploadTask task) { + if (!task.isRunning()) Log.w(TAG, "停止任务失败,【任务已经停止】"); + if (mExecutePool.removeTask(task)) { + task.stop(); + } else { + task.stop(); + Log.w(TAG, "停止任务失败,【任务已经停止】"); + } + } + + @Override public void cancelTask(UploadTask task) { + task.cancel(); + } + + @Override public void reTryStart(UploadTask task) { + if (task == null) { + Log.w(TAG, "重试下载失败,task 为null"); + return; + } + if (!task.isRunning()) { + task.start(); + } else { + Log.w(TAG, "任务没有完全停止,重试下载失败"); + } + } + + @Override public int size() { + return mExecutePool.size(); + } + + @Override public void setDownloadNum(int downloadNum) { + + } + + @Override public UploadTask createTask(String targetName, UploadTaskEntity entity) { + UploadTask task = null; + if (!TextUtils.isEmpty(targetName)) { + task = (UploadTask) TaskFactory.getInstance() + .createTask(targetName, entity, UploadSchedulers.getInstance()); + mCachePool.putTask(task); + } else { + Log.e(TAG, "target name 为 null是!!"); + } + return task; + } + + @Override public UploadTask getTask(UploadEntity entity) { + UploadTask task = mExecutePool.getTask(entity.getFilePath()); + if (task == null) { + task = mCachePool.getTask(entity.getFilePath()); + } + return task; + } + + @Override public void removeTask(UploadEntity entity) { + UploadTask task = mExecutePool.getTask(entity.getFilePath()); + if (task != null) { + Log.d(TAG, "从执行池删除任务,删除" + (mExecutePool.removeTask(task) ? "成功" : "失败")); + } + task = mCachePool.getTask(entity.getFilePath()); + if (task != null) { + Log.d(TAG, "从缓存池删除任务,删除" + (mCachePool.removeTask(task) ? "成功" : "失败")); + } + } + + @Override public UploadTask getNextTask() { + return mCachePool.pollTask(); + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/pool/CachePool.java b/Aria/src/main/java/com/arialyy/aria/core/queue/pool/CachePool.java index 8f710491..aa2f37cf 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/queue/pool/CachePool.java +++ b/Aria/src/main/java/com/arialyy/aria/core/queue/pool/CachePool.java @@ -18,9 +18,8 @@ package com.arialyy.aria.core.queue.pool; import android.text.TextUtils; import android.util.Log; -import com.arialyy.aria.core.queue.IPool; +import com.arialyy.aria.core.inf.ITask; import com.arialyy.aria.util.CommonUtil; -import com.arialyy.aria.core.task.Task; import java.util.HashMap; import java.util.Map; import java.util.concurrent.LinkedBlockingQueue; @@ -30,36 +29,26 @@ import java.util.concurrent.TimeUnit; * Created by lyy on 2016/8/14. * 任务缓存池,所有下载任务最先缓存在这个池中 */ -public class CachePool implements IPool { - private static final String TAG = "CachePool"; - 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 mCacheArray; - private LinkedBlockingQueue mCacheQueue; +public class CachePool implements IPool { + private static final String TAG = "CachePool"; + private static final Object LOCK = new Object(); + private static final int MAX_NUM = Integer.MAX_VALUE; //最大下载任务数 + private static final long TIME_OUT = 1000; + private Map mCacheArray; + private LinkedBlockingQueue mCacheQueue; - private CachePool() { + public CachePool() { mCacheQueue = new LinkedBlockingQueue<>(MAX_NUM); mCacheArray = new HashMap<>(); } - public static CachePool getInstance() { - if (INSTANCE == null) { - synchronized (LOCK) { - INSTANCE = new CachePool(); - } - } - return INSTANCE; - } - - @Override public boolean putTask(Task task) { + @Override public boolean putTask(TASK task) { synchronized (LOCK) { if (task == null) { Log.e(TAG, "下载任务不能为空!!"); return false; } - String url = task.getDownloadEntity().getDownloadUrl(); + String url = task.getKey(); if (mCacheQueue.contains(task)) { Log.w(TAG, "队列中已经包含了该任务,任务下载链接【" + url + "】"); return false; @@ -74,13 +63,13 @@ public class CachePool implements IPool { } } - @Override public Task pollTask() { + @Override public TASK pollTask() { synchronized (LOCK) { try { - Task task = null; + TASK task = null; task = mCacheQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS); if (task != null) { - String url = task.getDownloadEntity().getDownloadUrl(); + String url = task.getKey(); mCacheArray.remove(CommonUtil.keyToHashKey(url)); } return task; @@ -91,7 +80,7 @@ public class CachePool implements IPool { return null; } - @Override public Task getTask(String downloadUrl) { + @Override public TASK getTask(String downloadUrl) { synchronized (LOCK) { if (TextUtils.isEmpty(downloadUrl)) { Log.e(TAG, "请传入有效的下载链接"); @@ -102,13 +91,13 @@ public class CachePool implements IPool { } } - @Override public boolean removeTask(Task task) { + @Override public boolean removeTask(TASK task) { synchronized (LOCK) { if (task == null) { Log.e(TAG, "任务不能为空"); return false; } else { - String key = CommonUtil.keyToHashKey(task.getDownloadEntity().getDownloadUrl()); + String key = CommonUtil.keyToHashKey(task.getKey()); mCacheArray.remove(key); return mCacheQueue.remove(task); } @@ -121,8 +110,8 @@ public class CachePool implements IPool { Log.e(TAG, "请传入有效的下载链接"); return false; } - String key = CommonUtil.keyToHashKey(downloadUrl); - Task task = mCacheArray.get(key); + String key = CommonUtil.keyToHashKey(downloadUrl); + TASK task = mCacheArray.get(key); mCacheArray.remove(key); return mCacheQueue.remove(task); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/pool/ExecutePool.java b/Aria/src/main/java/com/arialyy/aria/core/queue/pool/ExecutePool.java index a3a1c911..450018f6 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/queue/pool/ExecutePool.java +++ b/Aria/src/main/java/com/arialyy/aria/core/queue/pool/ExecutePool.java @@ -18,9 +18,8 @@ package com.arialyy.aria.core.queue.pool; import android.text.TextUtils; import android.util.Log; +import com.arialyy.aria.core.inf.ITask; import com.arialyy.aria.util.CommonUtil; -import com.arialyy.aria.core.queue.IPool; -import com.arialyy.aria.core.task.Task; import com.arialyy.aria.util.Configuration; import java.util.HashMap; import java.util.Map; @@ -31,39 +30,29 @@ import java.util.concurrent.TimeUnit; * Created by lyy on 2016/8/15. * 任务执行池,所有当前下载任务都该任务池中,默认下载大小为2 */ -public class ExecutePool implements IPool { - private static final String TAG = "ExecutePool"; - private static final Object LOCK = new Object(); - private static final long TIME_OUT = 1000; - private static volatile ExecutePool INSTANCE = null; - private ArrayBlockingQueue mExecuteQueue; - private Map mExecuteArray; - private int mSize; +public class ExecutePool implements IPool { + private static final String TAG = "ExecutePool"; + private static final Object LOCK = new Object(); + private static final long TIME_OUT = 1000; + private ArrayBlockingQueue mExecuteQueue; + private Map mExecuteArray; + private int mSize; - private ExecutePool() { + public ExecutePool() { mSize = Configuration.getInstance().getDownloadNum(); mExecuteQueue = new ArrayBlockingQueue<>(mSize); mExecuteArray = new HashMap<>(); } - public static ExecutePool getInstance() { - if (INSTANCE == null) { - synchronized (LOCK) { - INSTANCE = new ExecutePool(); - } - } - return INSTANCE; - } - - @Override public boolean putTask(Task task) { + @Override public boolean putTask(TASK task) { synchronized (LOCK) { if (task == null) { - Log.e(TAG, "下载任务不能为空!!"); + Log.e(TAG, "任务不能为空!!"); return false; } - String url = task.getDownloadEntity().getDownloadUrl(); + String url = task.getKey(); if (mExecuteQueue.contains(task)) { - Log.e(TAG, "队列中已经包含了该任务,任务下载链接【" + url + "】"); + Log.e(TAG, "队列中已经包含了该任务,任务key【" + url + "】"); return false; } else { if (mExecuteQueue.size() >= mSize) { @@ -85,8 +74,8 @@ public class ExecutePool implements IPool { */ public void setDownloadNum(int downloadNum) { try { - ArrayBlockingQueue temp = new ArrayBlockingQueue<>(downloadNum); - Task task; + ArrayBlockingQueue temp = new ArrayBlockingQueue<>(downloadNum); + TASK task; while ((task = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS)) != null) { temp.offer(task); } @@ -103,12 +92,11 @@ public class ExecutePool implements IPool { * * @param newTask 新下载任务 */ - private boolean putNewTask(Task newTask) { - String url = newTask.getDownloadEntity().getDownloadUrl(); - boolean s = mExecuteQueue.offer(newTask); + private boolean putNewTask(TASK newTask) { + String url = newTask.getKey(); + boolean s = mExecuteQueue.offer(newTask); Log.w(TAG, "任务添加" + (s ? "成功" : "失败,【" + url + "】")); if (s) { - newTask.start(); mExecuteArray.put(CommonUtil.keyToHashKey(url), newTask); } return s; @@ -119,14 +107,13 @@ public class ExecutePool implements IPool { */ private boolean pollFirstTask() { try { - Task oldTask = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS); + TASK oldTask = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS); if (oldTask == null) { Log.e(TAG, "移除任务失败"); return false; } oldTask.stop(); - // wait(200); - String key = CommonUtil.keyToHashKey(oldTask.getDownloadEntity().getDownloadUrl()); + String key = CommonUtil.keyToHashKey(oldTask.getKey()); mExecuteArray.remove(key); } catch (InterruptedException e) { e.printStackTrace(); @@ -135,13 +122,13 @@ public class ExecutePool implements IPool { return true; } - @Override public Task pollTask() { + @Override public TASK pollTask() { synchronized (LOCK) { try { - Task task = null; + TASK task = null; task = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS); if (task != null) { - String url = task.getDownloadEntity().getDownloadUrl(); + String url = task.getKey(); mExecuteArray.remove(CommonUtil.keyToHashKey(url)); } return task; @@ -152,10 +139,10 @@ public class ExecutePool implements IPool { } } - @Override public Task getTask(String downloadUrl) { + @Override public TASK getTask(String downloadUrl) { synchronized (LOCK) { if (TextUtils.isEmpty(downloadUrl)) { - Log.e(TAG, "请传入有效的下载链接"); + Log.e(TAG, "请传入有效的任务key"); return null; } String key = CommonUtil.keyToHashKey(downloadUrl); @@ -163,13 +150,13 @@ public class ExecutePool implements IPool { } } - @Override public boolean removeTask(Task task) { + @Override public boolean removeTask(TASK task) { synchronized (LOCK) { if (task == null) { Log.e(TAG, "任务不能为空"); return false; } else { - String key = CommonUtil.keyToHashKey(task.getDownloadEntity().getDownloadUrl()); + String key = CommonUtil.keyToHashKey(task.getKey()); mExecuteArray.remove(key); return mExecuteQueue.remove(task); } @@ -179,11 +166,11 @@ public class ExecutePool implements IPool { @Override public boolean removeTask(String downloadUrl) { synchronized (LOCK) { if (TextUtils.isEmpty(downloadUrl)) { - Log.e(TAG, "请传入有效的下载链接"); + Log.e(TAG, "请传入有效的任务key"); return false; } - String key = CommonUtil.keyToHashKey(downloadUrl); - Task task = mExecuteArray.get(key); + String key = CommonUtil.keyToHashKey(downloadUrl); + TASK task = mExecuteArray.get(key); mExecuteArray.remove(key); return mExecuteQueue.remove(task); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/IPool.java b/Aria/src/main/java/com/arialyy/aria/core/queue/pool/IPool.java similarity index 84% rename from Aria/src/main/java/com/arialyy/aria/core/queue/IPool.java rename to Aria/src/main/java/com/arialyy/aria/core/queue/pool/IPool.java index f41258f4..53378e9c 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/queue/IPool.java +++ b/Aria/src/main/java/com/arialyy/aria/core/queue/pool/IPool.java @@ -14,27 +14,26 @@ * limitations under the License. */ +package com.arialyy.aria.core.queue.pool; -package com.arialyy.aria.core.queue; - -import com.arialyy.aria.core.task.Task; +import com.arialyy.aria.core.inf.ITask; /** * Created by lyy on 2016/8/14. * 任务池 */ -public interface IPool { +public interface IPool { /** * 将下载任务添加到任务池中 */ - public boolean putTask(Task task); + public boolean putTask(T task); /** * 按照队列原则取出下载任务 * * @return 返回null或者下载任务 */ - public Task pollTask(); + public T pollTask(); /** * 通过下载链接获取下载任务,当任务不为空时,队列将删除该下载任务 @@ -42,7 +41,7 @@ public interface IPool { * @param downloadUrl 下载链接 * @return 返回null或者下载任务 */ - public Task getTask(String downloadUrl); + public T getTask(String downloadUrl); /** * 删除任务池中的下载任务 @@ -50,7 +49,7 @@ public interface IPool { * @param task 下载任务 * @return true:移除成功 */ - public boolean removeTask(Task task); + public boolean removeTask(T task); /** * 通过下载链接移除下载任务 diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadSchedulers.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadSchedulers.java index 0e062e03..2ef63d82 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadSchedulers.java +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/DownloadSchedulers.java @@ -18,12 +18,10 @@ package com.arialyy.aria.core.scheduler; import android.os.CountDownTimer; 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.DownloadTaskQueue; +import com.arialyy.aria.core.download.DownloadEntity; +import com.arialyy.aria.core.download.DownloadTask; import com.arialyy.aria.util.Configuration; import java.util.Iterator; import java.util.Map; @@ -34,83 +32,50 @@ import java.util.concurrent.ConcurrentHashMap; * Created by lyy on 2016/8/16. * 任务下载器,提供抽象的方法供具体的实现类操作 */ -public class DownloadSchedulers implements IDownloadSchedulers { - /** - * 任务预加载 - */ - public static final int PRE = 0; - /** - * 任务开始 - */ - public static final int START = 1; - /** - * 任务停止 - */ - public static final int STOP = 2; - /** - * 任务失败 - */ - public static final int FAIL = 3; - /** - * 任务取消 - */ - public static final int CANCEL = 4; - /** - * 任务完成 - */ - public static final int COMPLETE = 5; - /** - * 下载中 - */ - public static final int RUNNING = 6; - /** - * 恢复下载 - */ - public static final int RESUME = 7; - private static final String TAG = "DownloadSchedulers"; - private static final Object LOCK = new Object(); +public class DownloadSchedulers implements ISchedulers { + + private static final String TAG = "DownloadSchedulers"; + private static final Object LOCK = new Object(); private static volatile DownloadSchedulers INSTANCE = null; /** * 下载器任务监听 */ - Map mSchedulerListeners = new ConcurrentHashMap<>(); - DownloadManager mManager = DownloadManager.getInstance(); - ITaskQueue mQueue; + private Map> mSchedulerListeners = + new ConcurrentHashMap<>(); + private DownloadTaskQueue mQueue; private DownloadSchedulers() { - mQueue = mManager.getTaskQueue(); + mQueue = DownloadTaskQueue.getInstance(); } public static DownloadSchedulers getInstance() { if (INSTANCE == null) { synchronized (LOCK) { - //INSTANCE = new DownloadSchedulers(queue); INSTANCE = new DownloadSchedulers(); } } return INSTANCE; } - @Override - public void addSchedulerListener(String targetName, OnSchedulerListener schedulerListener) { - mSchedulerListeners.put(targetName, schedulerListener); + @Override public void addSchedulerListener(String targetName, + ISchedulerListener schedulerListener) { + mSchedulerListeners.put(targetName, + (IDownloadSchedulerListener) schedulerListener); } - @Override - public void removeSchedulerListener(String targetName, OnSchedulerListener schedulerListener) { - //OnSchedulerListener listener = mSchedulerListeners.get(target.getClass().getName()); - //mSchedulerListeners.remove(listener); + @Override public void removeSchedulerListener(String targetName, + ISchedulerListener schedulerListener) { //该内存溢出解决方案:http://stackoverflow.com/questions/14585829/how-safe-is-to-delete-already-removed-concurrenthashmap-element - for (Iterator> iter = + for (Iterator>> iter = mSchedulerListeners.entrySet().iterator(); iter.hasNext(); ) { - Map.Entry entry = iter.next(); + Map.Entry> entry = iter.next(); if (entry.getKey().equals(targetName)) iter.remove(); } } @Override public boolean handleMessage(Message msg) { - Task task = (Task) msg.obj; + DownloadTask task = (DownloadTask) msg.obj; if (task == null) { Log.e(TAG, "请传入下载任务"); return true; @@ -122,12 +87,12 @@ public class DownloadSchedulers implements IDownloadSchedulers { case CANCEL: mQueue.removeTask(entity); if (mQueue.size() < Configuration.getInstance().getDownloadNum()) { - startNextTask(entity); + startNextTask(); } break; case COMPLETE: mQueue.removeTask(entity); - startNextTask(entity); + startNextTask(); break; case FAIL: handleFailTask(task); @@ -141,7 +106,7 @@ public class DownloadSchedulers implements IDownloadSchedulers { * * @param state 状态 */ - private void callback(int state, Task task) { + private void callback(int state, DownloadTask task) { if (mSchedulerListeners.size() > 0) { //if (!TextUtils.isEmpty(task.getTargetName())) { // callback(state, task, mSchedulerListeners.get(task.getTargetName())); @@ -153,7 +118,8 @@ public class DownloadSchedulers implements IDownloadSchedulers { } } - private void callback(int state, Task task, OnSchedulerListener listener) { + private void callback(int state, DownloadTask task, + IDownloadSchedulerListener listener) { if (listener != null) { if (task == null) { Log.e(TAG, "TASK 为null,回调失败"); @@ -184,6 +150,9 @@ public class DownloadSchedulers implements IDownloadSchedulers { case FAIL: listener.onTaskFail(task); break; + case SUPPORT_BREAK_POINT: + listener.onNoSupportBreakPoint(task); + break; } } } @@ -193,7 +162,7 @@ public class DownloadSchedulers implements IDownloadSchedulers { * * @param task 下载任务 */ - @Override public void handleFailTask(final Task task) { + private void handleFailTask(final DownloadTask task) { final Configuration config = Configuration.getInstance(); CountDownTimer timer = new CountDownTimer(config.getReTryInterval(), 1000) { @Override public void onTick(long millisUntilFinished) { @@ -202,8 +171,8 @@ public class DownloadSchedulers implements IDownloadSchedulers { @Override public void onFinish() { DownloadEntity entity = task.getDownloadEntity(); - if (entity.getFailNum() <= config.getReTryNum()) { - Task task = mQueue.getTask(entity); + if (entity.getFailNum() < config.getReTryNum()) { + DownloadTask task = mQueue.getTask(entity); mQueue.reTryStart(task); try { Thread.sleep(config.getReTryInterval()); @@ -212,7 +181,7 @@ public class DownloadSchedulers implements IDownloadSchedulers { } } else { mQueue.removeTask(entity); - startNextTask(entity); + startNextTask(); } } }; @@ -221,11 +190,9 @@ public class DownloadSchedulers implements IDownloadSchedulers { /** * 启动下一个任务,条件:任务停止,取消下载,任务完成 - * - * @param entity 通过Handler传递的下载实体 */ - @Override public void startNextTask(DownloadEntity entity) { - Task newTask = mQueue.getNextTask(); + private void startNextTask() { + DownloadTask newTask = mQueue.getNextTask(); if (newTask == null) { Log.w(TAG, "没有下一任务"); return; diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/IDownloadSchedulerListener.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/IDownloadSchedulerListener.java new file mode 100644 index 00000000..53ecf709 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/IDownloadSchedulerListener.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.scheduler; + +import com.arialyy.aria.core.inf.ITask; + +/** + * Created by Aria.Lao on 2017/4/5. + */ +public interface IDownloadSchedulerListener extends ISchedulerListener { + + /** + * 支持断点的回调 + */ + public void onNoSupportBreakPoint(TASK task); +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/OnSchedulerListener.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulerListener.java similarity index 70% rename from Aria/src/main/java/com/arialyy/aria/core/scheduler/OnSchedulerListener.java rename to Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulerListener.java index baa584af..8bb54b2e 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/scheduler/OnSchedulerListener.java +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulerListener.java @@ -15,49 +15,49 @@ */ package com.arialyy.aria.core.scheduler; -import com.arialyy.aria.core.task.Task; +import com.arialyy.aria.core.inf.ITask; /** * Target处理任务监听 */ -public interface OnSchedulerListener { +public interface ISchedulerListener { /** * 任务预加载 */ - public void onTaskPre(Task task); + public void onTaskPre(TASK task); /** * 任务恢复下载 */ - public void onTaskResume(Task task); + public void onTaskResume(TASK task); /** * 任务开始 */ - public void onTaskStart(Task task); + public void onTaskStart(TASK task); /** * 任务停止 */ - public void onTaskStop(Task task); + public void onTaskStop(TASK task); /** * 任务取消 */ - public void onTaskCancel(Task task); + public void onTaskCancel(TASK task); /** * 任务下载失败 */ - public void onTaskFail(Task task); + public void onTaskFail(TASK task); /** * 任务完成 */ - public void onTaskComplete(Task task); + public void onTaskComplete(TASK task); /** * 任务执行中 */ - public void onTaskRunning(Task task); + public void onTaskRunning(TASK task); } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/IDownloadSchedulers.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulers.java similarity index 51% rename from Aria/src/main/java/com/arialyy/aria/core/scheduler/IDownloadSchedulers.java rename to Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulers.java index 3e75061f..908d0861 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/scheduler/IDownloadSchedulers.java +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulers.java @@ -17,40 +17,62 @@ package com.arialyy.aria.core.scheduler; import android.os.Handler; -import com.arialyy.aria.core.DownloadEntity; -import com.arialyy.aria.core.task.Task; +import com.arialyy.aria.core.inf.ITask; /** * Created by “AriaLyy@outlook.com” on 2016/11/2. - * 下载调度器接口 + * 调度器功能接口 */ -public interface IDownloadSchedulers extends Handler.Callback { - +public interface ISchedulers extends Handler.Callback { /** - * 注册下载器监听,一个观察者只能注册一次监听 - * - * @param targetName 观察者,创建该监听器的对象类名 - * @param schedulerListener {@link OnSchedulerListener} + * 断点支持 */ - public void addSchedulerListener(String targetName, OnSchedulerListener schedulerListener); - + public static final int SUPPORT_BREAK_POINT = 8; /** - * @param targetName 观察者,创建该监听器的对象类名 - * 取消注册监听器 + * 任务预加载 + */ + public static final int PRE = 0; + /** + * 任务开始 + */ + public static final int START = 1; + /** + * 任务停止 + */ + public static final int STOP = 2; + /** + * 任务失败 */ - public void removeSchedulerListener(String targetName, OnSchedulerListener schedulerListener); + public static final int FAIL = 3; + /** + * 任务取消 + */ + public static final int CANCEL = 4; + /** + * 任务完成 + */ + public static final int COMPLETE = 5; + /** + * 任务处理中 + */ + public static final int RUNNING = 6; + /** + * 恢复任务 + */ + public static final int RESUME = 7; /** - * 处理下载任务下载失败的情形 + * 注册下载器监听,一个观察者只能注册一次监听 * - * @param task 下载任务 + * @param targetName 观察者,创建该监听器的对象类名 + * @param schedulerListener {@link ISchedulerListener} */ - public void handleFailTask(Task task); + public void addSchedulerListener(String targetName, ISchedulerListener schedulerListener); /** - * 启动下一个任务,条件:任务停止,取消下载,任务完成 - * - * @param entity 通过Handler传递的下载实体 + * @param targetName 观察者,创建该监听器的对象类名 + * 取消注册监听器 */ - public void startNextTask(DownloadEntity entity); + public void removeSchedulerListener(String targetName, + ISchedulerListener schedulerListener); } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/UploadSchedulers.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/UploadSchedulers.java new file mode 100644 index 00000000..b5108f6b --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/UploadSchedulers.java @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.scheduler; + +import android.os.CountDownTimer; +import android.os.Message; +import android.util.Log; +import com.arialyy.aria.core.inf.IEntity; +import com.arialyy.aria.core.queue.UploadTaskQueue; +import com.arialyy.aria.core.upload.UploadEntity; +import com.arialyy.aria.core.upload.UploadTask; +import com.arialyy.aria.util.Configuration; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Created by Aria.Lao on 2017/2/27. + * 上传任务调度器 + */ +public class UploadSchedulers implements ISchedulers { + private static final String TAG = "UploadSchedulers"; + private static final Object LOCK = new Object(); + private static volatile UploadSchedulers INSTANCE = null; + private Map> mSchedulerListeners = + new ConcurrentHashMap<>(); + private UploadTaskQueue mQueue; + + private UploadSchedulers() { + mQueue = UploadTaskQueue.getInstance(); + } + + public static UploadSchedulers getInstance() { + if (INSTANCE == null) { + synchronized (LOCK) { + INSTANCE = new UploadSchedulers(); + } + } + + return INSTANCE; + } + + @Override public void addSchedulerListener(String targetName, + ISchedulerListener schedulerListener) { + mSchedulerListeners.put(targetName, schedulerListener); + } + + @Override public void removeSchedulerListener(String targetName, + ISchedulerListener schedulerListener) { + for (Iterator>> iter = + mSchedulerListeners.entrySet().iterator(); iter.hasNext(); ) { + Map.Entry> entry = iter.next(); + if (entry.getKey().equals(targetName)) iter.remove(); + } + } + + private void handleFailTask(final UploadTask task) { + final Configuration config = Configuration.getInstance(); + CountDownTimer timer = new CountDownTimer(config.getReTryInterval(), 1000) { + @Override public void onTick(long millisUntilFinished) { + + } + + @Override public void onFinish() { + UploadEntity entity = task.getUploadEntity(); + if (entity.getFailNum() <= config.getReTryNum()) { + UploadTask task = mQueue.getTask(entity); + mQueue.reTryStart(task); + try { + Thread.sleep(config.getReTryInterval()); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } else { + mQueue.removeTask(entity); + startNextTask(); + } + } + }; + timer.start(); + } + + private void startNextTask() { + UploadTask newTask = mQueue.getNextTask(); + if (newTask == null) { + Log.w(TAG, "没有下一任务"); + return; + } + if (newTask.getUploadEntity().getState() == IEntity.STATE_WAIT) { + mQueue.startTask(newTask); + } + } + + /** + * 回调 + * + * @param state 状态 + */ + private void callback(int state, UploadTask task) { + if (mSchedulerListeners.size() > 0) { + //if (!TextUtils.isEmpty(task.getTargetName())) { + // callback(state, task, mSchedulerListeners.get(task.getTargetName())); + //} + Set keys = mSchedulerListeners.keySet(); + for (String key : keys) { + callback(state, task, mSchedulerListeners.get(key)); + } + } + } + + private void callback(int state, UploadTask task, ISchedulerListener listener) { + if (listener != null) { + if (task == null) { + Log.e(TAG, "TASK 为null,回调失败"); + return; + } + switch (state) { + case RUNNING: + listener.onTaskRunning(task); + break; + case START: + listener.onTaskStart(task); + break; + case STOP: + listener.onTaskStop(task); + break; + case RESUME: + listener.onTaskResume(task); + break; + case PRE: + listener.onTaskPre(task); + break; + case CANCEL: + listener.onTaskCancel(task); + break; + case COMPLETE: + listener.onTaskComplete(task); + break; + case FAIL: + listener.onTaskFail(task); + break; + } + } + } + + @Override public boolean handleMessage(Message msg) { + UploadTask task = (UploadTask) msg.obj; + if (task == null) { + Log.e(TAG, "请传入上传任务"); + return true; + } + callback(msg.what, task); + UploadEntity entity = task.getUploadEntity(); + switch (msg.what) { + case STOP: + case CANCEL: + mQueue.removeTask(entity); + if (mQueue.size() < Configuration.getInstance().getDownloadNum()) { + startNextTask(); + } + break; + case COMPLETE: + mQueue.removeTask(entity); + startNextTask(); + break; + case FAIL: + handleFailTask(task); + break; + } + return true; + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/task/TaskFactory.java b/Aria/src/main/java/com/arialyy/aria/core/task/TaskFactory.java deleted file mode 100644 index 8cc1b710..00000000 --- a/Aria/src/main/java/com/arialyy/aria/core/task/TaskFactory.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.arialyy.aria.core.task; - -import android.content.Context; -import com.arialyy.aria.core.DownloadEntity; -import com.arialyy.aria.core.scheduler.IDownloadSchedulers; - -/** - * Created by lyy on 2016/8/18. - * 任务工厂 - */ -public class TaskFactory { - private static final String TAG = "TaskFactory"; - - private static final Object LOCK = new Object(); - private static volatile TaskFactory INSTANCE = null; - - private TaskFactory() { - - } - - public static TaskFactory getInstance() { - if (INSTANCE == null) { - synchronized (LOCK) { - INSTANCE = new TaskFactory(); - } - } - return INSTANCE; - } - - /** - * 创建普通下载任务 - * - * @param entity 下载实体 - * @param schedulers {@link IDownloadSchedulers} - */ - public Task createTask(Context context, DownloadEntity entity, IDownloadSchedulers schedulers) { - return createTask("", context, entity, schedulers); - } - - public Task createTask(String targetName, Context context, DownloadEntity entity, - IDownloadSchedulers schedulers) { - Task.Builder builder = new Task.Builder(targetName, context, entity); - builder.setOutHandler(schedulers); - return builder.build(); - } -} \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/IUploadListener.java b/Aria/src/main/java/com/arialyy/aria/core/upload/IUploadListener.java new file mode 100644 index 00000000..f8044a39 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/IUploadListener.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.upload; + +/** + * Created by Aria.Lao on 2017/2/9. + * 上传监听 + */ +public interface IUploadListener { + + /** + * 预处理 + */ + public void onPre(); + + /** + * 开始上传 + */ + public void onStart(long fileSize); + + /** + * 恢复上传 + * + * @param resumeLocation 上次上传停止位置 + */ + public void onResume(long resumeLocation); + + /** + * 停止上传 + * + * @param stopLocation 上传停止位置 + */ + public void onStop(long stopLocation); + + /** + * 上传进度 + * + * @param currentLocation 当前进度 + */ + public void onProgress(long currentLocation); + + /** + * 取消上传 + */ + public void onCancel(); + + /** + * 上传成功 + */ + public void onComplete(); + + /** + * 上传失败 + */ + public void onFail(); +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadEntity.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadEntity.java new file mode 100644 index 00000000..dd4a54eb --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadEntity.java @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.upload; + +import android.os.Parcel; +import android.os.Parcelable; +import com.arialyy.aria.core.inf.IEntity; +import com.arialyy.aria.orm.DbEntity; +import com.arialyy.aria.orm.Ignore; + +/** + * Created by Aria.Lao on 2017/2/9. + * 上传文件实体 + */ +public class UploadEntity extends DbEntity implements IEntity, Parcelable { + + private String filePath; //文件路径 + private String fileName; //文件名 + private long fileSize; //文件大小 + private int state = STATE_WAIT; + private long currentProgress = 0; + private boolean isComplete = false; + @Ignore private long speed = 0; //下载速度 + @Ignore private int failNum = 0; + + public boolean isComplete() { + return isComplete; + } + + public void setComplete(boolean complete) { + isComplete = complete; + } + + public long getCurrentProgress() { + return currentProgress; + } + + public void setCurrentProgress(long currentProgress) { + this.currentProgress = currentProgress; + } + + public long getFileSize() { + return fileSize; + } + + public void setFileSize(long fileSize) { + this.fileSize = fileSize; + } + + public long getSpeed() { + return speed; + } + + public void setSpeed(long speed) { + this.speed = speed; + } + + public int getFailNum() { + return failNum; + } + + public void setFailNum(int failNum) { + this.failNum = failNum; + } + + @Override public int getState() { + return state; + } + + public void setState(int state) { + this.state = state; + } + + public String getFilePath() { + return filePath; + } + + public void setFilePath(String filePath) { + this.filePath = filePath; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public UploadEntity() { + } + + @Override public int describeContents() { + return 0; + } + + @Override public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.filePath); + dest.writeString(this.fileName); + dest.writeLong(this.fileSize); + dest.writeInt(this.state); + dest.writeLong(this.currentProgress); + dest.writeByte(this.isComplete ? (byte) 1 : (byte) 0); + dest.writeLong(this.speed); + dest.writeInt(this.failNum); + } + + protected UploadEntity(Parcel in) { + this.filePath = in.readString(); + this.fileName = in.readString(); + this.fileSize = in.readLong(); + this.state = in.readInt(); + this.currentProgress = in.readLong(); + this.isComplete = in.readByte() != 0; + this.speed = in.readLong(); + this.failNum = in.readInt(); + } + + @Ignore public static final Creator CREATOR = new Creator() { + @Override public UploadEntity createFromParcel(Parcel source) { + return new UploadEntity(source); + } + + @Override public UploadEntity[] newArray(int size) { + return new UploadEntity[size]; + } + }; +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadListener.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadListener.java new file mode 100644 index 00000000..94dce03d --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadListener.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.upload; + +/** + * Created by Aria.Lao on 2017/2/23. + */ + +public class UploadListener implements IUploadListener { + @Override public void onPre() { + + } + + @Override public void onStart(long fileSize) { + + } + + @Override public void onResume(long resumeLocation) { + + } + + @Override public void onStop(long stopLocation) { + + } + + @Override public void onProgress(long currentLocation) { + + } + + @Override public void onCancel() { + + } + + @Override public void onComplete() { + + } + + @Override public void onFail() { + + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java new file mode 100644 index 00000000..848843b5 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.upload; + +import android.support.annotation.NonNull; +import com.arialyy.aria.core.AriaManager; +import com.arialyy.aria.core.command.AbsCmd; +import com.arialyy.aria.core.command.CmdFactory; +import com.arialyy.aria.core.inf.IEntity; +import com.arialyy.aria.core.inf.IReceiver; +import com.arialyy.aria.core.scheduler.ISchedulerListener; +import com.arialyy.aria.core.scheduler.UploadSchedulers; +import com.arialyy.aria.orm.DbEntity; +import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.CommonUtil; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; + +/** + * Created by Aria.Lao on 2017/2/6. + * 上传功能接收器 + */ +public class UploadReceiver implements IReceiver { + private static final String TAG = "DownloadReceiver"; + public String targetName; + public ISchedulerListener listener; + + /** + * 加载任务 + * + * @param filePath 文件地址 + */ + public UploadTarget load(@NonNull String filePath) { + CheckUtil.checkUploadPath(filePath); + UploadEntity entity = UploadEntity.findData(UploadEntity.class, "filePath=?", filePath); + if (entity == null) { + entity = new UploadEntity(); + } + String regex = "[/|\\\\|//]"; + Pattern p = Pattern.compile(regex); + String[] strs = p.split(filePath); + String fileName = strs[strs.length - 1]; + entity.setFileName(fileName); + entity.setFilePath(filePath); + return new UploadTarget(entity, targetName); + } + + /** + * 通过上传路径获取上传实体 + */ + public UploadEntity getUploadEntity(String filePath) { + CheckUtil.checkUploadPath(filePath); + return DbEntity.findData(UploadEntity.class, "filePath=?", filePath); + } + + /** + * 下载任务是否存在 + */ + @Override public boolean taskExists(String filePath) { + return DbEntity.findData(UploadEntity.class, "filePath=?", filePath) != null; + } + + @Override public List getTaskList() { + return DbEntity.findAllData(UploadEntity.class); + } + + @Override public void stopAllTask() { + List allEntity = DbEntity.findAllData(UploadEntity.class); + List stopCmds = new ArrayList<>(); + for (UploadEntity entity : allEntity) { + if (entity.getState() == IEntity.STATE_RUNNING) { + stopCmds.add( + CommonUtil.createCmd(targetName, new UploadTaskEntity(entity), CmdFactory.TASK_STOP)); + } + } + AriaManager.getInstance(AriaManager.APP).setCmds(stopCmds).exe(); + } + + @Override public void removeAllTask() { + final AriaManager am = AriaManager.getInstance(AriaManager.APP); + List allEntity = DbEntity.findAllData(UploadEntity.class); + List cancelCmds = new ArrayList<>(); + for (UploadEntity entity : allEntity) { + cancelCmds.add( + CommonUtil.createCmd(targetName, new UploadTaskEntity(entity), CmdFactory.TASK_CANCEL)); + } + am.setCmds(cancelCmds).exe(); + Set keys = am.getReceiver().keySet(); + for (String key : keys) { + IReceiver receiver = am.getReceiver().get(key); + receiver.removeSchedulerListener(); + am.getReceiver().remove(key); + } + } + + @Override public void destroy() { + targetName = null; + listener = null; + } + + /** + * 添加调度器回调 + */ + public UploadReceiver addSchedulerListener(ISchedulerListener listener) { + this.listener = listener; + UploadSchedulers.getInstance().addSchedulerListener(targetName, listener); + return this; + } + + @Override public void removeSchedulerListener() { + if (listener != null) { + UploadSchedulers.getInstance().removeSchedulerListener(targetName, listener); + } + } +} \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java new file mode 100644 index 00000000..1276d1d2 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.upload; + +import android.support.annotation.NonNull; +import com.arialyy.aria.core.RequestEnum; +import com.arialyy.aria.core.inf.AbsTarget; +import com.arialyy.aria.core.queue.UploadTaskQueue; +import com.arialyy.aria.orm.DbEntity; +import java.util.Map; + +/** + * Created by Aria.Lao on 2017/2/28. + */ +public class UploadTarget extends AbsTarget { + + UploadTarget(UploadEntity entity, String targetName) { + this.entity = entity; + this.targetName = targetName; + taskEntity = new UploadTaskEntity(entity); + } + + /** + * 设置userAgent + */ + public UploadTarget setUserAngent(@NonNull String userAgent) { + taskEntity.userAgent = userAgent; + return this; + } + + /** + * 设置上传路径 + * + * @param uploadUrl 上传路径 + */ + public UploadTarget setUploadUrl(@NonNull String uploadUrl) { + taskEntity.uploadUrl = uploadUrl; + return this; + } + + /** + * 设置服务器需要的附件key + * + * @param attachment 附件key + */ + public UploadTarget setAttachment(@NonNull String attachment) { + taskEntity.attachment = attachment; + return this; + } + + /** + * 设置文件名 + */ + public UploadTarget setFileName(String fileName) { + entity.setFileName(fileName); + return this; + } + + /** + * 设置上传文件类型 + * + * @param contentType tip:multipart/form-data + */ + public UploadTarget setContentType(String contentType) { + taskEntity.contentType = contentType; + return this; + } + + /** + * 给url请求添加头部 + * + * @param key 头部key + * @param header 头部value + */ + public UploadTarget addHeader(@NonNull String key, @NonNull String header) { + super._addHeader(key, header); + return this; + } + + /** + * 给url请求添加头部 + * + * @param headers key为http头部的key,Value为http头对应的配置 + */ + public UploadTarget addHeaders(Map headers) { + super._addHeaders(headers); + return this; + } + + /** + * 设置请求类型 + * + * @param requestEnum {@link RequestEnum} + */ + public UploadTarget setRequestMode(RequestEnum requestEnum) { + super._setRequestMode(requestEnum); + return this; + } + + private UploadEntity getDownloadEntity(@NonNull String filePath) { + return DbEntity.findData(UploadEntity.class, "filePath=?", filePath); + } + + /** + * 是否在下载 + */ + public boolean isUploading() { + return UploadTaskQueue.getInstance().getTask(entity).isRunning(); + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTask.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTask.java new file mode 100644 index 00000000..d35109b8 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTask.java @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.upload; + +import android.content.Intent; +import android.os.Handler; +import android.util.Log; +import com.arialyy.aria.core.Aria; +import com.arialyy.aria.core.AriaManager; +import com.arialyy.aria.core.download.DownloadEntity; +import com.arialyy.aria.core.inf.IEntity; +import com.arialyy.aria.core.inf.ITask; +import com.arialyy.aria.core.scheduler.DownloadSchedulers; +import com.arialyy.aria.core.scheduler.ISchedulers; +import com.arialyy.aria.util.CommonUtil; +import com.arialyy.aria.util.Configuration; +import java.lang.ref.WeakReference; + +/** + * Created by Aria.Lao on 2017/2/23. + * 上传任务 + */ +public class UploadTask implements ITask { + private static final String TAG = "UploadTask"; + private Handler mOutHandler; + private UploadTaskEntity mTaskEntity; + private UploadEntity mUploadEntity; + private String mTargetName; + + private UploadUtil mUtil; + private UListener mListener; + + UploadTask(UploadTaskEntity taskEntity, Handler outHandler) { + mTaskEntity = taskEntity; + mOutHandler = outHandler; + mUploadEntity = mTaskEntity.uploadEntity; + mListener = new UListener(mOutHandler, this); + mUtil = new UploadUtil(mTaskEntity, mListener); + } + + @Override public void setTargetName(String targetName) { + mTargetName = targetName; + } + + @Override public String getKey() { + return mUploadEntity.getFilePath(); + } + + @Override public boolean isRunning() { + return mUtil.isRunning(); + } + + public UploadEntity getUploadEntity() { + return mUploadEntity; + } + + @Override public IEntity getEntity() { + return mUploadEntity; + } + + @Override public void start() { + if (mUtil.isRunning()) { + Log.d(TAG, "任务正在下载"); + } else { + if (mListener == null) { + mListener = new UploadTask.UListener(mOutHandler, this); + } + mUtil.start(); + } + } + + @Override public void stop() { + + } + + @Override public void cancel() { + if (mUtil.isRunning()) { + mUtil.cancel(); + } else { + // 如果任务不是下载状态 + mUtil.cancel(); + mUploadEntity.deleteData(); + if (mOutHandler != null) { + mOutHandler.obtainMessage(DownloadSchedulers.CANCEL, this).sendToTarget(); + } + //发送取消下载的广播 + Intent intent = CommonUtil.createIntent(AriaManager.APP.getPackageName(), Aria.ACTION_CANCEL); + intent.putExtra(Aria.ENTITY, mUploadEntity); + AriaManager.APP.sendBroadcast(intent); + } + } + + public String getTargetName() { + return mTargetName; + } + + @Override public long getSpeed() { + return mUploadEntity.getSpeed(); + } + + @Override public long getFileSize() { + return mUploadEntity.getFileSize(); + } + + @Override public long getCurrentProgress() { + return mUploadEntity.getCurrentProgress(); + } + + private static class UListener extends UploadListener { + WeakReference outHandler; + WeakReference task; + long lastLen = 0; //上一次发送长度 + long lastTime = 0; + long INTERVAL_TIME = 1000; //1m更新周期 + boolean isFirst = true; + UploadEntity entity; + Intent sendIntent; + + UListener(Handler outHandle, UploadTask task) { + this.outHandler = new WeakReference<>(outHandle); + this.task = new WeakReference<>(task); + entity = this.task.get().getUploadEntity(); + sendIntent = CommonUtil.createIntent(AriaManager.APP.getPackageName(), Aria.ACTION_RUNNING); + sendIntent.putExtra(Aria.ENTITY, entity); + } + + @Override public void onPre() { + entity.setState(IEntity.STATE_PRE); + sendIntent(Aria.ACTION_PRE, -1); + sendInState2Target(ISchedulers.PRE); + } + + @Override public void onStart(long fileSize) { + entity.setFileSize(fileSize); + entity.setState(IEntity.STATE_RUNNING); + sendIntent(Aria.ACTION_PRE, -1); + sendInState2Target(ISchedulers.START); + } + + @Override public void onResume(long resumeLocation) { + entity.setState(DownloadEntity.STATE_RUNNING); + sendInState2Target(DownloadSchedulers.RESUME); + sendIntent(Aria.ACTION_RESUME, resumeLocation); + } + + @Override public void onStop(long stopLocation) { + entity.setState(DownloadEntity.STATE_STOP); + entity.setSpeed(0); + sendInState2Target(DownloadSchedulers.STOP); + sendIntent(Aria.ACTION_STOP, stopLocation); + } + + @Override public void onProgress(long currentLocation) { + if (System.currentTimeMillis() - lastTime > INTERVAL_TIME) { + long speed = currentLocation - lastLen; + sendIntent.putExtra(Aria.CURRENT_LOCATION, currentLocation); + sendIntent.putExtra(Aria.CURRENT_SPEED, speed); + lastTime = System.currentTimeMillis(); + if (isFirst) { + entity.setSpeed(0); + isFirst = false; + } else { + entity.setSpeed(speed); + } + entity.setCurrentProgress(currentLocation); + lastLen = currentLocation; + sendInState2Target(DownloadSchedulers.RUNNING); + AriaManager.APP.sendBroadcast(sendIntent); + } + } + + @Override public void onCancel() { + entity.setState(DownloadEntity.STATE_CANCEL); + sendInState2Target(DownloadSchedulers.CANCEL); + sendIntent(Aria.ACTION_CANCEL, -1); + entity.deleteData(); + } + + @Override public void onComplete() { + entity.setState(DownloadEntity.STATE_COMPLETE); + entity.setComplete(true); + entity.setSpeed(0); + sendInState2Target(DownloadSchedulers.COMPLETE); + sendIntent(Aria.ACTION_COMPLETE, entity.getFileSize()); + } + + @Override public void onFail() { + entity.setFailNum(entity.getFailNum() + 1); + entity.setState(DownloadEntity.STATE_FAIL); + entity.setSpeed(0); + sendInState2Target(DownloadSchedulers.FAIL); + sendIntent(Aria.ACTION_FAIL, -1); + } + + /** + * 将任务状态发送给下载器 + * + * @param state {@link DownloadSchedulers#START} + */ + private void sendInState2Target(int state) { + if (outHandler.get() != null) { + outHandler.get().obtainMessage(state, task.get()).sendToTarget(); + } + } + + private void sendIntent(String action, long location) { + entity.setComplete(action.equals(Aria.ACTION_COMPLETE)); + entity.setCurrentProgress(location); + entity.update(); + if (!Configuration.isOpenBreadCast) return; + Intent intent = CommonUtil.createIntent(AriaManager.APP.getPackageName(), action); + intent.putExtra(Aria.ENTITY, entity); + if (location != -1) { + intent.putExtra(Aria.CURRENT_LOCATION, location); + } + AriaManager.APP.sendBroadcast(intent); + } + } + + public static class Builder { + private Handler mOutHandler; + private UploadTaskEntity mTaskEntity; + private String mTargetName; + + public void setOutHandler(ISchedulers outHandler) { + mOutHandler = new Handler(outHandler); + } + + public void setUploadTaskEntity(UploadTaskEntity taskEntity) { + mTaskEntity = taskEntity; + } + + public void setTargetName(String targetName) { + mTargetName = targetName; + } + + public Builder() { + + } + + public UploadTask build() { + UploadTask task = new UploadTask(mTaskEntity, mOutHandler); + task.setTargetName(mTargetName); + return task; + } + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTaskEntity.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTaskEntity.java new file mode 100644 index 00000000..7db1ab9c --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTaskEntity.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.upload; + +import com.arialyy.aria.core.inf.IEntity; +import com.arialyy.aria.core.inf.ITaskEntity; +import java.util.HashMap; +import java.util.Map; + +/** + * Created by Aria.Lao on 2017/2/9. + * 上传任务实体 + */ +public class UploadTaskEntity extends ITaskEntity { + public UploadEntity uploadEntity; + public String uploadUrl; //上传路径 + public String attachment; //文件上传需要的key + public String contentType = "multipart/form-data"; //上传的文件类型 + public String userAgent = "User-Agent"; + public String charset = "utf-8"; + + /** + * 文件上传表单 + */ + public Map formFields = new HashMap<>(); + + public UploadTaskEntity(UploadEntity downloadEntity) { + this.uploadEntity = downloadEntity; + } + + @Override public IEntity getEntity() { + return uploadEntity; + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadUtil.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadUtil.java new file mode 100644 index 00000000..1b05b200 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadUtil.java @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.core.upload; + +import android.util.Log; +import com.arialyy.aria.util.CheckUtil; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.util.Set; +import java.util.UUID; + +/** + * Created by Aria.Lao on 2017/2/9. + * 上传工具 + */ +final class UploadUtil implements Runnable { + private static final String TAG = "UploadUtil"; + private final String BOUNDARY = UUID.randomUUID().toString(); // 边界标识 随机生成 + private final String PREFIX = "--", LINE_END = "\r\n"; + private UploadEntity mUploadEntity; + private UploadTaskEntity mTaskEntity; + private IUploadListener mListener; + private HttpURLConnection mHttpConn; + private long mCurrentLocation = 0; + private boolean isCancel = false; + private boolean isRunning = false; + private OutputStream mOutputStream; + + UploadUtil(UploadTaskEntity taskEntity, IUploadListener listener) { + mTaskEntity = taskEntity; + CheckUtil.checkUploadTaskEntity(taskEntity.uploadEntity); + mUploadEntity = taskEntity.uploadEntity; + if (listener == null) { + throw new IllegalArgumentException("上传监听不能为空"); + } + mListener = listener; + } + + public void start() { + isCancel = false; + isRunning = false; + new Thread(this).start(); + } + + public void cancel() { + isCancel = true; + isRunning = false; + } + + @Override public void run() { + File uploadFile = new File(mUploadEntity.getFilePath()); + if (!uploadFile.exists()) { + Log.e(TAG, "【" + mUploadEntity.getFilePath() + "】,文件不存在。"); + fail(); + return; + } + + mListener.onPre(); + URL url; + try { + url = new URL(mTaskEntity.uploadUrl); + mHttpConn = (HttpURLConnection) url.openConnection(); + mHttpConn.setUseCaches(false); + mHttpConn.setDoOutput(true); + mHttpConn.setDoInput(true); + mHttpConn.setRequestProperty("Content-Type", + mTaskEntity.contentType + "; boundary=" + BOUNDARY); + mHttpConn.setRequestProperty("User-Agent", mTaskEntity.userAgent); + //mHttpConn.setRequestProperty("Range", "bytes=" + 0 + "-" + "100"); + //内部缓冲区---分段上传防止oom + mHttpConn.setChunkedStreamingMode(1024); + + //添加Http请求头部 + Set keys = mTaskEntity.headers.keySet(); + for (String key : keys) { + mHttpConn.setRequestProperty(key, mTaskEntity.headers.get(key)); + } + + mOutputStream = mHttpConn.getOutputStream(); + PrintWriter writer = + new PrintWriter(new OutputStreamWriter(mOutputStream, mTaskEntity.charset), true); + + //添加文件上传表单字段 + keys = mTaskEntity.formFields.keySet(); + for (String key : keys) { + addFormField(writer, key, mTaskEntity.formFields.get(key)); + } + mListener.onStart(uploadFile.length()); + uploadFile(writer, mTaskEntity.attachment, uploadFile); + Log.d(TAG, finish(writer) + ""); + } catch (IOException e) { + e.printStackTrace(); + fail(); + } + } + + boolean isRunning() { + return isRunning; + } + + private void fail() { + try { + mListener.onFail(); + if (mOutputStream != null) { + mOutputStream.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 添加文件上传表单字段 + */ + private void addFormField(PrintWriter writer, String name, String value) { + writer.append(PREFIX).append(BOUNDARY).append(LINE_END); + writer.append("Content-Disposition: form-data; name=\"") + .append(name) + .append("\"") + .append(LINE_END); + writer.append("Content-Type: text/plain; charset=") + .append(mTaskEntity.charset) + .append(LINE_END); + writer.append(LINE_END); + writer.append(value).append(LINE_END); + writer.flush(); + } + + /** + * 上传文件 + * + * @param attachment 文件上传attachment + * @throws IOException + */ + private void uploadFile(PrintWriter writer, String attachment, File uploadFile) + throws IOException { + writer.append(PREFIX).append(BOUNDARY).append(LINE_END); + writer.append("Content-Disposition: form-data; name=\"") + .append(attachment) + .append("\"; filename=\"") + .append(mTaskEntity.uploadEntity.getFileName()) + .append("\"") + .append(LINE_END); + writer.append("Content-Type: ") + .append(URLConnection.guessContentTypeFromName(mTaskEntity.uploadEntity.getFileName())) + .append(LINE_END); + writer.append("Content-Transfer-Encoding: binary").append(LINE_END); + writer.append(LINE_END); + writer.flush(); + + FileInputStream inputStream = new FileInputStream(uploadFile); + byte[] buffer = new byte[4096]; + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + mCurrentLocation += bytesRead; + mOutputStream.write(buffer, 0, bytesRead); + if (isCancel) { + break; + } + isRunning = true; + mListener.onProgress(mCurrentLocation); + } + + mOutputStream.flush(); + //outputStream.close(); //不能调用,否则服务器端异常 + inputStream.close(); + writer.append(LINE_END); + writer.flush(); + isRunning = false; + if (isCancel) { + mListener.onCancel(); + return; + } + mListener.onComplete(); + } + + /** + * 任务结束操作 + * + * @throws IOException + */ + private String finish(PrintWriter writer) throws IOException { + StringBuilder response = new StringBuilder(); + + writer.append(LINE_END).flush(); + writer.append(PREFIX).append(BOUNDARY).append(PREFIX).append(LINE_END); + writer.close(); + + int status = mHttpConn.getResponseCode(); + if (status == HttpURLConnection.HTTP_OK) { + BufferedReader reader = new BufferedReader(new InputStreamReader(mHttpConn.getInputStream())); + String line; + while ((line = reader.readLine()) != null) { + response.append(line); + } + reader.close(); + mHttpConn.disconnect(); + } else { + Log.w(TAG, "state_code = " + status); + mListener.onFail(); + } + + writer.flush(); + writer.close(); + mOutputStream.close(); + return response.toString(); + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/exception/FileException.java b/Aria/src/main/java/com/arialyy/aria/exception/FileException.java index f4fbb700..734b2ead 100644 --- a/Aria/src/main/java/com/arialyy/aria/exception/FileException.java +++ b/Aria/src/main/java/com/arialyy/aria/exception/FileException.java @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.arialyy.aria.exception; /** diff --git a/Aria/src/main/java/com/arialyy/aria/orm/DbEntity.java b/Aria/src/main/java/com/arialyy/aria/orm/DbEntity.java index c1dfbe08..e39df929 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/DbEntity.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/DbEntity.java @@ -27,9 +27,9 @@ import java.util.List; * 所有数据库实体父类 */ public class DbEntity { - private static final Object LOCK = new Object(); - protected int rowID = -1; - private DbUtil mUtil = DbUtil.getInstance(); + private static final Object LOCK = new Object(); + protected int rowID = -1; + private DbUtil mUtil = DbUtil.getInstance(); protected DbEntity() { @@ -75,7 +75,7 @@ public class DbEntity { * @return 没有数据返回null */ public static T findData(Class clazz, String... expression) { - DbUtil util = DbUtil.getInstance(); + DbUtil util = DbUtil.getInstance(); List datas = util.findData(clazz, expression); return datas == null ? null : datas.size() > 0 ? datas.get(0) : null; } @@ -150,15 +150,15 @@ public class DbEntity { private T findData(Class clazz, @NonNull String[] wheres, @NonNull String[] values) { - DbUtil util = DbUtil.getInstance(); + DbUtil util = DbUtil.getInstance(); List list = util.findData(clazz, wheres, values); return list == null ? null : list.get(0); } private void updateRowID() { try { - Field[] fields = CommonUtil.getFields(getClass()); - List where = new ArrayList<>(); + Field[] fields = CommonUtil.getFields(getClass()); + List where = new ArrayList<>(); List values = new ArrayList<>(); for (Field field : fields) { field.setAccessible(true); diff --git a/Aria/src/main/java/com/arialyy/aria/orm/DbUtil.java b/Aria/src/main/java/com/arialyy/aria/orm/DbUtil.java index 10b64600..443bd98d 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/DbUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/DbUtil.java @@ -34,19 +34,19 @@ import java.util.List; * 数据库操作工具 */ public class DbUtil { - private static final String TAG = "DbUtil"; - private static final Object LOCK = new Object(); - private volatile static DbUtil INSTANCE = null; - private int CREATE_TABLE = 0; - private int TABLE_EXISTS = 1; - private int INSERT_DATA = 2; - private int MODIFY_DATA = 3; - private int FIND_DATA = 4; - private int FIND_ALL_DATA = 5; - private int DEL_DATA = 6; - private int ROW_ID = 7; + private static final String TAG = "DbUtil"; + private static final Object LOCK = new Object(); + private volatile static DbUtil INSTANCE = null; + private int CREATE_TABLE = 0; + private int TABLE_EXISTS = 1; + private int INSERT_DATA = 2; + private int MODIFY_DATA = 3; + private int FIND_DATA = 4; + private int FIND_ALL_DATA = 5; + private int DEL_DATA = 6; + private int ROW_ID = 7; private SQLiteDatabase mDb; - private SqlHelper mHelper; + private SqlHelper mHelper; private DbUtil() { @@ -123,8 +123,8 @@ public class DbUtil { */ synchronized void modifyData(DbEntity dbEntity) { mDb = mHelper.getWritableDatabase(); - Class clazz = dbEntity.getClass(); - Field[] fields = CommonUtil.getFields(clazz); + Class clazz = dbEntity.getClass(); + Field[] fields = CommonUtil.getFields(clazz); if (fields != null && fields.length > 0) { StringBuilder sb = new StringBuilder(); sb.append("UPDATE ").append(CommonUtil.getClassName(dbEntity)).append(" SET "); @@ -398,8 +398,8 @@ public class DbUtil { synchronized int[] getRowId(Class clazz) { mDb = mHelper.getReadableDatabase(); Cursor cursor = mDb.rawQuery("SELECT rowid, * FROM " + CommonUtil.getClassName(clazz), null); - int[] ids = new int[cursor.getCount()]; - int i = 0; + int[] ids = new int[cursor.getCount()]; + int i = 0; while (cursor.moveToNext()) { ids[i] = cursor.getInt(cursor.getColumnIndex("rowid")); i++; @@ -430,8 +430,8 @@ public class DbUtil { i++; } print(ROW_ID, sb.toString()); - Cursor c = mDb.rawQuery(sb.toString(), null); - int id = c.getColumnIndex("rowid"); + Cursor c = mDb.rawQuery(sb.toString(), null); + int id = c.getColumnIndex("rowid"); c.close(); close(); return id; @@ -442,7 +442,7 @@ public class DbUtil { */ private synchronized List newInstanceEntity(Class clazz, Cursor cursor) { - Field[] fields = CommonUtil.getFields(clazz); + Field[] fields = CommonUtil.getFields(clazz); List entitys = new ArrayList<>(); if (fields != null && fields.length > 0) { try { @@ -453,8 +453,8 @@ public class DbUtil { if (ignoreField(field)) { continue; } - Class type = field.getType(); - int column = cursor.getColumnIndex(field.getName()); + Class type = field.getType(); + int column = cursor.getColumnIndex(field.getName()); if (type == String.class) { field.set(entity, cursor.getString(column)); } else if (type == int.class || type == Integer.class) { diff --git a/Aria/src/main/java/com/arialyy/aria/orm/Id.java b/Aria/src/main/java/com/arialyy/aria/orm/Id.java index e6861025..a59b85d9 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/Id.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/Id.java @@ -14,7 +14,6 @@ * limitations under the License. */ - package com.arialyy.aria.orm; import java.lang.annotation.ElementType; diff --git a/Aria/src/main/java/com/arialyy/aria/orm/Ignore.java b/Aria/src/main/java/com/arialyy/aria/orm/Ignore.java index 1b3c1359..33c4523f 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/Ignore.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/Ignore.java @@ -14,7 +14,6 @@ * limitations under the License. */ - package com.arialyy.aria.orm; import java.lang.annotation.ElementType; diff --git a/Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java b/Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java index 4ab30b02..211d8e1e 100644 --- a/Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java +++ b/Aria/src/main/java/com/arialyy/aria/orm/SqlHelper.java @@ -14,7 +14,6 @@ * limitations under the License. */ - package com.arialyy.aria.orm; import android.content.Context; diff --git a/Aria/src/main/java/com/arialyy/aria/util/BufferedRandomAccessFile.java b/Aria/src/main/java/com/arialyy/aria/util/BufferedRandomAccessFile.java index a0f36785..25431082 100644 --- a/Aria/src/main/java/com/arialyy/aria/util/BufferedRandomAccessFile.java +++ b/Aria/src/main/java/com/arialyy/aria/util/BufferedRandomAccessFile.java @@ -18,7 +18,10 @@ package com.arialyy.aria.util; -import java.io.*; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; import java.util.Arrays; //import org.apache.log4j.Logger; @@ -38,9 +41,9 @@ import java.util.Arrays; public final class BufferedRandomAccessFile extends RandomAccessFile { //private static final Logger logger_ = Logger.getLogger(BufferedRandomAccessFile.class); - static final int LogBuffSz_ = 16; // 64K buffer - public static final int BuffSz_ = (1 << LogBuffSz_); - static final long BuffMask_ = ~(((long) BuffSz_) - 1L); + static final int LogBuffSz_ = 16; // 64K buffer + public static final int BuffSz_ = (1 << LogBuffSz_); + static final long BuffMask_ = ~(((long) BuffSz_) - 1L); /* * This implementation is based on the buffer implementation in Modula-3's @@ -48,12 +51,12 @@ public final class BufferedRandomAccessFile extends RandomAccessFile { */ private boolean dirty_; // true iff unflushed bytes exist private boolean closed_; // true iff the file is closed - private long curr_; // current position in file - private long lo_, hi_; // bounds on characters in "buff" - private byte[] buff_; // local buffer - private long maxHi_; // this.lo + this.buff.length + private long curr_; // current position in file + private long lo_, hi_; // bounds on characters in "buff" + private byte[] buff_; // local buffer + private long maxHi_; // this.lo + this.buff.length private boolean hitEOF_; // buffer contains last file block? - private long diskPos_; // disk position + private long diskPos_; // disk position /* * To describe the above fields, we introduce the following abstractions for diff --git a/Aria/src/main/java/com/arialyy/aria/util/CheckUtil.java b/Aria/src/main/java/com/arialyy/aria/util/CheckUtil.java index fd07b7c1..2ac140af 100644 --- a/Aria/src/main/java/com/arialyy/aria/util/CheckUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/util/CheckUtil.java @@ -17,10 +17,12 @@ package com.arialyy.aria.util; import android.text.TextUtils; -import android.util.Log; -import com.arialyy.aria.core.DownloadEntity; +import com.arialyy.aria.core.download.DownloadEntity; +import com.arialyy.aria.core.download.DownloadTaskEntity; +import com.arialyy.aria.core.inf.ITaskEntity; +import com.arialyy.aria.core.upload.UploadEntity; +import com.arialyy.aria.core.upload.UploadTaskEntity; import com.arialyy.aria.exception.FileException; -import java.io.File; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -31,6 +33,9 @@ import java.util.regex.Pattern; public class CheckUtil { private static final String TAG = "CheckUtil"; + /** + * 判空 + */ public static void checkNull(Object obj) { if (obj == null) throw new IllegalArgumentException("不能传入空对象"); } @@ -51,14 +56,14 @@ public class CheckUtil { } Pattern pattern = Pattern.compile("\\?"); Matcher matcher = pattern.matcher(where); - int count = 0; + int count = 0; while (matcher.find()) { count++; } - if (count < expression.length - 1){ + if (count < expression.length - 1) { throw new IllegalArgumentException("条件语句的?个数不能小于参数个数"); } - if (count > expression.length - 1){ + if (count > expression.length - 1) { throw new IllegalArgumentException("条件语句的?个数不能大于参数个数"); } } @@ -70,35 +75,75 @@ public class CheckUtil { if (TextUtils.isEmpty(downloadUrl)) throw new IllegalArgumentException("下载链接不能为null"); } + /** + * 检测上传地址是否为null + */ + public static void checkUploadPath(String uploadPath) { + if (TextUtils.isEmpty(uploadPath)) throw new IllegalArgumentException("上传地址不能为null"); + } + + /** + * 检查任务实体 + */ + public static void checkTaskEntity(ITaskEntity entity) { + if (entity instanceof DownloadTaskEntity) { + checkDownloadTaskEntity(((DownloadTaskEntity) entity).downloadEntity); + } else if (entity instanceof UploadTaskEntity) { + checkUploadTaskEntity(((UploadTaskEntity) entity).uploadEntity); + } + } + + /** + * 检查命令实体 + */ + public static void checkCmdEntity(ITaskEntity entity) { + if (entity instanceof DownloadTaskEntity) { + DownloadEntity entity1 = ((DownloadTaskEntity) entity).downloadEntity; + if (entity1 == null) { + throw new NullPointerException("下载实体不能为空"); + } else if (TextUtils.isEmpty(entity1.getDownloadUrl())) { + throw new IllegalArgumentException("下载链接不能为空"); + } else if (TextUtils.isEmpty(entity1.getDownloadPath())) { + throw new IllegalArgumentException("保存路径不能为空"); + } + } else if (entity instanceof UploadTaskEntity) { + UploadEntity entity1 = ((UploadTaskEntity) entity).uploadEntity; + if (entity1 == null) { + throw new NullPointerException("上传实体不能为空"); + } else if (TextUtils.isEmpty(entity1.getFilePath())) { + throw new IllegalArgumentException("上传文件路径不能为空"); + } + } + } + + /** + * 检查上传实体是否合法 + */ + public static void checkUploadTaskEntity(UploadEntity entity) { + if (entity == null) { + throw new NullPointerException("上传实体不能为空"); + } else if (TextUtils.isEmpty(entity.getFilePath())) { + throw new IllegalArgumentException("上传文件路径不能为空"); + } else if (TextUtils.isEmpty(entity.getFileName())) { + throw new IllegalArgumentException("上传文件名不能为空"); + } + } + /** * 检测下载实体是否合法 + * 合法(true) * * @param entity 下载实体 - * @return 合法(true) */ - public static boolean checkDownloadEntity(DownloadEntity entity) { + public static void checkDownloadTaskEntity(DownloadEntity entity) { if (entity == null) { - Log.w(TAG, "下载实体不能为空"); - return false; + throw new NullPointerException("下载实体不能为空"); } else if (TextUtils.isEmpty(entity.getDownloadUrl())) { - Log.w(TAG, "下载链接不能为空"); - return false; + throw new IllegalArgumentException("下载链接不能为空"); } else if (TextUtils.isEmpty(entity.getFileName())) { - //Log.w(TAG, "文件名不能为空"); throw new FileException("文件名不能为null"); } else if (TextUtils.isEmpty(entity.getDownloadPath())) { throw new FileException("文件保存路径不能为null"); } - String fileName = entity.getFileName(); - if (fileName.contains(" ")) { - fileName = fileName.replace(" ", "_"); - } - String dPath = entity.getDownloadPath(); - File file = new File(dPath); - if (file.isDirectory()) { - dPath += fileName; - entity.setDownloadPath(dPath); - } - return true; } } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java b/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java index 3031b232..47c59018 100644 --- a/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java @@ -22,8 +22,8 @@ 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; -import com.arialyy.aria.core.command.IDownloadCmd; +import com.arialyy.aria.core.command.AbsCmd; +import com.arialyy.aria.core.inf.ITaskEntity; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -40,21 +40,17 @@ import java.util.Properties; public class CommonUtil { private static final String TAG = "util"; - public static IDownloadCmd createCmd(String target, DownloadEntity entity, int cmd) { + public static AbsCmd createCmd(String target, T entity, int cmd) { return CmdFactory.getInstance().createCmd(target, entity, cmd); } - public static IDownloadCmd createCmd(DownloadEntity entity, int cmd) { - 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(); + Uri uri = builder.build(); Intent intent = new Intent(action); intent.setData(uri); return intent; @@ -69,7 +65,7 @@ public class CommonUtil { * @return 成功标志 */ public static Boolean putString(String preName, Context context, String key, String value) { - SharedPreferences pre = context.getSharedPreferences(preName, Context.MODE_PRIVATE); + SharedPreferences pre = context.getSharedPreferences(preName, Context.MODE_PRIVATE); SharedPreferences.Editor editor = pre.edit(); editor.putString(key, value); return editor.commit(); @@ -302,9 +298,11 @@ public class CommonUtil { * 读取下载配置文件 */ public static Properties loadConfig(File file) { - Properties properties = new Properties(); - FileInputStream fis = null; - + Properties properties = new Properties(); + FileInputStream fis = null; + if (!file.exists()) { + createFile(file.getPath()); + } try { fis = new FileInputStream(file); properties.load(fis); diff --git a/Aria/src/main/java/com/arialyy/aria/util/Configuration.java b/Aria/src/main/java/com/arialyy/aria/util/Configuration.java index de3703d7..05081d1f 100644 --- a/Aria/src/main/java/com/arialyy/aria/util/Configuration.java +++ b/Aria/src/main/java/com/arialyy/aria/util/Configuration.java @@ -16,7 +16,7 @@ package com.arialyy.aria.util; import android.util.Log; -import com.arialyy.aria.core.DownloadManager; +import com.arialyy.aria.core.AriaManager; import java.io.File; import java.io.IOException; import java.util.Map; @@ -29,33 +29,38 @@ import java.util.WeakHashMap; * 信息配置 */ public class Configuration { - private static final String TAG = "Configuration"; - private static final String CONFIG_FILE = "/Aria/ADConfig.properties"; + private static final String TAG = "Configuration"; + private static final String CONFIG_FILE = "/Aria/ADConfig.properties"; /** * 当前调度器最大下载数,默认最大下载数为 “2” */ - private static final String DOWNLOAD_NUM = "DOWNLOAD_NUM"; + private static final String DOWNLOAD_NUM = "DOWNLOAD_NUM"; /** * 失败重试次数,默认最多重试 10 次 */ - private static final String RE_TRY_NUM = "RE_TRY_NUM"; + private static final String RE_TRY_NUM = "RE_TRY_NUM"; /** * 是否打开下载广播,默认 false */ - private static final String OPEN_BROADCAST = "OPEN_BROADCAST"; + private static final String OPEN_BROADCAST = "OPEN_BROADCAST"; /** * 失败重试间隔时间,默认 4000 ms */ - private static final String RE_TRY_INTERVAL = "RE_TRY_INTERVAL"; + private static final String RE_TRY_INTERVAL = "RE_TRY_INTERVAL"; /** * 超时时间,默认 10000 ms */ private static final String DOWNLOAD_TIME_OUT = "DOWNLOAD_TIME_OUT"; + /** + * 设置最大速度 + */ + private static final String MAX_SPEED = "MAX_SPEED"; + public static boolean isOpenBreadCast = false; - private static Configuration INSTANCE = null; - private File mConfigFile = null; - private static final Object LOCK = new Object(); + private static Configuration INSTANCE = null; + private File mConfigFile = null; + private static final Object LOCK = new Object(); public static Configuration getInstance() { if (INSTANCE == null) { @@ -67,13 +72,13 @@ public class Configuration { } private Configuration() { - mConfigFile = new File(DownloadManager.APP.getFilesDir().getPath() + CONFIG_FILE); + mConfigFile = new File(AriaManager.APP.getFilesDir().getPath() + CONFIG_FILE); try { if (!mConfigFile.exists()) { mConfigFile.getParentFile().mkdirs(); mConfigFile.createNewFile(); init(); - }else { + } else { isOpenBreadCast = isOpenBroadcast(); } } catch (IOException e) { @@ -88,6 +93,7 @@ public class Configuration { config.put(OPEN_BROADCAST, false + ""); config.put(RE_TRY_INTERVAL, 4000 + ""); config.put(DOWNLOAD_TIME_OUT, 10000 + ""); + config.put(MAX_SPEED, 64 + ""); saveConfig(config); } @@ -95,8 +101,8 @@ public class Configuration { if (config == null || config.size() == 0) { return; } - Properties properties = CommonUtil.loadConfig(mConfigFile); - Set keys = config.keySet(); + Properties properties = CommonUtil.loadConfig(mConfigFile); + Set keys = config.keySet(); for (String key : keys) { properties.setProperty(key, config.get(key)); } @@ -109,6 +115,20 @@ public class Configuration { saveConfig(map); } + /** + * 设置最大下载速度 + */ + public void setMaxSpeed(Speed speed) { + save(MAX_SPEED, speed.buf + ""); + } + + /** + * 获取最大速度 + */ + public int getMaxSpeed() { + return Integer.parseInt(CommonUtil.loadConfig(mConfigFile).getProperty(MAX_SPEED, "8192")); + } + /** * 获取下载超时时间 * diff --git a/Aria/src/main/java/com/arialyy/aria/util/FileUtil.java b/Aria/src/main/java/com/arialyy/aria/util/FileUtil.java new file mode 100644 index 00000000..6fb9bf09 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/util/FileUtil.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.util; + +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.Icon; +import com.arialyy.aria.window.FileEntity; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Aria.Lao on 2017/3/21. + */ + +public class FileUtil { + + Context mContext; + + public FileUtil(Context context) { + mContext = context; + } + + /** + * 文件列表 + */ + public List loadFiles(String path) { + File file = new File(path); + File[] files = file.listFiles(); + List list = new ArrayList<>(); + for (File f : files) { + FileEntity entity = new FileEntity(); + entity.fileName = f.getName(); + //entity.fileInfo = getFileType(f.getPath()); + //entity.fileDrawable = getApkIcon(mContext, f.getPath()); + list.add(entity); + } + return list; + } + + /** + * 获取文件类型 + */ + public FileType getFileType(String path) { + String exName = getExName(path); + String type = ""; + FileType fType = null; + if (exName.equalsIgnoreCase("apk")) { + fType = new FileType("应用", getApkIcon(path)); + } else if (exName.equalsIgnoreCase("img") + || exName.equalsIgnoreCase("png") + || exName.equalsIgnoreCase("jpg") + || exName.equalsIgnoreCase("jepg")) { + //fType = new FileType("图片", ) + } else if (exName.equalsIgnoreCase("mp3") || exName.equalsIgnoreCase("wm")) { + //fType = new FileType("音乐", ); + } else if (exName.equalsIgnoreCase("mp4") + || exName.equalsIgnoreCase("rm") + || exName.equalsIgnoreCase("rmvb")) { + //fType = new FileType("视频", ); + } + return fType; + } + + /** + * 获取扩展名 + */ + public String getExName(String path) { + int separatorIndex = path.lastIndexOf("."); + return (separatorIndex < 0) ? path : path.substring(separatorIndex + 1, path.length()); + } + + /** + * 获取apk文件的icon + * + * @param path apk文件路径 + */ + public Drawable getApkIcon(String path) { + PackageManager pm = mContext.getPackageManager(); + PackageInfo info = pm.getPackageArchiveInfo(path, PackageManager.GET_ACTIVITIES); + if (info != null) { + ApplicationInfo appInfo = info.applicationInfo; + //android有bug,需要下面这两句话来修复才能获取apk图片 + appInfo.sourceDir = path; + appInfo.publicSourceDir = path; + // String packageName = appInfo.packageName; //得到安装包名称 + // String version=info.versionName; //得到版本信息 + return pm.getApplicationIcon(appInfo); + } + return null; + } + + class FileType { + String name; + Drawable icon; + + public FileType(String name, Drawable icon) { + this.name = name; + this.icon = icon; + } + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/util/PathUtil.java b/Aria/src/main/java/com/arialyy/aria/util/PathUtil.java index ed7efc5a..b0e5aad3 100644 --- a/Aria/src/main/java/com/arialyy/aria/util/PathUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/util/PathUtil.java @@ -14,7 +14,6 @@ * limitations under the License. */ - package com.arialyy.aria.util; import android.os.Environment; diff --git a/Aria/src/main/java/com/arialyy/aria/util/SSLContextUtil.java b/Aria/src/main/java/com/arialyy/aria/util/SSLContextUtil.java index af40e0de..b93328f8 100644 --- a/Aria/src/main/java/com/arialyy/aria/util/SSLContextUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/util/SSLContextUtil.java @@ -16,10 +16,7 @@ package com.arialyy.aria.util; import android.text.TextUtils; -import com.arialyy.aria.core.DownloadManager; -import java.io.BufferedInputStream; -import java.io.FileInputStream; -import java.io.FileNotFoundException; +import com.arialyy.aria.core.AriaManager; import java.io.IOException; import java.io.InputStream; import java.security.KeyManagementException; @@ -42,8 +39,8 @@ import javax.net.ssl.X509TrustManager; /** * Created by Aria.Lao on 2017/1/11. + * SSL证书工具 */ - public class SSLContextUtil { /** @@ -61,7 +58,7 @@ public class SSLContextUtil { CertificateFactory cf = null; try { cf = CertificateFactory.getInstance("X.509"); - InputStream caInput = DownloadManager.APP.getAssets().open(caPath); + InputStream caInput = AriaManager.APP.getAssets().open(caPath); Certificate ca; ca = cf.generateCertificate(caInput); System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN()); diff --git a/Aria/src/main/java/com/arialyy/aria/util/Speed.java b/Aria/src/main/java/com/arialyy/aria/util/Speed.java new file mode 100644 index 00000000..f26a2329 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/util/Speed.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.util; + +/** + * Created by Aria.Lao on 2017/3/6. + */ +public enum Speed { + /** + * 最大速度为256kb + */ + KB_256(64), /** + * 最大速度为512kb + */ + KB_512(128), /** + * 最大速度为1mb + */ + MB_1(256), /** + * 最大速度为2mb + */ + MB_2(1024), /** + * 最大速度为10mb + */ + MAX(8192); + int buf; + + Speed(int buf) { + this.buf = buf; + } + +} diff --git a/Aria/src/main/java/com/arialyy/aria/util/WeakHandler.java b/Aria/src/main/java/com/arialyy/aria/util/WeakHandler.java index 2d176dde..55a334ab 100644 --- a/Aria/src/main/java/com/arialyy/aria/util/WeakHandler.java +++ b/Aria/src/main/java/com/arialyy/aria/util/WeakHandler.java @@ -47,467 +47,451 @@ import java.util.concurrent.locks.ReentrantLock; * * 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(); +@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 uptimeMillis. + * The time-base is {@link android.os.SystemClock#uptimeMillis}. + * 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 uptimeMillis. + * The time-base is {@link android.os.SystemClock#uptimeMillis}. + * 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. + * 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. + * + * @param r The Runnable that will be executed. + * @return Returns true if the message was successfully placed in to the + * message queue. Returns false on failure, usually because the + * looper processing the message queue is exiting. + */ + public final boolean postAtFrontOfQueue(Runnable r) { + return mExec.postAtFrontOfQueue(wrapRunnable(r)); + } + + /** + * Remove any pending posts of Runnable r that are in the message queue. + */ + public final void removeCallbacks(Runnable r) { + final WeakRunnable runnable = mRunnables.remove(r); + if (runnable != null) { + mExec.removeCallbacks(runnable); } - - /** - * Constructor associates this handler with the {@link Looper} for the - * current thread and takes a callback interface in which you can handle - * 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); + } + + /** + * Remove any pending posts of Runnable r with Object + * token that are in the message queue. If token 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); } - - /** - * 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)); + } + + /** + * 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. + * + * @return Returns true if the message was successfully placed in to the + * message queue. Returns false on failure, usually because the + * looper processing the message queue is exiting. + * @see #sendMessageDelayed(android.os.Message, long) + */ + public final boolean sendEmptyMessageDelayed(int what, long delayMillis) { + return mExec.sendEmptyMessageDelayed(what, delayMillis); + } + + /** + * Sends a Message containing only the what value, to be delivered + * at a specific time. + * + * @return Returns true if the message was successfully placed in to the + * message queue. Returns false on failure, usually because the + * looper processing the message queue is exiting. + * @see #sendMessageAtTime(android.os.Message, long) + */ + public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) { + return mExec.sendEmptyMessageAtTime(what, uptimeMillis); + } + + /** + * Enqueue a message into the message queue after all pending messages + * before (current time + delayMillis). You will receive it in + * callback, in the thread attached to this handler. + * + * @return Returns true if the message was successfully placed in to the + * message queue. Returns false on failure, usually because the + * looper processing the message queue is exiting. Note that a + * result of true does not mean the message will be processed -- if + * the looper is quit before the delivery time of the message + * occurs then the message will be dropped. + */ + public final boolean sendMessageDelayed(Message msg, long delayMillis) { + return mExec.sendMessageDelayed(msg, delayMillis); + } + + /** + * Enqueue a message into the message queue after all pending messages + * before the absolute time (in milliseconds) uptimeMillis. + * The time-base is {@link android.os.SystemClock#uptimeMillis}. + * 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. + * 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. + * + * @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 object 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 + * obj is token. If token 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; + } - /** - * Causes the Runnable r to be added to the message queue, to be run - * at a specific time given by uptimeMillis. - * The time-base is {@link android.os.SystemClock#uptimeMillis}. - * 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); - } + private static class ExecHandler extends Handler { + private final WeakReference mCallback; - /** - * Causes the Runnable r to be added to the message queue, to be run - * at a specific time given by uptimeMillis. - * The time-base is {@link android.os.SystemClock#uptimeMillis}. - * The runnable will be run on the thread to which this handler is attached. - * - * @param r The Runnable that will be executed. - * @param uptimeMillis The absolute time at which the callback should run, - * using the {@link android.os.SystemClock#uptimeMillis} time-base. - * - * @return Returns true if the Runnable was successfully placed in to the - * message queue. Returns false on failure, usually because the - * looper processing the message queue is exiting. Note that a - * result of true does not mean the Runnable will be processed -- if - * the looper is quit before the delivery time of the message - * occurs then the message will be dropped. - * - * @see android.os.SystemClock#uptimeMillis - */ - public final boolean postAtTime(Runnable r, Object token, long uptimeMillis) { - return mExec.postAtTime(wrapRunnable(r), token, uptimeMillis); + ExecHandler() { + mCallback = null; } - /** - * 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); + ExecHandler(WeakReference callback) { + mCallback = callback; } - /** - * 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. - * 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. - * - * @param r The Runnable that will be executed. - * - * @return Returns true if the message was successfully placed in to the - * message queue. Returns false on failure, usually because the - * looper processing the message queue is exiting. - */ - public final boolean postAtFrontOfQueue(Runnable r) { - return mExec.postAtFrontOfQueue(wrapRunnable(r)); + ExecHandler(Looper looper) { + super(looper); + mCallback = null; } - /** - * 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); - } + ExecHandler(Looper looper, WeakReference callback) { + super(looper); + mCallback = callback; } - /** - * Remove any pending posts of Runnable r with Object - * token that are in the message queue. If token 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); - } + @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); } + } - /** - * 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); - } + static class WeakRunnable implements Runnable { + private final WeakReference mDelegate; + private final WeakReference mReference; - /** - * 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); + WeakRunnable(WeakReference delegate, WeakReference reference) { + mDelegate = delegate; + mReference = reference; } - /** - * 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); + @Override public void run() { + final Runnable delegate = mDelegate.get(); + final ChainedRef reference = mReference.get(); + if (reference != null) { + reference.remove(); + } + if (delegate != null) { + delegate.run(); + } } + } - /** - * 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); - } + static class ChainedRef { + @Nullable ChainedRef next; + @Nullable ChainedRef prev; + @NonNull final Runnable runnable; + @NonNull final WeakRunnable wrapper; - /** - * 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); - } + @NonNull Lock lock; - /** - * Enqueue a message into the message queue after all pending messages - * before the absolute time (in milliseconds) uptimeMillis. - * The time-base is {@link android.os.SystemClock#uptimeMillis}. - * You will receive it in callback, in the thread attached - * to this handler. - * - * @param uptimeMillis The absolute time at which the message should be - * delivered, using the - * {@link android.os.SystemClock#uptimeMillis} time-base. - * - * @return Returns true if the message was successfully placed in to the - * message queue. Returns false on failure, usually because the - * looper processing the message queue is exiting. Note that a - * result of true does not mean the message will be processed -- if - * the looper is quit before the delivery time of the message - * occurs then the message will be dropped. - */ - public boolean sendMessageAtTime(Message msg, long uptimeMillis) { - return mExec.sendMessageAtTime(msg, uptimeMillis); + public ChainedRef(@NonNull Lock lock, @NonNull Runnable r) { + this.runnable = r; + this.lock = lock; + this.wrapper = new WeakRunnable(new WeakReference<>(r), new WeakReference<>(this)); } - /** - * 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. - * 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. - * - * @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 object 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 - * obj is token. If token 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 mCallback; - - ExecHandler() { - mCallback = null; - } - - ExecHandler(WeakReference callback) { - mCallback = callback; - } - - ExecHandler(Looper looper) { - super(looper); - mCallback = null; + public WeakRunnable remove() { + lock.lock(); + try { + if (prev != null) { + prev.next = next; } - - ExecHandler(Looper looper, WeakReference 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); + if (next != null) { + next.prev = prev; } + prev = null; + next = null; + } finally { + lock.unlock(); + } + return wrapper; } - static class WeakRunnable implements Runnable { - private final WeakReference mDelegate; - private final WeakReference mReference; - - WeakRunnable(WeakReference delegate, WeakReference reference) { - mDelegate = delegate; - mReference = reference; + public void insertAfter(@NonNull ChainedRef candidate) { + lock.lock(); + try { + if (this.next != null) { + this.next.prev = candidate; } - @Override - public void run() { - final Runnable delegate = mDelegate.get(); - final ChainedRef reference = mReference.get(); - if (reference != null) { - reference.remove(); - } - if (delegate != null) { - delegate.run(); - } - } + candidate.next = this.next; + this.next = candidate; + candidate.prev = this; + } finally { + lock.unlock(); + } } - 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; + @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; } + } } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/window/AriaFileChangeActivity.java b/Aria/src/main/java/com/arialyy/aria/window/AriaFileChangeActivity.java new file mode 100644 index 00000000..dbef9a15 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/window/AriaFileChangeActivity.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.window; + +import android.os.Bundle; +import android.os.Environment; +import android.support.annotation.Nullable; +import android.support.v4.app.FragmentActivity; +import android.widget.AbsListView; +import android.widget.ListView; +import com.arialyy.aria.R; +import com.arialyy.aria.util.FileUtil; +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by Aria.Lao on 2017/3/21. + * 文件选择 + */ +public class AriaFileChangeActivity extends FragmentActivity { + final String ROOT_PAT = Environment.getExternalStorageDirectory().getPath(); + ListView mList; + FileChangeAdapter mAdapter; + Map> mData = new HashMap<>(); + private String mCurrentPath = ROOT_PAT; + + @Override protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_aria_file_shange); + mList = (ListView) findViewById(R.id.list); + mList.setOnScrollListener(new AbsListView.OnScrollListener() { + int state; + + @Override public void onScrollStateChanged(AbsListView view, int scrollState) { + state = scrollState; + } + + @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, + int totalItemCount) { + if (state == AbsListView.OnScrollListener.SCROLL_STATE_IDLE + && firstVisibleItem + visibleItemCount == totalItemCount) { + loadMore(); + } + } + }); + } + + private void loadMore() { + + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/window/FileChangeAdapter.java b/Aria/src/main/java/com/arialyy/aria/window/FileChangeAdapter.java new file mode 100644 index 00000000..1e3335a9 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/window/FileChangeAdapter.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.window; + +import android.content.Context; +import android.util.SparseBooleanArray; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.CheckBox; +import android.widget.ImageView; +import android.widget.TextView; +import com.arialyy.aria.R; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Aria.Lao on 2017/3/21. + */ +final class FileChangeAdapter extends BaseAdapter { + + List mData = new ArrayList<>(); + SparseBooleanArray mCheck = new SparseBooleanArray(); + Context mContext; + + public FileChangeAdapter(Context context, List list) { + mContext = context; + mData.addAll(list); + for (int i = 0, len = mData.size(); i < len; i++) { + mCheck.append(i, false); + } + } + + @Override public int getCount() { + return mData.size(); + } + + @Override public Object getItem(int position) { + return null; + } + + @Override public long getItemId(int position) { + return 0; + } + + @Override public View getView(int position, View convertView, ViewGroup parent) { + FileChangeHolder holder = null; + if (convertView == null) { + convertView = LayoutInflater.from(mContext).inflate(R.layout.item_file, null); + holder = new FileChangeHolder(convertView); + convertView.setTag(holder); + } else { + holder = (FileChangeHolder) convertView.getTag(); + } + + holder.checkBox.setChecked(mCheck.get(position, false)); + return convertView; + } + + public void setCheck(int position, boolean check) { + if (position >= mData.size()) return; + mCheck.put(position, check); + notifyDataSetChanged(); + } + + private static class FileChangeHolder { + TextView title, info; + ImageView icon; + CheckBox checkBox; + + FileChangeHolder(View view) { + title = (TextView) view.findViewById(R.id.title); + info = (TextView) view.findViewById(R.id.info); + icon = (ImageView) view.findViewById(R.id.icon); + checkBox = (CheckBox) view.findViewById(R.id.checkbox); + } + } +} diff --git a/Aria/src/main/java/com/arialyy/aria/window/FileEntity.java b/Aria/src/main/java/com/arialyy/aria/window/FileEntity.java new file mode 100644 index 00000000..e0978bf9 --- /dev/null +++ b/Aria/src/main/java/com/arialyy/aria/window/FileEntity.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.window; + +import android.graphics.drawable.Drawable; + +/** + * Created by Aria.Lao on 2017/3/21. + */ + +public class FileEntity { + public String fileName; + public String fileInfo; + public int fileIcon; + public Drawable fileDrawable; +} diff --git a/Aria/src/main/res/layout/item_file.xml b/Aria/src/main/res/layout/item_file.xml index e24b1632..7f4c8044 100644 --- a/Aria/src/main/res/layout/item_file.xml +++ b/Aria/src/main/res/layout/item_file.xml @@ -10,7 +10,9 @@ android:id="@+id/checkbox" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_alignParentRight="true" android:layout_centerVertical="true" + android:clickable="false" /> \ No newline at end of file diff --git a/DownloadApi.md b/DownloadApi.md new file mode 100644 index 00000000..45134f3d --- /dev/null +++ b/DownloadApi.md @@ -0,0 +1,40 @@ +## 关于Aria,你还需要知道的一些东西 +- 设置下载任务数,Aria默认下载任务为**2** + + ```java + Aria.get(getContext()).setMaxDownloadNum(num); + ``` +- 停止所有下载 + + ```java + Aria.get(this).stopAllTask(); + ``` +- 设置失败重试次数,从事次数不能少于 1 + + ```java + Aria.get(this).setReTryNum(10); + ``` +- 设置失败重试间隔,重试间隔不能小于 5000ms + + ```java + Aria.get(this).setReTryInterval(5000); + ``` +- 设置是否打开广播,如果你需要在Service后台获取下载完成情况,那么你需要打开Aria广播,[Aria广播配置](https://github.com/AriaLyy/Aria/blob/v_2.0/BroadCast.md) + + ```java + Aria.get(this).openBroadcast(true); + ``` + +## https证书配置 + + 将你的证书导入`assets`目录 + + 调用以下代码配置ca证书相关信息 + + ```java + /** + * 设置CA证书信息 + * + * @param caAlias ca证书别名 + * @param caPath assets 文件夹下的ca证书完整路径 + */ + Aria.get(this).setCAInfo("caAlias","caPath"); + ``` diff --git a/README.md b/README.md index 6bbb3031..e5a2e22e 100644 --- a/README.md +++ b/README.md @@ -1,153 +1,158 @@ # Aria ![图标](https://github.com/AriaLyy/DownloadUtil/blob/v_2.0/app/src/main/res/mipmap-hdpi/ic_launcher.png)
-下载不应该是让人感到痛苦的功能,Aria,让下载更简单。
+Aria,让上传、下载更容易实现
+ Aria有以下特点: - 简单 - 可在Dialog、popupWindow等组件中使用 - - 可自定义是否使用广播 - 支持多线程、多任务下载 - - 支持任务自动切换 - - 支持下载速度直接获取 + - 支持多任务自动调度 + - 可以直接获取速度 - 支持https地址下载 + - 支持上传操作 -[Aria怎样使用?](#使用) +Aria怎样使用? +* [下载](#使用) +* [上传](#上传) 如果你觉得Aria对你有帮助,您的star和issues将是对我最大支持.`^_^` ## 下载 [![Download](https://api.bintray.com/packages/arialyy/maven/Aria/images/download.svg)](https://bintray.com/arialyy/maven/Aria/_latestVersion)
```java -compile 'com.arialyy.aria:Aria:2.4.4' +compile 'com.arialyy.aria:Aria:3.0.0' ``` ## 示例 -![多任务下载](https://github.com/AriaLyy/DownloadUtil/blob/v_2.0/img/download_img.gif) -![Dialog使用](https://github.com/AriaLyy/DownloadUtil/blob/v_2.0/img/dialog_use.gif "") +![多任务下载](https://github.com/AriaLyy/DownloadUtil/blob/master/img/download_img.gif) +![上传](https://github.com/AriaLyy/DownloadUtil/blob/master/img/sing_upload.gif) ## 性能 ![性能展示](https://github.com/AriaLyy/DownloadUtil/blob/master/img/performance.png) *** ## 使用 -### 一、添加权限 +由于Aria涉及到文件和网络的操作,因此需要你在manifest文件中添加以下权限 ```xml ``` -### 二、只需要以下参数,你便能很简单的使用Aria下载文件了 -```java - Aria.whit(this) - .load(DOWNLOAD_URL) //下载地址,必填 - .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk") //文件保存路径,必填 - .setDownloadName("test.apk") //文件名,必填 - .start(); -``` -### 三、为了能接收到Aria传递的数据,你需要把你的Activity或fragment注册到Aria管理器中,注册的方式很简单,在onResume -```java -@Override protected void onResume() { - super.onResume(); - Aria.whit(this).addSchedulerListener(new MySchedulerListener()); - } -``` -### 四、通过下载链接,你还能使用Aria执行很多操作,如: -Aria支持https下载,如果你希望使用自己的ca证书,那么你需要进行[Aria https证书配置](#https证书配置) -- 添加任务(不进行下载) +## 使用Aria进行下载 +* 添加任务(不进行下载),当其他下载任务完成时,将自动下载等待中的任务 ```java - Aria.whit(this).load(DOWNLOAD_URL) - .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk") //文件保存路径,必填 - .setDownloadName("test.apk") //文件名,必填 - .add(); - ``` -- 启动下载 - - ```java - Aria.whit(this).load(DOWNLOAD_URL).start(); + Aria.download(this) + .load(DOWNLOAD_URL) + .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk") //文件保存路径 + .add(); ``` -- 暂停下载 - ```java - Aria.whit(this).load(DOWNLOAD_URL).stop(); - ``` -- 恢复下载 +* 下载 ```java - Aria.whit(this).load(DOWNLOAD_URL).resume(); + Aria.download(this) + .load(DOWNLOAD_URL) //读取下载地址 + .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk") //设置文件保存的完整路径 + .start(); //启动下载 ``` -- 取消下载 +* 暂停 ```java - Aria.whit(this).load(DOWNLOAD_URL).cancel(); + Aria.download(this).load(DOWNLOAD_URL).pause(); ``` -- 获取当前下载进度 +* 恢复下载 ```java - Aria.whit(this).load(DOWNLOAD_URL).getCurrentProgress(); + Aria.download(this).load(DOWNLOAD_URL).resume(); ``` -- 获取文件大小 +* 取消下载 ```java - Aria.whit(this).load(DOWNLOAD_URL).getFileSize(); + Aria.download(this).load(DOWNLOAD_URL).cancel(); ``` -### 五、关于Aria,你还需要知道的一些东西 -- 设置下载任务数,Aria默认下载任务为**2** +### 二、如果你希望读取下载进度或下载信息,那么你需要创建事件类,并在onResume(Activity、Fragment)或构造函数(Dialog、PopupWindow),将该事件类注册到Aria管理器。 +* 创建事件类 ```java - Aria.get(getContext()).setMaxDownloadNum(num); + final static class MySchedulerListener extends Aria.DownloadSchedulerListener{ + @Override public void onTaskPre(DownloadTask task) { + super.onTaskPre(task); + } + + @Override public void onTaskStop(DownloadTask task) { + super.onTaskStop(task); + } + + @Override public void onTaskCancel(DownloadTask task) { + super.onTaskCancel(task); + } + + @Override public void onTaskRunning(DownloadTask task) { + super.onTaskRunning(task); + } + } ``` -- 停止所有下载 - ```java - Aria.get(this).stopAllTask(); - ``` -- 设置失败重试次数,从事次数不能少于 1 +* 将事件注册到Aria ```java - Aria.get(this).setReTryNum(10); + @Override protected void onResume() { + super.onResume(); + Aria.whit(this).addSchedulerListener(new MySchedulerListener()); + } ``` -- 设置失败重试间隔,重试间隔不能小于 5000ms - ```java - Aria.get(this).setReTryInterval(5000); - ``` -- 设置是否打开广播,如果你需要在Service后台获取下载完成情况,那么你需要打开Aria广播,[Aria广播配置](https://github.com/AriaLyy/Aria/blob/v_2.0/BroadCast.md) +### 关于下载的其它api +[Download API](https://github.com/AriaLyy/Aria/blob/master/DownloadApi.md) - ```java - Aria.get(this).openBroadcast(true); - ``` +**tips:为了防止内存泄露的情况,事件类需要使用staic进行修饰** -### https证书配置 - + 将你的证书导入`assets`目录 - + 调用以下代码配置ca证书相关信息 +## 上传 + * 添加任务(只添加,不上传) - ```java - /** - * 设置CA证书信息 - * - * @param caAlias ca证书别名 - * @param caPath assets 文件夹下的ca证书完整路径 - */ - Aria.get(this).setCAInfo("caAlias","caPath"); - ``` + ```java + Aria.upload(this) + .load(filePath) //文件路径 + .setUploadUrl(uploadUrl) //上传路径 + .setAttachment(fileKey) //服务器读取文件的key + .add(); + ``` -*** + * 上传 -## 开发日志 - + v_2.4.4 修复不支持断点的下载链接拿不到文件大小的问题 - + v_2.4.3 修复404链接卡顿的问题 - + v_2.4.2 修复失败重试无效的bug - + v_2.4.1 修复下载慢的问题,修复application、service 不能使用的问题 - + v_2.4.0 支持https链接下载 - + v_2.3.8 修复数据错乱的bug、添加fragment支持 - + v_2.3.6 添加dialog、popupWindow支持 - + v_2.3.3 添加断点支持、修改下载逻辑,让使用更加简单、修复一个内存泄露的bug - + v_2.3.1 重命名为Aria,下载流程简化 - + v_2.1.1 增加,选择最大下载任务数接口 + ```java + Aria.upload(this) + .load(filePath) //文件路径 + .setUploadUrl(uploadUrl) //上传路径 + .setAttachment(fileKey) //服务器读取文件的key + .start(); + ``` + * 取消上传 + + ```java + Aria.upload(this) + .load(filePath) + .cancel(); + ``` ## 其他 -有任何问题,可以在[issues](https://github.com/AriaLyy/Aria/issues)给我留言反馈。 + 有任何问题,可以在[issues](https://github.com/AriaLyy/Aria/issues)给我留言反馈。 + +*** + +## 开发日志 + + v_3.0.0 添加上传任务支持,修复一些已发现的bug + + v_2.4.4 修复不支持断点的下载链接拿不到文件大小的问题 + + v_2.4.3 修复404链接卡顿的问题 + + v_2.4.2 修复失败重试无效的bug + + v_2.4.1 修复下载慢的问题,修复application、service 不能使用的问题 + + v_2.4.0 支持https链接下载 + + v_2.3.8 修复数据错乱的bug、添加fragment支持 + + v_2.3.6 添加dialog、popupWindow支持 + + v_2.3.3 添加断点支持、修改下载逻辑,让使用更加简单、修复一个内存泄露的bug + + v_2.3.1 重命名为Aria,下载流程简化 + + v_2.1.1 增加,选择最大下载任务数接口 License ------- diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 681656f0..8e18878f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -13,7 +13,6 @@ android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme.NoActionBar"> - @@ -24,10 +23,14 @@ - - - - + + + + + + + + diff --git a/app/src/main/java/com/arialyy/simple/MainActivity.java b/app/src/main/java/com/arialyy/simple/MainActivity.java index 0df80bbc..f67abcc4 100644 --- a/app/src/main/java/com/arialyy/simple/MainActivity.java +++ b/app/src/main/java/com/arialyy/simple/MainActivity.java @@ -16,99 +16,38 @@ package com.arialyy.simple; -import android.Manifest; import android.content.Intent; -import android.os.Build; import android.os.Bundle; import android.support.v7.widget.Toolbar; -import android.view.Gravity; import android.view.View; -import android.widget.Button; import butterknife.Bind; -import com.arialyy.frame.permission.OnPermissionCallback; -import com.arialyy.frame.permission.PermissionManager; -import com.arialyy.frame.util.show.T; +import butterknife.OnClick; import com.arialyy.simple.base.BaseActivity; import com.arialyy.simple.databinding.ActivityMainBinding; -import com.arialyy.simple.dialog_task.DownloadDialog; -import com.arialyy.simple.fragment_task.FragmentActivity; -import com.arialyy.simple.multi_task.MultiTaskActivity; -import com.arialyy.simple.notification.SimpleNotification; -import com.arialyy.simple.pop_task.DownloadPopupWindow; -import com.arialyy.simple.single_task.SingleTaskActivity; +import com.arialyy.simple.download.DownloadActivity; +import com.arialyy.simple.upload.UploadActivity; /** - * Created by Lyy on 2016/10/13. + * Created by Aria.Lao on 2017/3/1. */ public class MainActivity extends BaseActivity { - @Bind(R.id.toolbar) Toolbar mBar; - @Bind(R.id.single_task) Button mSigleBt; - @Bind(R.id.multi_task) Button mMultiBt; - @Bind(R.id.dialog_task) Button mDialogBt; - @Bind(R.id.pop_task) Button mPopBt; - @Override protected int setLayoutId() { - return R.layout.activity_main; - } + @Bind(R.id.toolbar) Toolbar mBar; @Override protected void init(Bundle savedInstanceState) { super.init(savedInstanceState); - setSupportActionBar(mBar); - mBar.setTitle("多线程多任务下载"); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - setEnable(true); - } else { //6.0处理 - boolean hasPermission = PermissionManager.getInstance() - .checkPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE); - if (hasPermission) { - setEnable(true); - } else { - setEnable(false); - PermissionManager.getInstance().requestPermission(this, new OnPermissionCallback() { - @Override public void onSuccess(String... permissions) { - setEnable(true); - } + mBar.setTitle("Aria Demo"); + } - @Override public void onFail(String... permissions) { - T.showShort(MainActivity.this, "没有文件读写权限"); - setEnable(false); - } - }, Manifest.permission.WRITE_EXTERNAL_STORAGE); - } - } + @Override protected int setLayoutId() { + return R.layout.activity_main; } - private void setEnable(boolean enable) { - mSigleBt.setEnabled(enable); - mMultiBt.setEnabled(enable); - mDialogBt.setEnabled(enable); - mPopBt.setEnabled(enable); + @OnClick(R.id.download) public void downloadDemo() { + startActivity(new Intent(this, DownloadActivity.class)); } - public void onClick(View view) { - switch (view.getId()) { - case R.id.single_task: - startActivity(new Intent(this, SingleTaskActivity.class)); - break; - case R.id.multi_task: - startActivity(new Intent(this, MultiTaskActivity.class)); - break; - case R.id.dialog_task: - DownloadDialog dialog = new DownloadDialog(this); - dialog.show(); - break; - case R.id.pop_task: - DownloadPopupWindow pop = new DownloadPopupWindow(this); - //pop.showAsDropDown(mRootView); - pop.showAtLocation(mRootView, Gravity.CENTER_VERTICAL, 0, 0); - break; - case R.id.fragment_task: - startActivity(new Intent(this, FragmentActivity.class)); - break; - case R.id.notification: - SimpleNotification notification = new SimpleNotification(this); - notification.start(); - break; - } + @OnClick(R.id.upload) public void uploadDemo() { + startActivity(new Intent(this, UploadActivity.class)); } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/arialyy/simple/base/BaseApplication.java b/app/src/main/java/com/arialyy/simple/base/BaseApplication.java index 39f4aea0..117a34dd 100644 --- a/app/src/main/java/com/arialyy/simple/base/BaseApplication.java +++ b/app/src/main/java/com/arialyy/simple/base/BaseApplication.java @@ -14,11 +14,9 @@ * limitations under the License. */ - package com.arialyy.simple.base; import android.app.Application; -import com.arialyy.aria.core.DownloadManager; import com.arialyy.frame.core.AbsFrame; /** @@ -28,6 +26,5 @@ public class BaseApplication extends Application { @Override public void onCreate() { super.onCreate(); AbsFrame.init(this); - //DownloadManager.init(this); } } \ No newline at end of file diff --git a/app/src/main/java/com/arialyy/simple/base/BaseDialog.java b/app/src/main/java/com/arialyy/simple/base/BaseDialog.java index 2cc995e6..6233dad4 100644 --- a/app/src/main/java/com/arialyy/simple/base/BaseDialog.java +++ b/app/src/main/java/com/arialyy/simple/base/BaseDialog.java @@ -14,7 +14,6 @@ * limitations under the License. */ - package com.arialyy.simple.base; import android.databinding.ViewDataBinding; @@ -24,9 +23,9 @@ import com.arialyy.frame.core.AbsDialogFragment; /** * Created by “AriaLyy@outlook.com” on 2016/11/14. */ -public abstract class BaseDialog extends AbsDialogFragment{ +public abstract class BaseDialog extends AbsDialogFragment { - protected BaseDialog(Object obj){ + protected BaseDialog(Object obj) { super(obj); } diff --git a/app/src/main/java/com/arialyy/simple/base/BaseModule.java b/app/src/main/java/com/arialyy/simple/base/BaseModule.java index 5806c72d..223a9b65 100644 --- a/app/src/main/java/com/arialyy/simple/base/BaseModule.java +++ b/app/src/main/java/com/arialyy/simple/base/BaseModule.java @@ -14,7 +14,6 @@ * limitations under the License. */ - package com.arialyy.simple.base; import android.content.Context; diff --git a/app/src/main/java/com/arialyy/simple/download/DownloadActivity.java b/app/src/main/java/com/arialyy/simple/download/DownloadActivity.java new file mode 100644 index 00000000..04084e06 --- /dev/null +++ b/app/src/main/java/com/arialyy/simple/download/DownloadActivity.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.arialyy.simple.download; + +import android.Manifest; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.support.v7.widget.Toolbar; +import android.view.Gravity; +import android.view.View; +import android.widget.Button; +import butterknife.Bind; +import com.arialyy.frame.permission.OnPermissionCallback; +import com.arialyy.frame.permission.PermissionManager; +import com.arialyy.frame.util.show.T; +import com.arialyy.simple.R; +import com.arialyy.simple.base.BaseActivity; +import com.arialyy.simple.databinding.ActivityDownloadMeanBinding; +import com.arialyy.simple.download.fragment_download.FragmentActivity; +import com.arialyy.simple.download.multi_download.MultiTaskActivity; +import com.arialyy.simple.download.service_download.DownloadService; + +/** + * Created by Lyy on 2016/10/13. + */ +public class DownloadActivity extends BaseActivity { + @Bind(R.id.toolbar) Toolbar mBar; + @Bind(R.id.single_task) Button mSigleBt; + @Bind(R.id.multi_task) Button mMultiBt; + @Bind(R.id.dialog_task) Button mDialogBt; + @Bind(R.id.pop_task) Button mPopBt; + + @Override protected int setLayoutId() { + return R.layout.activity_download_mean; + } + + @Override protected void init(Bundle savedInstanceState) { + super.init(savedInstanceState); + setSupportActionBar(mBar); + mBar.setTitle("多线程多任务下载"); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + setEnable(true); + } else { //6.0处理 + boolean hasPermission = PermissionManager.getInstance() + .checkPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE); + if (hasPermission) { + setEnable(true); + } else { + setEnable(false); + PermissionManager.getInstance().requestPermission(this, new OnPermissionCallback() { + @Override public void onSuccess(String... permissions) { + setEnable(true); + } + + @Override public void onFail(String... permissions) { + T.showShort(DownloadActivity.this, "没有文件读写权限"); + setEnable(false); + } + }, Manifest.permission.WRITE_EXTERNAL_STORAGE); + } + } + } + + private void setEnable(boolean enable) { + mSigleBt.setEnabled(enable); + mMultiBt.setEnabled(enable); + mDialogBt.setEnabled(enable); + mPopBt.setEnabled(enable); + } + + public void onClick(View view) { + switch (view.getId()) { + case R.id.service: + startService(new Intent(this, DownloadService.class)); + break; + case R.id.single_task: + startActivity(new Intent(this, SingleTaskActivity.class)); + break; + case R.id.multi_task: + startActivity(new Intent(this, MultiTaskActivity.class)); + break; + case R.id.dialog_task: + DownloadDialog dialog = new DownloadDialog(this); + dialog.show(); + break; + case R.id.pop_task: + DownloadPopupWindow pop = new DownloadPopupWindow(this); + //pop.showAsDropDown(mRootView); + pop.showAtLocation(mRootView, Gravity.CENTER_VERTICAL, 0, 0); + break; + case R.id.fragment_task: + startActivity(new Intent(this, FragmentActivity.class)); + break; + case R.id.notification: + SimpleNotification notification = new SimpleNotification(this); + notification.start(); + break; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/arialyy/simple/dialog_task/DownloadDialog.java b/app/src/main/java/com/arialyy/simple/download/DownloadDialog.java similarity index 55% rename from app/src/main/java/com/arialyy/simple/dialog_task/DownloadDialog.java rename to app/src/main/java/com/arialyy/simple/download/DownloadDialog.java index 8f6db116..c88904b6 100644 --- a/app/src/main/java/com/arialyy/simple/dialog_task/DownloadDialog.java +++ b/app/src/main/java/com/arialyy/simple/download/DownloadDialog.java @@ -1,4 +1,20 @@ -package com.arialyy.simple.dialog_task; +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.arialyy.simple.download; import android.content.Context; import android.os.Environment; @@ -7,10 +23,10 @@ import android.widget.Button; import android.widget.TextView; import butterknife.Bind; import butterknife.OnClick; -import com.arialyy.aria.core.AMTarget; +import com.arialyy.aria.core.download.DownloadTarget; import com.arialyy.aria.core.Aria; -import com.arialyy.aria.core.DownloadEntity; -import com.arialyy.aria.core.task.Task; +import com.arialyy.aria.core.download.DownloadEntity; +import com.arialyy.aria.core.download.DownloadTask; import com.arialyy.aria.util.CommonUtil; import com.arialyy.frame.core.AbsDialog; import com.arialyy.simple.R; @@ -21,11 +37,11 @@ import com.arialyy.simple.widget.HorizontalProgressBarWithNumber; */ public class DownloadDialog extends AbsDialog { @Bind(R.id.progressBar) HorizontalProgressBarWithNumber mPb; - @Bind(R.id.start) Button mStart; - @Bind(R.id.stop) Button mStop; - @Bind(R.id.cancel) Button mCancel; - @Bind(R.id.size) TextView mSize; - @Bind(R.id.speed) TextView mSpeed; + @Bind(R.id.start) Button mStart; + @Bind(R.id.stop) Button mStop; + @Bind(R.id.cancel) Button mCancel; + @Bind(R.id.size) TextView mSize; + @Bind(R.id.speed) TextView mSpeed; private static final String DOWNLOAD_URL = "http://static.gaoshouyou.com/d/3a/93/573ae1db9493a801c24bf66128b11e39.apk"; @@ -40,17 +56,17 @@ public class DownloadDialog extends AbsDialog { } private void init() { - if (Aria.get(this).taskExists(DOWNLOAD_URL)) { - AMTarget target = Aria.whit(this).load(DOWNLOAD_URL); - int p = (int) (target.getCurrentProgress() * 100 / target.getFileSize()); + if (Aria.download(this).taskExists(DOWNLOAD_URL)) { + DownloadTarget target = Aria.download(this).load(DOWNLOAD_URL); + int p = (int) (target.getCurrentProgress() * 100 / target.getFileSize()); mPb.setProgress(p); } - Aria.whit(this).addSchedulerListener(new MyDialogDownloadCallback()); - DownloadEntity entity = Aria.get(this).getDownloadEntity(DOWNLOAD_URL); + Aria.download(this).addSchedulerListener(new MyDialogDownloadCallback()); + DownloadEntity entity = Aria.download(this).getDownloadEntity(DOWNLOAD_URL); if (entity != null) { mSize.setText(CommonUtil.formatFileSize(entity.getFileSize())); int state = entity.getState(); - setBtState(state != DownloadEntity.STATE_DOWNLOAD_ING); + setBtState(state != DownloadEntity.STATE_RUNNING); } else { setBtState(true); } @@ -59,17 +75,16 @@ public class DownloadDialog extends AbsDialog { @OnClick({ R.id.start, R.id.stop, R.id.cancel }) public void onClick(View view) { switch (view.getId()) { case R.id.start: - Aria.whit(this) + Aria.download(this) .load(DOWNLOAD_URL) .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/daialog.apk") - .setDownloadName("daialog.apk") .start(); break; case R.id.stop: - Aria.whit(this).load(DOWNLOAD_URL).stop(); + Aria.download(this).load(DOWNLOAD_URL).pause(); break; case R.id.cancel: - Aria.whit(this).load(DOWNLOAD_URL).cancel(); + Aria.download(this).load(DOWNLOAD_URL).cancel(); break; } } @@ -84,31 +99,31 @@ public class DownloadDialog extends AbsDialog { mStop.setEnabled(!startEnable); } - private class MyDialogDownloadCallback extends Aria.SimpleSchedulerListener { + private class MyDialogDownloadCallback extends Aria.DownloadSchedulerListener { - @Override public void onTaskPre(Task task) { + @Override public void onTaskPre(DownloadTask task) { super.onTaskPre(task); mSize.setText(CommonUtil.formatFileSize(task.getFileSize())); setBtState(false); } - @Override public void onTaskStop(Task task) { + @Override public void onTaskStop(DownloadTask task) { super.onTaskStop(task); setBtState(true); mSpeed.setText("0.0kb/s"); } - @Override public void onTaskCancel(Task task) { + @Override public void onTaskCancel(DownloadTask task) { super.onTaskCancel(task); setBtState(true); mPb.setProgress(0); mSpeed.setText("0.0kb/s"); } - @Override public void onTaskRunning(Task task) { + @Override public void onTaskRunning(DownloadTask task) { super.onTaskRunning(task); long current = task.getCurrentProgress(); - long len = task.getFileSize(); + long len = task.getFileSize(); if (len == 0) { mPb.setProgress(0); } else { diff --git a/app/src/main/java/com/arialyy/simple/module/DownloadModule.java b/app/src/main/java/com/arialyy/simple/download/DownloadModule.java similarity index 91% rename from app/src/main/java/com/arialyy/simple/module/DownloadModule.java rename to app/src/main/java/com/arialyy/simple/download/DownloadModule.java index b9ac5582..aa9dab49 100644 --- a/app/src/main/java/com/arialyy/simple/module/DownloadModule.java +++ b/app/src/main/java/com/arialyy/simple/download/DownloadModule.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.arialyy.simple.module; +package com.arialyy.simple.download; import android.content.BroadcastReceiver; import android.content.Context; @@ -23,14 +23,13 @@ import android.content.IntentFilter; import android.os.Environment; import android.os.Handler; import com.arialyy.aria.core.Aria; -import com.arialyy.aria.core.DownloadEntity; +import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.util.CommonUtil; import com.arialyy.frame.util.AndroidUtils; import com.arialyy.frame.util.StringUtil; import com.arialyy.frame.util.show.L; import com.arialyy.simple.R; -import com.arialyy.simple.multi_task.FileListEntity; -import com.arialyy.simple.single_task.SingleTaskActivity; +import com.arialyy.simple.download.multi_download.FileListEntity; import com.arialyy.simple.base.BaseModule; import java.io.File; import java.util.ArrayList; @@ -45,9 +44,12 @@ public class DownloadModule extends BaseModule { public DownloadModule(Context context) { super(context); - mTestDownloadUrl.add("http://static.gaoshouyou.com/d/e6/f5/4de6329f9cf5dc3a1d1e6bbcca0d003c.apk"); - mTestDownloadUrl.add("http://static.gaoshouyou.com/d/6e/e5/ff6ecaaf45e532e6d07747af82357472.apk"); - mTestDownloadUrl.add("http://static.gaoshouyou.com/d/36/69/2d3699acfa69e9632262442c46516ad8.apk"); + mTestDownloadUrl.add( + "http://static.gaoshouyou.com/d/e6/f5/4de6329f9cf5dc3a1d1e6bbcca0d003c.apk"); + mTestDownloadUrl.add( + "http://static.gaoshouyou.com/d/6e/e5/ff6ecaaf45e532e6d07747af82357472.apk"); + mTestDownloadUrl.add( + "http://static.gaoshouyou.com/d/36/69/2d3699acfa69e9632262442c46516ad8.apk"); } public String getRadomUrl() { @@ -56,7 +58,7 @@ public class DownloadModule extends BaseModule { return mTestDownloadUrl.get(i); } - public DownloadEntity createRandomDownloadEntity(){ + public DownloadEntity createRandomDownloadEntity() { return createDownloadEntity(getRadomUrl()); } @@ -86,7 +88,7 @@ public class DownloadModule extends BaseModule { String[] urls = getContext().getResources().getStringArray(R.array.test_apk_download_url); List list = new ArrayList<>(); for (String url : urls) { - DownloadEntity entity = Aria.get(getContext()).getDownloadEntity(url); + DownloadEntity entity = Aria.download(getContext()).getDownloadEntity(url); if (entity == null) { entity = createDownloadEntity(url); } diff --git a/app/src/main/java/com/arialyy/simple/pop_task/DownloadPopupWindow.java b/app/src/main/java/com/arialyy/simple/download/DownloadPopupWindow.java similarity index 56% rename from app/src/main/java/com/arialyy/simple/pop_task/DownloadPopupWindow.java rename to app/src/main/java/com/arialyy/simple/download/DownloadPopupWindow.java index 444d6767..450f3004 100644 --- a/app/src/main/java/com/arialyy/simple/pop_task/DownloadPopupWindow.java +++ b/app/src/main/java/com/arialyy/simple/download/DownloadPopupWindow.java @@ -1,4 +1,20 @@ -package com.arialyy.simple.pop_task; +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.arialyy.simple.download; import android.content.Context; import android.graphics.Color; @@ -9,10 +25,10 @@ import android.widget.Button; import android.widget.TextView; import butterknife.Bind; import butterknife.OnClick; -import com.arialyy.aria.core.AMTarget; +import com.arialyy.aria.core.download.DownloadTarget; import com.arialyy.aria.core.Aria; -import com.arialyy.aria.core.DownloadEntity; -import com.arialyy.aria.core.task.Task; +import com.arialyy.aria.core.download.DownloadEntity; +import com.arialyy.aria.core.download.DownloadTask; import com.arialyy.aria.util.CommonUtil; import com.arialyy.frame.core.AbsPopupWindow; import com.arialyy.simple.R; @@ -23,11 +39,11 @@ import com.arialyy.simple.widget.HorizontalProgressBarWithNumber; */ public class DownloadPopupWindow extends AbsPopupWindow { @Bind(R.id.progressBar) HorizontalProgressBarWithNumber mPb; - @Bind(R.id.start) Button mStart; - @Bind(R.id.stop) Button mStop; - @Bind(R.id.cancel) Button mCancel; - @Bind(R.id.size) TextView mSize; - @Bind(R.id.speed) TextView mSpeed; + @Bind(R.id.start) Button mStart; + @Bind(R.id.stop) Button mStop; + @Bind(R.id.cancel) Button mCancel; + @Bind(R.id.size) TextView mSize; + @Bind(R.id.speed) TextView mSpeed; private static final String DOWNLOAD_URL = "http://static.gaoshouyou.com/d/3a/93/573ae1db9493a801c24bf66128b11e39.apk"; @@ -42,17 +58,17 @@ public class DownloadPopupWindow extends AbsPopupWindow { } private void initWidget() { - if (Aria.get(this).taskExists(DOWNLOAD_URL)) { - AMTarget target = Aria.whit(this).load(DOWNLOAD_URL); - int p = (int) (target.getCurrentProgress() * 100 / target.getFileSize()); + if (Aria.download(this).taskExists(DOWNLOAD_URL)) { + DownloadTarget target = Aria.download(this).load(DOWNLOAD_URL); + int p = (int) (target.getCurrentProgress() * 100 / target.getFileSize()); mPb.setProgress(p); } - Aria.whit(this).addSchedulerListener(new MyDialogDownloadCallback()); - DownloadEntity entity = Aria.get(this).getDownloadEntity(DOWNLOAD_URL); + Aria.download(this).addSchedulerListener(new MyDialogDownloadCallback()); + DownloadEntity entity = Aria.download(this).getDownloadEntity(DOWNLOAD_URL); if (entity != null) { mSize.setText(CommonUtil.formatFileSize(entity.getFileSize())); int state = entity.getState(); - setBtState(state != DownloadEntity.STATE_DOWNLOAD_ING); + setBtState(state != DownloadEntity.STATE_RUNNING); } else { setBtState(true); } @@ -61,17 +77,16 @@ public class DownloadPopupWindow extends AbsPopupWindow { @OnClick({ R.id.start, R.id.stop, R.id.cancel }) public void onClick(View view) { switch (view.getId()) { case R.id.start: - Aria.whit(this) + Aria.download(this) .load(DOWNLOAD_URL) .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/daialog.apk") - .setDownloadName("daialog.apk") .start(); break; case R.id.stop: - Aria.whit(this).load(DOWNLOAD_URL).stop(); + Aria.download(this).load(DOWNLOAD_URL).pause(); break; case R.id.cancel: - Aria.whit(this).load(DOWNLOAD_URL).cancel(); + Aria.download(this).load(DOWNLOAD_URL).cancel(); break; } } @@ -86,31 +101,31 @@ public class DownloadPopupWindow extends AbsPopupWindow { mStop.setEnabled(!startEnable); } - private class MyDialogDownloadCallback extends Aria.SimpleSchedulerListener { + private class MyDialogDownloadCallback extends Aria.DownloadSchedulerListener { - @Override public void onTaskPre(Task task) { + @Override public void onTaskPre(DownloadTask task) { super.onTaskPre(task); mSize.setText(CommonUtil.formatFileSize(task.getFileSize())); setBtState(false); } - @Override public void onTaskStop(Task task) { + @Override public void onTaskStop(DownloadTask task) { super.onTaskStop(task); setBtState(true); mSpeed.setText("0.0kb/s"); } - @Override public void onTaskCancel(Task task) { + @Override public void onTaskCancel(DownloadTask task) { super.onTaskCancel(task); setBtState(true); mPb.setProgress(0); mSpeed.setText("0.0kb/s"); } - @Override public void onTaskRunning(Task task) { + @Override public void onTaskRunning(DownloadTask task) { super.onTaskRunning(task); long current = task.getCurrentProgress(); - long len = task.getFileSize(); + long len = task.getFileSize(); if (len == 0) { mPb.setProgress(0); } else { diff --git a/app/src/main/java/com/arialyy/simple/notification/SimpleNotification.java b/app/src/main/java/com/arialyy/simple/download/SimpleNotification.java similarity index 62% rename from app/src/main/java/com/arialyy/simple/notification/SimpleNotification.java rename to app/src/main/java/com/arialyy/simple/download/SimpleNotification.java index 3d11fd69..9adcd304 100644 --- a/app/src/main/java/com/arialyy/simple/notification/SimpleNotification.java +++ b/app/src/main/java/com/arialyy/simple/download/SimpleNotification.java @@ -1,13 +1,27 @@ -package com.arialyy.simple.notification; +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.arialyy.simple.download; import android.app.NotificationManager; import android.content.Context; import android.os.Environment; import android.support.v4.app.NotificationCompat; import com.arialyy.aria.core.Aria; -import com.arialyy.aria.core.task.Task; -import com.arialyy.frame.util.show.L; -import com.arialyy.frame.util.show.T; +import com.arialyy.aria.core.download.DownloadTask; import com.arialyy.simple.R; /** @@ -36,11 +50,11 @@ public class SimpleNotification { .setProgress(100, 0, false) .setSmallIcon(R.mipmap.ic_launcher); mManager.notify(mNotifiyId, mBuilder.build()); - Aria.whit(mContext).addSchedulerListener(new DownloadCallback(mBuilder, mManager)); + Aria.download(mContext).addSchedulerListener(new DownloadCallback(mBuilder, mManager)); } public void start() { - Aria.whit(mContext) + Aria.download(mContext) .load(DOWNLOAD_URL) .setDownloadName("notification_test.apk") .setDownloadPath( @@ -49,10 +63,10 @@ public class SimpleNotification { } public void stop() { - Aria.whit(mContext).load(DOWNLOAD_URL).stop(); + Aria.download(mContext).load(DOWNLOAD_URL).pause(); } - private static class DownloadCallback extends Aria.SimpleSchedulerListener { + private static class DownloadCallback extends Aria.DownloadSchedulerListener { NotificationCompat.Builder mBuilder; NotificationManager mManager; @@ -61,19 +75,19 @@ public class SimpleNotification { mManager = manager; } - @Override public void onTaskStart(Task task) { + @Override public void onTaskStart(DownloadTask task) { super.onTaskStart(task); } - @Override public void onTaskPre(Task task) { + @Override public void onTaskPre(DownloadTask task) { super.onTaskPre(task); } - @Override public void onTaskStop(Task task) { + @Override public void onTaskStop(DownloadTask task) { super.onTaskStop(task); } - @Override public void onTaskRunning(Task task) { + @Override public void onTaskRunning(DownloadTask task) { super.onTaskRunning(task); long len = task.getFileSize(); int p = (int) (task.getCurrentProgress() * 100 / len); @@ -83,7 +97,7 @@ public class SimpleNotification { } } - @Override public void onTaskComplete(Task task) { + @Override public void onTaskComplete(DownloadTask task) { super.onTaskComplete(task); if (mBuilder != null) { mBuilder.setProgress(100, 100, false); @@ -91,7 +105,7 @@ public class SimpleNotification { } } - @Override public void onTaskCancel(Task task) { + @Override public void onTaskCancel(DownloadTask task) { super.onTaskCancel(task); } } diff --git a/app/src/main/java/com/arialyy/simple/single_task/SingleTaskActivity.java b/app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java similarity index 65% rename from app/src/main/java/com/arialyy/simple/single_task/SingleTaskActivity.java rename to app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java index ba0fa003..ff595bbb 100644 --- a/app/src/main/java/com/arialyy/simple/single_task/SingleTaskActivity.java +++ b/app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.arialyy.simple.single_task; +package com.arialyy.simple.download; import android.content.BroadcastReceiver; import android.content.Context; @@ -26,46 +26,47 @@ 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.RadioGroup; import android.widget.TextView; import android.widget.Toast; import butterknife.Bind; -import com.arialyy.aria.core.AMTarget; +import com.arialyy.aria.core.download.DownloadTarget; import com.arialyy.aria.core.Aria; -import com.arialyy.aria.core.DownloadEntity; -import com.arialyy.aria.core.task.DownloadUtil; -import com.arialyy.aria.core.task.IDownloadListener; -import com.arialyy.aria.core.task.Task; +import com.arialyy.aria.core.download.DownloadEntity; +import com.arialyy.aria.core.download.DownloadTask; import com.arialyy.aria.util.CommonUtil; +import com.arialyy.aria.util.Speed; import com.arialyy.frame.util.show.L; +import com.arialyy.frame.util.show.T; import com.arialyy.simple.R; import com.arialyy.simple.base.BaseActivity; import com.arialyy.simple.databinding.ActivitySingleBinding; import com.arialyy.simple.widget.HorizontalProgressBarWithNumber; public class SingleTaskActivity extends BaseActivity { - public static final int DOWNLOAD_PRE = 0x01; - public static final int DOWNLOAD_STOP = 0x02; - public static final int DOWNLOAD_FAILE = 0x03; - public static final int DOWNLOAD_CANCEL = 0x04; - public static final int DOWNLOAD_RESUME = 0x05; - public static final int DOWNLOAD_COMPLETE = 0x06; - public static final int DOWNLOAD_RUNNING = 0x07; - - private static final String DOWNLOAD_URL = + public static final int DOWNLOAD_PRE = 0x01; + public static final int DOWNLOAD_STOP = 0x02; + public static final int DOWNLOAD_FAILE = 0x03; + public static final int DOWNLOAD_CANCEL = 0x04; + public static final int DOWNLOAD_RESUME = 0x05; + public static final int DOWNLOAD_COMPLETE = 0x06; + public static final int DOWNLOAD_RUNNING = 0x07; + + private static final String DOWNLOAD_URL = //"http://kotlinlang.org/docs/kotlin-docs.pdf"; //"https://atom-installer.github.com/v1.13.0/AtomSetup.exe?s=1484074138&ext=.exe"; - "http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk"; - //"http://ox.konsung.net:5555/ksdc-web/download/downloadFile/?fileName=ksdc_1.0.2.apk&rRange=0-"; + //"http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk"; + //不支持断点的链接 + "http://ox.konsung.net:5555/ksdc-web/download/downloadFile/?fileName=ksdc_1.0.2.apk&rRange=0-"; @Bind(R.id.progressBar) HorizontalProgressBarWithNumber mPb; - @Bind(R.id.start) Button mStart; - @Bind(R.id.stop) Button mStop; - @Bind(R.id.cancel) Button mCancel; - @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; + @Bind(R.id.start) Button mStart; + @Bind(R.id.stop) Button mStop; + @Bind(R.id.cancel) Button mCancel; + @Bind(R.id.size) TextView mSize; + @Bind(R.id.toolbar) Toolbar toolbar; + @Bind(R.id.speed) TextView mSpeed; + @Bind(R.id.speeds) RadioGroup mRg; + private DownloadEntity mEntity; private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); @@ -80,7 +81,7 @@ public class SingleTaskActivity extends BaseActivity { super.handleMessage(msg); switch (msg.what) { case DOWNLOAD_RUNNING: - Task task = (Task) msg.obj; + DownloadTask task = (DownloadTask) msg.obj; long current = task.getCurrentProgress(); long len = task.getFileSize(); if (len == 0) { @@ -143,7 +144,7 @@ public class SingleTaskActivity extends BaseActivity { @Override protected void onResume() { super.onResume(); - Aria.whit(this).addSchedulerListener(new MySchedulerListener()); + Aria.download(this).addSchedulerListener(new MySchedulerListener()); //registerReceiver(mReceiver, getModule(DownloadModule.class).getDownloadFilter()); } @@ -165,11 +166,38 @@ public class SingleTaskActivity extends BaseActivity { } private void init() { - if (Aria.get(this).taskExists(DOWNLOAD_URL)) { - AMTarget target = Aria.whit(this).load(DOWNLOAD_URL); - int p = (int) (target.getCurrentProgress() * 100 / target.getFileSize()); + if (Aria.download(this).taskExists(DOWNLOAD_URL)) { + DownloadTarget target = Aria.download(this).load(DOWNLOAD_URL); + int p = (int) (target.getCurrentProgress() * 100 / target.getFileSize()); mPb.setProgress(p); } + mRg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { + @Override public void onCheckedChanged(RadioGroup group, int checkedId) { + switch (checkedId) { + case 1: + Aria.get(this).setMaxSpeed(Speed.KB_256); + break; + case 2: + Aria.get(this).setMaxSpeed(Speed.KB_512); + break; + case 3: + Aria.get(this).setMaxSpeed(Speed.MB_1); + break; + case 4: + Aria.get(this).setMaxSpeed(Speed.MB_2); + break; + case 5: + Aria.get(this).setMaxSpeed(Speed.MAX); + break; + } + stop(); + new Handler().postDelayed(new Runnable() { + @Override public void run() { + start(); + } + }, 2000); + } + }); } public void onClick(View view) { @@ -192,53 +220,58 @@ public class SingleTaskActivity extends BaseActivity { } private void resume() { - Aria.whit(this).load(DOWNLOAD_URL).resume(); + Aria.download(this).load(DOWNLOAD_URL).resume(); } private void start() { - Aria.whit(this) + Aria.download(this) .load(DOWNLOAD_URL) .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk") - .setDownloadName("test.apk") .start(); } private void stop() { - Aria.whit(this).load(DOWNLOAD_URL).stop(); + Aria.download(this).load(DOWNLOAD_URL).pause(); } private void cancel() { - Aria.whit(this).load(DOWNLOAD_URL).cancel(); + Aria.download(this).load(DOWNLOAD_URL).cancel(); } - private class MySchedulerListener extends Aria.SimpleSchedulerListener { - @Override public void onTaskStart(Task task) { + private class MySchedulerListener extends Aria.DownloadSchedulerListener { + + @Override public void onNoSupportBreakPoint(DownloadTask task) { + super.onNoSupportBreakPoint(task); + T.showShort(SingleTaskActivity.this, "该下载链接不支持断点"); + } + + @Override public void onTaskStart(DownloadTask task) { mUpdateHandler.obtainMessage(DOWNLOAD_PRE, task.getDownloadEntity().getFileSize()) .sendToTarget(); } - @Override public void onTaskResume(Task task) { + @Override public void onTaskResume(DownloadTask task) { super.onTaskResume(task); mUpdateHandler.obtainMessage(DOWNLOAD_PRE, task.getFileSize()).sendToTarget(); } - @Override public void onTaskStop(Task task) { + @Override public void onTaskStop(DownloadTask task) { mUpdateHandler.sendEmptyMessage(DOWNLOAD_STOP); } - @Override public void onTaskCancel(Task task) { + @Override public void onTaskCancel(DownloadTask task) { mUpdateHandler.sendEmptyMessage(DOWNLOAD_CANCEL); } - @Override public void onTaskFail(Task task) { + @Override public void onTaskFail(DownloadTask task) { mUpdateHandler.sendEmptyMessage(DOWNLOAD_FAILE); } - @Override public void onTaskComplete(Task task) { + @Override public void onTaskComplete(DownloadTask task) { mUpdateHandler.sendEmptyMessage(DOWNLOAD_COMPLETE); } - @Override public void onTaskRunning(Task task) { + @Override public void onTaskRunning(DownloadTask task) { mUpdateHandler.obtainMessage(DOWNLOAD_RUNNING, task).sendToTarget(); } } diff --git a/app/src/main/java/com/arialyy/simple/fragment_task/DownloadFragment.java b/app/src/main/java/com/arialyy/simple/download/fragment_download/DownloadFragment.java similarity index 60% rename from app/src/main/java/com/arialyy/simple/fragment_task/DownloadFragment.java rename to app/src/main/java/com/arialyy/simple/download/fragment_download/DownloadFragment.java index 19502277..661032d1 100644 --- a/app/src/main/java/com/arialyy/simple/fragment_task/DownloadFragment.java +++ b/app/src/main/java/com/arialyy/simple/download/fragment_download/DownloadFragment.java @@ -1,4 +1,20 @@ -package com.arialyy.simple.fragment_task; +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.arialyy.simple.download.fragment_download; import android.os.Bundle; import android.os.Environment; @@ -7,10 +23,10 @@ import android.widget.Button; import android.widget.TextView; import butterknife.Bind; import butterknife.OnClick; -import com.arialyy.aria.core.AMTarget; +import com.arialyy.aria.core.download.DownloadTarget; import com.arialyy.aria.core.Aria; -import com.arialyy.aria.core.DownloadEntity; -import com.arialyy.aria.core.task.Task; +import com.arialyy.aria.core.download.DownloadEntity; +import com.arialyy.aria.core.download.DownloadTask; import com.arialyy.aria.util.CommonUtil; import com.arialyy.frame.core.AbsFragment; import com.arialyy.simple.R; @@ -32,16 +48,16 @@ public class DownloadFragment extends AbsFragment { "http://static.gaoshouyou.com/d/3a/93/573ae1db9493a801c24bf66128b11e39.apk"; @Override protected void init(Bundle savedInstanceState) { - if (Aria.get(this).taskExists(DOWNLOAD_URL)) { - AMTarget target = Aria.whit(this).load(DOWNLOAD_URL); - int p = (int) (target.getCurrentProgress() * 100 / target.getFileSize()); + if (Aria.download(this).taskExists(DOWNLOAD_URL)) { + DownloadTarget target = Aria.download(this).load(DOWNLOAD_URL); + int p = (int) (target.getCurrentProgress() * 100 / target.getFileSize()); mPb.setProgress(p); } - DownloadEntity entity = Aria.get(this).getDownloadEntity(DOWNLOAD_URL); + DownloadEntity entity = Aria.download(this).getDownloadEntity(DOWNLOAD_URL); if (entity != null) { mSize.setText(CommonUtil.formatFileSize(entity.getFileSize())); int state = entity.getState(); - setBtState(state != DownloadEntity.STATE_DOWNLOAD_ING); + setBtState(state != DownloadEntity.STATE_RUNNING); } else { setBtState(true); } @@ -49,23 +65,23 @@ public class DownloadFragment extends AbsFragment { @Override public void onResume() { super.onResume(); - Aria.whit(this).addSchedulerListener(new DownloadFragment.MyDialogDownloadCallback()); + Aria.download(this).addSchedulerListener(new DownloadFragment.MyDialogDownloadCallback()); } @OnClick({ R.id.start, R.id.stop, R.id.cancel }) public void onClick(View view) { switch (view.getId()) { case R.id.start: - Aria.whit(this) + Aria.download(this) .load(DOWNLOAD_URL) .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/daialog.apk") .setDownloadName("daialog.apk") .start(); break; case R.id.stop: - Aria.whit(this).load(DOWNLOAD_URL).stop(); + Aria.download(this).load(DOWNLOAD_URL).pause(); break; case R.id.cancel: - Aria.whit(this).load(DOWNLOAD_URL).cancel(); + Aria.download(this).load(DOWNLOAD_URL).cancel(); break; } } @@ -88,31 +104,31 @@ public class DownloadFragment extends AbsFragment { mStop.setEnabled(!startEnable); } - private class MyDialogDownloadCallback extends Aria.SimpleSchedulerListener { + private class MyDialogDownloadCallback extends Aria.DownloadSchedulerListener { - @Override public void onTaskPre(Task task) { + @Override public void onTaskPre(DownloadTask task) { super.onTaskPre(task); mSize.setText(CommonUtil.formatFileSize(task.getFileSize())); setBtState(false); } - @Override public void onTaskStop(Task task) { + @Override public void onTaskStop(DownloadTask task) { super.onTaskStop(task); setBtState(true); mSpeed.setText("0.0kb/s"); } - @Override public void onTaskCancel(Task task) { + @Override public void onTaskCancel(DownloadTask task) { super.onTaskCancel(task); setBtState(true); mPb.setProgress(0); mSpeed.setText("0.0kb/s"); } - @Override public void onTaskRunning(Task task) { + @Override public void onTaskRunning(DownloadTask task) { super.onTaskRunning(task); long current = task.getCurrentProgress(); - long len = task.getFileSize(); + long len = task.getFileSize(); if (len == 0) { mPb.setProgress(0); } else { diff --git a/app/src/main/java/com/arialyy/simple/download/fragment_download/FragmentActivity.java b/app/src/main/java/com/arialyy/simple/download/fragment_download/FragmentActivity.java new file mode 100644 index 00000000..9b3c48cb --- /dev/null +++ b/app/src/main/java/com/arialyy/simple/download/fragment_download/FragmentActivity.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.arialyy.simple.download.fragment_download; + +import com.arialyy.simple.R; +import com.arialyy.simple.base.BaseActivity; +import com.arialyy.simple.databinding.FragmentDownloadBinding; + +/** + * Created by Aria.Lao on 2017/1/4. + */ + +public class FragmentActivity extends BaseActivity { + @Override protected int setLayoutId() { + return R.layout.activity_fragment; + } +} diff --git a/app/src/main/java/com/arialyy/simple/multi_task/DownloadAdapter.java b/app/src/main/java/com/arialyy/simple/download/multi_download/DownloadAdapter.java similarity index 84% rename from app/src/main/java/com/arialyy/simple/multi_task/DownloadAdapter.java rename to app/src/main/java/com/arialyy/simple/download/multi_download/DownloadAdapter.java index 4ee18fde..430d3008 100644 --- a/app/src/main/java/com/arialyy/simple/multi_task/DownloadAdapter.java +++ b/app/src/main/java/com/arialyy/simple/download/multi_download/DownloadAdapter.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.arialyy.simple.multi_task; +package com.arialyy.simple.download.multi_download; import android.content.Context; import android.content.res.Resources; @@ -25,7 +25,7 @@ import butterknife.Bind; import com.arialyy.absadapter.common.AbsHolder; import com.arialyy.absadapter.recycler_view.AbsRVAdapter; import com.arialyy.aria.core.Aria; -import com.arialyy.aria.core.DownloadEntity; +import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.util.CommonUtil; import com.arialyy.simple.R; import com.arialyy.simple.widget.HorizontalProgressBarWithNumber; @@ -39,8 +39,8 @@ import java.util.concurrent.ConcurrentHashMap; * 下载列表适配器 */ final class DownloadAdapter extends AbsRVAdapter { - private static final String TAG = "DownloadAdapter"; - private Map mPositions = new ConcurrentHashMap<>(); + private static final String TAG = "DownloadAdapter"; + private Map mPositions = new ConcurrentHashMap<>(); DownloadAdapter(Context context, List data) { super(context, data); @@ -125,7 +125,7 @@ final class DownloadAdapter extends AbsRVAdapter { + @Bind(R.id.list) RecyclerView mList; + @Bind(R.id.toolbar) Toolbar mBar; + private DownloadAdapter mAdapter; + + @Override protected int setLayoutId() { + return R.layout.activity_multi_download; + } + + @Override protected void init(Bundle savedInstanceState) { + super.init(savedInstanceState); + mAdapter = new DownloadAdapter(this, Aria.download(this).getTaskList()); + mList.setLayoutManager(new LinearLayoutManager(this)); + mList.setAdapter(mAdapter); + mBar.setTitle("多任务下载"); + } + + @Override protected void dataCallback(int result, Object data) { + + } + + @Override protected void onResume() { + super.onResume(); + Aria.download(this).addSchedulerListener(new MySchedulerListener()); + } + + private class MySchedulerListener extends Aria.DownloadSchedulerListener { + @Override public void onTaskPre(DownloadTask task) { + super.onTaskPre(task); + L.d(TAG, "download pre"); + mAdapter.updateState(task.getDownloadEntity()); + } + + @Override public void onTaskStart(DownloadTask task) { + super.onTaskStart(task); + L.d(TAG, "download start"); + mAdapter.updateState(task.getDownloadEntity()); + } + + @Override public void onTaskResume(DownloadTask task) { + super.onTaskResume(task); + L.d(TAG, "download resume"); + mAdapter.updateState(task.getDownloadEntity()); + } + + @Override public void onTaskRunning(DownloadTask task) { + super.onTaskRunning(task); + mAdapter.setProgress(task.getDownloadEntity()); + } + + @Override public void onTaskStop(DownloadTask task) { + super.onTaskStop(task); + mAdapter.updateState(task.getDownloadEntity()); + } + + @Override public void onTaskCancel(DownloadTask task) { + super.onTaskCancel(task); + mAdapter.updateState(task.getDownloadEntity()); + } + + @Override public void onTaskComplete(DownloadTask task) { + super.onTaskComplete(task); + mAdapter.updateState(task.getDownloadEntity()); + } + + @Override public void onTaskFail(DownloadTask task) { + super.onTaskFail(task); + L.d(TAG, "download fail"); + } + } +} diff --git a/app/src/main/java/com/arialyy/simple/multi_task/MultiTaskActivity.java b/app/src/main/java/com/arialyy/simple/download/multi_download/MultiTaskActivity.java similarity index 77% rename from app/src/main/java/com/arialyy/simple/multi_task/MultiTaskActivity.java rename to app/src/main/java/com/arialyy/simple/download/multi_download/MultiTaskActivity.java index c7546b24..f0200597 100644 --- a/app/src/main/java/com/arialyy/simple/multi_task/MultiTaskActivity.java +++ b/app/src/main/java/com/arialyy/simple/download/multi_download/MultiTaskActivity.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.arialyy.simple.multi_task; +package com.arialyy.simple.download.multi_download; import android.content.Intent; import android.os.Bundle; @@ -24,13 +24,11 @@ import android.support.v7.widget.Toolbar; import android.view.View; import butterknife.Bind; import com.arialyy.aria.core.Aria; -import com.arialyy.aria.core.DownloadEntity; -import com.arialyy.aria.core.task.Task; -import com.arialyy.frame.util.show.L; +import com.arialyy.aria.core.download.DownloadTask; import com.arialyy.simple.R; import com.arialyy.simple.base.BaseActivity; import com.arialyy.simple.databinding.ActivityMultiBinding; -import com.arialyy.simple.module.DownloadModule; +import com.arialyy.simple.download.DownloadModule; import java.util.ArrayList; import java.util.List; @@ -38,9 +36,9 @@ import java.util.List; * Created by Lyy on 2016/9/27. */ public class MultiTaskActivity extends BaseActivity { - @Bind(R.id.list) RecyclerView mList; - @Bind(R.id.toolbar) Toolbar mBar; - private FileListAdapter mAdapter; + @Bind(R.id.list) RecyclerView mList; + @Bind(R.id.toolbar) Toolbar mBar; + private FileListAdapter mAdapter; List mData = new ArrayList<>(); @Override protected int setLayoutId() { @@ -64,17 +62,17 @@ public class MultiTaskActivity extends BaseActivity { dialog.show(getSupportFragmentManager(), "download_num"); break; case R.id.stop_all: - Aria.get(this).stopAllTask(); + Aria.download(this).stopAllTask(); break; case R.id.turn: - startActivity(new Intent(this, DownloadActivity.class)); + startActivity(new Intent(this, MultiDownloadActivity.class)); break; } } @Override protected void onResume() { super.onResume(); - Aria.whit(this).addSchedulerListener(new DownloadListener()); + Aria.download(this).addSchedulerListener(new DownloadListener()); } @Override protected void onDestroy() { @@ -89,28 +87,28 @@ public class MultiTaskActivity extends BaseActivity { } } - private class DownloadListener extends Aria.SimpleSchedulerListener { + private class DownloadListener extends Aria.DownloadSchedulerListener { - @Override public void onTaskStart(Task task) { + @Override public void onTaskStart(DownloadTask task) { super.onTaskStart(task); mAdapter.updateBtState(task.getDownloadUrl(), false); } - @Override public void onTaskRunning(Task task) { + @Override public void onTaskRunning(DownloadTask task) { super.onTaskRunning(task); } - @Override public void onTaskResume(Task task) { + @Override public void onTaskResume(DownloadTask task) { super.onTaskResume(task); mAdapter.updateBtState(task.getDownloadUrl(), false); } - @Override public void onTaskStop(Task task) { + @Override public void onTaskStop(DownloadTask task) { super.onTaskStop(task); mAdapter.updateBtState(task.getDownloadUrl(), true); } - @Override public void onTaskComplete(Task task) { + @Override public void onTaskComplete(DownloadTask task) { super.onTaskComplete(task); mAdapter.updateBtState(task.getDownloadUrl(), true); } diff --git a/app/src/main/java/com/arialyy/simple/download/service_download/DownloadNotification.java b/app/src/main/java/com/arialyy/simple/download/service_download/DownloadNotification.java new file mode 100644 index 00000000..4495530f --- /dev/null +++ b/app/src/main/java/com/arialyy/simple/download/service_download/DownloadNotification.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.arialyy.simple.download.service_download; + +import android.app.NotificationManager; +import android.content.Context; +import android.support.v4.app.NotificationCompat; +import com.arialyy.simple.R; + +/** + * Created by Aria.Lao on 2017/1/18. + */ +public class DownloadNotification { + + private NotificationManager mManager; + private Context mContext; + private NotificationCompat.Builder mBuilder; + private static final int mNotifiyId = 0; + + public DownloadNotification(Context context) { + mContext = context; + init(); + } + + private void init() { + mManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); + mBuilder = new NotificationCompat.Builder(mContext); + mBuilder.setContentTitle("Aria Download Test") + .setContentText("进度条") + .setProgress(100, 0, false) + .setSmallIcon(R.mipmap.ic_launcher); + mManager.notify(mNotifiyId, mBuilder.build()); + } + + public void upload(int progress){ + if (mBuilder != null) { + mBuilder.setProgress(100, progress, false); + mManager.notify(mNotifiyId, mBuilder.build()); + } + } +} diff --git a/app/src/main/java/com/arialyy/simple/download/service_download/DownloadService.java b/app/src/main/java/com/arialyy/simple/download/service_download/DownloadService.java new file mode 100644 index 00000000..92cc65f4 --- /dev/null +++ b/app/src/main/java/com/arialyy/simple/download/service_download/DownloadService.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.simple.download.service_download; + +import android.app.Service; +import android.content.Intent; +import android.os.Environment; +import android.os.IBinder; +import android.support.annotation.Nullable; +import com.arialyy.aria.core.Aria; +import com.arialyy.aria.core.download.DownloadTask; +import com.arialyy.frame.util.show.T; + +/** + * Created by Aria.Lao on 2017/4/5. + * 在服务中使用 Aria进行下载 + */ +public class DownloadService extends Service { + + private static final String DOWNLOAD_URL = + //"http://kotlinlang.org/docs/kotlin-docs.pdf"; + //"https://atom-installer.github.com/v1.13.0/AtomSetup.exe?s=1484074138&ext=.exe"; + //"http://static.gaoshouyou.com/d/21/e8/61218d78d0e8b79df68dbc18dd484c97.apk"; + //不支持断点的链接 + "http://ox.konsung.net:5555/ksdc-web/download/downloadFile/?fileName=ksdc_1.0.2.apk&rRange=0-"; + private DownloadNotification mNotify; + + @Nullable @Override public IBinder onBind(Intent intent) { + return null; + } + + @Override public int onStartCommand(Intent intent, int flags, int startId) { + return super.onStartCommand(intent, flags, startId); + } + + @Override public void onCreate() { + super.onCreate(); + mNotify = new DownloadNotification(getApplicationContext()); + Aria.download(this).addSchedulerListener(new MySchedulerListener()); + Aria.download(this) + .load(DOWNLOAD_URL) + .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/service_task.apk") + .start(); + } + + @Override public void onDestroy() { + super.onDestroy(); + Aria.download(this).removeSchedulerListener(); + } + + private class MySchedulerListener extends Aria.DownloadSchedulerListener { + + @Override public void onNoSupportBreakPoint(DownloadTask task) { + super.onNoSupportBreakPoint(task); + T.showShort(getApplicationContext(), "该下载链接不支持断点"); + } + + @Override public void onTaskStart(DownloadTask task) { + T.showShort(getApplicationContext(), task.getDownloadEntity().getFileName() + ",开始下载"); + } + + @Override public void onTaskResume(DownloadTask task) { + super.onTaskResume(task); + } + + @Override public void onTaskStop(DownloadTask task) { + T.showShort(getApplicationContext(), task.getDownloadEntity().getFileName() + ",停止下载"); + } + + @Override public void onTaskCancel(DownloadTask task) { + T.showShort(getApplicationContext(), task.getDownloadEntity().getFileName() + ",取消下载"); + } + + @Override public void onTaskFail(DownloadTask task) { + T.showShort(getApplicationContext(), task.getDownloadEntity().getFileName() + ",下载失败"); + } + + @Override public void onTaskComplete(DownloadTask task) { + T.showShort(getApplicationContext(), task.getDownloadEntity().getFileName() + ",下载完成"); + mNotify.upload(100); + } + + @Override public void onTaskRunning(DownloadTask task) { + long len = task.getFileSize(); + int p = (int) (task.getCurrentProgress() * 100 / len); + mNotify.upload(p); + } + } +} diff --git a/app/src/main/java/com/arialyy/simple/fragment_task/FragmentActivity.java b/app/src/main/java/com/arialyy/simple/fragment_task/FragmentActivity.java deleted file mode 100644 index ff7a30cd..00000000 --- a/app/src/main/java/com/arialyy/simple/fragment_task/FragmentActivity.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.arialyy.simple.fragment_task; - -import com.arialyy.simple.R; -import com.arialyy.simple.base.BaseActivity; -import com.arialyy.simple.databinding.FragmentDownloadBinding; - -/** - * Created by Aria.Lao on 2017/1/4. - */ - -public class FragmentActivity extends BaseActivity { - @Override protected int setLayoutId() { - return R.layout.activity_fragment; - } -} diff --git a/app/src/main/java/com/arialyy/simple/multi_task/DownloadActivity.java b/app/src/main/java/com/arialyy/simple/multi_task/DownloadActivity.java deleted file mode 100644 index 7e6652e4..00000000 --- a/app/src/main/java/com/arialyy/simple/multi_task/DownloadActivity.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.arialyy.simple.multi_task; - -import android.os.Bundle; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import butterknife.Bind; -import com.arialyy.aria.core.Aria; -import com.arialyy.aria.core.task.Task; -import com.arialyy.frame.util.show.L; -import com.arialyy.simple.R; -import com.arialyy.simple.base.BaseActivity; -import com.arialyy.simple.databinding.ActivityDownloadBinding; - -/** - * Created by AriaL on 2017/1/6. - */ - -public class DownloadActivity extends BaseActivity { - @Bind(R.id.list) RecyclerView mList; - private DownloadAdapter mAdapter; - - @Override protected int setLayoutId() { - return R.layout.activity_download; - } - - @Override protected void init(Bundle savedInstanceState) { - super.init(savedInstanceState); - mAdapter = new DownloadAdapter(this, Aria.get(this).getDownloadList()); - mList.setLayoutManager(new LinearLayoutManager(this)); - mList.setAdapter(mAdapter); - } - - @Override protected void dataCallback(int result, Object data) { - - } - - @Override protected void onResume() { - super.onResume(); - Aria.whit(this).addSchedulerListener(new MySchedulerListener()); - } - - private class MySchedulerListener extends Aria.SimpleSchedulerListener { - @Override public void onTaskPre(Task task) { - super.onTaskPre(task); - L.d(TAG, "download pre"); - mAdapter.updateState(task.getDownloadEntity()); - } - - @Override public void onTaskStart(Task task) { - super.onTaskStart(task); - L.d(TAG, "download start"); - mAdapter.updateState(task.getDownloadEntity()); - } - - @Override public void onTaskResume(Task task) { - super.onTaskResume(task); - L.d(TAG, "download resume"); - mAdapter.updateState(task.getDownloadEntity()); - } - - @Override public void onTaskRunning(Task task) { - super.onTaskRunning(task); - mAdapter.setProgress(task.getDownloadEntity()); - } - - @Override public void onTaskStop(Task task) { - super.onTaskStop(task); - mAdapter.updateState(task.getDownloadEntity()); - } - - @Override public void onTaskCancel(Task task) { - super.onTaskCancel(task); - mAdapter.updateState(task.getDownloadEntity()); - } - - @Override public void onTaskComplete(Task task) { - super.onTaskComplete(task); - mAdapter.updateState(task.getDownloadEntity()); - } - - @Override public void onTaskFail(Task task) { - super.onTaskFail(task); - L.d(TAG, "download fail"); - } - } -} diff --git a/app/src/main/java/com/arialyy/simple/multi_task/FileListEntity.java b/app/src/main/java/com/arialyy/simple/multi_task/FileListEntity.java deleted file mode 100644 index 15d584a8..00000000 --- a/app/src/main/java/com/arialyy/simple/multi_task/FileListEntity.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.arialyy.simple.multi_task; - -/** - * Created by AriaL on 2017/1/6. - */ - -public class FileListEntity { - public String name, downloadUrl, downloadPath; -} diff --git a/app/src/main/java/com/arialyy/simple/upload/UploadActivity.java b/app/src/main/java/com/arialyy/simple/upload/UploadActivity.java new file mode 100644 index 00000000..6325df0e --- /dev/null +++ b/app/src/main/java/com/arialyy/simple/upload/UploadActivity.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.arialyy.simple.upload; + +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import butterknife.Bind; +import butterknife.OnClick; +import com.arialyy.aria.core.Aria; +import com.arialyy.aria.core.upload.UploadTask; +import com.arialyy.frame.util.FileUtil; +import com.arialyy.frame.util.show.T; +import com.arialyy.simple.R; +import com.arialyy.simple.base.BaseActivity; +import com.arialyy.simple.databinding.ActivityUploadMeanBinding; +import com.arialyy.simple.widget.HorizontalProgressBarWithNumber; +import java.lang.ref.WeakReference; + +/** + * Created by Aria.Lao on 2017/2/9. + */ +public class UploadActivity extends BaseActivity { + @Bind(R.id.pb) HorizontalProgressBarWithNumber mPb; + private static final int START = 0; + private static final int STOP = 1; + private static final int CANCEL = 2; + private static final int RUNNING = 3; + private static final int COMPLETE = 4; + + private static final String FILE_PATH = "/sdcard/Download/test.zip"; + + private Handler mHandler = new Handler() { + @Override public void handleMessage(Message msg) { + super.handleMessage(msg); + UploadTask task = (UploadTask) msg.obj; + switch (msg.what) { + case START: + getBinding().setFileSize(FileUtil.formatFileSize(task.getFileSize())); + break; + case STOP: + mPb.setProgress(0); + break; + case CANCEL: + mPb.setProgress(0); + break; + case RUNNING: + int p = (int) (task.getCurrentProgress() * 100 / task.getFileSize()); + mPb.setProgress(p); + break; + case COMPLETE: + T.showShort(UploadActivity.this, "上传完成"); + mPb.setProgress(100); + break; + } + } + }; + + @Override protected int setLayoutId() { + return R.layout.activity_upload_mean; + } + + @Override protected void init(Bundle savedInstanceState) { + super.init(savedInstanceState); + } + + @OnClick(R.id.upload) void upload() { + Aria.upload(this) + .load(FILE_PATH) + .setUploadUrl("http://172.18.104.50:8080/upload/sign_file") + .setAttachment("file") + .start(); + } + + @OnClick(R.id.stop) void stop() { + Aria.upload(this).load(FILE_PATH).cancel(); + } + + @OnClick(R.id.remove) void remove() { + Aria.upload(this).load(FILE_PATH).cancel(); + } + + @Override protected void onResume() { + super.onResume(); + Aria.upload(this).addSchedulerListener(new UploadListener(mHandler)); + } + + static class UploadListener extends Aria.UploadSchedulerListener { + WeakReference handler; + + UploadListener(Handler handler) { + this.handler = new WeakReference<>(handler); + } + + @Override public void onTaskStart(UploadTask task) { + super.onTaskStart(task); + handler.get().obtainMessage(START, task).sendToTarget(); + } + + @Override public void onTaskStop(UploadTask task) { + super.onTaskStop(task); + handler.get().obtainMessage(STOP, task).sendToTarget(); + } + + @Override public void onTaskCancel(UploadTask task) { + super.onTaskCancel(task); + handler.get().obtainMessage(CANCEL, task).sendToTarget(); + } + + @Override public void onTaskRunning(UploadTask task) { + super.onTaskRunning(task); + handler.get().obtainMessage(RUNNING, task).sendToTarget(); + } + + @Override public void onTaskComplete(UploadTask task) { + super.onTaskComplete(task); + handler.get().obtainMessage(COMPLETE, task).sendToTarget(); + } + } +} diff --git a/app/src/main/java/com/arialyy/simple/widget/HorizontalProgressBarWithNumber.java b/app/src/main/java/com/arialyy/simple/widget/HorizontalProgressBarWithNumber.java index 0e8512a0..7c120850 100644 --- a/app/src/main/java/com/arialyy/simple/widget/HorizontalProgressBarWithNumber.java +++ b/app/src/main/java/com/arialyy/simple/widget/HorizontalProgressBarWithNumber.java @@ -14,7 +14,6 @@ * limitations under the License. */ - package com.arialyy.simple.widget; import android.content.Context; @@ -27,53 +26,50 @@ import android.widget.ProgressBar; import com.arialyy.simple.R; public class HorizontalProgressBarWithNumber extends ProgressBar { - private static final int DEFAULT_TEXT_SIZE = 10; - private static final int DEFAULT_TEXT_COLOR = 0XFFFC00D1; - private static final int DEFAULT_COLOR_UNREACHED_COLOR = 0xFFd3d6da; - private static final int DEFAULT_HEIGHT_REACHED_PROGRESS_BAR = 2; - private static final int DEFAULT_HEIGHT_UNREACHED_PROGRESS_BAR = 2; - private static final int DEFAULT_SIZE_TEXT_OFFSET = 10; + private static final int DEFAULT_TEXT_SIZE = 10; + private static final int DEFAULT_TEXT_COLOR = 0XFFFC00D1; + private static final int DEFAULT_COLOR_UNREACHED_COLOR = 0xFFd3d6da; + private static final int DEFAULT_HEIGHT_REACHED_PROGRESS_BAR = 2; + private static final int DEFAULT_HEIGHT_UNREACHED_PROGRESS_BAR = 2; + private static final int DEFAULT_SIZE_TEXT_OFFSET = 10; /** * painter of all drawing things */ - protected Paint mPaint = new Paint(); + protected Paint mPaint = new Paint(); /** * color of progress number */ - protected int mTextColor = DEFAULT_TEXT_COLOR; + protected int mTextColor = DEFAULT_TEXT_COLOR; /** * size of text (sp) */ - protected int mTextSize = sp2px(DEFAULT_TEXT_SIZE); + protected int mTextSize = sp2px(DEFAULT_TEXT_SIZE); /** * offset of draw progress */ - protected int mTextOffset = - dp2px(DEFAULT_SIZE_TEXT_OFFSET); + protected int mTextOffset = dp2px(DEFAULT_SIZE_TEXT_OFFSET); /** * height of reached progress bar */ - protected int mReachedProgressBarHeight = - dp2px(DEFAULT_HEIGHT_REACHED_PROGRESS_BAR); + protected int mReachedProgressBarHeight = dp2px(DEFAULT_HEIGHT_REACHED_PROGRESS_BAR); /** * color of reached bar */ - protected int mReachedBarColor = DEFAULT_TEXT_COLOR; + protected int mReachedBarColor = DEFAULT_TEXT_COLOR; /** * color of unreached bar */ - protected int mUnReachedBarColor = DEFAULT_COLOR_UNREACHED_COLOR; + protected int mUnReachedBarColor = DEFAULT_COLOR_UNREACHED_COLOR; /** * height of unreached progress bar */ - protected int mUnReachedProgressBarHeight = - dp2px(DEFAULT_HEIGHT_UNREACHED_PROGRESS_BAR); + protected int mUnReachedProgressBarHeight = dp2px(DEFAULT_HEIGHT_UNREACHED_PROGRESS_BAR); /** * view width except padding */ protected int mRealWidth; - protected boolean mIfDrawText = true; - protected static final int VISIBLE = 0; + protected boolean mIfDrawText = true; + protected static final int VISIBLE = 0; public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs) { this(context, attrs, 0); @@ -87,14 +83,14 @@ public class HorizontalProgressBarWithNumber extends ProgressBar { } @Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int width = MeasureSpec.getSize(widthMeasureSpec); + int width = MeasureSpec.getSize(widthMeasureSpec); int height = measureHeight(heightMeasureSpec); setMeasuredDimension(width, height); mRealWidth = getMeasuredWidth() - getPaddingRight() - getPaddingLeft(); } private int measureHeight(int measureSpec) { - int result = 0; + int result = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { @@ -148,12 +144,12 @@ public class HorizontalProgressBarWithNumber extends ProgressBar { @Override protected synchronized void onDraw(Canvas canvas) { canvas.save(); canvas.translate(getPaddingLeft(), getHeight() / 2); - boolean noNeedBg = false; - float radio = getProgress() * 1.0f / getMax(); - float progressPosX = (int) (mRealWidth * radio); - String text = getProgress() + "%"; + boolean noNeedBg = false; + float radio = getProgress() * 1.0f / getMax(); + float progressPosX = (int) (mRealWidth * radio); + String text = getProgress() + "%"; // mPaint.getTextBounds(text, 0, text.length(), mTextBound); - float textWidth = mPaint.measureText(text); + float textWidth = mPaint.measureText(text); float textHeight = (mPaint.descent() + mPaint.ascent()) / 2; if (progressPosX + textWidth > mRealWidth) { progressPosX = mRealWidth - textWidth; diff --git a/app/src/main/res/layout/activity_download_mean.xml b/app/src/main/res/layout/activity_download_mean.xml new file mode 100644 index 00000000..e52848d1 --- /dev/null +++ b/app/src/main/res/layout/activity_download_mean.xml @@ -0,0 +1,78 @@ + + + + + + + +