diff --git a/app/src/main/java/io/legado/app/help/http/cronet/AbsCallBack.kt b/app/src/main/java/io/legado/app/help/http/cronet/AbsCallBack.kt index 56f5b4bfd..0728b1db3 100644 --- a/app/src/main/java/io/legado/app/help/http/cronet/AbsCallBack.kt +++ b/app/src/main/java/io/legado/app/help/http/cronet/AbsCallBack.kt @@ -2,7 +2,7 @@ package io.legado.app.help.http.cronet import io.legado.app.help.http.okHttpClient import io.legado.app.utils.DebugLog -import io.legado.app.utils.rethrowAsIOException +import io.legado.app.utils.asIOException import okhttp3.* import okhttp3.EventListener import okhttp3.MediaType.Companion.toMediaTypeOrNull @@ -27,12 +27,24 @@ abstract class AbsCallBack( var mResponse: Response - var mException: IOException? = null private var followCount = 0 + @Throws(IOException::class) abstract fun waitForDone(urlRequest: UrlRequest): Response + /** + * 当发生错误时,通知子类终止阻塞抛出错误 + * @param error + */ + abstract fun onError(error: IOException) + + /** + * 请求成功后,通知子类结束阻塞,返回response + * @param response + */ + abstract fun onSuccess(response: Response) + override fun onRedirectReceived( request: UrlRequest, @@ -41,10 +53,13 @@ abstract class AbsCallBack( ) { if (followCount > MAX_FOLLOW_COUNT) { request.cancel() - mException = IOException("Too many redirect") + onError(IOException("Too many redirect")) + return } if (mCall.isCanceled()) { - mException = IOException("Request Canceled") + onError(IOException("Request Canceled")) + request.cancel() + return } followCount += 1 val client = okHttpClient @@ -55,7 +70,7 @@ abstract class AbsCallBack( } else if (okHttpClient.followRedirects) { request.followRedirect() } else { - mException = IOException("Too many redirect") + onError(IOException("Too many redirect")) request.cancel() } } @@ -73,7 +88,7 @@ abstract class AbsCallBack( } - @Throws(Exception::class) + @Throws(IOException::class) override fun onReadCompleted( request: UrlRequest, info: UrlResponseInfo, @@ -83,7 +98,7 @@ abstract class AbsCallBack( if (mCall.isCanceled()) { request.cancel() - mException = IOException("Request Canceled") + onError(IOException("Request Canceled")) } byteBuffer.flip() @@ -91,9 +106,9 @@ abstract class AbsCallBack( try { buffer.write(byteBuffer) } catch (e: IOException) { - DebugLog.i(javaClass.name, "IOException during ByteBuffer read. Details: ", e) - mException = IOException("IOException during ByteBuffer read. Details:", e) - throw e + DebugLog.e(javaClass.name, "IOException during ByteBuffer read. Details: ", e) + onError(IOException("IOException during ByteBuffer read. Details:", e)) + return } byteBuffer.clear() request.read(byteBuffer) @@ -108,7 +123,8 @@ abstract class AbsCallBack( buffer.asResponseBody(contentType) val newRequest = originalRequest.newBuilder().url(info.url).build() this.mResponse = this.mResponse.newBuilder().body(responseBody).request(newRequest).build() - DebugLog.i(javaClass.simpleName, "end[${info.negotiatedProtocol}]${info.url}") + onSuccess(this.mResponse) + //DebugLog.i(javaClass.simpleName, "end[${info.negotiatedProtocol}]${info.url}") eventListener?.callEnd(mCall) if (responseCallback != null) { @@ -123,8 +139,8 @@ abstract class AbsCallBack( //UrlResponseInfo可能为null override fun onFailed(request: UrlRequest, info: UrlResponseInfo?, error: CronetException) { - DebugLog.i(javaClass.name, error.message.toString()) - mException = error.rethrowAsIOException() + DebugLog.e(javaClass.name, error.message.toString()) + onError(error.asIOException()) this.eventListener?.callFailed(mCall, error) responseCallback?.onFailure(mCall, error) } @@ -132,7 +148,7 @@ abstract class AbsCallBack( override fun onCanceled(request: UrlRequest?, info: UrlResponseInfo?) { super.onCanceled(request, info) this.eventListener?.callEnd(mCall) - mException = IOException("Cronet Request Canceled") + onError(IOException("Cronet Request Canceled")) } diff --git a/app/src/main/java/io/legado/app/help/http/cronet/CronetHelper.kt b/app/src/main/java/io/legado/app/help/http/cronet/CronetHelper.kt index c3e2ae992..954d2f62f 100644 --- a/app/src/main/java/io/legado/app/help/http/cronet/CronetHelper.kt +++ b/app/src/main/java/io/legado/app/help/http/cronet/CronetHelper.kt @@ -2,6 +2,7 @@ package io.legado.app.help.http.cronet import io.legado.app.constant.AppLog import io.legado.app.help.config.AppConfig +import io.legado.app.help.http.okHttpClient import io.legado.app.utils.DebugLog import okhttp3.Headers import okhttp3.MediaType @@ -13,11 +14,8 @@ import org.chromium.net.UploadDataProviders import org.chromium.net.UrlRequest import splitties.init.appCtx -import java.util.concurrent.ExecutorService -import java.util.concurrent.Executors - -val executor: ExecutorService by lazy { Executors.newCachedThreadPool() } +//val executor: ExecutorService by lazy { Executors.newCachedThreadPool() } val cronetEngine: ExperimentalCronetEngine? by lazy { if (!AppConfig.isGooglePlay) { @@ -48,7 +46,11 @@ fun buildRequest(request: Request, callback: UrlRequest.Callback): UrlRequest? { val url = request.url.toString() val headers: Headers = request.headers val requestBody = request.body - return cronetEngine?.newUrlRequestBuilder(url, callback, executor)?.apply { + return cronetEngine?.newUrlRequestBuilder( + url, + callback, + okHttpClient.dispatcher.executorService + )?.apply { setHttpMethod(request.method)//设置 allowDirectExecutor() headers.forEachIndexed { index, _ -> @@ -65,7 +67,7 @@ fun buildRequest(request: Request, callback: UrlRequest.Callback): UrlRequest? { requestBody.writeTo(buffer) setUploadDataProvider( UploadDataProviders.create(buffer.readByteArray()), - executor + okHttpClient.dispatcher.executorService ) } diff --git a/app/src/main/java/io/legado/app/help/http/cronet/CronetInterceptor.kt b/app/src/main/java/io/legado/app/help/http/cronet/CronetInterceptor.kt index 124b6163f..74b685128 100644 --- a/app/src/main/java/io/legado/app/help/http/cronet/CronetInterceptor.kt +++ b/app/src/main/java/io/legado/app/help/http/cronet/CronetInterceptor.kt @@ -49,7 +49,6 @@ class CronetInterceptor(private val cookieJar: CookieJar?) : Interceptor { OldCallback(request, call) } buildRequest(request, callBack)?.let { - it.start() return callBack.waitForDone(it) } return null diff --git a/app/src/main/java/io/legado/app/help/http/cronet/CronetLoader.kt b/app/src/main/java/io/legado/app/help/http/cronet/CronetLoader.kt index b06d0719b..34ad3e5f5 100644 --- a/app/src/main/java/io/legado/app/help/http/cronet/CronetLoader.kt +++ b/app/src/main/java/io/legado/app/help/http/cronet/CronetLoader.kt @@ -268,7 +268,8 @@ object CronetLoader : CronetEngine.Builder.LibraryLoader() { return } download = true - executor.execute { + + Coroutine.async { val result = downloadFileIfNotExist(url, downloadTempFile) DebugLog.d(javaClass.simpleName, "download result:$result") //文件md5再次校验 @@ -279,7 +280,7 @@ object CronetLoader : CronetEngine.Builder.LibraryLoader() { downloadTempFile.deleteOnExit() } download = false - return@execute + return@async } DebugLog.d(javaClass.simpleName, "download success, copy to $destSuccessFile") //下载成功拷贝文件 @@ -289,6 +290,9 @@ object CronetLoader : CronetEngine.Builder.LibraryLoader() { @Suppress("SameParameterValue") deleteHistoryFile(parentFile!!, null) } +// executor.execute { +// +// } } /** diff --git a/app/src/main/java/io/legado/app/help/http/cronet/NewCallBack.kt b/app/src/main/java/io/legado/app/help/http/cronet/NewCallBack.kt index 6a0d0eeff..7960f54f8 100644 --- a/app/src/main/java/io/legado/app/help/http/cronet/NewCallBack.kt +++ b/app/src/main/java/io/legado/app/help/http/cronet/NewCallBack.kt @@ -6,11 +6,8 @@ import androidx.annotation.RequiresApi import okhttp3.Call import okhttp3.Request import okhttp3.Response -import org.chromium.net.CronetException import org.chromium.net.UrlRequest -import org.chromium.net.UrlResponseInfo import java.io.IOException -import java.nio.ByteBuffer import java.util.concurrent.CompletableFuture import java.util.concurrent.TimeUnit @@ -21,45 +18,29 @@ class NewCallBack(originalRequest: Request, mCall: Call) : AbsCallBack(originalR @Throws(IOException::class) override fun waitForDone(urlRequest: UrlRequest): Response { - return responseFuture.get(mCall.timeout().timeoutNanos(), TimeUnit.NANOSECONDS) - } - - override fun onRedirectReceived( - request: UrlRequest, - info: UrlResponseInfo, - newLocationUrl: String - ) { - super.onRedirectReceived(request, info, newLocationUrl) - if (mException != null) { - responseFuture.completeExceptionally(mException) + urlRequest.start() + return if (mCall.timeout().timeoutNanos() > 0) { + responseFuture.get(mCall.timeout().timeoutNanos(), TimeUnit.NANOSECONDS) + } else { + return responseFuture.get() } - } - - - override fun onReadCompleted( - request: UrlRequest, - info: UrlResponseInfo, - byteBuffer: ByteBuffer - ) { - super.onReadCompleted(request, info, byteBuffer) - if (mException != null) { - responseFuture.completeExceptionally(mException) - } - } - override fun onSucceeded(request: UrlRequest, info: UrlResponseInfo) { - super.onSucceeded(request, info) - responseFuture.complete(mResponse) } - override fun onFailed(request: UrlRequest, info: UrlResponseInfo?, error: CronetException) { - super.onFailed(request, info, error) - responseFuture.completeExceptionally(mException) + /** + * 当发生错误时,通知子类终止阻塞抛出错误 + * @param error + */ + override fun onError(error: IOException) { + responseFuture.completeExceptionally(error) } - override fun onCanceled(request: UrlRequest?, info: UrlResponseInfo?) { - super.onCanceled(request, info) - responseFuture.completeExceptionally(mException) + /** + * 请求成功后,通知子类结束阻塞,返回response + * @param response + */ + override fun onSuccess(response: Response) { + responseFuture.complete(response) } diff --git a/app/src/main/java/io/legado/app/help/http/cronet/OldCallback.kt b/app/src/main/java/io/legado/app/help/http/cronet/OldCallback.kt index 20ad29c60..3107187df 100644 --- a/app/src/main/java/io/legado/app/help/http/cronet/OldCallback.kt +++ b/app/src/main/java/io/legado/app/help/http/cronet/OldCallback.kt @@ -4,20 +4,19 @@ import android.os.ConditionVariable import okhttp3.Call import okhttp3.Request import okhttp3.Response -import org.chromium.net.CronetException import org.chromium.net.UrlRequest -import org.chromium.net.UrlResponseInfo import java.io.IOException -import java.nio.ByteBuffer class OldCallback(originalRequest: Request, mCall: Call) : AbsCallBack(originalRequest, mCall) { private val mResponseCondition = ConditionVariable() + private var mException: IOException? = null @Throws(IOException::class) override fun waitForDone(urlRequest: UrlRequest): Response { //获取okhttp call的完整请求的超时时间 val timeOutMs: Long = mCall.timeout().timeoutNanos() / 1000000 + urlRequest.start() if (timeOutMs > 0) { mResponseCondition.block(timeOutMs) } else { @@ -32,35 +31,25 @@ class OldCallback(originalRequest: Request, mCall: Call) : AbsCallBack(originalR if (mException != null) { throw mException as IOException } - return this.mResponse + return mResponse } - - override fun onReadCompleted( - request: UrlRequest, - info: UrlResponseInfo, - byteBuffer: ByteBuffer - ) { - super.onReadCompleted(request, info, byteBuffer) - if (mException != null) { - mResponseCondition.open() - } - } - - override fun onSucceeded(request: UrlRequest, info: UrlResponseInfo) { - super.onSucceeded(request, info) + /** + * 当发生错误时,通知子类终止阻塞抛出错误 + * @param error + */ + override fun onError(error: IOException) { + mException = error mResponseCondition.open() } - override fun onFailed(request: UrlRequest, info: UrlResponseInfo?, error: CronetException) { - super.onFailed(request, info, error) + /** + * 请求成功后,通知子类结束阻塞,返回response + * @param response + */ + override fun onSuccess(response: Response) { mResponseCondition.open() } - override fun onCanceled(request: UrlRequest?, info: UrlResponseInfo?) { - super.onCanceled(request, info) - mResponseCondition.open() - } - } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/utils/ThrowableExtensions.kt b/app/src/main/java/io/legado/app/utils/ThrowableExtensions.kt index a5bfaa8fc..088db9b3b 100644 --- a/app/src/main/java/io/legado/app/utils/ThrowableExtensions.kt +++ b/app/src/main/java/io/legado/app/utils/ThrowableExtensions.kt @@ -12,8 +12,8 @@ val Throwable.msg: String } } -fun Throwable.rethrowAsIOException(): IOException { +fun Throwable.asIOException(): IOException { val newException = IOException(this.message) newException.initCause(this) - throw newException + return newException } \ No newline at end of file