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 配置(引用方式:${占位符})该占位符,以表达渠道的概念:

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <meta-data
            android:name="channel"
            android:value="${channel}" />

    </application>

然后控制台执行 ./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,这里仅提供思路和方向,具体项目选择合适的打包方式即可。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 目录一、Python打包及优化(美团多渠道打包)二、Gradle打包三、其他打包方案:修改Zip文件的commen...
    守望君阅读 5,675评论 4 17
  • 前言: 01.应用的打包签名 什么是打包? 打包就是根据签名和其他标识生成安装包。 签名是什么? 1.在andro...
    温一阅读 7,016评论 2 7
  • 多渠道打包的用途 用途一:统计不同渠道的数据,方便在推广运营过程中进行有效的渠道比较。来评估渠道的质量。 用途二:...
    没有故事的男童鞋阅读 20,029评论 0 19
  • 苏禄王妃葛木宁和太子墓园,位于山东省德州市苏禄王墓东侧(关于“苏禄王墓”。本博客有专文介绍)。明朝永乐年间...
    2018栏杆拍遍阅读 281评论 0 0
  • 秋风吹,吹不开夏日的炎热。闷闷的,好像心情都开始躁动。 绿叶是清新,片片存阴。在树下才寻得一片阴凉,一丝慰藉。 在...
    元气少女易婷阅读 176评论 0 1