1. 程式人生 > >Android-Gradle閱讀筆記

Android-Gradle閱讀筆記

Gradle(2012) 是什麼?

類似Ant(2000)和Maven(2004)概念的專案自動化建構工具。

Ant

Apache Ant是一個java庫,主要用來構建Java程式。(C、C++、Java專案、Android專案)
主要功能:描述互相依賴, 提供了一個內建的編譯,安裝,測試和執行任務(target相當於gradle的task)。

Java專案的編譯規則:
這裡寫圖片描述

ADT
這裡寫圖片描述
\ADT\adt-bundle-windows-x86_64-20140702\sdk\tools\ant
這裡寫圖片描述
Build.xml
這裡寫圖片描述

Maven

第一:ant指令碼是可以直接執行在maven中的。maven和ant最大的差別就是在於maven的編譯以及所有的指令碼都有一個基礎,就是POM(project object model)。這個模型定義了專案的方方面面,然後各式各樣的指令碼在這個模型上工作,而ant完全是自己定義,顯然maven更勝一籌。
第二:Maven對所依賴的包有明確的定義,如使用哪個包,版本是多少,一目瞭然。而ant則通常是簡單的inclde 所有的jar。導致的最終結果就是,你根本無法確定JBoss中的lib下的common-logging 是哪個版本的,唯一的方法就是開啟 META-INF 目錄下MANIFEST.MF。估計JBoss遲早會轉向Maven的。
第三:Maven是基於中央倉庫的編譯,即把編譯所需要的資源放在一箇中央倉庫裡,如jar,tld,pom,等。當編譯的時候,maven會自動在倉庫中找到相應的包,如果本地倉庫沒有,則從設定好的遠端倉庫中下載到本地。這一切都是自動的,而ant需要自己定義了。這個好處導致的結果就是,用maven編譯的專案在釋出的時候只需要釋出原始碼,小得很,而反之,ant的釋出則要把所有的包一起釋出,顯然maven又勝了一籌。
第四:maven有大量的重用指令碼可以利用,如生成網站,生成javadoc,sourcecode reference,等。而ant都需要自己去寫。試試 maven site 的效果。
第五:maven目前不足的地方就是沒有象ant那樣成熟的GUI介面,不過mavengui正在努力中。目前使用maven最好的方法還是命令列,又快又方便。

Gradle

Gradle結合了前兩者的優點,在此基礎之上做了很多改進。
Gradle不用XML,它使用基於Groovy的專門的DSL, Gradle構建指令碼變得比用Ant和Maven寫的要簡潔清晰,功能更強大,可以直接呼叫javase程式碼。

ANT、Gradle都可以單獨安裝,ANT通過命令列+build.xml執行,Gradle通過命令列+build.gradle執行

Gradle Wrapper

Wrapper,是Gradle的下載器,便於在團隊開發過程中統一Gradle構建的版本,這樣大家都可以使用統一的Gradle版本進行構建,避免因為版本不同帶來不必要的問題。
這裡寫圖片描述

Gradle日誌

日誌級別

級別 用於
ERROR 錯誤訊息
QUIET 重要訊息
WARNING 警告訊息
LIFECYCLE 進度訊息
INFO 資訊訊息
DEBUG 除錯資訊

Gradle命令列

操作 命令
幫助 gradle –? 或者 gradle –h
檢視所有可執行的Tasks gradle tasks
檢視每個Task描述資訊 gradle help –task : xxmodule:xxxxtask
強制重新整理依賴(版本庫的version與snapshot版本變動後需要手動重新整理) gradle –refresh-dependencies assemble

補充:SNAPSHOT
Maven中的SNAPSHOT版本(快照版本)
快照版本和正式版本的主要區別在於,本地獲取這些依賴的機制有所不同。依賴正式版本,構建的會先在本次倉庫中查詢是否已經有了這個依賴庫,如果沒有的話才會去遠端倉庫中去拉取,不會拉取修改過已存在的同版本庫。
.
開發的時候,需要SNAPSHOT版本(快照版本),在構建時去檢視是否有同版本修改過的最新包,有則下載。在配置Maven的Repository可以配置查詢的頻率,頻率共有四種,分別是always、daily、interval、never。
在Gradle,可以設定本地快取的更新策略。
// check for updates every build
resolutionStrategy.cacheChangingModulesFor 0,’seconds’

Task

Groovy閉包≈Action

Groovy是基於JVM虛擬機器的一種動態語言,語法與Java相似,完全相容Java,增加了動態型別和靈活特性(支援閉包、支援DSL)。

閉包、FP函數語言程式設計、lambda表示式

閉包是Groovy的一個非常重要的特性,可以說它是DSL的基礎。

閉包(Closure)

維基百科:
1)閉包是引用了自由變數的函式。
2)由函式與其相關的引用環境組合而成的實體。

「函式」和「函式內部能訪問到的變數」(也叫環境)的總和,就是一個閉包。
這裡寫圖片描述

在一些語言中,在函式中可以(巢狀)定義另一個函式時,如果內部的函式引用了外部的函式的變數,則可能產生閉包。執行時,一旦外部的 函式被執行,一個閉包就形成了,閉包中包含了內部函式的程式碼,以及所需外部函式中的變數的引用。其中所引用的變數稱作上值(upvalue)。

閉包的作用

閉包常常用來「間接訪問一個變數」。換句話說,「隱藏一個變數」。

Groovy中的閉包(Closures):

閉包在groovy中是一個處於程式碼上下文中的開放的,匿名程式碼塊。它可以訪問到其外部的變數或方法。
這裡寫圖片描述

閉包也是物件

閉包在groovy中是groovy.lang.Closure類的例項,這使得閉包可以賦值給變數或欄位。

Groovy中的委託策略(略)

lambda表示式

——java1.8支援了lambda表示式

lambda表示式與閉包的關係:
lambda表示式大量用到了閉包和函式回撥
lambda表示式說到底只是一個函式表示式的表現形式而已
準確的說lambda表示式與閉包沒有直接的聯絡
如果支援函式表示式而不支援閉包,相當於買櫝還珠

函式程式設計

函式風格的程式設計特點:
1.第一等公民是函式
2.帶有閉包的Lambdas/Anonymous函式
3.不變性,大部分無態處理,沒有狀態和變數
4.高併發
5.無副作用的呼叫
6.通過tail call實現遞迴的效能優化。
7.模式匹配(Haskell, Erlang)
8.懶賦值(Miranda, Haskell)
9.Homoiconicity(類似LISP)

SQL是非常類似FP,它能滲透到業務中,它使用一致的資料結構(資料表結構Schema),一些基本函式能組合成很多查詢語句,它是declarative宣告式的, 也就是說,寫出的SQL是告訴資料庫我需要什麼,資料庫就為你返回,而不必指定資料庫如何具體去查詢。

Haskell 是純函數語言程式設計語言,研究函數語言程式設計必修之路

Gradle groovy解讀

Gradle Android 配置集錦

android {

//    SourceSet——原始碼集合——源集
    sourceSets{
        release{
            // java 指定程式碼檔案
            // res 指定資原始檔
//            java.srcDirs = xxxx
//            res.srcDirs = yyyy
        }
        debug{

        }
    }

    compileSdkVersion 23 // 配置SDK的API Level,對應的是Android 6.0 SDK
    buildToolsVersion '23.0.3' //Android構建工具的版本(是一個工具包,包括appt、dex等工具)
    // defaultConfig是預設配置,它是一個ProductFlavor。ProductFlavor允許我們根據不同的情況同時生成多個不同的APK包。
    defaultConfig{
//        applicationId "com.tongcheng.android"  包名
//        minSdkVersion rootProject.ext.minSdkVersion  App最低支援的Android作業系統版本
//        targetSdkVersion rootProject.ext.targetSdkVersion
//        versionCode Integer.valueOf(appVersionCode)  App內部版本號,用於版本的升級AA.BB.CC(BB為版本迭代,CC為bug修復版本)
//        versionName appVersionName  App版本名稱
//        multiDexEnabled true  配置BuildType是否啟用自動拆分多個Dex的功能。解決65535問題
        // 如果啟動期間需要的任何類未在主 DEX 檔案中提供,那麼您的應用將崩潰並出現錯誤 java.lang.NoClassDefFoundError。
        // 如果類在 multiDexKeepFile 或 multiDexKeepProguard 檔案中匹配,則該類會新增至主 DEX 檔案。
//        multiDexKeepProguard file("keep_in_main_dex.txt")
//        resConfigs "zh-rCN" 只有中文資源
//        ndk{
//            abiFilters "armeabi"
//        }
//        signingConfig  配置簽名信息,對生成的App簽名
//        proguardFile 配置App ProGuard混淆所使用的ProGuard配置檔案。

    }

    // buildTypes是一個NamedDomainObjectContainer型別,是一個域物件(與SourceSet一樣)。
    buildTypes{
        release{
            // 配置App ProGuard混淆所使用的ProGuard配置檔案。
//            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro', 'proguard-im.pro', 'rn-proguard-rules.pro'
//            proguardFiles:同事配置多個混淆檔案
//            debuggable false 是否生成一個可供除錯的apk
//            jniDebuggable false 類上
//            minifyEnabled true 是否啟用Proguard混淆
//            Android SDK提供了兩個Proguard配置檔案,proguard-android.txt和proguard-android-optimize.txt,一個是沒有優化的,另一個是優化的。

//            構建時,打包前,會檢測所有資源,如果沒有被引用,這些資源就不會被打包到apk包中,不管自己的還是第三方的都會被處理
//            shrinkResources true 是否自動清理未使用的資源,預設為false
//            zipAlignEnabled true  zipalign優化:是一個整理優化APK檔案的工具,客提高系統和應用的執行效率,更快地讀寫apk中的資源,降低記憶體的使用。

//            修改生成的apk檔名
//            applicationVariants.all { variant ->
//                variant.outputs.each { output ->
//                    def outputFile = output.outputFile
//                    if (outputFile != null && outputFile.name.endsWith('.apk')) {
//                        // 輸出apk名稱為AppName_v1.0_2015-01-15_wandoujia.apk
//                        def apkFile = "AppName_v${defaultConfig.versionName}_${buildTime()}" +
//                                "_${variant.productFlavors[0].name}.apk"
//                        output.outputFile = new File(outputFile.parent, apkFile)
//                    }
//                }
//            }
        }
        debug{
//            Debug模式的簽名使用的就是SDK自動生成的debug證書(.andriod/debug.keystore)

        }
    }

//    Android Gradle任務
//    assemble、check、build、connectedCheck、deviceCheck、lint、install、uninstall、gigningReport、androidDependencies等任

    signingConfigs {
        key_config {
//            keyAlias '17ukeystore'
//            keyPassword '17ukeystore'
//            storeFile file('/Users/android/share_root/etongAndroid.keystore')
//            storePassword '17ukeystore'
//            v2SigningEnabled false
        }
        debug {
            storeFile file('debug.keystore')
        }
    }

    flavorDimensions 'channel','pay'
    productFlavors{
        google{
//            動態配置AndroidManifest檔案
//            在構建過程中,動態修改AndroidManifest檔案中的內容(友盟統計等)
//            可以使用manifestPlaceholder、Manifest佔位符
            manifestPlaceholders.put("UMENG_CHANNEL","google")
//            buildConfigField 'String','WEB_URL','"http://www.google.com"'// 自定義BuildConfig屬性
//            resValue 'string','channel_tips','google渠道歡迎你' 動態新增自定義的資源

            dimension 'channel'

        }
        baidu{
            manifestPlaceholders.put("UMENG_CHANNEL","baidu")

            dimension 'channel'
        }

        free{
            dimension 'pay'
        }

        paid{
            dimension 'pay'
        }
        // 構建產物variant = ProductFlavor x BuildType
        // ProductFlavor = 以dimension為分組的乘積
        // variant = {  FreeGoogleRelease FreeGoogleDebug FreeBaiduRelease FreeBaiduDebug PaidGoogleRlease PaidGoogleDebug PaidBaiduRlease PaidBaiduDebug }
    }

    dexOptions {
//        jumboMode true 解決65535問題
//        javaMaxHeapSize "3072M" 配置最大堆記憶體
//        preDexLibraries屬性,是否預執行dex Libraries庫工程,開啟後會大大提高增量構建的速度,不過可能會影響clean構建的速度,預設為true,如需要使用dx的—multi-dex選項生成多個dex,導致和庫工程有衝突的時候,需要將該選項設定為false
//        threadCount 2  用來配置Gradle執行dx命令時使用的執行緒數量,適當的執行緒數量可以提高dx效率
//        incremental 配置是否啟用dx的增量模式(或許有時候不工作)

    }

}


def buildTime() {
    def date = new Date()
    def formattedDate = date.format('yyyy-MM-dd', TimeZone.getTimeZone("UTC"))
    return formattedDate
}

使用Gradle配置進行模組化開發

以下所有內容為筆記——均可忽略

Gradle基礎:

xxx 作用
Settings檔案 主要是為了配置子工程。
Build檔案(每個Project都會有一個Build檔案) 配置版本,接入外掛,依賴庫,依賴的Maven中心庫
Task 是一個操作,一個原子性的操作,比如打個jar包,複製一份檔案,編譯一次Java程式碼,上傳一個jar到Maven中心庫等,和Ant裡的Target,Maven中的goal是一樣的。(所謂task其實是project一個屬性Project.hasProperty(‘xxxTask’) 為 true)
任務依賴 dependsOn: xxxxTask

自定義屬性
Project和Task以及SourceSet都可以新增額外的自定義屬性,通過應用所屬對應的ext屬性即可實現。
新增之後可以通過ext屬性對自定義屬性讀取和設定。

ext.age = 19
ext{
    phone = 123423
    address = ‘xxx’
}

自定義屬性作用域廣,可以跨Project,跨Task訪問這些自定義屬性。

指令碼即程式碼,程式碼也是指令碼
Gradle檔案中寫指令碼,但是寫的都是程式碼,可以即刻使用Groovy、Java以及Gradle的任何語法和API。可以定義Class、內部類、導包、定義方法、常量、介面、列舉等。

Gradle任務

多種方法訪問任務
一:

task exTask1
exTask1.doLast{
    println ‘exTask1.doLast’
}

二:

task exTask2
tasks[‘exTask2’].doLast{
    println ‘exTask2.doLast’
}

tasks[‘exTask2’] 其實就是呼叫 tasks.getByName(‘exTask2’) 原始碼是呼叫 findByName(String name) 實現的
也可以通過路徑進行訪問:
findByPath(‘:example:exTask2’)
getByPath(‘:example:exTask2’)
get如果找不到會丟擲UnknownTaskException異常,而find在找不到該任務的時候會返回null

任務的分組和描述

在建立任務的時候,儘量進行分組和描述,便於對任務進行歸類整理,也便於閱讀:
def Task myTask = task exTask3
myTask.group = BasePlugin.BUILD_GROUP
myTask.description = ‘這是一個構建的引導任務’

可以通過gradle tasks檢視任務的分類描述

<<操作符
“<<” 操作符在Gradle的Task上是doLast方法的短標記形式,也就是說”<<”可以代替doLast

任務的執行分析
當我們執行Task的時候,其實就是執行其擁有的actions列表,這個列表儲存在Task物件實力中的actions成員變數中,其型別是一個List
doFirst其實是add在第一個位置,doLast新增在最後一個位置

任務順序
shouldRunAfter和mustRunAfter可以控制任務應該或者一定在某個任務之後執行。
例如:先執行單元測試,才能進行打包

任務的啟用和禁用
Task中有個enabled屬性,用於啟用和禁用任務,預設是true,表啟用;設定為false則禁止改任務執行,輸出會提示該任務被跳過。

任務的onlyif斷言
斷言就是一個條件表示式。Task有個onlyIf方法,接受閉包作為引數,如果返回true則該任務執行,否則跳過。
用途:比如控制哪些情況下打什麼包,什麼時候執行單元測試,什麼情況下執行單元測試的時候不執行網路測試等。
Example:
這裡寫圖片描述

任務規則

當執行、依賴一個不存在的任務時,Gradle會執行失敗。可以使用規則對其進行改進,當執行、依賴不存在的任務時,不會執行失敗,而是列印提示資訊,提示改任務不存在:
這裡寫圖片描述

Gradle外掛

Gradle本身提供了基本的概念和整體核心的框架,其他用於描述真實使用場景邏輯的都以外掛擴充套件的方式來實現,比如構建Java應用,就是通過Java外掛來實現的。

外掛的作用:個人理解就是編譯過程中,能用程式程式碼做的任何事情(程式碼生成、庫拉取、編譯修改、程式碼目錄指定、擴充套件屬性等等)

應用外掛

二進位制外掛:就是實現了org.gralde.api.Plugin介面的外掛
apply plugin:’java’
上面語句把Java外掛應用到我們的專案中了,其中’java’是Java外掛的plugin id,他是唯一的。

也可以:
apply plugin:org.gradle.api.plugins.JavaPlugin
也可以:
apply plugin:JavaPlugin
二進位制外掛一半都是被打爆在一個jar裡獨立釋出的。我們自定義的外掛,釋出的時候制定plugin id最好是一個全限定名稱,就像包名,避免重複。

指令碼外掛
build.gradle

apply from:’version.gradle’
其實就是把指令碼載入進來,和二進位制外掛不同的使用from關鍵字,後面緊跟一個指令碼檔案,可以是本地的,也可以是網路的,如果是網路上的話要使用HTTP UR。

應用第三方釋出的外掛
第三方釋出的jar的二進位制外掛,應用的時候,必須要現在buildscript{}裡面配置classpath才能使用。
比如Andriod Gradle外掛,就屬於Andrid釋出的第三方外掛,如果要使用就要進行配置:
這裡寫圖片描述

buildScript{}塊是一個在構建專案前,為專案進行前期準備和初始化相關配置以來的地方,配置好所需的以來,就可以應用外掛了:
apply plugin:’com.android.application’

使用plugins DSL應用外掛
Gradle2.1以上版本才可以用,如果該外掛已經被託管在https://plugins.gradle.org/網站上,我們就不用在buidscript裡配置classpath以來了,直接使用plugins就可以應用外掛:
這裡寫圖片描述

更多好用的外掛:

自定義外掛

指令碼外掛

這裡寫圖片描述

Groovy工程外掛(二進位制外掛)

這裡寫圖片描述

Gradle外掛基礎

sourceSets原始碼目錄

第三方依賴:
倉庫配置:
Repositories{
mavenCentral()
}
庫依賴
專案依賴
Jar依賴

如何構建Java專案

build任務:編譯原始碼,處理資原始檔等等
clean任務:刪除build目錄以及其他構建生成的檔案。
assemble任務:不會執行單元測試,只會編譯和打包
check任務:只會執行單元測試,有時候還會做一些質量檢查

原始碼集合SourceSet概念
SourceSet——原始碼集合——源集
有了源集,我們能針對不同的業務和應用進行原始碼分組

釋出構建
將程式碼釋出到庫中
這裡寫圖片描述

Andriod Gradle外掛

Android其實就是Gradle的一個第三方外掛,由Google的Android團隊開發的。

Andriod Gradle外掛分類
App外掛id:com.android.applicaton
Library外掛id:com.android.library
Test外掛id: com.android.test

Android Gradle外掛
Android Gradle外掛是第三方外掛,託管在Jcenter上,應用之前,需要先配置classpath
這裡寫圖片描述

compileSdkVersion

compileSdkVersion 23 配置SDK的API Level,對應的是Android 6.0 SDK
這裡寫圖片描述
方法的括號可以省略,分號可以省略,所以就是上面的寫法。

buildToolsVersion
buildToolsVersion ’23.0.1’:Android構建工具的版本(是一個工具包,包括appt、dex等工具)

defaultConfig
defaultConfig是預設配置,它是一個ProductFlavor。ProductFlavor允許我們根據不同的情況同時生成多個不同的APK包。

buildTypes
buildTypes是一個NamedDomainObjectContainer型別,是一個域物件(與SourceSet一樣)。
buildTypes裡面有release、debug等,也可以新增N多自定義型別。

Android Gradle任務
assemble、check、build、connectedCheck、deviceCheck、lint、install、uninstall、gigningReport、androidDependencies等任務
這裡寫圖片描述

從Eclipse遷移到Android Gradle工程
1. 直接使用Android Studio匯入
2. Eclipse>Export>Generate Gradle Build Files(生成Setting和build指令碼)>Android Studio>Import Project (這種方式保持了Eclipse原本的專案格式,只是重寫了SourceSet)

自定義Android Gradle工程

defaultConfig 是一個ProductFlavor,如果ProductFlavor沒有被特殊定的話,預設會使用defaultConfig{}塊值指定的配置(包名、版本號、版本名稱等)

applicationId:包名

minSdkVersion:App最低支援的Android作業系統版本

versionCode:App內部版本號,用於版本的升級AA.BB.CC(BB為版本迭代,CC為bug修復版本)

versionName:App版本名稱

testApplicationId:用於配置測試App的包名,預設情況下是applicationId + “.test”,預設即可

testInstrumentationRunner:配置單元測試時使用的Runner,預設是android.testInstrumenttationTestRunner,如果要自定義Runner,修改即可。

signingConfig:配置簽名信息,對生成的App簽名

proguardFile:配置App ProGuard混淆所使用的ProGuard配置檔案。

proguardFiles:同事配置多個混淆檔案

配置簽名信息
這裡寫圖片描述

Debug模式的簽名使用的就是SDK自動生成的debug證書(.andriod/debug.keystore)

構建的應用型別
這裡寫圖片描述

applicationIdSuffix:用於配置基於預設applicationId的字尾

debuggable:是否生成一個可供除錯的apk

jniDebuggable:類上

minifyEnable:是否啟用Proguard混淆

multiDexEnabled:配置BuildType是否啟用自動拆分多個Dex的功能。解決65535問題

shrinkResources:是否自動清理未使用的資源,預設為false

混淆:
Android SDK提供了兩個Proguard配置檔案,proguard-android.txt和proguard-android-optimize.txt,一個是沒有優化的,另一個是優化的。

zipalign優化:是一個整理優化APK檔案的工具,客提高系統和應用的執行效率,更快地讀寫apk中的資源,降低記憶體的使用。
zipAlignEnabled true 即可

Gradle高階定義
使用共享庫:com.google.android.maps、android.test.runner等,是獨立庫,並不會被系統自動連線,需要獨立進行生成使用。
這裡寫圖片描述

如果手機系統沒有需要的共享庫,將不能安裝該應用。

Android中,除了標準的SDK,還存在兩種庫:一種是add-ons庫,位於add-ons目錄下,大部分是第三方廠家或者公司開發的,為了讓開發者使用,但是又不想暴露具體標準實現;第二類是optional可選庫,位於platforms/android-xx/optional目錄下,一般是為了相容舊版本的API(org.apache.http.legacy 相容 HttpClient)

add-ons附件庫,Andriod Gradle會自動解析,自動新增到classpath裡。
Optional可選庫就不會了,使用需要:
這裡寫圖片描述

批量修改生成的apk檔名

applicationVariants(僅僅適用於Android應用Gradle外掛)、libraryVariants(僅適用於Andriod庫Gradle外掛)、testVariants(以上兩種Gradle外掛都使用)
這三個元素直譯過來意思是變體,通俗地講他們就是Android構建的產物。

觸發這3種集合都會觸發建立所有任務。
這裡寫圖片描述

動態生成版本資訊

版本:major.minor.path,第一個是主版本號,第二個是副版本號,第三個是補丁號

分模組:
這裡寫圖片描述
這裡寫圖片描述

從git的tag中獲取
tag的名字一般就是版本名稱,可以動態獲取tag名稱作為應用的名稱。
Git命令: git describe –abbrev=0 –tags
使用Gradle的exec,Project物件裡的exec方法
這裡寫圖片描述

git tag動態獲取版本名稱
這裡寫圖片描述
這裡寫圖片描述

從屬性檔案中動態獲取和遞增
使用Properties屬性,gradle進行讀寫。

隱藏簽名檔案資訊
簽名信息存放到伺服器。

自動打包伺服器程式碼:
這裡寫圖片描述
如果是Jenkins,只需要在Jenkins裡配置即可。
開發者直接使用debug簽名即可
這裡寫圖片描述

如果有時候需要使用正式釋出的簽名打正式包,比如Jenkins,給每個開發者開放一個賬號,他們自己新建個Job就可以打正式的包了,打包之後可以在生成的構建裡下載。

動態配置AndroidManifest檔案
在構建過程中,動態修改AndroidManifest檔案中的內容(友盟統計等)
可以使用manifestPlaceholder、Manifest佔位符
ManifestPlaceholders是ProductFlavor的一個屬性
這裡寫圖片描述
這裡寫圖片描述

還可以直接:
這裡寫圖片描述
這裡寫圖片描述

還可以使用佔位符動態修改動態配置meta資訊,比如ContentProvider的auth授權。

自定義BuildConfig
這裡寫圖片描述

注意:值是用單引號括起來的,value的值是什麼就寫什麼,要原封不動的放在單引號裡。

動態新增自定義的資源
資源還可以在Gradle中定義:
實現這一功能的是resValue方法,他在BuildType和ProductFlavor這兩個物件中都存在,也就是說我們可以分別針對不同渠道,或者不同的構建型別來自定義其特有的資源。
這裡寫圖片描述

生成的資源位置,以Baidu為例,debug模式下,在build/generated/res/resValues/baidu/debug/values/generated.xml這個檔案中。
這裡寫圖片描述

個人總結:包括圖片一樣可以做,自定義圖片名稱即可,可以通過名稱找圖片。

Java編譯選項
可以對Java原始檔的編碼、原始檔使用的JDK版本進行調優修改。(比如編碼UTF-8,配置Java原始碼的級別為1.6),Gradle提供了便捷入口:
這裡寫圖片描述
這裡寫圖片描述

Adb操作選項配置
這裡寫圖片描述
這裡寫圖片描述

這裡寫圖片描述

DEX選項配置
對於生成DEX檔案的過程和處理,Android Gradle外掛會呼叫SDk中的dx命令進行處理。
有時會遇到記憶體不足的情況:java.lang.OutOfMemoryError:GC overhead limit exceeded
預設情況給dx分配的記憶體是一個G,1024MB
這裡寫圖片描述

javaMaxHeapSize 配置最大堆記憶體
jumboMode屬性,解決65535問題
preDexLibraries屬性,是否預執行dex Libraries庫工程,開啟後會大大提高增量構建的速度,不過可能會影響clean構建的速度,預設為true,如需要使用dx的—multi-dex選項生成多個dex,導致和庫工程有衝突的時候,需要將該選項設定為false
threadCount屬性,用來配置Gradle執行dx命令時使用的執行緒數量,適當的執行緒數量可以提高dx效率
incremental 配置是否啟用dx的增量模式(或許有時候不工作)
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

突破65535方法限制

Facebook給的第一個方案是:打補丁
後來官方給的方案是Multidex,Android 5.0之後的ART執行方式,天然支援App有多個DEX檔案。ART在安裝App的時候執行預編譯,把多個DEX檔案合併成一個oat檔案執行。對於5.0之前的版本,虛擬機器限制沒個App只能有一個class.dex,要使用他們,需要使用Andriod提供的Multidex庫:
Andriod Build Tools 和 Android Support Repository 到21.1,這是支援Multidex功能的最低支援版本。
要在我們的專案中使用Multidex,首先要修改Gradle build配置檔案,啟用Multidex,並同時配置Multidex需要的jar依賴:
這裡寫圖片描述

開啟了Multidex,會讓我們的方法多於65535個的時候生成多個DEX檔案,其名字為classes.dex,classes(…n).dex這樣的格式。要想可執行,虛擬機器需要把其他幾個生成的classed記載進來,必須在App啟程啟動的入口控制,就是Application。直接使用MultiDexApplication或者繼承它,或者重寫attachBaseContext方法實現:
這裡寫圖片描述

思考:
這裡寫圖片描述
自動清理未使用的資源
Android Lint、Recource Shrinking(構建時,打包前,會檢測所有資源,如果沒有被引用,這些資源就不會被打包到apk包中,不管自己的還是第三方的都會被處理)

Resource Shrinking要集合Code Shrinking一起使用,就是ProGuard,也就是啟用minifyEnabled。
這裡寫圖片描述

自動清理未使用的資源可能會誤刪,因為我們再程式碼編寫的時候,可能會使用反射引用資原始檔,特別是第三方庫會這麼做,Gradle就區分不出來了,這種情況Gradle提供了keep方法來讓我們配置哪些資源不被清理:res/raw/keep.xml
這裡寫圖片描述

Keep.xml 有一個屬性是tools:shrinkMode,用於配置自動清理資源的模式,預設是safe,是安全的,可以識別如下引用:
這裡寫圖片描述
如果把清理模式改成strict就沒辦法識別了,這個資源會被認為沒有被引用,而被清除掉。
這裡寫圖片描述

resConfig使用非常廣泛,不止於上面描述的語言,還包括Api Level、解析度等。
上述姿勢在打包的時候,不打包到apk中,實際並沒有刪除工程中的資源。

Android Gradle多專案構建
settings.gradle配置檔案
這裡寫圖片描述
這裡寫圖片描述

庫專案引用和配置
這裡寫圖片描述

引用庫專案其實是庫專案釋出出來的aar包,預設情況下,Android庫專案發出來的包都是release版本的,當然可以通過配置來改變它,比如改成預設釋出的,下面是debug版本:
這裡寫圖片描述

還可以針對不同的flavor+buildtype配置:
這裡寫圖片描述

同時釋出多個版本的aar包以供不同專案引用:
這裡寫圖片描述
引用方法:
這裡寫圖片描述

庫專案單獨釋出

搭建自己的Maven私服,推薦使用Nexus Repository Manger,版本選擇2.x.x

釋出Mavne:
這裡寫圖片描述

快照版本SNAPSHOT:
比如配置成1.00-SNAPSHOT,這時候會發布到snapshot中心庫,每次釋出版本號不會變化,只會在版本號後按順序號+1,如1.0.0-1、1.0.0-2、1.0.0-3等。這樣的版本號,引用的時候版本號寫成1.0.0-SNAPSHOT即可,Maven會幫我們下載最新(序列最大)的快照版本。這種方式適用於聯調測試的時候,每次修復好測試的問題就釋出一個快照版本,知道沒有問題為止,然後再放出release版本,正式釋出。

釋出配置:
這裡寫圖片描述

使用自己Maven伺服器候中的庫:
這裡寫圖片描述
這裡寫圖片描述

可以使用一個Maven庫代替:Nexus Maven提供了一種group型別的repository,這種型別的repository可以同時整合好幾個repository,把他們同意當成一個group來對外發布,比如Nexus內建的public group,就包含了release和snapshot,就可以改成:
這裡寫圖片描述

Android Gradle多渠道構建

Android Gradle的Flavor完美解決多渠道問題。

Android Gradle中,定義了個Build Variant的概念,直譯是構建變體,可以理解為構建的產物。一個Build Variant=Build Type + Product Flavor,Build Type就是我們構建的型別,比如Baidu、Google等,它們加起來就是baiduRelease、baiduDebug、googleRelease、googleDebug這幾種組合的構建產出. Product Flavor是多渠道構建的基礎.

Flurry多渠道和友盟多渠道構建
Flurry只需要配置不同的Flurry Key即可,可以自定義BildConfig:
這裡寫圖片描述
使用: Flurry.init(this,FLURRY_KEY);

而友盟需要修改AndriodManifest.xml中的配置,通過配置meta-data標籤來設定:
這裡寫圖片描述
則我們可以使用manifestPlaceholders,來進行替換。

多渠道構建定製
Flavor:氣味、味道,就是我們點菜說的口味。

applicationId:是ProductFlavor的屬性,用於設定改渠道的包名

consumerProguardFiles:混淆檔案配置
這裡寫圖片描述
當釋出庫專案生成一個aar包的時候,使用consumerProguardFiles配置的混淆檔案列表也會被打包到aar裡一起釋出,當應用專案引用這個aar包,並且啟用混淆的時候,會自動使用aar包裡的混淆檔案對aar包程式碼進行混淆,這樣就不用對該aar包進行混淆配置了。

ConsumerPoguardFiles方法是一直新增的,不會清空以前的混淆檔案,而consumerProguardFiles屬性配置的方式是每次都是新的混淆檔案列表,以前配置的會先被清空。

proguardFiles:混淆使用的檔案配置
signingConfig:簽名配置

testApplicationId:單元測試有自己的專門apk測試包,testApplicationId是用來適配測試包的包名,使用方法與applicationId一樣。
一般的testApplicatonId的值為App的包名+.test

testFunctionalTest和testHandleProfiling
testFunctionalTest表示是否為功能測試,testHandleProfiling表示是否啟用分析功能。
他們主要用來控制測試包生成的AndroidManifest.xml,最終配置還要體現在AndroidManifest.xml檔案中的instrumentation標籤的配置上。

TestInstrumentationRunner、testInstrumentationRunnerArguments:測試相關(最終使用的都是adb shell am instrument這個命令),略

versionCode和versionName
渠道的版本號 和 版本名稱

useJack
用於標記是否啟用Jack和Jill這個全新的、高效能的編譯器。
書上說目前還處於實驗階段,有些特性還不支援,比如註解、JDK8的特性等。
正式產品中還是不要使用。
這裡寫圖片描述

dimension
針對不同渠道需要再細分給出的解決方案。
Dimension是productFlavor的一個屬性,接受一個字串,作為該productFlavor的維度。
需要現在flavorDimesions裡面宣告維度,才能在ProductFlavor中使用:
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

提高多渠道構建的效率
美團研究出了一個辦法,利用了在apk的META-INF目錄下新增檔案不用重新簽名的原理:
1. 利用Android Gradle打一個基本包(母包)
2. 然後基於該包複製一個,檔名要能區分出產品、打包時間、版本、渠道等
3. 然後對複製出來的apk檔案進行修改,在其META-INF目錄下新增空檔案,但是空檔案的檔名要有意義,必須包含能區分渠道的名字,如mtchannel_google
4. 重複步驟2、3生成我們所需的所有渠道包apk,可以使用Python指令碼來做。

使用:在apk啟動的時候,讀取apk中的META-INF目錄下的字首為matchannel_檔案,如果找到的話,把檔名取出來,然後就可以得到渠道標識了:
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

持續整合:
Jenkins
這裡寫圖片描述
這裡寫圖片描述

怎樣更好地做持續整合
1. 需要一個統一的程式碼版本控制管理庫(可以使用Git進行管理,企業內部,可以使用Gitlab來搭建Git程式碼管理平臺,和Github是非常相似的)
2. 搭建類似於Jenkins的構建平臺,Jenkins是把所有構建流程串起來的一個工具。
3. 單元測試、程式碼覆蓋率,以及程式碼靜態檢查等平臺工具,Android裡我們可以使用jacoco作為程式碼覆蓋率工具,單元測試使用Andriod自帶的工具就可以,靜態程式碼檢查推薦Sonar(可以進行程式碼靜態分析,還可以呈現程式碼覆蓋率和單元測試報告)
4. 每天想程式碼庫的主幹提交程式碼,這樣我們的程式碼修改才可以每天彙集到一起,進行驗證。
5. 程式碼提交的時候,要出觸發一次自動構建,這樣才是持續的,才能早發現合併後的問題。
6. 發現問題要及時修改,每個參與的人都可以很快獲取最近的修改後的程式碼。要做到這些需要每個人都清楚整個程式碼庫的構建情況。
7. 每個開發者必須要自己現在本機測試後才能提交程式碼到主幹,不能不測試直接提交。
8. 開發者必須每天要提交自己的程式碼,更新最新程式碼,要經常和最新的程式碼保持一致,避免長時間沒有同步程式碼,造成不清楚其他開發者做了什麼, 也避免了衝突。
9. 要保證每次構建都要通過,是100%通過
10. 要保證每個人構建的目標都是可以釋出的產品,而不是一個測試版的甚至是半成品,這是我們構建的目標

相關推薦

Android-Gradle閱讀筆記

Gradle(2012) 是什麼? 類似Ant(2000)和Maven(2004)概念的專案自動化建構工具。 Ant Apache Ant是一個java庫,主要用來構建Java程式。(C、C++、Java專案、Android專案) 主要功能:描述互相

Gradle閱讀筆記-第二章groovy基礎

Groovy是基於JVM虛擬機器的一種動態語言,支援閉包,支援DSL 字串 在Groovy中,單引號和雙引號都可以定義一個字串常量,但是單引號不能對字串裡的表示式做運算,單引號沒有運算能力 集合 List定義及訪問: task pringList <<

讀書筆記--Android Gradle權威指南(上)

說了 聲明 通過命令 google robot 結構 信息 我只 cati 最近看了一本書《Android Gradle 權威指南》,對於 Gradle 理解又更深了,但不想過段時間就又忘光了,所以打算寫一篇讀書筆記,將書中一些我個人覺得蠻有用的點記錄、總結一下。 前言 首

《Self-Protection of Android Systems from Inter-component Communication Attacks》論文閱讀筆記

前言 本篇部落格是用來記錄自己在閱讀《Self-Protection of Android Systems from Inter-component Communication Attacks》這篇論文期間的閱讀筆記,方便自己日後翻閱檢視,如果對於這篇論文的閱讀有什麼不正確的地方,歡迎大家批評指

《System Service Call-oriented Symbolic Execution of Android Framework with Applications to...》論文閱讀筆記

System Service Call-oriented Symbolic Execution of Android Framework with Applications to Vulnerability Discovery and Exploit Generation 用於Andro

《AppIntent - Analyzing Sensitive Data Transmission in Android for Privacy Leakage Detection》論文閱讀筆記

AppIntent: Analyzing Sensitive Data Transmission in Android for Privacy Leakage Detection APPIntent:分析敏感資料傳播在Android裝置中隱私洩露的檢測 文獻引

android啟動的閱讀筆記

Android的啟動過程,分為 1、Bootloader引導 2、裝載與啟動Linux核心 3、啟動Android系統, 流程上 先是BOOT層bootloader啟動,初始化硬體,是硬體進入一個準備工作的狀態,(此時會有一個暫時的先調通串列埠的程序或者稱之為程式,為了輸出列印啟

《老羅的Android之旅》閱讀筆記——Activity啟動過程

ActivityManagerService啟動Activity的過程大致如下圖所示: 在這個圖中,ActivityManagerService和ActivityStack位於同一個程序中,而ApplicationThread和ActivityThread位於另一個程序

《老羅的Android之旅》閱讀筆記——IPC機制Binder

Android系統Binder機制中的四個元件Client、Server、Service Manager和Binder驅動程式的關係: Service Manager成為Binder守護程序的過程原始碼路徑:frameworks/base/cmds/servicema

《老羅的Android之旅》閱讀筆記——Launcher和Zygote的啟動過程

Launcher啟動過程            系統中的應用程式安裝好了以後, SystemServer元件接下來就通過ActivityManagerService來啟動Home應用程式Launcher了, Launcher在啟動的時候便會通過PackageManagerS

《老羅的Android之旅》閱讀筆記——廣播(Broadcast)機制

使用廣播的兩個步驟: 1. 廣播的接收者需要通過呼叫registerReceiver函式告訴系統,它對什麼樣的廣播有興趣,即指定IntentFilter,並且向系統註冊廣播接收器,即指定BroadcastReceiver  2. 廣播的傳送者通過呼叫sendBroadc

《老羅的Android之旅》閱讀筆記——SurfaceFlinger服務

Android應用程式請求SurfaceFlinger服務渲染自己的UI可以分為三步曲: 首先是建立一個到SurfaceFlinger服務的連線, 接著再通過這個連線來建立一個Surface, 最後請求SurfaceFlinger服務渲染該Surface。 根據Surfa

Android Studio Gradle使用筆記

[張武] Gradle是一個基於Apache Ant和Apache Maven概念的專案自動化建構工具。 —— 百度百科 Android Studio Gradle是android st

kindle閱讀筆記17年3月

好的 對齊 商都 自己 不為 添加 nbsp 國家 唐詩 資治通鑒(1) (司馬光) - 您在位置 #30-31的標註 | 添加於 2017年3月27日星期一 上午12:25:15 夫事未有不生於微而成於著,聖人之慮遠,故能謹其微而治之,眾人之識近,故必待其著而後救之;

jdk源碼閱讀筆記之java集合框架(四)(LinkedList)

ray private array public 源碼閱讀 jdk源碼閱讀 oid color 解釋 關於LinkedList的分析,會從且僅從其添加(add)方法入手。 因為上一篇已經分析過ArrayList,相似的地方就不再敘述,關註點在LinkedList的特點。 屬

vue中$watch源碼閱讀筆記

vue 告訴 應該 最好 notify type 十分 msg 建立 項目中使用了vue,一直在比較computed和$watch的使用場景,今天周末抽時間看了下vue中$watch的源碼部分,也查閱了一些別人的文章,暫時把自己的筆記記錄於此,供以後查閱: 實現一個簡單的

Android:日常學習筆記(7)———探究UI開發(1)

tac calling repl action its 內容 schema lesson try Android:日常學習筆記(7)———探究UI開發(1) 常用控件的使用方法 TextView 說明:TextView是安卓中最為簡單的一個控件,常用來在界面上顯示一段文本信

Android:日常學習筆記(7)———探究UI開發(4)

this 活動 eal enc panel .html http 中間 編寫 Android:日常學習筆記(7)———探究UI開發(4) UI概述 View 和 ViewGrou   Android 應用中的所有用戶界面元素都是使用 View 和 ViewGroup 對象

Android:日常學習筆記(9)———探究廣播機制

ora rri enabled cas 管理 encoding protect 其他 acc Android:日常學習筆記(9)———探究廣播機制 引入廣播機制 Andorid廣播機制   廣播是任何應用均可接收的消息。系統將針對系統事件(例如:系統啟動或設備開始充電時)傳

Android:日常學習筆記(10)———使用LitePal操作數據庫

分享 數據 turn find netstat price 彈出 category 模式 Android:日常學習筆記(10)———使用LitePal操作數據庫 引入LitePal 什麽是LitePal   LitePal是一款開源的Android數據庫框架,采用了對象關系