Files
dacard-test-miniapp/Android4.2兼容性改动文档.md
T
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

157 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`
**修复**:
```groovy
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`
**修复**:
```groovy
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。
**修复**:
```groovy
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+。
**修复**:
```groovy
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 保留 |