optimize controller code

v4
laoyuyu 2 years ago
parent 16e76b42ed
commit 3ac7b0f211
  1. 1
      Aria/src/main/java/com/arialyy/aria/core/download/CheckDEntityUtil.java
  2. 2
      Http/src/main/java/com/arialyy/aria/http/HttpTaskOption.kt
  3. 10
      Http/src/main/java/com/arialyy/aria/http/HttpUtil.kt
  4. 8
      Http/src/main/java/com/arialyy/aria/http/download/HttpDGLoader.java
  5. 45
      Http/src/main/java/com/arialyy/aria/http/download/HttpDGLoaderUtil.java
  6. 9
      Http/src/main/java/com/arialyy/aria/http/download/HttpDStartController.kt
  7. 5
      Http/src/main/java/com/arialyy/aria/http/download/HttpDStopController.kt
  8. 24
      Http/src/main/java/com/arialyy/aria/http/download/HttpDStopController2.kt
  9. 4
      Http/src/main/java/com/arialyy/aria/http/download/HttpDTaskAdapter.kt
  10. 6
      Http/src/main/java/com/arialyy/aria/http/download/HttpSubDLoaderAdapter.java
  11. 6
      Http/src/main/java/com/arialyy/aria/http/upload/HttpUTaskAdapter.kt
  12. 0
      Http/src/main/resources/META-INF/services/com.arialyy.aria.core.inf.ITaskAdapter
  13. 4
      HttpGroup/src/main/java/com/arialyy/dua/group/DGroupAdapter.kt
  14. 132
      PublicComponent/src/main/java/com/arialyy/aria/core/TaskOptionParams.java
  15. 91
      PublicComponent/src/main/java/com/arialyy/aria/core/TaskRecord.java
  16. 68
      PublicComponent/src/main/java/com/arialyy/aria/core/ThreadRecord.java
  17. 12
      PublicComponent/src/main/java/com/arialyy/aria/core/command/AbsCmd.java
  18. 32
      PublicComponent/src/main/java/com/arialyy/aria/core/command/AbsCmdFactory.java
  19. 198
      PublicComponent/src/main/java/com/arialyy/aria/core/command/AbsNormalCmd.java
  20. 40
      PublicComponent/src/main/java/com/arialyy/aria/core/command/CancelCmd.kt
  21. 1
      PublicComponent/src/main/java/com/arialyy/aria/core/command/CmdResp.kt
  22. 114
      PublicComponent/src/main/java/com/arialyy/aria/core/command/NormalCmdFactory.java
  23. 47
      PublicComponent/src/main/java/com/arialyy/aria/core/command/StopCmd.java
  24. 50
      PublicComponent/src/main/java/com/arialyy/aria/core/command/StopCmd.kt
  25. 267
      PublicComponent/src/main/java/com/arialyy/aria/core/common/AbsEntity.java
  26. 103
      PublicComponent/src/main/java/com/arialyy/aria/core/common/AbsGroupEntity.java
  27. 125
      PublicComponent/src/main/java/com/arialyy/aria/core/common/AbsNormalEntity.java
  28. 42
      PublicComponent/src/main/java/com/arialyy/aria/core/common/CompleteInfo.java
  29. 33
      PublicComponent/src/main/java/com/arialyy/aria/core/common/ErrorCode.java
  30. 2
      PublicComponent/src/main/java/com/arialyy/aria/core/common/M3U8Entity.java
  31. 225
      PublicComponent/src/main/java/com/arialyy/aria/core/common/RecordHandler.java
  32. 207
      PublicComponent/src/main/java/com/arialyy/aria/core/common/RecordHelper.java
  33. 113
      PublicComponent/src/main/java/com/arialyy/aria/core/common/SubThreadConfig.java
  34. 2
      PublicComponent/src/main/java/com/arialyy/aria/core/common/TaskOption.kt
  35. 48
      PublicComponent/src/main/java/com/arialyy/aria/core/download/AbsGroupTaskWrapper.java
  36. 44
      PublicComponent/src/main/java/com/arialyy/aria/core/download/DGEntityWrapper.java
  37. 89
      PublicComponent/src/main/java/com/arialyy/aria/core/download/DGTaskWrapper.java
  38. 122
      PublicComponent/src/main/java/com/arialyy/aria/core/download/DTaskWrapper.java
  39. 214
      PublicComponent/src/main/java/com/arialyy/aria/core/download/DownloadEntity.java
  40. 86
      PublicComponent/src/main/java/com/arialyy/aria/core/download/DownloadGroupEntity.java
  41. 14
      PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsGroupLoader.java
  42. 6
      PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsGroupLoaderAdapter.java
  43. 8
      PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsSubDLoadAdapter.java
  44. 4
      PublicComponent/src/main/java/com/arialyy/aria/core/group/ISubQueue.java
  45. 12
      PublicComponent/src/main/java/com/arialyy/aria/core/group/SimpleSchedulers.java
  46. 38
      PublicComponent/src/main/java/com/arialyy/aria/core/group/SimpleSubQueue.java
  47. 2
      PublicComponent/src/main/java/com/arialyy/aria/core/group/SimpleSubRetryQueue.java
  48. 2
      PublicComponent/src/main/java/com/arialyy/aria/core/inf/ITaskAdapter.java
  49. 60
      PublicComponent/src/main/java/com/arialyy/aria/core/listener/BaseDListener.java
  50. 38
      PublicComponent/src/main/java/com/arialyy/aria/core/listener/BaseUListener.java
  51. 8
      PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalLoaderAdapter.java
  52. 2
      PublicComponent/src/main/java/com/arialyy/aria/core/processor/ITsMergeHandler.java
  53. 46
      PublicComponent/src/main/java/com/arialyy/aria/core/task/AbsTask.java
  54. 4
      PublicComponent/src/main/java/com/arialyy/aria/core/task/AbsTaskAdapter.kt
  55. 4
      PublicComponent/src/main/java/com/arialyy/aria/core/task/DownloadGroupTask.java
  56. 7
      PublicComponent/src/main/java/com/arialyy/aria/core/task/DownloadTask.java
  57. 3
      PublicComponent/src/main/java/com/arialyy/aria/core/task/ITask.java
  58. 28
      PublicComponent/src/main/java/com/arialyy/aria/core/task/TaskCachePool.kt
  59. 54
      PublicComponent/src/main/java/com/arialyy/aria/core/upload/UTaskWrapper.java
  60. 94
      PublicComponent/src/main/java/com/arialyy/aria/core/upload/UploadEntity.java
  61. 197
      PublicComponent/src/main/java/com/arialyy/aria/core/wrapper/AbsTaskWrapper.java
  62. 111
      PublicComponent/src/main/java/com/arialyy/aria/core/wrapper/ITaskWrapper.java
  63. 47
      PublicComponent/src/main/java/com/arialyy/aria/core/wrapper/RecordWrapper.java
  64. 27
      PublicComponent/src/main/java/com/arialyy/aria/orm/AbsDbWrapper.java
  65. 39
      PublicComponent/src/main/java/com/arialyy/aria/orm/AbsDelegate.java
  66. 62
      PublicComponent/src/main/java/com/arialyy/aria/orm/ActionPolicy.java
  67. 61
      PublicComponent/src/main/java/com/arialyy/aria/orm/DBConfig.java
  68. 93
      PublicComponent/src/main/java/com/arialyy/aria/orm/DatabaseContext.java
  69. 174
      PublicComponent/src/main/java/com/arialyy/aria/orm/DbContentProvider.kt
  70. 295
      PublicComponent/src/main/java/com/arialyy/aria/orm/DbEntity.java
  71. 639
      PublicComponent/src/main/java/com/arialyy/aria/orm/DelegateFind.java
  72. 69
      PublicComponent/src/main/java/com/arialyy/aria/orm/DelegateManager.java
  73. 58
      PublicComponent/src/main/java/com/arialyy/aria/orm/DelegateUpdate.java
  74. 213
      PublicComponent/src/main/java/com/arialyy/aria/orm/DelegateWrapper.java
  75. 552
      PublicComponent/src/main/java/com/arialyy/aria/orm/SqlHelper.java
  76. 590
      PublicComponent/src/main/java/com/arialyy/aria/orm/SqlUtil.java
  77. 30
      PublicComponent/src/main/java/com/arialyy/aria/orm/annotation/Default.java
  78. 50
      PublicComponent/src/main/java/com/arialyy/aria/orm/annotation/Foreign.java
  79. 30
      PublicComponent/src/main/java/com/arialyy/aria/orm/annotation/Ignore.java
  80. 44
      PublicComponent/src/main/java/com/arialyy/aria/orm/annotation/Many.java
  81. 30
      PublicComponent/src/main/java/com/arialyy/aria/orm/annotation/NoNull.java
  82. 29
      PublicComponent/src/main/java/com/arialyy/aria/orm/annotation/One.java
  83. 35
      PublicComponent/src/main/java/com/arialyy/aria/orm/annotation/Primary.java
  84. 30
      PublicComponent/src/main/java/com/arialyy/aria/orm/annotation/Table.java
  85. 29
      PublicComponent/src/main/java/com/arialyy/aria/orm/annotation/Unique.java
  86. 29
      PublicComponent/src/main/java/com/arialyy/aria/orm/annotation/Wrapper.java
  87. 4
      PublicComponent/src/main/java/com/arialyy/aria/util/ComponentUtil.java
  88. 2
      PublicComponent/src/main/java/com/arialyy/aria/util/DeleteM3u8Record.java
  89. 3
      PublicComponent/src/main/resources/META-INF/services/com.arialyy.aria.core.listener.IEventListener
  90. 2
      app/src/main/java/com/arialyy/simple/core/download/m3u8/M3U8VodDLoadActivity.java
  91. 4
      app/src/main/java/com/arialyy/simple/core/download/m3u8/VideoPlayerFragment.java

@ -16,6 +16,7 @@
package com.arialyy.aria.core.download; package com.arialyy.aria.core.download;
import android.text.TextUtils; import android.text.TextUtils;
import com.arialyy.aria.core.common.M3U8Entity;
import com.arialyy.aria.core.common.controller.FeatureController; import com.arialyy.aria.core.common.controller.FeatureController;
import com.arialyy.aria.core.inf.ICheckEntityUtil; import com.arialyy.aria.core.inf.ICheckEntityUtil;
import com.arialyy.aria.core.inf.IOptionConstant; import com.arialyy.aria.core.inf.IOptionConstant;

@ -15,7 +15,7 @@
*/ */
package com.arialyy.aria.http package com.arialyy.aria.http
import com.arialyy.aria.core.download.TaskOption import com.arialyy.aria.core.common.TaskOption
import com.arialyy.aria.core.processor.IHttpFileLenAdapter import com.arialyy.aria.core.processor.IHttpFileLenAdapter
import com.arialyy.aria.core.task.ITaskInterceptor import com.arialyy.aria.core.task.ITaskInterceptor

@ -17,9 +17,9 @@ package com.arialyy.aria.http
import android.net.Uri import android.net.Uri
import android.text.TextUtils import android.text.TextUtils
import com.arialyy.aria.core.inf.ITaskUtil import com.arialyy.aria.core.inf.ITaskAdapter
import com.arialyy.aria.core.task.TaskCachePool import com.arialyy.aria.core.task.TaskCachePool
import com.arialyy.aria.http.download.HttpDTaskUtil import com.arialyy.aria.http.download.HttpDTaskAdapter
import com.arialyy.aria.util.FileUtils import com.arialyy.aria.util.FileUtils
import com.arialyy.aria.util.Regular import com.arialyy.aria.util.Regular
import timber.log.Timber import timber.log.Timber
@ -37,10 +37,10 @@ import java.util.zip.InflaterInputStream
**/ **/
internal object HttpUtil { internal object HttpUtil {
fun getDTaskUtil(filePath: Uri): ITaskUtil { fun getDTaskUtil(filePath: Uri): ITaskAdapter {
var util = TaskCachePool.getTaskUtil(filePath) var util = TaskCachePool.getTaskAdapter(filePath)
if (util == null) { if (util == null) {
util = HttpDTaskUtil() util = HttpDTaskAdapter()
TaskCachePool.putTaskUtil(filePath, util) TaskCachePool.putTaskUtil(filePath, util)
} }
return util return util

@ -21,13 +21,12 @@ import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.group.AbsGroupLoader; import com.arialyy.aria.core.group.AbsGroupLoader;
import com.arialyy.aria.core.group.AbsSubDLoadUtil; import com.arialyy.aria.core.group.AbsSubDLoadAdapter;
import com.arialyy.aria.core.listener.DownloadGroupListener; import com.arialyy.aria.core.listener.DownloadGroupListener;
import com.arialyy.aria.core.loader.IInfoTask; import com.arialyy.aria.core.loader.IInfoTask;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper; import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.exception.AriaException; import com.arialyy.aria.exception.AriaException;
import com.arialyy.aria.exception.AriaHTTPException; import com.arialyy.aria.exception.AriaHTTPException;
import java.io.File;
/** /**
* http 组合任务加载器 * http 组合任务加载器
@ -45,8 +44,9 @@ final class HttpDGLoader extends AbsGroupLoader {
} }
@Override @Override
protected AbsSubDLoadUtil createSubLoader(DTaskWrapper wrapper, boolean needGetFileInfo) { protected AbsSubDLoadAdapter createSubLoader(DTaskWrapper wrapper, boolean needGetFileInfo) {
HttpSubDLoaderUtil subUtil = new HttpSubDLoaderUtil(getScheduler(), needGetFileInfo, getKey()); HttpSubDLoaderAdapter
subUtil = new HttpSubDLoaderAdapter(getScheduler(), needGetFileInfo, getKey());
subUtil.setParams(wrapper, null); subUtil.setParams(wrapper, null);
return subUtil; return subUtil;
} }

@ -1,45 +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.http.download;
import com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.group.AbsGroupLoader;
import com.arialyy.aria.core.group.AbsGroupLoaderUtil;
import com.arialyy.aria.core.listener.DownloadGroupListener;
import com.arialyy.aria.core.loader.LoaderStructure;
import com.arialyy.aria.http.HttpTaskOption;
/**
* Created by AriaL on 2017/6/30.
* 任务组下载工具
*/
public final class HttpDGLoaderUtil extends AbsGroupLoaderUtil {
@Override protected AbsGroupLoader getLoader() {
if (mLoader == null) {
getTaskWrapper().generateTaskOption(HttpTaskOption.class);
mLoader = new HttpDGLoader(getTaskWrapper(), (DownloadGroupListener) getListener());
}
return mLoader;
}
@Override protected LoaderStructure buildLoaderStructure() {
LoaderStructure structure = new LoaderStructure();
structure.addComponent(new HttpDGInfoTask((DGTaskWrapper) getTaskWrapper()));
structure.accept(getLoader());
return structure;
}
}

@ -84,13 +84,8 @@ class HttpDStartController(target: Any, val url: String) : HttpBaseStartControll
if (HttpUtil.checkHttpDParams(httpTaskOption)) { if (HttpUtil.checkHttpDParams(httpTaskOption)) {
throw IllegalArgumentException("invalid params") throw IllegalArgumentException("invalid params")
} }
val savePath = httpTaskOption.savePathUri!! val task = DownloadTask(httpTaskOption)
var util = TaskCachePool.getTaskUtil(savePath) task.adapter = HttpDTaskAdapter()
if (util == null) {
util = HttpDTaskUtil()
TaskCachePool.putTaskUtil(savePath, util)
}
val task = DownloadTask(httpTaskOption, util)
DuaContext.duaScope.launch { DuaContext.duaScope.launch {
val dEntity = findDEntityBySavePath(httpTaskOption) val dEntity = findDEntityBySavePath(httpTaskOption)
TaskCachePool.putEntity(task.taskId, dEntity) TaskCachePool.putEntity(task.taskId, dEntity)

@ -16,6 +16,7 @@
package com.arialyy.aria.http.download package com.arialyy.aria.http.download
import android.net.Uri import android.net.Uri
import com.arialyy.aria.core.command.StopCmd
import com.arialyy.aria.core.task.TaskCachePool import com.arialyy.aria.core.task.TaskCachePool
import timber.log.Timber import timber.log.Timber
@ -41,7 +42,7 @@ class HttpDStopController(val taskId: Int) {
Timber.e("task not found, taskId: $taskId") Timber.e("task not found, taskId: $taskId")
return return
} }
HttpDStopController2(Uri.parse(task.filePath)).stop() StopCmd(task).executeCmd()
} }
fun resume() { fun resume() {
@ -50,7 +51,7 @@ class HttpDStopController(val taskId: Int) {
Timber.e("task not found, taskId: $taskId") Timber.e("task not found, taskId: $taskId")
return return
} }
val util = TaskCachePool.getTaskUtil(Uri.parse(task.filePath)) val util = TaskCachePool.getTaskAdapter(Uri.parse(task.filePath))
if (util == null) { if (util == null) {
Timber.e("resume fail, please restart task, taskId: $taskId") Timber.e("resume fail, please restart task, taskId: $taskId")
return return

@ -17,7 +17,11 @@ package com.arialyy.aria.http.download
import android.net.Uri import android.net.Uri
import com.arialyy.aria.core.DuaContext import com.arialyy.aria.core.DuaContext
import com.arialyy.aria.http.HttpUtil import com.arialyy.aria.core.command.CancelCmd
import com.arialyy.aria.core.command.StopCmd
import com.arialyy.aria.core.common.TaskOption
import com.arialyy.aria.core.task.DownloadTask
import com.arialyy.aria.core.task.TaskCachePool
import com.arialyy.aria.util.FileUtils import com.arialyy.aria.util.FileUtils
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -50,7 +54,14 @@ class HttpDStopController2(val filePath: Uri) {
fun cancel() { fun cancel() {
DuaContext.duaScope.launch { DuaContext.duaScope.launch {
if (checkUri()) { if (checkUri()) {
HttpUtil.getDTaskUtil(filePath).cancel() var task = TaskCachePool.findTaskByPath(filePath)
if (task == null) {
Timber.i("task not exist, create new task")
task = DownloadTask(TaskOption())
task.adapter = HttpDTaskAdapter()
}
TaskCachePool.putTask(task)
CancelCmd(task).executeCmd()
} }
} }
} }
@ -58,8 +69,15 @@ class HttpDStopController2(val filePath: Uri) {
fun stop() { fun stop() {
DuaContext.duaScope.launch { DuaContext.duaScope.launch {
if (checkUri()) { if (checkUri()) {
HttpUtil.getDTaskUtil(filePath).stop() TaskCachePool.findTaskByPath(filePath)?.let {
StopCmd(it).executeCmd()
return@launch
}
Timber.e("not found task, uri: $filePath")
return@launch
} }
Timber.e("stop fail, invalid uri: $filePath")
} }
} }
} }

@ -18,7 +18,7 @@ package com.arialyy.aria.http.download
import android.os.Looper import android.os.Looper
import com.arialyy.aria.core.DuaContext import com.arialyy.aria.core.DuaContext
import com.arialyy.aria.core.inf.IBlockManager import com.arialyy.aria.core.inf.IBlockManager
import com.arialyy.aria.core.task.AbsTaskUtil import com.arialyy.aria.core.task.AbsTaskAdapter
import com.arialyy.aria.core.task.BlockManager import com.arialyy.aria.core.task.BlockManager
import com.arialyy.aria.core.task.DownloadTask import com.arialyy.aria.core.task.DownloadTask
import com.arialyy.aria.core.task.TaskResp import com.arialyy.aria.core.task.TaskResp
@ -33,7 +33,7 @@ import kotlinx.coroutines.launch
* @Description * @Description
* @Date 1:47 PM 2023/1/28 * @Date 1:47 PM 2023/1/28
**/ **/
internal class HttpDTaskUtil : AbsTaskUtil() { internal class HttpDTaskAdapter : AbsTaskAdapter() {
private var blockManager: BlockManager? = null private var blockManager: BlockManager? = null

@ -17,7 +17,7 @@ package com.arialyy.aria.http.download;
import android.os.Handler; import android.os.Handler;
import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.group.AbsSubDLoadUtil; import com.arialyy.aria.core.group.AbsSubDLoadAdapter;
import com.arialyy.aria.core.group.SubRecordHandler; import com.arialyy.aria.core.group.SubRecordHandler;
import com.arialyy.aria.core.loader.GroupSubThreadStateManager; import com.arialyy.aria.core.loader.GroupSubThreadStateManager;
import com.arialyy.aria.core.loader.LoaderStructure; import com.arialyy.aria.core.loader.LoaderStructure;
@ -28,12 +28,12 @@ import com.arialyy.aria.core.loader.SubLoader;
* @author lyy * @author lyy
* Date: 2019-09-28 * Date: 2019-09-28
*/ */
final class HttpSubDLoaderUtil extends AbsSubDLoadUtil { final class HttpSubDLoaderAdapter extends AbsSubDLoadAdapter {
/** /**
* @param schedulers 调度器 * @param schedulers 调度器
* @param needGetInfo {@code true} 需要获取文件信息{@code false} 不需要获取文件信息 * @param needGetInfo {@code true} 需要获取文件信息{@code false} 不需要获取文件信息
*/ */
HttpSubDLoaderUtil( Handler schedulers, boolean needGetInfo, String parentKey) { HttpSubDLoaderAdapter( Handler schedulers, boolean needGetInfo, String parentKey) {
super(schedulers, needGetInfo, parentKey); super(schedulers, needGetInfo, parentKey);
} }

@ -18,14 +18,12 @@ package com.arialyy.aria.http.upload
import android.os.Looper import android.os.Looper
import com.arialyy.aria.core.DuaContext import com.arialyy.aria.core.DuaContext
import com.arialyy.aria.core.inf.IBlockManager import com.arialyy.aria.core.inf.IBlockManager
import com.arialyy.aria.core.task.AbsTaskUtil import com.arialyy.aria.core.task.AbsTaskAdapter
import com.arialyy.aria.core.task.BlockManager import com.arialyy.aria.core.task.BlockManager
import com.arialyy.aria.core.task.TaskResp import com.arialyy.aria.core.task.TaskResp
import com.arialyy.aria.exception.AriaException import com.arialyy.aria.exception.AriaException
import com.arialyy.aria.http.HttpTaskOption import com.arialyy.aria.http.HttpTaskOption
import com.arialyy.aria.http.download.HttpBlockThreadInterceptor import com.arialyy.aria.http.download.HttpBlockThreadInterceptor
import com.arialyy.aria.http.download.HttpDBlockInterceptor
import com.arialyy.aria.http.download.HttpDHeaderInterceptor
import com.arialyy.aria.http.download.TimerInterceptor import com.arialyy.aria.http.download.TimerInterceptor
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -35,7 +33,7 @@ import kotlinx.coroutines.launch
* @Description * @Description
* @Date 9:21 PM 2023/2/21 * @Date 9:21 PM 2023/2/21
**/ **/
class HttpUTaskUtil : AbsTaskUtil() { class HttpUTaskAdapter : AbsTaskAdapter() {
private var blockManager: BlockManager? = null private var blockManager: BlockManager? = null
override fun getBlockManager(): IBlockManager { override fun getBlockManager(): IBlockManager {

@ -16,14 +16,14 @@
package com.arialyy.dua.group package com.arialyy.dua.group
import com.arialyy.aria.core.inf.IBlockManager import com.arialyy.aria.core.inf.IBlockManager
import com.arialyy.aria.core.task.AbsTaskUtil import com.arialyy.aria.core.task.AbsTaskAdapter
/** /**
* @Author laoyuyu * @Author laoyuyu
* @Description * @Description
* @Date 21:58 2023/2/20 * @Date 21:58 2023/2/20
**/ **/
internal class DGroupUtil : AbsTaskUtil() { internal class DGroupAdapter : AbsTaskAdapter() {
override fun getBlockManager(): IBlockManager { override fun getBlockManager(): IBlockManager {
TODO("Not yet implemented") TODO("Not yet implemented")
} }

@ -1,132 +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 com.arialyy.aria.core.common.BaseOption;
import com.arialyy.aria.core.inf.IEventHandler;
import com.arialyy.aria.core.inf.IOptionConstant;
import com.arialyy.aria.core.processor.FtpInterceptHandler;
import com.arialyy.aria.core.processor.IBandWidthUrlConverter;
import com.arialyy.aria.core.processor.IFtpUploadInterceptor;
import com.arialyy.aria.core.processor.IHttpFileLenAdapter;
import com.arialyy.aria.core.processor.IHttpFileNameAdapter;
import com.arialyy.aria.core.processor.IKeyUrlConverter;
import com.arialyy.aria.core.processor.ILiveTsUrlConverter;
import com.arialyy.aria.core.processor.ITsMergeHandler;
import com.arialyy.aria.core.processor.IVodTsUrlConverter;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 任务配置参数
*
* @author lyy
* Date: 2019-09-10
*/
public class TaskOptionParams {
private static List<Class> PROCESSORES = new ArrayList<>();
/**
* 普通参数
*/
private Map<String, Object> params = new HashMap<>();
/**
* 事件处理对象
*/
private Map<String, IEventHandler> handler = new HashMap<>();
static {
PROCESSORES.add(FtpInterceptHandler.class);
PROCESSORES.add(IBandWidthUrlConverter.class);
PROCESSORES.add(IFtpUploadInterceptor.class);
PROCESSORES.add(IHttpFileLenAdapter.class);
PROCESSORES.add(IHttpFileNameAdapter.class);
PROCESSORES.add(ILiveTsUrlConverter.class);
PROCESSORES.add(ITsMergeHandler.class);
PROCESSORES.add(IVodTsUrlConverter.class);
PROCESSORES.add(IKeyUrlConverter.class);
}
/**
* 设置任务参数
*
* @param option 任务配置
*/
public void setParams(BaseOption option) {
List<Field> fields = CommonUtil.getAllFields(option.getClass());
for (Field field : fields) {
field.setAccessible(true);
try {
if (PROCESSORES.contains(field.getType())) {
Object eventHandler = field.get(option);
if (eventHandler != null) {
setObjs(field.getName(), (IEventHandler) eventHandler);
}
} else {
Object params = field.get(option);
if (params != null) {
setParams(field.getName(), params);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 设置普通参数
*
* @param key {@link IOptionConstant}
*/
public TaskOptionParams setParams(String key, Object value) {
params.put(key, value);
return this;
}
/**
* 设置对象参数
*/
public TaskOptionParams setObjs(String key, IEventHandler handler) {
this.handler.put(key, handler);
return this;
}
public Map<String, Object> getParams() {
return params;
}
public Object getParam(String key) {
return params.get(key);
}
public IEventHandler getHandler(String key) {
return handler.get(key);
}
public Map<String, IEventHandler> getHandler() {
return handler;
}
}

@ -1,91 +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 com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.orm.annotation.Ignore;
import com.arialyy.aria.orm.annotation.NoNull;
import com.arialyy.aria.orm.annotation.Unique;
import java.util.List;
/**
* Created by laoyuyu on 2018/3/21.
* 任务上传或下载的任务记录
*/
public class TaskRecord extends DbEntity {
//public static final int TYPE_HTTP_FTP = 0;
//public static final int TYPE_M3U8_VOD = 1;
//public static final int TYPE_M3U8_LIVE = 2;
@Ignore
public List<ThreadRecord> threadRecords;
/**
* 任务线程数
*/
public int threadNum;
/**
* 任务文件路径
*/
public String filePath;
/**
* 文件长度
*/
public long fileLength;
/**
* 任务文件名
*/
@NoNull
public String fileName;
/**
* 是否是任务组的子任务记录
* {@code true}
*/
public boolean isGroupRecord = false;
/**
* 下载任务组名
*/
public String dGroupHash;
/**
* 上传组任务名暂时没有用
*/
@Ignore
@Deprecated
public String uGroupHash;
/**
* 是否是分块{@code true}{@code false} 不是
*/
public boolean isBlock = false;
/**
* 任务类型
* {@link ITaskWrapper}
*/
public int taskType = 0;
/**
* m3u8文件码率
*/
public long bandWidth = 0;
}

@ -1,68 +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 com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.DbEntity;
/**
* Created by laoyuyu on 2018/5/8.
* 任务的线程记录
*/
public class ThreadRecord extends DbEntity {
/**
* 任务的文件路径不是当前线程记录的的分块文件路径
*/
public String taskKey;
/**
* 开始位置
*/
public long startLocation;
/**
* 结束位置
*/
public long endLocation;
/**
* 线程是否完成
* {@code true}完成{@code false}未完成
*/
public boolean isComplete = false;
/**
* 线程id
*/
public int threadId = 0;
/**
* 分块长度
*/
public long blockLen = 0;
/**
* 线程类型
* {@link ITaskWrapper}
*/
public int threadType = 0;
/**
* ts文件的下载地址
*/
public String tsUrl;
}

@ -21,6 +21,7 @@ import com.arialyy.aria.core.inf.ITaskQueue;
import com.arialyy.aria.core.task.ITask; import com.arialyy.aria.core.task.ITask;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import timber.log.Timber;
/** /**
* Created by AriaL on 2017/6/29. * Created by AriaL on 2017/6/29.
@ -53,8 +54,13 @@ public abstract class AbsCmd implements ICmd {
* if interruption occurred, stop cmd * if interruption occurred, stop cmd
*/ */
protected CmdResp interceptor() { protected CmdResp interceptor() {
if (mTask == null) {
Timber.e("task is null");
return new CmdResp(CmdResp.CODE_TASK_NOT_FOUND);
}
if (userInterceptors == null || userInterceptors.isEmpty()) { if (userInterceptors == null || userInterceptors.isEmpty()) {
return null; Timber.e("not any interceptor");
return new CmdResp(CmdResp.CODE_INTERRUPT);
} }
List<ICmdInterceptor> interceptors = new ArrayList<>(); List<ICmdInterceptor> interceptors = new ArrayList<>();
interceptors.addAll(userInterceptors); interceptors.addAll(userInterceptors);
@ -64,6 +70,10 @@ public abstract class AbsCmd implements ICmd {
} }
public ITaskQueue<ITask> getTaskQueue() { public ITaskQueue<ITask> getTaskQueue() {
if (mTask == null) {
Timber.e("task is null");
return null;
}
ITaskQueue<?> itq = null; ITaskQueue<?> itq = null;
switch (mTask.getTaskType()) { switch (mTask.getTaskType()) {
case ITask.DOWNLOAD: { case ITask.DOWNLOAD: {

@ -1,32 +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 com.arialyy.aria.core.task.ITask;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
/**
* Created by AriaL on 2017/6/29.
* 抽象命令工厂
*/
public abstract class AbsCmdFactory<TASK_ENTITY extends AbsTaskWrapper, CMD extends AbsCmd> {
/**
* @param entity 下载实体
* {@link ITask#DOWNLOAD}{@link ITask#DOWNLOAD_GROUP}{@link ITask#UPLOAD}
*/
public abstract CMD createCmd(TASK_ENTITY entity, int type, int taskType);
}

@ -1,198 +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 com.arialyy.aria.core.download.DGTaskWrapper;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.task.ITask;
import com.arialyy.aria.core.queue.DGroupTaskQueue;
import com.arialyy.aria.core.queue.DTaskQueue;
import com.arialyy.aria.core.queue.UTaskQueue;
import com.arialyy.aria.core.listener.ISchedulers;
import com.arialyy.aria.core.upload.UTaskWrapper;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
/**
* Created by lyy on 2016/8/22. 下载命令
*/
public abstract class AbsNormalCmd<T extends AbsTaskWrapper> extends AbsCmd<T> {
/**
* 能否执行命令
*/
boolean canExeCmd = true;
int taskType;
/**
* @param taskType 下载任务类型{@link ITask#DOWNLOAD}{@link ITask#DOWNLOAD_GROUP}{@link
* ITask#UPLOAD}
*/
AbsNormalCmd(T entity, int taskType) {
this.taskType = taskType;
mTaskWrapper = entity;
TAG = CommonUtil.getClassName(this);
if (taskType == ITask.DOWNLOAD) {
if (!(entity instanceof DTaskWrapper)) {
ALog.e(TAG, "任务类型错误,任务类型应该为ICM.TASK_TYPE_DOWNLOAD");
return;
}
mQueue = DTaskQueue.getInstance();
} else if (taskType == ITask.DOWNLOAD_GROUP) {
if (!(entity instanceof DGTaskWrapper)) {
ALog.e(TAG, "任务类型错误,任务类型应该为ICM.TASK_TYPE_DOWNLOAD_GROUP");
return;
}
mQueue = DGroupTaskQueue.getInstance();
} else if (taskType == ITask.UPLOAD) {
if (!(entity instanceof UTaskWrapper)) {
ALog.e(TAG, "任务类型错误,任务类型应该为ICM.TASK_TYPE_UPLOAD");
return;
}
mQueue = UTaskQueue.getInstance();
} else {
ALog.e(TAG, "任务类型错误,任务类型应该为ICM.TASK_TYPE_DOWNLOAD、TASK_TYPE_DOWNLOAD_GROUP、TASK_TYPE_UPLOAD");
return;
}
isDownloadCmd = taskType == ITask.DOWNLOAD || taskType == ITask.DOWNLOAD_GROUP;
}
/**
* 发送等待状态
*/
void sendWaitState() {
AbsTask task = getTask();
if (task == null) {
task = createTask();
}
sendWaitState(task);
}
/**
* 发送等待状态
*/
void sendWaitState(AbsTask task) {
if (task != null) {
task.getTaskWrapper().setState(IEntity.STATE_WAIT);
task.getOutHandler().obtainMessage(ISchedulers.WAIT, task).sendToTarget();
}
}
/**
* 停止所有任务
*/
void stopAll() {
mQueue.stopAllTask();
}
/**
* 停止任务
*/
void stopTask() {
AbsTask task = getTask();
if (task == null) {
task = createTask();
}
mQueue.stopTask(task);
}
/**
* 删除任务
*/
void removeTask() {
AbsTask task = getTask();
if (task == null) {
task = createTask();
}
mQueue.cancelTask(task);
}
/**
* 删除任务
*/
void removeTask(AbsTaskWrapper wrapper) {
AbsTask tempTask = getTask(wrapper.getKey());
if (tempTask == null) {
tempTask = createTask(wrapper);
}
mQueue.cancelTask(tempTask);
}
/**
* 启动任务
*/
void startTask() {
AbsTask task = getTask();
if (task == null) {
task = createTask();
}
mQueue.startTask(task);
}
/**
* 恢复任务
*/
void resumeTask() {
AbsTask task = getTask();
if (task == null) {
task = createTask();
}
mQueue.resumeTask(task);
}
/**
* 从队列中获取任务
*
* @return 执行任务
*/
AbsTask getTask() {
return mQueue.getTask(mTaskWrapper.getEntity().getKey());
}
/**
* 从队列中获取任务
*
* @return 执行任务
*/
AbsTask getTask(String key) {
return mQueue.getTask(key);
}
/**
* 创建任务
*
* @return 创建的任务
*/
AbsTask createTask() {
return mQueue.createTask(mTaskWrapper);
}
/**
* 创建指定实体的任务
*
* @param wrapper 特定的任务实体
* @return 创建的任务
*/
AbsTask createTask(AbsTaskWrapper wrapper) {
return mQueue.createTask(wrapper);
}
}

@ -16,33 +16,35 @@
package com.arialyy.aria.core.command; package com.arialyy.aria.core.command;
import com.arialyy.aria.core.task.AbsTask; import com.arialyy.aria.core.DuaContext
import com.arialyy.aria.core.wrapper.AbsTaskWrapper; import com.arialyy.aria.core.task.ITask
import com.arialyy.aria.core.task.ThreadTaskManager2
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import timber.log.Timber
/** /**
* Created by lyy on 2016/9/20. * Created by lyy on 2016/9/20.
* 取消命令 * 取消命令
*/ */
final public class CancelCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> { class CancelCmd(task: ITask) : AbsCmd(task) {
/**
* removeFile {@code true} 删除已经下载完成的任务不仅删除下载记录还会删除已经下载完成的文件{@code false}
* 如果文件已经下载完成只删除下载记录
*/
public boolean removeFile = false;
CancelCmd(T entity, int taskType) { override fun executeCmd(): CmdResp {
super(entity, taskType); val resp = interceptor()
} if (resp.isInterrupt()) {
Timber.w("interruption occurred, cancel cmd")
return resp
}
@Override public void executeCmd() { if (!taskQueue.taskIsRunning(mTask?.taskId ?: -1)) {
if (!canExeCmd) return; // remove already file
AbsTask task = getTask();
if (task == null) { return CmdResp(CmdResp.CODE_COMPLETE)
task = createTask();
} }
if (task != null) { DuaContext.duaScope.launch(Dispatchers.IO) {
mTaskWrapper.setRemoveFile(removeFile); ThreadTaskManager2.stopThreadTask(mTask!!.taskId, true)
removeTask();
} }
return CmdResp(CmdResp.CODE_COMPLETE)
} }
} }

@ -25,6 +25,7 @@ class CmdResp(val code: Int = CODE_DEF) {
const val CODE_COMPLETE = 1 const val CODE_COMPLETE = 1
const val CODE_INTERRUPT = 999 const val CODE_INTERRUPT = 999
const val CODE_DEF = 0 const val CODE_DEF = 0
const val CODE_TASK_NOT_FOUND = 2
} }
/** /**

@ -1,114 +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 com.arialyy.aria.core.task.ITask;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
/**
* Created by Lyy on 2016/9/23.
* 命令工厂
*/
public class NormalCmdFactory extends AbsCmdFactory<AbsTaskWrapper, AbsNormalCmd> {
/**
* 创建任务
*/
public static final int TASK_CREATE = 0xb1;
/**
* 启动任务
*/
public static final int TASK_START = 0xb2;
/**
* 恢复任务
*/
public static final int TASK_RESUME = 0xb3;
/**
* 取消任务
*/
public static final int TASK_CANCEL = 0xb4;
/**
* 停止任务
*/
public static final int TASK_STOP = 0xb5;
/**
* 设置任务为最高优先级
*/
public static final int TASK_HIGHEST_PRIORITY = 0xb6;
/**
* 停止所有任务
*/
public static final int TASK_STOP_ALL = 0xb7;
/**
* 恢复所有停止的任务
*/
public static final int TASK_RESUME_ALL = 0xb8;
/**
* 删除所有任务
*/
public static final int TASK_CANCEL_ALL = 0xb9;
/**
* 重启任务
*/
public static final int TASK_RESTART = 0xba;
private static volatile NormalCmdFactory INSTANCE = null;
private NormalCmdFactory() {
}
public static NormalCmdFactory getInstance() {
if (INSTANCE == null) {
synchronized (NormalCmdFactory.class) {
INSTANCE = new NormalCmdFactory();
}
}
return INSTANCE;
}
/**
* @param entity 下载实体
* @param type 命令类型{@link #TASK_CREATE}{@link #TASK_START}{@link #TASK_CANCEL}{@link
* #TASK_STOP}{@link #TASK_HIGHEST_PRIORITY}{@link #TASK_STOP_ALL}{@link #TASK_RESUME_ALL}
* @param taskType {@link ITask#DOWNLOAD}{@link ITask#DOWNLOAD_GROUP}{@link ITask#UPLOAD}
*/
public AbsNormalCmd createCmd(AbsTaskWrapper entity, int type, int taskType) {
switch (type) {
case TASK_CREATE:
return new AddCmd<>(entity, taskType);
case TASK_RESUME:
case TASK_START:
return new StartCmd<>(entity, taskType);
case TASK_CANCEL:
return new CancelCmd<>(entity, taskType);
case TASK_STOP:
return new StopCmd<>(entity, taskType);
case TASK_HIGHEST_PRIORITY:
return new HighestPriorityCmd<>(entity, taskType);
case TASK_STOP_ALL:
return new StopAllCmd<>(entity, taskType);
case TASK_RESUME_ALL:
return new ResumeAllCmd<>(entity, taskType);
case TASK_CANCEL_ALL:
return new CancelAllCmd<>(entity, taskType);
case TASK_RESTART:
return new ReStartCmd<>(entity, taskType);
default:
return null;
}
}
}

@ -1,47 +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 com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.util.ALog;
/**
* Created by lyy on 2016/9/20.
* 停止命令
*/
final class StopCmd<T extends AbsTaskWrapper> extends AbsNormalCmd<T> {
StopCmd(T entity, int taskType) {
super(entity, taskType);
}
@Override public void executeCmd() {
if (!canExeCmd) return;
AbsTask task = getTask();
if (task == null) {
if (mTaskWrapper.getEntity().getState() == IEntity.STATE_RUNNING) {
stopTask();
} else {
ALog.w(TAG, "停止命令执行失败,【调度器中没有该任务】");
}
} else {
stopTask();
}
}
}

@ -0,0 +1,50 @@
/*
* 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 com.arialyy.aria.core.DuaContext
import com.arialyy.aria.core.command.CmdResp.Companion.CODE_COMPLETE
import com.arialyy.aria.core.command.CmdResp.Companion.CODE_INTERRUPT
import com.arialyy.aria.core.task.ITask
import com.arialyy.aria.core.task.ThreadTaskManager2
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import timber.log.Timber
/**
* Created by lyy on 2016/9/20.
* 停止命令
*/
class StopCmd(task: ITask) : AbsCmd(task) {
override fun executeCmd(): CmdResp {
val resp = interceptor()
if (resp.isInterrupt()) {
Timber.w("interruption occurred, cancel cmd");
return resp;
}
if (!taskQueue.taskIsRunning(mTask?.taskId ?: -1)) {
Timber.e("task not running")
return CmdResp(CODE_INTERRUPT)
}
DuaContext.duaScope.launch(Dispatchers.IO) {
ThreadTaskManager2.stopThreadTask(mTask!!.taskId)
}
return CmdResp(CODE_COMPLETE)
}
}

@ -1,267 +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.common;
import android.os.Parcel;
import android.os.Parcelable;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.orm.annotation.Default;
import com.arialyy.aria.orm.annotation.Ignore;
import java.io.Serializable;
/**
* Created by AriaL on 2017/6/29.
*/
public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable, Serializable {
/**
* 速度
*/
@Ignore private long speed = 0;
/**
* 单位转换后的速度
*/
@Ignore private String convertSpeed;
/**
* 下载失败计数每次开始都重置为0
*/
@Ignore private int failNum = 0;
/**
* 剩余时间单位s
*/
@Ignore private int timeLeft = Integer.MAX_VALUE;
/**
* 扩展字段
*/
private String str;
/**
* 文件大小
*/
private long fileSize = 0;
/**
* 转换后的文件大小
*/
private String convertFileSize;
/**
* 任务状态{@link IEntity}
*/
@Default("3")
private int state = STATE_WAIT;
/**
* 当前下载进度
*/
private long currentProgress = 0;
/**
* 完成时间
*/
private long completeTime;
/**
* 进度百分比
*/
private int percent;
@Default("false")
private boolean isComplete = false;
/**
* 上一次停止时间
*/
private long stopTime = 0;
@Ignore
private int netCode = 200;
public int getNetCode() {
return netCode;
}
public void setNetCode(int netCode) {
this.netCode = netCode;
}
/**
* 获取剩余时间单位s
* 如果是m3u8任务无法获取剩余时间m2u8任务如果需要获取剩余时间请设置文件长度{@link #setFileSize(long)}
*/
public int getTimeLeft() {
return timeLeft;
}
public void setTimeLeft(int timeLeft) {
this.timeLeft = timeLeft;
}
public boolean isComplete() {
return isComplete;
}
public void setComplete(boolean complete) {
isComplete = complete;
}
public String getConvertFileSize() {
return convertFileSize;
}
public void setConvertFileSize(String convertFileSize) {
this.convertFileSize = convertFileSize;
}
public int getFailNum() {
return failNum;
}
public void setFailNum(int failNum) {
this.failNum = failNum;
}
public long getSpeed() {
return speed;
}
public void setSpeed(long speed) {
this.speed = speed;
}
public String getConvertSpeed() {
return convertSpeed;
}
public void setConvertSpeed(String convertSpeed) {
this.convertSpeed = convertSpeed;
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public long getFileSize() {
return fileSize;
}
public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public long getCurrentProgress() {
return currentProgress;
}
public void setCurrentProgress(long currentProgress) {
this.currentProgress = currentProgress;
}
public long getCompleteTime() {
return completeTime;
}
public void setCompleteTime(long completeTime) {
this.completeTime = completeTime;
}
public int getPercent() {
return percent;
}
public void setPercent(int percent) {
this.percent = percent;
}
public long getStopTime() {
return stopTime;
}
public void setStopTime(long stopTime) {
this.stopTime = stopTime;
}
public long getId() {
return getRowID();
}
/**
* 实体唯一标识符
* 下载实体下载url
* 上传实体文件路径
* 下载任务组组名
* ftp文件夹下载下载url
*/
public abstract String getKey();
/**
* 实体驱动的下载任务类型
*
* @return {@link ITaskWrapper#D_FTP}{@link ITaskWrapper#D_FTP_DIR}{@link
* ITaskWrapper#U_HTTP}...
*/
public abstract int getTaskType();
public AbsEntity() {
}
@Override public int describeContents() {
return 0;
}
@Override public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(this.rowID);
dest.writeLong(this.speed);
dest.writeString(this.convertSpeed);
dest.writeInt(this.failNum);
dest.writeString(this.str);
dest.writeLong(this.fileSize);
dest.writeString(this.convertFileSize);
dest.writeInt(this.state);
dest.writeLong(this.currentProgress);
dest.writeLong(this.completeTime);
dest.writeInt(this.percent);
dest.writeByte(this.isComplete ? (byte) 1 : (byte) 0);
dest.writeLong(this.stopTime);
}
protected AbsEntity(Parcel in) {
this.rowID = in.readLong();
this.speed = in.readLong();
this.convertSpeed = in.readString();
this.failNum = in.readInt();
this.str = in.readString();
this.fileSize = in.readLong();
this.convertFileSize = in.readString();
this.state = in.readInt();
this.currentProgress = in.readLong();
this.completeTime = in.readLong();
this.percent = in.readInt();
this.isComplete = in.readByte() != 0;
this.stopTime = in.readLong();
}
}

@ -1,103 +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.common;
import android.os.Parcel;
import android.os.Parcelable;
import com.arialyy.aria.orm.annotation.Unique;
import java.util.ArrayList;
import java.util.List;
/**
* Created by AriaL on 2017/6/3.
*/
public abstract class AbsGroupEntity extends AbsEntity implements Parcelable {
/**
* 组合任务等hash为 为子任务地址相加的url的Md5
* ftpdir为ftpdir下载地址
*/
@Unique protected String groupHash;
/**
* 任务组别名
*/
private String alias;
/**
* 任务组下载文件的文件夹地址
*/
@Unique private String dirPath;
/**
* 子任务url地址
*/
private List<String> urls = new ArrayList<>();
public String getDirPath() {
return dirPath;
}
public void setDirPath(String dirPath) {
this.dirPath = dirPath;
}
public List<String> getUrls() {
return urls;
}
public void setUrls(List<String> urls) {
this.urls = urls;
}
/**
* 组合任务等hash为 为子任务地址相加的url的Md5
* ftpdir为ftpdir下载地址
*/
public String getGroupHash() {
return groupHash;
}
public String getAlias() {
return alias;
}
@Override public String getKey() {
return groupHash;
}
public void setAlias(String alias) {
this.alias = alias;
}
public AbsGroupEntity() {
}
@Override public int describeContents() {
return 0;
}
@Override public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(this.groupHash);
dest.writeString(this.alias);
}
protected AbsGroupEntity(Parcel in) {
super(in);
this.groupHash = in.readString();
this.alias = in.readString();
}
}

@ -1,125 +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.common;
import android.os.Parcel;
import android.os.Parcelable;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.annotation.Default;
/**
* Created by AriaL on 2017/6/3.
*/
public abstract class AbsNormalEntity extends AbsEntity implements Parcelable {
/**
* 服务器地址
*/
private String url;
/**
* 文件名
*/
private String fileName;
/**
* 是否是任务组里面的下载实体
*/
@Default("false")
private boolean isGroupChild = false;
@Default("false")
private boolean isRedirect = false; //是否重定向
private String redirectUrl; //重定向链接
/**
* 任务类型
* {@link ITaskWrapper}
*/
private int taskType;
public void setTaskType(int taskType) {
this.taskType = taskType;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public boolean isGroupChild() {
return isGroupChild;
}
public void setGroupChild(boolean groupChild) {
isGroupChild = groupChild;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public boolean isRedirect() {
return isRedirect;
}
public void setRedirect(boolean redirect) {
isRedirect = redirect;
}
public String getRedirectUrl() {
return redirectUrl;
}
public void setRedirectUrl(String redirectUrl) {
this.redirectUrl = redirectUrl;
}
public abstract String getFilePath();
public AbsNormalEntity() {
}
@Override public int describeContents() {
return 0;
}
@Override public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(this.url);
dest.writeString(this.fileName);
dest.writeByte(this.isGroupChild ? (byte) 1 : (byte) 0);
dest.writeByte(this.isRedirect ? (byte) 1 : (byte) 0);
dest.writeString(this.redirectUrl);
}
protected AbsNormalEntity(Parcel in) {
super(in);
this.url = in.readString();
this.fileName = in.readString();
this.isGroupChild = in.readByte() != 0;
this.isRedirect = in.readByte() != 0;
this.redirectUrl = in.readString();
}
}

@ -1,42 +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.common;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
/**
* Created by AriaL on 2018/3/3.
* 获取文件信息完成后 回调给下载线程的信息
*/
public class CompleteInfo {
/**
* 自定义的状态码
*/
public int code;
public ITaskWrapper wrapper;
public Object obj;
public CompleteInfo() {
}
public CompleteInfo(int code, ITaskWrapper wrapper) {
this.code = code;
this.wrapper = wrapper;
}
}

@ -1,33 +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.common;
public enum ErrorCode {
ERROR_CODE_NORMAL(0, "正常"), ERROR_CODE_TASK_ID_NULL(1, "任务id为空的错误码"),
ERROR_CODE_URL_NULL(2, "url 为空"), ERROR_CODE_URL_INVALID(3, "url 无效"),
ERROR_CODE_PAGE_NUM(4, "page和num不能小于1"), ERROR_CODE_GROUP_URL_NULL(5, "组合任务url列表为空"),
ERROR_CODE_UPLOAD_FILE_NULL(7, "上传文件不存在"),
ERROR_CODE_MEMBER_WARNING(8, "为了防止内存泄漏,请使用静态的成员类(public static class xxx)或文件类(A.java)"),
ERROR_CODE_TASK_NOT_EXIST(9, "任务信息不存在");
public int code;
public String msg;
ErrorCode(int code, String msg) {
this.code = code;
this.msg = msg;
}
}

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.download; package com.arialyy.aria.core.common;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;

@ -1,225 +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.common;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.loader.ILoaderVisitor;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.core.wrapper.RecordWrapper;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.DbDataHelper;
import com.arialyy.aria.util.FileUtil;
import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
/**
* 处理任务记录分配线程区间
*/
public abstract class RecordHandler implements IRecordHandler {
protected final String TAG = CommonUtil.getClassName(this);
@Deprecated private File mConfigFile;
private TaskRecord mTaskRecord;
private AbsTaskWrapper mTaskWrapper;
private AbsNormalEntity mEntity;
protected String mFilePath;
protected long mFileSize;
public RecordHandler(AbsTaskWrapper wrapper) {
mTaskWrapper = wrapper;
mEntity = (AbsNormalEntity) mTaskWrapper.getEntity();
}
public AbsTaskWrapper getWrapper() {
return mTaskWrapper;
}
public AbsNormalEntity getEntity() {
return mEntity;
}
@Override public void onPre() {
}
/**
* 获取任务记录如果任务记录存在检查任务记录
* 检查记录 对于分块任务 子分块不存在或被删除子线程将重新下载
* 对于普通任务 预下载文件不存在则任务任务呗删除
* 如果任务记录不存在或线程记录不存在初始化记录
*
* @return 任务记录
*/
@Override
public TaskRecord getRecord(long fileSize) {
mFileSize = fileSize;
mConfigFile = new File(CommonUtil.getFileConfigPath(false, mEntity.getFileName()));
if (mConfigFile.exists()) {
convertDb();
} else {
onPre();
mTaskRecord = DbDataHelper.getTaskRecord(getFilePath(), mEntity.getTaskType());
if (mTaskRecord == null) {
initRecord(true);
}else if (mTaskRecord.threadRecords == null || mTaskRecord.threadRecords.size() == 0){
if (mTaskRecord.threadRecords == null){
mTaskRecord.threadRecords = new ArrayList<>();
}
initRecord(false);
}
handlerTaskRecord(mTaskRecord);
}
saveRecord();
return mTaskRecord;
}
/**
* convertDb 是兼容性代码 从3.4.1开始线程配置信息将存储在数据库中 将配置文件的内容复制到数据库中并将配置文件删除
*/
private void convertDb() {
List<RecordWrapper> records =
DbEntity.findRelationData(RecordWrapper.class, "TaskRecord.filePath=?",
getFilePath());
if (records == null || records.size() == 0) {
Properties pro = FileUtil.loadConfig(mConfigFile);
if (pro.isEmpty()) {
ALog.d(TAG, "老版本的线程记录为空,任务为新任务");
initRecord(true);
return;
}
Set<Object> keys = pro.keySet();
// 老版本记录是5s存一次,但是5s中内,如果线程执行完成,record记录是没有的,只有state记录...
// 第一步应该是record 和 state去重取正确的线程数
Set<Integer> set = new HashSet<>();
for (Object key : keys) {
String str = String.valueOf(key);
int i = Integer.parseInt(str.substring(str.length() - 1));
set.add(i);
}
int threadNum = set.size();
if (threadNum == 0) {
ALog.d(TAG, "线程数为空,任务为新任务");
initRecord(true);
return;
}
mTaskWrapper.setNewTask(false);
mTaskRecord = createTaskRecord(threadNum);
mTaskRecord.isBlock = false;
File tempFile = new File(getFilePath());
for (int i = 0; i < threadNum; i++) {
ThreadRecord tRecord = new ThreadRecord();
tRecord.taskKey = mTaskRecord.filePath;
Object state = pro.getProperty(tempFile.getName() + STATE + i);
Object record = pro.getProperty(tempFile.getName() + RECORD + i);
if (state != null && Integer.parseInt(String.valueOf(state)) == 1) {
tRecord.isComplete = true;
continue;
}
if (record != null) {
long temp = Long.parseLong(String.valueOf(record));
tRecord.startLocation = temp > 0 ? temp : 0;
} else {
tRecord.startLocation = 0;
}
mTaskRecord.threadRecords.add(tRecord);
}
FileUtil.deleteFile(mConfigFile);
}
}
/**
* 初始化任务记录分配线程区间如果任务记录不存在则创建新的任务记录
*
* @param newRecord {@code true} 需要创建新{@link TaskRecord}
*/
private void initRecord(boolean newRecord) {
if (newRecord) {
mTaskRecord = createTaskRecord(initTaskThreadNum());
}
mTaskWrapper.setNewTask(true);
int requestType = mTaskWrapper.getRequestType();
if (requestType == ITaskWrapper.M3U8_LIVE) {
return;
}
long blockSize = getFileSize() / mTaskRecord.threadNum;
// 处理线程区间记录
for (int i = 0; i < mTaskRecord.threadNum; i++) {
long startL = i * blockSize, endL = (i + 1) * blockSize;
ThreadRecord tr = createThreadRecord(mTaskRecord, i, startL, endL);
mTaskRecord.threadRecords.add(tr);
}
}
/**
* 保存任务记录
*/
private void saveRecord() {
mTaskRecord.threadNum = mTaskRecord.threadRecords.size();
mTaskRecord.save();
if (mTaskRecord.threadRecords != null && !mTaskRecord.threadRecords.isEmpty()) {
DbEntity.saveAll(mTaskRecord.threadRecords);
}
ALog.d(TAG, String.format("保存记录,线程记录数:%s", mTaskRecord.threadRecords.size()));
}
protected long getFileSize() {
return mFileSize;
}
/**
* 获取任务路径
*
* @return 任务文件路径
*/
private String getFilePath() {
if (mEntity instanceof DownloadEntity) {
return ((DownloadEntity) mTaskWrapper.getEntity()).getFilePath();
} else {
return ((UploadEntity) mTaskWrapper.getEntity()).getFilePath();
}
}
@Override public void accept(ILoaderVisitor visitor) {
visitor.addComponent(this);
}
@Override public boolean checkTaskCompleted() {
if (mTaskRecord == null
|| mTaskRecord.threadRecords == null
|| mTaskRecord.threadRecords.isEmpty()) {
return false;
}
int completeNum = 0;
for (ThreadRecord tr : mTaskRecord.threadRecords) {
if (tr.isComplete) {
completeNum++;
}
}
return completeNum != 0 && completeNum == mTaskRecord.threadNum;
}
}

@ -1,207 +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.common;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.BufferedRandomAccessFile;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.FileUtil;
import java.io.File;
import java.io.IOException;
/**
* 任务记录帮助类用于处理统一的逻辑
*
* @author lyy
* Date: 2019-09-19
*/
public class RecordHelper {
private String TAG = CommonUtil.getClassName(getClass());
private AbsTaskWrapper mWrapper;
protected TaskRecord mTaskRecord;
public RecordHelper(AbsTaskWrapper wrapper, TaskRecord record) {
mWrapper = wrapper;
mTaskRecord = record;
}
/**
* 处理非分块的多线程任务
*/
public void handleMultiRecord() {
// 默认线程分块长度
long blockSize = mWrapper.getEntity().getFileSize() / mTaskRecord.threadRecords.size();
File temp = new File(mTaskRecord.filePath);
boolean fileExists = false;
if (!temp.exists()) {
createPlaceHolderFile(temp);
} else {
if (temp.length() != mWrapper.getEntity().getFileSize()) {
FileUtil.deleteFile(temp);
createPlaceHolderFile(temp);
}
fileExists = true;
}
// 处理文件被删除的情况
if (!fileExists) {
ALog.w(TAG, String.format("文件【%s】被删除,重新分配线程区间", mTaskRecord.filePath));
for (int i = 0; i < mTaskRecord.threadNum; i++) {
long startL = i * blockSize, endL = (i + 1) * blockSize;
ThreadRecord tr = mTaskRecord.threadRecords.get(i);
tr.startLocation = startL;
tr.isComplete = false;
//最后一个线程的结束位置即为文件的总长度
if (tr.threadId == (mTaskRecord.threadNum - 1)) {
endL = mWrapper.getEntity().getFileSize();
}
tr.endLocation = endL;
}
}
//mWrapper.setNewTask(false);
}
/**
* 创建非分块的占位文件
*/
private void createPlaceHolderFile(File temp) {
BufferedRandomAccessFile tempFile;
try {
tempFile = new BufferedRandomAccessFile(temp, "rw");
tempFile.setLength(mWrapper.getEntity().getFileSize());
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 处理分块任务的记录分块文件blockFileLen长度必须需要小于等于线程区间threadRectLen的长度
*/
public void handleBlockRecord() {
// 默认线程分块长度
long normalRectLen = mWrapper.getEntity().getFileSize() / mTaskRecord.threadRecords.size();
for (ThreadRecord tr : mTaskRecord.threadRecords) {
long threadRect = tr.blockLen;
File temp =
new File(String.format(IRecordHandler.SUB_PATH, mTaskRecord.filePath, tr.threadId));
if (!temp.exists()) {
ALog.i(TAG, String.format("分块文件【%s】不存在,该分块将重新开始", temp.getPath()));
tr.isComplete = false;
tr.startLocation = tr.threadId * normalRectLen;
} else {
if (!tr.isComplete) {
ALog.i(TAG, String.format(
"startLocation = %s; endLocation = %s; block = %s; tempLen = %s; threadId = %s",
tr.startLocation, tr.endLocation, threadRect, temp.length(), tr.threadId));
long blockFileLen = temp.length(); // 磁盘中的分块文件长度
/*
* 检查磁盘中的分块文件
*/
if (blockFileLen > threadRect) {
ALog.i(TAG, String.format("分块【%s】错误,分块长度【%s】 > 线程区间长度【%s】,将重新开始该分块",
tr.threadId, blockFileLen, threadRect));
temp.delete();
tr.startLocation = tr.threadId * threadRect;
continue;
}
//正常情况下,该线程的startLocation的位置
long realLocation = tr.threadId * normalRectLen + blockFileLen;
/*
* 检查记录文件
*/
if (blockFileLen == threadRect && blockFileLen != 0) {
ALog.i(TAG, String.format("分块【%s】已完成,更新记录", temp.getPath()));
tr.startLocation = blockFileLen;
tr.isComplete = true;
} else if (tr.startLocation != realLocation) { // 处理记录小于分块文件长度的情况
ALog.i(TAG, String.format("修正分块【%s】的进度记录为:%s", temp.getPath(), realLocation));
tr.startLocation = realLocation;
} else {
ALog.i(TAG, String.format("修正分块【%s】的进度记录为:%s", temp.getPath(), realLocation));
tr.startLocation = realLocation;
tr.isComplete = false;
}
} else {
ALog.i(TAG, String.format("分块【%s】已完成", temp.getPath()));
}
}
}
//mWrapper.setNewTask(false);
}
/**
* 处理单线程的任务的记录
*/
public void handleSingleThreadRecord() {
// mTaskRecord.isBlock是为了兼容以前的文件格式
File file = new File(
mTaskRecord.isBlock ? String.format(IRecordHandler.SUB_PATH, mTaskRecord.filePath, 0)
: mTaskRecord.filePath);
ThreadRecord tr = mTaskRecord.threadRecords.get(0);
if (!file.exists()) {
// 目标文件
File targetFile = new File(mTaskRecord.filePath);
// 处理组合任务其中一个子任务完成的情况
if (tr.isComplete
&& targetFile.exists()
&& targetFile.length() != 0
&& targetFile.length() == mWrapper.getEntity().getFileSize()) {
tr.isComplete = true;
} else {
ALog.w(TAG, String.format("文件【%s】不存在,任务将重新开始", file.getPath()));
tr.startLocation = 0;
tr.isComplete = false;
tr.endLocation = mWrapper.getEntity().getFileSize();
}
} else if (file.length() > mWrapper.getEntity().getFileSize()) {
ALog.i(TAG, String.format("文件【%s】错误,任务重新开始", file.getPath()));
FileUtil.deleteFile(file);
tr.startLocation = 0;
tr.isComplete = false;
tr.endLocation = mWrapper.getEntity().getFileSize();
} else if (file.length() != 0 && file.length() == mWrapper.getEntity().getFileSize()) {
ALog.d(TAG, "文件长度一致,线程完成");
tr.isComplete = true;
} else {
if (file.length() != tr.startLocation) {
ALog.i(TAG, String.format("修正【%s】的进度记录为:%s", file.getPath(), file.length()));
tr.startLocation = file.length();
tr.isComplete = false;
}
}
//mWrapper.setNewTask(false);
}
/**
* 处理不支持断点的记录
*/
public void handleNoSupportBPRecord() {
ThreadRecord tr = mTaskRecord.threadRecords.get(0);
tr.startLocation = 0;
tr.endLocation = mWrapper.getEntity().getFileSize();
tr.taskKey = mTaskRecord.filePath;
tr.blockLen = tr.endLocation;
tr.isComplete = false;
}
}

@ -1,113 +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.common;
import android.os.Handler;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import java.io.File;
/**
* 子线程下载信息类
*/
public class SubThreadConfig {
public static final int TYPE_HTTP = 1;
public static final int TYPE_FTP = 2;
public static final int TYPE_M3U8_PEER = 3;
public static final int TYPE_HTTP_DG_SUB = 4;
public static final int TYPE_FTP_DG_SUB = 5;
public AbsTaskWrapper taskWrapper;
public boolean isBlock = false;
// 启动的线程
public int startThreadNum;
// 真正的下载地址,如果是30x,则是30x后的地址
public String url;
public File tempFile;
// 线程记录
public ThreadRecord record;
// 状态处理器
public Handler stateHandler;
// m3u8切片索引
public int peerIndex;
// 线程任务类型
public int threadType = TYPE_HTTP;
// 进度更新间隔,单位:毫秒
public long updateInterval = 1000;
// 扩展数据
public Object obj;
// 忽略失败
public boolean ignoreFailure = false;
/**
* 转换线程任务类型
*
* @param requestType {@link AbsTaskWrapper#getRequestType()}
* @return {@link #threadType}
*/
public static int getThreadType(int requestType) {
int threadType = SubThreadConfig.TYPE_HTTP;
switch (requestType) {
case ITaskWrapper.D_HTTP:
case ITaskWrapper.U_HTTP:
threadType = SubThreadConfig.TYPE_HTTP;
break;
case ITaskWrapper.D_FTP:
case ITaskWrapper.U_FTP:
threadType = SubThreadConfig.TYPE_FTP;
break;
case ITaskWrapper.D_FTP_DIR:
threadType = SubThreadConfig.TYPE_FTP_DG_SUB;
break;
case ITaskWrapper.DG_HTTP:
threadType = SubThreadConfig.TYPE_HTTP_DG_SUB;
break;
case ITaskWrapper.M3U8_LIVE:
case ITaskWrapper.M3U8_VOD:
threadType = SubThreadConfig.TYPE_M3U8_PEER;
break;
}
return threadType;
}
/**
* 根据配置肚脐更新间隔
*
* @param requestType {@link AbsTaskWrapper#getRequestType()}
* @return {@link #updateInterval}
*/
public static long getUpdateInterval(int requestType) {
long updateInterval = 1000;
switch (requestType) {
case ITaskWrapper.D_HTTP:
case ITaskWrapper.D_FTP:
case ITaskWrapper.M3U8_LIVE:
case ITaskWrapper.M3U8_VOD:
updateInterval = AriaConfig.getInstance().getDConfig().getUpdateInterval();
break;
case ITaskWrapper.D_FTP_DIR:
case ITaskWrapper.DG_HTTP:
updateInterval = AriaConfig.getInstance().getDGConfig().getUpdateInterval();
break;
case ITaskWrapper.U_HTTP:
case ITaskWrapper.U_FTP:
updateInterval = AriaConfig.getInstance().getUConfig().getUpdateInterval();
}
return updateInterval;
}
}

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.download package com.arialyy.aria.core.common
import android.net.Uri import android.net.Uri
import com.arialyy.aria.core.inf.ITaskOption import com.arialyy.aria.core.inf.ITaskOption

@ -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.download;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import java.util.List;
/**
* 组合任务实体包裹器用于加载和任务相关的参数组合任务实体{@link DownloadGroupEntity}
*/
public abstract class AbsGroupTaskWrapper<ENTITY extends AbsEntity, SUB extends AbsTaskWrapper>
extends AbsTaskWrapper<ENTITY> {
public AbsGroupTaskWrapper(ENTITY entity) {
super(entity);
}
public abstract List<SUB> getSubTaskWrapper();
public abstract void setSubTaskWrapper(List<SUB> subTaskWrapper);
/**
* {@code true} 忽略任务冲突不考虑组任务hash冲突的情况
*/
private boolean ignoreTaskOccupy = false;
public boolean isIgnoreTaskOccupy() {
return ignoreTaskOccupy;
}
public void setIgnoreTaskOccupy(boolean ignoreTaskOccupy) {
this.ignoreTaskOccupy = ignoreTaskOccupy;
}
}

@ -1,44 +0,0 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.download;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.orm.AbsDbWrapper;
import com.arialyy.aria.orm.annotation.Many;
import com.arialyy.aria.orm.annotation.One;
import com.arialyy.aria.orm.annotation.Wrapper;
import java.util.List;
/**
* Created by laoyuyu on 2018/3/30.
* 任务组实体和子任务实体的关系
*/
@Wrapper
public class DGEntityWrapper extends AbsDbWrapper {
@One
public DownloadGroupEntity groupEntity;
@Many(parentColumn = "groupHash", entityColumn = "groupHash")
public List<DownloadEntity> subEntity;
@Override protected void handleConvert() {
if (subEntity != null && !subEntity.isEmpty()) {
groupEntity.setSubEntities(subEntity);
}
}
}

@ -1,89 +0,0 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.download;
import com.arialyy.aria.core.config.Configuration;
import com.arialyy.aria.core.config.DGroupConfig;
import java.util.ArrayList;
import java.util.List;
/**
* Created by AriaL on 2017/7/1. 任务组的任务实体修饰器
*/
public class DGTaskWrapper extends AbsGroupTaskWrapper<DownloadGroupEntity, DTaskWrapper> {
private List<DTaskWrapper> subWrappers;
private boolean unknownSize = false;
/**
* 保存临时设置的文件夹路径
*/
private String dirPathTemp;
/**
* 子任务文件名
*/
private List<String> subNameTemp = new ArrayList<>();
public DGTaskWrapper(DownloadGroupEntity entity) {
super(entity);
}
public List<String> getSubNameTemp() {
return subNameTemp;
}
public void setSubNameTemp(List<String> subNameTemp) {
this.subNameTemp = subNameTemp;
}
public String getDirPathTemp() {
return dirPathTemp;
}
public void setDirPathTemp(String mDirPathTemp) {
this.dirPathTemp = mDirPathTemp;
}
@Override
public void setSubTaskWrapper(List<DTaskWrapper> subTaskEntities) {
this.subWrappers = subTaskEntities;
}
public boolean isUnknownSize() {
return unknownSize;
}
public void setUnknownSize(boolean unknownSize) {
this.unknownSize = unknownSize;
}
@Override public String getKey() {
return getEntity().getKey();
}
@Override public DGroupConfig getConfig() {
return Configuration.getInstance().dGroupCfg;
}
@Override public List<DTaskWrapper> getSubTaskWrapper() {
if (subWrappers == null) {
subWrappers = new ArrayList<>();
}
return subWrappers;
}
}

@ -1,122 +0,0 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.download;
import com.arialyy.aria.core.TaskOptionParams;
import com.arialyy.aria.core.config.Configuration;
import com.arialyy.aria.core.config.DownloadConfig;
import com.arialyy.aria.core.inf.ITaskOption;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.util.ComponentUtil;
/**
* Created by lyy on 2017/1/23. 下载任务实体和下载实体为一对一关系下载实体删除任务实体自动删除
*/
public class DTaskWrapper extends AbsTaskWrapper<DownloadEntity> {
/**
* 所属的任务组组名如果不属于任务组则为null
*/
private String groupHash;
/**
* 该任务是否属于任务组
*/
private boolean isGroupTask = false;
/**
* M3u8任务配置信息
*/
private ITaskOption m3u8Option;
private TaskOptionParams m3u8Params = new TaskOptionParams();
/**
* 文件下载url的临时保存变量
*/
private String mTempUrl;
/**
* 文件保存路径的临时变量
*/
private String mTempFilePath;
public DTaskWrapper(DownloadEntity entity) {
super(entity);
}
public ITaskOption getM3u8Option() {
return m3u8Option;
}
public void generateM3u8Option(Class<? extends ITaskOption> clazz) {
m3u8Option = ComponentUtil.getInstance().buildTaskOption(clazz, m3u8Params);
}
public TaskOptionParams getM3U8Params() {
if (m3u8Params == null) {
m3u8Params = new TaskOptionParams();
}
return m3u8Params;
}
/**
* Task实体对应的key下载url
*/
@Override public String getKey() {
return getEntity().getKey();
}
@Override public DownloadConfig getConfig() {
if (isGroupTask) {
return Configuration.getInstance().dGroupCfg.getSubConfig();
} else {
return Configuration.getInstance().downloadCfg;
}
}
public String getGroupHash() {
return groupHash;
}
public boolean isGroupTask() {
return isGroupTask;
}
public void setGroupHash(String groupHash) {
this.groupHash = groupHash;
}
public void setGroupTask(boolean groupTask) {
isGroupTask = groupTask;
}
public String getTempUrl() {
return mTempUrl;
}
public void setTempUrl(String mTempUrl) {
this.mTempUrl = mTempUrl;
}
public String getTempFilePath() {
return mTempFilePath;
}
public void setTempFilePath(String mTempFilePath) {
this.mTempFilePath = mTempFilePath;
}
}

@ -1,214 +0,0 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.download;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import com.arialyy.aria.core.common.AbsNormalEntity;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.orm.annotation.Ignore;
import com.arialyy.aria.orm.annotation.Unique;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
/**
* Created by lyy on 2015/12/25.
* 下载实体
*/
public class DownloadEntity extends AbsNormalEntity implements Parcelable, Cloneable {
@Unique private String downloadPath; //保存路径
/**
* 所属任务组
*/
private String groupHash;
/**
* 从服务器的返回信息中获取的文件md5信息如果服务器没有返回则不会设置该信息
* 如果你已经设置了该任务的MD5信息Aria也不会从服务器返回的信息中获取该信息
*/
private String md5Code;
/**
* 从服务器的返回信息中获取的文件描述信息
*/
private String disposition;
/**
* 从disposition获取到的文件名如果可以获取到则会赋值到这个字段
*/
private String serverFileName;
@Ignore
private M3U8Entity m3U8Entity;
/**
* 获取m3u8数据信息
*
* @return 如果m3u8信息为空则返回null
*/
public M3U8Entity getM3U8Entity() {
if (TextUtils.isEmpty(downloadPath)) {
ALog.e("DownloadEntity", "文件保存路径为空,获取m3u8实体之前需要设置文件保存路径");
return null;
}
if (m3U8Entity == null) {
m3U8Entity = DbEntity.findFirst(M3U8Entity.class, "filePath=?", downloadPath);
}
return m3U8Entity;
}
/**
* 设置进来的地址如果需要获取真实的下载地址请使用{@link #getRealUrl()}
*/
@Override public String getKey() {
return getUrl();
}
public String getRealUrl(){
return isRedirect() ? getRedirectUrl() : getUrl();
}
@Override public int getTaskType() {
int type;
if (getUrl() == null) {
type = ITaskWrapper.ERROR;
} else if (getUrl().startsWith("http")) {
M3U8Entity temp = getM3U8Entity();
if (temp == null) {
type = ITaskWrapper.D_HTTP;
} else {
type = temp.isLive() ? ITaskWrapper.M3U8_LIVE : ITaskWrapper.M3U8_VOD;
}
} else if (getUrl().startsWith("ftp")) {
type = ITaskWrapper.D_FTP;
} else if (getUrl().startsWith("sftp")) {
type = ITaskWrapper.D_SFTP;
} else {
type = ITaskWrapper.ERROR;
}
return type;
}
public DownloadEntity() {
}
public String getMd5Code() {
return md5Code;
}
public void setMd5Code(String md5Code) {
this.md5Code = md5Code;
}
public String getDisposition() {
return TextUtils.isEmpty(disposition) ? "" : CommonUtil.decryptBASE64(disposition);
}
public void setDisposition(String disposition) {
this.disposition = disposition;
}
public String getServerFileName() {
return serverFileName;
}
public void setServerFileName(String serverFileName) {
this.serverFileName = serverFileName;
}
public String getGroupHash() {
return groupHash;
}
public void setGroupHash(String groupHash) {
this.groupHash = groupHash;
}
@Override
public String getFilePath() {
return downloadPath;
}
public DownloadEntity setFilePath(String filePath) {
this.downloadPath = filePath;
return this;
}
@Override public DownloadEntity clone() throws CloneNotSupportedException {
return (DownloadEntity) super.clone();
}
@Override public String toString() {
return "DownloadEntity{"
+ "downloadPath='"
+ downloadPath
+ '\''
+ ", groupHash='"
+ groupHash
+ '\''
+ ", fileName='"
+ getFileName()
+ '\''
+ ", md5Code='"
+ md5Code
+ '\''
+ ", disposition='"
+ disposition
+ '\''
+ ", serverFileName='"
+ serverFileName
+ '\''
+ '}';
}
@Override public int describeContents() {
return 0;
}
@Override public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(this.downloadPath);
dest.writeString(this.groupHash);
dest.writeString(this.md5Code);
dest.writeString(this.disposition);
dest.writeString(this.serverFileName);
dest.writeParcelable(this.m3U8Entity, flags);
}
protected DownloadEntity(Parcel in) {
super(in);
this.downloadPath = in.readString();
this.groupHash = in.readString();
this.md5Code = in.readString();
this.disposition = in.readString();
this.serverFileName = in.readString();
this.m3U8Entity = in.readParcelable(M3U8Entity.class.getClassLoader());
}
public static final Creator<DownloadEntity> CREATOR = new Creator<DownloadEntity>() {
@Override public DownloadEntity createFromParcel(Parcel source) {
return new DownloadEntity(source);
}
@Override public DownloadEntity[] newArray(int size) {
return new DownloadEntity[size];
}
};
}

@ -1,86 +0,0 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.download;
import android.os.Parcel;
import android.text.TextUtils;
import com.arialyy.aria.core.common.AbsGroupEntity;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.annotation.Ignore;
import java.util.ArrayList;
import java.util.List;
/**
* Created by AriaL on 2017/6/29. 下载任务组实体
*/
public class DownloadGroupEntity extends AbsGroupEntity {
@Ignore private List<DownloadEntity> subEntities;
/**
* 子任务实体列表
*/
public List<DownloadEntity> getSubEntities() {
if (subEntities == null) {
subEntities = new ArrayList<>();
}
return subEntities;
}
public void setSubEntities(List<DownloadEntity> subTasks) {
this.subEntities = subTasks;
}
public void setGroupHash(String key) {
this.groupHash = key;
}
@Override public int getTaskType() {
if (getSubEntities() == null || getSubEntities().isEmpty() || TextUtils.isEmpty(
getSubEntities().get(0).getUrl())) {
return ITaskWrapper.ERROR;
}
return (groupHash.startsWith("ftp") || groupHash.startsWith("sftp")) ? ITaskWrapper.D_FTP_DIR
: ITaskWrapper.DG_HTTP;
}
public DownloadGroupEntity() {
}
@Override public int describeContents() {
return 0;
}
@Override public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeTypedList(this.subEntities);
}
protected DownloadGroupEntity(Parcel in) {
super(in);
this.subEntities = in.createTypedArrayList(DownloadEntity.CREATOR);
}
public static final Creator<DownloadGroupEntity> CREATOR = new Creator<DownloadGroupEntity>() {
@Override public DownloadGroupEntity createFromParcel(Parcel source) {
return new DownloadGroupEntity(source);
}
@Override public DownloadGroupEntity[] newArray(int size) {
return new DownloadGroupEntity[size];
}
};
}

@ -52,7 +52,7 @@ public abstract class AbsGroupLoader implements ILoaderVisitor, ILoader {
private boolean isStop = false, isCancel = false; private boolean isStop = false, isCancel = false;
private Handler mScheduler; private Handler mScheduler;
private SimpleSubQueue mSubQueue = SimpleSubQueue.newInstance(); private SimpleSubQueue mSubQueue = SimpleSubQueue.newInstance();
private Map<String, AbsSubDLoadUtil> mExeLoader = new WeakHashMap<>(); private Map<String, AbsSubDLoadAdapter> mExeLoader = new WeakHashMap<>();
private Map<String, DTaskWrapper> mCache = new WeakHashMap<>(); private Map<String, DTaskWrapper> mCache = new WeakHashMap<>();
private DGTaskWrapper mGTWrapper; private DGTaskWrapper mGTWrapper;
private GroupRunState mState; private GroupRunState mState;
@ -75,7 +75,7 @@ public abstract class AbsGroupLoader implements ILoaderVisitor, ILoader {
* *
* @param needGetFileInfo {@code true} 需要获取文件信息{@code false} 不需要获取文件信息 * @param needGetFileInfo {@code true} 需要获取文件信息{@code false} 不需要获取文件信息
*/ */
protected abstract AbsSubDLoadUtil createSubLoader(DTaskWrapper wrapper, boolean needGetFileInfo); protected abstract AbsSubDLoadAdapter createSubLoader(DTaskWrapper wrapper, boolean needGetFileInfo);
protected IDGroupListener getListener() { protected IDGroupListener getListener() {
return mListener; return mListener;
@ -156,7 +156,7 @@ public abstract class AbsGroupLoader implements ILoaderVisitor, ILoader {
if (!mState.isRunning.get()) { if (!mState.isRunning.get()) {
startTimer(); startTimer();
} }
AbsSubDLoadUtil d = getDownloader(url, false); AbsSubDLoadAdapter d = getDownloader(url, false);
if (d != null && !d.isRunning()) { if (d != null && !d.isRunning()) {
mSubQueue.startTask(d); mSubQueue.startTask(d);
} }
@ -171,7 +171,7 @@ public abstract class AbsGroupLoader implements ILoaderVisitor, ILoader {
if (!checkSubTask(url, "停止")) { if (!checkSubTask(url, "停止")) {
return; return;
} }
AbsSubDLoadUtil d = getDownloader(url, false); AbsSubDLoadAdapter d = getDownloader(url, false);
if (d != null && d.isRunning()) { if (d != null && d.isRunning()) {
mSubQueue.stopTask(d); mSubQueue.stopTask(d);
} }
@ -203,8 +203,8 @@ public abstract class AbsGroupLoader implements ILoaderVisitor, ILoader {
* *
* @param url 子任务下载地址 * @param url 子任务下载地址
*/ */
private AbsSubDLoadUtil getDownloader(String url, boolean needGetFileInfo) { private AbsSubDLoadAdapter getDownloader(String url, boolean needGetFileInfo) {
AbsSubDLoadUtil d = mExeLoader.get(url); AbsSubDLoadAdapter d = mExeLoader.get(url);
if (d == null) { if (d == null) {
return createSubLoader(mCache.get(url), needGetFileInfo); return createSubLoader(mCache.get(url), needGetFileInfo);
} }
@ -311,7 +311,7 @@ public abstract class AbsGroupLoader implements ILoaderVisitor, ILoader {
/** /**
* 启动子任务下载器 * 启动子任务下载器
*/ */
protected void startSubLoader(AbsSubDLoadUtil loader) { protected void startSubLoader(AbsSubDLoadAdapter loader) {
mExeLoader.put(loader.getKey(), loader); mExeLoader.put(loader.getKey(), loader);
mSubQueue.startTask(loader); mSubQueue.startTask(loader);
} }

@ -15,7 +15,7 @@
*/ */
package com.arialyy.aria.core.group; package com.arialyy.aria.core.group;
import com.arialyy.aria.core.inf.ITaskUtil; import com.arialyy.aria.core.inf.ITaskAdapter;
import com.arialyy.aria.core.listener.IEventListener; import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.loader.LoaderStructure; import com.arialyy.aria.core.loader.LoaderStructure;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper; import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
@ -26,7 +26,7 @@ import com.arialyy.aria.util.CommonUtil;
* Created by AriaL on 2017/6/30. * Created by AriaL on 2017/6/30.
* 任务组核心逻辑 * 任务组核心逻辑
*/ */
public abstract class AbsGroupLoaderUtil implements ITaskUtil { public abstract class AbsGroupLoaderAdapter implements ITaskAdapter {
protected String TAG = CommonUtil.getClassName(getClass()); protected String TAG = CommonUtil.getClassName(getClass());
private IEventListener mListener; private IEventListener mListener;
@ -35,7 +35,7 @@ public abstract class AbsGroupLoaderUtil implements ITaskUtil {
private boolean isStop = false, isCancel = false; private boolean isStop = false, isCancel = false;
@Override public ITaskUtil setParams(AbsTaskWrapper taskWrapper, IEventListener listener) { @Override public ITaskAdapter setParams(AbsTaskWrapper taskWrapper, IEventListener listener) {
mTaskWrapper = taskWrapper; mTaskWrapper = taskWrapper;
mListener = listener; mListener = listener;
mLoader = getLoader(); mLoader = getLoader();

@ -19,7 +19,7 @@ import android.os.Handler;
import com.arialyy.aria.core.TaskRecord; import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.inf.ITaskUtil; import com.arialyy.aria.core.inf.ITaskAdapter;
import com.arialyy.aria.core.listener.IEventListener; import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.listener.ISchedulers; import com.arialyy.aria.core.listener.ISchedulers;
import com.arialyy.aria.core.loader.LoaderStructure; import com.arialyy.aria.core.loader.LoaderStructure;
@ -31,7 +31,7 @@ import com.arialyy.aria.util.CommonUtil;
/** /**
* 子任务下载器工具需要在线程池中执行 * 子任务下载器工具需要在线程池中执行
*/ */
public abstract class AbsSubDLoadUtil implements ITaskUtil, Runnable { public abstract class AbsSubDLoadAdapter implements ITaskAdapter, Runnable {
protected final String TAG = CommonUtil.getClassName(getClass()); protected final String TAG = CommonUtil.getClassName(getClass());
protected SubLoader mDLoader; protected SubLoader mDLoader;
@ -45,13 +45,13 @@ public abstract class AbsSubDLoadUtil implements ITaskUtil, Runnable {
* @param schedulers 调度器 * @param schedulers 调度器
* @param needGetInfo {@code true} 需要获取文件信息{@code false} 不需要获取文件信息 * @param needGetInfo {@code true} 需要获取文件信息{@code false} 不需要获取文件信息
*/ */
protected AbsSubDLoadUtil(Handler schedulers, boolean needGetInfo, String parentKey) { protected AbsSubDLoadAdapter(Handler schedulers, boolean needGetInfo, String parentKey) {
mSchedulers = schedulers; mSchedulers = schedulers;
this.parentKey = parentKey; this.parentKey = parentKey;
this.needGetInfo = needGetInfo; this.needGetInfo = needGetInfo;
} }
@Override public ITaskUtil setParams(AbsTaskWrapper taskWrapper, IEventListener listener) { @Override public ITaskAdapter setParams(AbsTaskWrapper taskWrapper, IEventListener listener) {
mWrapper = (DTaskWrapper) taskWrapper; mWrapper = (DTaskWrapper) taskWrapper;
mDLoader = getLoader(); mDLoader = getLoader();
return this; return this;

@ -16,7 +16,7 @@
package com.arialyy.aria.core.group; package com.arialyy.aria.core.group;
import com.arialyy.aria.core.loader.AbsNormalLoader; import com.arialyy.aria.core.loader.AbsNormalLoader;
import com.arialyy.aria.core.inf.ITaskUtil; import com.arialyy.aria.core.inf.ITaskAdapter;
import com.arialyy.aria.core.config.DGroupConfig; import com.arialyy.aria.core.config.DGroupConfig;
/** /**
@ -24,7 +24,7 @@ import com.arialyy.aria.core.config.DGroupConfig;
* *
* @param <Fileer> {@link AbsNormalLoader}下载器 * @param <Fileer> {@link AbsNormalLoader}下载器
*/ */
interface ISubQueue<Fileer extends ITaskUtil> { interface ISubQueue<Fileer extends ITaskAdapter> {
/** /**
* 添加任务 * 添加任务

@ -34,7 +34,7 @@ import java.io.File;
/** /**
* 组合任务子任务调度器用于调度任务的开始停止失败完成等情况 * 组合任务子任务调度器用于调度任务的开始停止失败完成等情况
* 该调度器生命周期和{@link AbsGroupLoaderUtil}生命周期一致 * 该调度器生命周期和{@link AbsGroupLoaderAdapter}生命周期一致
*/ */
final class SimpleSchedulers implements Handler.Callback { final class SimpleSchedulers implements Handler.Callback {
private final String TAG = CommonUtil.getClassName(this); private final String TAG = CommonUtil.getClassName(this);
@ -59,7 +59,7 @@ final class SimpleSchedulers implements Handler.Callback {
return true; return true;
} }
String threadName = b.getString(IBlockManager.DATA_THREAD_NAME); String threadName = b.getString(IBlockManager.DATA_THREAD_NAME);
AbsSubDLoadUtil loaderUtil = mQueue.getLoaderUtil(threadName); AbsSubDLoadAdapter loaderUtil = mQueue.getLoaderUtil(threadName);
if (loaderUtil == null) { if (loaderUtil == null) {
ALog.e(TAG, String.format("子任务loader不存在,state:%s,key:%s", msg.what, threadName)); ALog.e(TAG, String.format("子任务loader不存在,state:%s,key:%s", msg.what, threadName));
return true; return true;
@ -104,7 +104,7 @@ final class SimpleSchedulers implements Handler.Callback {
* *
* @param needRetry true 需要重试false 不需要重试 * @param needRetry true 需要重试false 不需要重试
*/ */
private synchronized void handleFail(final AbsSubDLoadUtil loaderUtil, boolean needRetry) { private synchronized void handleFail(final AbsSubDLoadAdapter loaderUtil, boolean needRetry) {
Log.d(TAG, String.format("handleFail, size = %s, completeNum = %s, failNum = %s, stopNum = %s", Log.d(TAG, String.format("handleFail, size = %s, completeNum = %s, failNum = %s, stopNum = %s",
mGState.getSubSize(), mGState.getCompleteNum(), mGState.getFailNum(), mGState.getSubSize(), mGState.getCompleteNum(), mGState.getFailNum(),
mGState.getSubSize())); mGState.getSubSize()));
@ -149,7 +149,7 @@ final class SimpleSchedulers implements Handler.Callback {
* 1所有的子任务已经停止则认为组合任务停止 * 1所有的子任务已经停止则认为组合任务停止
* 2completeNum + failNum + stopNum = subSize则认为组合任务停止 * 2completeNum + failNum + stopNum = subSize则认为组合任务停止
*/ */
private synchronized void handleStop(AbsSubDLoadUtil loadUtil, long curLocation) { private synchronized void handleStop(AbsSubDLoadAdapter loadUtil, long curLocation) {
Log.d(TAG, String.format("handleStop, size = %s, completeNum = %s, failNum = %s, stopNum = %s", Log.d(TAG, String.format("handleStop, size = %s, completeNum = %s, failNum = %s, stopNum = %s",
mGState.getSubSize(), mGState.getCompleteNum(), mGState.getFailNum(), mGState.getSubSize(), mGState.getCompleteNum(), mGState.getFailNum(),
mGState.getSubSize())); mGState.getSubSize()));
@ -177,7 +177,7 @@ final class SimpleSchedulers implements Handler.Callback {
* GroupRunState#getFailNum()}不为0则认为组合任务被停止 * GroupRunState#getFailNum()}不为0则认为组合任务被停止
* 3只有有缓存的子任务则任务组合任务没有完成 * 3只有有缓存的子任务则任务组合任务没有完成
*/ */
private synchronized void handleComplete(AbsSubDLoadUtil loader) { private synchronized void handleComplete(AbsSubDLoadAdapter loader) {
ALog.d(TAG, String.format("子任务【%s】完成", loader.getEntity().getFileName())); ALog.d(TAG, String.format("子任务【%s】完成", loader.getEntity().getFileName()));
Log.d(TAG, Log.d(TAG,
String.format("handleComplete, size = %s, completeNum = %s, failNum = %s, stopNum = %s", String.format("handleComplete, size = %s, completeNum = %s, failNum = %s, stopNum = %s",
@ -219,7 +219,7 @@ final class SimpleSchedulers implements Handler.Callback {
if (mQueue.isStopAll()) { if (mQueue.isStopAll()) {
return; return;
} }
AbsSubDLoadUtil next = mQueue.getNextTask(); AbsSubDLoadAdapter next = mQueue.getNextTask();
if (next != null) { if (next != null) {
ALog.d(TAG, String.format("启动任务:%s", next.getEntity().getFileName())); ALog.d(TAG, String.format("启动任务:%s", next.getEntity().getFileName()));
mQueue.startTask(next); mQueue.startTask(next);

@ -27,18 +27,18 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
/** /**
* 组合任务队列该队列生命周期和{@link AbsGroupLoaderUtil}生命周期一致 * 组合任务队列该队列生命周期和{@link AbsGroupLoaderAdapter}生命周期一致
*/ */
final class SimpleSubQueue implements ISubQueue<AbsSubDLoadUtil> { final class SimpleSubQueue implements ISubQueue<AbsSubDLoadAdapter> {
private final String TAG = CommonUtil.getClassName(getClass()); private final String TAG = CommonUtil.getClassName(getClass());
/** /**
* 缓存下载器 * 缓存下载器
*/ */
private Map<String, AbsSubDLoadUtil> mCache = new ConcurrentHashMap<>(); private Map<String, AbsSubDLoadAdapter> mCache = new ConcurrentHashMap<>();
/** /**
* 执行中的下载器 * 执行中的下载器
*/ */
private Map<String, AbsSubDLoadUtil> mExec = new ConcurrentHashMap<>(); private Map<String, AbsSubDLoadAdapter> mExec = new ConcurrentHashMap<>();
/** /**
* 最大执行任务数 * 最大执行任务数
@ -58,8 +58,8 @@ final class SimpleSubQueue implements ISubQueue<AbsSubDLoadUtil> {
return new SimpleSubQueue(); return new SimpleSubQueue();
} }
synchronized AbsSubDLoadUtil getLoaderUtil(String key) { synchronized AbsSubDLoadAdapter getLoaderUtil(String key) {
AbsSubDLoadUtil sub = mExec.get(key); AbsSubDLoadAdapter sub = mExec.get(key);
if (sub != null) { if (sub != null) {
return sub; return sub;
} }
@ -81,11 +81,11 @@ final class SimpleSubQueue implements ISubQueue<AbsSubDLoadUtil> {
return isStopAll; return isStopAll;
} }
@Override public void addTask(AbsSubDLoadUtil fileer) { @Override public void addTask(AbsSubDLoadAdapter fileer) {
mCache.put(fileer.getKey(), fileer); mCache.put(fileer.getKey(), fileer);
} }
@Override public void startTask(AbsSubDLoadUtil fileer) { @Override public void startTask(AbsSubDLoadAdapter fileer) {
if (mExec.size() < mMaxExecSize) { if (mExec.size() < mMaxExecSize) {
mCache.remove(fileer.getKey()); mCache.remove(fileer.getKey());
mExec.put(fileer.getKey(), fileer); mExec.put(fileer.getKey(), fileer);
@ -98,7 +98,7 @@ final class SimpleSubQueue implements ISubQueue<AbsSubDLoadUtil> {
addTask(fileer); addTask(fileer);
} }
@Override public void stopTask(AbsSubDLoadUtil fileer) { @Override public void stopTask(AbsSubDLoadAdapter fileer) {
fileer.stop(); fileer.stop();
mExec.remove(fileer.getKey()); mExec.remove(fileer.getKey());
} }
@ -109,7 +109,7 @@ final class SimpleSubQueue implements ISubQueue<AbsSubDLoadUtil> {
mCache.clear(); mCache.clear();
Set<String> keys = mExec.keySet(); Set<String> keys = mExec.keySet();
for (String key : keys) { for (String key : keys) {
AbsSubDLoadUtil loader = mExec.get(key); AbsSubDLoadAdapter loader = mExec.get(key);
if (loader != null) { if (loader != null) {
ALog.d(TAG, String.format("停止子任务:%s", loader.getEntity().getFileName())); ALog.d(TAG, String.format("停止子任务:%s", loader.getEntity().getFileName()));
loader.stop(); loader.stop();
@ -133,7 +133,7 @@ final class SimpleSubQueue implements ISubQueue<AbsSubDLoadUtil> {
if (oldSize < num) { // 处理队列变小的情况,该情况下将停止队尾任务,并将这些任务添加到缓存队列中 if (oldSize < num) { // 处理队列变小的情况,该情况下将停止队尾任务,并将这些任务添加到缓存队列中
if (mExec.size() > num) { if (mExec.size() > num) {
Set<String> keys = mExec.keySet(); Set<String> keys = mExec.keySet();
List<AbsSubDLoadUtil> caches = new ArrayList<>(); List<AbsSubDLoadAdapter> caches = new ArrayList<>();
int i = 0; int i = 0;
for (String key : keys) { for (String key : keys) {
if (i > num) { if (i > num) {
@ -141,12 +141,12 @@ final class SimpleSubQueue implements ISubQueue<AbsSubDLoadUtil> {
} }
i++; i++;
} }
Collection<AbsSubDLoadUtil> temp = mCache.values(); Collection<AbsSubDLoadAdapter> temp = mCache.values();
mCache.clear(); mCache.clear();
for (AbsSubDLoadUtil cache : caches) { for (AbsSubDLoadAdapter cache : caches) {
addTask(cache); addTask(cache);
} }
for (AbsSubDLoadUtil t : temp) { for (AbsSubDLoadAdapter t : temp) {
addTask(t); addTask(t);
} }
} }
@ -155,7 +155,7 @@ final class SimpleSubQueue implements ISubQueue<AbsSubDLoadUtil> {
// 处理队列变大的情况,该情况下将增加任务 // 处理队列变大的情况,该情况下将增加任务
if (mExec.size() < num) { if (mExec.size() < num) {
for (int i = 0; i < diff; i++) { for (int i = 0; i < diff; i++) {
AbsSubDLoadUtil next = getNextTask(); AbsSubDLoadAdapter next = getNextTask();
if (next != null) { if (next != null) {
startTask(next); startTask(next);
} else { } else {
@ -165,11 +165,11 @@ final class SimpleSubQueue implements ISubQueue<AbsSubDLoadUtil> {
} }
} }
@Override public void removeTaskFromExecQ(AbsSubDLoadUtil fileer) { @Override public void removeTaskFromExecQ(AbsSubDLoadAdapter fileer) {
mExec.remove(fileer.getKey()); mExec.remove(fileer.getKey());
} }
@Override public void removeTask(AbsSubDLoadUtil fileer) { @Override public void removeTask(AbsSubDLoadAdapter fileer) {
removeTaskFromExecQ(fileer); removeTaskFromExecQ(fileer);
mCache.remove(fileer.getKey()); mCache.remove(fileer.getKey());
} }
@ -178,7 +178,7 @@ final class SimpleSubQueue implements ISubQueue<AbsSubDLoadUtil> {
ALog.d(TAG, "删除组合任务"); ALog.d(TAG, "删除组合任务");
Set<String> keys = mExec.keySet(); Set<String> keys = mExec.keySet();
for (String key : keys) { for (String key : keys) {
AbsSubDLoadUtil loader = mExec.get(key); AbsSubDLoadAdapter loader = mExec.get(key);
if (loader != null) { if (loader != null) {
ALog.d(TAG, String.format("停止子任务:%s", loader.getEntity().getFileName())); ALog.d(TAG, String.format("停止子任务:%s", loader.getEntity().getFileName()));
loader.cancel(); loader.cancel();
@ -186,7 +186,7 @@ final class SimpleSubQueue implements ISubQueue<AbsSubDLoadUtil> {
} }
} }
@Override public AbsSubDLoadUtil getNextTask() { @Override public AbsSubDLoadAdapter getNextTask() {
Iterator<String> keys = mCache.keySet().iterator(); Iterator<String> keys = mCache.keySet().iterator();
if (keys.hasNext()) { if (keys.hasNext()) {
return mCache.get(keys.next()); return mCache.get(keys.next());

@ -43,7 +43,7 @@ final class SimpleSubRetryQueue {
} }
void offer(AbsSubDLoadUtil subDLoadUtil) { void offer(AbsSubDLoadAdapter subDLoadUtil) {
pool.submit(subDLoadUtil.getLoader()); pool.submit(subDLoadUtil.getLoader());
} }
} }

@ -24,7 +24,7 @@ import org.jetbrains.annotations.NotNull;
* Created by lyy on 2016/10/31. * Created by lyy on 2016/10/31.
* 任务功能接口 * 任务功能接口
*/ */
public interface ITaskUtil { public interface ITaskAdapter {
void init(@NotNull ITask task, @NotNull IEventListener listener); void init(@NotNull ITask task, @NotNull IEventListener listener);

@ -1,60 +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.listener;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.task.DownloadTask;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.DeleteDRecord;
/**
* 下载监听类
*/
public class BaseDListener extends AbsEventListener implements IDLoadListener {
@Override
public void onPostPre(long fileSize) {
mEntity.setFileSize(fileSize);
mEntity.setConvertFileSize(CommonUtil.formatFileSize(fileSize));
saveData(IEntity.STATE_POST_PRE, -1);
sendInState2Target(ISchedulers.POST_PRE);
}
@Override
public void supportBreakpoint(boolean support) {
if (!support) {
sendInState2Target(ISchedulers.NO_SUPPORT_BREAK_POINT);
}
}
@Override protected void handleCancel() {
int sType = getTask(DownloadTask.class).getSchedulerType();
if (sType == TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY) {
mEntity.setComplete(false);
mEntity.setState(IEntity.STATE_WAIT);
DeleteDRecord.getInstance().deleteRecord(mEntity, mTaskWrapper.isRemoveFile(), false);
//RecordUtil.delTaskRecord(mEntity.getFilePath(), IRecordHandler.TYPE_DOWNLOAD,
// mTaskWrapper.isRemoveFile(), false);
} else {
//RecordUtil.delTaskRecord(mEntity.getFilePath(), IRecordHandler.TYPE_DOWNLOAD,
// mTaskWrapper.isRemoveFile(), true);
DeleteDRecord.getInstance().deleteRecord(mEntity, mTaskWrapper.isRemoveFile(), true);
}
}
}

@ -1,38 +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.listener;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.task.UploadTask;
import com.arialyy.aria.util.DeleteURecord;
/**
* 下载监听类
*/
public class BaseUListener extends AbsEventListener implements IUploadListener {
@Override protected void handleCancel() {
int sType = getTask(UploadTask.class).getSchedulerType();
if (sType == TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY) {
mEntity.setComplete(false);
mEntity.setState(IEntity.STATE_WAIT);
DeleteURecord.getInstance().deleteRecord(mEntity, mTaskWrapper.isRemoveFile(), false);
} else {
DeleteURecord.getInstance().deleteRecord(mEntity, mTaskWrapper.isRemoveFile(), true);
}
}
}

@ -16,7 +16,7 @@
package com.arialyy.aria.core.loader; package com.arialyy.aria.core.loader;
import com.arialyy.aria.core.inf.ITaskUtil; import com.arialyy.aria.core.inf.ITaskAdapter;
import com.arialyy.aria.core.listener.IEventListener; import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper; import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.exception.AriaException; import com.arialyy.aria.exception.AriaException;
@ -27,17 +27,17 @@ import com.arialyy.aria.util.CommonUtil;
* Created by lyy on 2015/8/25. * Created by lyy on 2015/8/25.
* HTTP\FTP单任务下载工具 * HTTP\FTP单任务下载工具
*/ */
public abstract class AbsNormalLoaderUtil implements ITaskUtil { public abstract class AbsNormalLoaderAdapter implements ITaskAdapter {
protected String TAG = CommonUtil.getClassName(getClass()); protected String TAG = CommonUtil.getClassName(getClass());
private IEventListener mListener; private IEventListener mListener;
protected AbsNormalLoader mLoader; protected AbsNormalLoader mLoader;
private AbsTaskWrapper mTaskWrapper; private AbsTaskWrapper mTaskWrapper;
private boolean isStop = false, isCancel = false; private boolean isStop = false, isCancel = false;
protected AbsNormalLoaderUtil() { protected AbsNormalLoaderAdapter() {
} }
@Override public ITaskUtil setParams(AbsTaskWrapper taskWrapper, IEventListener listener) { @Override public ITaskAdapter setParams(AbsTaskWrapper taskWrapper, IEventListener listener) {
mTaskWrapper = taskWrapper; mTaskWrapper = taskWrapper;
mListener = listener; mListener = listener;
mLoader = getLoader(); mLoader = getLoader();

@ -15,7 +15,7 @@
*/ */
package com.arialyy.aria.core.processor; package com.arialyy.aria.core.processor;
import com.arialyy.aria.core.download.M3U8Entity; import com.arialyy.aria.core.common.M3U8Entity;
import com.arialyy.aria.core.inf.IEventHandler; import com.arialyy.aria.core.inf.IEventHandler;
import java.util.List; import java.util.List;

@ -16,9 +16,8 @@
package com.arialyy.aria.core.task; package com.arialyy.aria.core.task;
import android.text.TextUtils; import android.text.TextUtils;
import com.arialyy.aria.core.common.AbsEntity; import com.arialyy.aria.core.inf.ITaskAdapter;
import com.arialyy.aria.core.inf.ITaskOption; import com.arialyy.aria.core.inf.ITaskOption;
import com.arialyy.aria.core.inf.ITaskUtil;
import com.arialyy.aria.core.inf.TaskSchedulerType; import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import java.util.HashMap; import java.util.HashMap;
@ -31,7 +30,7 @@ import timber.log.Timber;
public abstract class AbsTask implements ITask { public abstract class AbsTask implements ITask {
protected ITaskOption mTaskOption; protected ITaskOption mTaskOption;
private boolean isCancel = false, isStop = false; private boolean isCancel = false, isStop = false;
private ITaskUtil mUtil; private ITaskAdapter mAdapter;
/** /**
* 该任务的调度类型 * 该任务的调度类型
*/ */
@ -40,20 +39,23 @@ public abstract class AbsTask implements ITask {
private int taskId = -1; private int taskId = -1;
private final Map<String, Object> mExpand = new HashMap<>(); private final Map<String, Object> mExpand = new HashMap<>();
protected AbsTask(ITaskOption taskOption, ITaskUtil util) { protected AbsTask(ITaskOption taskOption) {
mTaskOption = taskOption; mTaskOption = taskOption;
mUtil = util;
taskId = TaskStatePool.INSTANCE.buildTaskId$PublicComponent_debug(); taskId = TaskStatePool.INSTANCE.buildTaskId$PublicComponent_debug();
TaskStatePool.INSTANCE.putTaskState(getTaskId(), mTaskState); TaskStatePool.INSTANCE.putTaskState(getTaskId(), mTaskState);
util.init(this, taskOption.eventListener);
} }
@Override public void setState(int state) { public void setAdapter(ITaskAdapter adapter) {
mTaskState.setState(state); mAdapter = adapter;
mAdapter.init(this, mTaskOption.eventListener);
}
@Override public ITaskAdapter getAdapter() {
return mAdapter;
} }
ITaskUtil getTaskUtil() { @Override public void setState(int state) {
return mUtil; mTaskState.setState(state);
} }
@Override public <T extends ITaskOption> T getTaskOption(Class<T> clazz) { @Override public <T extends ITaskOption> T getTaskOption(Class<T> clazz) {
@ -66,7 +68,6 @@ public abstract class AbsTask implements ITask {
/** /**
* 获取剩余时间单位s * 获取剩余时间单位s
* 如果是m3u8任务无法获取剩余时间m2u8任务如果需要获取剩余时间请设置文件长度{@link AbsEntity#setFileSize(long)}
*/ */
public int getTimeLeft() { public int getTimeLeft() {
return mTaskState.getTimeLeft(); return mTaskState.getTimeLeft();
@ -152,47 +153,44 @@ public abstract class AbsTask implements ITask {
@Override public void start(int type) { @Override public void start(int type) {
mSchedulerType = type; mSchedulerType = type;
mUtil = getTaskUtil(); if (mAdapter == null) {
if (mUtil == null) {
Timber.e("util is null"); Timber.e("util is null");
return; return;
} }
if (type == TaskSchedulerType.TYPE_START_AND_RESET_STATE) { if (type == TaskSchedulerType.TYPE_START_AND_RESET_STATE) {
if (getTaskUtil().isRunning()) { if (mAdapter.isRunning()) {
Timber.e("task restart fail"); Timber.e("task restart fail");
return; return;
} }
mUtil.start(); mAdapter.start();
Timber.e("task restart success"); Timber.e("task restart success");
return; return;
} }
if (getTaskUtil().isRunning()) { if (mAdapter.isRunning()) {
Timber.d("task is running"); Timber.d("task is running");
return; return;
} }
getTaskUtil().start(); mAdapter.start();
} }
@Override public void stop(int type) { @Override public void stop(int type) {
mUtil = getTaskUtil(); if (mAdapter == null) {
if (mUtil == null) {
Timber.e("util is null"); Timber.e("util is null");
return; return;
} }
isStop = true; isStop = true;
mSchedulerType = type; mSchedulerType = type;
getTaskUtil().stop(); mAdapter.stop();
} }
@Override public void cancel(int type) { @Override public void cancel(int type) {
mUtil = getTaskUtil(); if (mAdapter == null) {
if (mUtil == null) {
Timber.e("util is null"); Timber.e("util is null");
return; return;
} }
isCancel = true; isCancel = true;
mSchedulerType = type; mSchedulerType = type;
getTaskUtil().cancel(); mAdapter.cancel();
} }
/** /**
@ -201,7 +199,7 @@ public abstract class AbsTask implements ITask {
* @return {@code true} 正在下载 * @return {@code true} 正在下载
*/ */
@Override public boolean isRunning() { @Override public boolean isRunning() {
return getTaskUtil().isRunning(); return mAdapter.isRunning();
} }
/** /**

@ -16,7 +16,7 @@
package com.arialyy.aria.core.task package com.arialyy.aria.core.task
import com.arialyy.aria.core.inf.IBlockManager import com.arialyy.aria.core.inf.IBlockManager
import com.arialyy.aria.core.inf.ITaskUtil import com.arialyy.aria.core.inf.ITaskAdapter
import com.arialyy.aria.core.listener.IEventListener import com.arialyy.aria.core.listener.IEventListener
import com.arialyy.aria.core.task.ITaskInterceptor.IChain import com.arialyy.aria.core.task.ITaskInterceptor.IChain
@ -25,7 +25,7 @@ import com.arialyy.aria.core.task.ITaskInterceptor.IChain
* @Description * @Description
* @Date 1:12 PM 2023/1/28 * @Date 1:12 PM 2023/1/28
**/ **/
abstract class AbsTaskUtil : ITaskUtil { abstract class AbsTaskAdapter : ITaskAdapter {
private lateinit var mTask: ITask private lateinit var mTask: ITask
private lateinit var mEventListener: IEventListener private lateinit var mEventListener: IEventListener

@ -17,7 +17,7 @@ package com.arialyy.aria.core.task;
import com.arialyy.aria.core.download.DTaskOption; import com.arialyy.aria.core.download.DTaskOption;
import com.arialyy.aria.core.inf.ITaskOption; import com.arialyy.aria.core.inf.ITaskOption;
import com.arialyy.aria.core.inf.ITaskUtil; import com.arialyy.aria.core.inf.ITaskAdapter;
import java.util.Objects; import java.util.Objects;
/** /**
@ -26,7 +26,7 @@ import java.util.Objects;
*/ */
public class DownloadGroupTask extends AbsTask { public class DownloadGroupTask extends AbsTask {
protected DownloadGroupTask(ITaskOption taskOption, ITaskUtil util) { protected DownloadGroupTask(ITaskOption taskOption, ITaskAdapter util) {
super(taskOption, util); super(taskOption, util);
} }

@ -17,8 +17,7 @@
package com.arialyy.aria.core.task; package com.arialyy.aria.core.task;
import android.net.Uri; import android.net.Uri;
import com.arialyy.aria.core.download.TaskOption; import com.arialyy.aria.core.common.TaskOption;
import com.arialyy.aria.core.inf.ITaskUtil;
import java.util.Objects; import java.util.Objects;
/** /**
@ -27,8 +26,8 @@ import java.util.Objects;
*/ */
public class DownloadTask extends AbsTask { public class DownloadTask extends AbsTask {
public DownloadTask(TaskOption taskOption, ITaskUtil util) { public DownloadTask(TaskOption taskOption) {
super(taskOption, util); super(taskOption);
} }
public Uri getSavePath() { public Uri getSavePath() {

@ -15,6 +15,7 @@
*/ */
package com.arialyy.aria.core.task; package com.arialyy.aria.core.task;
import com.arialyy.aria.core.inf.ITaskAdapter;
import com.arialyy.aria.core.inf.ITaskOption; import com.arialyy.aria.core.inf.ITaskOption;
import com.arialyy.aria.core.inf.TaskSchedulerType; import com.arialyy.aria.core.inf.TaskSchedulerType;
@ -52,6 +53,8 @@ public interface ITask {
*/ */
int OTHER = -1; int OTHER = -1;
ITaskAdapter getAdapter();
/** /**
* 获取任务类型 * 获取任务类型
* *

@ -18,7 +18,7 @@ package com.arialyy.aria.core.task
import android.net.Uri import android.net.Uri
import com.arialyy.aria.core.inf.BaseEntity import com.arialyy.aria.core.inf.BaseEntity
import com.arialyy.aria.core.inf.IEntity import com.arialyy.aria.core.inf.IEntity
import com.arialyy.aria.core.inf.ITaskUtil import com.arialyy.aria.core.inf.ITaskAdapter
import timber.log.Timber import timber.log.Timber
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
@ -32,7 +32,7 @@ object TaskCachePool {
* key: taskId * key: taskId
*/ */
private val entityMap = ConcurrentHashMap<Int, BaseEntity>() private val entityMap = ConcurrentHashMap<Int, BaseEntity>()
private val taskUtilMap = ConcurrentHashMap<Uri, ITaskUtil>() private val taskAdapterMap = ConcurrentHashMap<Uri, ITaskAdapter>()
private val taskMap = ConcurrentHashMap<Int, ITask>() private val taskMap = ConcurrentHashMap<Int, ITask>()
fun removeTask(taskId: Int) { fun removeTask(taskId: Int) {
@ -46,20 +46,34 @@ object TaskCachePool {
fun putTask(task: ITask) { fun putTask(task: ITask) {
taskMap[task.taskId] = task taskMap[task.taskId] = task
taskAdapterMap[Uri.parse(task.filePath)] = task.adapter
} }
/** /**
* @param filePath task unique identifier, like: savePath, sourceUrl * find task by filePath
*/ */
fun putTaskUtil(filePath: Uri, taskUtil: ITaskUtil) { fun findTaskByPath(filePath: Uri): ITask? {
taskUtilMap[filePath] = taskUtil taskMap.values.forEach {
if (it.filePath == filePath.toString()) {
return it
}
}
return null
} }
// /**
// * @param filePath task unique identifier, like: savePath, sourceUrl
// */
// fun putTaskUtil(filePath: Uri, taskUtil: ITaskAdapter) {
// taskAdapterMap[filePath] = taskUtil
// taskUtil.stop()
// }
/** /**
* @param filePath unique identifier, like: savePath, sourceUrl * @param filePath unique identifier, like: savePath, sourceUrl
*/ */
fun getTaskUtil(filePath: Uri): ITaskUtil? { fun getTaskAdapter(filePath: Uri): ITaskAdapter? {
return taskUtilMap[filePath] return taskAdapterMap[filePath]
} }
fun putEntity(taskId: Int, entity: BaseEntity) { fun putEntity(taskId: Int, entity: BaseEntity) {

@ -1,54 +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.upload;
import com.arialyy.aria.core.config.Configuration;
import com.arialyy.aria.core.config.UploadConfig;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
/**
* Created by lyy on 2017/2/9. 上传任务实体
*/
public class UTaskWrapper extends AbsTaskWrapper<UploadEntity> {
/**
* 保存临时设置的上传路径
*/
private String tempUrl;
public UTaskWrapper(UploadEntity entity) {
super(entity);
}
public String getTempUrl() {
return tempUrl;
}
public void setTempUrl(String tempUrl) {
this.tempUrl = tempUrl;
}
/**
* 文件保存路径
*/
@Override public String getKey() {
return getEntity().getKey();
}
@Override public UploadConfig getConfig() {
return Configuration.getInstance().uploadCfg;
}
}

@ -1,94 +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.upload;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import com.arialyy.aria.core.common.AbsNormalEntity;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.annotation.Primary;
/**
* Created by lyy on 2017/2/9.
* 上传文件实体
*/
public class UploadEntity extends AbsNormalEntity implements Parcelable {
/**
* 文件上传路径
*/
@Primary private String filePath;
/**
* 上传完成后服务器返回的数据
*/
private String responseStr = "";
public String getResponseStr() {
return responseStr;
}
public void setResponseStr(String responseStr) {
this.responseStr = responseStr;
}
@Override
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
@Override public String getKey() {
return filePath;
}
@Override public int getTaskType() {
if (TextUtils.isEmpty(getUrl())) {
return ITaskWrapper.ERROR;
}
return getUrl().startsWith("ftp") ? ITaskWrapper.U_FTP : ITaskWrapper.U_HTTP;
}
public UploadEntity() {
}
@Override public int describeContents() {
return 0;
}
@Override public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeString(this.filePath);
}
protected UploadEntity(Parcel in) {
super(in);
this.filePath = in.readString();
}
public static final Creator<UploadEntity> CREATOR = new Creator<UploadEntity>() {
@Override public UploadEntity createFromParcel(Parcel source) {
return new UploadEntity(source);
}
@Override public UploadEntity[] newArray(int size) {
return new UploadEntity[size];
}
};
}

@ -1,197 +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.wrapper;
import com.arialyy.aria.core.TaskOptionParams;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.config.BaseTaskConfig;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.event.ErrorEvent;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.inf.ITaskOption;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.util.ComponentUtil;
/**
* Created by lyy on 2017/2/23. 所有任务实体的父类
*/
public abstract class AbsTaskWrapper<ENTITY extends AbsEntity> implements ITaskWrapper {
/**
* 刷新信息 {@code true} 重新刷新下载信息
*/
private boolean refreshInfo = false;
/**
* 是否是新任务{@code true} 新任务
*/
private boolean isNewTask = false;
/**
* 请求类型 {@link ITaskWrapper#D_HTTP}{@link ITaskWrapper#D_FTP}{@link
* ITaskWrapper#D_FTP_DIR}..
*/
private int requestType = D_HTTP;
/**
* 删除任务时是否删除已下载完成的文件 未完成的任务不管true还是false都会删除文件 {@code true} 删除任务数据库记录并且删除已经下载完成的文件 {@code
* false} 如果任务已经完成只删除任务数据库记录
*/
private boolean removeFile = false;
/**
* 是否支持断点, {@code true} 为支持断点
*/
private boolean isSupportBP = true;
/**
* 状态码
*/
private int code;
/**
* {@link DownloadEntity} or {@link UploadEntity} or {@link DownloadGroupEntity}
*/
private ENTITY entity;
/**
* 错误信息
*/
private ErrorEvent errorEvent;
/**
* 任务配置
*/
private ITaskOption taskOption;
/**
* 任务配置信息
*/
private TaskOptionParams optionParams = new TaskOptionParams();
/**
* {@code true}强制下载\上传不考虑文件路径是否被占用
*/
private boolean ignoreFilePathOccupy = false;
public boolean isIgnoreFilePathOccupy() {
return ignoreFilePathOccupy;
}
public void setIgnoreFilePathOccupy(boolean ignoreFilePathOccupy) {
this.ignoreFilePathOccupy = ignoreFilePathOccupy;
}
public void setTaskOption(ITaskOption option) {
this.taskOption = option;
}
public ITaskOption getTaskOption() {
return taskOption;
}
public void generateTaskOption(Class<? extends ITaskOption> clazz) {
taskOption = ComponentUtil.getInstance().buildTaskOption(clazz, optionParams);
}
public TaskOptionParams getOptionParams() {
if (optionParams == null) {
optionParams = new TaskOptionParams();
}
return optionParams;
}
public AbsTaskWrapper(ENTITY entity) {
this.entity = entity;
}
public ErrorEvent getErrorEvent() {
return errorEvent;
}
public void setErrorEvent(ErrorEvent errorEvent) {
this.errorEvent = errorEvent;
}
@Override public ENTITY getEntity() {
return entity;
}
/**
* 获取任务下载状态
*
* @return {@link IEntity}
*/
public int getState() {
return getEntity().getState();
}
public abstract BaseTaskConfig getConfig();
public boolean isRefreshInfo() {
return refreshInfo;
}
public void setRefreshInfo(boolean refreshInfo) {
this.refreshInfo = refreshInfo;
}
public boolean isNewTask() {
return isNewTask;
}
public void setNewTask(boolean newTask) {
isNewTask = newTask;
}
public void setState(int state) {
entity.setState(state);
}
@Override
public int getRequestType() {
return requestType;
}
public void setRequestType(int requestType) {
this.requestType = requestType;
}
public boolean isRemoveFile() {
return removeFile;
}
public void setRemoveFile(boolean removeFile) {
this.removeFile = removeFile;
}
public boolean isSupportBP() {
return isSupportBP;
}
public void setSupportBP(boolean supportBP) {
isSupportBP = supportBP;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}

@ -1,111 +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.wrapper;
import com.arialyy.aria.core.inf.IEntity;
/**
* 组合任务实体包裹器用于加载和任务相关的参数
*/
public interface ITaskWrapper {
int ERROR = 0;
/**
* HTTP单任务载
*/
int D_HTTP = 1;
/**
* HTTP任务组下载
*/
int DG_HTTP = 2;
/**
* FTP单文件下载
*/
int D_FTP = 3;
/**
* FTP文件夹下载为避免登录过多子任务由单线程进行处理
*/
int D_FTP_DIR = 4;
/**
* HTTP单文件上传
*/
int U_HTTP = 5;
/**
* FTP单文件上传
*/
int U_FTP = 6;
/**
* M3u8点播
*/
int M3U8_VOD = 7;
/**
* m3u8直播
*/
int M3U8_LIVE = 8;
/**
* TCP 文件下载
*/
int D_TCP = 9;
/**
* TCP 文件上传
*/
int U_TCP = 10;
/**
* TCP 分片上传
*/
int U_TCP_PEER = 11;
/**
* SFTP 下载
*/
int D_SFTP = 12;
/**
* SFTP 上传
*/
int U_SFTP = 13;
/**
* 获取任务类型
*
* @return {@link ITaskWrapper}
*/
int getRequestType();
/**
* 获取任务实体
*/
IEntity getEntity();
/**
* 获取任务唯一标志
* 下载任务对应文件的下载地址
* 上传任务对应需要上传的文件路径
* 组合任务对应组合任务的groupHash
*/
String getKey();
}

@ -1,47 +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.wrapper;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.orm.AbsDbWrapper;
import com.arialyy.aria.orm.annotation.Many;
import com.arialyy.aria.orm.annotation.One;
import com.arialyy.aria.orm.annotation.Wrapper;
import java.util.ArrayList;
import java.util.List;
/**
* Created by laoyuyu on 2018/3/30.
* 任务记录和线程记录的关系
*/
@Wrapper
public class RecordWrapper extends AbsDbWrapper {
@One
public TaskRecord taskRecord;
@Many(parentColumn = "filePath", entityColumn = "taskKey")
public List<ThreadRecord> threadRecords;
@Override protected void handleConvert() {
if (threadRecords != null && !threadRecords.isEmpty()) {
taskRecord.threadRecords = threadRecords;
} else {
taskRecord.threadRecords = new ArrayList<>();
}
}
}

@ -1,27 +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.orm;
/**
* Created by laoyuyu on 2018/3/30.
*/
public abstract class AbsDbWrapper {
/**
* 处理转换
*/
protected abstract void handleConvert();
}

@ -1,39 +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.orm;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
/**
* Created by laoyuyu on 2018/3/22.
*/
public abstract class AbsDelegate {
static final String TAG = "AbsDelegate";
void closeCursor(Cursor cursor) {
SqlUtil.closeCursor(cursor);
}
/**
* 检查数据库是否关闭已经关闭的话打开数据库
*
* @return 返回数据库
*/
SQLiteDatabase checkDb(SQLiteDatabase db) {
return SqlUtil.checkDb(db);
}
}

@ -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.orm;
import com.arialyy.aria.orm.annotation.Foreign;
/**
* Created by laoyuyu on 2018/3/22.
* on update on delete 都可跟不同action功能
*
* @see <a href="https://sqlite.org/foreignkeys.html"></a>
* {@link Foreign#onDelete()}{@link Foreign#onUpdate()}
*/
public enum ActionPolicy {
/**
* 如果子表中有匹配的记录,则不允许对父表对应候选键进行update/delete操作
*/
NO_ACTION("NO ACTION"),
/**
* 和NO ACTION 作用一致和NO ACTION的区别是
* 主表update/delete执行时马上就触发约束
* 而NO ACTION 是执行完成语句后才触发约束
*/
RESTRICT("RESTRICT"),
/**
* 在父表上update/delete记录时将子表上匹配记录的列设为null (要注意子表的外键列不能为not null)
*/
SET_NULL("SET NULL"),
/**
* 父表有变更时,子表将外键列设置成一个默认的值default配置的值
*/
SET_DEFAULT("SET ERROR"),
/**
* 在父表上update/delete记录时同步update/delete掉子表的匹配记录
*/
CASCADE("CASCADE");
String function;
ActionPolicy(String function) {
this.function = function;
}
}

@ -1,61 +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.orm;
import android.text.TextUtils;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.download.M3U8Entity;
import com.arialyy.aria.core.upload.UploadEntity;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Created by lyy on 2017/4/6.
* 数据库配置信息
*/
class DBConfig {
/*adb pull /mnt/sdcard/Android/data/com.arialyy.simple/files/DB/AriaLyyDb d:/db*/
static boolean DEBUG = false;
static Map<String, Class<? extends DbEntity>> mapping = new LinkedHashMap<>();
static String DB_NAME;
static int VERSION = 58;
/**
* 是否将数据库保存在Sd卡{@code true}
*/
static final boolean SAVE_IN_SDCARD = false;
static {
if (TextUtils.isEmpty(DB_NAME)) {
DB_NAME = "AndroidAria.db";
}
if (VERSION == -1) {
VERSION = 1;
}
}
static {
mapping.put("DownloadEntity", DownloadEntity.class);
mapping.put("DownloadGroupEntity", DownloadGroupEntity.class);
mapping.put("UploadEntity", UploadEntity.class);
mapping.put("ThreadRecord", ThreadRecord.class);
mapping.put("TaskRecord", TaskRecord.class);
mapping.put("M3U8Entity", M3U8Entity.class);
}
}

@ -1,93 +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.orm;
import android.content.Context;
import android.content.ContextWrapper;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import com.arialyy.aria.util.CommonUtil;
import java.io.File;
import java.io.IOException;
/**
* 保存在sd卡的数据库使用的Context
*/
class DatabaseContext extends ContextWrapper {
public DatabaseContext(Context context) {
super(context);
}
/**
* 获得数据库路径如果不存在则创建对象对象
*/
@Override
public File getDatabasePath(String name) {
String dbDir = CommonUtil.getAppPath(getBaseContext());
dbDir += "DB";//数据库所在目录
String dbPath = dbDir + "/" + name;//数据库路径
//判断目录是否存在,不存在则创建该目录
File dirFile = new File(dbDir);
if (!dirFile.exists()) {
dirFile.mkdirs();
}
//数据库文件是否创建成功
boolean isFileCreateSuccess = false;
//判断文件是否存在,不存在则创建该文件
File dbFile = new File(dbPath);
if (!dbFile.exists()) {
try {
isFileCreateSuccess = dbFile.createNewFile();//创建文件
} catch (IOException e) {
e.printStackTrace();
}
} else {
isFileCreateSuccess = true;
}
//返回数据库文件对象
if (isFileCreateSuccess) {
return dbFile;
} else {
return null;
}
}
/**
* 重载这个方法是用来打开SD卡上的数据库的android 2.3及以下会调用这个方法
*/
@Override
public SQLiteDatabase openOrCreateDatabase(String name, int mode,
SQLiteDatabase.CursorFactory factory) {
return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null);
}
/**
* Android 4.0会调用此方法获取数据库
*
* @see android.content.ContextWrapper#openOrCreateDatabase(java.lang.String, int,
* android.database.sqlite.SQLiteDatabase.CursorFactory,
* android.database.DatabaseErrorHandler)
*/
@Override
public SQLiteDatabase openOrCreateDatabase(String name, int mode,
SQLiteDatabase.CursorFactory factory,
DatabaseErrorHandler errorHandler) {
return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null);
}
}

@ -1,174 +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.orm
import android.content.ContentProvider
import android.content.ContentValues
import android.content.Context
import android.database.Cursor
import android.net.Uri
import com.arialyy.aria.util.ALog
import com.arialyy.aria.util.CommonUtil
/**
* @Author laoyuyu
* @Description
* @Date 2:25 下午 2022/4/25
**/
class DbContentProvider : ContentProvider() {
val TAG = "DbContentProvider"
companion object {
// const val KEY_TABLE_NAME = "tableName"
const val KEY_ROW_ID = "rowId"
const val KEY_TABLE_CLAZZ = "tableClazz"
const val KEY_LIMIT = "limit"
fun createRequestUrl(context: Context, clazz: Class<*>): Uri {
return Uri.parse("content://${context.packageName}.com.arialyy.aria.provide/request?${KEY_TABLE_CLAZZ}=${clazz.name}")
}
fun getRequestUrl(context: Context): String {
return "content://${context.packageName}.com.arialyy.aria.provide/request"
}
fun getResponseUrl(context: Context): String {
return "content://${context.packageName}.com.arialyy.aria.provide/response"
}
}
/**
* key: clazzPath, value: tableName
*/
private val tableExistMap = mutableMapOf<String, String>()
private lateinit var helper: SqlHelper
override fun onCreate(): Boolean {
helper = SqlHelper.init(context)
return true
}
private fun getTableName(uri: Uri): String? {
val db = SqlUtil.checkDb(helper.db)
val clazzName = uri.getQueryParameter(KEY_TABLE_CLAZZ)
if (tableExistMap[clazzName!!] != null) {
return tableExistMap[clazzName]
}
val clazz: Class<out DbEntity>? =
javaClass.classLoader?.loadClass(clazzName) as Class<out DbEntity>?
if (clazz == null) {
ALog.e(TAG, "$clazz】为空")
return null
}
SqlUtil.checkOrCreateTable(db, clazz)
val tableName = CommonUtil.getClassName(clazz)
tableExistMap[clazzName] = tableName
return tableName
}
override fun query(
uri: Uri,
projection: Array<out String>?,
selection: String?,
selectionArgs: Array<out String>?,
sortOrder: String?
): Cursor? {
val db = SqlUtil.checkDb(helper.db)
val tableName = getTableName(uri)
if (tableName.isNullOrBlank()) {
return null
}
val clazzName = uri.getQueryParameter(KEY_TABLE_CLAZZ)
val clazz = javaClass.classLoader?.loadClass(clazzName) as Class<out DbEntity>?
val columns = SqlUtil.getColumns(clazz)
val limit = uri.getQueryParameter(KEY_LIMIT)
return db.query(
tableName,
columns.toTypedArray(),
selection,
selectionArgs,
null,
null,
null,
limit
)
}
override fun getType(uri: Uri): String? {
return null
}
override fun insert(uri: Uri, values: ContentValues?): Uri? {
val db = SqlUtil.checkDb(helper.db)
val tableName = getTableName(uri)
if (tableName.isNullOrBlank()) {
return null
}
db.beginTransaction()
try {
val rowId = db.insert(tableName, null, values)
if (rowId == -1L) {
return null
}
return Uri.parse("${getResponseUrl(context!!)}?${KEY_ROW_ID}=$rowId")
} finally {
db.endTransaction()
}
}
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
val db = SqlUtil.checkDb(helper.db)
val tableName = getTableName(uri)
if (tableName.isNullOrBlank()) {
return -1
}
db.beginTransaction()
try {
val rowId = db.delete(tableName, selection, selectionArgs)
if (rowId == -1) {
return -1
}
return rowId
} finally {
db.endTransaction()
}
}
override fun update(
uri: Uri,
values: ContentValues?,
selection: String?,
selectionArgs: Array<out String>?
): Int {
val db = SqlUtil.checkDb(helper.db)
val tableName = getTableName(uri)
if (tableName.isNullOrBlank()) {
return -1
}
db.beginTransaction()
try {
val rowId = db.update(tableName, values, selection, selectionArgs)
if (rowId == -1) {
return -1
}
return rowId
} finally {
db.endTransaction()
}
}
}

@ -1,295 +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.orm;
import java.util.ArrayList;
import java.util.List;
/**
* Created by lyy on 2015/11/2. 所有数据库实体父类
*/
public abstract class DbEntity {
private static final Object LOCK = new Object();
public long rowID = -1;
protected DbEntity() {
}
protected long getRowID() {
return rowID;
}
/**
* 查询关联数据
* <code>
* DbEntity.findRelationData(DGEntityWrapper.class, "downloadUrl=?", downloadUrl);
* </code>
*
* @param expression 查询条件
*/
public static <T extends AbsDbWrapper> List<T> findRelationData(Class<T> clazz,
String... expression) {
return DelegateWrapper.getInstance().findRelationData(clazz, expression);
}
/**
* 分页查询关联数据
*
* <code>
* DbEntity.findRelationData(DGEntityWrapper.class, 0, 10, "downloadUrl=?", downloadUrl);
* </code>
*
* @param expression 查询条件
* @param page 需要查询的页数从1开始如果page小于1 num 小于1返回null
* @param num 每页返回的数量
* @return 没有数据返回null如果页数大于总页数返回null
*/
public static <T extends AbsDbWrapper> List<T> findRelationData(Class<T> clazz, int page, int num,
String... expression) {
if (page < 1 || num < 1) {
return null;
}
return DelegateWrapper.getInstance().findRelationData(clazz, page, num, expression);
}
/**
* 检查某个字段的值是否存在
*
* @param expression 字段和值"downloadPath=?"
* @return {@code true}该字段的对应的value已存在
*/
public static boolean checkDataExist(Class clazz, String... expression) {
return DelegateWrapper.getInstance().checkDataExist(clazz, expression);
}
/**
* 清空表数据
*/
public static <T extends DbEntity> void clean(Class<T> clazz) {
DelegateWrapper.getInstance().clean(clazz);
}
/**
* 直接执行sql语句
*/
public static void exeSql(String sql) {
DelegateWrapper.getInstance().exeSql(sql);
}
/**
* 查询所有数据
*
* @return 没有数据返回null
*/
public static <T extends DbEntity> List<T> findAllData(Class<T> clazz) {
return DelegateWrapper.getInstance().findAllData(clazz);
}
/**
* 查询第一条数据
*/
public static <T extends DbEntity> T findFirst(Class<T> clazz) {
List<T> list = findAllData(clazz);
return (list == null || list.size() == 0) ? null : list.get(0);
}
/**
* 查询一组数据
* <code>
* DbEntity.findFirst(DownloadEntity.class, "downloadUrl=?", downloadUrl);
* </code>
*
* @return 没有数据返回null
*/
public static <T extends DbEntity> List<T> findDatas(Class<T> clazz, String... expression) {
return DelegateWrapper.getInstance().findData(clazz, expression);
}
/**
* 分页查询数据
* <code>
* DbEntity.findFirst(DownloadEntity.class, 0, 10, "downloadUrl=?", downloadUrl);
* </code>
*
* @param page 需要查询的页数从1开始如果page小于1 num 小于1返回null
* @param num 每页返回的数量
* @return 没有数据返回null如果页数大于总页数返回null
*/
public static <T extends DbEntity> List<T> findDatas(Class<T> clazz, int page, int num,
String... expression) {
if (page < 1 || num < 1) {
return null;
}
return DelegateWrapper.getInstance().findData(clazz, page, num, expression);
}
/**
* 模糊查询一组数据
* <code>
* DbEntity.findDataByFuzzy(DownloadEntity.class, "downloadUrl like http://");
* </code>
*
* @return 没有数据返回null
*/
public static <T extends DbEntity> List<T> findDataByFuzzy(Class<T> clazz, String conditions) {
return DelegateWrapper.getInstance().findDataByFuzzy(clazz, conditions);
}
/**
* 模糊查询一组数据
* <code>
* DbEntity.findDataByFuzzy(DownloadEntity.class, 0, 10, "downloadUrl like http://");
* </code>
*
* @param page 需要查询的页数从1开始如果page小于1 num 小于1返回null
* @param num 每页返回的数量
* @return 没有数据返回null如果页数大于总页数返回null
*/
public static <T extends DbEntity> List<T> findDataByFuzzy(Class<T> clazz, int page, int num,
String conditions) {
return DelegateWrapper.getInstance().findDataByFuzzy(clazz, page, num, conditions);
}
/**
* 查询一行数据
* <code>
* DbEntity.findFirst(DownloadEntity.class, "downloadUrl=?", downloadUrl);
* </code>
*
* @return 没有数据返回null
*/
public static <T extends DbEntity> T findFirst(Class<T> clazz, String... expression) {
DelegateWrapper util = DelegateWrapper.getInstance();
List<T> datas = util.findData(clazz, expression);
return datas == null ? null : datas.size() > 0 ? datas.get(0) : null;
}
/**
* 插入多条数据
*/
public static <T extends DbEntity> void insertManyData(List<T> entities) {
checkListData(entities);
DelegateWrapper.getInstance().insertManyData(entities);
}
/**
* 修改多条数据
*/
public static <T extends DbEntity> void updateManyData(List<T> entities) {
checkListData(entities);
DelegateWrapper.getInstance().updateManyData(entities);
}
/**
* 保存多条数据通过rowID来判断记录存在以否如果数据库已有记录则更新该记录如果数据库中没有记录则保存该记录
*/
public static <T extends DbEntity> void saveAll(List<T> entities) {
checkListData(entities);
List<T> insertD = new ArrayList<>();
List<T> updateD = new ArrayList<>();
DelegateWrapper wrapper = DelegateWrapper.getInstance();
for (T entity : entities) {
if (entity.rowID == -1) {
insertD.add(entity);
continue;
}
if (wrapper.isExist(entity.getClass(), entity.rowID)) {
updateD.add(entity);
} else {
insertD.add(entity);
}
}
if (!insertD.isEmpty()) {
wrapper.insertManyData(insertD);
}
if (!updateD.isEmpty()) {
wrapper.updateManyData(updateD);
}
}
/**
* 检查批量操作的列表数据如果数据为空抛出{@link NullPointerException}
*/
private static <T extends DbEntity> void checkListData(List<T> entities) {
if (entities == null || entities.isEmpty()) {
throw new NullPointerException("列表数据为空");
}
}
/**
* 删除当前数据
*/
public void deleteData() {
deleteData(getClass(), "rowid=?", rowID + "");
}
/**
* 根据条件删除数据
* <code>
* DbEntity.deleteData(DownloadEntity.class, "downloadUrl=?", downloadUrl);
* </code>
*/
public static <T extends DbEntity> void deleteData(Class<T> clazz, String... expression) {
DelegateWrapper util = DelegateWrapper.getInstance();
util.delData(clazz, expression);
}
/**
* 修改数据
*/
public void update() {
DelegateWrapper.getInstance().updateData(this);
}
/**
* 保存自身如果表中已经有数据则更新数据否则插入数据 只有 target中checkEntity成功后才能保存创建实体部分也不允许保存
*/
public void save() {
synchronized (LOCK) {
if (thisIsExist()) {
update();
} else {
insert();
}
}
}
/**
* 查找数据在表中是否存在
*/
private boolean thisIsExist() {
DelegateWrapper util = DelegateWrapper.getInstance();
return rowID != -1 && util.isExist(getClass(), rowID);
}
/**
* 表是否存在
*
* @return {@code true} 存在
*/
public static boolean tableExists(Class<DbEntity> clazz) {
return DelegateWrapper.getInstance().tableExists(clazz);
}
/**
* 插入数据只有 target中checkEntity成功后才能插入创建实体部分也不允许操作
*/
public void insert() {
DelegateWrapper.getInstance().insertData(this);
}
}

@ -1,639 +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.orm;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils;
import android.util.SparseArray;
import com.arialyy.aria.orm.annotation.Many;
import com.arialyy.aria.orm.annotation.One;
import com.arialyy.aria.orm.annotation.Wrapper;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import java.lang.reflect.Field;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* Created by laoyuyu on 2018/3/22.
* 查询数据
*/
class DelegateFind extends AbsDelegate {
private final String PARENT_COLUMN_ALIAS = "p";
private final String CHILD_COLUMN_ALIAS = "c";
private DelegateFind() {
}
/**
* 获取{@link One}{@link Many}注解的字段
*
* @return 返回[OneField, ManyField] 如果注解依赖错误返回null
*/
private Field[] getOneAndManyField(Class clazz) {
Field[] om = new Field[2];
Field[] fields = clazz.getDeclaredFields();
Field one = null, many = null;
boolean hasOne = false, hasMany = false;
for (Field field : fields) {
if (SqlUtil.isOne(field)) {
if (hasOne) {
ALog.w(TAG, "查询数据失败,实体中有多个@One 注解");
return null;
}
hasOne = true;
one = field;
}
if (SqlUtil.isMany(field)) {
if (hasMany) {
ALog.w(TAG, "查询数据失败,实体中有多个@Many 注解");
return null;
}
if (!field.getType().isAssignableFrom(List.class)) {
ALog.w(TAG, "查询数据失败,@Many 注解的类型不是List");
return null;
}
hasMany = true;
many = field;
}
}
if (one == null || many == null) {
ALog.w(TAG, "查询数据失败,实体中没有@One或@Many注解");
return null;
}
if (many.getType() != List.class) {
ALog.w(TAG, "查询数据失败,@Many注解的字段必须是List");
return null;
}
om[0] = one;
om[1] = many;
return om;
}
/**
* 查找一对多的关联数据
* 如果查找不到数据或实体没有被{@link Wrapper}注解将返回null
* 如果实体中没有{@link One}{@link Many}注解将返回null
* 如果实体中有多个{@link One}{@link Many}注解将返回nul
* {@link One} 的注解对象必须是{@link DbEntity}{@link Many}的注解对象必须是List并且List中的类型必须是{@link DbEntity}
*/
<T extends AbsDbWrapper> List<T> findRelationData(SQLiteDatabase db, Class<T> clazz,
String... expression) {
return exeRelationSql(db, clazz, 1, Integer.MAX_VALUE, expression);
}
/**
* 查找一对多的关联数据
* 如果查找不到数据或实体没有被{@link Wrapper}注解将返回null
* 如果实体中没有{@link One}{@link Many}注解将返回null
* 如果实体中有多个{@link One}{@link Many}注解将返回nul
* {@link One} 的注解对象必须是{@link DbEntity}{@link Many}的注解对象必须是List并且List中的类型必须是{@link DbEntity}
*/
<T extends AbsDbWrapper> List<T> findRelationData(SQLiteDatabase db, Class<T> clazz,
int page, int num, String... expression) {
if (page < 1 || num < 1) {
ALog.w(TAG, "page,num 小于1");
return null;
}
return exeRelationSql(db, clazz, page, num, expression);
}
/**
* 执行关联查询如果不需要分页page和num传-1
*
* @param page 当前页
* @param num 一页的数量
*/
private <T extends AbsDbWrapper> List<T> exeRelationSql(SQLiteDatabase db, Class<T> wrapperClazz,
int page, int num, String... expression) {
db = checkDb(db);
if (SqlUtil.isWrapper(wrapperClazz)) {
Field[] om = getOneAndManyField(wrapperClazz);
if (om == null) {
return null;
}
StringBuilder sb = new StringBuilder();
Field one = om[0], many = om[1];
try {
Many m = many.getAnnotation(Many.class);
Class parentClazz = Class.forName(one.getType().getName());
Class childClazz = Class.forName(CommonUtil.getListParamType(many).getName());
// 检查表
SqlUtil.checkOrCreateTable(db, parentClazz);
SqlUtil.checkOrCreateTable(db, childClazz);
final String pTableName = parentClazz.getSimpleName();
final String cTableName = childClazz.getSimpleName();
List<Field> pColumn = SqlUtil.getAllNotIgnoreField(parentClazz);
List<Field> cColumn = SqlUtil.getAllNotIgnoreField(childClazz);
StringBuilder pSb = new StringBuilder();
StringBuilder cSb = new StringBuilder();
if (pColumn != null) {
pSb.append(pTableName.concat(".rowid AS ").concat(PARENT_COLUMN_ALIAS).concat("rowid,"));
for (Field f : pColumn) {
String temp = PARENT_COLUMN_ALIAS.concat(f.getName());
pSb.append(pTableName.concat(".").concat(f.getName()))
.append(" AS ")
.append(temp)
.append(",");
}
}
if (cColumn != null) {
pSb.append(cTableName.concat(".rowid AS ").concat(CHILD_COLUMN_ALIAS).concat("rowid,"));
for (Field f : cColumn) {
String temp = CHILD_COLUMN_ALIAS.concat(f.getName());
cSb.append(cTableName.concat(".").concat(f.getName()))
.append(" AS ")
.append(temp)
.append(",");
}
}
String pColumnAlia = pSb.toString();
String cColumnAlia = cSb.toString();
if (!TextUtils.isEmpty(pColumnAlia)) {
pColumnAlia = pColumnAlia.substring(0, pColumnAlia.length() - 1);
}
if (!TextUtils.isEmpty(cColumnAlia)) {
cColumnAlia = cColumnAlia.substring(0, cColumnAlia.length() - 1);
}
sb.append("SELECT ");
if (!TextUtils.isEmpty(pColumnAlia)) {
sb.append(pColumnAlia).append(",");
}
if (!TextUtils.isEmpty(cColumnAlia)) {
sb.append(cColumnAlia);
}
if (TextUtils.isEmpty(pColumnAlia) && TextUtils.isEmpty(cColumnAlia)) {
sb.append(" * ");
}
sb.append(" FROM ")
.append(pTableName)
.append(" INNER JOIN ")
.append(cTableName)
.append(" ON ")
.append(pTableName.concat(".").concat(m.parentColumn()))
.append(" = ")
.append(cTableName.concat(".").concat(m.entityColumn()));
String sql;
if (expression != null && expression.length > 0) {
if (!CommonUtil.checkSqlExpression(expression)) {
return null;
}
sb.append(" WHERE ").append(expression[0]).append(" ");
sql = sb.toString();
sql = sql.replace("?", "%s");
Object[] params = new String[expression.length - 1];
for (int i = 0, len = params.length; i < len; i++) {
params[i] = String.format("'%s'", SqlUtil.encodeStr(expression[i + 1]));
}
sql = String.format(sql, params);
} else {
sql = sb.toString();
}
boolean paged = false;
if (page != -1 && num != -1) {
paged = true;
sql = sql.concat(String.format(" Group by %s LIMIT %s,%s",
pTableName.concat(".").concat(m.parentColumn()), (page - 1) * num, num));
}
Cursor cursor = db.rawQuery(sql, null);
List<T> data =
newInstanceEntity(wrapperClazz, parentClazz, childClazz, cursor, pColumn, cColumn,
paged, db, m.entityColumn(), m.parentColumn());
closeCursor(cursor);
return data;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} else {
ALog.e(TAG, "查询数据失败,实体类没有使用@Wrapper 注解");
return null;
}
return null;
}
/**
* 创建关联查询的数据
*
* @param pColumn 父表的所有字段
* @param cColumn 字表的所有字段
*/
private synchronized <T extends AbsDbWrapper, P extends DbEntity, C extends DbEntity> List<T> newInstanceEntity(
Class<T> wrapperClazz, Class<P> parentClazz,
Class<C> childClazz,
Cursor cursor,
List<Field> pColumn, List<Field> cColumn, boolean paged, SQLiteDatabase db,
String entityColumn, String parentColumn) {
List<T> wrappers = new ArrayList<>();
SparseArray<List<DbEntity>> childs = new SparseArray<>(); // 所有子表数据
SparseArray<DbEntity> parents = new SparseArray<>(); // 所有父表数据
try {
while (cursor.moveToNext()) {
int pRowId = cursor.getInt(cursor.getColumnIndex(PARENT_COLUMN_ALIAS.concat("rowid")));
if (childs.get(pRowId) == null) {
childs.put(pRowId, new ArrayList<DbEntity>());
parents.put(pRowId, createParent(pRowId, parentClazz, pColumn, cursor));
}
if (paged) {
List<C> list = createChildren(db, childClazz, pColumn, entityColumn, parentColumn,
parents.get(pRowId));
if (list != null) {
childs.get(pRowId).addAll(list);
}
} else {
childs.get(pRowId).add(createChild(childClazz, cColumn, cursor));
}
}
List<Field> wFields = SqlUtil.getAllNotIgnoreField(wrapperClazz);
if (wFields == null || wFields.isEmpty()) {
return null;
}
for (int i = 0; i < parents.size(); i++) {
int pRowId = parents.keyAt(i);
T wrapper = wrapperClazz.newInstance();
boolean isPSet = false, isCSet = false; // 保证One 或 Many 只设置一次
for (Field f : wFields) {
if (!isPSet && f.getAnnotation(One.class) != null) {
f.set(wrapper, parents.get(pRowId));
isPSet = true;
}
if (!isCSet && f.getAnnotation(Many.class) != null) {
f.set(wrapper, childs.get(pRowId));
isCSet = true;
}
}
wrapper.handleConvert(); //处理下转换
wrappers.add(wrapper);
}
} catch (Exception e) {
e.printStackTrace();
}
return wrappers;
}
/**
* 创建子对象集合
*/
private <T extends DbEntity> List<T> createChildren(SQLiteDatabase db, Class<T> childClazz,
List<Field> pColumn,
String entityColumn, String parentColumn, DbEntity parents)
throws IllegalAccessException {
for (Field field : pColumn) {
field.setAccessible(true);
if (field.getName().equals(parentColumn)) {
Object o = field.get(parents);
if (o instanceof String) {
o = URLEncoder.encode((String) o);
}
return findData(db, childClazz, entityColumn + "='" + o + "'");
}
}
return new ArrayList<T>();
}
/**
* 创建子对象
*/
private <T extends DbEntity> T createChild(Class<T> childClazz, List<Field> cColumn,
Cursor cursor)
throws InstantiationException, IllegalAccessException {
T child = childClazz.newInstance();
child.rowID = cursor.getInt(cursor.getColumnIndex(CHILD_COLUMN_ALIAS.concat("rowid")));
for (Field field : cColumn) {
field.setAccessible(true);
int columnIndex = cursor.getColumnIndex(CHILD_COLUMN_ALIAS.concat(field.getName()));
setFieldValue(field.getType(), field, columnIndex, cursor, child);
}
return child;
}
/**
* 创建父对象
*/
private <T extends DbEntity> T createParent(int rowId, Class<T> parentClazz, List<Field> pColumn,
Cursor cursor)
throws InstantiationException, IllegalAccessException {
T parent = parentClazz.newInstance();
parent.rowID = rowId;
for (Field field : pColumn) {
field.setAccessible(true);
int columnIndex = cursor.getColumnIndex(PARENT_COLUMN_ALIAS.concat(field.getName()));
setFieldValue(field.getType(), field, columnIndex, cursor, parent);
}
return parent;
}
/**
* 条件查寻数据
*/
<T extends DbEntity> List<T> findData(SQLiteDatabase db, Class<T> clazz, String... expression) {
db = checkDb(db);
if (!CommonUtil.checkSqlExpression(expression)) {
return null;
}
String sql = String.format("SELECT rowid, * FROM %s WHERE %s", CommonUtil.getClassName(clazz),
expression[0]);
String[] params = new String[expression.length - 1];
try {
// 处理系统出现的问题:https://github.com/AriaLyy/Aria/issues/450
System.arraycopy(expression, 1, params, 0, params.length);
} catch (Exception e) {
e.printStackTrace();
return null;
}
return exeNormalDataSql(db, clazz, sql, params);
}
/**
* 获取分页数据
*/
<T extends DbEntity> List<T> findData(SQLiteDatabase db, Class<T> clazz, int page, int num,
String... expression) {
if (page < 1 || num < 1) {
ALog.w(TAG, "page, bum 小于1");
return null;
}
db = checkDb(db);
if (!CommonUtil.checkSqlExpression(expression)) {
return null;
}
String sql = String.format("SELECT rowid, * FROM %s WHERE %s LIMIT %s,%s",
CommonUtil.getClassName(clazz),
expression[0], (page - 1) * num, num);
String[] params = new String[expression.length - 1];
try {
// 处理系统出现的问题:https://github.com/AriaLyy/Aria/issues/450
System.arraycopy(expression, 1, params, 0, params.length);
} catch (Exception e) {
e.printStackTrace();
return null;
}
return exeNormalDataSql(db, clazz, sql, params);
}
/**
* 模糊查寻数据
*/
<T extends DbEntity> List<T> findDataByFuzzy(SQLiteDatabase db, Class<T> clazz,
String conditions) {
db = checkDb(db);
if (TextUtils.isEmpty(conditions)) {
throw new IllegalArgumentException("sql语句表达式不能为null或\"\"");
}
if (!conditions.toUpperCase().contains("LIKE")) {
throw new IllegalArgumentException("sql语句表达式未包含LIEK");
}
String sql = String.format("SELECT rowid, * FROM %s, WHERE %s", CommonUtil.getClassName(clazz),
conditions);
return exeNormalDataSql(db, clazz, sql, null);
}
/**
* 分页模糊搜索数据
*/
<T extends DbEntity> List<T> findDataByFuzzy(SQLiteDatabase db, Class<T> clazz,
int page, int num, String conditions) {
if (page < 1 || num < 1) {
ALog.w(TAG, "page, bum 小于1");
return null;
}
db = checkDb(db);
if (TextUtils.isEmpty(conditions)) {
throw new IllegalArgumentException("sql语句表达式不能为null或\"\"");
}
if (!conditions.toUpperCase().contains("LIKE")) {
throw new IllegalArgumentException("sql语句表达式未包含LIEK");
}
String sql = String.format("SELECT rowid, * FROM %s WHERE %s LIMIT %s,%s",
CommonUtil.getClassName(clazz), conditions, (page - 1) * num, num);
return exeNormalDataSql(db, clazz, sql, null);
}
/**
* 查找表的所有数据
*/
<T extends DbEntity> List<T> findAllData(SQLiteDatabase db, Class<T> clazz) {
db = checkDb(db);
String sql = String.format("SELECT rowid, * FROM %s", CommonUtil.getClassName(clazz));
return exeNormalDataSql(db, clazz, sql, null);
}
/**
* 执行查询普通数据的sql语句并创建对象
*
* @param sql sql 查询语句
* @param selectionArgs 查询参数如何sql语句中查询条件含有'?'则该参数不能为空
*/
private <T extends DbEntity> List<T> exeNormalDataSql(SQLiteDatabase db, Class<T> clazz,
String sql, String[] selectionArgs) {
SqlUtil.checkOrCreateTable(db, clazz);
Cursor cursor;
try {
if (selectionArgs != null) {
String[] temp = new String[selectionArgs.length];
int i = 0;
for (String arg : selectionArgs) {
temp[i] = SqlUtil.encodeStr(arg);
i++;
}
//sql执行失败 android.database.sqlite.SQLiteException: no such column: filePath 异常
cursor = db.rawQuery(sql, temp);
} else {
cursor = db.rawQuery(sql, null);
}
List<T> data = cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor) : null;
closeCursor(cursor);
return data;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 根据数据游标创建一个具体的对象
*/
private synchronized <T extends DbEntity> List<T> newInstanceEntity(Class<T> clazz,
Cursor cursor) {
List<Field> fields = CommonUtil.getAllFields(clazz);
List<T> entitys = new ArrayList<>();
if (fields != null && fields.size() > 0) {
try {
while (cursor.moveToNext()) {
T entity = clazz.newInstance();
String primaryName = "";
for (Field field : fields) {
field.setAccessible(true);
if (SqlUtil.isIgnore(field)) {
continue;
}
Class<?> type = field.getType();
if (SqlUtil.isPrimary(field) && (type == int.class || type == Integer.class)) {
primaryName = field.getName();
}
int column = cursor.getColumnIndex(field.getName());
if (column == -1) continue;
setFieldValue(type, field, column, cursor, entity);
}
//当设置了主键,而且主键的类型为integer时,查询RowID等于主键
entity.rowID = cursor.getInt(
cursor.getColumnIndex(TextUtils.isEmpty(primaryName) ? "rowid" : primaryName));
//mDataCache.put(getCacheKey(entity), entity);
entitys.add(entity);
}
closeCursor(cursor);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return entitys;
}
/**
* 设置字段的值
*
* @throws IllegalAccessException
*/
private void setFieldValue(Class type, Field field, int columnIndex, Cursor cursor,
DbEntity entity)
throws IllegalAccessException {
if (cursor == null || cursor.isClosed()) {
ALog.e(TAG, "cursor没有初始化");
return;
}
if (type == String.class) {
String temp = cursor.getString(columnIndex);
if (!TextUtils.isEmpty(temp)) {
field.set(entity, URLDecoder.decode(temp));
}
} else if (type == int.class || type == Integer.class) {
field.setInt(entity, cursor.getInt(columnIndex));
} else if (type == float.class || type == Float.class) {
field.setFloat(entity, cursor.getFloat(columnIndex));
} else if (type == double.class || type == Double.class) {
field.setDouble(entity, cursor.getDouble(columnIndex));
} else if (type == long.class || type == Long.class) {
field.setLong(entity, cursor.getLong(columnIndex));
} else if (type == boolean.class || type == Boolean.class) {
String temp = cursor.getString(columnIndex);
if (TextUtils.isEmpty(temp)) {
field.setBoolean(entity, false);
} else {
field.setBoolean(entity, !temp.equalsIgnoreCase("false"));
}
} else if (type == java.util.Date.class || type == java.sql.Date.class) {
field.set(entity, new Date(URLDecoder.decode(cursor.getString(columnIndex))));
} else if (type == byte[].class) {
field.set(entity, cursor.getBlob(columnIndex));
} else if (type == Map.class) {
String temp = cursor.getString(columnIndex);
if (!TextUtils.isEmpty(temp)) {
field.set(entity, SqlUtil.str2Map(URLDecoder.decode(temp)));
}
} else if (type == List.class) {
String value = cursor.getString(columnIndex);
if (!TextUtils.isEmpty(value)) {
field.set(entity, SqlUtil.str2List(URLDecoder.decode(value), field));
}
}
}
/**
* 获取所在行Id
*/
int[] getRowId(SQLiteDatabase db, Class clazz) {
db = checkDb(db);
Cursor cursor = db.rawQuery("SELECT rowid, * FROM " + CommonUtil.getClassName(clazz), null);
int[] ids = new int[cursor.getCount()];
int i = 0;
while (cursor.moveToNext()) {
ids[i] = cursor.getInt(cursor.getColumnIndex("rowid"));
i++;
}
cursor.close();
return ids;
}
/**
* 获取行Id
*/
int getRowId(SQLiteDatabase db, Class clazz, Object[] wheres, Object[] values) {
db = checkDb(db);
if (wheres.length <= 0 || values.length <= 0) {
ALog.e(TAG, "请输入删除条件");
return -1;
} else if (wheres.length != values.length) {
ALog.e(TAG, "groupHash 和 vaule 长度不相等");
return -1;
}
StringBuilder sb = new StringBuilder();
sb.append("SELECT rowid FROM ").append(CommonUtil.getClassName(clazz)).append(" WHERE ");
int i = 0;
for (Object where : wheres) {
sb.append(where).append("=").append("'").append(values[i]).append("'");
sb.append(i >= wheres.length - 1 ? "" : ",");
i++;
}
Cursor c = db.rawQuery(sb.toString(), null);
int id = c.getColumnIndex("rowid");
c.close();
return id;
}
/**
* 通过rowId判断数据是否存在
*/
<T extends DbEntity> boolean itemExist(SQLiteDatabase db, Class<T> clazz, long rowId) {
return itemExist(db, CommonUtil.getClassName(clazz), rowId);
}
/**
* 通过rowId判断数据是否存在
*/
boolean itemExist(SQLiteDatabase db, String tableName, long rowId) {
db = checkDb(db);
String sql = "SELECT rowid FROM " + tableName + " WHERE rowid=" + rowId;
Cursor cursor = db.rawQuery(sql, null);
boolean isExist = cursor.getCount() > 0;
cursor.close();
return isExist;
}
}

@ -1,69 +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.orm;
import android.util.SparseArray;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* Created by laoyuyu on 2018/3/22.
* Delegate管理器
*/
class DelegateManager {
private final String TAG = "ModuleFactory";
private SparseArray<AbsDelegate> mDelegates = new SparseArray<>();
private static volatile DelegateManager INSTANCE = null;
private DelegateManager() {
}
static DelegateManager getInstance() {
if (INSTANCE == null) {
synchronized (DelegateManager.class) {
INSTANCE = new DelegateManager();
}
}
return INSTANCE;
}
/**
* 获取Module
*/
<M extends AbsDelegate> M getDelegate(Class<M> clazz) {
M delegate = (M) mDelegates.get(clazz.hashCode());
try {
if (delegate == null) {
Constructor c = clazz.getDeclaredConstructor();
c.setAccessible(true);
delegate = (M) c.newInstance();
mDelegates.put(clazz.hashCode(), delegate);
return delegate;
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return delegate;
}
}

@ -1,58 +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.orm;
import android.content.ContentValues;
import android.content.Context;
import android.net.Uri;
import com.arialyy.aria.util.ALog;
import java.util.List;
/**
* Created by laoyuyu on 2018/3/22. 增加数据更新数据
*/
class DelegateUpdate extends AbsDelegate {
private DelegateUpdate() {
}
/**
* 修改某行数据
*/
synchronized void updateData(Context context, DbEntity dbEntity) {
Uri uri = DbContentProvider.Companion.createRequestUrl(context, dbEntity.getClass());
ContentValues values = DbUtil.INSTANCE.createValues(dbEntity);
if (values != null) {
int rowId = context.getContentResolver()
.update(uri, values, "rowid=?", new String[] { String.valueOf(dbEntity.rowID) });
if (rowId != -1) {
ALog.d(TAG, "更新数据成功,rowid = " + rowId);
} else {
ALog.e(TAG, "更新数据成功,rowid = " + rowId);
}
return;
}
ALog.e(TAG, "更新记录失败,记录没有属性字段");
}
/**
* 更新多条记录
*/
synchronized <T extends DbEntity> void updateManyData(Context context, List<T> dbEntities) {
for (DbEntity entity : dbEntities) {
updateData(context, entity);
}
}
}

@ -1,213 +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.orm;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import java.util.List;
/**
* Created by lyy on 2015/2/11. 数据库操作工具
*/
public class DelegateWrapper {
private static final String TAG = "DelegateWrapper";
private volatile static DelegateWrapper INSTANCE = null;
private SQLiteDatabase mDb;
private DelegateManager mDManager;
private Context context;
private DelegateWrapper() {
}
private DelegateWrapper(Context context) {
this.context = context.getApplicationContext();
SqlHelper helper = SqlHelper.init(context.getApplicationContext());
mDb = helper.getDb();
mDManager = DelegateManager.getInstance();
}
public static DelegateWrapper init(Context context) {
if (INSTANCE == null) {
synchronized (DelegateWrapper.class) {
if (INSTANCE == null) {
INSTANCE = new DelegateWrapper(context);
}
}
}
return INSTANCE;
}
static DelegateWrapper getInstance() {
if (INSTANCE == null) {
throw new NullPointerException("请在Application中调用init进行数据库工具注册注册");
}
return INSTANCE;
}
/**
* 查询关联表数据
*
* @param expression 查询条件
*/
<T extends AbsDbWrapper> List<T> findRelationData(Class<T> clazz, String... expression) {
return mDManager.getDelegate(DelegateFind.class).findRelationData(mDb, clazz, expression);
}
/**
* 查询关联表数据
*
* @param expression 查询条件
*/
<T extends AbsDbWrapper> List<T> findRelationData(Class<T> clazz, int page, int num,
String... expression) {
return mDManager.getDelegate(DelegateFind.class)
.findRelationData(mDb, clazz, page, num, expression);
}
/**
* 检查某个字段的值是否存在
*
* @param expression 字段和值"url=xxx"
* @return {@code true}该字段的对应的value已存在
*/
boolean checkDataExist(Class clazz, String... expression) {
return SqlUtil.checkDataExist(mDb, clazz, expression);
}
/**
* 清空表数据
*/
<T extends DbEntity> void clean(Class<T> clazz) {
SqlUtil.clean(mDb, clazz);
}
/**
* 执行sql语句
*/
void exeSql(String sql) {
mDb.execSQL(sql);
}
/**
* 删除某条数据
*/
<T extends DbEntity> void delData(Class<T> clazz, String... expression) {
mDManager.getDelegate(DelegateDel.class).delData(context, clazz, expression);
}
/**
* 修改某行数据
*/
void updateData(DbEntity dbEntity) {
mDManager.getDelegate(DelegateUpdate.class).updateData(context, dbEntity);
}
/**
* 更新多条数据
*/
<T extends DbEntity> void updateManyData(List<T> dbEntitys) {
mDManager.getDelegate(DelegateUpdate.class).updateManyData(context, dbEntitys);
}
/**
* 遍历所有数据
*/
<T extends DbEntity> List<T> findAllData(Class<T> clazz) {
return mDManager.getDelegate(DelegateFind.class).findAllData(mDb, clazz);
}
/**
* 条件查寻数据
*/
<T extends DbEntity> List<T> findData(Class<T> clazz, String... expression) {
return mDManager.getDelegate(DelegateFind.class).findData(mDb, clazz, expression);
}
/**
* 获取分页数据
*/
<T extends DbEntity> List<T> findData(Class<T> clazz, int page, int num, String... expression) {
return mDManager.getDelegate(DelegateFind.class).findData(mDb, clazz, page, num, expression);
}
/**
* 模糊查寻数据
*/
<T extends DbEntity> List<T> findDataByFuzzy(Class<T> clazz, String conditions) {
return mDManager.getDelegate(DelegateFind.class).findDataByFuzzy(mDb, clazz, conditions);
}
/**
* 模糊查寻数据
*/
<T extends DbEntity> List<T> findDataByFuzzy(Class<T> clazz, int page, int num,
String conditions) {
return mDManager.getDelegate(DelegateFind.class)
.findDataByFuzzy(mDb, clazz, page, num, conditions);
}
/**
* 通过rowId判断数据是否存在
*/
<T extends DbEntity> boolean isExist(Class<T> clazz, long rowId) {
return mDManager.getDelegate(DelegateFind.class).itemExist(mDb, clazz, rowId);
}
/**
* 通过rowId判断数据是否存在
*/
boolean isExist(String tableName, long rowId) {
return mDManager.getDelegate(DelegateFind.class).itemExist(mDb, tableName, rowId);
}
/**
* 插入数据
*/
void insertData(DbEntity dbEntity) {
mDManager.getDelegate(DelegateInsert.class).insertData(context, dbEntity);
}
/**
* 插入多条数据
*/
<T extends DbEntity> void insertManyData(List<T> dbEntitys) {
mDManager.getDelegate(DelegateInsert.class).insertManyData(context, dbEntitys);
}
/**
* 查找某张表是否存在
*/
public boolean tableExists(Class clazz) {
return SqlUtil.tableExists(mDb, clazz);
}
/**
* 获取所在行Id
*/
int[] getRowId(Class clazz) {
return mDManager.getDelegate(DelegateFind.class).getRowId(mDb, clazz);
}
/**
* 获取行Id
*/
int getRowId(Class clazz, Object[] wheres, Object[] values) {
return mDManager.getDelegate(DelegateFind.class).getRowId(mDb, clazz, wheres, values);
}
}

@ -1,552 +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.orm;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Build;
import android.text.TextUtils;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.M3U8Entity;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.util.ALog;
import java.io.File;
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 2015/11/2.
* sql帮助类
*/
final class SqlHelper extends SQLiteOpenHelper {
private static final String TAG = "SqlHelper";
private static volatile SqlHelper INSTANCE = null;
private static boolean mainTmpDirSet = false;
private Context mContext;
synchronized static SqlHelper init(Context context) {
if (INSTANCE == null) {
synchronized (SqlHelper.class) {
INSTANCE = new SqlHelper(context.getApplicationContext());
}
}
return INSTANCE;
}
static SqlHelper getInstance() {
return INSTANCE;
}
private SqlHelper(Context context) {
super(DBConfig.SAVE_IN_SDCARD ? new DatabaseContext(context) : context, DBConfig.DB_NAME, null,
DBConfig.VERSION);
mContext = context;
}
@Override public void onOpen(SQLiteDatabase db) {
super.onOpen(db);
}
@Override public void onConfigure(SQLiteDatabase db) {
super.onConfigure(db);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
db.setForeignKeyConstraintsEnabled(true);
} else {
// SQLite在3.6.19版本中开始支持外键约束,
// 而在Android中 2.1以前的版本使用的SQLite版本是3.5.9, 在2.2版本中使用的是3.6.22.
// 但是为了兼容以前的程序,默认并没有启用该功能,如果要启用该功能
// 需要使用如下语句:
db.execSQL("PRAGMA foreign_keys=ON;");
}
}
@Override public void onCreate(SQLiteDatabase db) {
Set<String> tables = DBConfig.mapping.keySet();
for (String tableName : tables) {
Class clazz = DBConfig.mapping.get(tableName);
if (!SqlUtil.tableExists(db, clazz)) {
SqlUtil.createTable(db, clazz);
}
}
}
@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < newVersion) {
if (oldVersion < 31) {
handleLowAriaUpdate(db);
} else if (oldVersion < 45) {
handle360AriaUpdate(db);
} else if (oldVersion < 51) {
handle365Update(db);
} else if (oldVersion < 53) {
handle366Update(db);
} else {
handleDbUpdate(db, null);
}
// 处理380版本TaskRecord 增加的记录类型判断
if (newVersion == 57) {
addTaskRecordType(db);
}
}
}
@Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion > newVersion) {
handleDbUpdate(db, null);
}
}
/**
* 获取数据库连接
*/
SQLiteDatabase getDb() {
SQLiteDatabase db;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
SQLiteDatabase.OpenParams params = new SQLiteDatabase.OpenParams.Builder().setOpenFlags(
SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READWRITE |
SQLiteDatabase.CREATE_IF_NECESSARY).build();
setOpenParams(params);
db = getWritableDatabase();
} else {
//SQLiteDatabase.openOrCreateDatabase()
File dbFile = mContext.getDatabasePath(DBConfig.DB_NAME);
if (!dbFile.exists()) {
db = getWritableDatabase();
} else {
// 触发一次SQLiteOpenHelper的流程,再使用NO_LOCALIZED_COLLATORS标志打开数据库
db = getReadableDatabase();
db.close();
db = SQLiteDatabase.openDatabase(dbFile.getPath(), null,
SQLiteDatabase.NO_LOCALIZED_COLLATORS | SQLiteDatabase.OPEN_READWRITE |
SQLiteDatabase.CREATE_IF_NECESSARY);
}
}
db.enableWriteAheadLogging();
return db;
}
@Override public SQLiteDatabase getWritableDatabase() {
if (!mainTmpDirSet) {
createDbCacheDir();
return super.getWritableDatabase();
}
return super.getWritableDatabase();
}
/**
* 用于修复 Too many open files 的问题
* https://github.com/AriaLyy/Aria/issues/664
*/
@Override
public SQLiteDatabase getReadableDatabase() {
if (!mainTmpDirSet) {
createDbCacheDir();
return super.getReadableDatabase();
}
return super.getReadableDatabase();
}
private void createDbCacheDir() {
String cacheDir = mContext.getCacheDir().getPath() + "/AriaDbCacheDir";
File cacheFile = new File(cacheDir);
if (!cacheFile.exists()){
boolean rs = cacheFile.mkdirs();
ALog.d(TAG, rs + "");
}
super.getReadableDatabase()
.execSQL("PRAGMA temp_store_directory = '" + cacheDir + "'");
mainTmpDirSet = true;
}
/**
* 处理数据库升级
*
* @param modifyColumns 需要修改的表字段的映射key为表名
* value{@code Map<String, String>}中的Map的key为老字段名称value为该老字段对应的新字段名称
*/
private void handleDbUpdate(SQLiteDatabase db, Map<String, Map<String, String>> modifyColumns) {
if (db == null) {
ALog.e("SqlHelper", "db 为 null");
return;
} else if (!db.isOpen()) {
ALog.e("SqlHelper", "db已关闭");
return;
}
try {
db.beginTransaction();
Set<String> tables = DBConfig.mapping.keySet();
for (String tableName : tables) {
Class<? extends DbEntity> clazz = DBConfig.mapping.get(tableName);
if (SqlUtil.tableExists(db, clazz)) {
// ----------- 1、获取旧表字段、新表字段
Cursor columnC =
db.rawQuery(String.format("PRAGMA table_info(%s)", tableName), null);
// 获取新表的所有字段名称
List<String> newTabColumns = SqlUtil.getColumns(clazz);
// 获取旧表的所有字段名称
List<String> oldTabColumns = new ArrayList<>();
while (columnC.moveToNext()) {
String columnName = columnC.getString(columnC.getColumnIndex("name"));
oldTabColumns.add(columnName);
}
columnC.close();
// ----------- 2、为防止字段增加失败的情况,先给旧表增加字段
List<String> newAddColum = getNewColumn(newTabColumns, oldTabColumns);
// 删除重命名的字段
Map<String, String> modifyMap = null;
if (modifyColumns != null) {
modifyMap = modifyColumns.get(tableName);
if (modifyMap != null) {
Iterator<String> it = newAddColum.iterator();
while (it.hasNext()) {
String s = it.next();
if (modifyMap.get(s) != null) {
it.remove();
}
}
}
}
// 给旧表增加字段,防止新增字段失败
if (newAddColum.size() > 0) {
String sql = "ALTER TABLE %s ADD COLUMN %s %s";
for (String nc : newAddColum) {
String temp =
String.format(sql, tableName, nc, SqlUtil.getColumnTypeByFieldName(clazz, nc));
ALog.d(TAG, "添加表字段的sql:" + temp);
db.execSQL(temp);
}
}
// ----------- 3、将旧表备份下,并创建新表
String alertSql = String.format("ALTER TABLE %s RENAME TO %s_temp", tableName, tableName);
db.execSQL(alertSql);
//创建新表
SqlUtil.createTable(db, clazz);
String sql = String.format("SELECT COUNT(*) FROM %s_temp", tableName);
Cursor cursor = db.rawQuery(sql, null);
cursor.moveToFirst();
long count = cursor.getLong(0);
cursor.close();
// ----------- 4、将旧表数据复制到新表
if (count > 0) {
// 旧表需要删除的字段,删除旧表有而新表没的字段
List<String> diffTab = getDiffColumn(newTabColumns, oldTabColumns);
StringBuilder params = new StringBuilder();
// 需要修改的列名映射表
//Map<String, String> modifyMap = null;
if (modifyColumns != null) {
modifyMap = modifyColumns.get(tableName);
}
for (String column : oldTabColumns) {
if (!diffTab.isEmpty() && diffTab.contains(column)
// 如果旧表字段有修改,忽略这个删除
&& !(modifyMap != null && modifyMap.containsKey(column))) {
continue;
}
params.append(column).append(",");
}
String oldParamStr = params.toString();
oldParamStr = oldParamStr.substring(0, oldParamStr.length() - 1);
String newParamStr = oldParamStr;
// 处理字段名称改变
if (modifyMap != null && !modifyMap.isEmpty()) {
Set<String> keys = modifyMap.keySet();
for (String key : keys) {
if (newParamStr.contains(key)) {
newParamStr = newParamStr.replace(key, modifyMap.get(key));
}
}
}
//恢复数据
String insertSql =
String.format("INSERT INTO %s (%s) SELECT %s FROM %s_temp", tableName, newParamStr,
oldParamStr, tableName);
ALog.d(TAG, "恢复数据的sql:" + insertSql);
db.execSQL(insertSql);
}
// ----------- 5、删除备份的表
SqlUtil.dropTable(db, tableName + "_temp");
} else {
SqlUtil.createTable(db, clazz);
}
}
db.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
} finally {
db.endTransaction();
}
}
/**
* 取新表差值需要删除的字段旧表有而新表没的字段
*
* @param newTab 新表字段
* @param oldTab 旧表字段
* @return 旧表有而新表没的字段
*/
private List<String> getDiffColumn(List<String> newTab, List<String> oldTab) {
List<String> temp = new ArrayList<>(oldTab); // 拷贝旧表字段
temp.removeAll(newTab);
return temp;
}
/**
* 获取新增字段
*
* @param newTab 新表字段
* @param oldTab 就表字段
* @return 新表有而旧表没的字段
*/
private List<String> getNewColumn(List<String> newTab, List<String> oldTab) {
List<String> temp = new ArrayList<>(newTab);
temp.removeAll(oldTab);
return temp;
}
/**
* 给TaskRecord 增加任务类型
*/
private void addTaskRecordType(SQLiteDatabase db) {
try {
SqlUtil.checkOrCreateTable(db, ThreadRecord.class);
SqlUtil.checkOrCreateTable(db, TaskRecord.class);
SqlUtil.checkOrCreateTable(db, UploadEntity.class);
SqlUtil.checkOrCreateTable(db, DownloadEntity.class);
db.beginTransaction();
/*
* 增加下载实体的类型
*/
String dSql = "SELECT downloadPath, url FROM DownloadEntity";
Cursor c = db.rawQuery(dSql, null);
while (c.moveToNext()) {
int type;
String filePath = c.getString(0);
String url = c.getString(1);
if (url.startsWith("ftp") || url.startsWith("sftp")) {
type = ITaskWrapper.D_FTP;
} else {
if (SqlUtil.tableExists(db, M3U8Entity.class)) {
Cursor m3u8c = db.rawQuery("SELECT isLive FROM M3U8Entity WHERE filePath=\""
+ SqlUtil.encodeStr(filePath)
+ "\"", null);
if (m3u8c.moveToNext()) {
String temp = m3u8c.getString(0);
type =
(TextUtils.isEmpty(temp) ? false : Boolean.valueOf(temp)) ? ITaskWrapper.M3U8_LIVE
: ITaskWrapper.M3U8_VOD;
} else {
type = ITaskWrapper.D_HTTP;
}
m3u8c.close();
} else {
type = ITaskWrapper.D_HTTP;
}
}
db.execSQL("UPDATE DownloadEntity SET taskType=? WHERE downloadPath=?",
new Object[] { type, filePath });
db.execSQL("UPDATE TaskRecord SET taskType=? WHERE filePath=?",
new Object[] { type, filePath });
db.execSQL("UPDATE ThreadRecord SET threadType=? WHERE taskKey=?",
new Object[] { type, filePath });
}
c.close();
/*
* 增加上传实体的类型
*/
String uSql = "SELECT filePath, url FROM UploadEntity";
c = db.rawQuery(uSql, null);
while (c.moveToNext()) {
int type;
String filePath = c.getString(c.getColumnIndex("filePath"));
String url = c.getString(c.getColumnIndex("url"));
if (url.startsWith("ftp") || url.startsWith("sftp")) {
type = ITaskWrapper.D_FTP;
} else {
type = ITaskWrapper.D_HTTP;
}
db.execSQL("UPDATE UploadEntity SET taskType=? WHERE filePath=?",
new Object[] { type, filePath });
db.execSQL("UPDATE TaskRecord SET taskType=? WHERE filePath=?",
new Object[] { type, filePath });
db.execSQL("UPDATE ThreadRecord SET threadType=? WHERE taskKey=?",
new Object[] { type, filePath });
}
c.close();
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
/**
* 删除重复的repeat数据
*/
private void delRepeatThreadRecord(SQLiteDatabase db) {
SqlUtil.checkOrCreateTable(db, ThreadRecord.class);
String repeatSql = "DELETE FROM ThreadRecord WHERE (rowid) "
+ "IN (SELECT rowid FROM ThreadRecord GROUP BY taskKey, threadId, endLocation HAVING COUNT(*) > 1) "
+ "AND rowid NOT IN (SELECT MIN(rowid) FROM ThreadRecord GROUP BY taskKey, threadId, endLocation HAVING COUNT(*)> 1)";
ALog.d(TAG, repeatSql);
db.execSQL(repeatSql);
}
/**
* 处理366版本以下的升级
*/
private void handle366Update(SQLiteDatabase db) {
Map<String, Map<String, String>> modifyMap = new HashMap<>();
// 处理ThreadRecord的key字段名修改
Map<String, String> threadRecordModify = new HashMap<>();
threadRecordModify.put("key", "taskKey");
modifyMap.put("ThreadRecord", threadRecordModify);
// 执行升级操作
handleDbUpdate(db, modifyMap);
delRepeatThreadRecord(db);
}
/**
* 处理365版本以下的升级
*/
private void handle365Update(SQLiteDatabase db) {
SqlUtil.checkOrCreateTable(db, ThreadRecord.class);
db.execSQL("UPDATE ThreadRecord SET threadId=0 WHERE threadId=-1");
Map<String, Map<String, String>> modifyMap = new HashMap<>();
// 处理ThreadRecord的key字段名修改
Map<String, String> threadRecordModify = new HashMap<>();
threadRecordModify.put("key", "taskKey");
modifyMap.put("ThreadRecord", threadRecordModify);
// 执行升级操作
handleDbUpdate(db, modifyMap);
delRepeatThreadRecord(db);
}
/**
* 处理3.6以下版本的数据库升级
*/
private void handle360AriaUpdate(SQLiteDatabase db) {
String[] taskTables =
new String[] { "UploadTaskEntity", "DownloadTaskEntity", "DownloadGroupTaskEntity" };
for (String taskTable : taskTables) {
if (SqlUtil.tableExists(db, taskTable)) {
SqlUtil.dropTable(db, taskTable);
}
}
Map<String, Map<String, String>> modifyMap = new HashMap<>();
// 处理DownloadEntity、DownloadGroupEntity的 groupName字段名的修改
Map<String, String> entityModify = new HashMap<>();
entityModify.put("groupName", "groupHash");
modifyMap.put("DownloadEntity", entityModify);
modifyMap.put("DownloadGroupEntity", entityModify);
// 处理TaskRecord的dGroupName字段名的修改
Map<String, String> taskRecordModify = new HashMap<>();
taskRecordModify.put("dGroupName", "dGroupHash");
modifyMap.put("TaskRecord", taskRecordModify);
// 处理ThreadRecord的key字段名修改
Map<String, String> threadRecordModify = new HashMap<>();
threadRecordModify.put("key", "taskKey");
modifyMap.put("ThreadRecord", threadRecordModify);
// 执行升级操作
handleDbUpdate(db, modifyMap);
delRepeatThreadRecord(db);
}
/**
* 处理低版本的数据库迁移主要是修改子表外键字段对应的值
*/
private void handleLowAriaUpdate(SQLiteDatabase db) {
String[] taskTables =
new String[] { "UploadTaskEntity", "DownloadTaskEntity", "DownloadGroupTaskEntity" };
for (String taskTable : taskTables) {
if (SqlUtil.tableExists(db, taskTable)) {
SqlUtil.dropTable(db, taskTable);
}
}
//删除所有主键为null和主键重复的数据
String[] tables = new String[] { "DownloadEntity", "DownloadGroupEntity" };
String[] keys = new String[] { "downloadPath", "groupName" };
int i = 0;
for (String tableName : tables) {
if (!SqlUtil.tableExists(db, tableName)) {
continue;
}
String pColumn = keys[i];
String nullSql =
String.format("DELETE FROM %s WHERE %s='' OR %s IS NULL", tableName, pColumn, pColumn);
ALog.d(TAG, nullSql);
db.execSQL(nullSql);
//删除所有主键重复的数据
String repeatSql =
String.format(
"DELETE FROM %s WHERE %s IN(SELECT %s FROM %s GROUP BY %s HAVING COUNT(%s) > 1)",
tableName, pColumn, pColumn, tableName, pColumn, pColumn);
ALog.d(TAG, repeatSql);
db.execSQL(repeatSql);
i++;
}
// 处理数据库版本小于3的字段改变
Map<String, Map<String, String>> modifyMap = new HashMap<>();
Map<String, String> dEntityModifyMap = new HashMap<>();
dEntityModifyMap.put("groupName", "groupHash");
dEntityModifyMap.put("downloadUrl", "url");
dEntityModifyMap.put("isDownloadComplete", "isComplete");
modifyMap.put("DownloadEntity", dEntityModifyMap);
Map<String, String> dGEntityModifyMap = new HashMap<>();
dGEntityModifyMap.put("groupName", "groupHash");
modifyMap.put("DownloadGroupEntity", dGEntityModifyMap);
handleDbUpdate(db, modifyMap);
}
}

@ -1,590 +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.orm;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.orm.annotation.Default;
import com.arialyy.aria.orm.annotation.Foreign;
import com.arialyy.aria.orm.annotation.Ignore;
import com.arialyy.aria.orm.annotation.Many;
import com.arialyy.aria.orm.annotation.NoNull;
import com.arialyy.aria.orm.annotation.One;
import com.arialyy.aria.orm.annotation.Primary;
import com.arialyy.aria.orm.annotation.Unique;
import com.arialyy.aria.orm.annotation.Wrapper;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Created by lyy on 2017/7/24.
* sql工具
*/
final class SqlUtil {
private static final String TAG = CommonUtil.getClassName("SqlUtil");
/**
* 检查表是否存在不存在则创建表
*/
static void checkOrCreateTable(SQLiteDatabase db, Class<? extends DbEntity> clazz) {
if (!tableExists(db, clazz)) {
createTable(db, clazz);
}
}
static void closeCursor(Cursor cursor) {
synchronized (AbsDelegate.class) {
if (cursor != null && !cursor.isClosed()) {
try {
cursor.close();
} catch (android.database.SQLException e) {
e.printStackTrace();
}
}
}
}
/**
* 查找表是否存在
*
* @param clazz 数据库实体
* @return true该数据库实体对应的表存在false不存在
*/
static boolean tableExists(SQLiteDatabase db, Class<? extends DbEntity> clazz) {
return tableExists(db, CommonUtil.getClassName(clazz));
}
/**
* 查找表是否存在
*
* @param tableName 表名
* @return true该数据库实体对应的表存在false不存在
*/
static boolean tableExists(SQLiteDatabase db, String tableName) {
db = checkDb(db);
Cursor cursor = null;
try {
String sql =
String.format("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='%s'",
tableName);
cursor = db.rawQuery(sql, null);
if (cursor != null && cursor.moveToNext()) {
int count = cursor.getInt(0);
if (count > 0) {
return true;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
closeCursor(cursor);
}
return false;
}
/**
* 检查list参数是否合法list只能是{@code List<String>}
*
* @return {@code true} 合法
*/
static boolean checkList(Field list) {
Class t = CommonUtil.getListParamType(list);
if (t == String.class) {
return true;
} else {
ALog.d(TAG, "map参数错误,支持List<String>的参数字段");
return false;
}
}
/**
* 检查map参数是否合法map只能是{@code Map<String, String>}
*
* @return {@code true} 合法
*/
static boolean checkMap(Field map) {
Class[] ts = CommonUtil.getMapParamType(map);
if (ts != null
&& ts[0] != null
&& ts[1] != null
&& ts[0] == String.class
&& ts[1] == String.class) {
return true;
} else {
ALog.d(TAG, "map参数错误,支持Map<String,String>的参数字段");
return false;
}
}
/**
* 删除指定的表
*/
static void dropTable(SQLiteDatabase db, String tableName) {
db = checkDb(db);
String deleteSQL = String.format("DROP TABLE IF EXISTS %s", tableName);
//db.beginTransaction();
db.execSQL(deleteSQL);
//db.setTransactionSuccessful();
//db.endTransaction();
}
/**
* 清空表数据
*/
static void clean(SQLiteDatabase db, Class<? extends DbEntity> clazz) {
db = checkDb(db);
String tableName = CommonUtil.getClassName(clazz);
if (tableExists(db, clazz)) {
String sql = "DELETE FROM " + tableName;
db.execSQL(sql);
}
}
/**
* 检查某个字段的值是否存在
*
* @param expression 字段和值"url=xxx"
* @return {@code true}该字段的对应的value已存在
*/
static boolean checkDataExist(SQLiteDatabase db, Class<? extends DbEntity> clazz,
String... expression) {
db = checkDb(db);
if (!CommonUtil.checkSqlExpression(expression)) {
return false;
}
String sql = String.format("SELECT rowid, * FROM %s WHERE %s ", CommonUtil.getClassName(clazz),
expression[0]);
sql = sql.replace("?", "%s");
Object[] params = new String[expression.length - 1];
for (int i = 0, len = params.length; i < len; i++) {
params[i] = String.format("'%s'", SqlUtil.encodeStr(expression[i + 1]));
}
sql = String.format(sql, params);
Cursor cursor = db.rawQuery(sql, null);
final boolean isExist = cursor.getCount() > 0;
closeCursor(cursor);
return isExist;
}
/**
* 通过class 获取该class的表字段
*
* @return 表字段列表
*/
static List<String> getColumns(Class<? extends DbEntity> clazz) {
List<String> columns = new ArrayList<>();
List<Field> fields = CommonUtil.getAllFields(clazz);
for (Field field : fields) {
field.setAccessible(true);
if (SqlUtil.isIgnore(field)) {
continue;
}
columns.add(field.getName());
}
return columns;
}
/**
* 检查数据库是否关闭已经关闭的话打开数据库
*
* @return 返回数据库
*/
static SQLiteDatabase checkDb(SQLiteDatabase db) {
if (db == null || !db.isOpen()) {
db = SqlHelper.getInstance().getDb();
}
return db;
}
/**
* 创建表
*
* @param clazz 数据库实体
*/
static void createTable(SQLiteDatabase db, Class<? extends DbEntity> clazz) {
db = checkDb(db);
List<Field> fields = CommonUtil.getAllFields(clazz);
if (fields != null && fields.size() > 0) {
//外键Map,在Sqlite3中foreign修饰的字段必须放在最后
final List<Field> foreignArray = new ArrayList<>();
StringBuilder sb = new StringBuilder();
sb.append("CREATE TABLE IF NOT EXISTS ")
.append(CommonUtil.getClassName(clazz))
.append(" (");
for (Field field : fields) {
field.setAccessible(true);
if (SqlUtil.isIgnore(field)) {
continue;
}
Class<?> type = field.getType();
String columnType = getColumnType(type);
if (columnType == null) {
continue;
}
sb.append(field.getName());
sb.append(" ").append(columnType);
if (SqlUtil.isPrimary(field)) {
Primary pk = field.getAnnotation(Primary.class);
sb.append(" PRIMARY KEY");
if (pk.autoincrement() && (type == int.class || type == Integer.class)) {
sb.append(" AUTOINCREMENT");
}
}
if (SqlUtil.isForeign(field)) {
foreignArray.add(field);
}
if (SqlUtil.isNoNull(field)) {
sb.append(" NOT NULL");
}
if (SqlUtil.isDefault(field)) {
Default d = field.getAnnotation(Default.class);
if (!TextUtils.isEmpty(d.value())) {
sb.append(" ERROR ").append("'").append(d.value()).append("'");
}
}
if (SqlUtil.isUnique(field)) {
sb.append(" UNIQUE");
}
sb.append(",");
}
for (Field field : foreignArray) {
Foreign foreign = field.getAnnotation(Foreign.class);
sb.append("FOREIGN KEY (")
.append(field.getName())
.append(") REFERENCES ")
.append(CommonUtil.getClassName(foreign.parent()))
.append("(")
.append(foreign.column())
.append(")");
ActionPolicy update = foreign.onUpdate();
ActionPolicy delete = foreign.onDelete();
if (update != ActionPolicy.NO_ACTION) {
sb.append(" ON UPDATE ").append(update.function);
}
if (delete != ActionPolicy.NO_ACTION) {
sb.append(" ON DELETE ").append(update.function);
}
sb.append(",");
}
String str = sb.toString();
str = str.substring(0, str.length() - 1) + ");";
ALog.d(TAG, "创建表的sql:" + str);
db.execSQL(str);
}
}
/**
* 根据字段名获取字段类型
*/
static String getColumnTypeByFieldName(Class tabClass, String fieldName) {
List<Field> fields = CommonUtil.getAllFields(tabClass);
for (Field field : fields) {
if (field.getName().equals(fieldName)) {
return getColumnType(field.getType());
}
}
return null;
}
/**
* 获取字段类型
*/
static String getColumnType(Class fieldtype) {
if (fieldtype == String.class || fieldtype.isEnum()) {
return "VARCHAR";
} else if (fieldtype == int.class || fieldtype == Integer.class) {
return "INTEGER";
} else if (fieldtype == float.class || fieldtype == Float.class) {
return "FLOAT";
} else if (fieldtype == double.class || fieldtype == Double.class) {
return "DOUBLE";
} else if (fieldtype == long.class || fieldtype == Long.class) {
return "BIGINT";
} else if (fieldtype == boolean.class || fieldtype == Boolean.class) {
return "BOOLEAN";
} else if (fieldtype == java.util.Date.class || fieldtype == java.sql.Date.class) {
return "DATA";
} else if (fieldtype == byte.class || fieldtype == Byte.class) {
return "BLOB";
} else if (fieldtype == Map.class || fieldtype == List.class) {
return "TEXT";
} else {
return null;
}
}
/**
* URL编码字符串
*
* @param str 原始字符串
* @return 编码后的字符串
*/
static String encodeStr(String str) {
str = str.replaceAll("\\+", "%2B");
return URLEncoder.encode(str);
}
/**
* 获取主键字段名
*/
static String getPrimaryName(Class<? extends DbEntity> clazz) {
List<Field> fields = CommonUtil.getAllFields(clazz);
String column;
if (fields != null && !fields.isEmpty()) {
for (Field field : fields) {
field.setAccessible(true);
if (isPrimary(field)) {
column = field.getName();
return column;
}
}
}
return null;
}
/**
* 获取类中所有不被忽略的字段
*/
static List<Field> getAllNotIgnoreField(Class clazz) {
List<Field> fields = CommonUtil.getAllFields(clazz);
List<Field> temp = new ArrayList<>();
if (fields != null && fields.size() > 0) {
for (Field f : fields) {
f.setAccessible(true);
if (!isIgnore(f)) {
temp.add(f);
}
}
return temp;
} else {
return null;
}
}
/**
* 列表数据转字符串
*
* @param field list反射字段
*/
static String list2Str(DbEntity dbEntity, Field field) throws IllegalAccessException {
List list = (List) field.get(dbEntity);
if (list == null || list.isEmpty()) return "";
StringBuilder sb = new StringBuilder();
for (Object aList : list) {
sb.append(aList).append("$$");
}
return sb.toString();
}
/**
* 字符串转列表
*
* @param str 数据库中的字段
* @return 如果str为null则返回null
*/
static List str2List(String str, Field field) {
if (TextUtils.isEmpty(str)) return null;
String[] datas = str.split("\\$\\$");
List list = new ArrayList();
Class clazz = CommonUtil.getListParamType(field);
if (clazz != null) {
String type = clazz.getName();
for (String data : datas) {
list.add(checkData(type, data));
}
}
return list;
}
/**
* 字符串转Map只支持
* <pre>
* {@code Map<String, String>}
* </pre>
*/
static Map<String, String> str2Map(String str) {
Map<String, String> map = new HashMap<>();
if (TextUtils.isEmpty(str)) {
return map;
}
boolean isDecode = false;
if (str.endsWith("_&_decode_&_")) {
isDecode = true;
str = str.substring(0, str.length() - 12);
}
String[] element = str.split(",");
for (String data : element) {
String[] s = data.split("\\$");
if (isDecode) {
map.put(CommonUtil.decryptBASE64(s[0]), CommonUtil.decryptBASE64(s[1]));
} else {
map.put(s[0], s[1]);
}
}
return map;
}
/**
* Map转字符串只支持
* <pre>
* {@code Map<String, String>}
* </pre>
*/
static String map2Str(Map<String, String> map) {
StringBuilder sb = new StringBuilder();
Set<String> keys = map.keySet();
for (String key : keys) {
sb.append(CommonUtil.encryptBASE64(key))
.append("$")
.append(CommonUtil.encryptBASE64(map.get(key)))
.append(",");
}
String str = sb.toString();
str = TextUtils.isEmpty(str) ? str : str.substring(0, str.length() - 1);
//3.3.10版本之前没有decode,需要加标志
if (map.size() != 0) {
str += "_&_decode_&_";
}
return str;
}
/**
* shadow$_klass_shadow$_monitor_{@link Ignore}rowID{@link Field#isSynthetic()}{@link
* Modifier#isFinal(int)}{@link Modifier#isStatic(int)}将被忽略
*
* @return true 忽略该字段
*/
static boolean isIgnore(Field field) {
// field.isSynthetic(), 使用as热启动App时,AS会自动给你的class添加change字段
Ignore ignore = field.getAnnotation(Ignore.class);
int modifiers = field.getModifiers();
String fieldName = field.getName();
return (ignore != null && ignore.value()) || fieldName.equals("rowID") || fieldName.equals(
AriaConfig.IGNORE_CLASS_KLASS) || fieldName.equals(AriaConfig.IGNORE_CLASS_MONITOR)
|| field.isSynthetic() || Modifier
.isStatic(modifiers) || Modifier.isFinal(modifiers);
}
/**
* 判断是否是Wrapper注解
*
* @return {@code true}
*/
static boolean isWrapper(Class<? extends AbsDbWrapper> clazz) {
Wrapper w = clazz.getAnnotation(Wrapper.class);
return w != null;
}
/**
* 判断是否一对多注解
*/
static boolean isMany(Field field) {
Many oneToMany = field.getAnnotation(Many.class);
return oneToMany != null;
}
/**
* 判断是否是一对一注解
*/
static boolean isOne(Field field) {
One oneToOne = field.getAnnotation(One.class);
return oneToOne != null;
}
/**
* 判断是否是主键约束
*
* @return {@code true}主键约束
*/
static boolean isPrimary(Field field) {
Primary pk = field.getAnnotation(Primary.class);
return pk != null;
}
/**
* 判断是否是外键约束
*
* @return {@code true}外键约束
*/
static boolean isForeign(Field field) {
Foreign fk = field.getAnnotation(Foreign.class);
return fk != null;
}
/**
* 判断是否是非空约束
*
* @return {@code true}为非空约束
*/
static boolean isNoNull(Field field) {
NoNull nn = field.getAnnotation(NoNull.class);
return nn != null;
}
/**
* 判断是否是default
*
* @return {@code true}为default
*/
static boolean isDefault(Field field) {
Default nn = field.getAnnotation(Default.class);
return nn != null;
}
/**
* 判断是否是Unique
*
* @return {@code true}为Unique
*/
static boolean isUnique(Field field) {
Unique nn = field.getAnnotation(Unique.class);
return nn != null;
}
private static Object checkData(String type, String data) {
if (type.equalsIgnoreCase("java.lang.String")) {
return data;
} else if (type.equalsIgnoreCase("int") || type.equals("java.lang.Integer")) {
return Integer.parseInt(data);
} else if (type.equalsIgnoreCase("double") || type.equals("java.lang.Double")) {
return Double.parseDouble(data);
} else if (type.equalsIgnoreCase("float") || type.equals("java.lang.Float")) {
return Float.parseFloat(data);
}
return null;
}
}

@ -1,30 +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.orm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by lyy on 2015/11/2.
* 默认数据
*/
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Default {
String value() default "";
}

@ -1,50 +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.orm.annotation;
import com.arialyy.aria.orm.ActionPolicy;
import com.arialyy.aria.orm.DbEntity;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by AriaL on 2017/7/4.
* 外键约束
*/
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Foreign {
/**
* 关联的表
*/
Class<? extends DbEntity> parent();
/**
* 父表对应的列名
*/
String column();
/**
* ON UPDATE 约束
*/
ActionPolicy onUpdate() default ActionPolicy.NO_ACTION;
/**
* ON DELETE 约束
*/
ActionPolicy onDelete() default ActionPolicy.NO_ACTION;
}

@ -1,30 +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.orm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by lyy on 2015/11/2.
* 忽略某个字段
*/
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Ignore {
boolean value() default true;
}

@ -1,44 +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.orm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by AriaL on 2017/7/4.
* 一对多
*/
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Many {
/**
* 父表对应的字段名
*/
String parentColumn();
/**
* 父表在子表对应的字段
*/
String entityColumn();
///**
// * 是否是一对一关系
// *
// * @return {@code true} 是,{@code false} 不是
// */
//boolean isOne2One() default false;
}

@ -1,30 +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.orm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by lyy on 2015/11/2.
* 非空字段
*/
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface NoNull {
boolean value() default true;
}

@ -1,29 +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.orm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by AriaL on 2017/7/4.
*
*/
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface One {
}

@ -1,35 +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.orm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by lyy on 2015/11/2.
* 表ID字段指定
*/
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Primary {
int value() default -1;
/**
* 字段需要int类型才可以自增
*/
boolean autoincrement() default false;
}

@ -1,30 +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.orm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by lyy on 2015/11/2.
* 设置表名如果不是使用该注解默认为类名
*/
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Table {
String tableName();
}

@ -1,29 +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.orm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by laoyuyu on 2018/5/8.
* 数据库 UNIQUE 约束
*/
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME)
public @interface Unique {
}

@ -1,29 +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.orm.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by laoyuyu on 2018/3/21.
* 关系包裹
*/
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME)
public @interface Wrapper {
}

@ -19,7 +19,7 @@ import android.os.Handler;
import com.arialyy.aria.core.TaskOptionParams; import com.arialyy.aria.core.TaskOptionParams;
import com.arialyy.aria.core.inf.IEventHandler; import com.arialyy.aria.core.inf.IEventHandler;
import com.arialyy.aria.core.inf.ITaskOption; import com.arialyy.aria.core.inf.ITaskOption;
import com.arialyy.aria.core.inf.ITaskUtil; import com.arialyy.aria.core.inf.ITaskAdapter;
import com.arialyy.aria.core.listener.IEventListener; import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.task.AbsTask; import com.arialyy.aria.core.task.AbsTask;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper; import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
@ -104,7 +104,7 @@ public class ComponentUtil {
* *
* @return 返回任务工具 * @return 返回任务工具
*/ */
public synchronized <T extends ITaskUtil> T buildUtil(AbsTaskWrapper wrapper, public synchronized <T extends ITaskAdapter> T buildUtil(AbsTaskWrapper wrapper,
IEventListener listener) { IEventListener listener) {
int requestType = wrapper.getRequestType(); int requestType = wrapper.getRequestType();
String className = null; String className = null;

@ -20,7 +20,7 @@ import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.ThreadRecord; import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.common.AbsEntity; import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.M3U8Entity; import com.arialyy.aria.core.common.M3U8Entity;
import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.orm.DbEntity;
import java.io.File; import java.io.File;

@ -1,3 +0,0 @@
com.arialyy.aria.core.listener.BaseDListener
com.arialyy.aria.core.listener.BaseUListener
com.arialyy.aria.core.listener.DownloadGroupListener

@ -32,7 +32,7 @@ import com.arialyy.annotations.M3U8;
import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.common.AbsEntity; import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.M3U8Entity; import com.arialyy.aria.core.common.M3U8Entity;
import com.arialyy.aria.core.download.m3u8.M3U8VodOption; import com.arialyy.aria.core.download.m3u8.M3U8VodOption;
import com.arialyy.aria.core.processor.IBandWidthUrlConverter; import com.arialyy.aria.core.processor.IBandWidthUrlConverter;
import com.arialyy.aria.core.processor.IKeyUrlConverter; import com.arialyy.aria.core.processor.IKeyUrlConverter;

@ -1,8 +1,6 @@
package com.arialyy.simple.core.download.m3u8; package com.arialyy.simple.core.download.m3u8;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.graphics.Canvas;
import android.graphics.Color;
import android.media.AudioManager; import android.media.AudioManager;
import android.media.MediaPlayer; import android.media.MediaPlayer;
import android.os.Build; import android.os.Build;
@ -15,7 +13,7 @@ import android.widget.SeekBar;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import androidx.lifecycle.ViewModelProviders; import androidx.lifecycle.ViewModelProviders;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.M3U8Entity; import com.arialyy.aria.core.common.M3U8Entity;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.frame.base.BaseFragment; import com.arialyy.frame.base.BaseFragment;
import com.arialyy.simple.R; import com.arialyy.simple.R;

Loading…
Cancel
Save