android文本自动添加,Android 自动构建-签名信息及文件拷贝

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

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

签名文件如何配置(开发人员是不可以见的)

打包出来的apk如何的再发布和出问题如何回滚到上一次的apk

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,所以一共保存了三个地方。

apk存储的根目录, 永远都是最新的apk,方便集成发布工具

apk存储的根目录/日期 , 每日构建的apk,方便查询指定日期的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"

}

}

看到这里,点个赞吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值