Android 多渠道打包

Android 多渠道打包

Android 其实并没有多渠道的概念,所谓的渠道号是人为添加以识别应用市场渠道的。

Android Gradle 原生多渠道打包

原理

虽然 Android 本身不支持渠道号,但是 Android-Gradle 插件有维度的概念,通过维度可以实现模拟多渠道打包。

如下面的例子:

    flavorDimensions "channel", "version"

    productFlavors {
        dji {
            dimension 'channel'
            buildConfigField 'String','channel_key','"dji_sign"'
        }

        '360' {
            dimension 'channel'
            buildConfigField 'String','channel_key','"360_sign"'
        }

        free {
            dimension 'version'
        }

        vip {
            dimension 'version'
        }
    }

通过 productFlavorsdimension 的组合关系,上面的例子可以打出如下的多种组合包:

djifreedebug、djivipdebug、djifreerelease、djiviprelease、360...

buildConfigField 属性可以给特殊维度设置独有变量,如上述例子中,dji 维度的包会生成一个值为 "dji_sign" 的 channel_key 变量,而 360 维度的包则会生成一个值为 "360_sign" 的 channel_key 变量。

buildConfigField 顾名思义是给 BuildConfig 添加不同维度下的变量,与之作用类似的还有 manifestPlaceholders,从名字可以看出它是给 AndroidManifest 添加不同维度下的占位符。关于这俩个 Gradle 属性的详细使用规则这里不做详细介绍,各位可以自行 Google。

实现

Module - build.gradle - android 模块下,添加如下配置:

    flavorDimensions "channel"

    productFlavors {
        dji {
            dimension "channel"
        }
        baidu {
            dimension "channel"
        }
        xiaomi {
            dimension "channel"
        }
    }

    productFlavors.all {
        flavor -> manifestPlaceholders.put("channel", name)
    }

manifestPlaceholders 创建了一个名为 'channel',值为维度名的占位符,然后在 AndroidManifest 配置(引用方式:${占位符})该占位符,以表达渠道的概念:

    
        
            
                

                
            
        

        

    

然后控制台执行 ./gradlew build,就会打出所有维度(渠道)的包。

用下面的方式获取 channel 的值上报。

    public String parseChannel() {
        String channel = null;
        try {
            ApplicationInfo appInfo = getPackageManager().getApplicationInfo(getPackageName(), GET_META_DATA);
            Bundle metaData = appInfo.metaData;
            channel = metaData.getString("channel");
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return channel;
    }

总结

原生 Gradle 支持,缺点是工程量大、速度慢。

第三方 Gradle 插件多渠道打包

这里推荐使用 packer-ng-plugin

原理

APK 文件就是一个带签名信息的 ZIP 文件,根据 ZIP 文件格式规范,每个 ZIP 文件的最后都必须有一个叫 Central Directory Record 的部分,这个 CDR 的最后部分叫"end of central directory record",这一部分包含一些元数据,它的末尾是 ZIP 文件的注释。注释包含 Comment Length 和 File Comment 两个字段,前者表示注释内容的长度,后者是注释的内容,正确修改这一部分不会对 ZIP 文件造成破坏,利用这个字段,我们可以添加一些自定义的数据,PackerNg 项目就是在这里添加和读取渠道信息。

实现

根目录 build.gradle 添加:

buildscript {
    ......
    dependencies{
    // add packer-ng
        classpath 'com.mcxiaoke.gradle:packer-ng:1.0.9'
    }
}  

module 模块 build.gradle 添加:

apply plugin: 'com.android.application'
apply plugin: 'packer'  //1.

android {
    ...
    defaultConfig {
        ...
    }

    signingConfigs {
        release {
            storeFile file("你的签名地址")
            storePassword "你的签名密码"
            keyAlias "你的签名别名"
            keyPassword "你的签名密码"
            v2SigningEnabled false  //2.一定要把v2签名关掉
        }

        debug {
            storeFile file("你的签名地址")
            storePassword "你的签名密码"
            keyAlias "你的签名别名"
            keyPassword "你的签名密码"
            v2SigningEnabled false  //一定要把v2签名关掉
        }
    }

    buildTypes {
        release {
            ...
            signingConfig signingConfigs.release //3.
        }

        debug {
            ...
            signingConfig signingConfigs.debug
        }
    }
}

dependencies {
    ...
    implementation 'com.mcxiaoke.gradle:packer-helper:1.0.9' //4.
}

点击同步,代码中获取渠道号:

String market = PackerNg.getMarket(Context);

配置完毕,开始打包。

打包方式有俩种,这里只介绍控制台打包,其余参见 Github。

在项目根目录下创建 markets.txt 文件,文件内容如下:

google#谷歌渠道
xiaomi#小米渠道
huawei#华为渠道

每行一个渠道,# 号表示注释。

然后控制台输入如下命令打包(执行命令前建议运行一次项目,确认无误再执行):

./gradlew -Pmarket=markets.txt clean apkRelease

打包成功后,可在 根目录/build/archives 看到渠道包文件(注意不是 module 下的 build 文件夹)。

总结

packer-ng-plugin 插件通过修改复制 zip(apk)实现了快速打包,缺点是兼容性没有原生好,可能存在适配问题。

其它多渠道打包方式

除此之外还有其余快速打包方式,如通过 python 快速修改 apk -- AndroidManifest -- meta_data 属性,然后重签名对齐;如通过美团网批量打包工具 walle,这里仅提供思路和方向,具体项目选择合适的打包方式即可。

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