应使用 project.findProperty('key') 安全读取项目属性,而非 project.property('key'),因后者仅访问 Project 实例自身属性,而 findProperty 覆盖命令行 -P、gradle.properties、ext 声明等所有来源并容错返回 null。

project.property() 直接读取会报 UnknownPropertyException
Gradle 中用户传入的项目属性(比如命令行 -Pkey=value、gradle.properties 里定义的、或 ext 块声明的)**不能直接用 project.property('key') 访问**——这只会查 project 实例自身的属性(如 name、version),不是“项目级配置属性”。常见错误是写成:
println project.property('myFeatureEnabled') // 报错:Could not get unknown property 'myFeatureEnabled'正确做法是统一走 project.findProperty(),它安全返回 null 而非抛异常,且覆盖所有来源:
-
-PmyFeatureEnabled=true(命令行) -
myFeatureEnabled=true在gradle.properties或local.properties中 -
ext.myFeatureEnabled = true在任意 build.gradle 中
区分 findProperty 和 property 的行为差异
findProperty 是唯一能跨来源、容错读取项目属性的方法;property 只查 project 对象的直接属性,和构建配置无关。实际使用中:
- 用
project.findProperty('xxx') ?: 'default'做有默认值的安全读取 - 布尔值别直接强转:
findProperty('debugMode')?.toBoolean()比(boolean) findProperty('debugMode')更稳(避免null强转失败) - 数字类型需手动解析:
findProperty('timeoutMs')?.toInteger(),不支持自动类型推导 - 不要在
configuration阶段以外访问findProperty的结果来控制 task 输入——它虽然可用,但值可能被 later 配置覆盖
在自定义插件中读取用户传入属性的推荐姿势
如果你开发的是二进制插件(实现 Plugin<Project>),应在 apply 方法内通过 project.findProperty() 获取,而非依赖 ext 或硬编码。例如:
class MyPlugin implements Plugin<Project> {
void apply(Project project) {
def enabled = project.findProperty('myPlugin.enabled')?.toBoolean() ?: false
if (enabled) {
project.tasks.register('myCustomTask') { /* ... */ }
}
}
}注意两点:
- 不要在插件构造函数或静态块里读取——
Project实例还没 ready - 如果属性用于配置 extension(比如
myPlugin { enabled = ... }),应优先走 extension DSL,而不是 fallback 到findProperty;后者只适合“开关类”轻量配置 -
findProperty在settings.gradle里不可用(此时Project尚未创建),需改用settings.findProperty()
为什么 gradle.properties 里的属性有时读不到?
常见原因不是语法错,而是加载时机或作用域问题:
-
gradle.properties在初始化阶段就加载,但若你在子项目build.gradle里调用findProperty,只能读到**本项目及父项目**中定义的属性,不会自动继承 sibling 项目的gradle.properties - 如果用了
includeBuild,嵌套构建的gradle.properties**不会合并到主构建上下文**,必须显式通过-P透传 -
local.properties不是 Gradle 原生属性源,需手动加载(用Properties.load()),findProperty对它无效 - IDE(如 Android Studio)可能缓存旧的
gradle.properties,改完后要触发 “Refresh project” 或清掉.gradle缓存目录
最易被忽略的一点:Gradle 属性名不支持点号(.)作为层级分隔符——myplugin.enabled 在 gradle.properties 里会被当作文本键名,但 findProperty('myplugin.enabled') 无法命中;得用下划线或驼峰,如 myplugin_enabled。

















