构建与打包能力(一、如何高效的构建渠道包)

861 阅读2分钟

构建与打包能力系列

1、什么是多渠道

渠道包就是要在安装包apk中添加渠道信息,也就是channel,对应不同的渠道,例如:小米市场、360市场、应用宝市场等,需要为每个apk包设定一个可以区分渠道的标识,这个为apk包设定应用市场标识的过程就是多渠道打包。

2、gradle实现多渠道打包的方式

其核心原理就是在编译时通过gradle修改AndroidManifest.xml中的meta-data占位符的内容,执行N次打包流程,然后就可以在java中通过API获取对应的数据。

BuildTypes、Flavors、BuildVariants三个定义:

(1)BuildTypes:构建类型,gradle组件默认提供给了debug、release类型。

(2)Flavors:产品渠道,可以根据productFlavors,针对不同的渠道生产个性化apk。

(3)BuildVariants:每一个buildType和flavor组成一个buildVariant。

  • Mainfest配置渠道占位符
<meta-data
    android:name="channel"
    android:value="${channel_value}" />
  • app模块的build.gradle
android {
    //产品维度,没有实际意义,但gradle要求
    flavorDimensions 'default'
    //productFlavors是android节点的一个节点
    productFlavors {
        baidu {}
        xiaomi {}
    }

    //如果需要在不同渠道统一配置,使用productFlavors.all字段替换manifest里面channel_value的值
    productFlavors.all { flavor ->
        manifestPlaceholders = [channel_value: name]
    }

    //设置渠道包名称->howow-xiaomi-release-1.0.apk
    applicationVariants.all { variant ->
        variant.outputs.all { output ->
            //output即为该渠道最终的打包产物对象,设置它的outputFileName属性
            outputFileName = "howow-${variant.productFlavors[0].name}_${variant.buildType.name}_${variant.versionName}.apk"
        }
    }
}
  • 运行时获取渠道信息
private String getChannel() {
    PackageManager pm = getPackageManager();
    ApplicationInfo appInfo = pm.getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
    return appInfo.metaData.getString("channel_value");
}

但是,这种方式存在一些缺点:

(1)每生成一个渠道包,都要重新执行一遍构建流程,效率太低,只适用于渠道较少的场景。

(2)Gradle会为每个渠道包生成一个不同的BuildConfig.java类,记录渠道信息,导致每个渠道包的dex的CRC值都不同。

public final class BuildConfig {
  public static final boolean DEBUG = Boolean.parseBoolean("true");
  public static final String APPLICATION_ID = "com.example.myapplication";
  public static final String BUILD_TYPE = "debug";
  public static final int VERSION_CODE = 1;
  public static final String VERSION_NAME = "1.0";
  //增加了productflavor之后,这里的值,每个apk都不同
  public static final String FLAVOR = "";
}

如果使用了微信的Tinker热补丁方案,那么就需要为不同的渠道包打不同的补丁,因为Tinker是通过对比基础包base.apk和新包new.apk生成差分补丁patch.apk,然后再把补丁patch.apk和已安装的基础包old base.apk一起合成新的apk。

这就要求用于生成差分补丁的基础包base.apk里面的DEX和已安装的基础包old base.apk里面的DEX是完全一致的,就是说手机上安装的是应用宝渠道包,那必须使用应用宝渠道包来生成补丁patch.apk,才能合并成功。