Jenkins+Gradle實現Android自動化構建

Jenkins簡介

Jenkins是一個開源軟件項目,旨在提供一個開放易用的軟件平臺,使軟件的持續集成變成可能。目前大部分公司都在使用Jenkins來持續構建。html

Jenkins下載與安裝配置

Jenkins下載

安裝Jenkins有兩種方式:
第一種就是下載安裝包直接安裝,下載地址:http://mirrors.jenkins-ci.org
第二種就是下載war包,放到Tomcat中啓動。war包下載地址:http://mirrors.jenkins-ci.org...
或者http://updates.jenkins-ci.org...
這裏由於我電腦上面以前裝了Tomcat,因此我使用直接下載war包的方式進行安裝。android

Jenkins安裝

將下載的jenkins.war放到Tomcat下的webapps目錄下,而後啓動Tomcat。在瀏覽器中訪問"Tomcat訪問地址/jenkins"便可安裝,由於個人Tomcat裝在本機,而且端口爲8080,因此訪問http://localhost:8080/jenkins/便可進行安裝。git

Jenkins配置

Jenkins安裝以後能夠進行用戶的權限設置、插件的安裝等配置。github

用戶權限設置

系統管理-->Configure Global Security
以下圖所示,在此處能夠添加、刪除用戶以及配置用戶權限。
圖片描述web

插件安裝

搭建Android自動化打包環境須要安裝Gradle插件,若是使用Git還須要Git的插件,安裝Jenkins時默認已經安裝了這兩個插件。若是沒有安裝能夠進入「系統管理>管理插件」進行插件的安裝。
圖片描述瀏覽器

建立Jenkins任務

要想Jenkins可以幫咱們自動構建項目,咱們須要建立一個任務,而且配置這個任務要它幫咱們執行什麼操做,以及何時執行等。
圖片描述app

如上圖所示,點擊「新建」按鈕而且選擇「構建一個自由風格的軟件項目」,完了以後會進入到任務的配置界面,配置好以後任務會出如今如上圖右邊的任務列表中。框架

任務配置

建立一個任務以後,會自動跳轉到任務的配置界面對該任務進行配置,大概包括以下配置:webapp

源碼管理

圖片描述
構建項目,固然得有代碼了。Jenkins支持使用版本控制工具來進行源碼管理,好比Git或者SVN。這裏我使用的是Git,項目使用的是個人github上面的一個多渠道打包的demo。在Repository URL中輸入項目地址,點擊Add按鈕添加認證信息,而後選擇構建的分支,我這裏使用的是master分支。工具

構建觸發器

圖片描述

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...
圖片描述
Tasks中填上須要執行的gradle的task。上面我填的clean assembleRelease,即執行gradlew clean assembleRelease。

構建後的操做

配置構建後的操做可讓Jenkins在構建完以後執行什麼操做,好比郵件通知、構建其它項目等。
圖片描述
這裏我配置了Archive the artifacts,在「用於存檔的文件」中填寫須要存檔的文件名,可使用通配符。好比上面我配置了app/build/outputs/apk/v*.apk,表示疑v開頭的apk文件都存檔。構建完以後在任務首頁能夠下載存檔的文件。
任務配置完成以後,點擊任務首頁的「當即構建」按鈕,便可開始構建,構建過程首先會將源碼下載下來,位於jenkins目錄下的workspace中。而後執行配置好的gradle命令,若是使用gradlew,第一次應該會下載gradlew設置的版本的gradle,最後執行構建任務。構建完以後,以下圖,能夠看到存檔的文件,點擊便可下載。
圖片描述

附: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/201...

相關文章
相關標籤/搜索