[Android] 配置build.gradle 動態傳參


(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部分。


免責聲明!

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



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