mirror of
https://github.com/gedoor/legado.git
synced 2024-08-30 09:23:26 +08:00
commit
6187636659
@ -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…
Reference in New Issue
Block a user