VSTS Gradle构建任务Build tokens无法解析,Android版本号参数报错求助
首先得明确问题出在哪:你用的$(Year:yy)$(DayOfYear)$(rev:r)这类是CI系统(比如Azure DevOps)的变量占位符,但这些符号没有被CI环境提前解析成实际的数字,就直接原封不动传给了Gradle。而Android的versionCode要求必须是整数,Gradle拿到一堆$()符号的字符串,自然会报错“输入字符串无效”。
下面给你几个可行的解决思路:
1. 让CI提前解析变量再传给Gradle
如果是用Azure DevOps这类支持管道变量的CI,关键要确保这些占位符在执行gradlew命令前就被替换成真实值:
- 先在CI的变量面板里定义一个组合变量,比如叫
fullVersionCode,值设为$(Year:yy)$(DayOfYear)$(rev:r) - 然后在Gradle构建任务的参数里引用这个预定义的变量:
-PversionCode=$(fullVersionCode)
或者直接调整命令写法,确保CI能识别并解析引号内的变量(部分CI系统对双引号内的变量解析支持更好):
C:\Windows\system32\cmd.exe /D /S /C "D:\a\3\s\gradlew.bat -PversionCode=$(Year:yy)$(DayOfYear)$(rev:r) build"
如果还是不行,试试去掉外层引号,或者改用PowerShell执行(变量解析逻辑更稳定):
& "D:\a\3\s\gradlew.bat" "-PversionCode=$($env:BUILD_YEAR_2D)$($env:BUILD_DAY_OF_YEAR)$($env:BUILD_REVISION)" build
(这里需要对应CI环境里的环境变量名称,比如Azure DevOps里$(Year:yy)对应的环境变量是BUILD_YEAR_2D,可以查CI的文档确认)
2. 直接在Gradle脚本里生成版本号(更可控)
不想依赖CI的变量解析?那可以把版本号的生成逻辑直接写到Gradle里,这样不管是CI还是本地构建都能正常生成唯一版本号:
在你的app/build.gradle文件里添加这段代码:
def generateUniqueVersionCode() { def now = new Date() // 取年份后两位(比如2024→24) def year = String.format("%02d", now[Calendar.YEAR] % 100) // 取一年中的第几天,补前导零到3位(比如第5天→005) def dayOfYear = String.format("%03d", now[Calendar.DAY_OF_YEAR]) // 从环境变量取CI的修订号,本地构建默认用0 def revision = System.getenv("CI_BUILD_REVISION") ?: "0" // 拼接成整数返回 return Integer.parseInt(year + dayOfYear + revision) } android { defaultConfig { versionCode generateUniqueVersionCode() // 你的其他配置... } }
之后在CI里只需要把$(rev:r)的值注入到CI_BUILD_REVISION环境变量里就行,本地构建时会自动用0填充,完全不需要在命令行传版本号参数了。
3. 排查命令行的引号转义问题
你原来的命令里把-PversionCode=...放在了外层双引号里,有些CMD环境下可能会导致内部的$()被当成CMD的变量而不是CI的变量。试试把命令拆成更简单的形式:
cd D:\a\3\s && gradlew.bat -PversionCode=$(Year:yy)$(DayOfYear)$(rev:r) build
这样能减少CMD的转义干扰,让CI更顺利地解析变量。
内容的提问来源于stack exchange,提问作者Santhosh

