使用Gradle構建Android項目

jopen 10年前發布 | 129K 次閱讀 Gradle 項目構建

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

Gradle是什么?

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

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

    </li>

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

    </li>

  • 更容易配置,擴展;

    </li>

  • 更好的IDE集成;

    </li> </ul>

    環境需求

    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" }</pre>

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

    buildscript{…}

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

    </blockquote>

    apply plugin: 'android'

    設置使用android插件構建項目

    </blockquote>

    android{…}

    設置編譯android項目的參數

    </blockquote>

    任務task的執行

    通常會有以下任務:

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

      </li>

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

      </li>

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

      </li>

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

      </li> </ul>

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

      </blockquote>

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

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

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

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

      基本的構建定制

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

      • minSdkVersion 最小支持sdk版本

        </li>

      • targetSdkVersion 編譯時的目標sdk版本

        </li>

      • versionCode 程序版本號

        </li>

      • versionName 程序版本名稱

        </li>

      • packageName 程序包名

        </li>

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

        </li>

      • Instrumentation test runner 測試用的instrumentation實例

        </li> </ul>

        例如:

        android {
            compileSdkVersion 19
            buildToolsVersion "19.0.0"

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

        }</pre>

        目錄配置

        默認情況下項目目錄是這樣的
        有兩個組件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
            }
        }
        

        }</pre>

        上面的配置文件配置兩個類型,一個時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 { ... }</pre>

        對于maven倉庫文件:

        repositories {
            mavenCentral()
        }

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

        android { ... }</pre>

        輸出不同配置的應用

        看代碼:

        android {
            ...

        defaultConfig {
            minSdkVersion 8
            versionCode 10
        }
        
        productFlavors {
            flavor1 {
                packageName "com.example.flavor1"
                versionCode 20
            }
        
            flavor2 {
                packageName "com.example.flavor2"
                minSdkVersion 14
            }
        }
        

        }</pre>

        通過以上設置,我們可以輸出不同的保命不同的版本號,以及最小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.processResources.manifestFile = file("${buildDir}/manifests/${variant.dirName}/AndroidManifest.xml")
        }
        

        }</pre>

        以上的功能就是替換我的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

        原文地址:http://blog.isming.me/blog/2014/05/20/android4gradle/

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!