Android 多渠道打包方式详解

Android 多渠道打包方式详解

面试的时候,如果面试官突然问到:你们渠道包是怎么打的?如果你说是用gradle一个一个编译的,然后他很鄙视的说这个效率太低啦,你们写过什么脚本自己打渠道包没?你肯定心里想,卧槽,这么狂炫吊炸天,自己写脚本打包?!其实这个根本也不是太难啦!!今天就来聊聊多渠道打包的原理以及如何自己DIY多渠道打包的工具!

渠道包出现

当一个产品到发版的时候,我们搞Android的就会面临一个超级尴尬的问题:国内这么多的渠道,渠道统计是必须做滴,那么十多个主要渠道再加无限量的地推渠道包就成了一个巨坑了!这一块耗费的时间是一个无底洞啊!!!

方式一览

这里一共会介绍三种渠道包的实现方式,分别是:

1、使用gradle配置直接编译出不同的渠道包。

2、通过反编译修改对应的渠道号。

3、META-INF里面新加一个文件。

Gradle方式

不管是用友盟统计还是其他什么的,首先肯定都是要有一些准备工作的,由于本人就比较了解友盟的,所以就用友盟统计来举例啦!

友盟统计提供了两种渠道统计策略,其实就是一个自动挡的一个手动挡的。

<meta-data

android:name="UMENG_APPKEY"

android:value="xxxxxxxx"/>

<meta-data

android:name="UMENG_CHANNEL"

android:value="${GRADLE_CHANNEL_VALUE}"/>

在对应的build.gradle里面配置对应的信息:

productFlavors.all { flavor ->

flavor.manifestPlaceholders = [GRADLE_CHANNEL_VALUE: name]

}

productFlavors {

dev {

}

baidu {

minSdkVersion 18

applicationId "com.test.michat"

}

}

如果手动去设置对应的渠道号的话,就在程序入口处调用以下方法:

MobclickAgent. startWithConfigure(UMAnalyticsConfig config)

UMAnalyticsConfig(Context context, String appkey, String channelId)

UMAnalyticsConfig(Context context, String appkey, String channelId, EScenarioType eType)

UMAnalyticsConfig(Context context, String appkey, String channelId, EScenarioType eType,Boolean isCrashEnable)

那么怎么获取到对应的渠道号呢?!这个方法在之后的所有方式中都要使用滴,其实不管是哪种方式,最后都会调用这个方法去读相关数据的!!

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_VALUE");

} catch (PackageManager.NameNotFoundException ignored) {

}

return "";

}

Android 多渠道打包方式详解(上)

buildVariants.png

当然你也可以使用命令行:gradlew assemble 组装出所有的渠道包!!

反编译方式

gradle方式用着也挺不错的,为什么还要去搞什么反编译这么麻烦的东西呢?因为它有一个很大的问题,那就是每一个包都是要去编译打包的!这是相当的耗时!time is 加班啊!谁也不想加班打渠道包咯!!反编译的方式就是节省了每个渠道包都去编译的时间,而是编译好一个渠道包之后就使用该渠道包,通过反编译动态修改AndroidManifest.xml里面的信息,然后再重新打包签名!

说到反编译,那么这里就不得不提大名鼎鼎的apktool.jar了!纳尼,你说你从未听说过?!没事儿,以前没有听过,现在会用了就行了!!

然后总结一下接下来的一系列套路:

解包->修改相关参数->打包->签名->Zipalign优化

1、解包

apktool d your_original_apk build

你没有看错,就是这样的!因为我们是站在巨人的肩膀上工作的嘛,所以好多工作就不同自己搞了!

执行以上命令之后,如果不出什么意外,你就会得到一个文件夹:

Android 多渠道打包方式详解(上)

相关代码:

try {

brut.apktool.Main.main(new String[]{"d", "-f", apkFilePath, "-o", outPath});

return true;

} catch (Exception e) {

e.printStackTrace();

callback("解包失败 !!!!!\r\n" + e.getMessage());

}

2、修改对应的参数

打开对应的AndroidManifest.xml,你没有看错,什么都在里面,直接修改就好了!等等,xml解析你不会?!没有关系,这里有dom4j.jar给你使用啦!!

修改反编译之后的AndroidManifest文件相关代码

try {

File androidManifestFile = new File(appFolderName + File.separator + "AndroidManifest.xml");

Document document = new SAXReader().read(androidManifestFile);//使用dom4j的sax解析

Element element = document.getRootElement().element("application");

List<Element> list = element.elements("meta-data");//获取到所有的“meta-data”

List<MetaData> metaData = manifest.getMetaData();

boolean isUpdate = false;

for (MetaData data : metaData) {

String name = data.getName();

String value = data.getValue();

callback(" meta-data name=‘" + name + "‘ value=‘" + value + "‘");

for (Element s : list) {

Attribute attribute = s.attribute("name");

//更新相关渠道号

if ( "UMENG_CHANNEL".equals(name)&&"UMENG_CHANNEL".equals(attribute.getValue())) {//更换相关的渠道号

s.attribute("value").setValue(value);

isUpdate = true;

callback("更新1 AndroidManifest.xml meta-data name=‘" + attribute.getValue() + "‘ value=‘" + value + "‘");

break;

}

}

}

if(isUpdate){//更新后重新写入

XMLWriter writer = new XMLWriter(new FileOutputStream(androidManifestFile));

writer.write(document);

writer.close();

callback("更新 AndroidManifest.xml 完成 ~ ");

}

} catch (Exception e) {

e.printStackTrace();

return false;

}

3、打包

apktool b build your_unsigned_apk

还是这么简单:

try {

brut.apktool.Main.main(new String[]{"b", buildApkFolderPath, "-o", buildApkOutPath});

return true;

} catch (Exception e) {

e.printStackTrace();

callback("打包失败 !!!!!\r\n" + e.getMessage());

}

4、签名

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

这个是jdk里面直接提供了的,只要你的环境变量配置好了的,就没有什么问题啦!重新签名相关代码

executeCommand("jarsigner", "-verbose", "-sigalg", "SHA1withRSA", "-digestalg", "SHA1", "-keystore", keystoreFilePath, apkFilePath, alias, "-storepass", password);

/**

* 执行命令

*

* @param command 命令

*/

private synchronized boolean executeCommand(String... command) {

Process process = null;

BufferedReader reader = null;

try {

ProcessBuilder builder = new ProcessBuilder();

builder.command(command);

builder.redirectErrorStream(true);

process = builder.start();

reader = new BufferedReader(new InputStreamReader(process.getInputStream(),"UTF-8"));

String line;

while ((line = reader.readLine()) != null) {

callback(line);

if (line.contains("Exception") || line.contains("Unable to open")) {

return false;

}

}

return true;

} catch (IOException e) {

e.printStackTrace();

callback(e.getMessage());

} finally {

close(reader);

if (process != null) {

process.destroy();

}

}

return false;

}

5、Zipalign优化

Android 多渠道打包方式详解(上)

如图所示,sdk/build-tools里面每个版本都是有这个东西的,加到环境变量中就好了!!!

稿源:勤快学QKXue.NET

扩展阅读:

Android 多渠道打包方式详解(上):http://qkxue.net/info/25417/Android
Android 多渠道打包方式详解(下):http://qkxue.net/info/25418/Android

时间: 2024-08-06 07:55:23

Android 多渠道打包方式详解的相关文章

Gradle实战:Android多渠道打包方案汇总

查看原文:http://blog.csdn.net/u010818425/article/details/52319382 Gradle实战系列文章: <Gradle基本知识点与常用配置> <Gradle实战:不同编译类型的包同设备共存> <Gradle实战:发布aar包到maven仓库> <Gradle实战:执行sql操作hive数据库> 本文将延续之前几篇博客的风格,先从基本概念入手,这有助于我们对后文的理解: 在后续的代码中如果忘了某个概念的具体意义,

android adb 的各种使用方式详解

这篇文章主要介绍在windows 程序中使用adb 的方法,不介绍adb 的命令. 1) 启动adb 进程,从管道获取输出. 这种方式的弊端有多少,我也不知道,反正就是各种问题吧.但是目前我问过很多朋友,他们都是这么做的,因为这种方法最简单.弊端我列举一下 1) 每次执行一个adb 命令都要启动一个adb 进程,速度太慢,好像就是很不爽 2)  偶尔发现进程管理器中有N 多个adb 进程,然后就卡了. 3)  从管道获取输出,在很多情况下会发现adb 卡死了,进程退不出来. 4)  曾经发现 a

Android中的几种网络请求方式详解

http://blog.csdn.net/zuolongsnail/article/details/6373051 Android应用中使用AsyncHttpClient来异步网络数据 http://blog.csdn.net/sdvch/article/details/13615605 Android中的几种网络请求方式详解,布布扣,bubuko.com

给 Android 开发者的 RxJava 详解

作者:扔物线 前言 我从去年开始使用 RxJava ,到现在一年多了.今年加入了 Flipboard 后,看到 Flipboard 的 Android 项目也在使用 RxJava ,并且使用的场景越来越多 .而最近这几个月,我也发现国内越来越多的人开始提及 RxJava .有人说『RxJava 真是太好用了』,有人说『RxJava 真是太难用了』,另外更多的人表示:我真的百度了也谷歌了,但我还是想问: RxJava 到底是什么? 鉴于 RxJava 目前这种既火爆又神秘的现状,而我又在一年的使用

CSDN Android客户端开发(二):详解如何基于Java用Jsoup爬虫HTML数据

本文参考链接详细介绍如何使用Jsoup包抓取HTML数据,是一个纯java工程,并将其打包成jar包.希望了解如何用java语言爬虫网页的可以看下. 杂家前文就又介绍用HTTP访问百度主页得到html的string字符串,但html的文本数据如果不经过处理就是个文本字符串没有任何效果的.所谓的浏览器就是负责将文本的html"翻译"成看到的界面.在前文有介绍,这个csdn的客户端app分首页.业界.移动.研发.程序员.云计算五大类.以业界为例,http://news.csdn.net/ 

Android.mk 文件语法详解

转:http://blog.sina.com.cn/s/blog_602f8770010148ce.html ===================================================================================== 0. Android.mk简介: Android.mk文件用来告知NDK Build 系统关于Source的信息. Android.mk将是GNU Makefile的一部分,且将被Build System解析一次或多次

转:给 Android 开发者的 RxJava 详解

转自:  http://gank.io/post/560e15be2dca930e00da1083 评注:多图解析,但是我还是未看懂. 前言 我从去年开始使用 RxJava ,到现在一年多了.今年加入了 Flipboard 后,看到 Flipboard 的 Android 项目也在使用 RxJava ,并且使用的场景越来越多 .而最近这几个月,我也发现国内越来越多的人开始提及 RxJava .有人说『RxJava 真是太好用了』,有人说『RxJava 真是太难用了』,另外更多的人表示:我真的百度

Android:ViewPager扩展详解——带有导航的ViewPagerIndicator(附带图片缓存,异步加载图片)

大家都用过viewpager了, github上有对viewpager进行扩展,导航风格更加丰富,这个开源项目是ViewPagerIndicator,很好用,但是例子比较简单,实际用起来要进行很多扩展,比如在fragment里进行图片缓存和图片异步加载. 下面是ViewPagerIndicator源码运行后的效果,大家也都看过了,我多此一举截几张图: 下载源码请点击这里 ===========================================华丽的分割线==============

Android四大组件--Activity详解

Android四大组件--Activity详解 分类: android android应用android开发 本文的主要内容包括1.activity的建立.配置和使用:2.activity的跳转和传值:3.startActivityForResult:4.activity的生命周期. 1.activity的建立.配置和使用 Activity是一个应用中的组件,它为用户提供一个可视的界面,方便用户操作,比如说拔打电话.照相.发邮件或者是浏览地图等.每个activity会提供一个可视的窗口,一般情况