Android 项目 Build 总结


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


文章作者: ECM
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 ECM !
评论
  目录