应用与你的手机不兼容:检查 targetSdk、ABI 和 minSdk
本页目录
结论先行:手机提示“应用与你的手机不兼容”(英文系统是 “App not installed as app isn’t compatible with your phone”),背后其实是好几种不同的拒绝原因。在当前的 Android 版本上,最常见的是这几种:targetSdkVersion 太低(Android 14 拦截低于 23 的,Android 15 及以上拦截低于 24 的);原生库只有手机不支持的 ABI(典型情况是只有 32 位库,而手机只支持 64 位);minSdkVersion 高于手机的系统版本;或者声明了手机上没有的必需共享库。adb install 会打印出确切的 INSTALL_FAILED_* 代码,每个代码都对应构建配置里的一处修改。
本文用我自己构建的几个小 APK 把每种原因都复现了一遍,分别装到 Android 14(API 34)和 Android 16(API 36)模拟器上,下面是真实输出。然后再用本站的 APK/AAB 分析与上架体检 检查同一批文件,它在浏览器里读取 Manifest 和原生库,不上传任何内容。
适合谁读:在商店以外分发自家 APK、或者手动安装测试包,然后从用户或测试机那里收到这句提示的开发者。
读完你会知道:
- 怎么用 adb 拿到真正的失败代码
- 四类原因各自的复现方式和对应代码
- 哪些原因工具会直接标出来,哪些要从报告的表格里读
- Gradle、Flutter、Unity 里分别该改哪里
- REA(morluto 的开源项目)6.4.0 能补充什么、做不到什么
只测试你自己的构建或已获授权的构建,并且只用你自己控制的设备。
第 1 步:拿到真实的错误代码
手机不会告诉你原因。连上设备(或启动模拟器),从电脑上安装:
adb install app-release.apk
下面是样例 APK 的结果。所有 APK 的包名都是 dev.example.compat,都用我的发布密钥签名,每次只改一项设置。
| 样例 | 问题 | Android 14(API 34) | Android 16(API 36) |
|---|---|---|---|
compat-target22.apk |
targetSdkVersion 22 |
INSTALL_FAILED_DEPRECATED_SDK_VERSION |
INSTALL_FAILED_DEPRECATED_SDK_VERSION |
compat-target23.apk |
targetSdkVersion 23 |
Success | INSTALL_FAILED_DEPRECATED_SDK_VERSION |
compat-armv7-only.apk |
只有 lib/armeabi-v7a/ |
INSTALL_FAILED_NO_MATCHING_ABIS |
INSTALL_FAILED_NO_MATCHING_ABIS |
compat-x86_64-only.apk |
只有 lib/x86_64/ |
INSTALL_FAILED_NO_MATCHING_ABIS |
INSTALL_FAILED_NO_MATCHING_ABIS |
compat-min35.apk |
minSdkVersion 35 |
INSTALL_FAILED_OLDER_SDK |
Success |
compat-missing-library.apk |
必需的 <uses-library> 不存在 |
INSTALL_FAILED_MISSING_SHARED_LIBRARY |
INSTALL_FAILED_MISSING_SHARED_LIBRARY |
compat-watch-feature.apk |
要求 android.hardware.type.watch |
Success | Success |
compat-fixed.apk |
target 36、min 24,arm64-v8a + armeabi-v7a + x86_64 | Success | Success |
两台模拟器都是 arm64 镜像,ro.product.cpu.abilist 只有 arm64-v8a,没有任何 32 位 ABI。近几代 Pixel 手机同样只支持 64 位。
完整的失败信息本身就说得很清楚:
Failure [INSTALL_FAILED_DEPRECATED_SDK_VERSION: App package must target at least SDK version 23, but found 22]
Failure [INSTALL_FAILED_DEPRECATED_SDK_VERSION: App package must target at least SDK version 24, but found 23]
Failure [INSTALL_FAILED_NO_MATCHING_ABIS: INSTALL_FAILED_NO_MATCHING_ABIS: Failed to extract native libraries, res=-113]
Failure [INSTALL_FAILED_OLDER_SDK: Requires newer sdk version #35 (current version is #34)]
Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY: Reconciliation failed...: Reconcile failed: Package dev.example.compat requires unavailable shared library dev.example.missing.library; failing!]
前两行分别来自 API 34 和 API 36 模拟器,可以看到下限从 23 提到了 24。在我的模拟器上,logcat 没有记录这些失败,所以要看原因就看 adb 的输出。
第 2 步:在浏览器里检查 APK
打开 APK/AAB 分析与上架体检,场景选 Play 以外(线下分发) 或 两者都要。安装类规则 SIDE-01 属于线下分发场景,PLAY-04 属于 Google Play 场景,选“两者都要”就能同时看到。然后拖入 APK。
工具对这批样例的结果(按 2026-10-14 的规则):
compat-target22.apk
SIDE-01 fail reject targetSdkVersion=22
Android 15+ requires targetSdkVersion >= 24
Android 14+ requires targetSdkVersion >= 23
note: Installation fails on Android 14 and later (INSTALL_FAILED_DEPRECATED_SDK_VERSION).
PLAY-01 fail reject targetSdkVersion=22, required: >= 36 (phone/tablet, since 2026-08-31)
compat-target23.apk
SIDE-01 fail reject targetSdkVersion=23, Android 15+ requires targetSdkVersion >= 24
note: Installation fails on Android 15 and later (INSTALL_FAILED_DEPRECATED_SDK_VERSION).
compat-armv7-only.apk
PLAY-04 fail reject lib/armeabi-v7a/ present, lib/arm64-v8a/ missing
SIDE-01 和两台模拟器的结果完全吻合:target 22 在两台上都装不上,target 23 只在 Android 16 上装不上。
另外三种原因没有单独的检查项,要从报告里读出来:
- 只有 x86_64。PLAY-04 只标两种情况:有 32 位 ABI 却缺对应的 64 位 ABI,以及
.so的 ELF 头和所在目录不一致。只有lib/x86_64/的 APK 两条都不触发,compat-x86_64-only.apk的所有检查都通过了。问题要看原生库表格:只有一行,ABI 是x86_64,ELF 是64-bit x86-64,ARM 处理器的手机用不了。确认表里有arm64-v8a。 - minSdk。摘要里有
minSdk,拿它和手机的系统版本比(API 34 是 Android 14,35 是 Android 15,36 是 Android 16)。minSdk 设得高本身是合理选择,所以没有检查项会标它。 - 必需共享库。当前版本没有用表格列出
<uses-library>。打开 Manifest → 原始 XML,查找带android:required="true"的uses-library。
第 3 步:读取手机这一侧的信息
要对比,需要知道手机的 API 级别和支持的 ABI。用原生 adb:
adb shell getprop ro.build.version.sdk
adb shell getprop ro.product.cpu.abilist
用 REA 6.4.0 的话,inspect-adb-device 会读取一组固定的构建属性,其中就包括这两项:
export REA_ADB_PATH="$HOME/Library/Android/sdk/platform-tools/adb"
rea inspect-adb-device emulator-5582 --format json
API 34 模拟器上 normalized_result.properties 的摘录:
ro.build.version.release 14
ro.build.version.sdk 34
ro.product.cpu.abilist arm64-v8a
ro.product.model sdk_gphone64_arm64
rea list-adb-features <serial> 会列出设备声明的功能(pm list features),后面讲 Play 过滤时用得上。
REA 拿不到安装失败代码本身。rea install-adb-package 能装上正常的样例,但每次安装失败都只返回通用的 unreadable_output 错误,没有 INSTALL_FAILED_* 原文。6.4.0 的代码从 adb 的标准输出里读 Failure [...],而我用的 adb 37.0.1 把它写到标准错误,并以状态码 1 退出。这一步请继续用 adb install。
第 4 步:在构建里修好
targetSdkVersion 太低(DEPRECATED_SDK_VERSION)
提高 targetSdk。Android 14 拒绝低于 23 的,Android 15 及以上拒绝低于 24 的(Android 15 行为变更)。别只提到下限:自 2026-08-31 起,Google Play 要求手机和平板应用达到 36(PLAY-01),而且这个安装下限在两个 Android 版本里已经提高了两次。
android {
defaultConfig {
minSdk = 24
targetSdk = 36
}
}
提高 target 会改变运行时行为(权限、后台限制、Intent 等),要实际测试新版本,不能只是重新打个包。Flutter 项目的这些值在 android/app/build.gradle(.kts) 里,常见写法是 flutter.targetSdkVersion,由 Flutter SDK 版本决定。Unity 在 Player Settings → Other Settings 的 Target API Level 里设置。
adb install --bypass-low-target-sdk-block 可以强行装上 target 过低的包,我的 target 22 样例加这个参数后在两台模拟器上都装上了。它是给开发者在自己设备上测试旧构建用的,普通用户没有这个选项,它也不会修好 APK 本身。
没有匹配的 ABI(NO_MATCHING_ABIS)
面向手机一定要带 arm64-v8a。在 x86_64 模拟器上测试就保留 x86_64;只有要支持老的 32 位设备时才加 armeabi-v7a:
android {
defaultConfig {
ndk { abiFilters += listOf("arm64-v8a", "armeabi-v7a", "x86_64") }
}
}
重点排查两种情况:为模拟器临时设置、之后一直没改回来的 abiFilters;以及只提供 32 位 .so 的第三方 SDK。Flutter 的 release 构建默认就包含 arm64 库,检查一下构建脚本里有没有 --target-platform 参数。Unity 要选 IL2CPP,并在 Target Architectures 里勾选 ARM64;Mono 后端不支持 ARM64。只勾了 ARMv7 的 Unity 包,在只支持 64 位的手机上就会这样失败。
带三种 ABI 的 compat-fixed.apk 在两台模拟器上都装上了。如果还要上架 Play,记得对 64 位库做一次 16 KB 页面大小检查。
minSdkVersion 太高(OLDER_SDK)
要么是手机系统确实太旧,要么是 minSdk 被意外抬高了,常见原因是某个依赖要求更高的版本,Manifest 合并时取了较大值。如果你本来就想支持这台手机,降低 minSdk,并替换掉把它抬高的依赖;如果不打算支持,这个提示就是对的,告诉用户最低支持的 Android 版本即可。
缺少共享库(MISSING_SHARED_LIBRARY)
<uses-library android:required="true"> 指定了一个这台手机没有的库,比如某个厂商专有库。如果应用没有它也能运行,改成 android:required="false",在运行时再判断;否则就单独出一个不依赖它的构建变体。
uses-feature:不是安装器的检查项
声明必需 android.hardware.type.watch 的样例,用 adb install 在两台手机模拟器上都装上了。在我的测试里,<uses-feature> 不会阻止安装。Google Play 和一些商店用它来决定哪些设备能看到这个应用。如果用户是在商店页面上看到“不兼容”,拿你声明的必需功能和受影响设备上 rea list-adb-features 的输出对比,把可选的功能改成 android:required="false"。
常见问题
手机说“不兼容”,adb 却给出别的代码?
以 adb 为准。如果代码是 INSTALL_FAILED_UPDATE_INCOMPATIBLE,那是和已装版本的签名冲突,请看 安装包与现有包冲突。
64 位手机能跑只有 32 位库的 APK 吗?
只有手机还列出 32 位 ABI 时才行(看 ro.product.cpu.abilist)。很多新手机已经不支持,我的两台模拟器都报了 NO_MATCHING_ABIS。请提供 arm64-v8a。
应用里根本没有原生代码,还会是 ABI 的问题吗?
不会。没有 lib/ 目录就没有可匹配的东西,去查 targetSdk、minSdk 和共享库。
我拿到的是 AAB,不是 APK。 AAB 不能直接安装。先用 bundletool 生成 APK,见 AAB 转 APK 教程。
下一步
- 发包前检查 targetSdk、ABI 和签名:APK/AAB 分析与上架体检
- 和已装版本签名冲突:安装包与现有包冲突
- 装得上但会崩溃:用 REA 读 logcat 和 bugreport
- 参考资料:Android 14 行为变更、Android ABI、64 位要求、REA 的 DISCLAIMER.md