使用Gradle構建Android項目

新項目中,使用了Google I/O 2013發佈的新工具,使用Gradle構建android項目,並且在新版的Intellig IDEA以及google的Android Studio對其支持。本文就介紹一下怎麼使用gradle構建android項目,進行多個版本編譯。

Gradle是什麼?

Gradle是以Groovy爲基礎,面向java應用,基於DSL語法的自動化構建工具。是google引入,替換ant和maven的新工具,其依賴兼容maven和ivy。 
使用gradle的目的:

  • 更容易重用資源和代碼;

  • 可以更容易創建不同的版本的程序,多個類型的apk包;

  • 更容易配置,擴展;

  • 更好的IDE集成;

環境需求

Gradle1.10或者更高版本,grale插件0.9或者更高版本. 
android SDK需要有Build Tools 19.0.0以及更高版本

Gradle基本結構

使用ide創建的gradle構建的項目,會自動創建一個build.gradle,如下:

buildscript {    repositories {
        mavenCentral()
    }    dependencies {        classpath 'com.android.tools.build:gradle:0.9.0'
    }
}

apply plugin: 'android'android {
    compileSdkVersion 19
    buildToolsVersion "19.0.0"}

可以看到,構建文件主要有三個區域:

buildscript{…}

Configures the build script classpath for this project. 設置腳本的運行環境

apply plugin: 'android'

設置使用android插件構建項目

android{…}

設置編譯android項目的參數

任務task的執行

通常會有以下任務:

  • assemble The task to assemble the output(s) of the project(輸出一個項目文件,android就是打包apk)

  • check The task to run all the checks.(運行檢查,檢查程序的錯誤,語法,等等)

  • build This task does both assemble and check (執行assemble和check)

  • clean This task cleans the output of the project(清理項目輸出文件)

上面的任務assemble,check,build實際上什麼都不做,他們其實都是其他任務的集合。

執行一個任務的方式爲gradle 任務名, 如gradle assemble

在android項目中還有connectedCheck(檢查連接的設備或模擬器),deviceCheck(檢查設備使用的api版本)

通常我們的項目會有至少生成兩個版本,debug和release,我們可以用兩個任務assembleDebug和assembleRelease去分別生成兩個版本,也可以使用assemble一下子生成兩個版本。

gradle支持任務名縮寫,在我們執行gradle assembleRelease的時候,可以用gradle aR代替。

基本的構建定製

我們可以在build.gradle文件中配置我們的程序版本等信息,從而可以生成多個版本的程序。 
支持的配置有:

  • minSdkVersion 最小支持sdk版本

  • targetSdkVersion 編譯時的目標sdk版本

  • versionCode 程序版本號

  • versionName 程序版本名稱

  • packageName 程序包名

  • Package Name for the test application 測試用的程序包名

  • Instrumentation test runner 測試用的instrumentation實例

例如:

android {    compileSdkVersion 19
    buildToolsVersion "19.0.0"

    defaultConfig {        versionCode 12
        versionName "2.0"
        minSdkVersion 16
        targetSdkVersion 16
    }
}

目錄配置

默認情況下項目目錄是這樣的 
有兩個組件source sets,一個main,一個test,對應下面兩個文件夾。 
src/main/ 
src/androidTest/

然後對於每個組件目錄都有兩個目錄,分別存儲java代碼和資源文件 
java/ 
resources/

對於android項目中呢,對應的目錄和文件是 
AndroidManifest.xml //該文件src/androidTest/目錄下不需要,程序執行時會自動構建 
res/ 
assets/ 
aidl/ 
rs/ 
jni/

如果需要上面這些文件,但是不是在上面所說的目錄,則需要設置。

sourceSets {    main {        java {            srcDir 'src/java'
        }
        resources {            srcDir 'src/resources'
        }
    }
}

可以給main或者test設置根目錄,如

 sourceSets {
        androidTest.setRoot('tests')
    }

可以指定每種文件的存儲路徑

sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']        }
    }

特別是我們的ndk生成的.so文件,通常我們不是放到jni目錄中的,我們需要設置一下

sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }

簽名配置

可以給不同類型進行不同的配置,先看示例:

android {    signingConfigs {        debug {            storeFile file("debug.keystore")
        }

        myConfig {            storeFile file("other.keystore")
            storePassword "android"
            keyAlias "androiddebugkey"
            keyPassword "android"
        }
    }

    buildTypes {        foo {            debuggable true
            jniDebugBuild true
            signingConfig signingConfigs.myConfig
        }
    }
}

上面的配置文件配置兩個類型,一個時debug類型,一個時自己的自定義類型。兩個分別使用了不同的簽名,同時對於生成密鑰,要填寫設置的密碼。

代碼混淆設置

直接看代碼:

android {    buildTypes {        release {            runProguard true
            proguardFile getDefaultProguardFile('proguard-android.txt')
        }
    }
}

以上是使用默認的proguard文件去進行混淆,也可以使用自己編寫的規則進行混淆,proguardFile 'some-other-rules.txt'

依賴配置

程序中會依賴別的包,或者程序,需要引入別的類庫。前面也說到了,支持maven。 
對於本地的類庫,可以這樣引入:

dependencies {
    compile files('libs/foo.jar')   //單個文件
    compile fileTree(dir: 'libs', include: ['*.jar'])  //多個文件
}

android {    ...}

對於maven倉庫文件:

repositories {
    mavenCentral()
}


dependencies {
    compile 'com.google.guava:guava:11.0.2'}

android {    ...}

輸出不同配置的應用

看代碼:

android {    ...

    defaultConfig {
        minSdkVersion 8
        versionCode 10
    }

    productFlavors {
        flavor1 {
            packageName "com.example.flavor1"
            versionCode 20
        }

        flavor2 {
            packageName "com.example.flavor2"
            minSdkVersion 14
        }
    }
}

通過以上設置,我們可以輸出不同的保命不同的版本號,以及最小sdk的程序包。當然我們可以根據自己的需求去做其他的不同

生成多個渠道包(以Umeng爲例)

我的完整配置文件

buildscript {    repositories {
        mavenCentral()
    }    dependencies {        classpath 'com.android.tools.build:gradle:0.9.+'
    }
}
apply plugin: 'android'repositories {
        mavenCentral()
}

android {
    compileSdkVersion 19
    buildToolsVersion "19.0.3"

    defaultConfig {
        minSdkVersion 8
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    }    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }

    lintOptions {
        abortOnError false
    }//簽名
    signingConfigs {        //你自己的keystore信息
        release {
            storeFile file("×.keystore")
            storePassword "×××"
            keyAlias "××××"
            keyPassword "×××"
        }
    }

    buildTypes {

        debug {
            signingConfig signingConfigs.release
        }

        release {
            signingConfig signingConfigs.release
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }    //渠道Flavors,我這裏寫了一些常用的,你們自己改
    productFlavors {        //GooglePlay{}
        //Store360{}
        //QQ{}
        //Taobao{}
        //WanDouJia{}
        //AnZhuo{}
        //AnZhi{}
        //BaiDu{}
        //Store163{}
        //GFeng{}
        //AppChina{}
        //EoeMarket{}
        //Store91{}
        //NDuo{}
        xiaomi{}
        umeng{}
    }

}//替換AndroidManifest.xml的UMENG_CHANNEL_VALUE字符串爲渠道名稱android.applicationVariants.all{ variant ->
    variant.processManifest.doLast{        //之前這裏用的copy{},我換成了文件操作,這樣可以在v1.11版本正常運行,並保持文件夾整潔
        //${buildDir}是指./build文件夾
        //${variant.dirName}是flavor/buildtype,例如GooglePlay/release,運行時會自動生成
        //下面的路徑是類似這樣:./build/manifests/GooglePlay/release/AndroidManifest.xml
        def manifestFile = "${buildDir}/manifests/${variant.dirName}/AndroidManifest.xml"

        //將字符串UMENG_CHANNEL_VALUE替換成flavor的名字
        def updatedContent = new File(manifestFile).getText('UTF-8').replaceAll("UMENG_CHANNEL_VALUE", "${variant.productFlavors[0].name}")        new File(manifestFile).write(updatedContent, 'UTF-8')        //將此次flavor的AndroidManifest.xml文件指定爲我們修改過的這個文件
        variant.proce***esources.manifestFile = file("${buildDir}/manifests/${variant.dirName}/AndroidManifest.xml")
    }
}

以上的功能就是替換我的Manifest中的umeng渠道標示,同時去生成不同的apk包。

最後說明

程序在buid的時候,會執行lint檢查,有任何的錯誤或者警告提示,都會終止構建,我們可以將其關掉。

lintOptions {        abortOnError false
    }

最後PS一下

本人使用gradle確實方便很多,雖然電腦配置低,build的時候比較慢。 
內容呢,主要時參考谷歌官方的文檔。 
關於怎麼安裝,沒有講到,可以參考這篇文章:http://stormzhang.github.io/android/2014/02/28/android-gradle/

附上我參考的文檔,沒看懂的可以去看看。http://tools.android.com/tech-docs/new-build-system/user-guide


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章