Jenkins+Gradle实现Android自动化构建

Jenkins简介

Jenkins是一个开源软件项目,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能。目前大部分公司都在使用Jenkins来持续构建。

Jenkins下载与安装配置

Jenkins下载

安装Jenkins有两种方式:
第一种就是下载安装包直接安装,下载地址:http://mirrors.jenkins-ci.org
第二种就是下载war包,放到Tomcat中启动。war包下载地址:http://mirrors.jenkins-ci.org/war/
或者http://updates.jenkins-ci.org/download/war/
这里因为我电脑上面之前装了Tomcat,所以我使用直接下载war包的方式进行安装。

Jenkins安装

将下载的jenkins.war放到Tomcat下的webapps目录下,然后启动Tomcat。在浏览器中访问"Tomcat访问地址/jenkins"即可安装,因为我的Tomcat装在本机,并且端口为8080,所以访问http://localhost:8080/jenkins/即可进行安装。

Jenkins配置

Jenkins安装之后可以进行用户的权限设置、插件的安装等配置。

用户权限设置

系统管理-->Configure Global Security
如下图所示,在此处可以添加、删除用户以及配置用户权限。

jenkins-gradle-1.png
插件安装

搭建Android自动化打包环境需要安装Gradle插件,如果使用Git还需要Git的插件,安装Jenkins时默认已经安装了这两个插件。如果没有安装可以进入“系统管理>管理插件”进行插件的安装。

jenkins-gradle-2.png

创建Jenkins任务

要想Jenkins能够帮我们自动构建项目,我们需要创建一个任务,并且配置这个任务要它帮我们执行什么操作,以及什么时候执行等。

jenkins-gradle-3.png

如上图所示,点击“新建”按钮并且选择“构建一个自由风格的软件项目”,完了之后会进入到任务的配置界面,配置好之后任务会出现在如上图右边的任务列表中。

任务配置

创建一个任务之后,会自动跳转到任务的配置界面对该任务进行配置,大概包括如下配置:

源码管理
jenkins-gradle-4.png

构建项目,当然得有代码了。Jenkins支持使用版本控制工具来进行源码管理,比如Git或者SVN。这里我使用的是Git,项目使用的是我的github上面的一个多渠道打包的demo。在Repository URL中输入项目地址,点击Add按钮添加认证信息,然后选择构建的分支,我这里使用的是master分支。

构建触发器

jenkins-gradle-5.png

Jenkins支持上图所示的触发时机配置,如果都不选,则为手动构建,需要点击“立即构建”按钮才构建。
Build periodically:周期进行项目构建(它不关心源码是否发生变化);
Build when a change is pushed to GItHub:表示只要GitHub上面源码一更新即进行构件;
Poll SCM:定时检查源码变更(根据SCM软件的版本号),如果有更新就checkout最新code下来,然后执行构建动作。
Build periodically和Poll SCM都支持日程表的设置,这个与Spring框架中定时器的日程表配置类似,有5个参数:
第一个参数代表的是分钟 minute,取值 0~59;
第二个参数代表的是小时 hour,取值 0~23;
第三个参数代表的是天 day,取值 1~31;
第四个参数代表的是月 month,取值 1~12;
最后一个参数代表的是星期 week,取值 0~7,0 和 7 都是表示星期天。
如:
选择Build periodically并设置日程表为“0 4 * * ”,则表示每天凌晨4点构建一次源码。
选择Poll SCM并设置日程表为“
/10 * * * *”,则表示每10分钟检查一次源码变化,如果有更新才进行构建。

构建工具

因为现在Android项目默认都是使用Gradle来进行构建的,所以在构建中我选择的是Invoke Gradle script。当然你也可以选择其它的构建工具,比如Ant。
选择Invoke Gradle script之后可以选Invoke Gradle和Use Gradle Wrapper,选择Invoke Gradle就是调用本地安装配置好的Gradle,此时需要指定Gradle路径。为了方便所有开发者同意Gradle版本,一般都使用Gradle Wrapper。关于Gradle和Gradlew的区别可以看这篇文章https://www.zybuluo.com/xtccc/note/275168

jenkins-gradle-6.png

Tasks中填上需要执行的gradle的task。上面我填的clean assembleRelease,即执行gradlew clean assembleRelease。

构建后的操作

配置构建后的操作可以让Jenkins在构建完之后执行什么操作,比如邮件通知、构建其它项目等。

jenkins-gradle-7.png

这里我配置了Archive the artifacts,在“用于存档的文件”中填写需要存档的文件名,可以使用通配符。比如上面我配置了app/build/outputs/apk/v*.apk,表示疑v开头的apk文件都存档。构建完之后在任务首页可以下载存档的文件。
任务配置完成之后,点击任务首页的“立即构建”按钮,即可开始构建,构建过程首先会将源码下载下来,位于jenkins目录下的workspace中。然后执行配置好的gradle命令,如果使用gradlew,第一次应该会下载gradlew设置的版本的gradle,最后执行构建任务。构建完之后,如下图,可以看到存档的文件,点击即可下载。

jenkins-gradle-8.png

附:Android工程build.gradle文件

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        applicationId "com.lauren.multichanneldemo"
        minSdkVersion 17
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }

    signingConfigs {
        release {
            def liulingStoreFile = System.getenv("LIULING_STORE_FILE")
            def liulingKeyAlias = System.getenv("LIULING_KEY_ALIAS")
            def liulingKeyPassword = System.getenv("LIULING_KEY_PASSWORD")
            def liulingStorePassword = System.getenv("LIULING_STORE_PASSWORD")
            def isSigning = (liulingStoreFile != null) && (liulingKeyAlias != null) && (liulingKeyPassword != null) && (liulingStorePassword != null)
            if(isSigning){
                storeFile file(liulingStoreFile)
                keyAlias liulingKeyAlias
                keyPassword liulingKeyPassword
                storePassword liulingStorePassword
            } else {
                storeFile file("debug.keystore")
                keyAlias "AndroidDebugKey"
                keyPassword "android"
                storePassword "android"
            }
        }
        debug {
            storeFile file("debug.keystore")
            keyAlias "AndroidDebugKey"
            keyPassword "android"
            storePassword "android"
        }
    }

    buildTypes {
        release {
            // 不显示Log
            buildConfigField "boolean", "LOG_DEBUG", "false"
            //启用混淆代码的功能
            minifyEnabled true
            //压缩对齐生成的apk包
            zipAlignEnabled true
            //指定混淆规则,需要压缩优化的混淆要把proguard-android.txt换成proguard-android.txt
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            shrinkResources true
            signingConfig signingConfigs.release //打包命令行:gradlew assembleRelease
        }

        debug {
            signingConfig signingConfigs.debug
        }
    }

    lintOptions {
        abortOnError false
    }

//    productFlavors {
//        _91 {
//            manifestPlaceholders = [MTA_CHANNEL_VALUE: "91"]
//        }
//        wandoujia {
//            manifestPlaceholders = [MTA_CHANNEL_VALUE: "wandoujia"]
//        }
//        xiaomi {
//            manifestPlaceholders = [MTA_CHANNEL_VALUE: "xiaomi"]
//        }
//
//        _360shoufa{
//            manifestPlaceholders = [MTA_CHANNEL_VALUE: "360shoufa"]
//        }
//        anzhi{
//            manifestPlaceholders = [MTA_CHANNEL_VALUE: "anzhi"]
//        }
//        baidushoufa{
//            manifestPlaceholders = [MTA_CHANNEL_VALUE: "baidushoufa"]
//        }
//        huaweishoufa{
//            manifestPlaceholders = [MTA_CHANNEL_VALUE: "huaweishoufa"]
//        }
//    }

    // 如果嫌上面写法麻烦,也可以这样简写,加上一个批量处理即可.
    productFlavors {
        _91 {}
        wandoujia {}
        xiaomi {}
        _360shoufa{}
        anzhi{}
        baidushoufa{}
        huaweishoufa{}
    }
    //批量处理
    productFlavors.all {
        flavor ->
            def channel = name.startsWith("_") ? name.substring(1) : name
            flavor.manifestPlaceholders = [MTA_CHANNEL_VALUE: channel]
    }

    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def outputFile = output.outputFile
            if (variant.buildType.name.equals('release')) {
                //可自定义自己想要生成的格式
                def channel = variant.productFlavors[0].name.startsWith("_") ? variant.productFlavors[0].name.substring(1) : variant.productFlavors[0].name
                def fileName = "v${defaultConfig.versionName}_${releaseTime()}_${channel}.apk"
                output.outputFile = new File(outputFile.parent, fileName)
            }
        }
    }
    apply from: 'productFlavors.gradle'

}

def releaseTime() {
    return new Date().format("yyyyMMdd", TimeZone.getTimeZone("UTC"))
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:design:23.1.1'
}

本文首发:http://www.liuling123.com/2016/10/jenkins-gradle-auto-build.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容