From 4d75151abc1846eedef97de094f624c296e7c95b Mon Sep 17 00:00:00 2001 From: dongliang Date: Thu, 30 Apr 2026 21:58:56 +0930 Subject: [PATCH] =?UTF-8?q?fix:=20OTA=20=E4=B8=8B=E8=BD=BD=E5=8A=A0=20TLS?= =?UTF-8?q?=201.2=20=E5=85=BC=E5=AE=B9=EF=BC=88Android=208.1=20SSL=20?= =?UTF-8?q?=E6=8F=A1=E6=89=8B=E5=A4=B1=E8=B4=A5=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Android 8.1 默认 SSL 不兼容阿里云 OSS 导致 SSLHandshakeException。 显式配置 TLSv1.2 + 现代密码套件。同时读超时 60→120s 适配大 APK。 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../watch/service/manager/UpdateManager.kt | 40 ++++++++++++++++--- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/xiaoqu/watch/service/manager/UpdateManager.kt b/app/src/main/java/com/xiaoqu/watch/service/manager/UpdateManager.kt index 3632e51..e487e10 100644 --- a/app/src/main/java/com/xiaoqu/watch/service/manager/UpdateManager.kt +++ b/app/src/main/java/com/xiaoqu/watch/service/manager/UpdateManager.kt @@ -12,12 +12,18 @@ import com.xiaoqu.watch.network.safeApiCall import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import okhttp3.ConnectionSpec import okhttp3.OkHttpClient import okhttp3.Request +import okhttp3.TlsVersion import timber.log.Timber import java.io.File import java.io.IOException +import java.security.KeyStore import java.util.concurrent.TimeUnit +import javax.net.ssl.SSLContext +import javax.net.ssl.TrustManagerFactory +import javax.net.ssl.X509TrustManager import javax.inject.Inject import javax.inject.Singleton @@ -52,11 +58,35 @@ class UpdateManager @Inject constructor( var isUpdating = false /** 独立的下载用 OkHttpClient(不复用业务 API 的 client,避免签名拦截器干扰) */ - private val downloadClient = OkHttpClient.Builder() - .connectTimeout(30, TimeUnit.SECONDS) - .readTimeout(60, TimeUnit.SECONDS) - .writeTimeout(10, TimeUnit.SECONDS) - .build() + private val downloadClient: OkHttpClient by lazy { + // Android 8.1 的默认 SSL 可能不兼容某些服务器(如阿里云 OSS) + // 显式启用 TLS 1.2 + 兼容的连接规格 + val builder = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS) + .readTimeout(120, TimeUnit.SECONDS) // APK 较大,放宽读超时 + .writeTimeout(10, TimeUnit.SECONDS) + + try { + val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()) + trustManagerFactory.init(null as KeyStore?) + val trustManager = trustManagerFactory.trustManagers[0] as X509TrustManager + + val sslContext = SSLContext.getInstance("TLSv1.2") + sslContext.init(null, arrayOf(trustManager), null) + + // 兼容的连接规格:支持 TLS 1.2 和现代密码套件 + val connectionSpec = ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) + .tlsVersions(TlsVersion.TLS_1_2) + .build() + + builder.sslSocketFactory(sslContext.socketFactory, trustManager) + .connectionSpecs(listOf(connectionSpec, ConnectionSpec.CLEARTEXT)) + } catch (e: Exception) { + Timber.w(e, "OTA: TLS 配置失败,使用默认配置") + } + + builder.build() + } /** * 检查版本更新(5 分钟最小间隔)