V1.4.1: 修复 Android 5.1.1 设备一打开就闪退(API 守卫缺失)
根因(极米 H1S / MStar 6A928 / GMUI2.0 / Android 5.1.1):
- MainActivity 把 API 23 才有的 android.media.AudioDeviceCallback 写成了
**字段初始化器**(private val micDeviceCallback = object : ...)。
字段初始化在 Activity 构造期执行,早于 onCreate 里的 SDK_INT 判断,
于是下面的 registerMicInputWatcher() 版本守卫形同虚设 ——
构造 MainActivity 即抛 NoClassDefFoundError,表现为一打开就闪退。
- 顺带修复 36 处同类未守卫的高版本 API 调用(lint NewApi 全量清零):
* AudioDeviceCallback / AudioDeviceInfo.isSource/getType (API 23)
→ 改为可空字段 + 仅在 SDK_INT>=23 分支按需创建(@TargetApi)
* HashMap.putIfAbsent ×5 (API 24) → MutableMap.getOrPut
* Comparator.comparing ×3 + comparingInt ×1 (API 24) → Kotlin compareBy
(同时移除 java.util.function 导入)
* ConcurrentHashMap.newKeySet ×2 (API 24) → Collections.newSetFromMap
(连带 16 处 KeySetView.add/remove/contains)
* ConcurrentHashMap.computeIfAbsent (API 24) → ConcurrentHashMap.putIfAbsent(API 1)
* URLConnection.getContentLengthLong ×5 (API 24) → 新增 Compat.contentLengthCompat()
* ByteArrayOutputStream.toString(Charset) (API 33) → String(bytes, UTF_8)
防回归:
- app/build.gradle 打开 lint 闸门: checkReleaseBuilds true + abortOnError true +
fatal += NewApi(并 disable ExpiredTargetSdkVersion,避免它挤占闸门)。
已实测: 植入一个 NewApi 违规后 assembleRelease 直接 FAILED。
- AGENTS.md 新增「低版本设备闪退(API 守卫)」条目,记录根因、替代写法与自查命令。
版本号 1.4.0(16) → 1.4.1(17);签名证书不变,可覆盖安装。
This commit is contained in:
+14
-5
@@ -11,8 +11,8 @@ android {
|
||||
applicationId "com.local.ktv"
|
||||
minSdk 21
|
||||
targetSdk 25
|
||||
versionCode 16
|
||||
versionName "1.4.0"
|
||||
versionCode 17
|
||||
versionName "1.4.1"
|
||||
ndk {
|
||||
// 双 ABI 打包:兼容 64 位(Exynos 1580 等 arm64-v8a)与 32 位设备(极米 Play 超越版
|
||||
// 的 Amlogic 950X2/S905X2 采用 32 位 Android 用户态,必须包含 armeabi-v7a,否则
|
||||
@@ -52,10 +52,19 @@ android {
|
||||
noCompress 'ts', 'mp3', 'mp4', 'aac', 'm4a', 'flac', 'wav'
|
||||
}
|
||||
|
||||
// 关闭发布构建的 lint vital 检查(本地分发的 APK 不需要 Google Play 上架要求)
|
||||
// lint 策略:
|
||||
// - 「调用了高于 minSdk 且未做版本守卫的 API」(NewApi) 必须**阻断发布构建**:
|
||||
// 这类问题在 Android 5.x / 6.x 上直接 NoSuchMethodError / NoClassDefFoundError 闪退,
|
||||
// 而本地打包测试用的都是较新设备, 极容易漏出去(v1.4.0 在极米 H1S / Android 5.1.1
|
||||
// 一打开就闪退, 根因就是 AudioDeviceCallback(API 23) 被写进了 Activity 的字段初始化器)。
|
||||
// - ExpiredTargetSdkVersion 默认也是 fatal 级, 但本地分发的 APK 不上架 Google Play,
|
||||
// 显式关掉, 否则会挤占下面这道闸门。
|
||||
// - abortOnError 必须为 true: 设为 false 会把 lintVital 的失败一并吞掉, 闸门会失效。
|
||||
lint {
|
||||
checkReleaseBuilds false
|
||||
abortOnError false
|
||||
fatal += ['NewApi']
|
||||
disable += ['ExpiredTargetSdkVersion']
|
||||
checkReleaseBuilds true
|
||||
abortOnError true
|
||||
}
|
||||
|
||||
// 启用 BuildConfig 生成,供 AboutFragment 读取版本号/版本Code等信息
|
||||
|
||||
Reference in New Issue
Block a user