get file info reconstruct

v4
laoyuyu 2 years ago
parent c23a774dd8
commit 3fd103d616
  1. 0
      FtpComponent/src/main/resources/META-INF/services/com.arialyy.aria.core.inf.ITaskUtil
  2. 26
      Http/src/main/java/com/arialyy/aria/http/ConnectionHelp.java
  3. 74
      Http/src/main/java/com/arialyy/aria/http/HttpOption.kt
  4. 48
      Http/src/main/java/com/arialyy/aria/http/HttpUtil.kt
  5. 30
      Http/src/main/java/com/arialyy/aria/http/download/HttpDStartController.kt
  6. 2
      Http/src/main/java/com/arialyy/aria/http/download/HttpDTaskOption.kt
  7. 31
      Http/src/main/java/com/arialyy/aria/http/download/HttpDTaskUtil.kt
  8. 203
      Http/src/main/java/com/arialyy/aria/http/download/HttpHeaderInterceptor.kt
  9. 59
      Http/src/main/java/com/arialyy/aria/http/request/GetRequest.kt
  10. 59
      Http/src/main/java/com/arialyy/aria/http/request/HeadRequest.kt
  11. 152
      Http/src/main/java/com/arialyy/aria/http/request/IRequest.kt
  12. 74
      Http/src/main/java/com/arialyy/aria/http/request/PostRequest.kt
  13. 0
      Http/src/main/resources/META-INF/services/com.arialyy.aria.core.inf.ITaskUtil
  14. 0
      M3U8Component/src/main/resources/META-INF/services/com.arialyy.aria.core.inf.ITaskUtil
  15. 3
      PublicComponent/src/main/java/com/arialyy/aria/core/common/RequestEnum.java
  16. 1
      PublicComponent/src/main/java/com/arialyy/aria/core/download/DTaskOption.kt
  17. 7
      PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsGroupLoaderUtil.java
  18. 6
      PublicComponent/src/main/java/com/arialyy/aria/core/group/AbsSubDLoadUtil.java
  19. 4
      PublicComponent/src/main/java/com/arialyy/aria/core/group/ISubQueue.java
  20. 28
      PublicComponent/src/main/java/com/arialyy/aria/core/inf/ITaskUtil.java
  21. 4
      PublicComponent/src/main/java/com/arialyy/aria/core/listener/BaseListener.java
  22. 7
      PublicComponent/src/main/java/com/arialyy/aria/core/loader/AbsNormalLoaderUtil.java
  23. 8
      PublicComponent/src/main/java/com/arialyy/aria/core/task/AbsGroupTask.java
  24. 32
      PublicComponent/src/main/java/com/arialyy/aria/core/task/AbsTask.java
  25. 63
      PublicComponent/src/main/java/com/arialyy/aria/core/task/AbsTaskUtil.kt
  26. 5
      PublicComponent/src/main/java/com/arialyy/aria/core/task/DownloadTask.java
  27. 31
      PublicComponent/src/main/java/com/arialyy/aria/core/task/ITaskInterceptor.kt
  28. 26
      PublicComponent/src/main/java/com/arialyy/aria/core/task/TaskCachePool.kt
  29. 38
      PublicComponent/src/main/java/com/arialyy/aria/core/task/TaskChain.kt
  30. 17
      PublicComponent/src/main/java/com/arialyy/aria/core/task/TaskResp.kt
  31. 4
      PublicComponent/src/main/java/com/arialyy/aria/util/ComponentUtil.java
  32. 0
      SFtpComponent/src/main/resources/META-INF/services/com.arialyy.aria.core.inf.ITaskUtil

@ -19,7 +19,6 @@ import android.text.TextUtils;
import com.arialyy.aria.core.AriaConfig; import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.ProtocolType; import com.arialyy.aria.core.ProtocolType;
import com.arialyy.aria.core.common.RequestEnum; import com.arialyy.aria.core.common.RequestEnum;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.SSLContextUtil; import com.arialyy.aria.util.SSLContextUtil;
import java.io.IOException; import java.io.IOException;
@ -28,7 +27,6 @@ import java.net.CookieManager;
import java.net.CookieStore; import java.net.CookieStore;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.net.URLEncoder; import java.net.URLEncoder;
@ -49,25 +47,33 @@ public final class ConnectionHelp {
/** /**
* 处理url参数 * 处理url参数
*/ */
public static URL handleUrl(String url, HttpTaskOption taskDelegate) public static URL handleUrl(String url, HttpOption option)
throws MalformedURLException { throws MalformedURLException {
Map<String, String> params = taskDelegate.getParams(); Map<String, String> params = option.getParams();
if (params != null && taskDelegate.getRequestEnum() == RequestEnum.GET) { if (params.isEmpty()) {
if (url.contains("?")) {
ALog.e(TAG, String.format("设置参数失败,url中已经有?,url: %s", url));
return new URL(CommonUtil.convertUrl(url)); return new URL(CommonUtil.convertUrl(url));
} }
if (option.getRequestMethod() == RequestEnum.GET) {
if (!url.contains("?")) {
url = url.concat("?");
}
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(url).append("?"); sb.append(url).append("?");
Set<String> keys = params.keySet(); Set<String> keys = params.keySet();
for (String key : keys) { for (String key : keys) {
sb.append(key).append("=").append(URLEncoder.encode(params.get(key))).append("&"); sb.append(URLEncoder.encode(key))
.append("=")
.append(URLEncoder.encode(params.get(key)))
.append("&");
} }
String temp = sb.toString(); String temp = sb.toString();
temp = temp.substring(0, temp.length() - 1); temp = temp.substring(0, temp.length() - 1);
return new URL(CommonUtil.convertUrl(temp)); return new URL(CommonUtil.convertUrl(temp));
} else { }
return new URL(CommonUtil.convertUrl(url));
if (option.getRequestMethod() == RequestEnum.POST) {
} }
} }

@ -15,13 +15,85 @@
*/ */
package com.arialyy.aria.http package com.arialyy.aria.http
import com.arialyy.aria.core.common.RequestEnum
import java.net.CookieManager
import java.net.Proxy
/** /**
* @Author laoyuyu * @Author laoyuyu
* @Description * @Description
* @Date 14:27 AM 2023/1/20 * @Date 14:27 AM 2023/1/20
**/ **/
class HttpOption { class HttpOption {
private val params = hashMapOf<String, String>()
private val headers = hashMapOf<String, String>()
private var requestEnum = RequestEnum.GET
private var proxy: Proxy? = null
private var cookieManager: CookieManager? = null
private var body: String? = null
private var bodyBinary: ByteArray? = null
fun setProxy(proxy: Proxy): HttpOption {
this.proxy = proxy
return this
}
fun getProxy() = proxy
/**
* set http request key
*/
fun setParas(key: String, value: String): HttpOption {
params[key] = value
return this
}
fun setParams(params: Map<String, String>): HttpOption {
this.params.putAll(params)
return this
}
fun getParams() = params
fun getCookieManager(): CookieManager? {
return cookieManager
}
// fun se fun setBody(body: String): HttpOption {
this.body = body
return this
}
fun getBody() = body
fun setBodyBinary(body: ByteArray): HttpOption {
this.bodyBinary = body
return this
}
fun getBodyBinary() = bodyBinary
fun setCookieManager(cookieManager: CookieManager): HttpOption {
this.cookieManager = cookieManager
return this
}
fun setHeaders(headers: Map<String, String>): HttpOption {
this.headers.putAll(headers)
return this
}
fun getHeaders() = headers
/**
* Attempts to get file information before downloading a file
* by default, the get method is used to get
* if the server supports head requests, please set true
*/
fun setRequestMethod(requestEnum: RequestEnum): HttpOption {
this.requestEnum = requestEnum
return this
}
fun getRequestMethod() = requestEnum
} }

@ -15,9 +15,17 @@
*/ */
package com.arialyy.aria.http package com.arialyy.aria.http
import android.text.TextUtils
import com.arialyy.aria.http.download.HttpDTaskOption import com.arialyy.aria.http.download.HttpDTaskOption
import com.arialyy.aria.util.CheckUtil import com.arialyy.aria.util.CheckUtil
import com.arialyy.aria.util.Regular
import timber.log.Timber import timber.log.Timber
import java.io.IOException
import java.io.InputStream
import java.net.HttpURLConnection
import java.util.regex.Pattern
import java.util.zip.GZIPInputStream
import java.util.zip.InflaterInputStream
/** /**
* @Author laoyuyu * @Author laoyuyu
@ -25,6 +33,46 @@ import timber.log.Timber
* @Date 12:40 PM 2023/1/22 * @Date 12:40 PM 2023/1/22
**/ **/
internal object HttpUtil { internal object HttpUtil {
/**
* 拦截window.location.replace数据
*
* @return 重定向url
*/
fun getWindowReplaceUrl(text: String?): String? {
if (text.isNullOrEmpty()) {
Timber.e("text is null")
return null
}
val reg = Regular.REG_WINLOD_REPLACE
val p = Pattern.compile(reg)
val m = p.matcher(text)
if (m.find()) {
var s = m.group()
s = s.substring(9, s.length - 2)
return s
}
return null
}
/**
* 转换HttpUrlConnect的inputStream流
*
* @return [GZIPInputStream][InflaterInputStream]
* @throws IOException
*/
@Throws(IOException::class) fun convertInputStream(connection: HttpURLConnection): InputStream? {
val encoding = connection.getHeaderField("Content-Encoding")
if (TextUtils.isEmpty(encoding)) {
return connection.inputStream
}
if (encoding.contains("gzip")) {
return GZIPInputStream(connection.inputStream)
}
if (encoding.contains("deflate")) {
return InflaterInputStream(connection.inputStream)
}
return connection.inputStream
}
fun checkHttpDParams(option: HttpDTaskOption?): Boolean { fun checkHttpDParams(option: HttpDTaskOption?): Boolean {
if (option == null) { if (option == null) {

@ -20,13 +20,15 @@ import com.arialyy.aria.core.DuaContext
import com.arialyy.aria.core.command.AddCmd import com.arialyy.aria.core.command.AddCmd
import com.arialyy.aria.core.command.StartCmd import com.arialyy.aria.core.command.StartCmd
import com.arialyy.aria.core.inf.IStartController import com.arialyy.aria.core.inf.IStartController
import com.arialyy.aria.core.processor.IHttpFileLenAdapter
import com.arialyy.aria.core.task.DownloadTask import com.arialyy.aria.core.task.DownloadTask
import com.arialyy.aria.core.task.TaskCachePool
import com.arialyy.aria.http.HttpBaseController import com.arialyy.aria.http.HttpBaseController
import com.arialyy.aria.http.HttpOption import com.arialyy.aria.http.HttpOption
import com.arialyy.aria.http.HttpUtil import com.arialyy.aria.http.HttpUtil
import com.arialyy.aria.orm.EntityCachePool
import com.arialyy.aria.orm.entity.DEntity import com.arialyy.aria.orm.entity.DEntity
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.net.HttpURLConnection
/** /**
* @Author laoyuyu * @Author laoyuyu
@ -45,16 +47,28 @@ class HttpDStartController(target: Any, val url: String) : HttpBaseController(ta
/** /**
* set http params, link Header * set http params, link Header
*/ */
fun setHttpOption(httpOption: HttpOption): HttpBaseController { fun setHttpOption(httpOption: HttpOption): HttpDStartController {
httpDTaskOption.httpOption = httpOption httpDTaskOption.httpOption = httpOption
return this return this
} }
fun setListener(listener: HttpDownloadListener): HttpBaseController { /**
* Maybe the server has special rules, you need set [IHttpFileLenAdapter] to get the file length from [HttpURLConnection.getHeaderFields]
*/
fun setHttpFileLenAdapter(adapter: IHttpFileLenAdapter): HttpDStartController {
httpDTaskOption.fileSizeAdapter = adapter
return this
}
fun setListener(listener: HttpDownloadListener): HttpDStartController {
DuaContext.getLifeManager().addCustomListener(target, listener) DuaContext.getLifeManager().addCustomListener(target, listener)
return this return this
} }
/**
* set file save path, eg: /mnt/sdcard/Downloads/test.zip
*/
fun setSavePath(savePath: Uri): HttpDStartController { fun setSavePath(savePath: Uri): HttpDStartController {
httpDTaskOption.savePathUri = savePath httpDTaskOption.savePathUri = savePath
return this return this
@ -64,10 +78,16 @@ class HttpDStartController(target: Any, val url: String) : HttpBaseController(ta
if (HttpUtil.checkHttpDParams(httpDTaskOption)) { if (HttpUtil.checkHttpDParams(httpDTaskOption)) {
throw IllegalArgumentException("invalid params") throw IllegalArgumentException("invalid params")
} }
val task = DownloadTask(httpDTaskOption) val savePath = httpDTaskOption.savePathUri!!.toString()
var util = TaskCachePool.getTaskUtil(savePath)
if (util == null) {
util = HttpDTaskUtil()
TaskCachePool.putTaskUtil(savePath, util)
}
val task = DownloadTask(httpDTaskOption, util)
DuaContext.duaScope.launch { DuaContext.duaScope.launch {
val dEntity = findDEntityBySavePath(httpDTaskOption) val dEntity = findDEntityBySavePath(httpDTaskOption)
EntityCachePool.putEntity(task.taskId, dEntity) TaskCachePool.putEntity(task.taskId, dEntity)
} }
return task return task
} }

@ -16,6 +16,7 @@
package com.arialyy.aria.http.download package com.arialyy.aria.http.download
import com.arialyy.aria.core.download.DTaskOption import com.arialyy.aria.core.download.DTaskOption
import com.arialyy.aria.core.processor.IHttpFileLenAdapter
import com.arialyy.aria.http.HttpOption import com.arialyy.aria.http.HttpOption
/** /**
@ -26,4 +27,5 @@ import com.arialyy.aria.http.HttpOption
class HttpDTaskOption : DTaskOption() { class HttpDTaskOption : DTaskOption() {
var httpOption: HttpOption? = null var httpOption: HttpOption? = null
var fileSizeAdapter: IHttpFileLenAdapter? = null
} }

@ -0,0 +1,31 @@
package com.arialyy.aria.http.download
import com.arialyy.aria.core.task.AbsTaskUtil
/**
* @Author laoyuyu
* @Description
* @Date 1:47 PM 2023/1/28
**/
internal class HttpDTaskUtil : AbsTaskUtil() {
init {
}
override fun isRunning(): Boolean {
TODO("Not yet implemented")
}
override fun cancel() {
TODO("Not yet implemented")
}
override fun stop() {
TODO("Not yet implemented")
}
override fun start() {
}
}

@ -0,0 +1,203 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.http.download
import android.net.TrafficStats
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.core.task.ITask
import com.arialyy.aria.core.task.ITaskInterceptor
import com.arialyy.aria.core.task.TaskChain
import com.arialyy.aria.core.task.TaskResp
import com.arialyy.aria.http.HttpUtil
import com.arialyy.aria.http.request.IRequest
import com.arialyy.aria.util.CheckUtil
import timber.log.Timber
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStreamReader
import java.net.HttpURLConnection
import java.util.UUID
/**
* @Author laoyuyu
* @Description
* @Date 2:27 PM 2023/1/28
**/
internal class HttpHeaderInterceptor : ITaskInterceptor {
private lateinit var task: ITask
private lateinit var taskOption: HttpDTaskOption
companion object {
private val CODE_30X = listOf(
HttpURLConnection.HTTP_MOVED_TEMP, HttpURLConnection.HTTP_MOVED_PERM,
HttpURLConnection.HTTP_SEE_OTHER, HttpURLConnection.HTTP_CREATED, 307
)
}
override fun interceptor(chain: TaskChain): TaskResp {
if (Looper.myLooper() == Looper.getMainLooper()) {
throw IllegalThreadStateException("Io operations cannot be in the main thread")
}
task = chain.getTask()
taskOption = task.getTaskOption(HttpDTaskOption::class.java)
return try {
val fileSize = getFileSize()
chain.proceed(task)
} catch (e: IOException) {
Timber.e(
"download fail, url: ${
chain.getTask().getTaskOption(HttpDTaskOption::class.java).sourUrl
}"
)
TaskResp(TaskResp.CODE_GET_FILE_INFO_FAIL)
}
}
@Throws(IOException::class)
private fun getFileSize(): Long {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)
TrafficStats.setThreadStatsTag(UUID.randomUUID().toString().hashCode())
val conn: HttpURLConnection = IRequest.getRequest(taskOption.httpOption!!)
.getDConnection(taskOption.sourUrl!!, taskOption.httpOption!!)
// https://httpwg.org/specs/rfc9110.html#byte.ranges
// conn.setRequestProperty("Range", "bytes=" + 0 + "-")
conn.setRequestProperty("Range", "bytes=0-1") // 尝试获取1个字节
conn.connect()
return handleConnect(conn)
}
@Throws(IOException::class)
private fun handleConnect(conn: HttpURLConnection): Long {
val code = conn.responseCode
when {
code == HttpURLConnection.HTTP_PARTIAL -> return getFileSizeFromHeader(
conn.headerFields,
taskOption
)
code == HttpURLConnection.HTTP_OK -> {
val len = getFileSizeFromHeader(conn.headerFields, taskOption)
if (len > 0) {
return len
}
val contentType = conn.getHeaderField("Content-Type")
if (contentType == "text/html") {
val reader = BufferedReader(InputStreamReader(HttpUtil.convertInputStream(conn)))
val sb = StringBuilder()
var line: String?
while (reader.readLine().also { line = it } != null) {
sb.append(line)
}
reader.close()
return handleUrlReTurn(conn, HttpUtil.getWindowReplaceUrl(sb.toString()))
}
// code is 200, but file size cannot be obtained.
return -1
}
code in CODE_30X -> {
Timber.d("handle 30x turn, code: $code")
return handleUrlReTurn(conn, conn.getHeaderField("Location"))
}
code >= HttpURLConnection.HTTP_BAD_REQUEST -> {
Timber.e("download fail, code: $code")
return -1
}
else -> {
return -1
}
}
}
@Throws(IOException::class) private fun handleUrlReTurn(
oldConn: HttpURLConnection,
newUrl: String?
): Long {
Timber.i("handle 30x turn, new url: $newUrl")
if (newUrl.isNullOrEmpty() || newUrl.equals("null", ignoreCase = true)) {
return -1
}
var tempUrl = newUrl
if (tempUrl.startsWith("/")) {
val uri = Uri.parse(taskOption.sourUrl!!)
tempUrl = uri.host + newUrl
}
if (!CheckUtil.checkUrl(tempUrl)) {
Timber.e("get redirect url fail, $tempUrl")
return -1
}
taskOption.redirectUrl = newUrl
val cookies = oldConn.getHeaderField("Set-Cookie")
oldConn.disconnect()
val newConn: HttpURLConnection = IRequest.getRequest(taskOption.httpOption!!)
.getDConnection(taskOption.sourUrl!!, taskOption.httpOption!!)
newConn.setRequestProperty("Cookie", cookies)
newConn.setRequestProperty("Range", "bytes=" + 0 + "-")
newConn.connect()
return handleConnect(newConn)
}
/**
* get file size from header, if user not set [IHttpFileLenAdapter], use [FileLenAdapter]
*/
private fun getFileSizeFromHeader(
header: Map<String, List<String>>,
taskOption: HttpDTaskOption
): Long {
var lenAdapter = taskOption.fileSizeAdapter
if (lenAdapter == null) {
lenAdapter = FileLenAdapter()
}
return lenAdapter.handleFileLen(header)
}
/**
* https://httpwg.org/specs/rfc9110.html#field.content-range
*/
private class FileLenAdapter : IHttpFileLenAdapter {
override fun handleFileLen(headers: Map<String, List<String>>): Long {
if (headers.isEmpty()) {
Timber.e("header is empty, get file size fail")
return -1
}
val sLength = headers["Content-Length"]
if (sLength == null || sLength.isEmpty()) {
return -1
}
val temp = sLength[0]
var len = if (TextUtils.isEmpty(temp)) -1 else temp.toLong()
// 某些服务,如果设置了conn.setRequestProperty("Range", "bytes=" + 0 + "-");
// 会返回 Content-Range: bytes 0-225427911/225427913
if (len < 0) {
val sRange = headers["Content-Range"]
len = if (sRange == null || sRange.isEmpty()) {
-1
} else {
val start = temp.indexOf("/")
temp.substring(start + 1).toLong()
}
}
return len
}
}
}

@ -0,0 +1,59 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.http.request
import com.arialyy.aria.core.common.RequestEnum.GET
import com.arialyy.aria.http.HttpOption
import com.arialyy.aria.util.CommonUtil
import java.net.HttpURLConnection
import java.net.URL
import java.net.URLEncoder
/**
* @Author laoyuyu
* @Description
* @Date 9:52 AM 2023/1/29
**/
object GetRequest : IRequest {
override fun getDConnection(url: String, option: HttpOption): HttpURLConnection {
val params: Map<String, String> = option.getParams()
val realUrl = if (params.isNotEmpty()) {
val sb = StringBuilder()
sb.append(url)
if (!url.contains("?")) {
sb.append("?")
}
val keys = params.keys
for (key in keys) {
sb.append(URLEncoder.encode(key, Charsets.UTF_8.toString()))
.append("=")
.append(URLEncoder.encode(params[key], Charsets.UTF_8.toString()))
.append("&")
}
var temp = sb.toString()
temp = temp.substring(0, temp.length - 1)
URL(CommonUtil.convertUrl(temp))
} else {
URL(CommonUtil.convertUrl(url))
}
val conn = createConnection(realUrl, option)
conn.requestMethod = GET.name
return conn
}
}

@ -0,0 +1,59 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.http.request
import com.arialyy.aria.core.common.RequestEnum
import com.arialyy.aria.http.HttpOption
import com.arialyy.aria.util.CommonUtil
import java.net.HttpURLConnection
import java.net.URL
import java.net.URLEncoder
/**
* @Author laoyuyu
* @Description
* @Date 9:53 AM 2023/1/29
**/
internal object HeadRequest : IRequest {
override fun getDConnection(url: String, option: HttpOption): HttpURLConnection {
val params: Map<String, String> = option.getParams()
val realUrl = if (params.isNotEmpty()) {
val sb = StringBuilder()
sb.append(url)
if (!url.contains("?")) {
sb.append("?")
}
val keys = params.keys
for (key in keys) {
sb.append(URLEncoder.encode(key, Charsets.UTF_8.toString()))
.append("=")
.append(URLEncoder.encode(params[key], Charsets.UTF_8.toString()))
.append("&")
}
var temp = sb.toString()
temp = temp.substring(0, temp.length - 1)
URL(CommonUtil.convertUrl(temp))
} else {
URL(CommonUtil.convertUrl(url))
}
val conn = createConnection(realUrl, option)
conn.requestMethod = RequestEnum.HEAD.name
return conn
}
}

@ -0,0 +1,152 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.http.request
import android.text.TextUtils
import com.arialyy.aria.core.AriaConfig
import com.arialyy.aria.core.ProtocolType
import com.arialyy.aria.core.common.RequestEnum.GET
import com.arialyy.aria.core.common.RequestEnum.HEAD
import com.arialyy.aria.core.common.RequestEnum.POST
import com.arialyy.aria.http.HttpOption
import com.arialyy.aria.util.SSLContextUtil
import java.io.IOException
import java.net.HttpURLConnection
import java.net.URL
import java.net.URLConnection
import javax.net.ssl.HttpsURLConnection
/**
* @Author laoyuyu
* @Description
* @Date 19:48 AM 2023/1/29
**/
interface IRequest {
companion object {
fun getRequest(option: HttpOption): IRequest {
return when (option.getRequestMethod()) {
GET -> GetRequest
POST -> PostRequest
HEAD -> HeadRequest
else -> throw UnsupportedOperationException("unsupported method ${option.getRequestMethod()}")
}
}
}
fun getDConnection(url: String, option: HttpOption): HttpURLConnection
@Throws(IOException::class) fun createConnection(
url: URL,
option: HttpOption
): HttpURLConnection {
val conn: HttpURLConnection
val urlConn: URLConnection = if (option.getProxy() != null) {
url.openConnection(option.getProxy())
} else {
url.openConnection()
}
if (urlConn is HttpsURLConnection) {
val config = AriaConfig.getInstance()
conn = urlConn
var sslContext = SSLContextUtil.getSSLContextFromAssets(
config.dConfig.caName,
config.dConfig.caPath, ProtocolType.Default
)
if (sslContext == null) {
sslContext = SSLContextUtil.getDefaultSLLContext(ProtocolType.Default)
}
val ssf = sslContext!!.socketFactory
conn.sslSocketFactory = ssf
conn.hostnameVerifier = SSLContextUtil.HOSTNAME_VERIFIER
} else {
conn = urlConn as HttpURLConnection
}
setHeader(conn, option)
setConnectAttr(conn)
return conn
}
private fun setConnectAttr(conn: HttpURLConnection) {
conn.connectTimeout = AriaConfig.getInstance().dConfig.connectTimeOut
}
/**
* 设置头部参数
*/
private fun setHeader(conn: HttpURLConnection, option: HttpOption) {
option.getHeaders().forEach {
conn.setRequestProperty(it.key, it.value)
}
if (conn.getRequestProperty("Accept-Language") == null) {
conn.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7")
}
if (conn.getRequestProperty("Accept-Encoding") == null) {
conn.setRequestProperty("Accept-Encoding", "identity")
}
if (conn.getRequestProperty("Accept-Charset") == null) {
conn.setRequestProperty("Accept-Charset", "UTF-8")
}
if (conn.getRequestProperty("Connection") == null) {
conn.setRequestProperty("Connection", "Keep-Alive")
}
if (conn.getRequestProperty("Charset") == null) {
conn.setRequestProperty("Charset", "UTF-8")
}
if (conn.getRequestProperty("User-Agent") == null) {
conn.setRequestProperty(
"User-Agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
)
}
if (conn.getRequestProperty("Accept") == null) {
val accept = StringBuilder()
accept.append("image/gif, ")
.append("image/jpeg, ")
.append("image/pjpeg, ")
.append("image/webp, ")
.append("image/apng, ")
.append("application/xml, ")
.append("application/xaml+xml, ")
.append("application/xhtml+xml, ")
.append("application/x-shockwave-flash, ")
.append("application/x-ms-xbap, ")
.append("application/x-ms-application, ")
.append("application/msword, ")
.append("application/vnd.ms-excel, ")
.append("application/vnd.ms-xpsdocument, ")
.append("application/vnd.ms-powerpoint, ")
.append("application/signed-exchange, ")
.append("text/plain, ")
.append("text/html, ")
.append("*/*")
conn.setRequestProperty("Accept", accept.toString())
}
//302获取重定向地址
conn.instanceFollowRedirects = false
val manager = option.getCookieManager()
if (manager != null) {
val store = manager.cookieStore
if (store != null && store.cookies.size > 0) {
conn.setRequestProperty(
"Cookie",
TextUtils.join(";", store.cookies)
)
}
}
}
}

@ -0,0 +1,74 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.http.request
import com.arialyy.aria.core.common.RequestEnum
import com.arialyy.aria.http.HttpOption
import com.arialyy.aria.util.CommonUtil
import java.io.BufferedWriter
import java.io.OutputStreamWriter
import java.net.HttpURLConnection
import java.net.URL
import java.net.URLEncoder
/**
* @Author laoyuyu
* @Description
* @Date 19:52 AM 2023/1/29
**/
internal object PostRequest : IRequest {
override fun getDConnection(url: String, option: HttpOption): HttpURLConnection {
val conn = createConnection(URL(CommonUtil.convertUrl(url)), option)
conn.doInput = true
conn.doOutput = true
conn.useCaches = false
conn.requestMethod = RequestEnum.POST.name
if (option.getParams().isNotEmpty()
|| !option.getBody().isNullOrEmpty()
|| option.getBodyBinary() != null
) {
conn.outputStream.use {
val writer = BufferedWriter(OutputStreamWriter(it, "UTF-8"))
if (option.getParams().isNotEmpty()) {
writer.write(getQuery(option.getParams()))
}
if (!option.getBody().isNullOrEmpty()) {
writer.write(option.getBody())
}
if (option.getBodyBinary() != null) {
it.write(option.getBodyBinary())
}
writer.flush()
writer.close()
it.close()
}
}
return conn
}
private fun getQuery(params: Map<String, String>): String {
val result = StringBuilder()
var first = true
for (kv in params) {
if (first) first = false else result.append("&")
result.append(URLEncoder.encode(kv.key, Charsets.UTF_8.toString()))
result.append("=")
result.append(URLEncoder.encode(kv.value, Charsets.UTF_8.toString()))
}
return result.toString()
}
}

@ -20,12 +20,11 @@ package com.arialyy.aria.core.common;
* url请求方式目前支持GETPOST * url请求方式目前支持GETPOST
*/ */
public enum RequestEnum { public enum RequestEnum {
GET("GET"), POST("POST"); GET("GET"), POST("POST"), HEAD("HEAD");
public String name; public String name;
RequestEnum(String name) { RequestEnum(String name) {
this.name = name; this.name = name;
} }
} }

@ -26,4 +26,5 @@ import com.arialyy.aria.core.inf.ITaskOption
open class DTaskOption : ITaskOption() { open class DTaskOption : ITaskOption() {
var sourUrl: String? = null var sourUrl: String? = null
var savePathUri: Uri? = null var savePathUri: Uri? = null
var redirectUrl: String? = null
} }

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

@ -19,7 +19,7 @@ import android.os.Handler;
import com.arialyy.aria.core.TaskRecord; import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.download.DTaskWrapper; import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.inf.IUtil; import com.arialyy.aria.core.inf.ITaskUtil;
import com.arialyy.aria.core.listener.IEventListener; import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.listener.ISchedulers; import com.arialyy.aria.core.listener.ISchedulers;
import com.arialyy.aria.core.loader.LoaderStructure; import com.arialyy.aria.core.loader.LoaderStructure;
@ -31,7 +31,7 @@ import com.arialyy.aria.util.CommonUtil;
/** /**
* 子任务下载器工具需要在线程池中执行 * 子任务下载器工具需要在线程池中执行
*/ */
public abstract class AbsSubDLoadUtil implements IUtil, Runnable { public abstract class AbsSubDLoadUtil implements ITaskUtil, Runnable {
protected final String TAG = CommonUtil.getClassName(getClass()); protected final String TAG = CommonUtil.getClassName(getClass());
protected SubLoader mDLoader; protected SubLoader mDLoader;
@ -51,7 +51,7 @@ public abstract class AbsSubDLoadUtil implements IUtil, Runnable {
this.needGetInfo = needGetInfo; this.needGetInfo = needGetInfo;
} }
@Override public IUtil setParams(AbsTaskWrapper taskWrapper, IEventListener listener) { @Override public ITaskUtil setParams(AbsTaskWrapper taskWrapper, IEventListener listener) {
mWrapper = (DTaskWrapper) taskWrapper; mWrapper = (DTaskWrapper) taskWrapper;
mDLoader = getLoader(); mDLoader = getLoader();
return this; return this;

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

@ -16,37 +16,17 @@
package com.arialyy.aria.core.inf; package com.arialyy.aria.core.inf;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.listener.IEventListener; import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.core.upload.UploadEntity; import com.arialyy.aria.core.task.ITask;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper; import org.jetbrains.annotations.NotNull;
/** /**
* Created by lyy on 2016/10/31. * Created by lyy on 2016/10/31.
* 任务功能接口 * 任务功能接口
*/ */
public interface IUtil { public interface ITaskUtil {
IUtil setParams(AbsTaskWrapper taskWrapper, IEventListener listener); void init(@NotNull ITask task, @NotNull IEventListener listener);
/**
* 获取任务标志
*
* @return {@link DownloadEntity#getKey()}{@link DownloadGroupEntity#getKey()}{@link
* UploadEntity#getKey()}
*/
String getKey();
/**
* 获取文件大小
*/
long getFileSize();
/**
* 获取当前位置
*/
long getCurrentLocation();
/** /**
* 任务是否正在执行 * 任务是否正在执行

@ -25,7 +25,7 @@ import com.arialyy.aria.core.task.ITask;
import com.arialyy.aria.core.task.TaskState; import com.arialyy.aria.core.task.TaskState;
import com.arialyy.aria.core.wrapper.ITaskWrapper; import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.exception.AriaException; import com.arialyy.aria.exception.AriaException;
import com.arialyy.aria.orm.EntityCachePool; import com.arialyy.aria.core.task.TaskCachePool;
import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.ErrorHelp; import com.arialyy.aria.util.ErrorHelp;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
@ -174,6 +174,6 @@ public abstract class BaseListener implements IEventListener {
if (state == IEntity.STATE_COMPLETE) { if (state == IEntity.STATE_COMPLETE) {
handleComplete(); handleComplete();
} }
EntityCachePool.INSTANCE.updateState(mTask.getTaskId(), state, location); TaskCachePool.INSTANCE.updateState(mTask.getTaskId(), state, location);
} }
} }

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

@ -35,8 +35,8 @@ public abstract class AbsGroupTask<TASK_ENTITY extends AbsGroupTaskWrapper>
* @param url 子任务下载地址 * @param url 子任务下载地址
*/ */
public void startSubTask(String url) { public void startSubTask(String url) {
if (getUtil() != null) { if (getTaskUtil() != null) {
((AbsGroupLoaderUtil) getUtil()).startSubTask(url); ((AbsGroupLoaderUtil) getTaskUtil()).startSubTask(url);
} }
} }
@ -46,8 +46,8 @@ public abstract class AbsGroupTask<TASK_ENTITY extends AbsGroupTaskWrapper>
* @param url 子任务下载地址 * @param url 子任务下载地址
*/ */
public void stopSubTask(String url) { public void stopSubTask(String url) {
if (getUtil() != null) { if (getTaskUtil() != null) {
((AbsGroupLoaderUtil) getUtil()).stopSubTask(url); ((AbsGroupLoaderUtil) getTaskUtil()).stopSubTask(url);
} }
} }
} }

@ -18,10 +18,9 @@ package com.arialyy.aria.core.task;
import android.text.TextUtils; import android.text.TextUtils;
import com.arialyy.aria.core.common.AbsEntity; import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.inf.ITaskOption; import com.arialyy.aria.core.inf.ITaskOption;
import com.arialyy.aria.core.inf.IUtil; import com.arialyy.aria.core.inf.ITaskUtil;
import com.arialyy.aria.core.inf.TaskSchedulerType; import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.ComponentUtil;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import timber.log.Timber; import timber.log.Timber;
@ -32,7 +31,7 @@ import timber.log.Timber;
public abstract class AbsTask implements ITask { public abstract class AbsTask implements ITask {
protected ITaskOption mTaskOption; protected ITaskOption mTaskOption;
private boolean isCancel = false, isStop = false; private boolean isCancel = false, isStop = false;
private IUtil mUtil; private ITaskUtil mUtil;
/** /**
* 该任务的调度类型 * 该任务的调度类型
*/ */
@ -41,20 +40,19 @@ public abstract class AbsTask implements ITask {
private int taskId = -1; private int taskId = -1;
private final Map<String, Object> mExpand = new HashMap<>(); private final Map<String, Object> mExpand = new HashMap<>();
protected AbsTask(ITaskOption taskOption) { protected AbsTask(ITaskOption taskOption, ITaskUtil util) {
mTaskOption = taskOption; mTaskOption = taskOption;
mUtil = util;
taskId = TaskStatePool.INSTANCE.buildTaskId$PublicComponent_debug(); taskId = TaskStatePool.INSTANCE.buildTaskId$PublicComponent_debug();
TaskStatePool.INSTANCE.putTaskState(getTaskId(), mTaskState); TaskStatePool.INSTANCE.putTaskState(getTaskId(), mTaskState);
util.init(this, taskOption.taskListener);
} }
@Override public void setState(int state) { @Override public void setState(int state) {
mTaskState.setState(state); mTaskState.setState(state);
} }
synchronized IUtil getUtil() { ITaskUtil getTaskUtil() {
if (mUtil == null) {
mUtil = ComponentUtil.getInstance().buildUtil(mTaskWrapper, mListener);
}
return mUtil; return mUtil;
} }
@ -154,13 +152,13 @@ public abstract class AbsTask implements ITask {
@Override public void start(int type) { @Override public void start(int type) {
mSchedulerType = type; mSchedulerType = type;
mUtil = getUtil(); mUtil = getTaskUtil();
if (mUtil == null) { if (mUtil == null) {
Timber.e("util is null"); Timber.e("util is null");
return; return;
} }
if (type == TaskSchedulerType.TYPE_START_AND_RESET_STATE) { if (type == TaskSchedulerType.TYPE_START_AND_RESET_STATE) {
if (getUtil().isRunning()) { if (getTaskUtil().isRunning()) {
Timber.e("task restart fail"); Timber.e("task restart fail");
return; return;
} }
@ -168,33 +166,33 @@ public abstract class AbsTask implements ITask {
Timber.e("task restart success"); Timber.e("task restart success");
return; return;
} }
if (getUtil().isRunning()) { if (getTaskUtil().isRunning()) {
Timber.d("task is running"); Timber.d("task is running");
return; return;
} }
getUtil().start(); getTaskUtil().start();
} }
@Override public void stop(int type) { @Override public void stop(int type) {
mUtil = getUtil(); mUtil = getTaskUtil();
if (mUtil == null) { if (mUtil == null) {
Timber.e("util is null"); Timber.e("util is null");
return; return;
} }
isStop = true; isStop = true;
mSchedulerType = type; mSchedulerType = type;
getUtil().stop(); getTaskUtil().stop();
} }
@Override public void cancel(int type) { @Override public void cancel(int type) {
mUtil = getUtil(); mUtil = getTaskUtil();
if (mUtil == null) { if (mUtil == null) {
Timber.e("util is null"); Timber.e("util is null");
return; return;
} }
isCancel = true; isCancel = true;
mSchedulerType = type; mSchedulerType = type;
getUtil().cancel(); getTaskUtil().cancel();
} }
/** /**
@ -203,7 +201,7 @@ public abstract class AbsTask implements ITask {
* @return {@code true} 正在下载 * @return {@code true} 正在下载
*/ */
@Override public boolean isRunning() { @Override public boolean isRunning() {
return getUtil().isRunning(); return getTaskUtil().isRunning();
} }
/** /**

@ -0,0 +1,63 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.task
import com.arialyy.aria.core.inf.ITaskUtil
import com.arialyy.aria.core.listener.IEventListener
import com.arialyy.aria.core.task.ITaskInterceptor.IChain
/**
* @Author laoyuyu
* @Description
* @Date 1:12 PM 2023/1/28
**/
abstract class AbsTaskUtil : ITaskUtil {
protected lateinit var mTask: ITask
protected lateinit var mEventListener: IEventListener
private val mUserInterceptor = mutableListOf<ITaskInterceptor>()
private val mCoreInterceptor = mutableListOf<ITaskInterceptor>()
override fun init(task: ITask, listener: IEventListener) {
mTask = task
mEventListener = listener
}
/**
* add user interceptor
*/
open fun setInterceptors(userInterceptors: List<ITaskInterceptor>) {
mUserInterceptor.addAll(userInterceptors)
}
protected open fun addCoreInterceptor(interceptor: ITaskInterceptor) {
mCoreInterceptor.add(interceptor)
}
/**
* if interruption occurred, stop cmd
*/
protected open fun interceptor(): TaskResp? {
if (mUserInterceptor.isEmpty()) {
return null
}
val interceptors: MutableList<ITaskInterceptor> = ArrayList()
interceptors.addAll(mUserInterceptor)
interceptors.addAll(mCoreInterceptor)
val chain: IChain = TaskChain(interceptors, 0, mTask)
return chain.proceed(mTask)
}
}

@ -18,6 +18,7 @@ package com.arialyy.aria.core.task;
import android.net.Uri; import android.net.Uri;
import com.arialyy.aria.core.download.DTaskOption; import com.arialyy.aria.core.download.DTaskOption;
import com.arialyy.aria.core.inf.ITaskUtil;
/** /**
* Created by lyy on 2016/8/11. * Created by lyy on 2016/8/11.
@ -25,8 +26,8 @@ import com.arialyy.aria.core.download.DTaskOption;
*/ */
public class DownloadTask extends AbsTask { public class DownloadTask extends AbsTask {
public DownloadTask(DTaskOption taskOption) { public DownloadTask(DTaskOption taskOption, ITaskUtil util) {
super(taskOption); super(taskOption, util);
taskOption.taskListener.setParams(this); taskOption.taskListener.setParams(this);
} }

@ -0,0 +1,31 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.task
/**
* @Author laoyuyu
* @Description
* @Date 1:19 PM 2023/1/28
**/
interface ITaskInterceptor {
fun interceptor(chain: TaskChain): TaskResp
interface IChain {
fun getTask(): ITask
fun proceed(task: ITask): TaskResp
}
}

@ -13,10 +13,11 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.orm package com.arialyy.aria.core.task
import com.arialyy.aria.core.inf.BaseEntity import com.arialyy.aria.core.inf.BaseEntity
import com.arialyy.aria.core.inf.IEntity import com.arialyy.aria.core.inf.IEntity
import com.arialyy.aria.core.inf.ITaskUtil
import timber.log.Timber import timber.log.Timber
/** /**
@ -24,15 +25,34 @@ import timber.log.Timber
* @Description * @Description
* @Date 21:43 AM 2023/1/22 * @Date 21:43 AM 2023/1/22
**/ **/
object EntityCachePool { object TaskCachePool {
/** /**
* key: taskId * key: taskId
*/ */
private val entityMap = hashMapOf<Int, BaseEntity>() private val entityMap = hashMapOf<Int, BaseEntity>()
private val taskUtilMap = hashMapOf<String, ITaskUtil>()
/**
* @param taskKey task unique identifier, like: savePath, sourceUrl
*/
fun putTaskUtil(taskKey: String, taskUtil: ITaskUtil) {
if (taskKey.isEmpty()) {
Timber.e("invalid taskKey: $taskKey")
return
}
taskUtilMap[taskKey] = taskUtil
}
/**
* @param taskKey task unique identifier, like: savePath, sourceUrl
*/
fun getTaskUtil(taskKey: String): ITaskUtil? {
return taskUtilMap[taskKey]
}
fun putEntity(taskId: Int, entity: BaseEntity) { fun putEntity(taskId: Int, entity: BaseEntity) {
if (taskId <= 0) { if (taskId <= 0) {
Timber.e("invalid taskId: ${taskId}") Timber.e("invalid taskId: $taskId")
return return
} }
entityMap[taskId] = entity entityMap[taskId] = entity

@ -0,0 +1,38 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.task
/**
* @Author laoyuyu
* @Description
* @Date 11:06 AM 2023/1/27
**/
class TaskChain(
private val interceptors: List<ITaskInterceptor>,
private val index: Int = 0,
private val task: ITask,
) : ITaskInterceptor.IChain {
override fun getTask(): ITask {
return task
}
override fun proceed(task: ITask): TaskResp {
val next = TaskChain(interceptors, index, task)
val interceptor = interceptors[index]
return interceptor.interceptor(next)
}
}

@ -0,0 +1,17 @@
package com.arialyy.aria.core.task
/**
* @Author laoyuyu
* @Description
* @Date 1:43 PM 2023/1/28
**/
class TaskResp(val code: Int = CODE_DEF) {
companion object {
const val CODE_COMPLETE = 1
const val CODE_INTERRUPT = 999
const val CODE_DEF = 0
const val CODE_GET_FILE_INFO_FAIL = 2
}
var fileSize: Long = 0
}

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

Loading…
Cancel
Save