(1)一個Android工程中有一個build.gradle是負責Project范圍的,而Module中又有各自的build.gradle是專門負責模塊的。
(2)在Gradle中Task是一等公民,通過gradlew + task名 可以直接執行指定Task,例如下面的命令就是執行:task releaseAutoBLForAar
gradlew releaseAutoBLForAar
(3)在defaultConfig中可以自定義變量名,編譯時可以在Java代碼中引用到:
defaultConfig { applicationId "com.test" minSdkVersion 15 targetSdkVersion 23 versionCode 5 versionName 1.1.0 buildConfigField("String", "API_HOST", "${API_DEV_HOST}") }
這里面的API_HOST是String型的(第三個參數是表示傳值),可以看到Java代碼生成,這樣就能建立起代碼與配置之間的橋梁:
public final class BuildConfig { public static final boolean DEBUG = Boolean.parseBoolean("true"); public static final String APPLICATION_ID = "com.test"; public static final String BUILD_TYPE = "debug"; public static final int VERSION_CODE = 6; public static final String VERSION_NAME = "1.1.1"; // Fields from default config. public static final String API_HOST = "http://test.api.cn"; }
(4)通過 buildTypes 可以配置不同的任務參數
buildTypes { release { /* 線上環境 */ buildConfigField "boolean", "LOG_DEBUG", "false" // 不顯示Log buildConfigField "String", "API_HOST", "${API_RELEASE_HOST}" //API Host minifyEnabled true //是否混淆 zipAlignEnabled true //是否設置zip對齊優化 shrinkResources true // 移除無用的resource文件 signingConfig signingConfigs.release //簽名 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } preRelease { /* 預發環境 */ buildConfigField "boolean", "LOG_DEBUG", "false" // 不顯示Log // 。。。 } debug { /* 本地開發環境 */ minifyEnabled false } beta { /* 測試環境 */ buildConfigField "boolean", "LOG_DEBUG", "true" // 顯示Log // 。。。 } }
可以通過AndroidStudio的Gradle面板看到多個編譯任務,原來默認只有assembleDebug,現在就多了assembleBeta、assemblePreRelease、assembleRelease,雙擊即可執行。
(5)如何通過Gradle動態配置不同的AndroidManifest.xml 變量內容呢?通過自定義manifestPlaceholders 屬性值。
首先在AndroidManifest.xml 文件中指定要使用Gradle動態配置值${TALKING_DATA_APP_ID}:
<!--TalkingData 配置--> <meta-data android:name="TD_APP_ID" android:value="${TALKING_DATA_APP_ID}" />
可以在build.gradle中配置一個特別的變量屬性:
def TEST_TALKING_DATA_APP_ID = "6E5389EAD0C2C2CFB7B379701F6D2BA8" defaultConfig { applicationId "com.test" minSdkVersion 15 targetSdkVersion 23 versionCode 5 versionName 1.1.0 buildConfigField("String", "API_HOST", "${API_DEV_HOST}") manifestPlaceholders = [ /* talkingData 測試環境 */ TALKING_DATA_APP_ID: "${TEST_TALKING_DATA_APP_ID}" /* 可以新增多個鍵值對,表示變量與對應的值 */ ] }
同理,我們可以在buildTypes中分別指定release、debug等配置的manifestPlaceholders 來達到不同的配置效果。
(6)如何在build.gradle中動態獲取參數選項?通過 project.hasProperty('VERSION_CODE') 的形式來獲取動態傳參。
defaultConfig { applicationId "com.ixwork" minSdkVersion 15 targetSdkVersion 23 //關鍵看這兩行 versionCode project.hasProperty('VERSION_CODE') ? Integer.parseInt(VERSION_CODE) : DEF_VERSION_CODE versionName project.hasProperty('VERSION_NAME') ? VERSION_NAME : "${DEF_VERSION_NAME}" buildConfigField("String", "API_HOST", "${API_DEV_HOST}") }
(7)怎么傳參呢?通過-PVAR_NAME=VAR_VALUE 的形式,其中-P就是加參數,例如:
gradle clean assembleBeta -PVERSION_CODE=5 -PVERSION_NAME=1.1.1 -POUT_PUT_DIR=/home/user/Desktop -PFILE_NAME=test.apk
// 這里面一個小細節很重要,執行gradle任務時之前加一個clean清除一下結果,可以有效防止編譯過程中誤報錯誤。比如關閉了某個宏導致某些class文件不再被編譯,但是可能由於舊的信息殘留導致報錯提示找不到class
(8)怎么設置APP工程使用一個aar庫呢?兩步走:(1)設置本地倉庫地址;(2)設置依賴文件名稱和擴展名。
dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation 'com.android.support:appcompat-v7:26.1.0' implementation 'com.android.support.constraint:constraint-layout:1.0.2' // implementation project(':testjni') // 這一句是用來設置工程依賴的,如果設置了直接依賴那么就好比就是同一個工程內了,直接import類使用即可 compile (name:'testjni-debug', ext:'aar') // 這一句是用來設置工程依賴某個具體aar包的,name字段填寫包名,ext字段填寫擴展名 }
如果是初始工程這么設置一下的話,編譯會報錯說找不到這個testjni-debug.arr,原因是存放這個文件的“倉庫”路徑並沒有被加入到工程內,需要我們設置一下倉庫地址(假設存在aar文件的路徑是app/libs目錄):
allprojects { repositories { google() jcenter() flatDir {dirs '../app/libs'} // 在整個工程的build.gradle 中倉庫配置此字段 } }
(9)怎么理解一個task的內容?舉幾個很實用的小例子來看看:
task clearOutput(type:Delete){ // 刪除任務,內容就是刪除兩個目錄 delete 'build_output' delete '../app/libs' } task taskJar(type:Jar, dependsOn:"assembleRelease" ) { // 這個Jar包的任務依賴於assembleRelease(系統的Release配置任務)意思就是相當於執行這個任務了,並且還附加了下面的邏輯步驟 from 'build/intermediates/classes/release/' // 源路徑 destinationDir = file('build_output/libs') // 目標路徑 } task releaseOutput(type:Copy, dependsOn: [clearOutput, taskJar]) { // 依賴於兩個任務,相當於要依次執行完這兩個任務,之后再拷貝文件(文件列表如下描述) from('libs') { include '*.jar','armeabi-v7a/lib*.so' } into ('build_output/libs') } task releaseOutputAar(type:Copy, dependsOn:[clearOutput, "assembleRelease"]){ // 依賴於兩個任務,之后拷貝,拷貝的目標可以是多個,連續執行 from('build/outputs/aar') { include 'testjni-release.aar' } into ('build_output') into ('../app/libs') }
(10)【坑】有一點要理解深入點:一旦配置了externalNativeBuild,那么執行以及依賴assembRelease/Debug的任務可就都會編譯打包so了!不配置就只會編譯打包Java部分。
