Android批量打包-如何一秒内打完几百个apk渠道包
在国内Android常用渠道可能多达几十个,如:
谷歌市场、腾讯应用宝、百度手机助手、91手机商城、360应用平台、豌豆荚、安卓市场、小米、魅族商店、oppo手机、联想乐商、中兴汇天地、华为、安智、应用汇、木蚂蚁、3G安卓市场(久邦开发者发布系统)
uc应用商店、苏宁应用、淘宝手机助手、蘑菇市场、搜狗市场、搜狗助手、机锋、易用汇(金立手机)、中国联通沃商、中国移动MM、中国电信天翼、亿优市场、历趣世界、冒泡堂、网讯安卓开发者平台、桌乐、网易、泡椒网、十字猫、酷传、安粉、安卓园、安卓之家
所以在工作中,当项目开发、测试完毕后就需要针对不同的渠道打出对应的apk安装包。为了统计每个渠道效果,我们可以使用Umeng sdk或者百度的sdk。这些sdk的使用我就不再这里赘述了,请看相应的开发文档即可。本文以友盟统计为例。
批量打包方式一:Gradle方式
我相信现在应该很多开发环境都是AndroidStudio了,对Gradle相对还是熟悉的。如果您使用的是Eclipse也没有关系,用AndroidStudio导入Eclipse工程,或者把gradle配置放在Eclipse工程下(因为AndroidStudio和Eclipse的工程目录有些差别,把对应的目录配置对即可)
首先我们使用AndroidStudio新建一个工程,名叫AndroidBatchApk,工程结构如下:
打开AndroidManifest.xml文件 添加友盟的渠道配置如下:
在MainActivity 显示渠道名代码:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String channel = ManifestUtil.getMetaDataFromAppication(this, "UMENG_CHANNEL");
//String channel = ManifestUtil.getUmengChannel(this);
((TextView) findViewById(R.id.tv_channel)).setText(channel);
}
}
<meta-data
android:name="UMENG_APPKEY"
android:value="Your UMENG_APPKEY" />
<meta-data
android:name="UMENG_CHANNEL"
android:value="${UMENG_CHANNEL_VALUE}" /> //${UMENG_CHANNEL_VALUE}是个占位符
打开app目录下的build.gradle文件,修改成如下形式:
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
packagingOptions {
exclude 'META-INF/NOTICE.txt'
exclude 'META-INF/LICENSE.txt'
}
//签名
signingConfigs {
release {
//storeFile file("../yourapp.keystore")
storeFile file("keystore_apk.jks")
storePassword "123456"
keyAlias "apk"
keyPassword "123456"
}
}
buildTypes {
release {
// 不显示Log
//buildConfigField "boolean", "LOG_DEBUG", "false"
//minifyEnabled true //混淆
zipAlignEnabled true //内存对齐
shrinkResources true //移除无用的resource文件
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
android.applicationVariants.all { variant ->
def stringsFile = new File(variant.outputs[0].processResources.assetsDir, "abc.txt")
stringsFile.mkdir()
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def fileName = "APK_${releaseTime()}_${variant.productFlavors[0].name}.apk"
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
}
}
lintOptions {
checkReleaseBuilds false
abortOnError false
ignoreWarnings true
}
// 渠道列表
productFlavors {
_360 {}
_91 {}
QQ {}
appChina {}
baidu {}
google {}
//.....
}
productFlavors.all { flavor ->
flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
}
}
def releaseTime() {
return new Date().format("yyyy-MM-dd HH-mm-ss", TimeZone.getTimeZone("GMT+8"))
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.1'
}
上面的配置,我们测试打6个包,分别是google 、_360、 _91、 appChina、 QQ、 baidu
打开cmd命令行 进入工程所在的目录,输入命令:gradle build 不出意外将看到如下成功界面:
并且在output目录下生成了我们要的apk包(AndroidBatchApk\app\build\outputs\apk)
现在用的安装我们的生成apk文件,安装google渠道的apk。
到这里我们就通过gradle方式成功的批量打包了,
时间我们只花费了25秒,但是这是最简单的工程,如果是实际的开发中,我们的项目会很大,打包的时间也会花费很长时间,我现在公司的项目,通过这种方式打包,需要30、40分钟左右,这也是挺长的。时间上并不占优势。但是比我们用工具一个个的打apk强太多了。下面为大家界面一种更高效的打包方式。
批量打包方式二:Python批量打包
首先配置好Python,我用的是Python2.7版本。使用该方式,不把渠道名称放在AndroidManifest.xml 里,而是新建一个空文件,文件名就是渠道名称。该文件放在apk目录的META-INF里。META-INF目录下默认文件列表如下:
现在我们要解决两个问题:
如果在META-INF目录下新建文件?
我们解决第一个问题。首先我们通过AndroidStudio或者Eclipse打一个正式环境的apk安装包,不需要有渠道。
然后按照渠道列表 复制出各个渠道的,然后往apk文件里写入文件为渠道名的空文件。我们使用Python代码来实现该功能,代码如下:
import sys,os,shutil,zipfile,time
apkVersion="1.0"
srcFileName="source.apk"
destDir=os.path.abspath('.')
file=open("channel.txt")
def writeChannelToApk(filename,channel):
z=zipfile.ZipFile(filename,'a',zipfile.ZIP_DEFLATED)
empty_channel_file="META-INF/channel_{channe}".format(channe=channel)
target_file="channel.apk"
z.write(target_file,empty_channel_file)
z.close()
print "writeChannelToApkchannel"+channel+","+filename+"\n"
def cpFile(srcPath,fileName):
destPath = destDir + os.path.sep + fileName
if os.path.exists(srcPath) and not os.path.exists(destPath):
shutil.copy(srcPath,destPath)
if not os.path.exists(srcFileName):
print "sourcefile"+srcFileName+"notexists"
sys.exit(1)
start = time.clock()
for line in file:
channel=line.strip('\n').strip()
targetFileName="apk_"+channel+"-"+apkVersion+".apk"
print "copyfile:"+targetFileName
cpFile(srcFileName,targetFileName)
writeChannelToApk(targetFileName,channel)
end = time.clock()
print("The function run time is : %.03f seconds" %(end-start))
上面是我编写的Python代码,根据代码我们需要三个文件,一个我们打出的apk文件(source.apk 当然名字可以改)、一个空apk文件(channel.apk)和渠道列表文件(channel.txt) 目录如下:
渠道文件内容如下:
360
appChina
wandoujia
91
baidu
QQ
3G
eoe
anzhi
163
hiapk
jifeng
xiaomi
meizu
oppo
lenovo
在命令行输入:python batch_apk.py 回车
瞬间完成:
解压文件oppo渠道的apk,看看是不是META-INF下是不是有渠道文件:
如果读取META-INF下的渠道文件?
public class ManifestUtil {
public static String channel;
public static String getUmengChannel(Context context) {
//return getMetaDataFromAppication(context, "UMENG_CHANNEL");
return getChannel(context);
}
/**
* 获取META-INFO下面的渠道
* @param context
* @return
*/
public static String getChannel(Context context) {
if (!TextUtils.isEmpty(channel)) {
return channel;
}
ApplicationInfo appinfo = context.getApplicationInfo();
String sourceDir = appinfo.sourceDir;
ZipFile zipfile = null;
final String start_flag = "META-INF/channel_";
try {
zipfile = new ZipFile(sourceDir);
Enumeration<?> entries = zipfile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = ((ZipEntry) entries.nextElement());
String entryName = entry.getName();
if (entryName.contains(start_flag)) {
channel = entryName.replaceAll(start_flag, "");
return channel;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (zipfile != null) {
try {
zipfile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return "";
}
}
我们安装oppo渠道的apk看看能否读取到渠道名:
通过上面的对比,使用Pyhon往META-INF写入渠道的方式,比gradle方式极大的提高了效率。
Have Fun !
Android批量打包-如何一秒内打完几百个apk渠道包的更多相关文章
- Android 批量打包利器
因为添加了渠道号,对应不同的渠道包,此时,动不动就几十个包,实在让人头疼,此时,需要引入自动打包功能. 首先,列举出援引的博客内容 美团Android自动化之旅—生成渠道包 http://tech.m ...
- Ant自动化打多渠道包,Android批量打包提速
Eclipse用起来虽然方便,但是编译打包android项目还是比较慢,尤其将应用打包发布到各个渠道时,用Eclipse手动打包各种渠道包就有点不切实际了,这时候我们用到Ant帮我们自动编译打包了. ...
- Android批量打包提速 - 1分钟900个市场不是梦
版权声明: 欢迎转载,但请保留文章原始出处 作者:GavinCT 出处:http://www.cnblogs.com/ct2011/p/4152323.html 黎明前的黑暗 使用Ant或者Gradl ...
- 【转】安装Intel HAXM为Android 模拟器加速,30秒内启动完成
http://www.cnblogs.com/Li-Cheng/p/4351966.html http://www.cnblogs.com/csulennon/p/4178404.html https ...
- 安装Intel HAXM为Android 模拟器加速,30秒内启动完成
要求 必备知识 windows 7 基本操作. 运行环境 windows 7(64位); Android Studio 1.1.0;JDK 1.7.0_75(64位);android-sdk_r24 ...
- 基于apktool项目的android批量打包工具,多平台支持
好久木有写博客了,今天有点兴致就写一下,献上一个没怎么用的批量打包工具,python实现的,虽然说现在android的批量打包有一个很好的工具可以使用gradle,这个灰常牛叉的工具和android ...
- android批量打包
http://blog.csdn.net/johnny901114/article/details/48714849
- Android几种常见的多渠道(批量)打包方式介绍
多渠道打包,主要是为了统计不同的渠道上包的下载数量,渠道越多,我们需要打的包数量越多,这个时候,我们没法去使用单纯的手动打包去一个一个的生成不同的渠道包,我们需要更高效的打包方式. 声明渠道方式一: ...
- 新一代开源Android渠道包生成工具Walle
本文转自:http://tech.meituan.com/android-apk-v2-signature-scheme.html 新一代开源Android渠道包生成工具Walle 新的应用签名方案A ...
随机推荐
- 【bzoj4444 scoi2015】国旗计划
题目描述 A 国正在开展一项伟大的计划 —— 国旗计划.这项计划的内容是边防战士手举国旗环绕边境线奔袭一圈.这项计划需要多名边防战士以接力的形式共同完成,为此,国土安全局已经挑选了 NN 名优秀的边防 ...
- 【Uva 11280 飞到弗雷德里顿】
·你可以尽情地坐飞机,但停留次数遭到限制. ·英文题,述大意: 给出一张有向图,起点是输入的第一个城市,终点是输入的最后一个城市.给出q个询问,每个询问含一个t,表示 #include&l ...
- Linux查看Tomcat是否多次重启命令
1.查看命令 ps -ef|grep apache-tomcat-9090|grep -v grep|awk '{print $2}' 如果存在两个端口则多次重启, 2.停掉命令: kill -9 ...
- 入口开始,解读Vue源码(一)-- 造物创世
Why? 网上现有的Vue源码解析文章一搜一大批,但是为什么我还要去做这样的事情呢?因为觉得纸上得来终觉浅,绝知此事要躬行. 然后平时的项目也主要是Vue,在使用Vue的过程中,也对其一些约定产生了一 ...
- Linux/Centos笔记目录
Linux介绍 Linux入门--个人感想 Google怎么用linux 初入Linux Windows XP硬盘安装Ubuntu 12.04双系统图文详解 实例讲解虚拟机3种网络模式(桥接. ...
- ionic 禁用 手势 滑动返回
$ionicConfigProvider.views.swipeBackEnabled(false); 在 应用的 config里面 配置下 上面的那句话 就OK了.
- 重构:从Promise到Async/Await
摘要: 夸张点说,技术的发展与历史一样,顺之者昌,逆之者亡.JS开发者们,赶紧拥抱Async/Await吧! GitHub仓库: Fundebug/promise-asyncawait 早在半年多之前 ...
- web缓存之--http缓存机制
一.web缓存可以分为数据库缓存.代理服务器缓存.浏览器缓存. 其中浏览器缓存又包含很多内容:http缓存.indexDb.cookie.localStorage等.本片只讨论http缓存相关内容. ...
- Java关键字---this的由来和其三大作用
[声明]欢迎转载,但请保留文章原始出处→_→ 秦学苦练:http://www.cnblogs.com/Qinstudy/ 文章来源:http://www.cnblogs.com/Qinstudy/p/ ...
- JS的replace默认只替换第一个匹配项
1. JS的replace默认只替换第一个匹配项. 解决方法: 使用正则表达式进行匹配替换[ ①.replace(new RegExp(②,"g") ,③); ] ①:包含 ...