build.gradle代碼


本篇文章已授權微信公眾號 dasu_Android(大蘇)獨家發布

Android Studio 這么強大的工具,就算我們不懂 gradle, groovy, 也照樣能借助AS對 Android 項目進行編譯、調試、運行、打包等操作。build.gradle 這個文件接觸這么久了,基本的項目配置也基本很熟悉了,畢竟每次自動創建的 build.gradle 里的代碼就那么幾項配置,看一下那些英文單詞也基本猜到是什么配置。

但是,不知道你們會不會跟我一樣,在 github 上 clone 大神的項目后,總會發現他們的 build.gradle 里多了很多平常沒看見過的代碼,而且還看不懂代碼要做什么;

或者是比如當需要進行簽名時,網上資料會讓你在 Android 標簽內加個 signingConfigs, 然后在它里面進行各種配置,比如 storeFile, keyAlias 等等之類的。還有其他類似這種情況,比如當需要打包時,在哪個地方加個什么標簽再對它進行各種配置之類的。不知道你們會不會也跟我一樣會有這樣的疑問,這個標簽名怎么來的,為什么要放在這個位置,它里面有哪些屬性可以進行配置?

疑惑久了,總想去了解下這是為什么,所以花了一段時間來學習 gradle 的相關知識,這次在這里記錄也分享一下,如果有錯的地方,還望指點一下。

本次計划是寫個 gradle 系列博客,大概會有3-4篇,第一篇只是簡單的針對某個具體的 build.gradle 文件代碼進行注釋解釋以及拋出一些疑問,當然這個 build.gradle 不會是AS自動創建的那么簡單的代碼。然后再寫1-2篇介紹 gradle, groovy, 相關的資料網上很多,所以不會寫得很基礎,大概是挑選一些我認為比較重要的知識點進行介紹。最后在前面的基礎上,對 build.gradle 里面的代碼進行分析講解,比如介紹說都有哪些標簽,哪里去找這些標簽等等。

好了,廢話就嘮叨到這,下面就開始正文。


系列索引

build.gradle系列一:看不懂的build.gradle代碼
build.gradle系列二:學點Groovy來理解build.gradle代碼
build.gradle系列三:如何用Adnroid Studio查看build.gradle源碼
...


build.Gradle

這個 build.Gradle 文件來自 drakeet 大神的 Meizi 項目
我直接在代碼上加注釋,參照着注釋看代碼就行,是不是發現有很多代碼平時都沒看見過。

//Model都有各自的build.gradle,這里聲明該Model作為主項目,常見的還有另一個取值:
//apply plugin: 'com.android.library' 聲明該Model作為庫使用,當然還有其他取值,后面博客會介紹
apply plugin: 'com.android.application'

//這里是在as里引入一個retrolambda插件,具體我也不大懂,可以看看這篇博客: 
//http://blog.csdn.net/zhupumao/article/details/51934317?locationNum=12
apply plugin: 'me.tatarka.retrolambda'

//這里是groovy的代碼了,定義了一個獲取時間的方法,groovy是兼容java,它可以直接使用jdk里的方法
def releaseTime() {
    return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}

//file()是Project.java里的一個方法,這里定義一個File類型的對象,Project后面博客會介紹到
def keyStore = file('meizhi.keystore')

android {

    //這個大家應該很熟悉了,有疑問的應該是后面的代碼,這里表示獲取一些全局變量
    //這些變量的值在根目錄下的build.gradle中定義,具體可以看看這篇博客:
    //http://blog.csdn.net/fwt336/article/details/54613419
    compileSdkVersion rootProject.ext.android.compileSdkVersion
    buildToolsVersion rootProject.ext.android.buildToolsVersion

    //同理,這里都是通過獲取全局設置的變量值來進行相關配置,這樣做的好處在於當
    //你的項目里有多個model時,可以方便修改這些公共的配置,只需要修改一個地方就可以同步了
    defaultConfig {
        applicationId rootProject.ext.android.applicationId
        minSdkVersion rootProject.ext.android.minSdkVersion
        targetSdkVersion rootProject.ext.android.targetSdkVersion
        versionCode rootProject.ext.android.versionCode
        versionName rootProject.ext.android.versionName
    }

    //這里應該是設置打包后的apk里的META-INF移除指定的文件吧
    packagingOptions {
        exclude 'META-INF/DEPENDENCIES.txt'
        //省略部分exclude 代碼...
    }

    //關閉指定的lint檢查
    lintOptions {
        disable 'MissingTranslation', 'ExtraTranslation'
    }

    //lint檢查到錯誤時不中斷編譯,好像是說lint檢查是為優化代碼,發現的錯誤其實並不會導致程序異常
    //所以有的時候及時發現Lint檢查錯誤還是可以直接運行查看效果
    lintOptions {
        abortOnError false
    }

    //簽名的相關配置
    signingConfigs {
        //這個標簽名可以隨意命名,這里的作用大概類似於定義一個對象,該對象里設置好了簽名需要的各種配置
        //可以定義不止一種配置的簽名對象,例如常見的還有 debug{...}, release{...},然后在buildTypes{}里
        //通過 signingConfigs.app1 進行調用
        app1 {
            //簽名的相關配置,網上資料很多,STOREPASS, KEYALIAS, KEYPASS 這些常量是定義在
            //gradle.properties 文件里,如果沒有該文件手動創建即可,這樣可以保證安全
            //只有定義在 gradle.properties 里的常量才可以直接通過常量名引用
            storeFile file('meizhi.keystore')
            storePassword project.hasProperty('STOREPASS') ? STOREPASS : ''
            keyAlias project.hasProperty('KEYALIAS') ? KEYALIAS : ''
            keyPassword project.hasProperty('KEYPASS') ? KEYPASS : ''
        }
    }

    //編譯,打包的項目配置
    buildTypes {

        debug {
            //在 BuildConfig 里自定義一個 boolean 類型的常量
            //更多資料可以查看:http://stormzhang.com/android/2015/01/25/gradle-build-field/ 
            buildConfigField "boolean", "LOG_DEBUG", "true"
            
            debuggable true
            applicationIdSuffix ".debug"
        }

        release {
            buildConfigField "boolean", "LOG_DEBUG", "false"

            debuggable false
            
            //開啟混淆
            minifyEnabled true
            //刪除無用的資源
            shrinkResources true
            //混淆文件
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            if (keyStore.exists()) {
                println "Meizhi: using drakeet's key"
                //根據在signingConfigs.app1里的簽名配置進行簽名
                signingConfig signingConfigs.app1
            } else {
                println "Meizhi: using default key"
            }

            //這段代碼應該會在大神的項目里挺常見的,我在很多項目里都看見過了
            //這也是groovy的代碼,這里的代碼作用是重命名最后打包出來的apk
            //根據 def fileName 設置的格式來命名,${}表示的是某個變量的引用
            //例如根據設置的格式最后apk命名可能是: Meizhi_v1.0.0_2017-03-28_fir.apk
            //至於 applicationVariants 這些變量含義后面博客會介紹
            applicationVariants.all { variant ->
                variant.outputs.each { output ->
                    def outputFile = output.outputFile
                    if (outputFile != null && outputFile.name.endsWith('.apk')) {
                        def fileName = "Meizhi_v${defaultConfig.versionName}_${releaseTime()}_${variant.productFlavors[0].name}.apk"
                        output.outputFile = new File(outputFile.parent, fileName)
                    }
                }
            }
        }

        //這里的作用跟 singingConfigs 差不多,只是為不同的 flavor 設置一些屬性
        //常見的設置比如設置不同的渠道編號,設置不同的 api 服務器等等
        productFlavors {
            fir {
                //這個的作用是將 AndroidManifest.xml 里的占位符 ¥{UMENG_CHANNEL_VALUE} 的值替換成fir
                manifestPlaceholders = [UMENG_CHANNEL_VALUE: "fir"]
            }
            GooglePlay {
                manifestPlaceholders = [UMENG_CHANNEL_VALUE: "GooglePlay"]
            }
            Umeng {
                manifestPlaceholders = [UMENG_CHANNEL_VALUE: "Umeng"]
            }
        }
    }

    //設置JDK的版本通過compileOptions
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    //lint的相關配置吧
    lintOptions {
        disable "InvalidPackage"
        lintConfig file("lint.xml")
    }
}

//這里就不用說了
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile project(":libraries:headsupcompat")
    compile project(":libraries:smooth-app-bar-layout")
    //as默認會去下載傳遞依賴,下面是指定不需要去下載傳遞依賴
    compile ('com.squareup.retrofit2:retrofit:2.1.0') {
        exclude module: 'okhttp'
    }
    retrolambdaConfig 'net.orfjackal.retrolambda:retrolambda:2.3.0'
    //省略部分compile代碼...
}



疑問

1.apply plugin: 'com.android.application' 聽說這是調用一個方法?

2.rootProject.ext.android.compileSdkVersion, 不用 ext 來設置全局變量是否可以?

3.defaultConfig{}, packagingOptions{}, signingConfigs{}, buildTypes{} 等等這些,我怎么知道 Android{} 里都有哪些可以使用?

...

參考資料

·徐宜生寫的《Android群英傳:神兵利器》第4章:與Gradle的愛恨情仇
·retrolambda使用教程
·Gradle配置全局變量
·GRADLE自定義你的BUILDCONFIG


QQ圖片20180316094923.jpg
最近剛開通了公眾號,想激勵自己堅持寫作下去,初期主要分享原創的Android或Android-Tv方面的小知識,感興趣的可以點一波關注,謝謝支持~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM