gradleAndroid开发经验谈首页投稿(暂停使用,暂停投稿)

Android 自动构建-签名信息及文件拷贝

2016-07-29  本文已影响553人  花开堪折枝

根据项目需求,现要在团队内部搭建一个统一的打包平台,实现对Android项目的打包。而且为了方便团队内部的测试包分发。

打包平台使用的是Jenkins,在构建前面我们面临的两个问题就是:

TODO

环境搭建

自行在查询,因为大家的平台可能都不同,现在这类的文章已经很多了,这里就不进行展开了。

签名文件管理

这个需要达到两个目标且不能去修改配置相关信息和使用简单

设计思路:
通过在打包的机器添加一个环境变量来判断是否是打包机器,这样就可以使用试用两份配置,部分代码如下(后面会提供全部):

File propFile = file(isJenkins ?  configPath : 'apk.properties');
if (propFile.exists()) {
    def Properties props = new Properties()
    props.load(new FileInputStream(propFile))
    if (props.containsKey('STORE_FILE') && props.containsKey('STORE_PASSWORD') &&
            props.containsKey('KEY_ALIAS') && props.containsKey('KEY_PASSWORD')) {

        //配置签名信息
    } else {
        throw new IllegalArgumentException('apk.properties')
    }
} else {
    println "apk.properties not exist"
    android.buildTypes.release.signingConfig = null
}

apk存储

每天、每次构建出来的apk都有记录,方便获取当前软件最新的apk,所以一共保存了三个地方。

完整脚本信息如下:

打包运行:

gradle clean publishRelease
APK_NAME=test.apk //apk输入名称
APK_DIR=d:/test   //保存目录
STORE_FILE=u2020.keystore
STORE_PASSWORD=android
KEY_ALIAS=android
KEY_PASSWORD=android
def storeDir = System.getenv("STORE_ROOT") //配置文件存储路径
def os = System.getProperty("os.name")     // 系统类型
def isJenkins = "true".equals(System.getenv("IS_JENKINS")) //是否是打包机
def projectRootName = project.rootProject.name


if (isJenkins && storeDir == null){
    throw new NullPointerException('storeDir is null, you need add it in system env ' +
            'with key: STORE_ROOT')
}

project.ext{
    projectName = projectRootName
    apkName = projectName + ".apk"
    apkRootDir = null
    outputPath = null
    sourceApk = null
    sourceApkName = null
}

/**
 * 默认打包完把apk存储的目录
 * win :d:/
 * mac :/Download
 * linux : /opt
 */

if (project.ext.apkRootDir == null){
    if (os == null || os.indexOf('windows')){
        project.ext.apkRootDir = 'd:/'
    }else if (os.indexOf('linux') > 0){
        project.ext.apkRootDir = '/opt'
    }else if (os.indexOf('windows')){
        project.ext.apkRootDir = '/Download'
    }
}


def configPath = storeDir + project.ext.projectName + "/apk.properties"
println "config path: " + configPath

File propFile = file(isJenkins ?  configPath : 'apk.properties');
if (propFile.exists()) {
    def Properties props = new Properties()
    props.load(new FileInputStream(propFile))
    if (props.containsKey('STORE_FILE') && props.containsKey('STORE_PASSWORD') &&
            props.containsKey('KEY_ALIAS') && props.containsKey('KEY_PASSWORD')) {

        android.signingConfigs.release.storeFile = file(props['STORE_FILE'])
        android.signingConfigs.release.storePassword = props['STORE_PASSWORD']
        android.signingConfigs.release.keyAlias = props['KEY_ALIAS']
        android.signingConfigs.release.keyPassword = props['KEY_PASSWORD']

        project.ext.apkName = props['APK_NAME']
        project.ext.apkRootDir = props['APK_DIR']
        if (hasProperty('PROJECT_NAME')){
            project.ext.projectName = PROJECT_NAME
        }

        println "apkName: " + project.ext.apkName
        println "apk store dir: " + project.ext.apkRootDir
        println "projectName: " + project.ext.projectName
    } else {
        throw new IllegalArgumentException('invalid args in apk.properties')
    }
} else {
    println "apk.properties not exist"
    if (isJenkins){
        throw new FileNotFoundException("File not found at: " + configPath)
    }else{
        android.buildTypes.release.signingConfig = null
    }
}


def buildDay = new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("GMT+8"))
def buildTime = new Date().format("yyyy-MM-dd HH.mm.ss", TimeZone.getTimeZone("GMT+8"))


android.applicationVariants.all { variant ->
    if (variant.buildType.name == 'release') {
        variant.outputs.each { output ->
            project.ext.sourceApk = output.outputFile.getAbsolutePath();
            project.ext.sourceApkName = output.outputFile.getName()
        }
    }
}

task publishRelease(dependsOn: 'assembleRelease') << {
    //构建最新的,固定位置,方便拷贝
    def onlyApkDir = project.ext.apkRootDir + "/" ;
    def onlyApk = onlyApkDir + project.ext.projectName + ".apk";
    //每日保存最新的一个
    def dayApkDir = project.ext.apkRootDir + "/" + buildDay + "/";
    def dayApk = dayApkDir + project.ext.projectName + ".apk";
    //保留每次打包的apk
    def timesApkDir = project.ext.apkRootDir + "/" + buildDay + "/" + project.ext.projectName + "/";

    def srcApk = project.ext.sourceApk
    def srcName = project.ext.sourceApkName
    //clean
    File dk = new File(dayApk)
    if (dk.exists()){
        dk.delete()
    }

    File ok = new File(onlyApk)
    if (ok.exists()){
        ok.delete()
    }

    copy{
        from srcApk
        into onlyApkDir + project.ext.apkName
        rename srcName, project.ext.apkName
    }

    copy{
        from srcApk
        into dayApkDir
        rename srcName, project.ext.apkName
    }

    copy{
        from srcApk
        into timesApkDir
        rename srcName, buildTime + ".apk"
    }
}

看到这里,点个赞吧

上一篇下一篇

猜你喜欢

热点阅读