1. 老项目升级踩坑minSdk 8 调用 Fragment 直接编译报错如果你手上维护着一个 2013 年前后的 Android 老工程AndroidManifest.xml里还写着android:minSdkVersion8某天想在 Activity 里加个 Fragment 做页面拆分写完new android.app.Fragment()一编译Android Studio 立刻甩你一脸红Call requires API level 11 (current min is 8): new android.app.Fragment这个报错的意思是android.app.Fragment这个类从 API 11Android 3.0 Honeycomb才开始提供而你的工程声明最低支持 API 8Android 2.2 Froyo。Lint 检查发现你在一个「最低兼容 8」的项目里用了「11 才存在」的 API于是判定为 NewApi 违规直接拦下编译。它到底影响谁三类人最容易撞上一是维护存量 App 的开发者minSdk 因为渠道或老设备要求压得很低二是做 SDK 或组件库的同学宿主 App 的 minSdk 由别人决定三是刚接手老代码的新人看到报错第一反应是「我代码没错啊」。这篇就围绕这个报错把 NewApi 检查机制、minSdkVersion 调整、兼容写法以及一份可复制的settings.json配置骨架讲清楚最后给你编译和运行两段验证动作照着做就能定位并解决。需要先说明一点这个报错本质是「编译期静态检查」不是运行时崩溃。也就是说如果你强行绕过 Lint在 API 8 的真机上跑到这行代码才会真正抛NoClassDefFoundError或ClassNotFoundException。所以解决思路分两条线——要么抬高 minSdk 让 API 合法要么用兼容库让低版本也能跑。下面逐条展开。2. 动手前的前置准备TaoToken 接入与工程环境确认在改配置之前我习惯先把「模型辅助排查」这条链路搭好因为老项目的报错往往不止一个逐个查文档效率太低。这里用 TaoToken 做统一入口它把常见大模型的对话、编码计划、API Key 管理放在一个控制台里排查这类版本冲突时可以直接把报错贴进去问省去来回切工具。官网入口在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册后在控制台创建 API Key就能拿到调用凭证。API 基地址是 https://taotoken.net/api 注意这个地址不带任何查询参数配置时别自己拼 UTM。工程侧你需要确认三件事第一build.gradle模块级里的minSdkVersion当前值报错里的current min is 8就是从这来的第二compileSdkVersion和targetSdkVersion它们决定你编译时能用哪些 API第三是否已经引入 AndroidX 或旧版 Support 库这决定你走哪条兼容路线。提示老项目如果还在用android.support.v4.app.Fragment说明 Support 库已经在工程里了兼容路线几乎零成本如果完全没引库那要么加依赖要么抬 minSdk。把 API Key 拿到手后可以在控制台的模型对话里直接问「minSdk 8 用 Fragment 有哪几种改法」它会给你列出SuppressLint(NewApi)、TargetApi、换 Support 库三条路和下面要讲的内容能对上。这一步不是必须但对不熟悉 Lint 注解的人能快速建立全局认知。3. 可复制配置settings.json 骨架与三种兼容写法先给一份settings.json配置骨架。这个文件通常放在工程根目录或.vscode/下用于统一编辑器与 Lint 行为避免团队里有人本地关了检查、有人没关导致 CI 结果不一致。骨架如下字段含义我在注释里标了JSON 不支持注释实际使用时请删掉//部分{ android.lint.enabled: true, android.lint.checkNewApi: true, android.lint.abortOnError: false, android.lint.baseline: lint-baseline.xml, java.compile.nullAnalysis.mode: automatic, files.associations: { *.gradle: groovy }, editor.formatOnSave: false }关键字段是android.lint.checkNewApi设为true表示保留 NewApi 检查这样报错不会被静默吞掉abortOnError设为false让 Lint 只警告不中断构建方便你先跑通再逐个修baseline指向基线文件可以把历史遗留的 NewApi 问题冻结起来只对新增代码生效。这套组合适合老项目渐进式治理不会一上来就卡死构建。配置骨架只是「让检查可控」真正解决报错还得改代码。三种写法按推荐度排序第一种换用 Support/AndroidX 的 Fragment。这是最正统的兼容方案因为 Support 库的 Fragment 从 API 4 就可用import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; public class ArticleFragment extends Fragment { // 用 getSupportFragmentManager() 提交事务 }对应 Activity 要继承FragmentActivityAndroidX 下是AppCompatActivity事务用getSupportFragmentManager()。这样 minSdk 8 完全合法运行时也不会崩。第二种用TargetApi精确声明。它告诉编译器「这个类按指定 API 编译」适合你确实只在高版本设备上走这段逻辑import android.annotation.TargetApi; import android.os.Build; TargetApi(Build.VERSION_CODES.HONEYCOMB) public class ArticleFragment extends android.app.Fragment { // 仅 API 11 设备会实例化此类 }注意TargetApi只是关掉编译检查不改变运行时行为。你必须自己保证低版本设备不会走到这里否则照样崩。第三种SuppressLint(NewApi)。它比TargetApi更粗暴直接压制整个类的 NewApi 警告import android.annotation.SuppressLint; SuppressLint(NewApi) public class ArticleFragment extends android.app.Fragment { // 编译不再报错但兼容性由你自己负责 }我一般只在临时验证或明确知道调用路径受版本判断保护时才用它长期方案还是第一种。方案改动成本低版本安全性适用场景Support/AndroidX Fragment中高长期维护、需兼容低版本TargetApi低中逻辑有版本判断保护SuppressLint最低低临时验证、快速跑通4. 验证请求与成功结果编译 运行两段动作改完配置和代码别急着提交先做两段验证。第一段是编译验证。在工程根目录执行./gradlew clean assembleDebug --warning-mode all重点看输出里还有没有Call requires API level 11这条。如果换成 Support 库方案这条应该彻底消失如果用TargetApi或SuppressLintLint 报告里可能仍有记录但不阻断构建。想单独跑 Lint 看 NewApi 项./gradlew lintDebug报告在app/build/reports/lint-results-debug.html打开搜NewApi就能定位剩余问题。第二段是运行验证。准备两台设备或模拟器一台 API 11比如 API 30一台 API 8 或 10。分别安装运行重点观察进入 Fragment 所在页面时是否崩溃。如果低版本设备抛ClassNotFoundException: android.app.Fragment说明你用了TargetApi但没做版本判断得补上if (Build.VERSION.SDK_INT Build.VERSION_CODES.HONEYCOMB) { // 使用 android.app.Fragment } else { // 降级逻辑或提示不支持 }成功的结果是高版本设备正常显示 Fragment 内容低版本设备要么走兼容分支、要么明确提示日志里没有NoClassDefFoundError。到这一步版本冲突就算真正解决了而不只是「编译不报错」。5. 本篇常见错排查报错没消失、运行崩溃、配置不生效排查过程中有几个高频坑我按出现频率列一下。第一个改了settings.json但报错还在。原因通常是这个文件没被 IDE 识别或者工程里还有.idea/下的本地配置覆盖了它。解决办法是重启 IDE并确认settings.json在工程根目录而非用户目录。另外 Gradle 构建走的是build.gradle里的lintOptionssettings.json主要影响编辑器内联提示两者要一起改。第二个换成 Support 库后getSupportFragmentManager()报红。这多半是 Activity 没继承FragmentActivity/AppCompatActivity或者依赖没加。检查build.gradledependencies { implementation androidx.appcompat:appcompat:1.6.1 implementation androidx.fragment:fragment:1.6.2 }第三个TargetApi加了还是运行崩溃。回到上面说的注解不改变运行时低版本设备实例化android.app.Fragment必然失败。要么加Build.VERSION.SDK_INT判断要么干脆换 Support 库。第四个minSdkVersion抬到 11 后其他老代码报新错。这是连锁反应抬 minSdk 会让一批原本被压制的 API 检查重新生效。建议用lint-baseline.xml把存量问题冻结只处理新增的。第五个CI 上构建失败但本地正常。通常是 CI 没读settings.json或者 Lint 版本不一致。在 CI 脚本里显式跑./gradlew lintDebug并上传报告能快速对齐。注意Disable Check In This File Only和Disable Check In This Project这两个 IDE 快捷选项看着省事但会把检查永久关掉团队协作时极易埋雷不建议点。6. 后续怎么走把排查链路固定下来这类版本冲突排查完一次最好把经验固化成流程下次遇到Call requires API level XX能直接套。我的做法是先在模型对话里把报错和build.gradle片段贴进去让它列出候选方案再对照本文的三种写法选一条改完跑assembleDebug和双版本运行验证最后把结论写进工程 README 的「兼容性说明」里。如果你后续要长期做这类老项目维护或者想让 AI 辅助编码、批量处理 Lint 问题可以了解下 Coding Plan它更适合把「贴报错—给方案—改代码—验证」这条链路做成日常习惯。API Key 的管理和创建在控制台的 API Keys 页面接入细节看官方文档模型对话入口则适合临时验证某个 API 到底从哪个版本开始可用。把工具链路和本文的配置骨架结合起来minSdk 8 这类老工程的版本冲突就不再是拦路虎了。