Android 4.1.2开启minifyEnabled致okhttp3崩溃的Proguard规则求解
OkHttp 3.12.13 低版本Android混淆崩溃问题
问题现象
在okhttp:3.12.13版本中,配置minifyEnabled false时以下代码可正常运行:
private static boolean supportsAlpn() { if (Security.getProvider("GMSCore_OpenSSL") != null) { return true; } else { try { Class.forName("android.net.Network"); // 开启minifyEnabled true时此处抛出NoClassDefFoundError return true; } catch (ClassNotFoundException ignored) { } } return false; }
在Android 4.1.2设备上配置minifyEnabled true时会抛出如下异常:
Caused by: java.lang.ExceptionInInitializerError at okhttp3.OkHttpClient.newSslSocketFactory(OkHttpClient.java:292) at okhttp3.OkHttpClient.<init>(OkHttpClient.java:258) at okhttp3.OkHttpClient.<init>(OkHttpClient.java:231) Caused by: java.lang.ExceptionInInitializerError at java.lang.Class.classForName(Native Method) at java.lang.Class.forName(Class.java:217) at java.lang.Class.forName(Class.java:172) at okhttp3.internal.platform.AndroidPlatform.supportsAlpn(AndroidPlatform.java:219) at okhttp3.internal.platform.AndroidPlatform.buildIfSupported(AndroidPlatform.java:262) at okhttp3.internal.platform.Platform.findAndroidPlatform(Platform.java:246) at okhttp3.internal.platform.Platform.findPlatform(Platform.java:202) at okhttp3.internal.platform.Platform.<clinit>(Platform.java:78) Caused by: java.lang.NoClassDefFoundError at android.net.Network.<clinit>(Unknown Source)
已尝试方案
- 已添加okhttp3、okio官方提供的默认Proguard规则,未解决问题。
- 使用如下全量保留okhttp3所有类与接口的规则可修复崩溃,但会导致APK体积增加0.6MB:
-keepattributes Signature -keepattributes *Annotation* -keep class okhttp3.** { *; } -keep interface okhttp3.** { *; } -dontwarn okhttp3.**
需求为:无需全量保留APK中所有okhttp3类即可修复该问题。
根因分析
崩溃本质是混淆工具(R8/Proguard)的优化逻辑误判:
android.net.Network是Android 5.0(API 21)才新增的系统类,Android 4.1.2(API 16)系统中不存在该类- 原代码通过
Class.forName+捕获ClassNotFoundException做了兼容性判断,非混淆场景下低版本触发异常会被正常捕获,不会崩溃 - 开启混淆后,工具检测到编译依赖的SDK中存在
android.net.Network类,会错误优化反射逻辑,移除/修改原有异常捕获分支,运行时加载类触发NoClassDefFoundError(属于Error,不在原代码捕获的Exception范围内),直接导致崩溃
最小体积修复方案
不需要全量保留所有okhttp3类,仅需添加如下针对性Proguard规则即可修复,体积增量仅几KB:
# 保留AndroidPlatform的平台兼容性判断方法,避免混淆修改反射异常捕获逻辑 -keep class okhttp3.internal.platform.AndroidPlatform { private static boolean supportsAlpn(); static okhttp3.internal.platform.AndroidPlatform buildIfSupported(); } # 告知混淆工具无需校验android.net.Network类的存在性,避免错误优化 -dontwarn android.net.Network
如果添加上述规则后仍有异常,可以补充一条规则禁止混淆工具对okhttp3平台查找逻辑做优化:
-keep class okhttp3.internal.platform.Platform { static okhttp3.internal.platform.Platform findPlatform(); }
内容的提问来源于stack exchange,提问作者A.G.
相关产品推荐
相关产品推荐

