美团Android自动化之旅—生成渠道包

每当发新版本时,美团团购Android客户端会被分发到各个应用市场,比如豌豆荚,360手机助手等。为了统计这些市场的效果(活跃数,下单数等),需要有一种方法来唯一标识它们。

团购客户端目前通过渠道号(channel)来区分不同的市场,代码中使用Config.channel变量记录该渠道号。比如,豌豆荚市场中美团应用的渠道号是wandoujia,360手机助手中美团应用的渠道号为qihu360。客户端访问API时会在请求参数中带上渠道号,以便后台接下来计算不同渠道的效果。

每次发版时,市场部会提供一个渠道列表,Android RD会根据这些渠道相应地生成等量的渠道包。随着渠道越来越多(截止本文写作时已有900多个渠道),客户端打渠道包的方式也一直在演进,本文接下来就详细介绍美团应用的打包之旅。

Maven是一个软件项目管理和自动构建工具,配合使用android-maven-plugin插件,以及maven-resources-plugin插件可以很方便的生成渠道包,下面简要介绍下打包过程,更多Maven以及插件的使用方法请参考相关文档。

首先,在AndroidManifest.xml<application>节点中添加如下<meta-data>元素,用来定义渠道的来源:

<!-- 使用Maven打包时会用具体的渠道号替换掉${channel} -->
<meta-dataandroid:name="channel"android:value="${channel}" />

定义好渠道来源后,接下来就可以在程序启动时读取渠道号了:

private String getChannel(Context context) {try {PackageManager pm = context.getPackageManager();ApplicationInfo appInfo = pm.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);return appInfo.metaData.getString("channel");} catch (PackageManager.NameNotFoundException ignored) {}return "";}

要替换AndroidManifest.xml文件定义的渠道号,还需要在pom.xml文件中配置Resources插件:

<resources>           <resource><directory>${project.basedir}</directory><filtering>true</filtering><targetPath>${project.build.directory}/filtered-manifest</targetPath><includes><include>AndroidManifest.xml</include></includes></resource>
</resources>

准备工作已经完成,现在需要的就是实际的渠道号了。下面的脚本会遍历渠道列表,逐个替换并打包:

#!/bin/bashpackage(){while read linedomvn cleanmvn  -Dchannel=$line packagedone < $1
}package $1

在前期渠道很少时这种方法还可以接受,但只要渠道稍微增多该方法就不再适用了,原因是每打一个包都要执行一遍构建过程,效率太低。

apktool是一个逆向工程工具,可以用它解码(decode)并修改apk中的资源。接下来详细介绍如何使用apktool生成渠道包。

前期工作和用Maven打包一样,也需要在AndroidManifest.xml文件中定义<meta-data>元素,并在应用启动的时候读取清单文件中的渠道号。具体请参考上面的代码。

和Maven不一样的是,每次打包时不再需要重新构建项目。打包时,只需生成一个apk,然后在该apk的基础上生成其他渠道包即可。

首先,使用apktool decode应用程序,在终端中输入如下命令:

apktool d your_original_apk build 

上面的命令会在build目录中decode应用文件,decode完成后的目录如下:

接下来,替换AndroidManifest.xml文件中定义的渠道号,下面是一段python脚本:

import redef replace_channel(channel, manifest):pattern = r'(<meta-data\s+android:name="channel"\s+android:value=")(\S+)("\s+/>)'replacement = r"\g<1>{channel}\g<3>".format(channel=channel)return re.sub(pattern, replacement, manifest)

然后,使用apktool构建未签名的apk:

apktool b build your_unsigned_apk

最后,使用jarsigner重新签名apk:

jarsigner -sigalg MD5withRSA -digestalg SHA1 -keystore your_keystore_path -storepass your_storepass -signedjar your_signed_apk, your_unsigned_apk, your_alias

上面就是使用apktool打包的方法,通过使用脚本可以批量地生成渠道包。不像Maven,每打一个包都需要执行一次构建过程,该方法只需构建一次,大大节省了时间。

但是好景不长,我们的渠道包越来越多,目前已有近900个渠道,打完所有的渠道包需要近3个小时。有没有更快的打包方式呢?且看下节。

如果能直接修改apk的渠道号,而不需要再重新签名能节省不少打包的时间。幸运的是我们找到了这种方法。直接解压apk,解压后的根目录会有一个META-INF目录,如下图所示:

如果在META-INF目录内添加空文件,可以不用重新签名应用。因此,通过为不同渠道的应用添加不同的空文件,可以唯一标识一个渠道。

下面的python代码用来给apk添加空的渠道文件,渠道名的前缀为mtchannel_

import zipfile
zipped = zipfile.ZipFile(your_apk, 'a', zipfile.ZIP_DEFLATED) 
empty_channel_file = "META-INF/mtchannel_{channel}".format(channel=your_channel)
zipped.write(your_empty_file, empty_channel_file)

添加完空渠道文件后的目录,META-INFO目录多了一个名为mtchannel_meituan的空文件:

接下来就可以在Java代码中读取空渠道文件名了:

public static String getChannel(Context context) {ApplicationInfo appinfo = context.getApplicationInfo();String sourceDir = appinfo.sourceDir;String ret = "";ZipFile zipfile = null;try {zipfile = new ZipFile(sourceDir);Enumeration<?> entries = zipfile.entries();while (entries.hasMoreElements()) {ZipEntry entry = ((ZipEntry) entries.nextElement());String entryName = entry.getName();if (entryName.startsWith("mtchannel")) {ret = entryName;break;}}} catch (IOException e) {e.printStackTrace();} finally {if (zipfile != null) {try {zipfile.close();} catch (IOException e) {e.printStackTrace();}}}String[] split = ret.split("_");if (split != null && split.length >= 2) {return ret.substring(split[0].length() + 1);} else {return "";}}

这样,每打一个渠道包只需复制一个apk,在META-INF中添加一个使用渠道号命名的空文件即可。这种打包方式速度非常快,900多个渠道不到一分钟就能打完。

上面总共介绍了三种打渠道包的方式。目前,Android团队打包基本使用第三种方式,完成了打包的自动化,解放了工程师的生产力,善哉善哉。

打包的问题解决了,但有时候还需要为不同的渠道定制不同的APK。下一讲会介绍Android构建利器Gradle,以及如何使用Gradle定制渠道包,敬请期待。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/477879.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源开放 | 细粒度可循证医学文档知识融合表示和推理(CCKS2021)

OpenKG地址&#xff1a;http://openkg.cn/dataset/mdo-dataset开放许可协议&#xff1a;GPL 3.0贡献者&#xff1a;武汉科技大学&#xff08;高峰、龚珊珊、顾进广、徐芳芳&#xff09;摘要本开放资源在医学文档知识的基础上&#xff0c;使用知识图谱相关技术&#xff0c;解决了…

图灵奖大佬 Lecun 发表对比学习新作,比 SimCLR 更好用!

文 | Rukawa_Y编 | 智商掉了一地&#xff0c;Sheryc_王苏比 SimCLR 更好用的 Self-Supervised Learning&#xff0c;一起来看看吧&#xff01;Self-Supervised Learning作为深度学习中的独孤九剑&#xff0c;当融汇贯通灵活应用之后&#xff0c;也能打败声名在外的武当太极剑。…

5whys分析法在美团工程师中的实践

前言 网站的质量和稳定性对于用户和公司来说至关重要&#xff0c;但是在网站的快速发展过程中&#xff0c;由于各种原因导致事故不可避免的发生&#xff0c;这些大大小小的事故对公司难免会造成一些负面的影响&#xff0c;为了避免同类事故的再次发生&#xff0c;美团的工程师们…

LeetCode 382. 链表随机节点(概率)

1. 题目 给定一个单链表&#xff0c;随机选择链表的一个节点&#xff0c;并返回相应的节点值。保证每个节点被选的概率一样。 进阶: 如果链表十分大且长度未知&#xff0c;如何解决这个问题&#xff1f;你能否使用常数级空间复杂度实现&#xff1f; 来源&#xff1a;力扣&am…

图谱实战 | 斯坦福黄柯鑫:图机器学习在生物图上的应用

转载公众号 | DataFunSummit分享嘉宾&#xff1a;黄柯鑫 斯坦福大学 博士生编辑整理&#xff1a;元玉蒲 西北大学出品平台&#xff1a;DataFunTalk导读&#xff1a;大家好&#xff0c;我叫黄柯鑫。我现在是斯坦福大学的计算机科学博士第一年级&#xff0c;研究方向是机器学习在…

排得更好VS估得更准VS搜的更全「推荐、广告、搜索」算法间到底有什么区别?...

文 | 王喆源 | 王喆的机器学习笔记作为互联网的核心应用“搜广推”&#xff0c;三个方向基本都是互联网公司的标配。各头部公司的搜广推系统也都各自发展成了集成了多种模型、算法、策略的庞然大物&#xff0c;想一口气讲清楚三者的区别并不容易。不过万事总有一个头绪&#xf…

Solr Facet技术的应用与研究

问题背景 在《搜索引擎关键字智能提示的一种实现》一文中介绍过&#xff0c;美团的CRM系统负责管理销售人员的门店(POI)和项目(DEAL)信息&#xff0c;提供统一的检索功能&#xff0c;其索引层采用的是SolrCloud。在用户搜索时&#xff0c;如果能直观地给出每个品类的POI数目&am…

LeetCode 129. 求根到叶子节点数字之和(DFS)

1. 题目 给定一个二叉树&#xff0c;它的每个结点都存放一个 0-9 的数字&#xff0c;每条从根到叶子节点的路径都代表一个数字。 例如&#xff0c;从根到叶子节点路径 1->2->3 代表数字 123。 计算从根到叶子节点生成的所有数字之和。 说明: 叶子节点是指没有子节点的…

推荐精排之锋:FM的一小步,泛化的一大步

文 | 水哥源 | 知乎1.如果说LR是复读机&#xff0c;那么FM可以算作是电子词典2.泛化就是我没见过你&#xff0c;我也能懂你&#xff0c;但是泛化有时候和个性化有点矛盾&#xff0c;属于此消彼长的关系3.实践中的泛化往往来源于拆解&#xff0c;没见过组成的产品&#xff0c;但…

图谱实战 | 阿里周晓欢:如何将实体抽取从生成问题变成匹配问题?

转载公众号 | DataFunSummit分享嘉宾&#xff1a;周晓欢 阿里巴巴 算法专家编辑整理&#xff1a;刘香妍 中南财经政法大学出品平台&#xff1a;DataFunSummit导读&#xff1a;实体抽取或者说命名实体识别 ( NER ) 在信息抽取中扮演着重要角色&#xff0c;常见的实体抽取多是对文…

剖析 Promise 之基础篇

随着浏览器端异步操作复杂程度的日益增加&#xff0c;以及以 Evented I/O 为核心思想的 NodeJS 的持续火爆&#xff0c;Promise、Async 等异步操作封装由于解决了异步编程上面临的诸多挑战&#xff0c;得到了越来越广泛的应用。本文旨在剖析 Promise 的内部机制&#xff0c;从实…

LeetCode 318. 最大单词长度乘积(位运算)

1. 题目 给定一个字符串数组 words&#xff0c;找到 length(word[i]) * length(word[j]) 的最大值&#xff0c;并且这两个单词不含有公共字母。你可以认为每个单词只包含小写字母。如果不存在这样的两个单词&#xff0c;返回 0。 示例 1: 输入: ["abcw","baz&…

百度研究院商业智能实验室招聘研究实习生!

致力于连接最靠谱的算法岗与最强的求职者招聘贴投放请联系微信xixiaoyao-1岗位职责&#xff1a;同实验室的数据科学家和工程师一起参与研发前沿的机器学习技术&#xff0c;主要内容为对前沿技术进行调研&#xff0c;复现前沿科研成果在顶级会议和期刊上发表论文支持及落地百度飞…

论文浅尝 | KGNLI: 知识图谱增强的自然语言推理模型

笔记整理 | 韩振峰&#xff0c;天津大学硕士链接&#xff1a;https://aclanthology.org/2020.coling-main.571.pdf动机自然语言推理 (NLI) 是自然语言处理中的一项重要任务&#xff0c;它旨在识别两个句子之间的逻辑关系。现有的大多数方法都是基于训练语料库来获得语义知识从而…

block在美团iOS的实践

说到block&#xff0c;相信大部分iOS开发者都会想到retain cycle或是__block修饰的变量。 但是本文将忽略这些老生常谈的讨论&#xff0c;而是将重点放在美团iOS在实践中对block的应用&#xff0c;希望能对同行有所助益。 本文假设读者对block有一定的了解。 从闭包说起 在Lisp…

写Rap,编菜谱,你画我猜……这些 AI demo 我可以玩一天!

文 | ZenMoore编 | 小轶上次写的那篇 《Prompt 综述15篇最新论文梳理]》 有亿点点肝。这次给大家整点轻松好玩的&#xff08;顺便给这篇推文打个广告&#xff0c;快去看&#xff01;&#xff09;。不知道读者朋友们有没有遇到这样的情况&#xff1a;有新的论文发表了&#xff0…

LeetCode 1254. 统计封闭岛屿的数目(图的BFS DFS)

文章目录1. 题目2. 解题2.1 DFS2.2 BFS1. 题目 有一个二维矩阵 grid &#xff0c;每个位置要么是陆地&#xff08;记号为 0 &#xff09;要么是水域&#xff08;记号为 1 &#xff09;。 我们从一块陆地出发&#xff0c;每次可以往上下左右 4 个方向相邻区域走&#xff0c;能…

技术动态 | 图对比学习的最新进展

转载公众号 | DataFunSummit 分享嘉宾&#xff1a;朱彦樵 中国科学院自动化研究所编辑整理&#xff1a;吴祺尧 加州大学圣地亚哥分校出品平台&#xff1a;DataFunSummit导读&#xff1a;本文跟大家分享下图自监督学习中最近比较热门的研究方向&#xff1a;图对比学习&#xff0…

如何把Android手机变成一个WIFI下载热点? — 报文转发及DNS报文拦截

随着WiFi的普及&#xff0c;移动运营商的热点也越来越多了&#xff0c;如中国移动的CMCC、中国电信的ChinaNet、中国联通的ChinaUnicom等&#xff0c;一般来说&#xff0c;连上此类的热点&#xff0c;打开浏览器上网时都会自动跳转到一个验证页面&#xff0c;最近有个项目也有类…

OpenKG 祝大家新春快乐

OpenKG 祝各位读者新春快乐&#xff0c;虎虎生威&#xff01;OpenKGOpenKG&#xff08;中文开放知识图谱&#xff09;旨在推动以中文为核心的知识图谱数据的开放、互联及众包&#xff0c;并促进知识图谱算法、工具及平台的开源开放。点击阅读原文&#xff0c;进入 OpenKG 网站。…