当前位置:   article > 正文

Gradle配置3_productflavors.all { flavor -> //manifest的占位符赋值 fl

productflavors.all { flavor -> //manifest的占位符赋值 flavor.manifestplaceho

多渠道打包

创建渠道占位符

首先在AndroidMainifest文件的Application节点下,创建如下所示的meta-date节点。

<meta-data
            android:name="PRODUCT"
            android:value="${CHANNEL_VALUE}"/>
  • 1
  • 2
  • 3

其中”${CHANNEL_VALUE}”就是要进行替换的渠道占位符。

配置gradle脚本

在项目的gradle脚本的android领域中,添加productFlavors领域,并增加定义的渠道名。同时,使用manifestPlaceholders指定要替换渠道占位符的值,代码如下:

buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        xys{
            signingConfig signingConfigs.xys
        }
    }

    productFlavors{
        xiaomi{
            manifestPlaceholders = [CHANNEL_VALUE:"XIAOMI"]
        }
        wandujia {
            manifestPlaceholders = [CHANNEL_VALUE:"WANDUJIA"]
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

定义了两种不同的渠道,——xiaomi、wandoujia。每个渠道都将指定值赋给渠道占位符CHANNEL_VALUE。这样配置后,就完成了整个多渠道打包工作。生成的apk如下:
这里写图片描述
每个渠道包都有三种:debug、release(系统默认的两种buildType)和xys(自定义的buildType)。

脚本优化

熟悉groovy语言之后,可以对以上脚本进行优化:

productFlavors{
        xiaomi{}
        wandujia {}
    }

    productFlavors.all { flavor ->
        flavor.manifestPlaceholders=[CHANNEL_VALUE:name]
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

生成重命名包名

在生成渠道包名后,包的命名通常是默认命名,即app-渠道名-buildType.apk。
但是有时候我们需要自定义apk包名,这时就可以通过gradle脚本进行快速重命名,代码如下:

android {
   buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        xys{
            signingConfig signingConfigs.xys
        }
    }

    productFlavors{
        xiaomi{}
        wandujia {}
    }

    productFlavors.all { flavor ->
        flavor.manifestPlaceholders=[CHANNEL_VALUE:name]
    }

    applicationVariants.all{ variant->
        variant.outputs.each { output ->
            if (output.outputFile != null && output.outputFile.name.endsWith(".apk")) {
                if ('release'.equals(variant.buildType.name)) {
                    def apkFile = new File(output.outputFile.getParent(),
                            "releaseApp_${variant.flavorName}_v${variant.versionName}.apk")
                    output.outputFile = apkFile
                }
                if ('xys'.equals(variant.buildType.name)) {
                    def apkFile = new File(output.outputFile.getParent(),
                            "xysApp_${variant.flavorName}_v${variant.versionName}.apk")
                    output.outputFile = apkFile
                }
                if ('debug'.equals(variant.buildType.name)) {

                }
            }

        }

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

这段代码的意思是取出所有的生成的apk包,并判断其文件是否是apk、是否是release、xys版本。如果是,则重新命名为“buildType名App_渠道名_v版本号.apk”。如下:
这里写图片描述
因为debug类型没有进行重命名,所以它的apk包名还是以前的。

为不同的版本添加不同的代码

在开发中,不同的版本通常有不同的代码功能。例如最常用的Log开关,在debug版本中会打印开发日志,而在release版本中是需要关闭的。因此,一般会有一个全局的变量开关,根据不同的版本设置不同的值。这一切在gradle脚本的支持下,仅仅变成了一句配置。以buildType为例,为不同的buildType添加不同的参数配置,代码如下所示:

buildTypes {
        release {
            buildConfigField("boolean", "testFlag", "true")
            minifyEnabled false
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        xys{
            buildConfigField("boolean", "testFlag", "false")
            signingConfig signingConfigs.xys
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

通过指定buildConfigField的三个参数——类型、名称、值,就可以将一个变量设置到不同的buildType中去。打开系统的BuildConfig类,可以看到不同的buildType下对应的testFlag的值。该文件对应的路径为/项目/app/build/generated/source/buildConfig/,内容如下:

public final class BuildConfig {
  public static final boolean DEBUG = false;
  public static final String APPLICATION_ID = "com.example.administrator.demo";
  public static final String BUILD_TYPE = "release";
  public static final String FLAVOR = "wandujia";
  public static final int VERSION_CODE = 1;
  public static final String VERSION_NAME = "1.0";
  // Fields from build type: release
  public static final boolean testFlag = true;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
public final class BuildConfig {
  public static final boolean DEBUG = false;
  public static final String APPLICATION_ID = "com.example.administrator.demo";
  public static final String BUILD_TYPE = "xys";
  public static final String FLAVOR = "wandujia";
  public static final int VERSION_CODE = 1;
  public static final String VERSION_NAME = "1.0";
  // Fields from build type: xys
  public static final boolean testFlag = false;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

如果是string类型的变量,在写入字符串的时候,需要加入转义字符。

buildConfigField("String", "testFlag", "\"abc\"")
  • 1

也可以在设置变量的时候,继续使用变量,如下:

buildConfigField("String", "testFlag", "\"${param}\"")
def param = ···
  • 1
  • 2

除了java代码可以使用这种方式进行添加之外,资源文件同样可以进行分版本设置属性值。例如要给不同的版本设置不同的AppName,通过gradle同样是仅仅一行配置即可实现。
在buildType的release和xys这两个Type中进行设置resValue,添加如下所示代码:

buildTypes {

        release {
            resValue("string", "app_name", "AppRelease")
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        xys{
            resValue("string", "app_name", "AppXys")
            signingConfig signingConfigs.xys
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

同时在defaultConfig领域中添加默认的配置,代码如下:

defaultConfig {
        applicationId "com.example.administrator.demo"
        minSdkVersion 15
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        resValue("string", "app_name", "App")
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

在AndroidMainfest文件中,同样使用android:label=”@string/app_name”来获取app_name,但是要注意的是,一定要把string.xml文件中的Demo删掉,这样才能编译过。因为gradle在编译过程中会将脚本中的配置和string.xml文件中的配置进行merge操作,如果同时存在两份相同的属性值,就会发生冲突。

另外resValue配置的参数,不一定非要替换代码中的占位,还可以直接增加变量到R文件中。


def buildTime() {
    return new Date().format("yyyy-MM-dd HH:mm:ss")
}

defaultConfig {
        resValue("string", "build_time", buildTime())
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在上面的代码中,定义了一个buildTime方法,并赋值给自定义的build_time变量。这时候不需要在java代码中增加变量,即可直接引用已经编译到R文件中的变量build_time,代码如下:

Log.d("-->", getString(R.string.build_time));
  • 1

打印结果:

01-08 22:51:50.403 19532-19532/com.example.administrator.demo D/-->: 2017-01-08 22:50:45
  • 1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/265502
推荐阅读
  

闽ICP备14008679号