zoukankan      html  css  js  c++  java
  • Android Gradle defaultConfig详解及实用技巧

    实际项目中,都会应用Android Gradle Plugin,根据实际中的项目模块的职责,可以具体应用如下四种插件类型。

    1,apply plugin: 'com.android.application'
    实际对应的原型是:com.android.build.gradle.AppExtension,表示此项目模块类型为Android App Module,对应构建生成的文件为.apk类型文件。

    2,apply plugin: 'com.android.library'
    实际对应的原型是:com.android.build.gradle.LibraryExtension,表示此项目模块类型为Android Library Module,对应构建生成的文件为.arr类型的文件。

    3,apply plugin: 'com.android.test'
    实际对应的原型是:com.android.build.gradle.TestExtension,表示此项目模块类型为Android test Module,可以在单个模块内通过targetProjectPath指定项目,用于对应项目的单元测试。

    4,apply plugin: 'com.android.feature'
    实际对应的原型是:com.android.build.gradle.FeatureExtension,表示此项目模块类型为Android feature Module,主要用于单个模块内实现特性,以支持Android Instant Apps

    其中,一般项目中最常见的是applicationlibrary插件类型。

    项目模块内应用了具体的Android Gradle Plugin类型后,可以开始进行对应的配置,如最常见的如下配置项:

    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 28
        defaultConfig {
            applicationId "com.happycorn"
            minSdkVersion 15
            targetSdkVersion 28
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
            ...
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
            ...
        }
        
        ...
    }
    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        ...
    }
    复制代码

    此时可以按住CTRL,通过鼠标悬浮,可以看到对应的配置原型信息。

    不同的Android Gradle Plugin插件类型,对应不同的实现原型,以及对应可能不同的对外配置项。

    同样的,跟踪defaultConfig{}原型信息,可以进入到如下原型说明。

    /**
         * Specifies defaults for variant properties that the Android plugin applies to all build
         * variants.
         *
         * <p>You can override any <code>defaultConfig</code> property when <a
         * href="https://developer.android.com/studio/build/build-variants.html#product-flavors">
         * configuring product flavors</a>.
         *
         * <p>For more information about the properties you can configure in this block, see {@link
         * ProductFlavor}.
         */
        public void defaultConfig(Action<DefaultConfig> action) {
            checkWritability();
            action.execute(defaultConfig);
        }
    复制代码

    可见,defaultConfig{}所对应的具体职责是:
    为变体属性,指定默认值,Android plugin 可以将指定的变体属性的默认值,应用到所有的变体中。

    执行action.execute(defaultConfig);后,将为DefaultConfig对象指定具体的配置。

    实际项目开发中,我们往往关注此处有哪些配置项,以及每个配置项对应的含义及作用。

    首先可以在Android Gradle DSL文档上对应查询DefaultConfig使用说明。 具体参见: google.github.io/android-gra…

    文档中列出了DefaultConfig对象的对外可配置的属性、方法,以及对应说明,在具体配置时,可能有些需要注意的事项,文档中也做了详尽叙述。

    但无论是属性还是方法,一般在build.gradle中配置defaultConfig{}时,一般都是采用形如 key value形式,当然,实际上也可以采用对应的方法原型形式配置,效果是等价的,不过有个前提是,此方法原型是确实存在的,否则,Gradle会报错。 如:

    defaultConfig {
        ...
        minSdkVersion 15
        ...
    }
    
    等价于
    defaultConfig {
        ...
        minSdkVersion(15)
        ...
    }
    复制代码

    defaultConfig{}中配置的属性,在构建时,会默认生成对应的变体目录下的BuildConfig.java文件,此文件中将之前配置的属性转变成了对应的JAVA常量形式。

    build.gradle中配置如下:

    android {
        compileSdkVersion 28
    
        defaultConfig {
            applicationId "com.happycorn"
            minSdkVersion 15
            targetSdkVersion 28
            versionCode 1
            versionName "1.0"
        }
    
    
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
    
            debug {
    
            }
        }
    
    
        flavorDimensions "default"
    
        productFlavors {
            demo {
                applicationIdSuffix "demo"
            }
    
            full {
                applicationIdSuffix "full"
            }
        }
    
    }
    复制代码

    执行./gradlew assembleFull命令,对应生成的BuildConfig文件为:

    如其中的buildTypedebug对应的BuildConfig文件内容为:

    /**
     * Automatically generated file. DO NOT MODIFY
     */
    package com.happycorn;
    
    public final class BuildConfig {
      public static final boolean DEBUG = Boolean.parseBoolean("true");
      public static final String APPLICATION_ID = "com.happycorn.full";
      public static final String BUILD_TYPE = "debug";
      public static final String FLAVOR = "full";
      public static final int VERSION_CODE = 1;
      public static final String VERSION_NAME = "1.0";
    }
    复制代码

    BuildConfig文件为JAVA源码级别,构建时也会对应被编译打包到包中,可以直接在对应的模块中使用。

    利用此特性,我们经常可以在项目中对变体环境进行逻辑判断,对应的进行逻辑处理。 如:判断是否是DEBUG,对应的输出Log等。

    if (BuildConfig.DEBUG) {
        Log.d(TAG, "come here...");
    }
    复制代码

    另外,DefaultConfig对象中专门对外提供了buildConfigField(type, name, value)方法,用于向构建时生成的BuildConfig.java类中增加新的属性。

    如:defaultConfig{}中通过buildConfigField(type, name, value)添加如下。

    defaultConfig {
        ...
        // 是否打对对用户的内测包
        innerTest = project.hasProperty('innertest') ? innertest : 'false'
        buildConfigField "boolean", "INNER_TEST", innerTest
        
        // 添加模块对应的模块名
        buildConfigField "String", "MODULE_NAME", ""${project.name}""
    }
    复制代码

    生成的BuildConfig.java中将有对应属性产生。

    public final class BuildConfig {
      ...
      // Fields from default config.
      public static final boolean INNER_TEST = false;
      public static final String MODULE_NAME = "app";
    }
    复制代码

    利用此特性,可以很有技巧性的去处理项目中的一些特定的问题。参照上例代码中的两个追加的属性。
    如:
    Gradle构建时,通过命令参数-P传入对应参数键值,可以将其在defaultConfig{}中添加,以自动在BuildConfig.java中生成对应属性,然后程序中对应进行一些逻辑的特别处理。

    if (BuildConfig.INNER_TEST) {
        // 用户内测的一些逻辑处理
        ...
    }
    复制代码

    又如:
    调用项目日志系统时,可以传入对应的模块名,以实现对各个模块的日志过滤展示等。 此时就可以通过project.name取到模块名,追加到BuildConfig.java中。然后调用日志库时可以取用。

    CLog.e(BuildConfig.MODULE_NAME, TAG, e)
    复制代码

    更进一步,此处对各个模块通过defaultConfig{}配置向BuildConfig.java中追加属性可以写成:

    allprojects {
        ...
        afterEvaluate { project ->
            def android = project.extensions.findByName("android")
            if(android != null){
                def defaultConfig =  android["defaultConfig"]
                defaultConfig.buildConfigField("String", "MODULE_NAME", ""${project.name}"")
            }
        }
    }
    复制代码

    使得整体用法显得非常灵活。

    除了buildConfigField(type, name, value)方法外,还有一个实用方法resValue(String type, String name, String value)
    resValue(String type, String name, String value)等价于向模块res/values中新增一个资源。

    如:在buildTypedebug中新增资源:

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    
        debug {
            resValue("string", "app_name_debug", "HappyCornDebug")
            resValue("integer", "token", "365")
        }
    }
    复制代码

    编译后,对应变体目录结构下会生成资源文件,及对应的资源键值。

    项目中对应需要的此资源的地方也可以直接取用:

    getResources().getString(R.string.app_name_debug);
    getResources().getInteger(R.integer.token);
    复制代码

    defaultConfig{}中配置的属性与productFlavors中具体Flavor中配置的属性重复时,Android Gradle构建时将以productFlavors中的对应配置为准,可以理解成将defaultConfig{}中对应的配置覆盖掉了。但applicationIdSuffix除外(applicationIdSuffix依然是追加的形式)。

    在现实的项目需求中,外部传入的参数键值或通过Gradle/Android Gradle脚本获取的值,结合defaultConfig{}配置,变体,以及对应生成的BuildConfig.java或资源文件,实现一些特定场景下的需求,整体可以非常灵活,且具有一定的技巧性。


    作者:HappyCorn
    链接:https://juejin.im/post/5c70a1f56fb9a04a0e2dd008
    来源:掘金
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    记2008年7月25日午后 心情
    [多媒体]词典编码
    [多媒体]算术编码、游程编码
    [多媒体]数据压缩的类型
    [多媒体]理解PCM、DPCM、APCM、ADPCM
    C++异常处理
    [转]linux上SVN解决冲突的办法
    从海量数据查找有或者没有出现的数据
    八数码问题
    [转]linux中强大的screen命令
  • 原文地址:https://www.cnblogs.com/lwbqqyumidi/p/10422956.html
Copyright © 2011-2022 走看看