Android多渠道打包--多维度

照片是 2020.05.01 花了半个小时用小米9专业模式拍出的效果,有点月色朦胧的味道。感觉到极客时间的摄影课没有白买,至少了解了一点摄影的基础知识。

开端

日常Android开发会有打出不同用途包的要求,最基本的就是给开发环境、测试环境和生产环境打出不同地址的包。以前都是在Java代码里写多个地址,打包时去注释切换不同的地址。例如:

String url = "";
url = "http://192.168.1.1/";     // 开发环境
// url = "http://192.168.1.2/";     // 测试环境
// url = "http://192.168.1.3/";     // 生产环境

这样的方式有个问题,如果忘记改了那就打错包了,而且一次只能打出一个包。如果多个人开发,并且切换过不同的地址提交到git,还得解决冲突问题,特别的麻烦。

以上就是我这个强迫症的动力源泉,就去万能的google搜索解决方案去了。说到这,还是要批评下自己,很多东西知道它的存在,但是没有亲自动手用过,影响就是需要用的时候不能直接上手,领导也不会让你直接用,还需要花时间学习使用。这也就是日常学习与练手的目的,知其然,知其所以然,还要能熟练运用。

单维度

上面的那个需求,只需要添加下面的配置,就可以将配置提到 gradle 内,在开发与打包时都可以通过选择版本来控制打包地址,甚至可以将三个包一同打出来。

flavorDimensions "default"

productFlavors {
    dev {
        buildConfigField "String", "BASE_URL", '"http://192.168.20.100/flavors/"'
    }

    ftest {
        buildConfigField "String", "BASE_URL", '"http://172.16.20.100/flavors/"'
    }

    pro {
        buildConfigField "String", "BASE_URL", '"http://www.pro.flavors.conan/"'
    }
}

可以看到定义了三个地址,那么怎么在代码中运用呢?留意一下这个 BASE_URL 变量的名字,还有这个单引号嵌套双引号的写法。

public static Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(BuildConfig.BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .client(httpClient)
        .build();

日常我们使用 Retrofit 作为网络库,在公共代码部分会使用 BuildConfig.BASE_URL 作为网络库地址。可以看到 BASE_URL 这个变量的名字,与我们上面在 gradle 中定义的变量是一样的。其实这个 BuildConfig 类就是由 gradle 编译时生成的类,它的内容大概是:

/**
 * Automatically generated file. DO NOT MODIFY
 */
package com.example.xue.myapplication;

public final class BuildConfig {
  public static final boolean DEBUG = Boolean.parseBoolean("true");
  public static final String APPLICATION_ID = "com.example.xue.myapplication";
  public static final String BUILD_TYPE = "debug";
  public static final String FLAVOR = "dev";
  public static final int VERSION_CODE = 1;
  public static final String VERSION_NAME = "1.0";
  // Fields from product flavor: dev
  public static final String BASE_URL = "http://192.168.20.100/flavors/";
}

可以看到这个类的最后一行和它的注释这个就是我们配置的变量,这就说明了,刚才为什么要用单引号嵌套双引号。因为它是个String类型的变量,如果是 int 或者 boolean 类型就不需要写双引号了。

默认是 dev 地址的包,如果开发过程中想要使用 ftest 的包怎么办(ps:ftest不是打错了,是不让用test作为开头,所以可以使用for test -> test 或者 te5t 之类的作为名字)?可以使用 Build Variants 来切换环境包。

Build Variants

切换后 BuildConfig 会重新生成,也就能使用相应的地址了,这也就是切换地址的原理。打包时就更方便了:

打包页面效果

可以选择需要的地址甚至是运行release包,来测试应用。这个方式可以还可以替换应用ID、应用名、应用图标等,计划在另外的教程内讲解。

双维度

如果公司要求不止三个地址,还需要区分手机和平板的应用,这时应该怎么办,难道是写六个配置吗?no,只需要写五个(ps:好像没有节省太多吖。。。)

先上配置:

// 维度定义
flavorDimensions "path", "type"

productFlavors {
    dev {
        dimension "path"
        buildConfigField "String", "BASE_URL", '"http://192.168.20.100/flavors/"'
    }

    ftest {
        dimension "path"
        buildConfigField "String", "BASE_URL", '"http://172.16.20.100/flavors/"'
    }

    pro {
        dimension "path"
        buildConfigField "String", "BASE_URL", '"http://www.pro.flavors.conan/"'
    }

    mobile {
        dimension "type"
        applicationId "com.conan.multiflavors.mobile"
    }

    hd {
        dimension "type"
        applicationId "com.conan.multiflavors.hd"
    }
}

可以看到 flavorDimensions 有了变化,上面我们没有讲,如果只有一个默认的值,基本可以忽略它的存在。这个单词的翻译,我没有找到确切的答案,有人称之为维度,我自己叫它调味盘。一份料理可以分成多个工序,手法,调料,食材,烹饪时间,改变一样料理就会有不同的味道,它们之间的组合就是笛卡尔积的关系。而 flavorDimensions 就是用来有多少个维度的。

然后每个配置会发现都多了一个 dimension ,这是用来指定当前配置属于哪个维度,这样 gradle 就会为我们生成多个维度的组合关系。

多维度

可以看到这里生成之前两倍的类型,值都是笛卡尔积的关系。打包的位置也是同理的,为了偷懒就不放图了。

三维度

这时如果需求找你,我们需要定义友盟渠道包,用来统计不用应用市场的运营情况。友盟需要在注册位置传入不用的渠道名作为区分,聪明的你应该想到了,这里还需要定义一个维度。

// 维度定义
flavorDimensions "path", "type", "channel"

productFlavors {
    dev {
        dimension "path"
        buildConfigField "String", "BASE_URL", '"http://192.168.20.100/flavors/"'
    }

    ftest {
        dimension "path"
        buildConfigField "String", "BASE_URL", '"http://172.16.20.100/flavors/"'
    }

    pro {
        dimension "path"
        buildConfigField "String", "BASE_URL", '"http://www.pro.flavors.conan/"'
    }

    mobile {
        dimension "type"
        applicationId "com.conan.multiflavors.mobile"
    }

    hd {
        dimension "type"
        applicationId "com.conan.multiflavors.hd"
    }

    xiaomi {
        dimension "channel"
        manifestPlaceholders = [channel: "xiaomi"]
    }

    huawei {
        dimension "channel"
        manifestPlaceholders = [channel: "huawei"]
    }

    smartision {
        dimension "channel"
        manifestPlaceholders = [channel: "smartision"]
    }
}

新增了一个 channel 的维度,用来区分不用的渠道商的类别,这里定义了三种,真实的可能需要十几种吧。

口算一下我们这次定义了 3 + 2 + 3 = 8 个配置,如果全都写在一起 3 * 2 * 3 = 18 个配置,可以节省很多配置呦。

打包时就可以选择相应渠道包,可以单选可以多选,一次性打出所有的包。这里要夸下 google,以前在这列出了所有的 release 和 debug 很不方便,现在有了改进,将 release 和 debug 改进成了下拉框,也是本来打包功能大部分需求也是 release 很少需要 debug 包的。

一次性打包

给大家看个产物,基本跟正常打包时差不多,也就是花打一个包的时间打出了所有需要的包。

产物

因为不同的渠道产生的文件夹不一样,所以对 git 的 ignore 文件有影响,我是这样配置的忽略规则。

release
debug

by 费城的二鹏 2020.5.2 白山

你可能感兴趣的:(Android多渠道打包--多维度)