android開發之Jenkins+Gradle實現android開發持續整合、多渠道打包
需求:
我今天在專案上加了一個功能,那麼一個好的專案開發流程必然得跑單元測試,意思是:“改一次程式碼,需要手動跑一次單元測試,來檢驗程式碼在當前情況下是否能執行成功!”,但每次都需要手動跑的話就太累了,因為一個新增專案功能,我一天下來可能會改十幾次程式碼。因此我們將目標鎖定一下,只要某個工具能實時監控,每當svn上專案版本更改後,我就自動構建,然後跑一次單元測試,當然也可以改成每天一次或者每小時一次來監控svn上專案版本更改情況(隨你配置,後面會講),這樣豈不是妙湛!
一、Jenkins簡介
Jenkins是一個開源專案,提供了一種易於使用的持續整合系統,使開發者從繁雜的整合中解脫出來,專注於更為重要的業務邏輯實現上。同時Jenkins能實現監控整合中存在的錯誤,提供詳細的日誌檔案和提醒功能,還能用圖表的形式形象地展示專案構建的趨勢和穩定性。Jenkins的前身是Hudson,是一個可擴充套件的持續整合引擎。
二、Jenkins安裝與配置
- 安裝:將下載的jenkins.war包直接放到tomcat下的webapps目錄下,然後啟動tomcat即可安裝完成,接下來登入:http://localhost:8080/jenkins就能進入jenkins系統頁面,在此不說tomcat如何配置環境變數。
編碼問題:
- 當你進入jenkins系統管理頁面,會出現如圖提示,可修改tomcat的server.xml配置,在Connector 標籤新增上 URIEncoding=”UTF-8” 。
- 當你進入jenkins系統管理頁面,會出現如圖提示,可修改tomcat的server.xml配置,在Connector 標籤新增上 URIEncoding=”UTF-8” 。
配置:
三、Jenkins Gradle外掛安裝
點選“系統管理”–> “管理外掛” –> “可選外掛” 選中Gradle plugin外掛安裝重啟即可。
設定代理
四、Jenkins新建任務
點選“新建”
選擇“原始碼系統”
Repository URL: svn 的 的地址,如果輸入的地址需要輸入使用者名稱和密碼,將自動跳出紅色的提示資訊,點選”enter credential” 進入設定svn 使用者名稱。
選擇“構建觸發器”
來到了這一步,實屬不易,這裡就是我們的天堂,就能完成“每當svn上專案版本更改後,我就自動構建,然後跑一次單元測試,當然也可以改成每天一次或者每小時一次來監控svn上專案版本更改情況。”
Build periodically:週期進行專案構建(它不關心原始碼是否發生變化)
Poll SCM:定時檢查原始碼變更(根據SCM軟體的版本號),如果有更新就checkout最新code下來,然後執行構建動作,這裡我選擇它。
選擇“日程表”
第一個引數代表的是分鐘 minute,取值 0~59;
第二個引數代表的是小時 hour,取值 0~23;
第三個引數代表的是天 day,取值 1~31;
第四個引數代表的是月 month,取值 1~12;
第五個引數代表的是星期 week,取值 0~7,0 和 7 都是表示星期天。
如H/5 * * * * 表示的就是每5分鐘檢查一次原始碼變化。選擇 “構建”,新增“Invoke Gradle script”
Switches :即gradle 後面所接的命令。上面相當於執行gradle clean build命令。- 構建後操作:構建失敗可以傳送郵件通知
五、Gradle介紹
Gradle 是以 Groovy 語言為基礎,面向Java應用為主.基於DSL(領域特定語言)語法的自動化構建工具。現在已是android的預設構建工具了。
六、android build.gradle配置
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.5.6'//依賴
}
}
apply plugin: 'android'
dependencies {
compile fileTree(dir: 'libs', include: '*.jar')//新增android依賴libs
}
android {
compileSdkVersion 17
buildToolsVersion "17.0.0"
//簽名
signingConfigs {
myConfig {
storeFile file("debug.keystore")
storePassword "android"
keyAlias "androiddebugkey"
keyPassword "android"
}
}
defaultConfig {
versionCode 1
versionName getVersionName()
minSdkVersion 8
targetSdkVersion 17
}
//渠道
productFlavors {
google{
}
tantai{
}
}
buildTypes{
release {
signingConfig signingConfigs.myConfig
runProguard true
proguardFile 'proguard.cfg'
}
}
sourceSets {
main {
manifest {
srcFile 'AndroidManifest.xml'
}
java {
srcDir 'src'
}
res {
srcDir 'res'
}
assets {
srcDir 'assets'
}
resources {
srcDir 'src'
}
aidl {
srcDir 'src'
}
}
}
}
tasks.withType(Compile) {
options.encoding = "UTF-8"
}
//替換AndroidManifest.xml的UMENG_CHANNEL_VALUE字串為渠道名稱
android.applicationVariants.all{ variant ->
variant.processManifest.doLast{
copy{
from("${buildDir}/manifests"){
include "${variant.dirName}/AndroidManifest.xml"
}
into("${buildDir}/manifests/$variant.name")
filter{
String line -> line.replaceAll("UMENG_CHANNEL_VALUE", "$variant.name")
}
variant.processResources.manifestFile = file("${buildDir}/manifests/${variant.name}/${variant.dirName}/AndroidManifest.xml")
}
}
}
遇到的問題:tomcat下gradle 構建如果遇到Could not load Logmanager “org.apache.juli.ClassLoaderLogManager”。
解決:註釋掉catalina.bat裡面的set JAVA_OPTS=%JAVA_OPTS% %LOGGING_MANAGER%即可!
注意:Gradle外掛能配置成功的前提是:“你的專案中是由Gradle構建的,否則免談”,Jenkins只是構建,得配合Gradle才能跑單元測試。
七、手動跑單元測試
- 選擇專案:
- 點選“立即構建”
- 點選“#1 / #2 …”檢視執行情況
- 點選“Console Output”–控制檯輸出
八、Gradle實現的兩種簡單的多渠道打包方法
目前我掌握的方法有兩種,都非常簡單,用的都是Gradle Android外掛裡的productFlavors。
以友盟的多渠道打包為例,假設我們需要打包出如下渠道:UMENG, WANDOUJIA, YINGYONGBAO。
第一種方法,是需要建立檔案的:
我們在寫完我們的程式碼之後,在app/src下面,分別建立和main同級目錄的資料夾umeng, wandoujia, yingyongbao,這三個資料夾裡面都各只有一個AndroidManifest.xml檔案,檔案程式碼只需要如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="your.package.name">
<application>
<meta-data android:name="UMENG_CHANNEL" android:value="UMENG"/>
</application>
</manifest>
注意,上面的value的值要和你的渠道名所對應。比如wandoujia裡面要對應為你豌豆莢上的渠道名(如WANDOUJAI)。
然後在你的build.gradle的android{}節點裡面,新增productFlavors節點,程式碼如下:
android {
// 這裡是你的其他配置
productFlavors{
umeng{ }
wandoujai { }
yingyongbao{ }
}
// 你的其他配置
}
注意這裡的flavors的名字要和你的資料夾的名字對應。這樣配置之後,構建的就是多渠道的APK了。
第二種方法,不用建立那些檔案的:
它使用的是Gradle Android外掛裡的另一個功能:manifestPlaceholders。
在這種方法中,你只需要在AndroidManifest.xml中,對友盟的渠道進行這樣配置:
<meta-data
android:name="UMENG_CHANNEL"
android:value="${CHANNEL_NAME}" />
然後同樣使用productFlavors,不過這時它的配置是這樣的:
android {
// 你的其他配置程式碼
productFlavors {
yingyongbao {
manifestPlaceholders = [ CHANNEL_NAME:"YINGYONGBAO"]
}
umeng {
manifestPlaceholders = [ CHANNEL_NAME:"UMENG" ]
}
wandoujia {
manifestPlaceholders = [ CHANNEL_NAME:"WANDOUJIA" ]
}
}
// 你的其他配置程式碼
}
在上面當中,我們也可以指定一個預設的渠道名,如果需要的話。指定預設的值是在defaultConfig節點當中新增如下內容:
manifestPlaceholders = [ CHANNEL_NAME:"Unspecified"]
這裡的Unspecified換成你實際上的預設的渠道名。
使用manifestPlaceholders的這種配置,同樣適用於manifest的其他配置。比如你需要在不同渠道釋出的apk裡面,指定不同的啟動Activity。比如在豌豆莢裡面釋出的,啟動的Activity顯示的是豌豆莢首發的介面,應用寶裡面啟動的是應用寶首發的介面(哈哈,有點壞),你就可以對你的activity的值使用①的方式,然後在productFlavors裡面配置這個①的值。
①:${activity_name}