Android 项目 Build 总结
Gradle
查询当前项目依赖
./gradlew module:dependencies
最后会询问是否生成在线的doc yes
./gradlew build --scan
获得当前flavor name
import java.util.regex.Matcher
import java.util.regex.Pattern
def getCurrentFlavor() {
Gradle gradle = getGradle()
String tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
Pattern pattern;
if( tskReqStr.contains( "assemble" ) )
pattern = Pattern.compile("assemble(\\w+)(Release|Debug)")
else
pattern = Pattern.compile("generate(\\w+)(Release|Debug)")
Matcher matcher = pattern.matcher( tskReqStr )
if( matcher.find() )
return matcher.group(1).toLowerCase()
else
{
println "[error]NO MATCH FOUND"
return "";
}
}
Gradle修改输出的文件夹名称
直接设置 起始目录是rootDir
android.applicationVariants.all { variant ->
variant.outputs.all {
variant.packageApplication.outputDirectory = new File(variant.packageApplication.outputDirectory.absolutePath.replace("${variant.flavorName}","${variant.flavorName}_v${variant.mergedFlavor.versionName}"))
outputFileName = "v${variant.mergedFlavor.versionName}${variant.buildType.name}.apk".replaceAll("/", "-")
}
}
自动 versionCode
使用 Git 仓库的 commit 数量作为 versionCode。使用命令 git rev-list --count
, revision 可以是 HEAD, master, 也可以是 commit hash. 更多 git rev-list
的用法。
通常我们使用当前分支的 commit 数量:
git rev-list --count HEAD
也可以使用所有的 commit 数量:
git rev-list --all --count
在 Android Studio 中这样使用:
def cmd = 'git rev-list HEAD --count'
def gitCommitCount = cmd.execute().text.trim().toInteger()
android {
...
defaultConfig {
...
versionCode gitCommitCount
}
}
自动 versionName
使用 Git 的 tag 作为 versionName。
首先,需要在当前分支中的 commit 打上 tag,使用命令 git tag
如下:
git tag 0.0.1
然后使用命令 git describe --tags
获取当前的 tag.
在 Android Studio 中这样使用:
def cmd = 'git describe --tags'
def gitTag = cmd.execute().text.trim()
android {
...
defaultConfig {
...
versionName gitTag
}
}
在实际开发中,我们通常不会这样使用,tag 命名不适合用于 versionName.
优雅的设置 APK 文件名
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = getApkName()
}
}
gradle 读取local.properties
def readProperties(key) {
File file = rootProject.file('local.properties')
if (file.exists()) {
InputStream inputStream = rootProject.file('local.properties').newDataInputStream()
Properties properties = new Properties()
properties.load(inputStream)
if (properties.containsKey(key)) {
return properties.getProperty(key)
}
}
}
打包APP并上传到测试渠道
通过curl 上传文件
curl -F "file=@build/outputs/apk/lowversion/debug/echatsdkdemo-1.0.38-lowVersion-debug.apk" -F "_api_key=key" -F "buildUpdateDescription=update" https://www.pgyer.com/apiv2/app/upload
gradle 设置apk输出
在主gradle中,buildscript
配置ext信息
buildscript{
ext {
demoVersionCode = 1039
demoVersionName = "1.0.39"
apiKey=""
pgyUpload="https://www.pgyer.com/apiv2/app/upload"
}
}
在 application 工程的 build.gradle
中修改 apk 文件名
productFlavors {
offline {
versionName getVersionName("offline") //修改 versionName
}
lowversion {
minSdkVersion 15
versionName getVersionName("lowversion")
}
online {
versionName demoVersionName
}
admin {
versionName versionName getVersionName("管理员") //修改 versionName
}
}
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = getApkName(variant.versionName)
}
}
根据Flavor和debug模式等,手动配置apk路径供脚本上传
def getVersionName(String suffix) {
if (suffix == null || suffix.isEmpty()) {
return String.format("%s", demoVersionName)
} else {
return String.format("%s.%s", demoVersionName, suffix)
}
}
def getApkName(String versionName) {
return String.format("appName-v%s-%s.apk", versionName, releaseTime())
}
static def releaseTime() {
return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}
static def getUpdateDescription() {
return 'update'
}
private def uploadPGY(String filePath) {
def stdout = new ByteArrayOutputStream()
exec {
executable = 'curl'
args = ['-F', "file=@${filePath}", '-F', "_api_key=${apiKey}"
, '-F', "buildUpdateDescription=${getUpdateDescription()}", pgyUpload]
standardOutput = stdout
}
String output = stdout.toString()
def parsedJson = new groovy.json.JsonSlurper().parseText(output)
println parsedJson.data.buildQRCodeURL
println "版本号:" + parsedJson.data.buildVersion+" \n"
println ""
println output
}
def lowversion = "${projectDir.absolutePath}/build/outputs/apk/lowversion/%s/${getApkName(getVersionName("lowversion"))}"
def getApkPath(String path, String type) {
return String.format(path, type)
}
task uploadLowversionDebugApk(dependsOn: 'assembleLowversionDebug') {
doLast {
uploadPGY(getApkPath(lowversion, "debug"))
}
}
打包加固
https://juejin.im/post/5c977ead6fb9a070ea79d3f6
Docker 打包
docker run --rm -v ${PWD}:/build -w /build circleci/android:api-29 bash -c "./gradlew assembleDebug"
Dockerfile
Android:api-29
https://github.com/CircleCI-Public/circleci-dockerfiles/blob/master/android/images/api-29/Dockerfile