Horis пре 2 година
родитељ
комит
c86afd3002

+ 4 - 1
app/src/main/java/io/legado/app/help/exoplayer/ExoPlayerHelper.kt

@@ -133,7 +133,10 @@ object ExoPlayerHelper {
      * Okhttp DataSource.Factory
      * Okhttp DataSource.Factory
      */
      */
     private val okhttpDataFactory by lazy {
     private val okhttpDataFactory by lazy {
-        OkHttpDataSource.Factory(okHttpClient)
+        val client = okHttpClient.newBuilder()
+            .callTimeout(0, TimeUnit.SECONDS)
+            .build()
+        OkHttpDataSource.Factory(client)
             .setCacheControl(CacheControl.Builder().maxAge(1, TimeUnit.DAYS).build())
             .setCacheControl(CacheControl.Builder().maxAge(1, TimeUnit.DAYS).build())
     }
     }
 
 

+ 6 - 2
app/src/main/java/io/legado/app/lib/cronet/AbsCallBack.kt

@@ -35,6 +35,7 @@ import java.util.concurrent.atomic.AtomicBoolean
 abstract class AbsCallBack(
 abstract class AbsCallBack(
     var originalRequest: Request,
     var originalRequest: Request,
     val mCall: Call,
     val mCall: Call,
+    var readTimeoutMillis: Int,
     private val eventListener: EventListener? = null,
     private val eventListener: EventListener? = null,
     private val responseCallback: Callback? = null
     private val responseCallback: Callback? = null
 ) : UrlRequest.Callback() {
 ) : UrlRequest.Callback() {
@@ -52,6 +53,9 @@ abstract class AbsCallBack(
     private var redirectRequest: Request? = null
     private var redirectRequest: Request? = null
 
 
     init {
     init {
+        if (readTimeoutMillis == 0) {
+            readTimeoutMillis = Int.MAX_VALUE
+        }
         if (originalRequest.header(cookieJarHeader) != null) {
         if (originalRequest.header(cookieJarHeader) != null) {
             enableCookieJar = true
             enableCookieJar = true
             originalRequest = originalRequest.newBuilder()
             originalRequest = originalRequest.newBuilder()
@@ -411,7 +415,7 @@ abstract class AbsCallBack(
 
 
         private var buffer = ByteBuffer.allocateDirect(32 * 1024)
         private var buffer = ByteBuffer.allocateDirect(32 * 1024)
         private var closed = false
         private var closed = false
-        private val timeout = mCall.timeout().timeoutNanos()
+        private val timeout = readTimeoutMillis.toLong()
 
 
         override fun close() {
         override fun close() {
             cancelJob?.cancel()
             cancelJob?.cancel()
@@ -443,7 +447,7 @@ abstract class AbsCallBack(
 
 
             request?.read(buffer)
             request?.read(buffer)
 
 
-            val result = callbackResults.poll(timeout, TimeUnit.NANOSECONDS)
+            val result = callbackResults.poll(timeout, TimeUnit.MILLISECONDS)
             if (result == null) {
             if (result == null) {
                 request?.cancel()
                 request?.cancel()
                 throw IOException("Body Read Timeout")
                 throw IOException("Body Read Timeout")

+ 14 - 5
app/src/main/java/io/legado/app/lib/cronet/CronetCoroutineInterceptor.kt

@@ -5,7 +5,12 @@ import io.legado.app.utils.printOnDebug
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.suspendCancellableCoroutine
 import kotlinx.coroutines.suspendCancellableCoroutine
 import kotlinx.coroutines.withTimeout
 import kotlinx.coroutines.withTimeout
-import okhttp3.*
+import okhttp3.Call
+import okhttp3.CookieJar
+import okhttp3.HttpUrl
+import okhttp3.Interceptor
+import okhttp3.Request
+import okhttp3.Response
 import okhttp3.internal.http.receiveHeaders
 import okhttp3.internal.http.receiveHeaders
 import org.chromium.net.UrlRequest
 import org.chromium.net.UrlRequest
 import org.chromium.net.UrlResponseInfo
 import org.chromium.net.UrlResponseInfo
@@ -43,12 +48,12 @@ class CronetCoroutineInterceptor(private val cookieJar: CookieJar) : Interceptor
             runBlocking() {
             runBlocking() {
                 if (timeout > 0) {
                 if (timeout > 0) {
                     withTimeout(timeout) {
                     withTimeout(timeout) {
-                        proceedWithCronet(newReq, chain.call()).also { response ->
+                        proceedWithCronet(newReq, chain.call(), chain.readTimeoutMillis()).also { response ->
                             cookieJar.receiveHeaders(newReq.url, response.headers)
                             cookieJar.receiveHeaders(newReq.url, response.headers)
                         }
                         }
                     }
                     }
                 } else {
                 } else {
-                    proceedWithCronet(newReq, chain.call()).also { response ->
+                    proceedWithCronet(newReq, chain.call(), chain.readTimeoutMillis()).also { response ->
                         cookieJar.receiveHeaders(newReq.url, response.headers)
                         cookieJar.receiveHeaders(newReq.url, response.headers)
                     }
                     }
                 }
                 }
@@ -68,10 +73,14 @@ class CronetCoroutineInterceptor(private val cookieJar: CookieJar) : Interceptor
     }
     }
 
 
 
 
-    private suspend fun proceedWithCronet(request: Request, call: Call): Response =
+    private suspend fun proceedWithCronet(
+        request: Request,
+        call: Call,
+        readTimeoutMillis: Int
+    ): Response =
         suspendCancellableCoroutine<Response> { coroutine ->
         suspendCancellableCoroutine<Response> { coroutine ->
 
 
-            val callBack = object : AbsCallBack(originalRequest = request, mCall = call) {
+            val callBack = object : AbsCallBack(request, call, readTimeoutMillis) {
                 override fun waitForDone(urlRequest: UrlRequest): Response {
                 override fun waitForDone(urlRequest: UrlRequest): Response {
                     TODO("Not yet implemented")
                     TODO("Not yet implemented")
                 }
                 }

+ 4 - 4
app/src/main/java/io/legado/app/lib/cronet/CronetInterceptor.kt

@@ -27,7 +27,7 @@ class CronetInterceptor(private val cookieJar: CookieJar) : Interceptor {
             builder.removeHeader("Accept-Encoding")
             builder.removeHeader("Accept-Encoding")
 
 
             val newReq = builder.build()
             val newReq = builder.build()
-            proceedWithCronet(newReq, chain.call())/*?.let { response ->
+            proceedWithCronet(newReq, chain.call(), chain.readTimeoutMillis())/*?.let { response ->
                 //从Response 中保存Cookie到CookieJar
                 //从Response 中保存Cookie到CookieJar
                 //cookieJar.receiveHeaders(newReq.url, response.headers)
                 //cookieJar.receiveHeaders(newReq.url, response.headers)
                 response
                 response
@@ -45,11 +45,11 @@ class CronetInterceptor(private val cookieJar: CookieJar) : Interceptor {
     }
     }
 
 
     @SuppressLint("ObsoleteSdkInt")
     @SuppressLint("ObsoleteSdkInt")
-    private fun proceedWithCronet(request: Request, call: Call): Response? {
+    private fun proceedWithCronet(request: Request, call: Call, readTimeoutMillis: Int): Response? {
         val callBack = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
         val callBack = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-            NewCallBack(request, call)
+            NewCallBack(request, call, readTimeoutMillis)
         } else {
         } else {
-            OldCallback(request, call)
+            OldCallback(request, call, readTimeoutMillis)
         }
         }
         buildRequest(request, callBack)?.runCatching {
         buildRequest(request, callBack)?.runCatching {
             return callBack.waitForDone(this)
             return callBack.waitForDone(this)

+ 2 - 1
app/src/main/java/io/legado/app/lib/cronet/NewCallBack.kt

@@ -15,7 +15,8 @@ import java.util.concurrent.TimeUnit
 @SuppressLint("ObsoleteSdkInt")
 @SuppressLint("ObsoleteSdkInt")
 @Keep
 @Keep
 @RequiresApi(api = Build.VERSION_CODES.N)
 @RequiresApi(api = Build.VERSION_CODES.N)
-class NewCallBack(originalRequest: Request, mCall: Call) : AbsCallBack(originalRequest, mCall) {
+class NewCallBack(originalRequest: Request, mCall: Call, readTimeoutMillis: Int) :
+    AbsCallBack(originalRequest, mCall, readTimeoutMillis) {
 
 
     private val responseFuture = CompletableFuture<Response>()
     private val responseFuture = CompletableFuture<Response>()
 
 

+ 2 - 1
app/src/main/java/io/legado/app/lib/cronet/OldCallback.kt

@@ -9,7 +9,8 @@ import org.chromium.net.UrlRequest
 import java.io.IOException
 import java.io.IOException
 
 
 @Keep
 @Keep
-class OldCallback(originalRequest: Request, mCall: Call) : AbsCallBack(originalRequest, mCall) {
+class OldCallback(originalRequest: Request, mCall: Call, readTimeoutMillis: Int) :
+    AbsCallBack(originalRequest, mCall, readTimeoutMillis) {
 
 
     private val mResponseCondition = ConditionVariable()
     private val mResponseCondition = ConditionVariable()
     private var mException: IOException? = null
     private var mException: IOException? = null

+ 2 - 0
app/src/main/java/io/legado/app/lib/webdav/WebDav.kt

@@ -30,6 +30,7 @@ import java.net.URLEncoder
 import java.time.LocalDateTime
 import java.time.LocalDateTime
 import java.time.ZoneOffset
 import java.time.ZoneOffset
 import java.time.format.DateTimeFormatter
 import java.time.format.DateTimeFormatter
+import java.util.concurrent.TimeUnit
 
 
 @Suppress("unused", "MemberVisibilityCanBePrivate")
 @Suppress("unused", "MemberVisibilityCanBePrivate")
 open class WebDav(
 open class WebDav(
@@ -97,6 +98,7 @@ open class WebDav(
             chain.proceed(request)
             chain.proceed(request)
         }
         }
         okHttpClient.newBuilder().run {
         okHttpClient.newBuilder().run {
+            callTimeout(0, TimeUnit.SECONDS)
             interceptors().add(0, authInterceptor)
             interceptors().add(0, authInterceptor)
             addNetworkInterceptor(authInterceptor)
             addNetworkInterceptor(authInterceptor)
             build()
             build()

+ 18 - 5
app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt

@@ -27,12 +27,15 @@ import io.legado.app.utils.*
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.runBlocking
 import okhttp3.MediaType.Companion.toMediaType
 import okhttp3.MediaType.Companion.toMediaType
+import okhttp3.OkHttpClient
 import okhttp3.RequestBody.Companion.toRequestBody
 import okhttp3.RequestBody.Companion.toRequestBody
 import okhttp3.Response
 import okhttp3.Response
 import java.io.ByteArrayInputStream
 import java.io.ByteArrayInputStream
 import java.io.InputStream
 import java.io.InputStream
 import java.net.URLEncoder
 import java.net.URLEncoder
+import java.util.concurrent.TimeUnit
 import java.util.regex.Pattern
 import java.util.regex.Pattern
+import kotlin.math.max
 
 
 /**
 /**
  * Created by GKF on 2018/1/24.
  * Created by GKF on 2018/1/24.
@@ -51,6 +54,7 @@ class AnalyzeUrl(
     private val source: BaseSource? = null,
     private val source: BaseSource? = null,
     private val ruleData: RuleDataInterface? = null,
     private val ruleData: RuleDataInterface? = null,
     private val chapter: BookChapter? = null,
     private val chapter: BookChapter? = null,
+    private val readTimeout: Long? = null,
     headerMapF: Map<String, String>? = null,
     headerMapF: Map<String, String>? = null,
 ) : JsExtensions {
 ) : JsExtensions {
     companion object {
     companion object {
@@ -404,7 +408,7 @@ class AnalyzeUrl(
             if (this.useWebView && useWebView) {
             if (this.useWebView && useWebView) {
                 strResponse = when (method) {
                 strResponse = when (method) {
                     RequestMethod.POST -> {
                     RequestMethod.POST -> {
-                        val res = getProxyClient(proxy).newCallStrResponse(retry) {
+                        val res = getClient().newCallStrResponse(retry) {
                             addHeaders(headerMap)
                             addHeaders(headerMap)
                             url(urlNoQuery)
                             url(urlNoQuery)
                             if (fieldMap.isNotEmpty() || body.isNullOrBlank()) {
                             if (fieldMap.isNotEmpty() || body.isNullOrBlank()) {
@@ -432,7 +436,7 @@ class AnalyzeUrl(
                     ).getStrResponse()
                     ).getStrResponse()
                 }
                 }
             } else {
             } else {
-                strResponse = getProxyClient(proxy).newCallStrResponse(retry) {
+                strResponse = getClient().newCallStrResponse(retry) {
                     addHeaders(headerMap)
                     addHeaders(headerMap)
                     when (method) {
                     when (method) {
                         RequestMethod.POST -> {
                         RequestMethod.POST -> {
@@ -484,7 +488,7 @@ class AnalyzeUrl(
         val concurrentRecord = getConcurrentRecord()
         val concurrentRecord = getConcurrentRecord()
         try {
         try {
             setCookie()
             setCookie()
-            val response = getProxyClient(proxy).newCallResponse(retry) {
+            val response = getClient().newCallResponse(retry) {
                 addHeaders(headerMap)
                 addHeaders(headerMap)
                 when (method) {
                 when (method) {
                     RequestMethod.POST -> {
                     RequestMethod.POST -> {
@@ -511,15 +515,24 @@ class AnalyzeUrl(
         }
         }
     }
     }
 
 
+    private fun getClient(): OkHttpClient {
+        val client = getProxyClient(proxy)
+        if (readTimeout == null) {
+            return client
+        }
+        return client.newBuilder()
+            .readTimeout(readTimeout, TimeUnit.MILLISECONDS)
+            .callTimeout(max(60 * 1000L, readTimeout * 2), TimeUnit.MILLISECONDS)
+            .build()
+    }
+
     fun getResponse(): Response {
     fun getResponse(): Response {
         return runBlocking {
         return runBlocking {
             getResponseAwait()
             getResponseAwait()
         }
         }
     }
     }
 
 
-    @Suppress("UnnecessaryVariable")
     private fun getByteArrayIfDataUri(): ByteArray? {
     private fun getByteArrayIfDataUri(): ByteArray? {
-        @Suppress("RegExpRedundantEscape")
         val dataUriFindResult = dataUriRegex.find(urlNoQuery)
         val dataUriFindResult = dataUriRegex.find(urlNoQuery)
         if (dataUriFindResult != null) {
         if (dataUriFindResult != null) {
             val dataUriBase64 = dataUriFindResult.groupValues[1]
             val dataUriBase64 = dataUriFindResult.groupValues[1]

+ 2 - 1
app/src/main/java/io/legado/app/service/HttpReadAloudService.kt

@@ -167,7 +167,8 @@ class HttpReadAloudService : BaseReadAloudService(),
                     speakText = speakText,
                     speakText = speakText,
                     speakSpeed = speechRate,
                     speakSpeed = speechRate,
                     source = httpTts,
                     source = httpTts,
-                    headerMapF = httpTts.getHeaderMap(true)
+                    headerMapF = httpTts.getHeaderMap(true),
+                    readTimeout = 300 * 1000L
                 )
                 )
                 var response = analyzeUrl.getResponseAwait()
                 var response = analyzeUrl.getResponseAwait()
                 coroutineContext.ensureActive()
                 coroutineContext.ensureActive()