Android多渠道打包

目录

一、Python打包及优化(美团多渠道打包)

二、Gradle打包

三、其他打包方案:修改Zip文件的comment

参考阅读

早几个月前在有心课堂看过Android多渠道打包的视频,觉得蛮有用的,时至今日却发现不少具体的细节已经忘得差不多,于是重新整理了一篇笔记,顺道分享给大家。

一、Python打包及优化(美团多渠道打包)

既然是Python打包,那么python环境是必须的,否则无法运行python脚本文件,mac系统下默认安装了Python环境,而Windows系统下则需要自己安装了,这个安装过程相对可以简单,大家可以自行谷歌下,记得配好环境变量。验证是否安装成功的方式是,打开命令行,输入python,如果安装成功的话,会打印python的版本信息。

下面我们以友盟应用统计为例,进行相关的操作。

需要准备的东西:
  • 签名好的Apk文件
  • channel.py (python脚本文件
  • channel列表文件 (注:必须命名为android_channels.txt,如果不想这样命名,可自行更改python脚本代码
  • ChannelUtil.java工具类

其中channel列表文件(android_channels.txt)的格式为每一个渠道号换一行,示例:


xiaomi
360mobile
wandoujia
baidu

另外python脚本文件、ChannelUtil.java这里就不贴代码了,有点长,但还是比较简单容易理解的,大家可以自己下载下来看看,附上 :传送门

使用姿势:

首先,在签名打包一个Apk之前,需要在程序的入口处添加如下代码:


        String channel= ChannelUtil.getChannel(mAppContext);  //获取渠道号,内存>SharedPreferences>apk的/META-INF/目录
        MobclickAgent.startWithConfigure(new MobclickAgent.UMAnalyticsConfig(getApplicationContext(),umengAppkey,channel)); //友盟:通过代码的方式设置渠道号

生成好以后,将该apk文件和上面所准备的东西放在同一个文件夹,打开终端命令行,进入该文件夹。执行命令:

python channel.py apk包名

很快就在当前目录下生成一个release文件夹,里面生成了各个渠道所需要的渠道包。

这一条简单的命令背后,到底隐藏着什么不为人知的流程呢?请看下图:

Python打包流程

整理思路来看,就是通过python脚本去读取渠道列表,然后一个for循环将签名好的apk写入渠道号,并在当前目录下,生成一个release文件夹,将写入好的渠道包放进去,那么这个for循环内部究竟是怎样的一个操作呢?它分为以下几步:

  1. 复制签名好的signatured.apk到./release文件夹下
  2. 重命名signatured.spk 为 signatured_channel_xxx.apk
  3. 找到apk/META-INF/目录
  4. 新建一个文件名为 channel_xxx的空文件

这种通过python打包的方式有什么优点和缺点呢?

优点:

  • 只需要一个签名好的apk
  • 速度快(在渠道少的情况下,基本秒开,如果渠道更多,有100多个的话应该也不会超过一分钟)

缺点:

  • 依赖Java的签名方式(现有的打包方式,在apk的META-INF目录下添加文件,是不需要重新签名的,但如果谷歌更改了这套签名方式,那么这种方法就不适用了)
  • 必须支持只用Java代码写入渠道号
zipalign优化:

是否上述的这种打包方式就一定完美了呢?也许你会遇到这样的问题:

  • 在Google Play上提交会失败(如果你的应用要上传到该市场的话
  • Lollipop系统(Android 5.0.1)安装可能会提示解析安装包错误

所以介绍来要介绍另外一款工具——zipalign,官方的定义是这样子的:

zipalign is an archive alignment tool that provides important optimization to Android application (APK) files

简单提炼为关键词就是:优化工具4字节边界对齐减少内存使用提高效率

何时需要使用这个工具?

  • apk签名之后(在开发过程中,更多的时候是eclipse、as自动帮我们使用了这个工具,不需要我们手动去使用它的
  • 对apk进行添加或更改的时候

常用的命令:

  • zipalign -c -v <alignment> existing.apk
  • zipalign [-f] [-v] <alignment> infile.apk outfile.apk

-c :验证apk是否按照某种对齐方式对齐

-f :覆盖已经存在的文件

-v :输出verbose级别的信息

<alignment> :对齐方式,这里我们以4字节的方式对齐

existing.apk :需要验证的apk文件

infile.apk :要打包的apk文件

outfile.apk :要输出的apk文件

第一条命令是用来验证apk是否有进行过zipalign优化;第二条命令是用来进行zipalign优化

那么zipalign这个工具在哪里呢?

我们可以打开android sdk的安装目录下,在build-tools/版本号文件夹/找到一个zipalign.exe,其实zipalign是在android 1.6之后提供的一个工具,在使用之前我们最好可以把这个路径配置到环境变量里。

在使用的时候,我们通常先用第一条命令判断我们的apk文件是否已经进行过zipalign优化,接着再使用第二条命令是优化我们的apk文件,快捷命令:

首先是验证apk:

zipalign -c -v 4 demo_channel.apk

进行zipalign优化:

zipalign -f -v 4 demo_channel.apk demo_align.apk

有些同学可能会问,你这一个apk优化还好,那如果有很多个渠道包,我们应该怎么去优化呢?这里已经在刚刚的传送门里,给大家准备好了两个脚本文件,分别是mac系统下的zipalign_batch.sh和windows系统下的zipalign_batch.bat文件,并且已经集成到channel.py的python脚本当中,我们在使用的时候,可以根据自己的需要自行开启相关的代码即可:


    #mac
    #os.system('chmod u+x zipalign_batch.sh')
    #os.system('./zipalign_batch.sh')

    #windows
    #os.system('zipalign_batch.bat')

再次提醒下大家,在开启使用这段代码的前,要把zipalign工具配置到你系统的环境变量里,否则在运行python脚本过程中会提示相关的文件找不到哈。

二、Gradle打包

相信大部分开发者都已经迁移到AS下进行开发,那么利用gradle进行多渠道打包也是我们必须掌握的一个知识点,下面分别讲解下gradle的多渠道打包和多Apk打包。

多渠道打包

多渠道打包,大家应该都知道,这里不解释,同样以友盟统计为例,

第一步:

在AndroidManifest.xml文件中配置渠道ID,${UMENG_CHANNEL_VALUE} 为占位符,其中的UMENG_CHANNEL_VALUE可以自己任意定义

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

第二步:

在项目的build.gradle文件中设置打包签名信息 signingConfigs:


    android {
        debug {
            // No debug config
        }

        release {
            storeFile file("../yourapp.jks")
            storePassword "your password"
            keyAlias "your alias"
            keyPassword "your password"
        }
    }

接着,设置productFlavors,这里包含你了所需要的渠道号:


    android {
        productFlavors {
            xiaomi {
                manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"]
            }
            360 mobile {
                manifestPlaceholders = [UMENG_CHANNEL_VALUE: "360mobile"]
            }
            wandoujia {
                manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
            }
            baidu {
                manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu"]
            }
        }
    }

也有另外一种简便的写法,其实就是用Groovy语法执行一个for循环:


    productFlavors {
        xiaomi {}
        360 mobile {}
        wandoujia {}
        baidu {}
    }

    productFlavors.all { flavor ->
        flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
    }

最后:

在AS的内置终端Terminal工具中执行命令:

./gradlew assembleRelease
(所有生成的apk在项目的build\outputs\apk下)

好了,接下来可以静静等待打包完成。

如果不想使用命令行的方式进行打包,AS也为我们提供了图形界面的方式,点击菜单栏->Build->Generate Signed APK,输入相关的签名证书路径和密码即可:

图形界面打包1
图形界面打包2

这种打包方式的其中一个好处是可以指定打包后的apk所存放的路径。

多Apk打包

什么叫多Apk打包?可能很多人不知道,也没有碰到这样的需求,多Apk打包其实就是根据特定的需求,生成不同类型的apk,譬如说每个apk的有不同的应用名称、应用icon或cpu类型等等。

下面以生成不同的cup类型的apk为例,cup的类型大致可以分为分别是arm、mips、X86这三种:

同样地,我们在build.gradle设置这ProductFlavors即可:


    productFlavors {
        arm {
            ndk{
                abiFilters("armeabi","armeabi-v7a")
            }
        }
        mips {
            ndk{
                abiFilters("mips","mips86")
            }
        }
        x86 {
            ndk{
                abiFilters("x86","x86_64")
            }
        }
    }

这里要插句补充下defaultConfig 跟 productFlavors的关系,defaultConfig相当于一个默认的flavor,如果我们没有定义productFlavors,gradle在构建过程中就会只读取defaultConfig的配置信息;如果自定义了productFlavors,那么defaultConfig相当于每一个flavor的基础配置信息。如果flavor和defaultConfig的某些配置项相同,flavor的配置将会覆盖defaultConfig。

补充知识点

Gradle常用命令

  • ./gradlew -v :版本号
  • ./gradlew clean :清除项目/app目录下的build文件夹
  • ./gradlew build 检查依赖并编译打包
需要注意的是 ./gradlew build 命令会debug、release环境的包都打出来,如果正式发布只需要打Release的包,可以使用assemble命令
  • ./gradlew assembleDebug :编译并打Debug包
  • ./gradlew assembleRelease :编译并打Release的包
  • ./gradlew installRelease :Release模式打包并安装
  • ./gradlew uninstallRelease :卸载Release模式包

我们执行命令前,都会加上./gradlew./代表当前目录,gradlew代表gradle wrapper,意思是gradle的一层包装,可以理解为在这个项目本地就封装了gradle,即gradle wrapper。在项目名/gradle/wrapper/gralde-wrapper.properties文件中声明了它指向的目录和版本.

关于assemble

在上面的assemble命令中,会结合Build Type来创建自己的task,譬如:

  • ./gradlew assembleDebug
  • ./gradlew assembleRelease

除此之外,assemble还能和ProductFlavor 结合创建新的任务,其实assemble是和Build >Variants 一起结合使用的,大家可以这么来理解:

Build Variants = Build Type + Product Flavor

举个栗子:

如果我们想打wandoujia渠道的Release版本,可以执行如下命令

./gradlew assembleWandoujiaRelease

如果我们只打wandoujia渠道版本,则:

./gradlew assembleWandoujia
(此命令会生成wandoujia渠道的Release和Debug版本)

同理,如果想打全部Release版本:

./gradlew assembleRelease
(这条命令会把Product Flavor下的所有渠道的Release版本都打出来)

基于以上,总结一下assemble创建task有如下用法:

  • 允许直接构建一个Variant版本,例如 assembleFlavor1Debug
  • 允许构建指定Build Type的所有APK,例如assembleDebug将会构建Flavor1Debug和Flavor2Debug两个Variant版本
  • 允许构建指定flavor的所有APK,例如assembleFlavor1将会构建Flavor1Debug和Flavor1Release两个Variant版本

关于BuildVariants

在AS中有个BuildVariants的概念,Build Variants = Build Type + Product Flavor,譬如如下代码:


android {
    productFlavors {
        xiaomi {}
        _360mobile {}
        wandoujia {}
        baidu {}
    }

    productFlavors.all { flavor ->
        flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
    }
}

会生成以下的BuildVariants:

AS-BuildVariants

我们就可以看到,productFlavors有多个维度,并且每个Flavor都有debug和release,所以总共生成Build Type*ProductFlavor个不同的apk,也即2*4=8种不同的APK。

最后附上送一个完整的gradle脚本文件:传送门

三、其他打包方案:修改Zip文件的comment

核心原理:

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

所以原理很简单,就是将渠道信息存放在APK文件的注释字段中

优点:

  • 没有解压缩、压缩、重签名过程,打包速度极快,单个包只需要5毫秒左右,甚至可用于网站后台动态生成渠道包

缺点:

  • 没有使用Android的productFlavors,无法利用flavor条件编译的功能

相关工具:

参考阅读

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

推荐阅读更多精彩内容

  • Android多渠道打包 概述 每当发新版本时,Android客户端会被分发到各个应用市场,比如豌豆荚,360手机...
    砺雪凝霜阅读 2,113评论 2 11
  • 我们做Android用户级应用开发的时候都要考虑这样的问题,目前的应用市场有很多,我们的安装包是通过哪个渠道进入用...
    尹star阅读 8,746评论 11 26
  • 面试的时候,如果面试官突然问到:你们渠道包是怎么打的?如果你说是用gradle一个一个编译的,然后他很鄙视的说这个...
    lovejjfg阅读 2,266评论 10 14
  • ###多渠道打包概念 >* 发布到不同渠道上的apk,标记不同的渠道,目的是为了统计该渠道的下载量,留存率等等数据...
    未聞椛洺阅读 598评论 0 0
  • 一、什么是多渠道 我理解的是:APP发布到不同的应用平台,监测用户是从哪个平台安装的。 二、为什么要多渠道打包 1...
    LucasAdam阅读 902评论 0 1