Android美团多渠道打包Walle集成

1、为何使用美团多渠道打包的方式?

  • 打包更加快速 传统的经过productFlavors渠道包的方式,渠道10个之内还能够接受,若是100个渠道包,每一个包须要打5Min,就是将近10个小时的打包,而采用美团Walle多渠道打包的方式只须要打一个包的时间。
  • 配置更加灵活 能够在APK渠道包中经过配置config文件,针对于不一样渠道包配置各个渠道定制化额外信息

2、多渠道打包原理介绍

整个APK(ZIP文件格式)会被分为如下四个区块:java

  • Contents of ZIP entries(from offset 0 until the start of APK Signing Block)
  • APK Signing Block
  • ZIP Central Directory
  • ZIP End of Central Directory
    apk-sections.png

这个是V2签名包的APK包格式,新的应用签名方案有着良好的向后兼容性,能彻底兼容低于Android 7.0(Nougat)的版本。对比旧签名方案,它有更快的验证速度和更安全的保护。 区块一、三、4都是受保护区块,不容许修改保护区块。美团打包的方式,是在2区块内写入ID-value的扩展信息(渠道信息),并保存到APK中。这样,每打一个渠道包只需复制一个APK,而后在APK中添加一个ID-value便可,这种打包方式速度很是快,对一个30M大小的APK包只须要100多毫秒(包含文件复制时间)就能生成一个渠道包,而在运行时获取渠道信息只须要大约几毫秒的时间。android

3、Walle的工程配置及打包方式

在位于项目的根目录 build.gradle 文件中添加Walle Gradle插件的依赖, 以下:

buildscript {
    dependencies {
        classpath 'com.meituan.android.walle:plugin:1.1.6'
    }
}
复制代码

并在当前App的 build.gradle 文件中apply这个插件,并添加上用于读取渠道号的AAR

apply plugin: 'walle'

dependencies {
    compile 'com.meituan.android.walle:library:1.1.6'
}
复制代码

配置插件

walle {
    // 指定渠道包的输出路径
    apkOutputFolder = new File("${project.buildDir}/outputs/channels");
    // 定制渠道包的APK的文件名称
    apkFileNameFormat = '${appName}-${packageName}-${channel}-${buildType}-v${versionName}-${versionCode}-${buildTime}.apk';
    // 渠道配置文件
    channelFile = new File("${project.getProjectDir()}/channel")
}
复制代码

配置项具体解释:json

  • apkOutputFolder:指定渠道包的输出路径, 默认值为new File("${project.buildDir}/outputs/apk")
  • apkFileNameFormat:定制渠道包的APK的文件名称, 默认值为 ${appName}-${buildType}-${channel}.apk 可以使用如下变量:
projectName - 项目名字
     appName - App模块名字
     packageName - applicationId (App包名packageName)
     buildType - buildType (release/debug等)
     channel - channel名称 (对应渠道打包中的渠道名字)
     versionName - versionName (显示用的版本号)
     versionCode - versionCode (内部版本号)
     buildTime - buildTime (编译构建日期时间)
     fileSHA1 - fileSHA1 (最终APK文件的SHA1哈希值)
     flavorName - 编译构建 productFlavors 名
复制代码

插入额外信息 channelFile只支持渠道写入,若是想插入除渠道之外的其余信息,请在walle配置中使用configFile安全

walle {
    // 渠道&额外信息配置文件,与channelFile互斥
	configFile = new File("${project.getProjectDir()}/config.json")
}
复制代码

configFile是包含渠道信息和额外信息的配置文件路径。 配置文件采用json格式,支持为每一个channel单独配置额外的写入信息。markdown

{
  //extraInfo 不要出现以`channel`为key的状况
  /*
  不声明extraInfo的channel默认使用的extraInfo
  若是没有此项则没有默认extraInfo
  */
  "defaultExtraInfo": {
    "key2": "20161213",
    "key": "20161212"
  },

  /*
    strategy:
     1. ifNone (默认适用此策略) : 仅当对应channel没有extraInfo时生效
     2. always : 全部channel都生效,channel中extraInfo的key与defaultExtraInfo重复时,覆盖defaultExtraInfo中的内容。
   */

  //"defaultExtraInfoStrategy": "always",

  "channelInfoList": [
    {
      "channel": "meituan",
      // 此channel将使用本身声明的extraInfo
      /*
      此alias能够作到写入apk的channel是meituan,而打包时输出的文件名是美团
      注意:alias不声明时,walle配置apkFileNameFormat中channel就是channel,不然为alias
      */
      "alias": "美团",
      "extraInfo": {
        "buildtime": "20161212",
        "hash": "123"
      }
    },
    {
      "channel": "360cn",
      // 此channel将使用本身声明的extraInfo
      "extraInfo": {
        "key": "20161213"
      }
    },
    {
      "channel": "googleplay"
      // 此channel将使用defaultExtraInfo
    },
    {
      "channel": "xiaomi"
      // 此channel将使用defaultExtraInfo
    },
    {
      "channel": "meizu"
      // 此channel将使用defaultExtraInfo
    },
    {
      "channel": "wandoujia",
      "excludeDefaultExtraInfo": true
      //强制声明不使用defaultExtraInfo,默认false
    },
    {
      "channel": "myapp",
      "excludeDefaultExtraInfo": true,
      //强制声明不使用defaultExtraInfo,默认false
      "extraInfo": {
        // 尽管exclude default,但也能够继续写入本身的。
        "key": "20161212"
      }
    }
  ]
}
复制代码

注意:app

  • 此配置项与channelFile功能互斥,开发者在使用时选择其一便可,二者都存在时configFile优先执行。
  • extraInfo 不要出现以channel为key的状况

如何获取渠道信息:

在须要渠道等信息时能够经过下面代码进行获取工具

String channel = WalleChannelReader.getChannel(this.getApplicationContext());
复制代码

生成渠道包

AS右侧点开Gradle工具栏,以下图所示,双击运行Task任务 gradle

TM20181108103724.png

生成的APK渠道包,根据Walle配置文件路径查找 ui

TM20181108103732.png

4、关于友盟统计多渠道的变动

由于友盟统计以前的多渠道统计方式是在AndroidManifast.xml文件中配合Gradle脚本productFlavors实现的多渠道信息集成。采用这种多渠道打包方式以后,productFlavors不存在了,就算没有删除经过原有的获取渠道信息的方式获取到的渠道信息也不对了。因此须要进行变动。很简单,只需在友盟初始化的时候把Channel信息做为参数传入便可。以下所示:this

/** * 做者:郭翰林 * 时间:2018/6/15 0015 12:07 * 注释:Umeng初始化配置 * * @param mAppContext * @param mUmengKey * @param mUmengChannel * @param mUmengSecret */
    public UmengModule(Context mAppContext, String mUmengKey, String mUmengChannel, String mUmengSecret) {
        this.mUmengKey = mUmengKey;
        this.mUmengChannel = mUmengChannel;
        this.mUmengSecret = mUmengSecret;
        this.mAppContext=mAppContext;
        UMConfigure.init(mAppContext, mUmengKey, mUmengChannel, UMConfigure.DEVICE_TYPE_PHONE, mUmengSecret);
    }
		
	 /** * 做者:郭翰林 * 时间:2018/6/15 0015 14:15 * 注释:注册友盟,不要作主进程判断和在线程里注册 */
    private void registerUmeng() {
        UmengModule module = new UmengModule(sysApplication, "XXXXXXXXXXX",
                WalleChannelReader.getChannel(sysApplication), "XXXXXXXXXX");
				.........
				.........
    }
复制代码