Merge pull request #2425 from ag2s20150909/master

fix bugs
pull/2431/head
kunfei 2 years ago committed by GitHub
commit 6187636659
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      app/src/main/java/io/legado/app/help/http/cronet/AbsCallBack.kt
  2. 106
      app/src/main/java/io/legado/app/help/http/cronet/CronetCoroutineInterceptor.kt
  3. 3
      app/src/main/java/io/legado/app/lib/prefs/SwitchPreference.kt
  4. 8
      build.gradle

@ -148,7 +148,7 @@ abstract class AbsCallBack(
override fun onCanceled(request: UrlRequest?, info: UrlResponseInfo?) {
super.onCanceled(request, info)
this.eventListener?.callEnd(mCall)
onError(IOException("Cronet Request Canceled"))
//onError(IOException("Cronet Request Canceled"))
}

@ -0,0 +1,106 @@
package io.legado.app.help.http.cronet
import io.legado.app.utils.printOnDebug
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeout
import okhttp3.*
import okhttp3.internal.http.receiveHeaders
import org.chromium.net.UrlRequest
import org.chromium.net.UrlResponseInfo
import java.io.IOException
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
class CronetCoroutineInterceptor(private val cookieJar: CookieJar = CookieJar.NO_COOKIES) :
Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
if (chain.call().isCanceled()) {
throw IOException("Canceled")
}
val original: Request = chain.request()
//Cronet未初始化
return if (!CronetLoader.install() || cronetEngine == null) {
chain.proceed(original)
} else try {
val builder: Request.Builder = original.newBuilder()
//移除Keep-Alive,手动设置会导致400 BadRequest
builder.removeHeader("Keep-Alive")
builder.removeHeader("Accept-Encoding")
if (cookieJar != CookieJar.NO_COOKIES) {
val cookieStr = getCookie(original.url)
//设置Cookie
if (cookieStr.length > 3) {
builder.addHeader("Cookie", cookieStr)
}
}
val newReq = builder.build()
val timeout = chain.call().timeout().timeoutNanos() / 1000000
runBlocking() {
if (timeout > 0) {
withTimeout(timeout) {
proceedWithCronet(newReq, chain.call()).also { response ->
cookieJar.receiveHeaders(newReq.url, response.headers)
}
}
} else {
proceedWithCronet(newReq, chain.call()).also { response ->
cookieJar.receiveHeaders(newReq.url, response.headers)
}
}
}
} catch (e: Exception) {
//不能抛出错误,抛出错误会导致应用崩溃
//遇到Cronet处理有问题时的情况,如证书过期等等,回退到okhttp处理
if (!e.message.toString().contains("ERR_CERT_", true)
&& !e.message.toString().contains("ERR_SSL_", true)
) {
e.printOnDebug()
}
chain.proceed(original)
}
}
private suspend fun proceedWithCronet(request: Request, call: Call): Response =
suspendCancellableCoroutine<Response> { coroutine ->
val callBack = object : AbsCallBack(originalRequest = request, mCall = call) {
override fun waitForDone(urlRequest: UrlRequest): Response {
TODO("Not yet implemented")
}
override fun onError(error: IOException) {
coroutine.resumeWithException(error)
}
override fun onSuccess(response: Response) {
coroutine.resume(response)
}
override fun onCanceled(request: UrlRequest?, info: UrlResponseInfo?) {
super.onCanceled(request, info)
coroutine.cancel()
}
}
buildRequest(request, callBack)?.start()
}
/** Returns a 'Cookie' HTTP request header with all cookies, like `a=b; c=d`. */
private fun getCookie(url: HttpUrl): String = buildString {
val cookies = cookieJar.loadForRequest(url)
cookies.forEachIndexed { index, cookie ->
if (index > 0) append("; ")
append(cookie.name).append('=').append(cookie.value)
}
}
}

@ -23,7 +23,7 @@ class SwitchPreference(context: Context, attrs: AttributeSet) :
}
override fun onBindViewHolder(holder: PreferenceViewHolder) {
super.onBindViewHolder(holder)
val v = Preference.bindView<SwitchCompat>(
context,
holder,
@ -37,6 +37,7 @@ class SwitchPreference(context: Context, attrs: AttributeSet) :
if (v is SwitchCompat && !v.isInEditMode) {
v.applyTint(context.accentColor)
}
super.onBindViewHolder(holder)
onLongClick?.let { listener ->
holder.itemView.setOnLongClickListener {
listener.invoke(this)

@ -2,9 +2,9 @@
buildscript {
ext{
kotlin_version = '1.7.10'
compose_version = '1.2.1'
compose_compiler_version = '1.3.0'
kotlin_version = '1.7.20'
compose_version = '1.3.0-rc01'
compose_compiler_version = '1.3.2'
agp_version = '7.3.1'
exoplayer_version = '2.18.1'
splitties_version = '3.0.0'
@ -16,7 +16,7 @@ plugins {
id 'com.android.application' version "$agp_version" apply false
id 'com.android.library' version "$agp_version" apply false
id 'org.jetbrains.kotlin.android' version "$kotlin_version" apply false
id "de.undercouch.download" version "5.1.0" apply false
id "de.undercouch.download" version "5.2.1" apply false
id "com.google.gms.google-services" version "4.3.10" apply false
}

Loading…
Cancel
Save