Files
dacard-test-miniapp/Android4.2兼容性改动文档.md
zhaogd 37738504b9 fix: Android 4.2 兼容性修复 - 降级第三方库 + 移除 ExoPlayer + multidex 配置
1. OkHttp 3.14.9 -> 3.12.0(Android10Platform 引用 Android 10+ API 导致 VerifyError)
2. Gson 2.10.1 -> 2.8.6(ReflectionHelper 引用 Java 9+ API 导致 VerifyError)
3. Retrofit 2.9.0 -> 2.6.0(与客户环境一致,配合 OkHttp 3.12.0)
4. Coroutines 1.7.3 -> 1.6.4(1.7+ 要求 minSdk 21)
5. 移除 ExoPlayer 2.19.1,改用系统原生 MediaPlayer + SurfaceView
6. 主题 MaterialComponents -> AppCompat(避免 MaterialComponentsViewInflater multidex 问题)
7. multidex-config.pro 新增 kotlinx.coroutines.** 和 retrofit2.** 到主 dex
8. 新增 Android 4.2 兼容性改动文档
2026-07-28 19:47:57 +08:00

6.9 KiB
Raw Permalink Blame History

Android 4.2 兼容性改动文档

背景

项目 original 目标为 Android 5.0+,需降级兼容 Android 4.2(API 17)。Android 4.2 使用 Dalvik 虚拟机(非 ART),对 multidex 和高版本 API 引用有严格限制,导致一系列兼容性问题。

问题分类

兼容性问题分为两大类:

  1. Dalvik multidex 类加载失败:Dalvik 在框架级反射和内部类加载场景下,无法从 secondary dex 加载类,导致 ClassNotFoundException / NoClassDefFoundError / VerifyError
  2. 高版本 API 引用:第三方库的某些类引用了 Android 10+ 或 Java 9+ 的 API,Dalvik 验证器拒绝加载,导致 VerifyError

一、Multidex 配置改动

1.1 multidex-config.pro(主 dex 保留类)

文件:app/multidex-config.pro

原因:Dalvik multidex 环境下,以下场景无法从 secondary dex 加载类:

  • LayoutInflater.createViewFromTag(框架级反射创建 View)
  • AppCompatDelegateImpl.createSubDecor(inflate 内部装饰布局)
  • 协程内部机制加载 CoroutineExceptionHandlerImplKt
  • Retrofit KotlinExtensions.await() 被 HttpServiceMethod 运行时调用

保留到主 dex 的包:

- com.pukka.mediaapp.**           # 项目自身所有类
- androidx.appcompat.app.**       # AppCompatDelegateImpl、AppCompatViewInflater
- androidx.appcompat.widget.**    # FitWindowsLinearLayout、AppCompatButton 等
- kotlinx.coroutines.**           # 协程核心类
- retrofit2.**                    # KotlinExtensions、HttpServiceMethod 等

1.2 AndroidManifest.xml

文件:app/src/main/AndroidManifest.xml

改动:

  • 移除 com.google.android.exoplayer2 的 overrideLibrary(已移除 ExoPlayer 依赖)
  • 保留其他 AndroidX 库的 overrideLibrary(core-ktx 1.12.0、appcompat 1.6.1 等的 minSdk 为 19-21,通过 override 覆盖为 17)
  • 移除 androidx.startup.InitializationProvider(Android 4.x Dalvik multidex 下 Provider 启动时无法加载 secondary dex 中的初始化类,App 手动初始化所有组件)

二、第三方库版本降级

2.1 OkHttp:3.14.9 → 3.12.0

问题:OkHttp 3.12.1+ 包含 Android10Platform 类,引用 Android 10+ 的 SSL API(SSLParameters.setApplicationProtocols)。Platform.findAndroidPlatform() 在静态初始化时尝试加载该类,Dalvik 验证器拒绝 → VerifyError

修复:

implementation 'com.squareup.okhttp3:okhttp:3.12.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.12.0'
// 防止其他依赖传递引入 3.12.1+
configurations.all {
    resolutionStrategy.force 'com.squareup.okhttp3:okhttp:3.12.0'
}

2.2 Gson:2.10.1 → 2.8.6

问题:Gson 2.9+ 引入 ReflectionHelper 类,引用 Java 9+ 的反射 API(java.lang.invoke.MethodHandles)。ReflectiveTypeAdapterFactory.create() 调用该类,Dalvik 验证器拒绝 → VerifyError

修复:

implementation 'com.google.code.gson:gson:2.8.6'

2.3 Retrofit:2.9.0 → 2.6.0

问题:Retrofit 2.9.0 传递依赖 OkHttp 3.14.9(含 Android10Platform)。与客户环境保持一致使用 2.6.0。

修复:

implementation 'com.squareup.retrofit2:retrofit:2.6.0'
implementation 'com.squareup.retrofit2:converter-gson:2.6.0'

2.4 Kotlin Coroutines:1.7.3 → 1.6.4

问题:kotlinx-coroutines 1.7+ 要求 minSdk 21(Android 5.0),1.6.4 兼容 API 16+。

修复:

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'

三、ExoPlayer 移除,改用系统原生 MediaPlayer

问题:ExoPlayer 2.14+ 要求 minSdk 21,2.19.1 的类大量引用 Android 5+ API,在 Android 4.2 上会 VerifyError。即使降到 2.13.0,API 差异大且仍有兼容性风险。

修复:完全移除 ExoPlayer,改用 Android 系统原生 MediaPlayer + SurfaceView(API 1+,零兼容性问题)。

涉及文件:

文件 改动
app/build.gradle 移除 exoplayer:2.19.1 依赖
app/src/main/AndroidManifest.xml 移除 com.google.android.exoplayer2 overrideLibrary
app/src/main/res/layout/activity_player.xml PlayerView → SurfaceView
app/src/main/java/.../ui/VideoPlayerActivity.kt 重写为 MediaPlayer + SurfaceHolder.Callback

四、主题改动

文件:app/src/main/res/values/themes.xml

改动:Theme.MaterialComponents.NoActionBar → Theme.AppCompat.NoActionBar

原因:

  • MaterialComponentsViewInflater 继承 AppCompatViewInflater,被框架反射加载时需在主 dex
  • 保留整个 com.google.android.material.** 到主 dex 会导致方法数超限(80949 > 65536)
  • 布局中只用了标准控件(TextView/EditText/Button/ProgressBar),无需 Material 主题
  • 改用 AppCompat 主题后,使用 AppCompatViewInflater,避免 Material 的 multidex 问题

五、build.gradle 完整依赖对照

依赖 修复前 修复后 原因
retrofit 2.9.0 2.6.0 传递依赖 OkHttp 3.14.9 不兼容
converter-gson 2.9.0 2.6.0 同上
okhttp 3.14.9(传递) 3.12.0(force) Android10Platform VerifyError
logging-interceptor 3.12.12 3.12.0 同上
gson 2.10.1 2.8.6 ReflectionHelper VerifyError
coroutines 1.7.3 1.6.4 1.7+ 要求 minSdk 21
exoplayer 2.19.1 移除 minSdk 21,改用 MediaPlayer
appcompat 1.6.1 1.6.1(不变) overrideLibrary 覆盖
core-ktx 1.12.0 1.12.0(不变) overrideLibrary 覆盖
material 1.11.0 1.11.0(不变) 改用 AppCompat 主题
lifecycle 2.3.1 2.3.1(不变) 兼容 API 16+
activity 1.3.1 1.3.1(不变) 兼容 API 16+
multidex 2.0.1 2.0.1(不变) 兼容 API 16+

六、问题排查记录(按发现顺序)

序号 错误 根因 修复
1 VerifyError: AppCompatViewInflater Dalvik multidex 无法加载 secondary dex 的 AppCompat 类 multidex-config.pro 保留 androidx.appcompat.**
2 ClassNotFoundException: FitWindowsLinearLayout AppCompat 内部 widget 不以 AppCompat 开头,通配符未覆盖 改用包级别 androidx.appcompat.widget.**
3 NoClassDefFoundError: CoroutineExceptionHandlerImplKt 协程内部类加载失败 multidex-config.pro 保留 kotlinx.coroutines.**
4 VerifyError: Android10Platform OkHttp 3.12.1+ 引用 Android 10+ API OkHttp 降级 3.12.0 + force 锁定
5 VerifyError: ReflectionHelper Gson 2.9+ 引用 Java 9+ API Gson 降级 2.8.6
6 NoClassDefFoundError: retrofit2.KotlinExtensions Retrofit suspend 支持类在 secondary dex multidex-config.pro 保留 retrofit2.**
7 主 dex 方法数超限 80949 > 65536 保留 material.** 到主 dex 改用 AppCompat 主题,移除 material 保留