feat: Android 4.2 兼容改造
- minSdk 19 -> 17(config.gradle) - OkHttp 4.12 -> 3.12.0(app build.gradle 新老双栈统一锁定) - Retrofit 2.11 -> 2.6.0 + Coroutines 1.8.1 -> 1.6.4 - SignRequestPolicy: toHttpUrlOrNull -> HttpUrl.parse(3.12 API 适配) - HeaderInterceptor/SignAuthenticator: 属性访问改方法调用(url()/request()/priorResponse()) - VideoViewTv: SDK_INT<19 强制切 AndroidMediaPlayer 内核 + instanceof 短路保护 - AndroidManifest: overrideLibrary OAID 4.1.3(minSdk 19) - 全局 resolutionStrategy.force 锁定 OkHttp/Retrofit 版本
This commit is contained in:
@@ -26,7 +26,8 @@ class HeaderInterceptor : Interceptor {
|
||||
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
val original = chain.request()
|
||||
val path = SignRequestPolicy.relativePath(original.url.toString())
|
||||
// OkHttp 3.12 兼容:Java 版字段访问需用方法调用(url()),4.x 的 Kotlin val 语法不可用
|
||||
val path = SignRequestPolicy.relativePath(original.url().toString())
|
||||
|
||||
val builder = original.newBuilder()
|
||||
|
||||
|
||||
@@ -55,7 +55,8 @@ class SignAuthenticator : Authenticator {
|
||||
private var credentialBroken: Boolean = false
|
||||
|
||||
override fun authenticate(route: Route?, response: Response): Request? {
|
||||
val path = SignRequestPolicy.relativePath(response.request.url.toString())
|
||||
// OkHttp 3.12 兼容:Java 版 request()/priorResponse() 方法调用(4.x Kotlin val 语法不可用)
|
||||
val path = SignRequestPolicy.relativePath(response.request().url().toString())
|
||||
|
||||
// 保护 1:首签/刷新接口 401 直接放行
|
||||
if (!SignRequestPolicy.shouldTriggerRefresh(path)) {
|
||||
@@ -63,12 +64,12 @@ class SignAuthenticator : Authenticator {
|
||||
}
|
||||
|
||||
// 保护 2:刷新调用本身带 X-Refresh-Call=1 标记,Authenticator 见到放行
|
||||
if (response.request.header(HEADER_REFRESH_CALL) == "1") {
|
||||
if (response.request().header(HEADER_REFRESH_CALL) == "1") {
|
||||
return null
|
||||
}
|
||||
|
||||
// 保护 3:priorResponse 链上已有 X-Refresh-Marker,说明已刷新过一次仍 401,放弃
|
||||
val prior = response.priorResponse
|
||||
val prior = response.priorResponse()
|
||||
if (prior != null && prior.header(HEADER_REFRESH_MARKER) != null) {
|
||||
return null
|
||||
}
|
||||
@@ -104,7 +105,7 @@ class SignAuthenticator : Authenticator {
|
||||
Network.tokenStore.refreshAndPersist(newSign)
|
||||
|
||||
// 重建原 Request:保留所有原有 headers,注入新 sign 头 + X-Refresh-Marker 标记
|
||||
response.request.newBuilder()
|
||||
response.request().newBuilder()
|
||||
.header("sign", newSign)
|
||||
.header(HEADER_REFRESH_MARKER, "1")
|
||||
.build()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.pukka.jiecheng.network.auth
|
||||
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import okhttp3.HttpUrl
|
||||
|
||||
/**
|
||||
* sign 头注入 / 401 刷新触发策略。
|
||||
@@ -36,11 +36,14 @@ object SignRequestPolicy {
|
||||
|
||||
/**
|
||||
* 提取相对 baseUrl 的 path(去掉 query/fragment),用于上述匹配。
|
||||
*
|
||||
* 注意:HttpUrl.parse 是 OkHttp 3.12 的 API(4.x 才有 toHttpUrlOrNull 扩展),
|
||||
* 项目已为 Android 4.2 兼容全局锁定 OkHttp 3.12.0,勿改回扩展函数。
|
||||
*/
|
||||
fun relativePath(absoluteUrl: String): String {
|
||||
val url = absoluteUrl.toHttpUrlOrNull() ?: return absoluteUrl
|
||||
val url = HttpUrl.parse(absoluteUrl) ?: return absoluteUrl
|
||||
// pathSegments.joinToString("/") 自动处理首尾斜杠
|
||||
return url.encodedPath.trimStart('/').let {
|
||||
return url.encodedPath().trimStart('/').let {
|
||||
// 去掉 /api/ 前缀,匹配 Set<String> 中的相对路径
|
||||
if (it.startsWith("api/")) it.removePrefix("api/") else it
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user