Android Gradle全局配置

Gradle是一個優秀的構建系統和構建工具,它允許通過插件創建自定義的構建邏輯。 基於Gradle以下的一些特點而選擇了它:
1、採用了Domain Specific Language(DSL語言)來描述和控制構建邏輯。
2、構建文件基於Groovy,並且允許通過混合聲明DSL元素和使用代碼來控制DSL元素以控制自定義的構建邏輯。
3、支持Maven或者Ivy的依賴管理。
4、非常靈活。允許使用最好的實現,但是不會強制實現的方式。
5、插件可以提供自己的DSL和API以供構建文件使用。

6、良好的API工具供IDE集成。

  • Gradle全局配置:

一般我們各個module的build.gradle中都有這一段配置:


android {
    compileSdkVersion 25
    buildToolsVersion '25.0.0'
    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
    }
}
假如我們項目中有多個module,如果升級targetSdk、buildTool等,那麼每個module都需要改值,不僅麻煩,還有可能導致module之間的版本不統一而出現問題,解決方法是Gradle配置全局變量供各個module使用,在你的Project的根目錄下的build.gradle定義ext全局變量:

ext {
    compileSdkVersion = 25
    buildToolsVersion = '25.0.0'
    minSdkVersion = 15
    targetSdkVersion = 25
    versionCode = 1
    versionName = "1.0"
}
然後在各module中的build.gradle中引用如下:

android {
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion
    defaultConfig {
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode rootProject.ext.versionCode
        versionName rootProject.ext.versionName
    }
}

這樣每次修改Project的build.gradle配置就可以實現全局配置了。

  • 在release版本中關閉Log

我們在調試代碼的時候希望顯示Log日誌信息,但是當我們發佈到應用市場的時候我們又不希望我們的應用顯示Log信息,因爲這樣會拖慢應用的運行速度甚至是暴露關鍵信息,那麼該怎麼辦呢?可以通過配置buildTypes來達到在release版本中自動關閉Log的效果:

buildTypes {
        release {
            minifyEnabled false
            buildConfigField "boolean", "IS_SHOW_LOG", NOT_SHOW_LOG
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
            minifyEnabled false
            buildConfigField "boolean", "IS_SHOW_LOG", SHOW_LOG
        }
    }
配置的buildConfigField參數,編譯後會在..\app\build\generated\source\buildConfig文件夾下會自動生成對應版本對應module的BuildConfig.java文件,該文件可以在代碼中直接使用,上面配置信息中的NOT_SHOW_LOG和SHOW_LOG是在Project的gradle.properties中定義的值:

org.gradle.jvmargs=-Xmx1536m
SHOW_LOG true
NOT_SHOW_LOG false
先來解釋下buildConfigField的用法, buildConfigField 使用示例:

buildConfigField "boolean", "IS_SHOW_LOG", NOT_SHOW_LOG
buildConfigField 各參數含義:

buildConfigField 備註
String type 要創建的字段類型,如上面的boolean
String name 要創建的字段名,如上面的IS_SHOW_LOG
String value 創建此字段的值,如上面的NOT_SHOW_LOG(false)
配置好上面的信息後,在項目中編寫一個LogUtil.java類如下:

public class LogUtil {
    public static int v(String tag, String msg) {
        if (BuildConfig.IS_SHOW_LOG) {
            return Log.v(tag, msg);
        } else {
            return -1;
        }
    }
---------其他方法----------
}
上面對Log類做了一層封裝,根據BuildConfig.IS_SHOW_LOG的值來決定是否打印Log,我們在buildTypes 的release 裏面配置的IS_SHOW_LOG是false,在debug 裏面配置的IS_SHOW_LOG是true,這樣當我們調試的時候會顯示log日誌,而當我們打的是release 包的時候就會自動屏蔽了Log。
  • Build Variant 管理,多渠道打包

BuildTypes:定義了編譯類型,針對每個類型可以有不同的編譯配置(通常在混淆代碼、可調試、資源壓縮上做一些區分)。默認的有debug、release 類型,除了這兩種外還可以手動添加編譯類型(如preview)。
ProductFlavors:如果針對同一個BuildType還想編譯出多個版本(如友盟多渠道打包,根據不同的meta-data中的值來區分不同的渠道),這時候就需要ProductFlavors了。
所以最後可以編出的APK的個數 = BuildTypes x ProductFlavors,即:

Build Variant = BuildTypes x ProductFlavors

友盟多渠道打包示例:

1、首先在AndroidManifest.xml中定義meta-data:

<meta-data
    android:name="UMENG_CHANNEL"
    //佔位符,在build.gradle中賦值
    android:value="${UMENG_CHANNEL_VALUE}" />

2、配置buildTypes

可以手寫,也可以讓Gradle自動生成,步驟:在app上點右鍵->Open Module Settings->點擊Build Types 按鈕,即可配置不同的buildType了,如下所示又加了一個preview :

buildTypes {
        release {
            minifyEnabled false
            buildConfigField "boolean", "IS_SHOW_LOG", NOT_SHOW_LOG
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
            minifyEnabled false
            buildConfigField "boolean", "IS_SHOW_LOG", SHOW_LOG
        }
        preview {
            minifyEnabled false
            buildConfigField "boolean", "IS_SHOW_LOG", SHOW_LOG
        }
    }
3、配置 productFlavors,可以手寫,也可以讓Gradle自動生成,步驟:在app上點右鍵->Open Module Settings->點擊Flavors按鈕,即可配置不同的Flavors了:

最後在生成的productFlavors中給UMENG_CHANNEL_VALUE賦值:

//給AndroidManifest.xml中的UMENG_CHANNEL_VALUE賦值
  productFlavors {
        market_meizu {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "meizu"]
        }
        market_xiaomi {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "meizu"]
        }
        market_huawei {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "huawei"]
        }
        market_wandoujia {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
        }
        market_yingyongbao {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "yingyongbao"]
        }
        market_360 {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "360"]
        }
    }
4、修改生成的APK名稱

//獲取時間戳
def getDate() {
    def date = new Date()
    def formattedDate = date.format('yyyyMMddHHmm')
    return formattedDate
}
//修改APK生成名字  通過android.applicationVariants索引來遍歷所有的 build variant
    applicationVariants.all { variant ->
        variant.outputs.each { output ->

            def timeNow = getDate()
            def newName
            if (variant.buildType.name.equals('debug')) {
                newName = "android-" + timeNow + "_v${variant.versionName}-debug.apk"
            } else {
                newName = "android_${variant.flavorName}_" + timeNow + "_v${variant.versionName}.apk"
            }
            output.outputFile = new File(output.outputFile.parent, newName)
        }
    }
如現在想生成 preview版本,在buildtypes中選擇preview,選擇我們要打的渠道包,點擊finish

最後生成的渠道包,名字即是按我們想要的命名的


完整的build.gradle

apply plugin: 'com.android.application'

//獲取時間戳
def getDate() {
    def date = new Date()
    def formattedDate = date.format('yyyyMMddHHmm')
    return formattedDate
}

android {
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion
    defaultConfig {
        applicationId "org.ninetripods.mq.study"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode rootProject.ext.versionCode
        versionName rootProject.ext.versionName
        vectorDrawables.useSupportLibrary = true
        buildConfigField "boolean", "IS_SHOW_LOG", "false"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
//        ndk {
//            abiFilters 'armeabi-v7a', 'armeabi'
//        }

    }
    sourceSets {
        main {
            java.srcDirs = ['src/main/java', 'src/main/aidl']
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            buildConfigField "boolean", "IS_SHOW_LOG", NOT_SHOW_LOG
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
            minifyEnabled false
            buildConfigField "boolean", "IS_SHOW_LOG", SHOW_LOG
        }
        preview {
            minifyEnabled false
            buildConfigField "boolean", "IS_SHOW_LOG", SHOW_LOG
        }
    }
    productFlavors {
        market_meizu {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "meizu"]
        }
        market_xiaomi {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "meizu"]
        }
        market_huawei {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "huawei"]
        }
        market_wandoujia {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
        }
        market_yingyongbao {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "yingyongbao"]
        }
        market_360 {
            manifestPlaceholders = [UMENG_CHANNEL_VALUE: "360"]
//            ndk {
//                abiFilters 'armeabi'
//            }
        }
    }

    //修改APK生成名字  通過android.applicationVariants索引來遍歷所有的 build variant
    applicationVariants.all { variant ->
        variant.outputs.each { output ->

            def timeNow = getDate()
            def newName
            if (variant.buildType.name.equals('debug')) {
                newName = "android-" + timeNow + "_v${variant.versionName}-debug.apk"
            } else {
                newName = "android_${variant.flavorName}_" + timeNow + "_v${variant.versionName}_${variant.buildType.name}.apk"
            }
            output.outputFile = new File(output.outputFile.parent, newName)
        }
    }
//    externalNativeBuild {
//        cmake {
//            path 'CMakeLists.txt'
//        }
//    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    //漢字轉拼音,通訊錄 https://github.com/promeG/TinyPinyin
    // TinyPinyin核心包,約80KB
    // 可選,適用於Android的中國地區詞典
    compile 'com.android.support:design:25.2.0'
    compile 'com.android.support:appcompat-v7:25.2.0'
    compile 'com.android.support:recyclerview-v7:25.2.0'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    compile 'com.android.support:support-v4:25.3.1'
    compile 'com.github.promeg:tinypinyin:2.0.3'
    compile 'com.github.promeg:tinypinyin-lexicons-android-cncity:2.0.3'
    testCompile 'junit:junit:4.12'
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章