应使用 project.logger.error() 而非 throw new GradleException(),并在 afterEvaluate 阶段校验;前者不中断构建、保留上下文并支持多问题一次性发现,后者避免因 DSL 延迟求值导致误判。

插件里用 project.logger.error() 而不是 throw new GradleException()
直接 throw 会中断整个构建流程,掩盖真实配置上下文;而 project.logger.error() 可以在不终止执行的前提下,把错误定位到具体行号和插件名。比如你在自定义插件中检测到 minSdkVersion 小于 21,应该这样写:
if (extension.minSdkVersion <p>这样用户同步时能看到红字错误 + 黄字提示,且构建继续运行,方便一次性发现多个问题。</p><h3>在 <code>afterEvaluate</code> 阶段做校验,别在 <code>apply</code> 里硬检查</h3><p>Gradle 的 DSL 是延迟求值的,<code>apply</code> 执行时 <code>android {}</code> 块可能还没被解析。如果你在 <code>apply</code> 里就去读 <code>project.extensions.findByType(…)</code>,大概率拿到 null 或默认值,导致误报或漏报。</p><p>正确做法是把校验逻辑挪到 <code>project.afterEvaluate</code> 中:</p><pre class="brush:php;toolbar:false;">project.reportError()
- 你的插件依赖了 AGP 8.0+ 的 API(如
com.android.tools.build:gradle:8.5.1) - 调用时传入一个
ConfigurationProblem实例
示例:
val problem = ConfigurationProblem.create(
"MYPLUGIN_INVALID_TARGET_SDK",
"targetSdkVersion must match compileSdkVersion",
ProblemReporter.Type.ERROR,
project.file("build.gradle")
)
project.reportError(problem)
注意:这个 API 不会终止构建,但会被 Android Studio 的 Problems 工具窗口捕获并高亮显示,对新手友好度明显提升。
避免在闭包里抛异常——闭包外校验 + 闭包内标记
常见陷阱:在 myplugin { … } 闭包内部直接 throw,结果堆栈指向 Groovy 解析器,而不是你写的插件代码。
推荐模式是两阶段处理:
- 闭包执行时只收集配置(如
extension.targetSdk = 34) - 在
afterEvaluate中统一校验,出错时用project.logger.error()输出带上下文的提示
这样既保留了 DSL 的可读性,又让错误可定位、可复现。尤其当用户写了 myplugin { targetSdk = "34" }(字符串而非整数)时,你能在日志里明确指出:“第 15 行:targetSdk 必须为整数,当前值类型为 String”。
真正难的不是抛错,而是让错误信息自带上下文、位置和修复路径。很多人卡在构建失败后反复改配置却不知哪一行触发了哪条规则——这往往是因为插件没把 project.buildFile 和实际配置块的位置绑定起来。











