diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/HttpOption.java b/Aria/src/main/java/com/arialyy/aria/core/common/HttpOption.java index 34eef965..13c08a2f 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/HttpOption.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/HttpOption.java @@ -16,8 +16,8 @@ package com.arialyy.aria.core.common; import android.text.TextUtils; -import com.arialyy.aria.core.processor.IHttpFileLenAdapter; -import com.arialyy.aria.core.processor.IHttpFileNameAdapter; +import com.arialyy.aria.http.IHttpFileLenAdapter; +import com.arialyy.aria.http.IHttpFileNameAdapter; import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.FileUtils; import java.net.Proxy; diff --git a/Http/src/main/java/com/arialyy/aria/http/HttpComponent.kt b/Http/src/main/java/com/arialyy/aria/http/HttpComponent.kt index 9f49cd6c..9d393204 100644 --- a/Http/src/main/java/com/arialyy/aria/http/HttpComponent.kt +++ b/Http/src/main/java/com/arialyy/aria/http/HttpComponent.kt @@ -1,6 +1,9 @@ package com.arialyy.aria.http import android.content.Context +import com.arialyy.aria.core.event.Event +import com.arialyy.aria.core.event.EventMsgUtil +import com.arialyy.aria.core.event.ResumeAllEvent import com.arialyy.aria.core.inf.IComponentInit /** @@ -10,5 +13,12 @@ import com.arialyy.aria.core.inf.IComponentInit **/ class HttpComponent : IComponentInit { override fun init(context: Context) { + EventMsgUtil.getDefault().register(this) } + + @Event + fun resumeAll(resumeAllEvent: ResumeAllEvent) { + + } + } \ No newline at end of file diff --git a/Http/src/main/java/com/arialyy/aria/http/HttpComponentLoader.kt b/Http/src/main/java/com/arialyy/aria/http/HttpComponentLoader.kt index 1f122ff7..fc903afb 100644 --- a/Http/src/main/java/com/arialyy/aria/http/HttpComponentLoader.kt +++ b/Http/src/main/java/com/arialyy/aria/http/HttpComponentLoader.kt @@ -19,7 +19,6 @@ import com.arialyy.annotations.TaskEnum import com.arialyy.aria.core.DuaContext import com.arialyy.aria.core.inf.IBaseLoader import com.arialyy.aria.core.inf.IComponentLoader -import com.arialyy.aria.core.inf.IDownloader import com.arialyy.aria.http.download.HttpDownloader import com.arialyy.aria.http.upload.HttpULoader import kotlin.LazyThreadSafetyMode.SYNCHRONIZED @@ -41,17 +40,17 @@ class HttpComponentLoader : IComponentLoader { private lateinit var loader: IBaseLoader - override fun download(): T { + fun download(): HttpDownloader { loader = downloader - return downloader as T + return downloader + } + + override fun getTaskEnum(): TaskEnum { + return TaskEnum.DOWNLOAD } // override fun upload(): T { // loader = uploader // return uploader as T // } - - override fun getTaskEnum(): TaskEnum { - return loader.getTaskEnum() - } } \ No newline at end of file diff --git a/Http/src/main/java/com/arialyy/aria/http/HttpTaskOption.kt b/Http/src/main/java/com/arialyy/aria/http/HttpTaskOption.kt index 5540d1ec..b8342893 100644 --- a/Http/src/main/java/com/arialyy/aria/http/HttpTaskOption.kt +++ b/Http/src/main/java/com/arialyy/aria/http/HttpTaskOption.kt @@ -17,7 +17,6 @@ package com.arialyy.aria.http import com.arialyy.aria.core.common.TaskOption import com.arialyy.aria.core.task.ITaskInterceptor -import com.arialyy.aria.orm.entity.BlockRecord /** * @Author laoyuyu @@ -28,9 +27,9 @@ class HttpTaskOption : TaskOption() { var httpOption: HttpOption? = null var taskInterceptor = mutableListOf() - lateinit var taskOptionAdapter: IHttpTaskOptionAdapter + lateinit var taskOptionDelegate: IHttpTaskOptionDelegate - fun getOptionAdapter(clazz: Class): T { - return taskOptionAdapter as T + fun getOptionDelegate(clazz: Class): T { + return taskOptionDelegate as T } } \ No newline at end of file diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/processor/IHttpFileLenAdapter.java b/Http/src/main/java/com/arialyy/aria/http/IHttpFileLenAdapter.java similarity index 96% rename from PublicComponent/src/main/java/com/arialyy/aria/core/processor/IHttpFileLenAdapter.java rename to Http/src/main/java/com/arialyy/aria/http/IHttpFileLenAdapter.java index f7090a86..784d534b 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/processor/IHttpFileLenAdapter.java +++ b/Http/src/main/java/com/arialyy/aria/http/IHttpFileLenAdapter.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.arialyy.aria.core.processor; +package com.arialyy.aria.http; import com.arialyy.aria.core.inf.IEventHandler; import java.net.URLConnection; diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/processor/IHttpFileNameAdapter.java b/Http/src/main/java/com/arialyy/aria/http/IHttpFileNameAdapter.java similarity index 92% rename from PublicComponent/src/main/java/com/arialyy/aria/core/processor/IHttpFileNameAdapter.java rename to Http/src/main/java/com/arialyy/aria/http/IHttpFileNameAdapter.java index f6b40239..06f95c39 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/processor/IHttpFileNameAdapter.java +++ b/Http/src/main/java/com/arialyy/aria/http/IHttpFileNameAdapter.java @@ -13,9 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.arialyy.aria.core.processor; +package com.arialyy.aria.http; -import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.inf.IEventHandler; import java.net.URLConnection; diff --git a/Http/src/main/java/com/arialyy/aria/http/IHttpTaskOptionAdapter.kt b/Http/src/main/java/com/arialyy/aria/http/IHttpTaskOptionDelegate.kt similarity index 95% rename from Http/src/main/java/com/arialyy/aria/http/IHttpTaskOptionAdapter.kt rename to Http/src/main/java/com/arialyy/aria/http/IHttpTaskOptionDelegate.kt index b558afd7..ab635bfc 100644 --- a/Http/src/main/java/com/arialyy/aria/http/IHttpTaskOptionAdapter.kt +++ b/Http/src/main/java/com/arialyy/aria/http/IHttpTaskOptionDelegate.kt @@ -20,4 +20,4 @@ package com.arialyy.aria.http * @Description * @Date 8:03 PM 2023/3/6 **/ -interface IHttpTaskOptionAdapter \ No newline at end of file +interface IHttpTaskOptionDelegate \ No newline at end of file diff --git a/Http/src/main/java/com/arialyy/aria/http/download/HttpBlockThreadInterceptor.kt b/Http/src/main/java/com/arialyy/aria/http/download/HttpBlockThreadInterceptor.kt index 73ecf034..06fa3b14 100644 --- a/Http/src/main/java/com/arialyy/aria/http/download/HttpBlockThreadInterceptor.kt +++ b/Http/src/main/java/com/arialyy/aria/http/download/HttpBlockThreadInterceptor.kt @@ -33,12 +33,12 @@ import com.arialyy.aria.orm.entity.BlockRecord **/ class HttpBlockThreadInterceptor : ITaskInterceptor { private lateinit var blockManager: IBlockManager - private lateinit var taskOption: HttpDOptionAdapter + private lateinit var taskOption: HttpDOptionDelegate override suspend fun interceptor(chain: TaskChain): TaskResp { blockManager = chain.blockManager taskOption = chain.getTask().getTaskOption(HttpTaskOption::class.java) - .getOptionAdapter(HttpDOptionAdapter::class.java) + .getOptionDelegate(HttpDOptionDelegate::class.java) val unfinishedBlockList = taskOption.getUnfinishedBlockList() if (unfinishedBlockList.isEmpty()) { return TaskResp(TaskResp.CODE_INTERRUPT) @@ -55,7 +55,7 @@ class HttpBlockThreadInterceptor : ITaskInterceptor { val threadConfig = ThreadConfig(it, option, DuaContext.getDConfig().maxSpeed) threadTaskList.add( ThreadTask2( - adapter = if (option.getOptionAdapter(HttpDOptionAdapter::class.java).isChunkTask) HttpDCTTaskAdapter( + adapter = if (option.getOptionDelegate(HttpDOptionDelegate::class.java).isChunkTask) HttpDCTTaskAdapter( threadConfig ) else HttpDBTaskAdapter( threadConfig @@ -65,7 +65,7 @@ class HttpBlockThreadInterceptor : ITaskInterceptor { ) ) } - option.getOptionAdapter(HttpDOptionAdapter::class.java).threadList = threadTaskList + option.getOptionDelegate(HttpDOptionDelegate::class.java).threadList = threadTaskList blockManager.start() } } \ No newline at end of file diff --git a/Http/src/main/java/com/arialyy/aria/http/download/HttpDBTaskAdapter.kt b/Http/src/main/java/com/arialyy/aria/http/download/HttpDBTaskAdapter.kt index 2313deac..5c6d9e55 100644 --- a/Http/src/main/java/com/arialyy/aria/http/download/HttpDBTaskAdapter.kt +++ b/Http/src/main/java/com/arialyy/aria/http/download/HttpDBTaskAdapter.kt @@ -43,7 +43,7 @@ class HttpDBTaskAdapter(threadConfig: ThreadConfig) : AbsThreadTaskAdapter(threa val taskOption = getTaskOption() val option = taskOption.httpOption!! val conn = getRequest(option).getDConnection(taskOption.sourUrl!!, option) - if (!taskOption.getOptionAdapter(HttpDOptionAdapter::class.java).isSupportResume) { + if (!taskOption.getOptionDelegate(HttpDOptionDelegate::class.java).isSupportResume) { Timber.w("this task not support resume, url: %s", taskOption.sourUrl) } else { conn.setRequestProperty( diff --git a/Http/src/main/java/com/arialyy/aria/http/download/HttpDBlockInterceptor.kt b/Http/src/main/java/com/arialyy/aria/http/download/HttpDBlockInterceptor.kt index eb16a5a7..a69e8289 100644 --- a/Http/src/main/java/com/arialyy/aria/http/download/HttpDBlockInterceptor.kt +++ b/Http/src/main/java/com/arialyy/aria/http/download/HttpDBlockInterceptor.kt @@ -136,7 +136,7 @@ internal class HttpDBlockInterceptor : ITaskInterceptor { if (br.curProgress != blockF.length()) { br.curProgress = blockF.length() needUpdateBlockRecord.add(br) - taskOption.getOptionAdapter(HttpDOptionAdapter::class.java).putUnfinishedBlock(br) + taskOption.getOptionDelegate(HttpDOptionDelegate::class.java).putUnfinishedBlock(br) } // update task progress handler.obtainMessage(ITaskManager.STATE_UPDATE_PROGRESS, br.curProgress) diff --git a/Http/src/main/java/com/arialyy/aria/http/download/HttpDBlockManager.kt b/Http/src/main/java/com/arialyy/aria/http/download/HttpDBlockManager.kt index 67cd6fc4..6172bce8 100644 --- a/Http/src/main/java/com/arialyy/aria/http/download/HttpDBlockManager.kt +++ b/Http/src/main/java/com/arialyy/aria/http/download/HttpDBlockManager.kt @@ -27,7 +27,7 @@ import kotlinx.coroutines.launch **/ class HttpDBlockManager(task: ITask) : DBlockManager(task) { private val optionAdapter = - task.getTaskOption(HttpTaskOption::class.java).getOptionAdapter(HttpDOptionAdapter::class.java) + task.getTaskOption(HttpTaskOption::class.java).getOptionDelegate(HttpDOptionDelegate::class.java) override fun start() { optionAdapter.threadList.forEach { tt -> diff --git a/Http/src/main/java/com/arialyy/aria/http/download/HttpDHeaderInterceptor.kt b/Http/src/main/java/com/arialyy/aria/http/download/HttpDHeaderInterceptor.kt index 9435a2dd..e0dc141f 100644 --- a/Http/src/main/java/com/arialyy/aria/http/download/HttpDHeaderInterceptor.kt +++ b/Http/src/main/java/com/arialyy/aria/http/download/HttpDHeaderInterceptor.kt @@ -20,7 +20,7 @@ import android.net.Uri import android.os.Looper import android.os.Process import android.text.TextUtils -import com.arialyy.aria.core.processor.IHttpFileLenAdapter +import com.arialyy.aria.http.IHttpFileLenAdapter import com.arialyy.aria.core.task.ITask import com.arialyy.aria.core.task.ITaskInterceptor import com.arialyy.aria.core.task.TaskChain @@ -56,8 +56,8 @@ internal class HttpDHeaderInterceptor : ITaskInterceptor { ) } - private fun getOptionAdapter(): HttpDOptionAdapter { - return taskOption.getOptionAdapter(HttpDOptionAdapter::class.java) + private fun getOptionAdapter(): HttpDOptionDelegate { + return taskOption.getOptionDelegate(HttpDOptionDelegate::class.java) } override suspend fun interceptor(chain: TaskChain): TaskResp { diff --git a/Http/src/main/java/com/arialyy/aria/http/download/HttpDOptionAdapter.kt b/Http/src/main/java/com/arialyy/aria/http/download/HttpDOptionDelegate.kt similarity index 90% rename from Http/src/main/java/com/arialyy/aria/http/download/HttpDOptionAdapter.kt rename to Http/src/main/java/com/arialyy/aria/http/download/HttpDOptionDelegate.kt index e2df9861..3606bacf 100644 --- a/Http/src/main/java/com/arialyy/aria/http/download/HttpDOptionAdapter.kt +++ b/Http/src/main/java/com/arialyy/aria/http/download/HttpDOptionDelegate.kt @@ -15,9 +15,9 @@ */ package com.arialyy.aria.http.download -import com.arialyy.aria.core.processor.IHttpFileLenAdapter +import com.arialyy.aria.http.IHttpFileLenAdapter import com.arialyy.aria.core.task.IThreadTask -import com.arialyy.aria.http.IHttpTaskOptionAdapter +import com.arialyy.aria.http.IHttpTaskOptionDelegate import com.arialyy.aria.orm.entity.BlockRecord /** @@ -25,7 +25,7 @@ import com.arialyy.aria.orm.entity.BlockRecord * @Description * @Date 2:03 PM 2023/3/6 **/ -class HttpDOptionAdapter : IHttpTaskOptionAdapter { +class HttpDOptionDelegate : IHttpTaskOptionDelegate { var fileSizeAdapter: IHttpFileLenAdapter? = null var isChunkTask = false diff --git a/Http/src/main/java/com/arialyy/aria/http/download/HttpDStartController.kt b/Http/src/main/java/com/arialyy/aria/http/download/HttpDStartController.kt index 4125588b..79b3d7cc 100644 --- a/Http/src/main/java/com/arialyy/aria/http/download/HttpDStartController.kt +++ b/Http/src/main/java/com/arialyy/aria/http/download/HttpDStartController.kt @@ -21,7 +21,7 @@ import com.arialyy.aria.core.command.AddCmd import com.arialyy.aria.core.command.CancelCmd import com.arialyy.aria.core.command.StartCmd import com.arialyy.aria.core.command.StopCmd -import com.arialyy.aria.core.processor.IHttpFileLenAdapter +import com.arialyy.aria.http.IHttpFileLenAdapter import com.arialyy.aria.core.task.SingleDownloadTask import com.arialyy.aria.core.task.ITaskInterceptor import com.arialyy.aria.core.task.TaskCachePool @@ -37,11 +37,11 @@ import java.net.HttpURLConnection * @Date 12:38 PM 2023/1/22 **/ class HttpDStartController(target: Any, val url: String) : HttpBaseStartController(target) { - private val taskOptionAdapter = HttpDOptionAdapter() + private val taskOptionAdapter = HttpDOptionDelegate() init { httpTaskOption.sourUrl = url - httpTaskOption.taskOptionAdapter = taskOptionAdapter + httpTaskOption.taskOptionDelegate = taskOptionAdapter } override fun setTaskInterceptor(taskInterceptor: ITaskInterceptor): HttpDStartController { diff --git a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGroupAdapter.kt b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGAdapter.kt similarity index 94% rename from HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGroupAdapter.kt rename to HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGAdapter.kt index f4d428dc..b69915a2 100644 --- a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGroupAdapter.kt +++ b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGAdapter.kt @@ -33,16 +33,16 @@ import timber.log.Timber * @Description * @Date 21:58 2023/2/20 **/ -internal class HttpDGroupAdapter : AbsTaskAdapter() { +internal class HttpDGAdapter : AbsTaskAdapter() { private val taskManager by lazy { - val manager = HttpDGTaskManager(getTask() as HttpDGroupTask) + val manager = HttpDGTaskManager(getTask() as HttpDGTask) ThreadTaskManager2.putTaskManager(getTask().taskId, manager) manager } init { getTask().getTaskOption(HttpTaskOption::class.java).eventListener = - HttpDGEventListener(getTask() as HttpDGroupTask) + HttpDGEventListener(getTask() as HttpDGTask) } override fun getBlockManager(): IBlockManager { diff --git a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGCheckInterceptor.kt b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGCheckInterceptor.kt index f14ef5fb..9e91a8a9 100644 --- a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGCheckInterceptor.kt +++ b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGCheckInterceptor.kt @@ -24,7 +24,7 @@ import com.arialyy.aria.core.task.TaskResp import com.arialyy.aria.http.HttpTaskOption import com.arialyy.aria.orm.entity.DEntity import com.arialyy.aria.orm.entity.DGEntity -import com.arialyy.aria.util.CheckUtil +import com.arialyy.aria.util.DuaUtil import com.arialyy.aria.util.FileUri import com.arialyy.aria.util.FileUtils import timber.log.Timber @@ -40,7 +40,7 @@ import java.io.File internal class HttpDGCheckInterceptor : ITaskInterceptor { private lateinit var task: ITask - private lateinit var optionAdapter: HttpDGOptionAdapter + private lateinit var optionAdapter: HttpDGOptionDelegate private lateinit var taskOption: HttpTaskOption private val dgDao by lazy { DuaContext.getServiceManager().getDbService().getDuaDb().getDGEntityDao() @@ -49,7 +49,7 @@ internal class HttpDGCheckInterceptor : ITaskInterceptor { override suspend fun interceptor(chain: TaskChain): TaskResp { task = chain.getTask() taskOption = task.getTaskOption(HttpTaskOption::class.java) - optionAdapter = taskOption.getOptionAdapter(HttpDGOptionAdapter::class.java) + optionAdapter = taskOption.getOptionDelegate(HttpDGOptionDelegate::class.java) if (checkParams(taskOption.savePathDir)) { return TaskResp(TaskResp.CODE_INTERRUPT) @@ -140,7 +140,7 @@ internal class HttpDGCheckInterceptor : ITaskInterceptor { } optionAdapter.subUrlList.forEach { - if (!CheckUtil.checkUrl(it)) { + if (!DuaUtil.checkUrl(it)) { Timber.e("invalid url: $it") return false } diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/command/DGSubStartCmd.java b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGComponent.kt similarity index 56% rename from PublicComponent/src/main/java/com/arialyy/aria/core/command/DGSubStartCmd.java rename to HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGComponent.kt index bb16de55..47e5cc11 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/command/DGSubStartCmd.java +++ b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGComponent.kt @@ -13,22 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.arialyy.aria.core.command; +package com.arialyy.dua.group -import com.arialyy.aria.core.download.AbsGroupTaskWrapper; +import android.content.Context +import com.arialyy.aria.core.event.Event +import com.arialyy.aria.core.event.EventMsgUtil +import com.arialyy.aria.core.event.ResumeAllEvent +import com.arialyy.aria.core.inf.IComponentInit /** - * Created by AriaL on 2017/6/29. - * 任务组开始命令,该命令负责处理任务组子任务的开始\恢复等工作 - */ -final class DGSubStartCmd extends AbsGroupCmd { - DGSubStartCmd(T wrapper) { - super(wrapper); + * @Author laoyuyu + * @Description + * @Date 21:51 2023/2/20 + **/ +class HttpDGComponent : IComponentInit { + override fun init(context: Context) { + EventMsgUtil.getDefault().register(this) } - @Override public void executeCmd() { - if (checkTask()) { - tempTask.startSubTask(childUrl); - } + @Event + fun resumeAll(resumeAllEvent: ResumeAllEvent) { } -} +} \ No newline at end of file diff --git a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGComponentLoader.kt b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGComponentLoader.kt index 7cc1283a..1016f3d1 100644 --- a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGComponentLoader.kt +++ b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGComponentLoader.kt @@ -18,20 +18,19 @@ package com.arialyy.dua.group import com.arialyy.annotations.TaskEnum import com.arialyy.aria.core.DuaContext import com.arialyy.aria.core.inf.IComponentLoader -import com.arialyy.aria.core.inf.IDownloader /** * @Author laoyuyu * @Description * @Date 7:51 AM 2023/3/6 **/ -class HttpDGComponentLoader : IComponentLoader { +internal class HttpDGComponentLoader : IComponentLoader { private val downloader by lazy { HttpDGLoader(DuaContext.getLifeManager().getTargetByLoader(this)!!) } - override fun download(): T { - return downloader as T + fun download(): HttpDGLoader { + return downloader } override fun getTaskEnum(): TaskEnum { diff --git a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGEventListener.kt b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGEventListener.kt index 2b21ffff..79736816 100644 --- a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGEventListener.kt +++ b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGEventListener.kt @@ -15,19 +15,33 @@ */ package com.arialyy.dua.group +import com.arialyy.aria.core.DuaContext +import com.arialyy.aria.core.inf.IEntity import com.arialyy.aria.core.listener.AbsEventListener +import com.arialyy.aria.core.listener.ISchedulers +import com.arialyy.aria.core.task.TaskCachePool +import com.arialyy.aria.orm.entity.DEntity +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch /** * @Author laoyuyu * @Description * @Date 9:15 PM 2023/3/6 **/ -internal class HttpDGEventListener(task: HttpDGroupTask) : AbsEventListener(task) { +internal class HttpDGEventListener(task: HttpDGTask) : AbsEventListener(task) { override fun onComplete() { - TODO("Not yet implemented") + handleSpeed(0) + sendInState2Target(ISchedulers.COMPLETE) + saveData(IEntity.STATE_COMPLETE, task.taskState.fileSize) } override fun handleCancel() { - TODO("Not yet implemented") + DuaContext.duaScope.launch(Dispatchers.IO) { + val entity = TaskCachePool.getEntity(taskId = task.taskId) + val db = DuaContext.getServiceManager().getDbService().getDuaDb() + db.getRecordDao().deleteTaskRecord(task.taskState.taskRecord) + db.getDEntityDao().delete(entity as DEntity) + } } } \ No newline at end of file diff --git a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpGroupComponent.kt b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGListener.kt similarity index 78% rename from HttpGroup/src/main/java/com/arialyy/dua/group/HttpGroupComponent.kt rename to HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGListener.kt index 7280540f..02751c82 100644 --- a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpGroupComponent.kt +++ b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGListener.kt @@ -15,16 +15,11 @@ */ package com.arialyy.dua.group -import android.content.Context -import com.arialyy.aria.core.inf.IComponentInit +import com.arialyy.aria.core.listener.ITaskStatusListener /** * @Author laoyuyu * @Description - * @Date 21:51 2023/2/20 + * @Date 7:26 PM 2023/3/21 **/ -class HttpGroupComponent : IComponentInit { - override fun init(context: Context) { - - } -} \ No newline at end of file +class HttpDGListener : ITaskStatusListener \ No newline at end of file diff --git a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGLoader.kt b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGLoader.kt index d9a7e4c0..12665862 100644 --- a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGLoader.kt +++ b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGLoader.kt @@ -18,13 +18,14 @@ package com.arialyy.dua.group import android.net.Uri import com.arialyy.annotations.TaskEnum import com.arialyy.aria.core.inf.IDownloader +import com.arialyy.aria.http.download.HttpDStopController /** * @Author laoyuyu * @Description * @Date 7:53 AM 2023/3/6 **/ -class HttpDGLoader(val target: Any) : IDownloader { +class HttpDGLoader(private val target: Any) : IDownloader { override fun getTaskEnum(): TaskEnum { return TaskEnum.DOWNLOAD_GROUP } @@ -36,4 +37,8 @@ class HttpDGLoader(val target: Any) : IDownloader { fun load(savePath: Uri): HttpDGStartController { return HttpDGStartController(target, savePath) } + + fun load(taskId: Int): HttpDStopController { + return HttpDStopController(taskId) + } } \ No newline at end of file diff --git a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGOptionAdapter.kt b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGOptionDelegate.kt similarity index 88% rename from HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGOptionAdapter.kt rename to HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGOptionDelegate.kt index d4bf25a9..80b7ba78 100644 --- a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGOptionAdapter.kt +++ b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGOptionDelegate.kt @@ -15,14 +15,14 @@ */ package com.arialyy.dua.group -import com.arialyy.aria.http.IHttpTaskOptionAdapter +import com.arialyy.aria.http.IHttpTaskOptionDelegate /** * @Author laoyuyu * @Description * @Date 8:14 PM 2023/3/6 **/ -internal class HttpDGOptionAdapter : IHttpTaskOptionAdapter { +internal class HttpDGOptionDelegate : IHttpTaskOptionDelegate { val subUrlList = mutableSetOf() val subNameList = mutableListOf() diff --git a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGStartController.kt b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGStartController.kt index bc6bc61b..0c341255 100644 --- a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGStartController.kt +++ b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGStartController.kt @@ -16,7 +16,11 @@ package com.arialyy.dua.group import android.net.Uri +import com.arialyy.aria.core.DuaContext +import com.arialyy.aria.core.command.AddCmd +import com.arialyy.aria.core.command.CancelCmd import com.arialyy.aria.core.command.StartCmd +import com.arialyy.aria.core.command.StopCmd import com.arialyy.aria.core.task.ITaskInterceptor import com.arialyy.aria.core.task.TaskCachePool import com.arialyy.aria.http.HttpBaseStartController @@ -30,12 +34,13 @@ import timber.log.Timber * @Description * @Date 7:47 PM 2023/3/6 **/ -class HttpDGStartController(target: Any, val savePath: Uri) : HttpBaseStartController(target) { +class HttpDGStartController(target: Any, private val savePath: Uri) : + HttpBaseStartController(target) { - private val optionAdapter = HttpDGOptionAdapter() + private val optionAdapter = HttpDGOptionDelegate() init { - httpTaskOption.taskOptionAdapter = optionAdapter + httpTaskOption.taskOptionDelegate = optionAdapter httpTaskOption.savePathDir = savePath } @@ -51,6 +56,14 @@ class HttpDGStartController(target: Any, val savePath: Uri) : HttpBaseStartContr return super.setHttpOption(httpOption) as HttpDGStartController } + /** + * set download listener + */ + fun setListener(listener: HttpDGListener): HttpDGStartController { + DuaContext.getLifeManager().addCustomListener(target, listener) + return this + } + /** * Number of subtasks executed simultaneously * @param num max 16 @@ -84,20 +97,33 @@ class HttpDGStartController(target: Any, val savePath: Uri) : HttpBaseStartContr return this } - private fun getTask(createNewTask: Boolean = true): HttpDGroupTask { + private fun getTask(createNewTask: Boolean = true): HttpDGTask? { if (HttpUtil.checkHttpDParams(httpTaskOption)) { throw IllegalArgumentException("invalid params") } val temp = TaskCachePool.getTaskByKey(savePath.toString()) if (temp != null) { - return temp as HttpDGroupTask + return temp as HttpDGTask + } + if (!createNewTask) { + return null } - val task = HttpDGroupTask(httpTaskOption) - task.adapter = HttpDGroupAdapter() + val task = HttpDGTask(httpTaskOption) + task.adapter = HttpDGAdapter() TaskCachePool.putTask(task) return task } + fun add(): Int { + if (!FileUtils.uriEffective(savePath)) { + Timber.e("invalid savePath: $savePath") + return -1 + } + val task = getTask() + val resp = AddCmd(task).executeCmd() + return if (resp.isInterrupt()) -1 else task?.taskId ?: -1 + } + /** * Start task * @return taskId @@ -110,6 +136,28 @@ class HttpDGStartController(target: Any, val savePath: Uri) : HttpBaseStartContr val task = getTask() val resp = StartCmd(task).executeCmd() - return if (resp.isInterrupt()) -1 else task.taskId + return if (resp.isInterrupt()) -1 else task?.taskId ?: -1 + } + + fun resume(): Int { + return start() + } + + fun cancel() { + val task = getTask(true) + if (task == null) { + Timber.e("not found task, savePath: $savePath") + return + } + CancelCmd(task).executeCmd() + } + + fun stop() { + val task = getTask(false) + if (task == null) { + Timber.e("task not running, savePath: $savePath") + return + } + StopCmd(task).executeCmd() } } \ No newline at end of file diff --git a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGSubTaskInterceptor.kt b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGSubTaskInterceptor.kt index 02975486..2f8fc708 100644 --- a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGSubTaskInterceptor.kt +++ b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGSubTaskInterceptor.kt @@ -69,17 +69,17 @@ internal class HttpDGSubTaskInterceptor : ITaskInterceptor { tp.sourUrl = it.sourceUrl tp.savePathDir = taskOption.savePathDir tp.threadNum = 1 - tp.eventListener = HttpSubListener() val subTask = SingleDownloadTask(tp) val subAdapter = HttpDTaskAdapter(true) subAdapter.setBlockManager(HttpSubBlockManager(subTask, chain.blockManager.handler)) subTask.adapter = subAdapter if (it.isComplete && checkTaskIsComplete(it)) { - (chain.getTask() as HttpDGroupTask).addIncompleteTaskList(subTask) Timber.d("task already complete, sourUrl: ${it.sourceUrl}") + chain.blockManager.handler.obtainMessage(ITaskManager.SUB_STATE_COMPLETE, subTask) + } else { + (chain.getTask() as HttpDGTask).addIncompleteTaskList(subTask) } - (chain.getTask() as HttpDGroupTask).addSubTask(subTask) + (chain.getTask() as HttpDGTask).addSubTask(subTask) } } - } \ No newline at end of file diff --git a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGroupTask.java b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGTask.java similarity index 90% rename from HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGroupTask.java rename to HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGTask.java index ba41ba80..c7850b93 100644 --- a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGroupTask.java +++ b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGTask.java @@ -28,18 +28,18 @@ import java.util.Objects; * Created by AriaL on 2017/6/27. * 任务组任务 */ -public class HttpDGroupTask extends AbsTask { +public class HttpDGTask extends AbsTask { private final List incompleteTaskList = new ArrayList<>(); private final List subTaskList = new ArrayList<>(); - public HttpDGroupTask(ITaskOption taskOption) { + public HttpDGTask(ITaskOption taskOption) { super(taskOption); } - public HttpDGOptionAdapter getDGOptionAdapter() { - return getTaskOption(HttpTaskOption.class).getOptionAdapter(HttpDGOptionAdapter.class); + public HttpDGOptionDelegate getDGOptionAdapter() { + return getTaskOption(HttpTaskOption.class).getOptionDelegate(HttpDGOptionDelegate.class); } void setIncompleteTaskList(List list) { diff --git a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGTaskManager.kt b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGTaskManager.kt index 7beb7f74..26cf46d8 100644 --- a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGTaskManager.kt +++ b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGTaskManager.kt @@ -19,23 +19,28 @@ import android.os.Handler import android.os.Looper import com.arialyy.aria.core.inf.IBlockManager import com.arialyy.aria.core.inf.ITaskManager +import com.arialyy.aria.core.inf.TaskSchedulerType import com.arialyy.aria.core.listener.IEventListener import com.arialyy.aria.http.HttpTaskOption import com.arialyy.aria.http.download.HttpDTaskAdapter +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.MainScope import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.cancel +import kotlinx.coroutines.isActive import kotlinx.coroutines.launch +import timber.log.Timber import java.util.concurrent.LinkedBlockingQueue import java.util.concurrent.ThreadPoolExecutor import java.util.concurrent.TimeUnit.MILLISECONDS +import java.util.concurrent.atomic.AtomicInteger /** * @Author laoyuyu * @Description * @Date 7:43 PM 2023/3/7 **/ -internal class HttpDGTaskManager(val task: HttpDGroupTask) : ITaskManager, IBlockManager { +internal class HttpDGTaskManager(private val task: HttpDGTask) : ITaskManager, IBlockManager { private lateinit var looper: Looper private lateinit var handler: Handler private val subTaskNum = task.dgOptionAdapter.subTaskNum @@ -46,20 +51,50 @@ internal class HttpDGTaskManager(val task: HttpDGroupTask) : ITaskManager, IBloc ) private val dispatcher = threadPool.asCoroutineDispatcher() private val scope = MainScope() + private var progress = 0L + private var lastUpdateTime = System.currentTimeMillis() private val eventListener: IEventListener = task.getTaskOption(HttpTaskOption::class.java).eventListener + private val canceledNum = AtomicInteger(0) // 已经取消的线程的数 + private val stoppedNum = AtomicInteger(0) // 已经停止的线程数 + private val failedNum = AtomicInteger(0) // 失败的线程数 + private val completedNum = AtomicInteger(0) // 完成的线程数 private val callback = Handler.Callback { msg -> when (msg.what) { ITaskManager.SUB_STATE_STOP -> { + stoppedNum.getAndDecrement() + if (isStopped()) { + Timber.d("isStopped") + eventListener.onStop(progress) + quitLooper() + } } ITaskManager.SUB_STATE_CANCEL -> { + canceledNum.getAndDecrement() + if (isCanceled()) { + Timber.d("isCanceled") + eventListener.onCancel() + quitLooper() + } } ITaskManager.SUB_STATE_FAIL -> { + failedNum.getAndDecrement() } ITaskManager.SUB_STATE_COMPLETE -> { + completedNum.getAndDecrement() + if (isCompleted()) { + Timber.d("isCompleted") + eventListener.onComplete() + } } ITaskManager.SUB_STATE_RUNNING -> { + val len = msg.obj as Long + progress += len + task.taskState.curProgress = progress + if (System.currentTimeMillis() - lastUpdateTime > 1000) { + eventListener.onProgress(progress) + } } } false @@ -90,39 +125,49 @@ internal class HttpDGTaskManager(val task: HttpDGroupTask) : ITaskManager, IBloc } override fun stop() { + scope.launch(Dispatchers.IO) { + task.subTaskList.forEach { + it.stop(TaskSchedulerType.TYPE_DEFAULT) + } + } } override fun cancel() { - + scope.launch(Dispatchers.IO) { + task.subTaskList.forEach { + it.cancel(TaskSchedulerType.TYPE_DEFAULT) + } + task.subTaskList.clear() + } } override fun isCompleted(): Boolean { - TODO("Not yet implemented") + return completedNum.get() == task.subTaskList.size } override fun getCurrentProgress(): Long { - TODO("Not yet implemented") + return task.currentProgress } override fun isStopped(): Boolean { - TODO("Not yet implemented") + return stoppedNum.get() + canceledNum.get() + failedNum.get() + completedNum.get() == task.subTaskList.size } override fun isCanceled(): Boolean { - TODO("Not yet implemented") + return canceledNum.get() == task.subTaskList.size } override fun isRunning(): Boolean { - TODO("Not yet implemented") + return scope.isActive } override fun setBlockNum(blockNum: Int) { - TODO("Not yet implemented") + Timber.e("Group tasks do not support setting threads") } override fun getHandler(): Handler = handler override fun hasFailedTask(): Boolean { - TODO("Not yet implemented") + return failedNum.get() != 0 } } \ No newline at end of file diff --git a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpSubBlockManager.kt b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpSubBlockManager.kt index 1126075a..7b013d53 100644 --- a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpSubBlockManager.kt +++ b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpSubBlockManager.kt @@ -25,7 +25,7 @@ import com.arialyy.aria.core.task.TaskCachePool.removeTask import com.arialyy.aria.core.task.TaskCachePool.updateState import com.arialyy.aria.core.task.TaskState import com.arialyy.aria.http.HttpTaskOption -import com.arialyy.aria.http.download.HttpDOptionAdapter +import com.arialyy.aria.http.download.HttpDOptionDelegate import com.arialyy.aria.util.BlockUtil import timber.log.Timber @@ -76,6 +76,7 @@ internal class HttpSubBlockManager(private val task: ITask, private val groupHan task.taskState.speed = 0 saveData(IEntity.STATE_COMPLETE) } + quitLooper() } ITaskManager.STATE_RUNNING -> { updateProgress(msg.obj as Long) @@ -126,7 +127,7 @@ internal class HttpSubBlockManager(private val task: ITask, private val groupHan handler = Handler(looper, callback) // Synchronized sequential execution of all block task.getTaskOption(HttpTaskOption::class.java) - .getOptionAdapter(HttpDOptionAdapter::class.java).threadList.forEach { tt -> + .getOptionDelegate(HttpDOptionDelegate::class.java).threadList.forEach { tt -> if (isBreak) { Timber.d("task stopped") return diff --git a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpSubListener.kt b/HttpGroup/src/main/java/com/arialyy/dua/group/HttpSubListener.kt deleted file mode 100644 index 8ff1c543..00000000 --- a/HttpGroup/src/main/java/com/arialyy/dua/group/HttpSubListener.kt +++ /dev/null @@ -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.dua.group - -import com.arialyy.aria.core.listener.IEventListener -import com.arialyy.aria.exception.AriaException - -/** - * @Author laoyuyu - * @Description - * @Date 10:13 2023/3/12 - **/ -internal class HttpSubListener : IEventListener { - override fun onPre() { - TODO("Not yet implemented") - } - - override fun onStart(startLocation: Long) { - TODO("Not yet implemented") - } - - override fun onResume(resumeLocation: Long) { - TODO("Not yet implemented") - } - - override fun onProgress(currentLocation: Long) { - TODO("Not yet implemented") - } - - override fun onStop(stopLocation: Long) { - TODO("Not yet implemented") - } - - override fun onComplete() { - TODO("Not yet implemented") - } - - override fun onCancel() { - TODO("Not yet implemented") - } - - override fun onFail(needRetry: Boolean, e: AriaException?) { - TODO("Not yet implemented") - } -} \ No newline at end of file diff --git a/HttpGroup/src/main/resources/META-INF/services/com.arialyy.aria.core.inf.IComponentInit b/HttpGroup/src/main/resources/META-INF/services/com.arialyy.aria.core.inf.IComponentInit index 510f8e0a..43eb4595 100644 --- a/HttpGroup/src/main/resources/META-INF/services/com.arialyy.aria.core.inf.IComponentInit +++ b/HttpGroup/src/main/resources/META-INF/services/com.arialyy.aria.core.inf.IComponentInit @@ -1 +1 @@ -com.arialyy.dua.group.HttpGroupComponent \ No newline at end of file +com.arialyy.dua.group.HttpDGComponent \ No newline at end of file diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/command/AbsGroupCmd.java b/PublicComponent/src/main/java/com/arialyy/aria/core/command/AbsGroupCmd.java deleted file mode 100644 index dc97c141..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/command/AbsGroupCmd.java +++ /dev/null @@ -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.command; - -import com.arialyy.aria.core.download.AbsGroupTaskWrapper; -import com.arialyy.aria.core.download.DGTaskWrapper; -import com.arialyy.aria.core.queue.DGroupTaskQueue; -import com.arialyy.aria.core.task.AbsGroupTask; -import com.arialyy.aria.core.task.AbsTask; -import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CommonUtil; - -/** - * Created by AriaL on 2017/6/29. - * 任务组命令 - */ -public abstract class AbsGroupCmd extends AbsCmd { - /** - * 需要控制的子任务url - */ - String childUrl; - - AbsGroupTask tempTask; - - AbsGroupCmd(T entity) { - mTaskWrapper = entity; - TAG = CommonUtil.getClassName(this); - if (entity instanceof DGTaskWrapper) { - mQueue = DGroupTaskQueue.getInstance(); - isDownloadCmd = true; - } - } - - /** - * 创建任务 - * - * @return 创建的任务 - */ - AbsTask createTask() { - tempTask = (AbsGroupTask) mQueue.createTask(mTaskWrapper); - return tempTask; - } - - boolean checkTask() { - tempTask = (AbsGroupTask) mQueue.getTask(mTaskWrapper.getEntity().getKey()); - if (tempTask == null) { - createTask(); - if (tempTask.isComplete()) { - ALog.i(TAG, "任务已完成"); - return false; - } - } - return true; - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/command/CmdHelper.java b/PublicComponent/src/main/java/com/arialyy/aria/core/command/CmdHelper.java deleted file mode 100644 index d1ca8740..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/command/CmdHelper.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.AbsGroupTaskWrapper; -import com.arialyy.aria.core.task.ITask; -import com.arialyy.aria.core.wrapper.AbsTaskWrapper; - -public class CmdHelper { - /** - * 创建任务命令 - * - * @param taskType {@link ITask#SINGLE_DOWNLOAD}、{@link ITask#HTTP_GROUP}、{@link ITask#UPLOAD} - */ - public static AbsNormalCmd createNormalCmd(T entity, int cmd, - int taskType) { - return NormalCmdFactory.getInstance().createCmd(entity, cmd, taskType); - } - - /** - * 创建任务组命令 - * - * @param childUrl 子任务url - */ - public static AbsGroupCmd createGroupCmd(T entity, int cmd, - String childUrl) { - return GroupCmdFactory.getInstance().createCmd(entity, cmd, childUrl); - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/command/DGSubStopCmd.java b/PublicComponent/src/main/java/com/arialyy/aria/core/command/DGSubStopCmd.java deleted file mode 100644 index 7cdcd226..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/command/DGSubStopCmd.java +++ /dev/null @@ -1,34 +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.AbsGroupTaskWrapper; - -/** - * Created by AriaL on 2017/6/29. - * 停止任务组子任务的命令 - */ -final class DGSubStopCmd extends AbsGroupCmd { - DGSubStopCmd(T entity) { - super(entity); - } - - @Override public void executeCmd() { - if (checkTask()) { - tempTask.stopSubTask(childUrl); - } - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/command/GroupCmdFactory.java b/PublicComponent/src/main/java/com/arialyy/aria/core/command/GroupCmdFactory.java deleted file mode 100644 index e1241d65..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/command/GroupCmdFactory.java +++ /dev/null @@ -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.command; - -import com.arialyy.aria.core.download.AbsGroupTaskWrapper; - -/** - * Created by AriaL on 2017/6/29. 任务组子任务控制命令 - */ -public class GroupCmdFactory { - /** - * 启动子任务 - */ - public static final int SUB_TASK_START = 0xa1; - /** - * 停止子任务 - */ - public static final int SUB_TASK_STOP = 0xa2; - - private static volatile GroupCmdFactory INSTANCE = null; - - private GroupCmdFactory() { - - } - - public static GroupCmdFactory getInstance() { - if (INSTANCE == null) { - synchronized (GroupCmdFactory.class) { - INSTANCE = new GroupCmdFactory(); - } - } - return INSTANCE; - } - - /** - * @param wrapper 参数信息 - * @param type 命令类型{@link #SUB_TASK_START}、{@link #SUB_TASK_STOP} - * @param childUrl 需要控制的子任务url - */ - public AbsGroupCmd createCmd(AbsGroupTaskWrapper wrapper, int type, String childUrl) { - AbsGroupCmd cmd = null; - switch (type) { - case SUB_TASK_START: - cmd = new DGSubStartCmd<>(wrapper); - break; - case SUB_TASK_STOP: - cmd = new DGSubStopCmd<>(wrapper); - break; - } - if (cmd != null) { - cmd.childUrl = childUrl; - } - return cmd; - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/command/HighestPriorityCmd.java b/PublicComponent/src/main/java/com/arialyy/aria/core/command/HighestPriorityCmd.java deleted file mode 100644 index fa914bff..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/command/HighestPriorityCmd.java +++ /dev/null @@ -1,57 +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.AriaConfig; -import com.arialyy.aria.core.AriaManager; -import com.arialyy.aria.core.task.SingleDownloadTask; -import com.arialyy.aria.core.wrapper.AbsTaskWrapper; -import com.arialyy.aria.core.queue.DTaskQueue; -import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.NetUtils; - -/** - * Created by lyy on 2017/6/2. - * 最高优先级命令,最高优先级命令有以下属性 - * 1、在下载队列中,有且只有一个最高优先级任务 - * 2、最高优先级任务会一直存在,直到用户手动暂停或任务完成 - * 3、任务调度器不会暂停最高优先级任务 - * 4、用户手动暂停或任务完成后,第二次重新执行该任务,该命令将失效 - * 5、如果下载队列中已经满了,则会停止队尾的任务,当高优先级任务完成后,该队尾任务将自动执行 - * 6、把任务设置为最高优先级任务后,将自动执行任务,不需要重新调用start()启动任务 - * - * 目前只只支持单下载任务的最高优先级任务 - */ -final class HighestPriorityCmd extends AbsNormalCmd { - HighestPriorityCmd(T entity, int taskType) { - super(entity, taskType); - } - - @Override public void executeCmd() { - if (!canExeCmd) return; - if (!NetUtils.isConnected(AriaConfig.getInstance().getAPP())){ - ALog.e(TAG, "启动任务失败,网络未连接"); - return; - } - SingleDownloadTask task = (SingleDownloadTask) getTask(); - if (task == null) { - task = (SingleDownloadTask) createTask(); - } - if (task != null) { - ((DTaskQueue) mQueue).setTaskHighestPriority(task); - } - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/command/ReStartCmd.java b/PublicComponent/src/main/java/com/arialyy/aria/core/command/ReStartCmd.java deleted file mode 100644 index a2bef76c..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/command/ReStartCmd.java +++ /dev/null @@ -1,41 +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.inf.TaskSchedulerType; -import com.arialyy.aria.core.task.AbsTask; -import com.arialyy.aria.core.wrapper.AbsTaskWrapper; - -/** - * 重新开始任务命令 - */ -final class ReStartCmd extends AbsNormalCmd { - - ReStartCmd(T entity, int taskType) { - super(entity, taskType); - } - - @Override public void executeCmd() { - AbsTask task = getTask(); - if (task == null) { - task = createTask(); - } - if (task != null) { - mQueue.cancelTask(task, TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY); - mQueue.startTask(task, TaskSchedulerType.TYPE_START_AND_RESET_STATE); - } - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/command/ResumeAllCmd.java b/PublicComponent/src/main/java/com/arialyy/aria/core/command/ResumeAllCmd.kt similarity index 62% rename from PublicComponent/src/main/java/com/arialyy/aria/core/command/ResumeAllCmd.java rename to PublicComponent/src/main/java/com/arialyy/aria/core/command/ResumeAllCmd.kt index 4e81b18a..cd560898 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/command/ResumeAllCmd.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/command/ResumeAllCmd.kt @@ -13,13 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.arialyy.aria.core.command; +package com.arialyy.aria.core.command -import com.arialyy.aria.core.AriaConfig; -import com.arialyy.aria.core.inf.IEntity; -import com.arialyy.aria.core.wrapper.AbsTaskWrapper; -import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.NetUtils; +import com.arialyy.aria.core.DuaContext +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch /** * Created by AriaL on 2017/6/13. @@ -28,19 +26,13 @@ import com.arialyy.aria.util.NetUtils; * 2.如果队列执行队列已经满了,则将所有任务添加到等待队列中 * 3.如果队列中只有等待状态的任务,如果执行队列没有满,则会启动等待状态的任务,如果执行队列已经满了,则会将所有等待状态的任务加载到缓存队列中 * 4.恢复下载的任务规则是,停止时间越晚的任务启动越早,按照DESC来进行排序 - */ -final class ResumeAllCmd extends AbsNormalCmd { + **/ +class ResumeAllCmd() : ICmd { - ResumeAllCmd(T entity, int taskType) { - super(entity, taskType); - } + override fun executeCmd(): CmdResp { + DuaContext.duaScope.launch(Dispatchers.IO) { - @Override public void executeCmd() { - if (!NetUtils.isConnected(AriaConfig.getInstance().getAPP())) { - ALog.w(TAG, "恢复任务失败,网络未连接"); - return; } - new Thread(new ResumeThread(isDownloadCmd, - String.format("state!=%s", IEntity.STATE_COMPLETE))).start(); + return CmdResp(CmdResp.CODE_COMPLETE) } -} +} \ No newline at end of file diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/command/ResumeThread.java b/PublicComponent/src/main/java/com/arialyy/aria/core/command/ResumeThread.java deleted file mode 100644 index 32f442d6..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/command/ResumeThread.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.arialyy.aria.core.command; - -import android.text.TextUtils; -import com.arialyy.aria.core.common.AbsEntity; -import com.arialyy.aria.core.download.DGTaskWrapper; -import com.arialyy.aria.core.download.DTaskWrapper; -import com.arialyy.aria.core.download.DownloadEntity; -import com.arialyy.aria.core.download.DownloadGroupEntity; -import com.arialyy.aria.core.inf.IEntity; -import com.arialyy.aria.core.inf.IOptionConstant; -import com.arialyy.aria.core.listener.ISchedulers; -import com.arialyy.aria.core.manager.TaskWrapperManager; -import com.arialyy.aria.core.queue.AbsTaskQueue; -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.task.AbsTask; -import com.arialyy.aria.core.upload.UTaskWrapper; -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.orm.DbEntity; -import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CommonUtil; -import java.util.ArrayList; -import java.util.List; - -/** - * 恢复任务工具 - */ -public class ResumeThread implements Runnable { - private String TAG = CommonUtil.getClassName(getClass()); - private List mWaitList = new ArrayList<>(); - private boolean isDownloadCmd; - private String sqlCondition; - - ResumeThread(boolean isDownload, String sqlCondition) { - this.isDownloadCmd = isDownload; - this.sqlCondition = sqlCondition; - } - - /** - * 查找数据库中的所有任务数据 - * - * @param type {@code 1}单任务下载任务;{@code 2}任务组下载任务;{@code 3} 单任务上传任务 - */ - private void findTaskData(int type) { - if (type == 1) { - List entities = - DbEntity.findDatas(DownloadEntity.class, - String.format("NOT(isGroupChild) AND NOT(isComplete) AND %s ORDER BY stopTime DESC", - sqlCondition)); - if (entities != null && !entities.isEmpty()) { - for (DownloadEntity entity : entities) { - addResumeEntity(TaskWrapperManager.getInstance() - .getNormalTaskWrapper(DTaskWrapper.class, entity.getId())); - } - } - } else if (type == 2) { - List entities = - DbEntity.findDatas(DownloadGroupEntity.class, - String.format("NOT(isComplete) AND %s ORDER BY stopTime DESC", - sqlCondition)); - if (entities != null && !entities.isEmpty()) { - for (DownloadGroupEntity entity : entities) { - addResumeEntity( - TaskWrapperManager.getInstance() - .getGroupWrapper(DGTaskWrapper.class, entity.getId())); - } - } - } else if (type == 3) { - List entities = - DbEntity.findDatas(UploadEntity.class, - String.format("NOT(isComplete) AND %s ORDER BY stopTime DESC", - sqlCondition)); - if (entities != null && !entities.isEmpty()) { - for (UploadEntity entity : entities) { - addResumeEntity(TaskWrapperManager.getInstance() - .getNormalTaskWrapper(UTaskWrapper.class, entity.getId())); - } - } - } - } - - /** - * 添加恢复实体 - */ - private void addResumeEntity(AbsTaskWrapper te) { - if (te == null || te.getEntity() == null || TextUtils.isEmpty(te.getKey())) { - return; - } - mWaitList.add(te); - } - - /** - * 处理等待状态的任务 - */ - private void resumeWaitTask() { - - if (mWaitList == null || mWaitList.isEmpty()) { - return; - } - List resumeEntities = new ArrayList<>(); - - for (AbsTaskWrapper wrapper : mWaitList) { - AbsTaskQueue queue = null; - if (wrapper instanceof DTaskWrapper) { - queue = DTaskQueue.getInstance(); - } else if (wrapper instanceof UTaskWrapper) { - queue = UTaskQueue.getInstance(); - } else if (wrapper instanceof DGTaskWrapper) { - queue = DGroupTaskQueue.getInstance(); - } - - if (queue == null) { - ALog.e(TAG, "任务类型错误"); - continue; - } - - if (wrapper.getEntity() == null || TextUtils.isEmpty(wrapper.getKey())) { - ALog.e(TAG, "任务实体为空或key为空"); - continue; - } - - AbsTask task = queue.getTask(wrapper.getKey()); - if (task != null) { - ALog.w(TAG, "任务已存在"); - continue; - } - - int maxTaskNum = queue.getMaxTaskNum(); - task = queue.createTask(wrapper); - if (task == null) { - continue; - } - - handleWrapper(wrapper); - - if (queue.getCurrentExePoolNum() < maxTaskNum) { - queue.startTask(task); - } else { - wrapper.getEntity().setState(IEntity.STATE_WAIT); - sendWaitState(task); - resumeEntities.add(wrapper.getEntity()); - } - } - if (!resumeEntities.isEmpty()) { - DbEntity.updateManyData(resumeEntities); - } - } - - /** - * 处理ftp的wrapper - */ - private void handleWrapper(AbsTaskWrapper wrapper) { - int requestType = wrapper.getRequestType(); - if (requestType == ITaskWrapper.D_FTP - || requestType == ITaskWrapper.U_FTP - || requestType == ITaskWrapper.D_FTP_DIR) { - wrapper.getOptionParams() - .setParams(IOptionConstant.ftpUrlEntity, - CommonUtil.getFtpUrlInfo(wrapper.getEntity().getKey())); - } - } - - /** - * 发送等待状态 - */ - private void sendWaitState(AbsTask task) { - if (task != null) { - task.getTaskWrapper().setState(IEntity.STATE_WAIT); - task.getOutHandler().obtainMessage(ISchedulers.WAIT, task).sendToTarget(); - } - } - - @Override public void run() { - if (isDownloadCmd) { - findTaskData(1); - findTaskData(2); - } else { - findTaskData(3); - } - resumeWaitTask(); - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/command/StopAllCmd.java b/PublicComponent/src/main/java/com/arialyy/aria/core/command/StopAllCmd.java index bd95cbc8..7b1210b4 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/command/StopAllCmd.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/command/StopAllCmd.java @@ -1,12 +1,11 @@ package com.arialyy.aria.core.command; -import com.arialyy.aria.core.wrapper.AbsTaskWrapper; /** * Created by AriaL on 2017/6/13. * 停止所有任务的命令,并清空所有等待队列 */ -final class StopAllCmd extends AbsNormalCmd { +final class StopAllCmd extends AbsCmd { StopAllCmd(T entity, int taskType) { super(entity, taskType); } diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/ILoaderComponent.java b/PublicComponent/src/main/java/com/arialyy/aria/core/event/ResumeAllEvent.kt similarity index 81% rename from PublicComponent/src/main/java/com/arialyy/aria/core/loader/ILoaderComponent.java rename to PublicComponent/src/main/java/com/arialyy/aria/core/event/ResumeAllEvent.kt index 465d4dab..8c7c50c7 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/ILoaderComponent.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/event/ResumeAllEvent.kt @@ -13,13 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.arialyy.aria.core.loader; +package com.arialyy.aria.core.event /** - * 加载器部件 - */ -public interface ILoaderComponent { - - void accept(ILoaderVisitor visitor); - -} + * @Author laoyuyu + * @Description + * @Date 8:26 PM 2023/3/21 + **/ +class ResumeAllEvent \ No newline at end of file diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsGroupLoader.java b/PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsGroupLoader.java deleted file mode 100644 index 50eacc6e..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsGroupLoader.java +++ /dev/null @@ -1,375 +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.group; - -import android.os.Handler; -import android.os.Looper; -import com.arialyy.aria.core.config.Configuration; -import com.arialyy.aria.core.download.DGTaskWrapper; -import com.arialyy.aria.core.download.DTaskWrapper; -import com.arialyy.aria.core.inf.IEntity; -import com.arialyy.aria.core.inf.ITaskManager; -import com.arialyy.aria.core.listener.IDGroupListener; -import com.arialyy.aria.core.listener.IEventListener; -import com.arialyy.aria.core.loader.IInfoTask; -import com.arialyy.aria.core.loader.ILoader; -import com.arialyy.aria.core.loader.ILoaderVisitor; -import com.arialyy.aria.core.loader.IRecordHandler; -import com.arialyy.aria.core.loader.IThreadTaskBuilder; -import com.arialyy.aria.core.wrapper.AbsTaskWrapper; -import com.arialyy.aria.exception.AriaException; -import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CommonUtil; -import java.io.File; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -/** - * 组合任务加载器 - */ -public abstract class AbsGroupLoader implements ILoaderVisitor, ILoader { - protected final String TAG = CommonUtil.getClassName(getClass()); - - private long mCurrentLocation = 0; - private IDGroupListener mListener; - private ScheduledThreadPoolExecutor mTimer; - private long mUpdateInterval; - private boolean isStop = false, isCancel = false; - private Handler mScheduler; - private SimpleSubQueue mSubQueue = SimpleSubQueue.newInstance(); - private Map mExeLoader = new WeakHashMap<>(); - private Map mCache = new WeakHashMap<>(); - private DGTaskWrapper mGTWrapper; - private GroupRunState mState; - - protected IInfoTask mInfoTask; - - protected AbsGroupLoader(AbsTaskWrapper groupWrapper, IEventListener listener) { - mListener = (IDGroupListener) listener; - mGTWrapper = (DGTaskWrapper) groupWrapper; - mUpdateInterval = Configuration.getInstance().downloadCfg.getUpdateInterval(); - } - - /** - * 处理任务 - */ - protected abstract void handlerTask(Looper looper); - - /** - * 创建子任务加载器工具 - * - * @param needGetFileInfo {@code true} 需要获取文件信息。{@code false} 不需要获取文件信息 - */ - protected abstract AbsSubDLoadAdapter createSubLoader(DTaskWrapper wrapper, boolean needGetFileInfo); - - protected IDGroupListener getListener() { - return mListener; - } - - protected DGTaskWrapper getWrapper() { - return mGTWrapper; - } - - protected GroupRunState getState() { - return mState; - } - - public Handler getScheduler() { - return mScheduler; - } - - /** - * 初始化组合任务状态 - */ - private void initState(Looper looper) { - mState = new GroupRunState(getWrapper().getKey(), mListener, mSubQueue); - for (DTaskWrapper wrapper : mGTWrapper.getSubTaskWrapper()) { - long fileLen = checkFileExists(wrapper.getEntity().getFilePath()); - if (wrapper.getEntity().getState() == IEntity.STATE_COMPLETE - && fileLen > 0 - && fileLen == wrapper.getEntity().getFileSize()) { - //mState.updateCompleteNum(); - mCurrentLocation += wrapper.getEntity().getFileSize(); - } else { - if (fileLen <= 0) { - wrapper.getEntity().setCurrentProgress(0); - } - wrapper.getEntity().setState(IEntity.STATE_POST_PRE); - mCache.put(wrapper.getKey(), wrapper); - mCurrentLocation += wrapper.getEntity().getCurrentProgress(); - } - } - if (getWrapper().getSubTaskWrapper().size() != mState.getCompleteNum()) { - getWrapper().setState(IEntity.STATE_POST_PRE); - } - mState.updateProgress(mCurrentLocation); - mScheduler = new Handler(looper, SimpleSchedulers.newInstance(mState, mGTWrapper.getKey())); - } - - /** - * 检查文件是否存在,需要检查普通任务和分块任务的 - * - * @param filePath 文件路径 - * @return 文件存在返回文件长度,不存在返回-1 - */ - private long checkFileExists(String filePath) { - File temp = new File(filePath); - if (temp.exists()) { - return temp.length(); - } - File block = new File(String.format(IRecordHandler.SUB_PATH, filePath, 0)); - if (block.exists()) { - return block.length(); - } else { - return -1; - } - } - - @Override public String getKey() { - return mGTWrapper.getKey(); - } - - /** - * 启动子任务下载 - * - * @param url 子任务下载地址 - */ - void startSubTask(String url) { - if (!checkSubTask(url, "开始")) { - return; - } - if (!mState.isRunning.get()) { - startTimer(); - } - AbsSubDLoadAdapter d = getDownloader(url, false); - if (d != null && !d.isRunning()) { - mSubQueue.startTask(d); - } - } - - /** - * 停止子任务下载 - * - * @param url 子任务下载地址 - */ - void stopSubTask(String url) { - if (!checkSubTask(url, "停止")) { - return; - } - AbsSubDLoadAdapter d = getDownloader(url, false); - if (d != null && d.isRunning()) { - mSubQueue.stopTask(d); - } - } - - /** - * 检查子任务 - * - * @param url 子任务url - * @param type 任务类型 - * @return {@code true} 任务可以下载 - */ - private boolean checkSubTask(String url, String type) { - DTaskWrapper wrapper = mCache.get(url); - if (wrapper != null) { - if (wrapper.getState() == IEntity.STATE_COMPLETE) { - ALog.w(TAG, "任务【" + url + "】已完成," + type + "失败"); - return false; - } - } else { - ALog.w(TAG, "任务组中没有该任务【" + url + "】," + type + "失败"); - return false; - } - return true; - } - - /** - * 通过地址获取下载器 - * - * @param url 子任务下载地址 - */ - private AbsSubDLoadAdapter getDownloader(String url, boolean needGetFileInfo) { - AbsSubDLoadAdapter d = mExeLoader.get(url); - if (d == null) { - return createSubLoader(mCache.get(url), needGetFileInfo); - } - return d; - } - - @Override public boolean isRunning() { - return mState != null && mState.isRunning.get(); - } - - @Override public void cancel() { - isCancel = true; - if (mInfoTask != null){ - mInfoTask.cancel(); - } - closeTimer(); - mSubQueue.removeAllTask(); - mListener.onCancel(); - } - - @Override public void stop() { - if (mInfoTask != null){ - mInfoTask.stop(); - } - isStop = true; - if (mSubQueue.getExecSize() == 0) { - mListener.onStop(mGTWrapper.getEntity().getCurrentProgress()); - } else { - mSubQueue.stopAllTask(); - } - closeTimer(); - } - - @Override public void run() { - checkComponent(); - if (isStop || isCancel) { - closeTimer(); - return; - } - startRunningFlow(); - } - - /** - * 开始进度流程 - */ - private void startRunningFlow() { - closeTimer(); - Looper.prepare(); - Looper looper = Looper.myLooper(); - if (looper == Looper.getMainLooper()) { - throw new IllegalThreadStateException("不能在主线程程序中调用Loader"); - } - initState(looper); - getState().setSubSize(getWrapper().getSubTaskWrapper().size()); - if (getState().getCompleteNum() != 0 - && getState().getCompleteNum() == getState().getSubSize()) { - mListener.onComplete(); - return; - } - startTimer(); - handlerTask(looper); - Looper.loop(); - } - - /** - * 组合任务获取完成子任务的信息后调用 - */ - protected void onPostStart() { - if (isBreak()) { - return; - } - getListener().onPostPre(getWrapper().getEntity().getFileSize()); - if (getWrapper().getEntity().getFileSize() > 0) { - getListener().onResume(getWrapper().getEntity().getCurrentProgress()); - } else { - getListener().onStart(getWrapper().getEntity().getCurrentProgress()); - } - } - - private synchronized void startTimer() { - mState.isRunning.set(true); - mTimer = new ScheduledThreadPoolExecutor(1); - mTimer.scheduleWithFixedDelay(new Runnable() { - @Override public void run() { - if (!mState.isRunning.get()) { - closeTimer(); - } else if (mCurrentLocation >= 0) { - long t = 0; - for (DTaskWrapper te : mGTWrapper.getSubTaskWrapper()) { - if (te.getState() == IEntity.STATE_COMPLETE) { - t += te.getEntity().getFileSize(); - } else { - t += te.getEntity().getCurrentProgress(); - } - } - mCurrentLocation = t; - mState.updateProgress(mCurrentLocation); - mListener.onProgress(t); - } - } - }, 0, mUpdateInterval, TimeUnit.MILLISECONDS); - } - - /** - * 启动子任务下载器 - */ - protected void startSubLoader(AbsSubDLoadAdapter loader) { - mExeLoader.put(loader.getKey(), loader); - mSubQueue.startTask(loader); - } - - @Override public boolean isBreak() { - if (isCancel || isStop) { - //ALog.d(TAG, "isCancel = " + isCancel + ", isStop = " + isStop); - ALog.d(TAG, String.format("任务【%s】已停止或取消了", mGTWrapper.getKey())); - return true; - } - return false; - } - - private synchronized void closeTimer() { - if (mTimer != null && !mTimer.isShutdown()) { - mTimer.shutdown(); - } - } - - protected void fail(AriaException e, boolean needRetry) { - closeTimer(); - getListener().onFail(needRetry, e); - } - - @Override public long getCurrentProgress() { - return mCurrentLocation; - } - - /** - * @deprecated 组合任务不需要实现这个,记录交由其子任务处理 - */ - @Deprecated - @Override public void addComponent(IRecordHandler recordHandler) { - - } - - /** - * @deprecated 组合任务不需要实现这个,线程创建交有子任务处理 - */ - @Deprecated - @Override public void addComponent(IThreadTaskBuilder builder) { - - } - - /** - * @deprecated 组合任务不需要实现这个,其内部是一个子任务调度器,并不是线程状态管理器 - */ - @Deprecated - @Override public void addComponent(ITaskManager threadState) { - - } - - /** - * 检查组件: {@link #mInfoTask} - */ - private void checkComponent() { - if (mInfoTask == null) { - throw new NullPointerException(("文件信息组件为空")); - } - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsGroupLoaderAdapter.java b/PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsGroupLoaderAdapter.java deleted file mode 100644 index 8835020b..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsGroupLoaderAdapter.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.arialyy.aria.core.group; - -import com.arialyy.aria.core.inf.ITaskAdapter; -import com.arialyy.aria.core.listener.IEventListener; -import com.arialyy.aria.core.loader.LoaderStructure; -import com.arialyy.aria.core.wrapper.AbsTaskWrapper; -import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CommonUtil; - -/** - * Created by AriaL on 2017/6/30. - * 任务组核心逻辑 - */ -public abstract class AbsGroupLoaderAdapter implements ITaskAdapter { - - protected String TAG = CommonUtil.getClassName(getClass()); - private IEventListener mListener; - protected AbsGroupLoader mLoader; - private AbsTaskWrapper mTaskWrapper; - private boolean isStop = false, isCancel = false; - - - @Override public ITaskAdapter setParams(AbsTaskWrapper taskWrapper, IEventListener listener) { - mTaskWrapper = taskWrapper; - mListener = listener; - mLoader = getLoader(); - return this; - } - - protected abstract AbsGroupLoader getLoader(); - - protected abstract LoaderStructure buildLoaderStructure(); - - public IEventListener getListener() { - return mListener; - } - - public AbsTaskWrapper getTaskWrapper() { - return mTaskWrapper; - } - - @Override public String getKey() { - return mTaskWrapper.getKey(); - } - - @Override public long getFileSize() { - return mTaskWrapper.getEntity().getFileSize(); - } - - @Override public long getCurrentLocation() { - return mLoader.getCurrentProgress(); - } - - @Override public boolean isRunning() { - return mLoader.isRunning(); - } - - public void startSubTask(String url) { - getLoader().startSubTask(url); - } - - public void stopSubTask(String url) { - getLoader().stopSubTask(url); - } - - /** - * 取消下载 - */ - @Override public void cancel() { - isCancel = true; - mLoader.cancel(); - } - - /** - * 停止下载 - */ - @Override public void stop() { - isStop = true; - mLoader.stop(); - } - - @Override public void start() { - if (isStop || isCancel) { - ALog.w(TAG, "启动组合任务失败,任务已停止或已取消"); - return; - } - mListener.onPre(); - - buildLoaderStructure(); - new Thread(mLoader).start(); - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsSubDLoadAdapter.java b/PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsSubDLoadAdapter.java deleted file mode 100644 index 66ef66c2..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsSubDLoadAdapter.java +++ /dev/null @@ -1,165 +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.group; - -import android.os.Handler; -import com.arialyy.aria.core.TaskRecord; -import com.arialyy.aria.core.download.DTaskWrapper; -import com.arialyy.aria.core.download.DownloadEntity; -import com.arialyy.aria.core.inf.ITaskAdapter; -import com.arialyy.aria.core.listener.IEventListener; -import com.arialyy.aria.core.listener.ISchedulers; -import com.arialyy.aria.core.loader.LoaderStructure; -import com.arialyy.aria.core.loader.SubLoader; -import com.arialyy.aria.core.wrapper.AbsTaskWrapper; -import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CommonUtil; - -/** - * 子任务下载器工具,需要在线程池中执行 - */ -public abstract class AbsSubDLoadAdapter implements ITaskAdapter, Runnable { - protected final String TAG = CommonUtil.getClassName(getClass()); - - protected SubLoader mDLoader; - private DTaskWrapper mWrapper; - private Handler mSchedulers; - private boolean needGetInfo; - private boolean isStop = false, isCancel = false; - private String parentKey; - - /** - * @param schedulers 调度器 - * @param needGetInfo {@code true} 需要获取文件信息。{@code false} 不需要获取文件信息 - */ - protected AbsSubDLoadAdapter(Handler schedulers, boolean needGetInfo, String parentKey) { - mSchedulers = schedulers; - this.parentKey = parentKey; - this.needGetInfo = needGetInfo; - } - - @Override public ITaskAdapter setParams(AbsTaskWrapper taskWrapper, IEventListener listener) { - mWrapper = (DTaskWrapper) taskWrapper; - mDLoader = getLoader(); - return this; - } - - /** - * 创建加载器 - */ - protected abstract SubLoader getLoader(); - - protected abstract LoaderStructure buildLoaderStructure(); - - public String getParentKey() { - return parentKey; - } - - protected boolean isNeedGetInfo() { - return needGetInfo; - } - - public Handler getSchedulers() { - return mSchedulers; - } - - @Override public String getKey() { - return mDLoader.getKey(); - } - - public DTaskWrapper getWrapper() { - return mWrapper; - } - - public DownloadEntity getEntity() { - return mWrapper.getEntity(); - } - - public TaskRecord getRecord(){ - return getLoader().getRecord(); - } - - @Override public void run() { - if (isStop || isCancel) { - return; - } - buildLoaderStructure(); - new Thread(mDLoader).start(); - } - - /** - * 请在线程池中使用 - */ - @Deprecated - @Override public void start() { - throw new AssertionError("请在线程池中使用"); - } - - /** - * 重新开始任务 - */ - void reStart() { - if (mDLoader != null) { - mDLoader.retryTask(); - } - } - - /** - * @deprecated 子任务不实现这个 - */ - @Deprecated - @Override public long getFileSize() { - return -1; - } - - /** - * 子任务不实现这个 - */ - @Deprecated - @Override public long getCurrentLocation() { - return -1; - } - - @Override public boolean isRunning() { - return mDLoader != null && mDLoader.isRunning(); - } - - @Override public void cancel() { - if (isCancel) { - ALog.w(TAG, "子任务已取消"); - return; - } - isCancel = true; - if (mDLoader != null && isRunning()) { - mDLoader.cancel(); - } else { - mSchedulers.obtainMessage(ISchedulers.CANCEL, this).sendToTarget(); - } - } - - @Override public void stop() { - if (isStop) { - ALog.w(TAG, "任务已停止"); - return; - } - isStop = true; - if (mDLoader != null && isRunning()) { - mDLoader.stop(); - } else { - mSchedulers.obtainMessage(ISchedulers.STOP, this).sendToTarget(); - } - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/group/GroupRunState.java b/PublicComponent/src/main/java/com/arialyy/aria/core/group/GroupRunState.java deleted file mode 100644 index 94c487d8..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/group/GroupRunState.java +++ /dev/null @@ -1,189 +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.group; - -import com.arialyy.aria.core.listener.IDGroupListener; -import com.arialyy.aria.core.wrapper.AbsTaskWrapper; -import com.arialyy.aria.util.ALog; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * 组合任务执行中的状态信息 - */ -public final class GroupRunState { - private String TAG = "GroupRunState"; - /** - * 子任务数 - */ - private int mSubSize; - - /** - * 已经完成的任务数 - */ - private AtomicInteger mCompleteNum = new AtomicInteger(); - - /** - * 失败的任务数 - */ - private AtomicInteger mFailNum = new AtomicInteger(); - - /** - * 停止的任务数 - */ - private AtomicInteger mStopNum = new AtomicInteger(); - - /** - * 当前进度 - */ - private long mProgress; - - /** - * 组合任务监听 - */ - IDGroupListener listener; - - /** - * 子任务队列 - */ - SimpleSubQueue queue; - - /** - * 是否在执行 - */ - AtomicBoolean isRunning = new AtomicBoolean(false); - - /** - * 子任务失败、停止记录,用于当子任务失败重新被用户点击开始时,更新{@link #mStopNum}或{@link #mFailNum} - * 保存的数据为:子任务key - */ - private Set mFailTemp = new HashSet<>(), mStopTemp = new HashSet<>(); - - private String mGroupHash; - - GroupRunState(String groupHash, IDGroupListener listener, SimpleSubQueue queue) { - this.listener = listener; - this.queue = queue; - mGroupHash = groupHash; - } - - public void setSubSize(int subSize) { - mSubSize = subSize; - } - - /** - * 组合任务是否正在自行 - * - * @return {@code true}组合任务正在执行 - */ - public boolean isRunning() { - return isRunning.get(); - } - - public void setRunning(boolean running) { - isRunning.set(running); - } - - String getGroupHash() { - return mGroupHash; - } - - /** - * 获取组合任务子任务数 - */ - public int getSubSize() { - return mSubSize; - } - - /** - * 获取失败的数量 - */ - public int getFailNum() { - return mFailNum.get(); - } - - /** - * 获取停止的数量 - */ - public int getStopNum() { - return mStopNum.get(); - } - - /** - * 获取完成的数量 - */ - public int getCompleteNum() { - return mCompleteNum.get(); - } - - /** - * 获取当前组合任务总进度 - */ - public long getProgress() { - return mProgress; - } - - /** - * 更新完成的数量,mCompleteNum + 1 - */ - public void updateCompleteNum() { - mCompleteNum.getAndIncrement(); - } - - /** - * 更新任务进度 - */ - public void updateProgress(long newProgress) { - this.mProgress = newProgress; - } - - /** - * 当子任务开始时,更新停止\失败的任务数 - * - * @param key {@link AbsTaskWrapper#getKey()} - */ - public void updateCount(String key) { - if (mFailTemp.contains(key)) { - mFailTemp.remove(key); - mFailNum.getAndDecrement(); - } else if (mStopTemp.contains(key)) { - mStopTemp.remove(key); - mStopNum.getAndDecrement(); - } - } - - /** - * 统计子任务停止的数量 - * - * @param key {@link AbsTaskWrapper#getKey()} - */ - public void countStopNum(String key) { - mStopTemp.add(key); - mStopNum.getAndIncrement(); - } - - /** - * 统计子任务失败的数量 - * - * @param key {@link AbsTaskWrapper#getKey()} - */ - public void countFailNum(String key) { - mFailTemp.add(key); - mFailNum.getAndIncrement(); - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/group/GroupSendParams.java b/PublicComponent/src/main/java/com/arialyy/aria/core/group/GroupSendParams.java deleted file mode 100644 index 303fff3d..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/group/GroupSendParams.java +++ /dev/null @@ -1,37 +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.group; - -import com.arialyy.aria.core.common.AbsNormalEntity; -import com.arialyy.aria.core.task.AbsGroupTask; - -/** - * Created by lyy on 2017/9/8. - * 任务组参数传递 - */ -public final class GroupSendParams { - - public GROUP_TASK groupTask; - public ENTITY entity; - - public GroupSendParams() { - } - - public GroupSendParams(GROUP_TASK groupTask, ENTITY entity) { - this.groupTask = groupTask; - this.entity = entity; - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/group/ISubQueue.java b/PublicComponent/src/main/java/com/arialyy/aria/core/group/ISubQueue.java deleted file mode 100644 index 5a914ea9..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/group/ISubQueue.java +++ /dev/null @@ -1,85 +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.group; - -import com.arialyy.aria.core.loader.AbsNormalLoader; -import com.arialyy.aria.core.inf.ITaskAdapter; -import com.arialyy.aria.core.config.DGroupConfig; - -/** - * 组合任务子任务队列 - * - * @param {@link AbsNormalLoader}下载器 - */ -interface ISubQueue { - - /** - * 添加任务 - */ - - void addTask(Fileer fileer); - - /** - * 开始任务 - * 如果执行队列没有达到上限,则启动任务。 - * 如果执行队列已经到达上限,则将任务添加到等待队列总。 - * 队列上限配置{@link DGroupConfig#setSubMaxTaskNum(int)} - */ - void startTask(Fileer fileer); - - /** - * 停止单个任务,如果缓存队列中有等待中的任务,则启动等待中的任务 - */ - void stopTask(Fileer fileer); - - /** - * 停止全部任务,停止所有正在执行的任务,并清空所有等待中的端服务 - */ - void stopAllTask(); - - /** - * 修改最大任务数 - * - * @param num 任务数不能小于1 - */ - void modifyMaxExecNum(int num); - - /** - * 从执行队列中移除任务,一般用于任务完成的情况 - */ - void removeTaskFromExecQ(Fileer fileer); - - /** - * 删除任务,如果缓存队列中有等待中的任务,则启动等待中的任务 - */ - void removeTask(Fileer fileer); - - /** - * 停止全部任务,停止所有正在执行的任务,并清空所有等待中的端服务 - */ - void removeAllTask(); - - - /** - * 获取下一个任务 - */ - Fileer getNextTask(); - - /** - * 清空缓存队列和执行队列 - */ - void clear(); -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/group/SimpleSchedulers.java b/PublicComponent/src/main/java/com/arialyy/aria/core/group/SimpleSchedulers.java deleted file mode 100644 index 225b9256..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/group/SimpleSchedulers.java +++ /dev/null @@ -1,230 +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.group; - -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.util.Log; -import com.arialyy.aria.core.AriaConfig; -import com.arialyy.aria.core.TaskRecord; -import com.arialyy.aria.core.config.Configuration; -import com.arialyy.aria.core.inf.ITaskManager; -import com.arialyy.aria.core.loader.IRecordHandler; -import com.arialyy.aria.core.manager.ThreadTaskManager; -import com.arialyy.aria.exception.ExceptionFactory; -import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CommonUtil; -import com.arialyy.aria.util.NetUtils; -import java.io.File; - -/** - * 组合任务子任务调度器,用于调度任务的开始、停止、失败、完成等情况 - * 该调度器生命周期和{@link AbsGroupLoaderAdapter}生命周期一致 - */ -final class SimpleSchedulers implements Handler.Callback { - private final String TAG = CommonUtil.getClassName(this); - private SimpleSubQueue mQueue; - private GroupRunState mGState; - private String mKey; // 组合任务的key - - private SimpleSchedulers(GroupRunState state, String key) { - mQueue = state.queue; - mGState = state; - mKey = key; - } - - static SimpleSchedulers newInstance(GroupRunState state, String key) { - return new SimpleSchedulers(state, key); - } - - @Override public boolean handleMessage(Message msg) { - Bundle b = msg.getData(); - if (b == null) { - ALog.w(TAG, "组合任务子任务调度数据为空"); - return true; - } - String threadName = b.getString(ITaskManager.DATA_THREAD_NAME); - AbsSubDLoadAdapter loaderUtil = mQueue.getLoaderUtil(threadName); - if (loaderUtil == null) { - ALog.e(TAG, String.format("子任务loader不存在,state:%s,key:%s", msg.what, threadName)); - return true; - } - long curLocation = b.getLong(ITaskManager.DATA_THREAD_LOCATION, - loaderUtil.getLoader().getWrapper().getEntity().getCurrentProgress()); - // 处理状态 - switch (msg.what) { - case ITaskManager.STATE_RUNNING: - long range = (long) msg.obj; - mGState.listener.onSubRunning(loaderUtil.getEntity(), range); - break; - case ITaskManager.STATE_PRE: - mGState.listener.onSubPre(loaderUtil.getEntity()); - mGState.updateCount(loaderUtil.getKey()); - break; - case ITaskManager.STATE_START: - mGState.listener.onSubStart(loaderUtil.getEntity()); - break; - case ITaskManager.STATE_STOP: - handleStop(loaderUtil, curLocation); - ThreadTaskManager.getInstance().removeSingleTaskThread(mKey, threadName); - break; - case ITaskManager.STATE_COMPLETE: - handleComplete(loaderUtil); - ThreadTaskManager.getInstance().removeSingleTaskThread(mKey, threadName); - break; - case ITaskManager.STATE_FAIL: - boolean needRetry = b.getBoolean(ITaskManager.DATA_RETRY, false); - handleFail(loaderUtil, needRetry); - ThreadTaskManager.getInstance().removeSingleTaskThread(mKey, threadName); - break; - } - return true; - } - - /** - * 处理子任务失败的情况 - * 1、子任务失败次数大于等于配置的重试次数,才能认为子任务停止 - * 2、stopNum + failNum + completeNum + cacheNum == subSize,则认为组合任务停止 - * 3、failNum == subSize,只有全部的子任务都失败了,才能任务组合任务失败 - * - * @param needRetry true 需要重试,false 不需要重试 - */ - private synchronized void handleFail(final AbsSubDLoadAdapter loaderUtil, boolean needRetry) { - Log.d(TAG, String.format("handleFail, size = %s, completeNum = %s, failNum = %s, stopNum = %s", - mGState.getSubSize(), mGState.getCompleteNum(), mGState.getFailNum(), - mGState.getSubSize())); - - Configuration config = Configuration.getInstance(); - int num = config.dGroupCfg.getSubReTryNum(); - boolean isNotNetRetry = config.appCfg.isNotNetRetry(); - - if (!needRetry - || (!NetUtils.isConnected(AriaConfig.getInstance().getAPP()) && !isNotNetRetry) - || loaderUtil.getLoader() == null // 如果获取不到文件信息,loader为空 - || loaderUtil.getEntity().getFailNum() > num) { - mQueue.removeTaskFromExecQ(loaderUtil); - mGState.listener.onSubFail(loaderUtil.getEntity(), - ExceptionFactory.getException(ExceptionFactory.TYPE_GROUP, - String.format("任务组子任务【%s】下载失败,下载地址【%s】", loaderUtil.getEntity().getFileName(), - loaderUtil.getEntity().getUrl()), null)); - mGState.countFailNum(loaderUtil.getKey()); - if (mGState.getFailNum() == mGState.getSubSize() - || mGState.getStopNum() + mGState.getFailNum() + mGState.getCompleteNum() - == mGState.getSubSize()) { - mGState.isRunning.set(false); - if (mGState.getCompleteNum() > 0 - && Configuration.getInstance().dGroupCfg.isSubFailAsStop()) { - ALog.e(TAG, String.format("任务组【%s】停止", mGState.getGroupHash())); - mGState.listener.onStop(mGState.getProgress()); - return; - } - mGState.listener.onFail(false, - ExceptionFactory.getException(ExceptionFactory.TYPE_GROUP, - String.format("任务组【%s】下载失败", mGState.getGroupHash()), null)); - return; - } - startNext(); - return; - } - SimpleSubRetryQueue.getInstance().offer(loaderUtil); - } - - /** - * 处理子任务停止的情况 - * 1、所有的子任务已经停止,则认为组合任务停止 - * 2、completeNum + failNum + stopNum = subSize,则认为组合任务停止 - */ - private synchronized void handleStop(AbsSubDLoadAdapter loadUtil, long curLocation) { - Log.d(TAG, String.format("handleStop, size = %s, completeNum = %s, failNum = %s, stopNum = %s", - mGState.getSubSize(), mGState.getCompleteNum(), mGState.getFailNum(), - mGState.getSubSize())); - - mGState.listener.onSubStop(loadUtil.getEntity(), curLocation); - mGState.countStopNum(loadUtil.getKey()); - if (mGState.getStopNum() == mGState.getSubSize() - || mGState.getStopNum() - + mGState.getCompleteNum() - + mGState.getFailNum() - + mQueue.getCacheSize() - == mGState.getSubSize()) { - mGState.isRunning.set(false); - mGState.listener.onStop(mGState.getProgress()); - return; - } - startNext(); - } - - /** - * 处理子任务完成的情况,有以下三种情况 - * 1、已经没有缓存的子任务,并且停止的子任务是数{@link GroupRunState#getStopNum()} ()}为0,失败的子任数{@link - * GroupRunState#getFailNum()}为0,则认为组合任务已经完成 - * 2、已经没有缓存的子任务,并且停止的子任务是数{@link GroupRunState#getCompleteNum()}不为0,或者失败的子任数{@link - * GroupRunState#getFailNum()}不为0,则认为组合任务被停止 - * 3、只有有缓存的子任务,则任务组合任务没有完成 - */ - private synchronized void handleComplete(AbsSubDLoadAdapter loader) { - ALog.d(TAG, String.format("子任务【%s】完成", loader.getEntity().getFileName())); - Log.d(TAG, - String.format("handleComplete, size = %s, completeNum = %s, failNum = %s, stopNum = %s", - mGState.getSubSize(), mGState.getCompleteNum(), mGState.getFailNum(), - mGState.getStopNum())); - - TaskRecord record = loader.getRecord(); - if (record != null && record.isBlock) { - File partFile = - new File(String.format(IRecordHandler.SUB_PATH, record.filePath, 0)); - partFile.renameTo(new File(record.filePath)); - } - ThreadTaskManager.getInstance().removeTaskThread(loader.getKey()); - mGState.listener.onSubComplete(loader.getEntity()); - mQueue.removeTaskFromExecQ(loader); - mGState.updateCompleteNum(); - if (mGState.getCompleteNum() + mGState.getFailNum() + mGState.getStopNum() - == mGState.getSubSize()) { - if (mGState.getStopNum() == 0 && mGState.getFailNum() == 0) { - mGState.listener.onComplete(); - } else if (mGState.getStopNum() == 0 - && !Configuration.getInstance().dGroupCfg.isSubFailAsStop()) { - mGState.listener.onFail(false, - ExceptionFactory.getException(ExceptionFactory.TYPE_GROUP, - String.format("任务组【%s】下载失败", mGState.getGroupHash()), null)); - } else { - mGState.listener.onStop(mGState.getProgress()); - } - mGState.isRunning.set(false); - return; - } - startNext(); - } - - /** - * 如果有等待中的任务,则启动下一任务 - */ - private void startNext() { - if (mQueue.isStopAll()) { - return; - } - AbsSubDLoadAdapter next = mQueue.getNextTask(); - if (next != null) { - ALog.d(TAG, String.format("启动任务:%s", next.getEntity().getFileName())); - mQueue.startTask(next); - return; - } - ALog.i(TAG, "没有下一子任务"); - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/group/SimpleSubQueue.java b/PublicComponent/src/main/java/com/arialyy/aria/core/group/SimpleSubQueue.java deleted file mode 100644 index ae3c4809..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/group/SimpleSubQueue.java +++ /dev/null @@ -1,201 +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.group; - -import com.arialyy.aria.core.config.Configuration; -import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CommonUtil; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -/** - * 组合任务队列,该队列生命周期和{@link AbsGroupLoaderAdapter}生命周期一致 - */ -final class SimpleSubQueue implements ISubQueue { - private final String TAG = CommonUtil.getClassName(getClass()); - /** - * 缓存下载器 - */ - private Map mCache = new ConcurrentHashMap<>(); - /** - * 执行中的下载器 - */ - private Map mExec = new ConcurrentHashMap<>(); - - /** - * 最大执行任务数 - */ - private int mMaxExecSize; - - /** - * 是否停止任务任务 - */ - private boolean isStopAll = false; - - private SimpleSubQueue() { - mMaxExecSize = Configuration.getInstance().dGroupCfg.getSubMaxTaskNum(); - } - - static SimpleSubQueue newInstance() { - return new SimpleSubQueue(); - } - - synchronized AbsSubDLoadAdapter getLoaderUtil(String key) { - AbsSubDLoadAdapter sub = mExec.get(key); - if (sub != null) { - return sub; - } - return mCache.get(key); - } - - /** - * 获取缓存队列大小 - */ - int getCacheSize() { - return mCache.size(); - } - - public int getExecSize(){ - return mExec.size(); - } - - boolean isStopAll() { - return isStopAll; - } - - @Override public void addTask(AbsSubDLoadAdapter fileer) { - mCache.put(fileer.getKey(), fileer); - } - - @Override public void startTask(AbsSubDLoadAdapter fileer) { - if (mExec.size() < mMaxExecSize) { - mCache.remove(fileer.getKey()); - mExec.put(fileer.getKey(), fileer); - ALog.d(TAG, - String.format("开始执行子任务:%s,key: %s", fileer.getEntity().getFileName(), fileer.getKey())); - fileer.run(); - return; - } - ALog.d(TAG, String.format("执行队列已满,任务进入缓存器中,key: %s", fileer.getKey())); - addTask(fileer); - } - - @Override public void stopTask(AbsSubDLoadAdapter fileer) { - fileer.stop(); - mExec.remove(fileer.getKey()); - } - - @Override public void stopAllTask() { - isStopAll = true; - ALog.d(TAG, "停止组合任务"); - mCache.clear(); - Set keys = mExec.keySet(); - for (String key : keys) { - AbsSubDLoadAdapter loader = mExec.get(key); - if (loader != null) { - ALog.d(TAG, String.format("停止子任务:%s", loader.getEntity().getFileName())); - loader.stop(); - } - } - } - - @Override public void modifyMaxExecNum(int num) { - if (num < 1) { - ALog.e(TAG, String.format("修改组合任务子任务队列数失败,num: %s", num)); - return; - } - if (num == mMaxExecSize) { - ALog.i(TAG, String.format("忽略此次修改,oldSize: %s, num: %s", mMaxExecSize, num)); - return; - } - int oldSize = mMaxExecSize; - mMaxExecSize = num; - int diff = Math.abs(oldSize - num); - - if (oldSize < num) { // 处理队列变小的情况,该情况下将停止队尾任务,并将这些任务添加到缓存队列中 - if (mExec.size() > num) { - Set keys = mExec.keySet(); - List caches = new ArrayList<>(); - int i = 0; - for (String key : keys) { - if (i > num) { - caches.add(mExec.get(key)); - } - i++; - } - Collection temp = mCache.values(); - mCache.clear(); - for (AbsSubDLoadAdapter cache : caches) { - addTask(cache); - } - for (AbsSubDLoadAdapter t : temp) { - addTask(t); - } - } - return; - } - // 处理队列变大的情况,该情况下将增加任务 - if (mExec.size() < num) { - for (int i = 0; i < diff; i++) { - AbsSubDLoadAdapter next = getNextTask(); - if (next != null) { - startTask(next); - } else { - ALog.d(TAG, "子任务中没有缓存任务"); - } - } - } - } - - @Override public void removeTaskFromExecQ(AbsSubDLoadAdapter fileer) { - mExec.remove(fileer.getKey()); - } - - @Override public void removeTask(AbsSubDLoadAdapter fileer) { - removeTaskFromExecQ(fileer); - mCache.remove(fileer.getKey()); - } - - @Override public void removeAllTask() { - ALog.d(TAG, "删除组合任务"); - Set keys = mExec.keySet(); - for (String key : keys) { - AbsSubDLoadAdapter loader = mExec.get(key); - if (loader != null) { - ALog.d(TAG, String.format("停止子任务:%s", loader.getEntity().getFileName())); - loader.cancel(); - } - } - } - - @Override public AbsSubDLoadAdapter getNextTask() { - Iterator keys = mCache.keySet().iterator(); - if (keys.hasNext()) { - return mCache.get(keys.next()); - } - return null; - } - - @Override public void clear() { - mCache.clear(); - mExec.clear(); - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/group/SimpleSubRetryQueue.java b/PublicComponent/src/main/java/com/arialyy/aria/core/group/SimpleSubRetryQueue.java deleted file mode 100644 index 3d8cb2c2..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/group/SimpleSubRetryQueue.java +++ /dev/null @@ -1,49 +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.group; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -/** - * 子任务重试队列 - */ -final class SimpleSubRetryQueue { - private volatile static SimpleSubRetryQueue INSTANCE = null; - private ExecutorService pool = new ThreadPoolExecutor(5, 100, - 60L, TimeUnit.SECONDS, - new SynchronousQueue()); - - public synchronized static SimpleSubRetryQueue getInstance() { - if (INSTANCE == null) { - synchronized (SimpleSubRetryQueue.class) { - INSTANCE = new SimpleSubRetryQueue(); - } - } - - return INSTANCE; - } - - private SimpleSubRetryQueue() { - - } - - void offer(AbsSubDLoadAdapter subDLoadUtil) { - pool.submit(subDLoadUtil.getLoader()); - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/group/SubRecordHandler.java b/PublicComponent/src/main/java/com/arialyy/aria/core/group/SubRecordHandler.java deleted file mode 100644 index 5d4021d0..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/group/SubRecordHandler.java +++ /dev/null @@ -1,108 +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.group; - -import com.arialyy.aria.core.TaskRecord; -import com.arialyy.aria.core.ThreadRecord; -import com.arialyy.aria.core.common.RecordHandler; -import com.arialyy.aria.core.common.RecordHelper; -import com.arialyy.aria.core.config.Configuration; -import com.arialyy.aria.core.download.DownloadEntity; -import com.arialyy.aria.core.loader.IRecordHandler; -import com.arialyy.aria.core.wrapper.AbsTaskWrapper; -import com.arialyy.aria.core.wrapper.ITaskWrapper; -import com.arialyy.aria.util.RecordUtil; -import java.util.ArrayList; - -/** - * 子任务记录处理 - */ -public class SubRecordHandler extends RecordHandler { - public SubRecordHandler(AbsTaskWrapper wrapper) { - super(wrapper); - } - - @Override public void handlerTaskRecord(TaskRecord record) { - RecordHelper helper = new RecordHelper(getWrapper(), record); - if (getWrapper().isSupportBP() && record.threadNum > 1) { - if (record.isBlock) { - helper.handleBlockRecord(); - } else { - helper.handleMultiRecord(); - } - } else if (!getWrapper().isSupportBP()) { - helper.handleNoSupportBPRecord(); - } else { - helper.handleSingleThreadRecord(); - } - } - - @Override - public ThreadRecord createThreadRecord(TaskRecord record, int threadId, long startL, long endL) { - ThreadRecord tr; - tr = new ThreadRecord(); - tr.taskKey = record.filePath; - tr.threadId = threadId; - tr.startLocation = startL; - tr.isComplete = false; - - tr.threadType = record.taskType; - //最后一个线程的结束位置即为文件的总长度 - if (threadId == (record.threadNum - 1)) { - endL = getFileSize(); - } - tr.endLocation = endL; - tr.blockLen = RecordUtil.getBlockLen(getFileSize(), threadId, record.threadNum); - return tr; - } - - @Override public TaskRecord createTaskRecord(int threadNum) { - TaskRecord record = new TaskRecord(); - record.fileName = getEntity().getFileName(); - record.filePath = getEntity().getFilePath(); - record.threadRecords = new ArrayList<>(); - record.threadNum = threadNum; - - int requestType = getWrapper().getRequestType(); - if (requestType == ITaskWrapper.D_HTTP || requestType == ITaskWrapper.DG_HTTP) { - record.isBlock = Configuration.getInstance().downloadCfg.isUseBlock(); - } else { - record.isBlock = false; - } - record.taskType = requestType; - record.isGroupRecord = getEntity().isGroupChild(); - if (record.isGroupRecord) { - if (getEntity() instanceof DownloadEntity) { - record.dGroupHash = ((DownloadEntity) getEntity()).getGroupHash(); - } - } - - return record; - } - - @Override public int initTaskThreadNum() { - int requestTpe = getWrapper().getRequestType(); - if (requestTpe == ITaskWrapper.U_HTTP - || (requestTpe == ITaskWrapper.D_HTTP && (!getWrapper().isSupportBP()) - )) { - return 1; - } - int threadNum = Configuration.getInstance().downloadCfg.getThreadNum(); - return getFileSize() <= IRecordHandler.SUB_LEN - ? 1 - : threadNum; - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/inf/IComponentLoader.kt b/PublicComponent/src/main/java/com/arialyy/aria/core/inf/IComponentLoader.kt index bb842e79..b8de48a2 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/inf/IComponentLoader.kt +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/inf/IComponentLoader.kt @@ -20,19 +20,12 @@ import com.arialyy.annotations.TaskEnum /** * @Author laoyuyu * @Description - * @Date 10:44 AM 2023/1/20 + * @Date 8:09 PM 2023/3/21 **/ interface IComponentLoader { - companion object { val proxyMethods = arrayOf("download", "upload") } - // fun upload() - - fun download(): T - -// fun upload(): T - fun getTaskEnum(): TaskEnum } \ No newline at end of file diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalLoader.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalLoader.java deleted file mode 100644 index 6ce461e9..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalLoader.java +++ /dev/null @@ -1,340 +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.loader; - -import android.os.Looper; -import android.util.Log; -import com.arialyy.aria.core.TaskRecord; -import com.arialyy.aria.core.inf.ITaskManager; -import com.arialyy.aria.core.listener.IEventListener; -import com.arialyy.aria.core.manager.ThreadTaskManager; -import com.arialyy.aria.core.task.IThreadTask; -import com.arialyy.aria.core.wrapper.AbsTaskWrapper; -import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CommonUtil; -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -/** - * Created by AriaL on 2017/7/1. - * 任务执行器,用于处理任务的开始,停止 - * 流程: - * 1、获取任务记录 - * 2、创建任务状态管理器,用于管理任务的状态 - * 3、创建文件信息获取器,获取文件信息,根据文件信息执行任务 - * 4、创建线程任务执行下载、上传操作 - */ -public abstract class AbsNormalLoader implements ILoaderVisitor, ILoader { - protected final String TAG = CommonUtil.getClassName(getClass()); - private IEventListener mListener; - protected T mTaskWrapper; - protected File mTempFile; - - private List mTask = new ArrayList<>(); - private ScheduledThreadPoolExecutor mTimer; - - /** - * 进度刷新间隔 - */ - private long mUpdateInterval = 1000; - protected TaskRecord mRecord; - protected boolean isCancel = false, isStop = false; - private boolean isRuning = false; - - protected IRecordHandler mRecordHandler; - protected ITaskManager mStateManager; - protected IInfoTask mInfoTask; - protected IThreadTaskBuilder mTTBuilder; - - protected AbsNormalLoader(T wrapper, IEventListener listener) { - mListener = listener; - mTaskWrapper = wrapper; - } - - /** - * 启动线程任务 - */ - protected abstract void handleTask(Looper looper); - - /** - * 获取文件长度 - */ - public abstract long getFileSize(); - - protected IEventListener getListener() { - return mListener; - } - - protected ITaskManager getStateManager() { - return mStateManager; - } - - public String getKey() { - return mTaskWrapper.getKey(); - } - - public List getTaskList() { - return mTask; - } - - /** - * 重置任务状态 - */ - private void resetState() { - closeTimer(); - if (mTask != null && mTask.size() != 0) { - for (int i = 0; i < mTask.size(); i++) { - mTask.get(i).breakTask(); - } - mTask.clear(); - } - } - - @Override public void run() { - checkComponent(); - if (isRunning()) { - ALog.d(TAG, String.format("任务【%s】正在执行,启动任务失败", mTaskWrapper.getKey())); - return; - } - startFlow(); - } - - /** - * 开始流程 - */ - private void startFlow() { - if (isBreak()) { - return; - } - Looper.prepare(); - Looper looper = Looper.myLooper(); - if (looper == Looper.getMainLooper()) { - throw new IllegalThreadStateException("不能在主线程程序中调用Loader"); - } - isRuning = true; - resetState(); - onPostPre(); - handleTask(looper); - Looper.loop(); - } - - /** - * 预处理完成 - */ - protected void onPostPre() { - - } - - /** - * 延迟启动定时器 - */ - protected long delayTimer() { - return 1000; - } - - /** - * 启动进度获取定时器 - */ - protected synchronized void startTimer() { - if (isBreak()) { - return; - } - ALog.d(TAG, String.format("启动定时器,delayTimer = %s, updateInterval = %s", delayTimer(), - mUpdateInterval)); - closeTimer(); - try { - mTimer = new ScheduledThreadPoolExecutor(1); - mTimer.scheduleWithFixedDelay(new Runnable() { - @Override public void run() { - // 线程池中是不抛异常的,没有日志,很难定位问题,需要手动try-catch - try { - if (mStateManager == null) { - ALog.e(TAG, "stateManager is null"); - } else if (mStateManager.isCompleted() - || mStateManager.hasFailedBlock() - || !isRunning() - || isBreak()) { - //ALog.d(TAG, "isComplete = " + mStateManager.isComplete() - // + "; isFail = " + mStateManager.isFail() - // + "; isRunning = " + isRunning() - // + "; isBreak = " + isBreak()); - ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey()); - closeTimer(); - onDestroy(); - } else if (mStateManager.getCurrentProgress() >= 0) { - Log.d(TAG, "running..."); - mListener.onProgress(mStateManager.getCurrentProgress()); - } else { - Log.d(TAG, "未知状态"); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - }, delayTimer(), mUpdateInterval, TimeUnit.MILLISECONDS); - } catch (Exception e) { - ALog.e(TAG, "启动定时器失败"); - e.printStackTrace(); - } - } - - private synchronized void closeTimer() { - if (mTimer != null && !mTimer.isShutdown()) { - mTimer.shutdown(); - } - } - - public void onDestroy() { - isRuning = false; - } - - /** - * 设置定时器更新间隔 - * - * @param interval 单位毫秒,不能小于0 - */ - protected void setUpdateInterval(long interval) { - if (interval < 0) { - ALog.w(TAG, "更新间隔不能小于0,默认为1000毫秒"); - return; - } - mUpdateInterval = interval; - } - - @Override - public synchronized boolean isRunning() { - boolean b = ThreadTaskManager.getInstance().taskIsRunning(mTaskWrapper.getKey()); - //ALog.d(TAG, "isRunning = " + b); - return b && isRuning; - } - - @Override final public synchronized void cancel() { - if (isCancel) { - ALog.d(TAG, String.format("任务【%s】正在删除,删除任务失败", mTaskWrapper.getKey())); - return; - } - if (mInfoTask != null){ - mInfoTask.cancel(); - } - closeTimer(); - isCancel = true; - onCancel(); - for (int i = 0; i < mTask.size(); i++) { - IThreadTask task = mTask.get(i); - if (task != null && !task.isThreadComplete()) { - task.cancel(); - } - } - ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey()); - onPostCancel(); - onDestroy(); - mListener.onCancel(); - } - - /** - * 删除线程任务前的操作 - */ - protected void onCancel() { - - } - - /** - * 删除操作处理完成 - */ - protected void onPostCancel() { - - } - - final public synchronized void stop() { - if (isStop) { - return; - } - if (mInfoTask != null){ - mInfoTask.stop(); - } - closeTimer(); - isStop = true; - onStop(); - for (int i = 0; i < mTask.size(); i++) { - IThreadTask task = mTask.get(i); - if (task != null && !task.isThreadComplete()) { - task.stop(); - } - } - ThreadTaskManager.getInstance().removeTaskThread(mTaskWrapper.getKey()); - onPostStop(); - onDestroy(); - mListener.onStop(getCurrentProgress()); - } - - /** - * 停止线程任务前的操作 - */ - protected void onStop() { - - } - - /** - * 停止操作完成 - */ - protected void onPostStop() { - - } - - /** - * 重试任务 - */ - public void retryTask() { - ALog.w(TAG, String.format("任务【%s】开始重试", mTaskWrapper.getKey())); - startFlow(); - } - - /** - * 任务是否已经中断 - * - * @return {@code true}中断 - */ - public boolean isBreak() { - if (isCancel || isStop) { - //closeTimer(); - ALog.d(TAG, "isCancel = " + isCancel + ", isStop = " + isStop); - ALog.d(TAG, String.format("任务【%s】已停止或取消了", mTaskWrapper.getKey())); - return true; - } - return false; - } - - /** - * 检查组件: {@link #mRecordHandler}、{@link #mInfoTask}、{@link #mStateManager}、{@link #mTTBuilder} - */ - protected void checkComponent() { - if (mRecordHandler == null) { - throw new NullPointerException("任务记录组件为空"); - } - if (mInfoTask == null) { - throw new NullPointerException(("文件信息组件为空")); - } - if (mStateManager == null) { - throw new NullPointerException("任务状态管理组件为空"); - } - if (mTTBuilder == null) { - throw new NullPointerException("线程任务组件为空"); - } - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalLoaderAdapter.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalLoaderAdapter.java deleted file mode 100644 index e982f040..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalLoaderAdapter.java +++ /dev/null @@ -1,153 +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.loader; - -import com.arialyy.aria.core.inf.ITaskAdapter; -import com.arialyy.aria.core.listener.IEventListener; -import com.arialyy.aria.core.wrapper.AbsTaskWrapper; -import com.arialyy.aria.exception.AriaException; -import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CommonUtil; - -/** - * Created by lyy on 2015/8/25. - * HTTP\FTP单任务下载工具 - */ -public abstract class AbsNormalLoaderAdapter implements ITaskAdapter { - protected String TAG = CommonUtil.getClassName(getClass()); - private IEventListener mListener; - protected AbsNormalLoader mLoader; - private AbsTaskWrapper mTaskWrapper; - private boolean isStop = false, isCancel = false; - - protected AbsNormalLoaderAdapter() { - } - - @Override public ITaskAdapter setParams(AbsTaskWrapper taskWrapper, IEventListener listener) { - mTaskWrapper = taskWrapper; - mListener = listener; - mLoader = getLoader(); - return this; - } - - /** - * 获取加载器 - */ - public abstract AbsNormalLoader getLoader(); - - /** - * 获取构造器 - */ - public abstract LoaderStructure BuildLoaderStructure(); - - @Override public String getKey() { - return mTaskWrapper.getKey(); - } - - @Override public long getFileSize() { - return mLoader.getFileSize(); - } - - /** - * 获取当前下载位置 - */ - @Override public long getCurrentLocation() { - return mLoader.getCurrentProgress(); - } - - @Override public boolean isRunning() { - return mLoader.isRunning(); - } - - /** - * 取消下载 - */ - @Override public void cancel() { - isCancel = true; - mLoader.cancel(); - onCancel(); - } - - protected void onCancel() { - - } - - /** - * 停止下载 - */ - @Override public void stop() { - isStop = true; - mLoader.stop(); - onStop(); - } - - protected void onStop() { - - } - - /** - * 多线程断点续传下载文件,开始下载 - */ - @Override public void start() { - if (isStop || isCancel) { - ALog.w(TAG, "启动任务失败,任务已停止或已取消"); - return; - } - mListener.onPre(); - // 如果网址没有变,而服务器端端文件改变,以下代码就没有用了 - //if (mTaskWrapper.getEntity().getFileSize() <= 1 - // || mTaskWrapper.isRefreshInfo() - // || mTaskWrapper.getRequestType() == AbsTaskWrapper.D_FTP - // || mTaskWrapper.getState() == IEntity.STATE_FAIL) { - // new Thread(createInfoThread()).create(); - //} else { - // mDownloader.create(); - //} - - BuildLoaderStructure(); - new Thread(mLoader).start(); - onStart(); - } - - protected void onStart() { - - } - - public boolean isStop() { - return isStop; - } - - public boolean isCancel() { - return isCancel; - } - - public IEventListener getListener() { - return mListener; - } - - protected void fail(AriaException e, boolean needRetry) { - if (isStop || isCancel) { - return; - } - mListener.onFail(needRetry, e); - mLoader.onDestroy(); - } - - public AbsTaskWrapper getTaskWrapper() { - return mTaskWrapper; - } -} \ No newline at end of file diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalTTBuilderAdapter.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalTTBuilderAdapter.java deleted file mode 100644 index 636c748a..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalTTBuilderAdapter.java +++ /dev/null @@ -1,90 +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.loader; - -import android.os.Handler; -import com.arialyy.aria.core.TaskRecord; -import com.arialyy.aria.core.ThreadRecord; -import com.arialyy.aria.core.common.AbsNormalEntity; -import com.arialyy.aria.core.common.SubThreadConfig; -import com.arialyy.aria.core.task.IThreadTaskAdapter; -import com.arialyy.aria.core.wrapper.AbsTaskWrapper; -import com.arialyy.aria.util.CommonUtil; -import java.io.File; - -public abstract class AbsNormalTTBuilderAdapter { - protected String TAG = CommonUtil.getClassName(this); - protected AbsTaskWrapper wrapper; - private File tempFile; - - public AbsNormalTTBuilderAdapter() { - } - - protected void setWrapper(AbsTaskWrapper wrapper) { - this.wrapper = wrapper; - tempFile = new File(((AbsNormalEntity) wrapper.getEntity()).getFilePath()); - } - - /** - * 创建线程任务适配器 - */ - public abstract IThreadTaskAdapter getAdapter(SubThreadConfig config); - - /** - * 处理新任务 - * - * @param record 任务记录 - * @param totalThreadNum 任务的线程总数 - * @return {@code true}创建新任务成功 - */ - public abstract boolean handleNewTask(TaskRecord record, int totalThreadNum); - - /** - * SubThreadConfig 模版,如果不使用该方法创建配置,则默认使用{@link #createNormalSubThreadConfig(Handler, ThreadRecord, - * boolean, int)}创建配置 - */ - protected SubThreadConfig getSubThreadConfig(Handler stateHandler, ThreadRecord threadRecord, - boolean isBlock, int startNum) { - return createNormalSubThreadConfig(stateHandler, threadRecord, isBlock, startNum); - } - - private SubThreadConfig createNormalSubThreadConfig(Handler stateHandler, - ThreadRecord threadRecord, - boolean isBlock, int startNum) { - SubThreadConfig config = new SubThreadConfig(); - config.url = getEntity().isRedirect() ? getEntity().getRedirectUrl() : getEntity().getUrl(); - config.tempFile = - isBlock ? new File( - String.format(IRecordHandler.SUB_PATH, tempFile.getPath(), threadRecord.threadId)) - : tempFile; - config.isBlock = isBlock; - config.startThreadNum = startNum; - config.taskWrapper = wrapper; - config.record = threadRecord; - config.stateHandler = stateHandler; - config.threadType = SubThreadConfig.getThreadType(wrapper.getRequestType()); - config.updateInterval = SubThreadConfig.getUpdateInterval(wrapper.getRequestType()); - return config; - } - - protected AbsNormalEntity getEntity() { - return (AbsNormalEntity) wrapper.getEntity(); - } - - protected File getTempFile() { - return tempFile; - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/GroupSubThreadStateManager.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/GroupSubThreadStateManager.java deleted file mode 100644 index a9884a4d..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/GroupSubThreadStateManager.java +++ /dev/null @@ -1,311 +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.loader; - -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; - -import com.arialyy.aria.core.TaskRecord; -import com.arialyy.aria.core.inf.ITaskManager; -import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CommonUtil; -import com.arialyy.aria.util.FileUtil; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * 线程任务管理器,用于处理多线程下载时任务的状态回调 - */ -public class GroupSubThreadStateManager implements ITaskManager { - private final String TAG = CommonUtil.getClassName(this); - - /** - * 任务状态回调 - */ - private Handler mHandler;//SimpleSchedulers - private int mThreadNum; // 启动的线程总数 - private AtomicInteger mCancelNum = new AtomicInteger(0); // 已经取消的线程的数 - private AtomicInteger mStopNum = new AtomicInteger(0); // 已经停止的线程数 - private AtomicInteger mFailNum = new AtomicInteger(0); // 失败的线程数 - private AtomicInteger mCompleteNum = new AtomicInteger(0); // 完成的线程数 - private long mProgress; //当前总进度 - private TaskRecord mTaskRecord; // 任务记录 - private Looper mLooper; - private String mKey; - /** - * @param handler 任务事件 - */ - public GroupSubThreadStateManager(Handler handler,String key) { - mHandler = handler; - mKey = key; - } - - @Override public void setLooper(TaskRecord taskRecord, Looper looper) { - mTaskRecord = taskRecord; - mThreadNum = mTaskRecord.threadNum; - mLooper = looper; - } - - private void checkLooper() { - if (mTaskRecord == null) { - throw new NullPointerException("任务记录为空"); - } - if (mLooper == null) { - throw new NullPointerException("Looper为空"); - } - } - - private Handler.Callback callback = new Handler.Callback() { - @Override public boolean handleMessage(Message msg) { - checkLooper(); - switch (msg.what) { - case STATE_STOP: - mStopNum.getAndIncrement(); - if (isStop()) { - quitLooper(); - } - sendMessageFromMsg(msg); - break; - case STATE_CANCEL: - mCancelNum.getAndIncrement(); - if (isCancel()) { - quitLooper(); - } - sendMessageFromMsg(msg); - break; - case STATE_FAIL: - mFailNum.getAndIncrement(); - if (hasFailedBlock()) { - sendMessageFromMsg(msg); - - /* Bundle b = msg.getData(); - mListener.onFail(b.getBoolean(DATA_RETRY, false), - (AriaException) b.getSerializable(DATA_ERROR_INFO));*/ - quitLooper(); - } - //sendMessageFromMsg(msg); - break; - case STATE_COMPLETE: - mCompleteNum.getAndIncrement(); - if (isCompleted()) { - ALog.d(TAG, "isComplete, completeNum = " + mCompleteNum); - //if (mTaskRecord.taskType == ITaskWrapper.D_SFTP) { - // mergerSFtp(); - // mListener.onComplete(); - //} else - - if (mTaskRecord.isBlock) { - /*if (mergeFile()) { - mListener.onComplete(); - } else { - mListener.onFail(false, null); - }*/ - if (!mergeFile()) { - Bundle b=msg.getData(); - b.putBoolean(ITaskManager.DATA_RETRY, false); - msg.setData(b); - msg.what = STATE_FAIL; - sendMessageFromMsg(msg); - } - sendMessageFromMsg(msg); - } else { - sendMessageFromMsg(msg); - //mListener.onComplete(); - } - quitLooper(); - }else if (hasFailedBlock()) { - sendMessageFromMsg(msg); - quitLooper(); - } - break; - case STATE_RUNNING: - Bundle b = msg.getData(); - if (b != null) { - long len = b.getLong(ITaskManager.DATA_ADD_LEN, 0); - mProgress += len; - } - msg.obj=mProgress; - sendMessageFromMsg(msg); - - break; - case STATE_UPDATE_PROGRESS: - - if (msg.obj == null) { - mProgress = updateBlockProgress(); - } else if (msg.obj instanceof Long) { - mProgress = (long) msg.obj; - } - msg.obj=mProgress; - sendMessageFromMsg(msg); - break; - } - return false; - } - public void sendMessageFromMsg(Message msg){ - Message mMsg=mHandler.obtainMessage(); - Bundle b=mMsg.getData(); - b.putString(ITaskManager.DATA_THREAD_NAME,mKey); - msg.setData(b); - mMsg.copyFrom(msg); - mHandler.sendMessage(mMsg); - } - }; - - @Override public void updateCurrentProgress(long currentProgress) { - mProgress = currentProgress; - } - - /** - * 退出looper循环 - */ - private void quitLooper() { - mLooper.quit(); - } - - /** - * 获取当前任务下载进度 - * - * @return 当前任务下载进度 - */ - @Override - public long getCurrentProgress() { - return mProgress; - } - - @Override public Handler.Callback getHandlerCallback() { - return callback; - } - - /** - * 所有子线程是否都已经停止 - */ - public boolean isStop() { - //ALog.d(TAG, - // String.format("isStop; stopNum: %s, cancelNum: %s, failNum: %s, completeNum: %s", mStopNum, - // mCancelNum, mFailNum, mCompleteNum)); - return mStopNum.get() == mThreadNum || mStopNum.get() + mCompleteNum.get() == mThreadNum; - } - - /** - * 所有子线程是否都已经失败 - */ - @Override - public boolean hasFailedBlock() { - //ALog.d(TAG, - // String.format("isFail; stopNum: %s, cancelNum: %s, failNum: %s, completeNum: %s", mStopNum, - // mCancelNum, mFailNum, mCompleteNum)); - return mCompleteNum.get() != mThreadNum - && (mFailNum.get() == mThreadNum || mFailNum.get() + mCompleteNum.get() == mThreadNum); - } - - /** - * 所有子线程是否都已经完成 - */ - @Override - public boolean isCompleted() { - //ALog.d(TAG, - // String.format("isComplete; stopNum: %s, cancelNum: %s, failNum: %s, completeNum: %s", - // mStopNum, - // mCancelNum, mFailNum, mCompleteNum)); - return mCompleteNum.get() == mThreadNum; - } - - /** - * 所有子线程是否都已经取消 - */ - public boolean isCancel() { - //ALog.d(TAG, String.format("isCancel; stopNum: %s, cancelNum: %s, failNum: %s, completeNum: %s", - // mStopNum, - // mCancelNum, mFailNum, mCompleteNum)); - return mCancelNum.get() == mThreadNum; - } - - /** - * 更新分块任务s的真实进度 - */ - private long updateBlockProgress() { - long size = 0; - for (int i = 0, len = mTaskRecord.threadRecords.size(); i < len; i++) { - File temp = new File(String.format(IRecordHandler.SUB_PATH, mTaskRecord.filePath, i)); - if (temp.exists()) { - size += temp.length(); - } - } - return size; - } - - /** - * 合并sftp的分块 - */ - private boolean mergerSFtp() { - if (mTaskRecord.threadNum == 1) { - File partFile = new File(String.format(IRecordHandler.SUB_PATH, mTaskRecord.filePath, 0)); - return partFile.renameTo(new File(mTaskRecord.filePath)); - } - - List partPath = new ArrayList<>(); - for (int i = 0, len = mTaskRecord.threadNum; i < len; i++) { - partPath.add(String.format(IRecordHandler.SUB_PATH, mTaskRecord.filePath, i)); - } - FileUtil.mergeSFtpFile(mTaskRecord.filePath, partPath, mTaskRecord.fileLength); - for (String pp : partPath) { - FileUtil.deleteFile(pp); - } - return true; - } - - /** - * 合并文件 - * - * @return {@code true} 合并成功,{@code false}合并失败 - */ - private boolean mergeFile() { - if (mTaskRecord.threadNum == 1) { - File partFile = new File(String.format(IRecordHandler.SUB_PATH, mTaskRecord.filePath, 0)); - return partFile.renameTo(new File(mTaskRecord.filePath)); - } - - List partPath = new ArrayList<>(); - for (int i = 0, len = mTaskRecord.threadNum; i < len; i++) { - partPath.add(String.format(IRecordHandler.SUB_PATH, mTaskRecord.filePath, i)); - } - boolean isSuccess = FileUtil.mergeFile(mTaskRecord.filePath, partPath); - if (isSuccess) { - for (String pp : partPath) { - FileUtil.deleteFile(pp); - } - File targetFile = new File(mTaskRecord.filePath); - if (targetFile.exists() && targetFile.length() > mTaskRecord.fileLength) { - ALog.e(TAG, String.format("任务【%s】分块文件合并失败,下载长度超出文件真实长度,downloadLen: %s,fileSize: %s", - targetFile.getName(), targetFile.length(), mTaskRecord.fileLength)); - return false; - } - return true; - } else { - ALog.e(TAG, "合并失败"); - return false; - } - } - - @Override public void accept(ILoaderVisitor visitor) { - visitor.addComponent(this); - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/IInfoTask.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/IInfoTask.java deleted file mode 100644 index 70a532e4..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/IInfoTask.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.arialyy.aria.core.loader; - -import com.arialyy.aria.core.common.AbsEntity; -import com.arialyy.aria.core.common.CompleteInfo; -import com.arialyy.aria.exception.AriaException; - -/** - * 任务信息采集 - */ -public interface IInfoTask extends ILoaderComponent { - - /** - * 执行任务 - */ - void run(); - - /** - * 设置回调 - */ - void setCallback(Callback callback); - - /** - * 任务停止 - */ - void stop(); - - /** - * 任务取消 - */ - void cancel(); - - interface Callback { - /** - * 处理完成 - * - * @param info 一些回调的信息 - */ - void onSucceed(String key, CompleteInfo info); - - /** - * 请求失败 - * - * @param e 错误信息 - */ - void onFail(AbsEntity entity, AriaException e, boolean needRetry); - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/ILoader.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/ILoader.java deleted file mode 100644 index 42895716..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/ILoader.java +++ /dev/null @@ -1,43 +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.loader; - -public interface ILoader extends Runnable { - - //void start(); - - /** - * 任务是否在执行 - * - * @return true 任务执行中 - */ - boolean isRunning(); - - void cancel(); - - void stop(); - - /** - * 任务是否被中断(停止,取消) - * - * @return true 任务中断,false 任务没有中断 - */ - boolean isBreak(); - - String getKey(); - - long getCurrentProgress(); -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/ILoaderAdapter.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/ILoaderAdapter.java deleted file mode 100644 index 004d592e..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/ILoaderAdapter.java +++ /dev/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.loader; - -import com.arialyy.aria.core.TaskRecord; -import com.arialyy.aria.core.task.IThreadTask; -import com.arialyy.aria.core.wrapper.AbsTaskWrapper; -import com.arialyy.aria.core.common.SubThreadConfig; - -/** - * @author lyy - * Date: 2019-09-18 - */ -public interface ILoaderAdapter { - - /** - * 处理新任务 - * - * @param record 任务记录 - * @param totalThreadNum 任务的线程总数 - * @return {@code true}创建新任务成功 - */ - boolean handleNewTask(TaskRecord record, int totalThreadNum); - - /** - * 创建线程任务 - */ - IThreadTask createThreadTask(SubThreadConfig config); - - /** - * 处理任务记录 - */ - IRecordHandler recordHandler(AbsTaskWrapper wrapper); -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/ILoaderVisitor.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/ILoaderVisitor.java deleted file mode 100644 index 72e6ecb0..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/ILoaderVisitor.java +++ /dev/null @@ -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.loader; - -import com.arialyy.aria.core.inf.ITaskManager; - -/** - * 加载器访问者 - */ -public interface ILoaderVisitor { - - /** - * 处理任务记录 - */ - void addComponent(IRecordHandler recordHandler); - - /** - * 处理任务的文件信息 - */ - void addComponent(IInfoTask infoTask); - - /** - * 线程状态 - */ - void addComponent(ITaskManager threadState); - - /** - * 构造线程任务 - */ - void addComponent(IThreadTaskBuilder builder); -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/IRecordHandler.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/IRecordHandler.java deleted file mode 100644 index c7c77329..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/IRecordHandler.java +++ /dev/null @@ -1,87 +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.loader; - -import com.arialyy.aria.core.TaskRecord; -import com.arialyy.aria.core.ThreadRecord; - -/** - * @author lyy - * Date: 2019-09-18 - */ -public interface IRecordHandler extends ILoaderComponent { - - int TYPE_DOWNLOAD = 1; - int TYPE_UPLOAD = 2; - int TYPE_M3U8_VOD = 3; - int TYPE_M3U8_LIVE = 4; - - String STATE = "_state_"; - String RECORD = "_record_"; - /** - * 小于1m的文件不启用多线程 - */ - long SUB_LEN = 1024 * 1024; - - /** - * 分块文件路径,文件路径.线程id.part - */ - String SUB_PATH = "%s.%s.part"; - - /** - * 获取任务记录 - */ - TaskRecord getRecord(long fileSize); - - /** - * 记录处理前的操作,可用来删除任务记录 - */ - void onPre(); - - /** - * 处理任务记录 - */ - void handlerTaskRecord(TaskRecord record); - - /** - * 处理线程任务 - * - * @param record 任务记录 - * @param threadId 线程id - * @param startL 线程开始位置 - * @param endL 线程结束位置 - */ - ThreadRecord createThreadRecord(TaskRecord record, int threadId, long startL, long endL); - - /** - * 新任务创建任务记录 - */ - TaskRecord createTaskRecord(int threadNum); - - /** - * 配置新任务的线程数 - * - * @return 新任务的线程数 - */ - int initTaskThreadNum(); - - /** - * 检查任务是否已完成 - * - * @return true 任务已完成 - */ - boolean checkTaskCompleted(); -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/IThreadTaskBuilder.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/IThreadTaskBuilder.java deleted file mode 100644 index 2d3b9dd0..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/IThreadTaskBuilder.java +++ /dev/null @@ -1,37 +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.loader; - -import android.os.Handler; -import com.arialyy.aria.core.TaskRecord; -import com.arialyy.aria.core.task.IThreadTask; -import java.util.List; - -/** - * 线程任务构造器 - */ -public interface IThreadTaskBuilder extends ILoaderComponent { - - /** - * 构造线程任务 - */ - List buildThreadTask(TaskRecord record, Handler stateHandler); - - /** - * 获取创建的线程任务数,需要先调用{@link #buildThreadTask(TaskRecord, Handler)}方法才能获取创建的线程任务数 - */ - int getCreatedThreadNum(); -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/LoaderStructure.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/LoaderStructure.java deleted file mode 100644 index 94bbf8b7..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/LoaderStructure.java +++ /dev/null @@ -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.core.loader; - -import com.arialyy.aria.core.inf.ITaskManager; -import java.util.ArrayList; -import java.util.List; - -public class LoaderStructure { - private List parts = new ArrayList<>(); - - public void accept(ILoaderVisitor visitor) { - - for (ILoaderComponent part : parts) { - part.accept(visitor); - } - } - - /** - * 将组件加入到集合,必须添加以下集合: - * 1 {@link IRecordHandler} - * 2 {@link IInfoTask} - * 3 {@link ITaskManager} - * 4 {@link IThreadTaskBuilder} - * - * @param component 待添加的组件 - */ - public LoaderStructure addComponent(ILoaderComponent component) { - parts.add(component); - return this; - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/NormalLoader.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/NormalLoader.java deleted file mode 100644 index c2cec32e..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/NormalLoader.java +++ /dev/null @@ -1,169 +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.loader; - -import android.os.Handler; -import android.os.Looper; -import com.arialyy.aria.core.common.AbsEntity; -import com.arialyy.aria.core.common.AbsNormalEntity; -import com.arialyy.aria.core.common.CompleteInfo; -import com.arialyy.aria.core.event.EventMsgUtil; -import com.arialyy.aria.core.inf.ITaskManager; -import com.arialyy.aria.core.listener.IDLoadListener; -import com.arialyy.aria.core.listener.IEventListener; -import com.arialyy.aria.core.manager.ThreadTaskManager; -import com.arialyy.aria.core.task.IThreadTask; -import com.arialyy.aria.core.wrapper.AbsTaskWrapper; -import com.arialyy.aria.exception.AriaException; -import com.arialyy.aria.util.FileUtil; -import java.io.File; - -/** - * 单文件 - */ -public class NormalLoader extends AbsNormalLoader { - private int startThreadNum; //启动的线程数 - protected boolean isComplete = false; - private Looper looper; - - public NormalLoader(T wrapper, IEventListener listener) { - super(wrapper, listener); - mTempFile = new File(getEntity().getFilePath()); - EventMsgUtil.getDefault().register(this); - setUpdateInterval(wrapper.getConfig().getUpdateInterval()); - } - - public AbsNormalEntity getEntity() { - return (AbsNormalEntity) mTaskWrapper.getEntity(); - } - - @Override public long getFileSize() { - return getEntity().getFileSize(); - } - - /** - * 设置最大下载/上传速度AbsFtpInfoThread - * - * @param maxSpeed 单位为:kb - */ - protected void setMaxSpeed(int maxSpeed) { - for (IThreadTask threadTask : getTaskList()) { - if (threadTask != null && startThreadNum > 0) { - threadTask.setMaxSpeed(maxSpeed / startThreadNum); - } - } - } - - @Override public void onDestroy() { - super.onDestroy(); - EventMsgUtil.getDefault().unRegister(this); - } - - ///** - // * 如果使用"Content-Disposition"中的文件名,需要更新{@link #mTempFile}的路径 - // */ - //public void updateTempFile() { - // if (!mTempFile.getPath().equals(getEntity().getFilePath())) { - // boolean b = mTempFile.renameTo(new File(getEntity().getFilePath())); - // ALog.d(TAG, String.format("更新tempFile文件名%s", b ? "成功" : "失败")); - // } - //} - - protected Looper getLooper() { - return looper; - } - - /** - * 启动单线程任务 - */ - @Override - public void handleTask(Looper looper) { - if (isBreak() || isComplete) { - return; - } - this.looper = looper; - mInfoTask.run(); - } - - protected void startThreadTask() { - if (isBreak()){ - return; - } - - if (getListener() instanceof IDLoadListener) { - ((IDLoadListener) getListener()).onPostPre(getEntity().getFileSize()); - } - File file = new File(getEntity().getFilePath()); - if (file.getParentFile() != null && !file.getParentFile().exists()) { - FileUtil.createDir(file.getPath()); - } - // 处理记录、初始化状态管理器 - mRecord = mRecordHandler.getRecord(getFileSize()); - mStateManager.setLooper(mRecord, looper); - getTaskList().addAll(mTTBuilder.buildThreadTask(mRecord, - new Handler(looper, mStateManager.getHandlerCallback()))); - startThreadNum = mTTBuilder.getCreatedThreadNum(); - - mStateManager.updateCurrentProgress(getEntity().getCurrentProgress()); - if (mStateManager.getCurrentProgress() > 0) { - getListener().onResume(mStateManager.getCurrentProgress()); - } else { - getListener().onStart(mStateManager.getCurrentProgress()); - } - - // 启动线程任务 - for (IThreadTask threadTask : getTaskList()) { - ThreadTaskManager.getInstance().startThread(mTaskWrapper.getKey(), threadTask); - } - - // 启动定时器 - startTimer(); - } - - @Override public long getCurrentProgress() { - return isRunning() ? mStateManager.getCurrentProgress() : getEntity().getCurrentProgress(); - } - - @Override public void addComponent(IRecordHandler recordHandler) { - mRecordHandler = recordHandler; - if (recordHandler.checkTaskCompleted()) { - mRecord.deleteData(); - isComplete = true; - getListener().onComplete(); - } - } - - @Override public void addComponent(IInfoTask infoTask) { - mInfoTask = infoTask; - infoTask.setCallback(new IInfoTask.Callback() { - @Override public void onSucceed(String key, CompleteInfo info) { - startThreadTask(); - } - - @Override public void onFail(AbsEntity entity, AriaException e, boolean needRetry) { - getListener().onFail(needRetry, e); - } - }); - } - - @Override public void addComponent(ITaskManager threadState) { - mStateManager = threadState; - } - - @Override public void addComponent(IThreadTaskBuilder builder) { - mTTBuilder = builder; - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/NormalTTBuilder.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/NormalTTBuilder.java deleted file mode 100644 index 782a0d94..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/NormalTTBuilder.java +++ /dev/null @@ -1,166 +0,0 @@ -package com.arialyy.aria.core.loader; - -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import com.arialyy.aria.core.TaskRecord; -import com.arialyy.aria.core.ThreadRecord; -import com.arialyy.aria.core.common.AbsNormalEntity; -import com.arialyy.aria.core.common.SubThreadConfig; -import com.arialyy.aria.core.download.DGTaskWrapper; -import com.arialyy.aria.core.inf.ITaskManager; -import com.arialyy.aria.core.task.IThreadTask; -import com.arialyy.aria.core.task.ThreadTask; -import com.arialyy.aria.core.wrapper.AbsTaskWrapper; -import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CommonUtil; -import java.util.ArrayList; -import java.util.List; - -public final class NormalTTBuilder implements IThreadTaskBuilder { - protected String TAG = CommonUtil.getClassName(this); - - private Handler mStateHandler; - private AbsTaskWrapper mWrapper; - private TaskRecord mRecord; - private int mTotalThreadNum; - private int mStartThreadNum; - private AbsNormalTTBuilderAdapter mAdapter; - - public NormalTTBuilder(AbsTaskWrapper wrapper, AbsNormalTTBuilderAdapter adapter) { - if (wrapper instanceof DGTaskWrapper) { - throw new AssertionError("NormalTTBuilder 不适用于组合任务"); - } - mWrapper = wrapper; - mAdapter = adapter; - mAdapter.setWrapper(wrapper); - } - - protected AbsNormalEntity getEntity() { - return (AbsNormalEntity) mWrapper.getEntity(); - } - - public AbsNormalTTBuilderAdapter getAdapter() { - return mAdapter; - } - - /** - * 创建线程任务 - */ - private IThreadTask createThreadTask(SubThreadConfig config) { - ThreadTask task = new ThreadTask(config); - task.setAdapter(mAdapter.getAdapter(config)); - return task; - } - - /** - * 启动断点任务时,创建单线程任务 - * - * @param record 线程记录 - * @param startNum 启动的线程数 - */ - private IThreadTask createSingThreadTask(ThreadRecord record, int startNum) { - return createThreadTask( - mAdapter.getSubThreadConfig(mStateHandler, record, mRecord.isBlock, startNum)); - } - - /** - * 处理不支持断点的任务 - */ - private List handleNoSupportBP() { - List list = new ArrayList<>(); - mStartThreadNum = 1; - mRecord.isBlock = false; - mRecord.update(); - IThreadTask task = createSingThreadTask(mRecord.threadRecords.get(0), 1); - list.add(task); - return list; - } - - /** - * 处理支持断点的任务 - */ - private List handleBreakpoint() { - long fileLength = getEntity().getFileSize(); - long blockSize = fileLength / mTotalThreadNum; - long currentProgress = 0; - List threadTasks = new ArrayList<>(mTotalThreadNum); - - mRecord.fileLength = fileLength; - if (mWrapper.isNewTask() && !mAdapter.handleNewTask(mRecord, mTotalThreadNum)) { - ALog.e(TAG, "初始化线程任务失败"); - return null; - } - - for (ThreadRecord tr : mRecord.threadRecords) { - if (!tr.isComplete) { - mStartThreadNum++; - } - } - - for (int i = 0; i < mTotalThreadNum; i++) { - long startL = i * blockSize, endL = (i + 1) * blockSize; - ThreadRecord tr = mRecord.threadRecords.get(i); - - if (tr.isComplete) {//该线程已经完成 - currentProgress += endL - startL; - ALog.d(TAG, String.format("任务【%s】线程__%s__已完成", mWrapper.getKey(), i)); - Message msg = mStateHandler.obtainMessage(); - msg.what = ITaskManager.STATE_COMPLETE; - Bundle b = msg.getData(); - if (b == null) { - b = new Bundle(); - } - b.putString(ITaskManager.DATA_THREAD_NAME, - CommonUtil.getThreadName(getEntity().getKey(), tr.threadId)); - msg.setData(b); - msg.sendToTarget(); - continue; - } - - //如果有记录,则恢复任务 - long r = tr.startLocation; - //记录的位置需要在线程区间中 - if (startL < r && r <= (i == (mTotalThreadNum - 1) ? fileLength : endL)) { - currentProgress += r - startL; - } - ALog.d(TAG, String.format("任务【%s】线程__%s__恢复任务", getEntity().getFileName(), i)); - - IThreadTask task = createSingThreadTask(tr, mStartThreadNum); - if (task == null) { - ALog.e(TAG, "创建线程任务失败"); - return null; - } - threadTasks.add(task); - } - if (currentProgress != getEntity().getCurrentProgress()) { - ALog.d(TAG, String.format("进度修正,当前进度:%s", currentProgress)); - getEntity().setCurrentProgress(currentProgress); - } - //mStateManager.updateProgress(currentProgress); - return threadTasks; - } - - private List handleTask() { - if (mWrapper.isSupportBP()) { - return handleBreakpoint(); - } else { - return handleNoSupportBP(); - } - } - - @Override public List buildThreadTask(TaskRecord record, Handler stateHandler) { - mRecord = record; - mStateHandler = stateHandler; - mTotalThreadNum = mRecord.threadNum; - return handleTask(); - } - - @Override public int getCreatedThreadNum() { - return mStartThreadNum; - } - - @Override public void accept(ILoaderVisitor visitor) { - visitor.addComponent(this); - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/SubLoader.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/SubLoader.java deleted file mode 100644 index f205bcae..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/SubLoader.java +++ /dev/null @@ -1,291 +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.loader; - -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.text.TextUtils; -import com.arialyy.aria.core.TaskRecord; -import com.arialyy.aria.core.common.AbsEntity; -import com.arialyy.aria.core.common.CompleteInfo; -import com.arialyy.aria.core.inf.ITaskManager; -import com.arialyy.aria.core.manager.ThreadTaskManager; -import com.arialyy.aria.core.task.IThreadTask; -import com.arialyy.aria.core.task.ThreadTask; -import com.arialyy.aria.core.wrapper.AbsTaskWrapper; -import com.arialyy.aria.exception.AriaException; -import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CommonUtil; -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -/** - * 子任务加载器 - */ -public final class SubLoader implements ILoader, ILoaderVisitor { - private String TAG = CommonUtil.getClassName(this); - // 是否需要获取信息 - private boolean needGetInfo = true; - private Handler schedulers; - private boolean isCancel = false, isStop = false; - private AbsTaskWrapper wrapper; - private IInfoTask infoTask; - private IThreadTaskBuilder ttBuild; - private IRecordHandler recordHandler; - private List mTask = new ArrayList<>(); - private String parentKey; - private TaskRecord record; - protected ITaskManager mStateManager; - - public SubLoader(AbsTaskWrapper wrapper, Handler schedulers) { - this.wrapper = wrapper; - this.schedulers = schedulers; - } - - public AbsTaskWrapper getWrapper() { - return wrapper; - } - - /** - * 发送状态到调度器 - * - * @param state {@link ITaskManager} - */ - private void sendNormalState(int state) { - Message msg = schedulers.obtainMessage(); - Bundle b = msg.getData(); - if (b == null) { - b = new Bundle(); - } - b.putString(ITaskManager.DATA_THREAD_NAME, getKey()); - msg.what = state; - msg.setData(b); - msg.sendToTarget(); - } - - /** - * 发送失败的状态 - */ - private void sendFailState(boolean needRetry) { - Message msg = schedulers.obtainMessage(); - Bundle b = msg.getData(); - if (b == null) { - b = new Bundle(); - } - b.putString(ITaskManager.DATA_THREAD_NAME, getKey()); - b.putBoolean(ITaskManager.DATA_RETRY, needRetry); - msg.what = ITaskManager.STATE_FAIL; - msg.setData(b); - msg.sendToTarget(); - } - - private void handlerTask() { - if (isBreak()) { - return; - } - Looper looper = Looper.myLooper(); - if (looper == null) { - Looper.prepare(); - looper = Looper.myLooper(); - } - - record = recordHandler.getRecord(wrapper.getEntity().getFileSize()); - if (record == null) { - ALog.d(TAG, "子任务记录为空"); - sendFailState(false); - return; - } - if (record.threadRecords != null - && !TextUtils.isEmpty(record.filePath) - && new File(record.filePath).exists() - && !record.threadRecords.isEmpty() - && record.threadRecords.get(0).isComplete) { - ALog.d(TAG, "子任务已完成,key:" + wrapper.getKey()); - sendNormalState(ITaskManager.STATE_COMPLETE); - return; - } - List task = - ttBuild.buildThreadTask(record, new Handler(looper, mStateManager.getHandlerCallback())); - mStateManager.setLooper(record, looper); - if (task == null || task.isEmpty()) { - ALog.e(TAG, "创建子任务的线程任务失败,key:" + wrapper.getKey()); - sendFailState(false); - return; - } - if (TextUtils.isEmpty(parentKey)) { - ALog.e(TAG, "parentKey为空"); - sendFailState(false); - return; - } - - sendNormalState(ITaskManager.STATE_PRE); - mTask.addAll(task); - try { - for (IThreadTask iThreadTask : mTask) { - ThreadTaskManager.getInstance().startThread(parentKey, iThreadTask); - } - - sendNormalState(ITaskManager.STATE_START); - - mStateManager.updateCurrentProgress(getWrapper().getEntity().getCurrentProgress()); - } catch (Exception e) { - e.printStackTrace(); - } - Looper.loop(); - } - - public TaskRecord getRecord() { - return record; - } - - public void setParentKey(String parentKey) { - this.parentKey = parentKey; - } - - public void setNeedGetInfo(boolean needGetInfo) { - this.needGetInfo = needGetInfo; - } - - public void retryTask() { - try { - if (!mTask.isEmpty()) { - for (IThreadTask iThreadTask : mTask) { - iThreadTask.call(); - } - return; - } - ALog.e(TAG, "子任务的线程任务为空"); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Override public void stop() { - if (isStop) { - ALog.w(TAG, "子任务已停止"); - return; - } - isStop = true; - if (infoTask != null){ - infoTask.stop(); - } - for (IThreadTask iThreadTask : mTask) { - iThreadTask.stop(); - } - } - - @Override public boolean isRunning() { - if (mTask.isEmpty()) { - return false; - } - for (IThreadTask iThreadTask : mTask) { - if (!iThreadTask.isBreak()) return true; - } - return false; - } - - @Override public void cancel() { - if (isCancel) { - ALog.w(TAG, "子任务已取消"); - return; - } - isCancel = true; - if (infoTask != null){ - infoTask.cancel(); - } - for (IThreadTask iThreadTask : mTask) { - iThreadTask.cancel(); - } - } - - @Override public boolean isBreak() { - if (isCancel || isStop) { - ALog.d(TAG, "isCancel = " + isCancel + ", isStop = " + isStop); - ALog.d(TAG, String.format("任务【%s】已停止或取消了", wrapper.getKey())); - return true; - } - return false; - } - - /** - * 线程名,一个子任务的loader只有一个线程,使用线程名标示key - * - * @return {@link ThreadTask#getThreadName()} - */ - @Override public String getKey() { - return CommonUtil.getThreadName(wrapper.getKey(), 0); - } - - @Override public long getCurrentProgress() { - return isRunning() ? mStateManager.getCurrentProgress() - : getWrapper().getEntity().getCurrentProgress(); - } - - @Override public void addComponent(IRecordHandler recordHandler) { - this.recordHandler = recordHandler; - } - - @Override public void addComponent(IInfoTask infoTask) { - this.infoTask = infoTask; - infoTask.setCallback(new IInfoTask.Callback() { - @Override public void onSucceed(String key, CompleteInfo info) { - handlerTask(); - } - - @Override public void onFail(AbsEntity entity, AriaException e, boolean needRetry) { - sendFailState(needRetry); - } - }); - } - - @Override public void addComponent(ITaskManager threadState) { - mStateManager = threadState; - } - - @Override public void addComponent(IThreadTaskBuilder builder) { - ttBuild = builder; - } - - @Override public void run() { - checkComponent(); - if (isBreak()) { - return; - } - if (needGetInfo) { - infoTask.run(); - return; - } - handlerTask(); - } - - /** - * 检查组件: {@link #recordHandler}、{@link #infoTask}、{@link #ttBuild} - */ - private void checkComponent() { - if (recordHandler == null) { - throw new NullPointerException("任务记录组件为空"); - } - if (infoTask == null) { - throw new NullPointerException(("文件信息组件为空")); - } - if (ttBuild == null) { - throw new NullPointerException("线程任务组件为空"); - } - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/SubTTBuilder.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/SubTTBuilder.java deleted file mode 100644 index 8ec3fe15..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/SubTTBuilder.java +++ /dev/null @@ -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.loader; - -import android.os.Handler; -import com.arialyy.aria.core.TaskRecord; -import com.arialyy.aria.core.task.IThreadTask; -import java.util.List; - -public class SubTTBuilder implements IThreadTaskBuilder{ - - - - @Override public List buildThreadTask(TaskRecord record, Handler stateHandler) { - return null; - } - - @Override public int getCreatedThreadNum() { - return 1; - } - - @Override public void accept(ILoaderVisitor visitor) { - visitor.addComponent(this); - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/TaskThreadStateManager.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/TaskThreadStateManager.java deleted file mode 100644 index c1521f8c..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/TaskThreadStateManager.java +++ /dev/null @@ -1,259 +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.loader; - -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import com.arialyy.aria.core.inf.ITaskManager; -import com.arialyy.aria.core.listener.IEventListener; -import com.arialyy.aria.exception.AriaException; -import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.FileUtil; -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; -import timber.log.Timber; - -/** - * 线程任务管理器,用于处理多线程下载时任务的状态回调 - */ -public class TaskThreadStateManager implements ITaskManager { - /** - * 分块文件路径: 文件路径.blockId.part - */ - public static String SUB_PATH = "%s.%s.part"; - /** - * 任务状态回调 - */ - private final IEventListener mListener; - private final int mThreadNum; // 启动的线程总数 - private final AtomicInteger mCancelNum = new AtomicInteger(0); // 已经取消的线程的数 - private final AtomicInteger mStopNum = new AtomicInteger(0); // 已经停止的线程数 - private final AtomicInteger mFailNum = new AtomicInteger(0); // 失败的线程数 - private final AtomicInteger mCompleteNum = new AtomicInteger(0); // 完成的线程数 - private long mProgress; //当前总进度 - private Looper mLooper; - - /** - * @param listener 任务事件 - */ - public TaskThreadStateManager(IEventListener listener, int threadNum) { - mListener = listener; - mThreadNum = threadNum; - } - - @Override public void setLooper(Looper looper) { - mLooper = looper; - } - - private void checkLooper() { - if (mLooper == null) { - throw new NullPointerException("Looper为空"); - } - } - - private final Handler.Callback callback = new Handler.Callback() { - @Override public boolean handleMessage(Message msg) { - checkLooper(); - switch (msg.what) { - case STATE_STOP: - mStopNum.getAndIncrement(); - if (isStop()) { - quitLooper(); - } - break; - case STATE_CANCEL: - mCancelNum.getAndIncrement(); - if (isCancel()) { - quitLooper(); - } - break; - case STATE_FAIL: - mFailNum.getAndIncrement(); - if (hasFailedBlock()) { - Bundle b = msg.getData(); - mListener.onFail(b.getBoolean(DATA_RETRY, false), - (AriaException) b.getSerializable(DATA_ERROR_INFO)); - quitLooper(); - } - break; - case STATE_COMPLETE: - mCompleteNum.getAndIncrement(); - if (isCompleted()) { - Timber.d("isComplete, completeNum = %s", mCompleteNum); - if (mTaskRecord.isBlock || mTaskRecord.threadNum == 1) { - if (mergeFile()) { - mListener.onComplete(); - } else { - mListener.onFail(false, null); - } - quitLooper(); - break; - } - mListener.onComplete(); - quitLooper(); - } - break; - case STATE_RUNNING: - Bundle b = msg.getData(); - if (b != null) { - long len = b.getLong(ITaskManager.DATA_ADD_LEN, 0); - mProgress += len; - } - - break; - case STATE_UPDATE_PROGRESS: - if (msg.obj == null) { - mProgress = updateBlockProgress(); - } else if (msg.obj instanceof Long) { - mProgress = (long) msg.obj; - } - break; - } - return false; - } - }; - - @Override public void updateCurrentProgress(long currentProgress) { - mProgress = currentProgress; - } - - /** - * 退出looper循环 - */ - private void quitLooper() { - mLooper.quit(); - } - - /** - * 获取当前任务下载进度 - * - * @return 当前任务下载进度 - */ - @Override - public long getCurrentProgress() { - return mProgress; - } - - @Override public Handler.Callback getHandlerCallback() { - return callback; - } - - /** - * 所有子线程是否都已经停止 - */ - public boolean isStop() { - //ALog.d(TAG, - // String.format("isStop; stopNum: %s, cancelNum: %s, failNum: %s, completeNum: %s", mStopNum, - // mCancelNum, mFailNum, mCompleteNum)); - return mStopNum.get() == mThreadNum || mStopNum.get() + mCompleteNum.get() == mThreadNum; - } - - /** - * 所有子线程是否都已经失败 - */ - @Override - public boolean hasFailedBlock() { - //ALog.d(TAG, - // String.format("isFail; stopNum: %s, cancelNum: %s, failNum: %s, completeNum: %s", mStopNum, - // mCancelNum, mFailNum, mCompleteNum)); - return mCompleteNum.get() != mThreadNum - && (mFailNum.get() == mThreadNum || mFailNum.get() + mCompleteNum.get() == mThreadNum); - } - - /** - * 所有子线程是否都已经完成 - */ - @Override - public boolean isCompleted() { - //ALog.d(TAG, - // String.format("isComplete; stopNum: %s, cancelNum: %s, failNum: %s, completeNum: %s", - // mStopNum, - // mCancelNum, mFailNum, mCompleteNum)); - return mCompleteNum.get() == mThreadNum; - } - - /** - * 所有子线程是否都已经取消 - */ - public boolean isCancel() { - //ALog.d(TAG, String.format("isCancel; stopNum: %s, cancelNum: %s, failNum: %s, completeNum: %s", - // mStopNum, - // mCancelNum, mFailNum, mCompleteNum)); - return mCancelNum.get() == mThreadNum; - } - - /** - * 更新分块任务s的真实进度 - */ - private long updateBlockProgress() { - long size = 0; - for (int i = 0, len = mTaskRecord.threadRecords.size(); i < len; i++) { - File temp = new File(String.format(IRecordHandler.SUB_PATH, mTaskRecord.filePath, i)); - if (temp.exists()) { - size += temp.length(); - } - } - return size; - } - - /** - * 合并文件 - * - * @return {@code true} 合并成功,{@code false}合并失败 - */ - private boolean mergeFile() { - if (mTaskRecord.threadNum == 1) { - File targetFile = new File(mTaskRecord.filePath); - if (targetFile.exists()) { - //没有获得文件长度:不支持断点续传 - if (mTaskRecord.fileLength == 0 && targetFile.length() != 0) { - return true; - } - if (targetFile.length() != 0 && targetFile.length() == mTaskRecord.fileLength) { - return true; - } - } - FileUtil.deleteFile(targetFile); - File partFile = new File(String.format(IRecordHandler.SUB_PATH, mTaskRecord.filePath, 0)); - return partFile.renameTo(targetFile); - } - - List partPath = new ArrayList<>(); - for (int i = 0, len = mTaskRecord.threadNum; i < len; i++) { - partPath.add(String.format(IRecordHandler.SUB_PATH, mTaskRecord.filePath, i)); - } - boolean isSuccess = FileUtil.mergeFile(mTaskRecord.filePath, partPath); - if (isSuccess) { - for (String pp : partPath) { - FileUtil.deleteFile(pp); - } - File targetFile = new File(mTaskRecord.filePath); - if (targetFile.exists() && targetFile.length() > mTaskRecord.fileLength) { - ALog.e(TAG, String.format("任务【%s】分块文件合并失败,下载长度超出文件真实长度,downloadLen: %s,fileSize: %s", - targetFile.getName(), targetFile.length(), mTaskRecord.fileLength)); - return false; - } - return true; - } else { - ALog.e(TAG, "合并失败"); - return false; - } - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/processor/IFtpUploadInterceptor.java b/PublicComponent/src/main/java/com/arialyy/aria/core/processor/IFtpUploadInterceptor.java index de480d57..dbd36f34 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/processor/IFtpUploadInterceptor.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/processor/IFtpUploadInterceptor.java @@ -1,34 +1,34 @@ -/* - * 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.processor; - -import com.arialyy.aria.core.inf.IEventHandler; -import com.arialyy.aria.core.upload.UploadEntity; -import java.util.List; - -/** - * FTP文件上传拦截器,如果远端已有同名文件,可使用该拦截器控制覆盖文件或修改该文件上传到服务器端端文件名 - */ -public interface IFtpUploadInterceptor extends IEventHandler { - - /** - * 处理拦截事件 - * - * @param entity 上传信息实体 - * @param fileList ftp服务器端remotePath下的文件列表 - */ - FtpInterceptHandler onIntercept(UploadEntity entity, List fileList); -} +///* +// * 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.processor; +// +//import com.arialyy.aria.core.inf.IEventHandler; +//import com.arialyy.aria.core.upload.UploadEntity; +//import java.util.List; +// +///** +// * FTP文件上传拦截器,如果远端已有同名文件,可使用该拦截器控制覆盖文件或修改该文件上传到服务器端端文件名 +// */ +//public interface IFtpUploadInterceptor extends IEventHandler { +// +// /** +// * 处理拦截事件 +// * +// * @param entity 上传信息实体 +// * @param fileList ftp服务器端remotePath下的文件列表 +// */ +// FtpInterceptHandler onIntercept(UploadEntity entity, List fileList); +//} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/provider/DuaStartupProvider.kt b/PublicComponent/src/main/java/com/arialyy/aria/core/provider/DuaStartupProvider.kt index e623f667..9507eb08 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/provider/DuaStartupProvider.kt +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/provider/DuaStartupProvider.kt @@ -16,6 +16,7 @@ package com.arialyy.aria.core.provider import android.content.Context +import androidx.annotation.Keep import androidx.startup.Initializer import com.arialyy.aria.core.DuaContext import com.arialyy.aria.core.inf.IComponentInit @@ -24,6 +25,7 @@ import timber.log.Timber import timber.log.Timber.DebugTree import java.util.ServiceLoader +@Keep class DuaStartupProvider : Initializer { override fun create(context: Context) { diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/task/UploadTask.java b/PublicComponent/src/main/java/com/arialyy/aria/core/task/UploadTask.java deleted file mode 100644 index 8d5f0590..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/task/UploadTask.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.arialyy.aria.core.task; - -import android.os.Handler; -import android.os.Looper; -import com.arialyy.aria.core.listener.ISchedulers; -import com.arialyy.aria.core.upload.UTaskWrapper; -import com.arialyy.aria.core.upload.UploadEntity; -import com.arialyy.aria.util.ComponentUtil; - -/** - * Created by lyy on 2017/2/23. 上传任务 - */ -public class UploadTask extends AbsTask { - - private UploadTask(UTaskWrapper taskWrapper, Handler outHandler) { - mTaskWrapper = taskWrapper; - mOutHandler = outHandler; - mListener = - ComponentUtil.getInstance().buildListener(taskWrapper.getRequestType(), this, mOutHandler); - } - - @Override public int getTaskType() { - return UPLOAD; - } - - @Override public String getKey() { - return mTaskWrapper.getEntity().getKey(); - } - - public UploadEntity getEntity() { - return mTaskWrapper.getEntity(); - } - - @Override public String getTaskName() { - return mTaskWrapper.getEntity().getFileName(); - } - - public static class Builder { - private Handler mOutHandler; - private UTaskWrapper mTaskEntity; - - public void setOutHandler(ISchedulers outHandler) { - mOutHandler = new Handler(Looper.getMainLooper(), outHandler); - } - - public void setUploadTaskEntity(UTaskWrapper taskEntity) { - mTaskEntity = taskEntity; - } - - public Builder() { - - } - - public UploadTask build() { - return new UploadTask(mTaskEntity, mOutHandler); - } - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/util/AriaCrashHandler.java b/PublicComponent/src/main/java/com/arialyy/aria/util/AriaCrashHandler.java deleted file mode 100644 index d529b252..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/util/AriaCrashHandler.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.arialyy.aria.util; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * Created by Aria.Lao on 2017/10/25. - * 程序异常日志捕获器 - */ -public class AriaCrashHandler implements Thread.UncaughtExceptionHandler { - private Thread.UncaughtExceptionHandler mDefaultHandler; - private ExecutorService mExecutorService; - - public AriaCrashHandler() { - mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); - mExecutorService = Executors.newSingleThreadExecutor(); - } - - @Override - public void uncaughtException(Thread thread, Throwable ex) { - ex.printStackTrace(); - //ALog.d(thread.getName(), ex.getLocalizedMessage()); - handleException(thread.getName(), ex); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - mDefaultHandler.uncaughtException(thread, ex); - exit(); - } - } - - /** - * 处理异常 - */ - private void handleException(final String name, final Throwable ex) { - if (ex == null) { - return; - } - - mExecutorService.execute(new Runnable() { - @Override - public void run() { - ErrorHelp.saveError("", ALog.getExceptionString(ex)); - } - }); - } - - /** - * 退出当前应用 - */ - private void exit() { - android.os.Process.killProcess(android.os.Process.myPid()); - System.exit(1); - } -} \ No newline at end of file diff --git a/PublicComponent/src/main/java/com/arialyy/aria/util/CheckUtil.java b/PublicComponent/src/main/java/com/arialyy/aria/util/CheckUtil.java deleted file mode 100644 index 8e92c028..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/util/CheckUtil.java +++ /dev/null @@ -1,209 +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.util; - -import android.text.TextUtils; -import com.arialyy.aria.core.download.DownloadEntity; -import com.arialyy.aria.core.download.DownloadGroupEntity; -import com.arialyy.aria.core.upload.UploadEntity; -import com.arialyy.aria.core.wrapper.AbsTaskWrapper; -import com.arialyy.aria.orm.DbEntity; -import java.lang.reflect.Modifier; -import java.net.HttpURLConnection; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Created by Lyy on 2016/9/23. - * 检查帮助类 - */ -public class CheckUtil { - private static final String TAG = "CheckUtil"; - - /** - * 检查ip是否正确 - * - * @param ip ipv4 地址 - * @return {@code true} ip 正确,{@code false} ip 错误 - */ - public static boolean checkIp(String ip) { - if (TextUtils.isEmpty(ip) || ip.length() < 7 || ip.length() > 15) { - return false; - } - Pattern p = Pattern.compile(Regular.REG_IP_V4); - Matcher m = p.matcher(ip); - return m.find() && m.groupCount() > 0; - } - - /** - * 判断http请求是否有效 - * {@link HttpURLConnection#HTTP_BAD_GATEWAY} or {@link HttpURLConnection#HTTP_BAD_METHOD} - * or {@link HttpURLConnection#HTTP_BAD_REQUEST} 无法重试 - * - * @param errorCode http 返回码 - * @return {@code true} 无效请求;{@code false} 有效请求 - */ - public static boolean httpIsBadRequest(int errorCode) { - return errorCode == HttpURLConnection.HTTP_BAD_GATEWAY - || errorCode == HttpURLConnection.HTTP_BAD_METHOD - || errorCode == HttpURLConnection.HTTP_BAD_REQUEST; - } - - /** - * 判断ftp请求是否有效 - * - * @return {@code true} 无效请求;{@code false} 有效请求 - */ - public static boolean ftpIsBadRequest(int errorCode) { - return errorCode >= 400 && errorCode < 600; - } - - /** - * 检查和处理下载任务的路径冲突 - * - * @param isForceDownload true,如果路径冲突,将删除其它任务的记录的 - * @param filePath 文件保存路径 - * @param type {@link AbsTaskWrapper#getRequestType()} - * @return false 任务不再执行,true 任务继续执行 - */ - public static boolean checkDPathConflicts(boolean isForceDownload, String filePath, int type) { - if (DbEntity.checkDataExist(DownloadEntity.class, "downloadPath=?", filePath)) { - if (!isForceDownload) { - ALog.e(TAG, String.format("下载失败,保存路径【%s】已经被其它任务占用,请设置其它保存路径", filePath)); - return false; - } else { - ALog.w(TAG, String.format("保存路径【%s】已经被其它任务占用,当前任务将覆盖该路径的文件", filePath)); - RecordUtil.delTaskRecord(filePath, type, false, true); - return true; - } - } - return true; - } - - /** - * 检查和处理上传任务的路径冲突 - * - * @param isForceUpload true,如果路径冲突,将删除其它任务的记录的 - * @param filePath 文件保存路径 - * @param type {@link AbsTaskWrapper#getRequestType()} - * @return false 任务不再执行,true 任务继续执行 - */ - public static boolean checkUPathConflicts(boolean isForceUpload, String filePath, int type) { - if (DbEntity.checkDataExist(UploadEntity.class, "filePath=?", filePath)) { - if (!isForceUpload) { - ALog.e(TAG, String.format("上传失败,文件路径【%s】已经被其它任务占用,请设置其它文件路径", filePath)); - return false; - } else { - ALog.w(TAG, String.format("文件路径【%s】已经被其它任务占用,当前任务将覆盖该路径的文件", filePath)); - RecordUtil.delTaskRecord(filePath, type, false, true); - return true; - } - } - return true; - } - - /** - * 检查和处理组合任务的路径冲突 - * - * @param isForceDownload true,如果路径冲突,将删除其它任务的记录的 - * @param dirPath 文件保存路径 - * @return false 任务不再执行,true 任务继续执行 - */ - public static boolean checkDGPathConflicts(boolean isForceDownload, String dirPath) { - if (DbEntity.checkDataExist(DownloadGroupEntity.class, "dirPath=?", dirPath)) { - if (!isForceDownload) { - ALog.e(TAG, String.format("下载失败,文件夹路径【%s】已经被其它任务占用,请设置其它文件路径", dirPath)); - return false; - } else { - ALog.w(TAG, String.format("文件夹路径【%s】已经被其它任务占用,当前任务将覆盖该路径", dirPath)); - DeleteDGRecord.getInstance().deleteRecord(dirPath, false, true); - return true; - } - } - return true; - } - - /** - * 检查成员类是否是静态和public - */ - public static void checkMemberClass(Class clazz) { - int modifiers = clazz.getModifiers(); - //ALog.d(TAG, "isMemberClass = " - // + clazz.isMemberClass() - // + "; isStatic = " - // + Modifier.isStatic(modifiers) - // + "; isPrivate = " - // + Modifier.isPrivate(modifiers)); - if (!clazz.isMemberClass() || !Modifier.isStatic(modifiers)) { - ALog.e(TAG, String.format("为了防止内存泄漏,请使用静态的成员类(public static class %s)或文件类(%s.java)", - clazz.getSimpleName(), clazz.getSimpleName())); - } - } - - /** - * 检查分页数据,需要查询的页数,从1开始,如果page小于1 或 num 小于1,则抛出{@link NullPointerException} - * - * @param page 从1 开始 - * @param num 每页数量 - */ - public static void checkPageParams(int page, int num) { - if (page < 1 || num < 1) throw new NullPointerException("page和num不能小于1"); - } - - /** - * 检测url是否合法 - * - * @return {@code true} 合法,{@code false} 非法 - */ - public static boolean checkUrl(String url) { - if (TextUtils.isEmpty(url)) { - ALog.e(TAG, "url不能为null"); - return false; - } else if (!url.startsWith("http") && !url.startsWith("ftp") && !url.startsWith("sftp")) { - ALog.e(TAG, "url【" + url + "】错误"); - return false; - } - int index = url.indexOf("://"); - if (index == -1) { - ALog.e(TAG, "url【" + url + "】不合法"); - } - return true; - } - - /** - * 检测下载链接组是否为null - * - * @return true 组合任务url为空 - */ - public static boolean checkDownloadUrlsIsEmpty(List urls) { - if (urls == null || urls.isEmpty()) { - ALog.e(TAG, "链接组不能为null"); - return true; - } - return false; - } - - /** - * 检测上传地址是否为null - */ - public static void checkUploadPathIsEmpty(String uploadPath) { - if (TextUtils.isEmpty(uploadPath)) { - throw new IllegalArgumentException("上传地址不能为null"); - } - } -} \ No newline at end of file diff --git a/PublicComponent/src/main/java/com/arialyy/aria/util/ComponentUtil.java b/PublicComponent/src/main/java/com/arialyy/aria/util/ComponentUtil.java deleted file mode 100644 index b49f5e4c..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/util/ComponentUtil.java +++ /dev/null @@ -1,262 +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.util; - -import android.os.Handler; -import com.arialyy.aria.core.TaskOptionParams; -import com.arialyy.aria.core.inf.IEventHandler; -import com.arialyy.aria.core.inf.ITaskOption; -import com.arialyy.aria.core.inf.ITaskAdapter; -import com.arialyy.aria.core.listener.IEventListener; -import com.arialyy.aria.core.task.AbsTask; -import com.arialyy.aria.core.wrapper.AbsTaskWrapper; -import com.arialyy.aria.core.wrapper.ITaskWrapper; -import java.lang.ref.SoftReference; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.List; - -/** - * 组件工具,用于跨组件创建对应的工具类 - * - * @author lyy - * Date: 2019-09-23 - */ -public class ComponentUtil { - public static final int COMPONENT_TYPE_HTTP = 1; - public static final int COMPONENT_TYPE_FTP = 2; - public static final int COMPONENT_TYPE_M3U8 = 3; - public static final int COMPONENT_TYPE_SFTP = 4; - - private String TAG = CommonUtil.getClassName(getClass()); - private static volatile ComponentUtil INSTANCE = null; - - private ComponentUtil() { - - } - - public static ComponentUtil getInstance() { - if (INSTANCE == null) { - synchronized (ComponentUtil.class) { - if (INSTANCE == null) { - INSTANCE = new ComponentUtil(); - } - } - } - - return INSTANCE; - } - - /** - * 检查组件是否存在,不存在抛出异常退出 - * - * @param componentType 组件类型{@link #COMPONENT_TYPE_FTP}, {@link #COMPONENT_TYPE_M3U8}, {@link - * #COMPONENT_TYPE_HTTP} - * @return true 组件存在 - */ - public boolean checkComponentExist(int componentType) { - String errorStr = "", className = null; - switch (componentType) { - case COMPONENT_TYPE_M3U8: - className = "com.arialyy.aria.m3u8.M3U8TaskOption"; - errorStr = "m3u8插件不存在,请添加m3u8插件"; - break; - case COMPONENT_TYPE_FTP: - className = "com.arialyy.aria.ftp.FtpTaskOption"; - errorStr = "ftp插件不存在,请添加ftp插件"; - break; - case COMPONENT_TYPE_HTTP: - className = "com.arialyy.aria.http.HttpTaskOption"; - errorStr = "http插件不存在,请添加http插件"; - break; - case COMPONENT_TYPE_SFTP: - className = "com.arialyy.aria.sftp.SFtpTaskOption"; - errorStr = "sftp插件不存在,请添加sftp插件"; - break; - } - - try { - getClass().getClassLoader().loadClass(className); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - throw new IllegalArgumentException(errorStr); - } - return true; - } - - /** - * 创建任务工具 - * - * @return 返回任务工具 - */ - public synchronized T buildUtil(AbsTaskWrapper wrapper, - IEventListener listener) { - int requestType = wrapper.getRequestType(); - String className = null; - switch (requestType) { - case ITaskWrapper.M3U8_LIVE: - className = "com.arialyy.aria.m3u8.live.M3U8LiveUtil"; - break; - case ITaskWrapper.M3U8_VOD: - className = "com.arialyy.aria.m3u8.vod.M3U8VodUtil"; - break; - case ITaskWrapper.D_FTP: - className = "com.arialyy.aria.ftp.download.FtpDLoaderUtil"; - break; - case ITaskWrapper.D_HTTP: - className = "com.arialyy.aria.http.download.HttpDLoaderUtil"; - break; - case ITaskWrapper.U_FTP: - className = "com.arialyy.aria.ftp.upload.FtpULoaderUtil"; - break; - case ITaskWrapper.U_HTTP: - className = "com.arialyy.aria.http.upload.HttpULoaderUtil"; - break; - case ITaskWrapper.D_FTP_DIR: - className = "com.arialyy.aria.ftp.download.FtpDGLoaderUtil"; - break; - case ITaskWrapper.DG_HTTP: - className = "com.arialyy.aria.http.download.HttpDGLoaderUtil"; - break; - case ITaskWrapper.D_SFTP: - className = "com.arialyy.aria.sftp.download.SFtpDLoaderUtil"; - break; - case ITaskWrapper.U_SFTP: - className = "com.arialyy.aria.sftp.upload.SFtpULoaderUtil"; - break; - } - if (className == null) { - ALog.e(TAG, "不识别的类名:" + className); - return null; - } - T util = null; - try { - Class clazz = (Class) getClass().getClassLoader().loadClass(className); - Constructor con = clazz.getConstructor(); - util = con.newInstance(); - Method method = - CommonUtil.getMethod(clazz, "setParams", AbsTaskWrapper.class, IEventListener.class); - method.invoke(util, wrapper, listener); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - return util; - } - - /** - * 创建任务事件监听 - * - * @param wrapperType 任务类型{@link ITaskWrapper} - * @return 返回事件监听,如果创建失败返回null - */ - public synchronized T buildListener(int wrapperType, AbsTask task, - Handler outHandler) { - String className = null, errorStr = "请添加FTP插件"; - switch (wrapperType) { - case ITaskWrapper.M3U8_LIVE: - case ITaskWrapper.M3U8_VOD: - className = "com.arialyy.aria.m3u8.M3U8Listener"; - errorStr = "请添加m3u8插件"; - break; - case ITaskWrapper.D_FTP: - case ITaskWrapper.D_HTTP: - case ITaskWrapper.D_SFTP: - className = "com.arialyy.aria.core.listener.BaseDListener"; - break; - case ITaskWrapper.U_FTP: - case ITaskWrapper.U_HTTP: - case ITaskWrapper.U_SFTP: - className = "com.arialyy.aria.core.listener.BaseUListener"; - break; - case ITaskWrapper.DG_HTTP: - case ITaskWrapper.D_FTP_DIR: - className = "com.arialyy.aria.core.listener.DownloadGroupListener"; - break; - } - if (className == null) { - return null; - } - T listener = null; - try { - Class clazz = (Class) getClass().getClassLoader().loadClass(className); - Constructor con = clazz.getConstructor(); - listener = con.newInstance(); - Method method = - CommonUtil.getMethod(clazz, "setParams", AbsTask.class, Handler.class); - method.invoke(listener, task, outHandler); - } catch (ClassNotFoundException e) { - throw new IllegalArgumentException(errorStr); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - return listener; - } - - /** - * 构建TaskOption信息 - * - * @param clazz 实现{@link ITaskOption}接口的配置信息类 - * @param params 任务配置信息参数 - * @return 构建失败,返回null - */ - public synchronized T buildTaskOption(Class clazz, - TaskOptionParams params) { - List fields = CommonUtil.getAllFields(clazz); - T taskOption = null; - try { - taskOption = clazz.newInstance(); - for (Field field : fields) { - field.setAccessible(true); - Class type = field.getType(); - String key = field.getName(); - if (type != SoftReference.class) { - Object obj = params.getParams().get(key); - if (obj == null) { - continue; - } - field.set(taskOption, obj); - } else { - IEventHandler handler = params.getHandler().get(key); - if (handler == null) { - continue; - } - field.set(taskOption, new SoftReference<>(handler)); - } - } - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InstantiationException e) { - e.printStackTrace(); - } - return taskOption; - } -} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/util/DuaUtil.kt b/PublicComponent/src/main/java/com/arialyy/aria/util/DuaUtil.kt index 71af1a30..fabbe524 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/util/DuaUtil.kt +++ b/PublicComponent/src/main/java/com/arialyy/aria/util/DuaUtil.kt @@ -15,6 +15,8 @@ */ package com.arialyy.aria.util +import android.text.TextUtils +import timber.log.Timber import java.security.MessageDigest /** @@ -23,6 +25,27 @@ import java.security.MessageDigest * @Date 21:38 2023/3/11 **/ object DuaUtil { + /** + * 检测url是否合法 + * + * @return `true` 合法,`false` 非法 + */ + fun checkUrl(url: String): Boolean { + if (TextUtils.isEmpty(url)) { + Timber.e("url不能为null") + return false + } + if (!url.startsWith("http") && !url.startsWith("ftp") && !url.startsWith("sftp")) { + Timber.e("url【$url】错误") + return false + } + val index = url.indexOf("://") + if (index == -1) { + Timber.e("url【$url】不合法") + } + return true + } + fun getMD5Hash(str: String): String { val md = MessageDigest.getInstance("MD5") val messageDigest = md.digest(str.toByteArray()) @@ -33,5 +56,4 @@ object DuaUtil { } return hashText } - } diff --git a/PublicComponent/src/main/java/com/arialyy/aria/util/IDeleteRecord.java b/PublicComponent/src/main/java/com/arialyy/aria/util/IDeleteRecord.java deleted file mode 100644 index 2479ab3e..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/util/IDeleteRecord.java +++ /dev/null @@ -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.util; - -import com.arialyy.aria.core.common.AbsEntity; - -/** - * 删除记录 - */ -public interface IDeleteRecord { - - /** - * 删除记录 - * - * @param key 记录关联的key - * @param needRemoveFile 是否需要删除文件 - * @param needRemoveEntity 是否需要删除实体,true 删除实体 - */ - void deleteRecord(String key, boolean needRemoveFile, boolean needRemoveEntity); - - /** - * 删除记录 - * - * @param absEntity 记录关联的实体 - * @param needRemoveFile 是否需要删除文件 - * @param needRemoveEntity 是否需要删除实体,true 删除实体 - */ - void deleteRecord(AbsEntity absEntity, boolean needRemoveFile, boolean needRemoveEntity); -} diff --git a/app/src/main/java/com/arialyy/simple/core/download/SingleTaskActivity.java b/app/src/main/java/com/arialyy/simple/core/download/SingleTaskActivity.java index 09dccc4d..7658949b 100644 --- a/app/src/main/java/com/arialyy/simple/core/download/SingleTaskActivity.java +++ b/app/src/main/java/com/arialyy/simple/core/download/SingleTaskActivity.java @@ -35,7 +35,7 @@ import com.arialyy.aria.core.common.AbsEntity; import com.arialyy.aria.core.common.HttpOption; import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.listener.ISchedulers; -import com.arialyy.aria.core.processor.IHttpFileLenAdapter; +import com.arialyy.aria.http.IHttpFileLenAdapter; import com.arialyy.aria.core.task.SingleDownloadTask; import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.CommonUtil; diff --git a/app/src/main/java/com/arialyy/simple/core/download/group/DownloadGroupActivity.java b/app/src/main/java/com/arialyy/simple/core/download/group/DownloadGroupActivity.java index 6620f35a..13a7139f 100644 --- a/app/src/main/java/com/arialyy/simple/core/download/group/DownloadGroupActivity.java +++ b/app/src/main/java/com/arialyy/simple/core/download/group/DownloadGroupActivity.java @@ -25,7 +25,7 @@ import com.arialyy.aria.core.common.AbsEntity; import com.arialyy.aria.core.common.HttpOption; import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadGroupEntity; -import com.arialyy.aria.core.processor.IHttpFileLenAdapter; +import com.arialyy.aria.http.IHttpFileLenAdapter; import com.arialyy.aria.core.task.DownloadGroupTask; import com.arialyy.aria.util.ALog; import com.arialyy.frame.util.show.T;