Android的持續(xù)化集成及多版本打包

文檔概述

關于Android開發(fā)饲趋,除了技術方面需要掌握,還有發(fā)布流程需要了解撤蟆。本文檔就包括以上兩個方面奕塑,主要介紹:

  • 使用配置文件配置不同功能的apk
  • 使用gradle為Android構建簽名包
  • Jenkins集成Android自動化打包
  • 使用gradle為Android生成不同配置的簽名包

一、場景描述

在項目開發(fā)中枫疆,我們可能有多個功能有區(qū)別但是整體框架一致的工程爵川。

情景:我們有一app敷鸦,基礎功能包括a,b,c,擴張功能包括d,e,f息楔,其中客戶1需要擴展功能d,f,客戶2需要e,f扒披。

二值依、配置文件簡介

鑒于以上場景,開發(fā)app過程應該怎么做碟案?如果客戶1創(chuàng)建一份工程代碼愿险,客戶2創(chuàng)建一份工程代碼效率就太低了。因此我們需要另辟思路价说,采用配置文件的方式進行開發(fā)辆亏。

配置文件分類

關于配置文件目前有兩種方式:

  1. apk文件寫注釋
  2. apk源碼屬性文件

配置方式的區(qū)別

方式1主要適用于輕量的注釋,例如書寫渠道名等一些簡單的注釋鳖目,不用修改源碼扮叨。方式2就比較適合當前的場景,但是缺點在于配置文件在源碼部分领迈,所以修改配置文件就必須修改源碼彻磁。

配置文件的使用

關于方式1的使用,可以: 美團批量打包

基本原理就是在apk文件生成之后狸捅,修改apk文件的部分字段衷蜓,而不影響apk本身簽名驗證,在源碼中根據(jù)apk安裝的位置獲取安裝包文件再讀取其中的字段尘喝。

方式2就是使用屬性文件磁浇。實現(xiàn)方式就是使用java.util.Properties類進行文件加載。
預先在Android工程的main文件夾下創(chuàng)建assets文件夾朽褪,里面存放配置文件置吓,客戶1的配置文件命名為:a.properties鳍贾,b.properties,里面的內(nèi)容如下:

fun_a=true
fun_b=true
fun_c=true
fun_d=true
fun_e=false
fun_f=true

讀取配置屬性代碼:

public String funX(Context context, String x){
    Properties props = new Properties();
    try {
        props.load(context.getAssets().open("a.properties"));
    //  props.load(context.getAssets().open("b.properties"));
    } catch (IOException e) {
        e.printStackTrace();
    }
    return props.getProperties("fun_" + x);
}

在源碼中根據(jù)對應函數(shù)的配置信息決定是否執(zhí)行對應操作交洗。

對于客戶1和客戶2的不同需求可以選擇性的加載配置文件進行打包操作骑科。

以上就是不同需求的具體操作。但是我們可以發(fā)現(xiàn)构拳,這個操作效率太低咆爽,每次打包都要修改源碼。下面介紹自動化過程置森。

三斗埂、 自動化之gradle打包

配置操作

為了之后可以執(zhí)行自動化操作,簽名必須也要能進行自動化執(zhí)行凫海。

首先放置簽名文件到:項目的根目錄呛凶。

modulebuild.gradle文件中添加以下內(nèi)容:

apply plugin: 'com.android.application'

def keystorePSW = ''
def keystoreAlias = ''
def keystoreAliasPSW = ''
// default keystore file, PLZ config file path in local.properties
Properties properties = new Properties()
// local.properties file in the root director
properties.load(project.rootProject.file('gradle.properties').newDataInputStream())

keystorePSW = properties.getProperty("keystore.password")
keystoreAlias = properties.getProperty("keystore.alias")
keystoreAliasPSW = properties.getProperty("keystore.alias_password")

android {
    ...
    signingConfigs {
        release {
            keyAlias keystoreAlias
            keyPassword keystoreAliasPSW
            storePassword keystorePSW
            storeFile file('../xxx.jks')            // 簽名文件的位置
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            zipAlignEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
    }
}
dependencies {
    ...
}

為了能夠在Jenkins環(huán)境也能使用自動打包操作,在項目的根目錄gradle.properties文件中添加如下內(nèi)容:

keystore.password = xxx             // 密鑰的密碼
keystore.alias = xxx                // 密鑰的別稱
keystore.alias_password = xxx       // 別稱的密碼

隨后在項目的根目錄下使用gradle即可進行打包行贪。

執(zhí)行命令

打包命令:

gradlew clean               // 清除build文件夾
// 二選一
gradlew build               // 檢查依賴并編譯打包漾稀,會生成debug和release兩個包
gradlew assesmRelease       // 生成release包

執(zhí)行以上命令之后,會在項目的app/build/output/apk/*.apk生成對應的apk建瘫。

注:Windows操作系統(tǒng)使用gradlew崭捍,Linux系統(tǒng)使用./gradlew

以上啰脚,使用gradle自動打包就以完成殷蛇。下面就是集成Jenkins持續(xù)集成環(huán)境了。

四橄浓、Jenkins集成

創(chuàng)建項目

關于構建介紹可以參考:Jenkins+Gradle實現(xiàn)android開發(fā)持續(xù)集成粒梦、打包

配置信息沒什么特別的。主要是輸出文件路徑:直接填寫app/build/output/app/*.apk即可荸实。

輸出文件路徑

可能遇到的問題

  • 由于Jenkins自動構建匀们,所以對語法要求比較嚴格。如果出現(xiàn)以下錯誤:

      FAILURE: Build failed with an exception.
      * What went wrong:
      Execution failed for task ':app:lint'.
      > Lint found errors in the project; aborting build.
       
        Fix the issues identified by lint, or add the following to your build script to proceed with errors:
        ...
        android {
            lintOptions {
                abortOnError false
            }
        }
        ...
      
      * Try:
      Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
    

    這個是因為代碼不符合規(guī)范泪勒,lint檢查時報錯昼蛀,因此中斷了整個編譯過程。

    只要在當前app的app/build.gradle文件內(nèi)增加如下代碼:

      android{
          ...
          lintOptions{
              abortOnError false
          }
          ...
      }
    
  • 安裝Jenkins配置局域網(wǎng)訪問

    在mac安裝Jenkins之后圆存,局域網(wǎng)無法訪問叼旋,原因在于使用brew安裝jenkins會避免很多其他安裝方式產(chǎn)生的用戶權限問題,但是會將httpListenAddress默認設置為127.0.0.1沦辙,這樣我們雖然可以在本地用localhost:8080訪問夫植,但是本機和局域網(wǎng)均無法用ip訪問。解決辦法為修改兩個路徑下的plist配置。

      ~/Library/LaunchAgents/homebrew.mxcl.jenkins.plist
      /usr/local/opt/jenkins/homebrew.mxcl.jenkins.plist
    

    修改之后重啟Jenkins即可訪問详民。

      brew services start jenkins         // 開啟服務
      brew services stop jenkins          // 關閉服務
      brew services restart jenkins       // 重啟服務
    
  • 更多錯誤查看:

    使用Jenkins持續(xù)集成Android項目遇到的坑

通過以上操作延欠,Android項目就可以使用Jenkins自動集成了。

但是我們第一部分的場景問題還是沒有解決沈跨,如何自動化區(qū)分客戶的版本呢由捎?

五、自動化版本區(qū)分

Android官網(wǎng)介紹了 構建變體

通過配置不同的 productFlavors我們可以獲取不同版本的apk饿凛。

因此第一部分的需求通過以下操作實現(xiàn)狞玛。

更新buidl.gradle文件

android {
    ...
    buildTypes {
        ...
    }

    productFlavors {
        fun_a {
            buildConfigField "String", "CONF_NAME", "\"a.properties\""
        }
        fun_b {
            buildConfigField "String", "CONF_NAME", "\"b.properties\""
        }
    }
}

修改讀取配置文件代碼

配置屬性文件不變涧窒,讀取的代碼進行如下修改:

public String funX(Context contex, tString x){
    Properties props = new Properties();
    try {
        props.load(context.getAssets().open(BuildConfig.CONF_NAME));
    } catch (IOException e) {   
        e.printStackTrace();
    }
    return props.getProperties("fun_" + x);
}

之后使用打包命令就會生成兩個apk安裝包心肪,一個是客戶1定制的功能,一個是客戶2定制的功能纠吴。

輸出路徑不變硬鞍,生成包名:

  • app-fun_a-releas.apk
  • app-fun_b-releas.apk

這樣,Jenkins一次編譯也就可以獲取到正確的版本戴已。

修改輸出文件的包名

以上操作之后已經(jīng)可以正確獲取目標apk固该,但是并不直觀。如果可以在輸出文件名中添加輸出版本號和打包時間就完美了恭陡。

在項目的build.gradle文件中蹬音,最后節(jié)點添加:

def releaseTime() {
    return new Date().format("yyyyMMdd-HHmm", TimeZone.getTimeZone("GMT+08:00"))
}
android{
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def outputFile = output.outputFile
            if (variant.buildType.name.equals('release')) {
                def fileName = outputFile.name.replace("app-","").replace("release", "v${defaultConfig.versionName}-${releaseTime()}")
                output.outputFile = new File(outputFile.parent, fileName)
            }
        }
    }
}

修改之后輸出文件名:

fun_a-v2.0.5-20171115-1655.apk
fun_b-v2.0.5-20171115-1655.apk

以上上煤。

六休玩、小結(jié)

通過使用gradle+Jenkins,可以讓程序員從繁復的打包任務中解放出來劫狠,更多時間去做核心開發(fā)的相關業(yè)務拴疤。

gradle的功能強大到我沒法想象,好好學習独泞,好好鉆研呐矾。

技術,可以解放你懦砂。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蜒犯,一起剝皮案震驚了整個濱河市赏壹,隨后出現(xiàn)的幾起案子马澈,更是在濱河造成了極大的恐慌,老刑警劉巖丁逝,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件羽资,死亡現(xiàn)場離奇詭異淘菩,居然都是意外死亡,警方通過查閱死者的電腦和手機屠升,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門潮改,熙熙樓的掌柜王于貴愁眉苦臉地迎上來狭郑,“玉大人,你說我怎么就攤上這事汇在『踩” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵糕殉,是天一觀的道長缨历。 經(jīng)常有香客問我,道長糙麦,這世上最難降的妖魔是什么辛孵? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮赡磅,結(jié)果婚禮上魄缚,老公的妹妹穿的比我還像新娘。我一直安慰自己焚廊,他們只是感情好冶匹,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著咆瘟,像睡著了一般嚼隘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上袒餐,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天飞蛹,我揣著相機與錄音,去河邊找鬼灸眼。 笑死卧檐,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的焰宣。 我是一名探鬼主播霉囚,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼匕积!你這毒婦竟也來了盈罐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤闪唆,失蹤者是張志新(化名)和其女友劉穎盅粪,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體苞氮,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡湾揽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片库物。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡霸旗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出戚揭,到底是詐尸還是另有隱情诱告,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布民晒,位于F島的核電站精居,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏潜必。R本人自食惡果不足惜靴姿,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望磁滚。 院中可真熱鬧佛吓,春花似錦、人聲如沸垂攘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽晒他。三九已至吱型,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間陨仅,已是汗流浹背津滞。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留掂名,地道東北人据沈。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像饺蔑,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子嗜诀,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容