如何阻止R8移除Flutter插件第三方库代码并解决编译错误
Flutter插件Release模式下R8编译报错(缺失BouncyCastle/Conscrypt/OpenJSSE类)
背景
我开发了一个Flutter插件,其Android模块引入以下依赖:
implementation 'com.microsoft.signalr:signalr:8.0.4' implementation 'org.slf4j:slf4j-api:2.0.13' implementation 'org.slf4j:slf4j-jdk14:2.0.13' testImplementation 'junit:junit:4.13.2' testImplementation 'org.mockito:mockito-core:5.2.0'
插件托管在GitHub,通过Flutter应用的pubspec.yaml引入依赖。
调试模式下功能正常,但切换到release模式时编译失败,R8报大量类缺失错误:
ERROR: Missing classes detected while running R8. Please add the missing classes or apply additional keep rules that are generated in /Users/haidarmehsen/Work/acksession/flutter/vsa-tablet/build/app/outputs/mapping/release/missing_rules.txt. ERROR: R8: Missing class org.bouncycastle.jsse.BCSSLParameters (referenced from: void okhttp3.internal.platform.BouncyCastlePlatform.configureTlsExtensions(javax.net.ssl.SSLSocket, java.lang.String, java.util.List) and 1 other context) Missing class org.bouncycastle.jsse.BCSSLSocket (referenced from: void okhttp3.internal.platform.BouncyCastlePlatform.configureTlsExtensions(javax.net.ssl.SSLSocket, java.lang.String, java.util.List) and 5 other contexts) Missing class org.bouncycastle.jsse.provider.BouncyCastleJsseProvider (referenced from: void okhttp3.internal.platform.BouncyCastlePlatform.<init>()) Missing class org.conscrypt.Conscrypt$Version (referenced from: boolean okhttp3.internal.platform.ConscryptPlatform$Companion.atLeastVersion(int, int, int)) Missing class org.conscrypt.Conscrypt (referenced from: boolean okhttp3.internal.platform.ConscryptPlatform$Companion.atLeastVersion(int, int, int) and 4 other contexts) Missing class org.conscrypt.ConscryptHostnameVerifier (referenced from: okhttp3.internal.platform.ConscryptPlatform$DisabledHostnameVerifier) Missing class org.openjsse.javax.net.ssl.SSLParameters (referenced from: void okhttp3.internal.platform.OpenJSSEPlatform.configureTlsExtensions(javax.net.ssl.SSLSocket, java.lang.String, java.util.List)) Missing class org.openjsse.javax.net.ssl.SSLSocket (referenced from: void okhttp3.internal.platform.OpenJSSEPlatform.configureTlsExtensions(javax.net.ssl.SSLSocket, java.lang.String, java.util.List) and 1 other context) Missing class org.openjsse.net.ssl.OpenJSSE (referenced from: void okhttp3.internal.platform.OpenJSSEPlatform.<init>()) FAILURE: Build failed with an exception.
自动生成的missing_rules.txt内容:
# Please add these rules to your existing keep rules in order to suppress warnings. # This is generated automatically by the Android Gradle plugin. -dontwarn org.bouncycastle.jsse.BCSSLParameters -dontwarn org.bouncycastle.jsse.BCSSLSocket -dontwarn org.bouncycastle.jsse.provider.BouncyCastleJsseProvider -dontwarn org.conscrypt.Conscrypt$Version -dontwarn org.conscrypt.Conscrypt -dontwarn org.conscrypt.ConscryptHostnameVerifier -dontwarn org.openjsse.javax.net.ssl.SSLParameters -dontwarn org.openjsse.javax.net.ssl.SSLSocket -dontwarn org.openjsse.net.ssl.OpenJSSE
已尝试的方案
- 添加上述
-dontwarn规则:编译通过,但插件运行时报错 - 添加
-keep规则保留缺失类:编译错误依旧-keep class org.bouncycastle.jsse.BCSSLParameters { *; } -keep class org.bouncycastle.jsse.BCSSLSocket { *; } -keep class org.bouncycastle.jsse.provider.BouncyCastleJsseProvider { *; } -keep class org.conscrypt.Conscrypt$Version { *; } -keep class org.conscrypt.Conscrypt { *; } -keep class org.conscrypt.ConscryptHostnameVerifier { *; } -keep class org.openjsse.javax.net.ssl.SSLParameters { *; } -keep class org.openjsse.javax.net.ssl.SSLSocket { *; } -keep class org.openjsse.net.ssl.OpenJSSE { *; } - 完全禁用R8(release配置中
minifyEnabled=false、shrinkResources=false):有效但应用体积翻倍,不接受
问题
如何在不关闭代码压缩的前提下解决该编译错误?
解决方案
这些缺失类是OkHttp为兼容不同TLS实现(BouncyCastle/Conscrypt/OpenJSSE)引入的可选依赖,你的项目里并没有实际引入这些库,所以R8在压缩时会报错。正确的处理方式是结合-dontwarn和针对OkHttp平台类的-keep规则,而不是保留那些不存在的类。
- 在Flutter插件的Android模块中创建/修改
proguard-rules.pro文件,添加以下规则:
# 允许忽略缺失的可选TLS实现类 -dontwarn org.bouncycastle.jsse.** -dontwarn org.conscrypt.** -dontwarn org.openjsse.** # 保留OkHttp的平台检测类,避免R8误删导致运行时找不到实现 -keep class okhttp3.internal.platform.** { *; } -keep interface okhttp3.internal.platform.Platform { *; }
- 确保插件的
build.gradle中正确配置ProGuard规则(如果还没配置):
android { buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } }
- 如果你是在Flutter应用端配置,也可以在应用的Android模块
proguard-rules.pro中添加上述规则,但更推荐在插件内部配置,这样所有使用该插件的应用都无需额外处理。
原理
OkHttp会在运行时检测当前环境可用的TLS实现,这些BouncyCastle/Conscrypt/OpenJSSE类是可选依赖,并非必须存在。之前单独加-dontwarn导致运行时报错,是因为R8把OkHttp的平台检测相关类也给压缩删除了,所以需要保留OkHttp的平台类,确保运行时能正常走默认的TLS实现逻辑。
内容的提问来源于stack exchange,提问作者Haidar
相关产品推荐
相关产品推荐

