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 ...
随机推荐
- C++traits——STL源码剖析
有时候我们希望知道迭代器所指的元素类型. 以迭代器所指声明对象: template<typename Iterator, typename T> void func_impl(Iterat ...
- SQL Server 连接 MySQL
1.在SQL SERVER服务器上安装MYSQL ODBC驱动; 驱动下载地址:http://dev.mysql.com/downloads/connector/odbc/ 2.安装好后,在管理工具- ...
- c++ primer第15章这几个例子中的构造函数形式不太理解
//向基类构造函数传递实参p491 class Bulk_item : public Item_base{ public: Bulk_item(,double disc_rate = 0.0): It ...
- 《Java技术》第三次作业--面向对象——继承、抽象类、接口
1.阅读下面程序,分析是否能编译通过?如果不能,说明原因.应该如何修改?程序的运行结果是什么?为什么子类的构造方法在运行之前,必须调用父 类的构造方法?能不能反过来? class Grandparen ...
- java异常处理之throw, throws,try和catch
转自 http://blog.csdn.net/zhouyong80/article/details/1907799 程序运行过程中可能会出现异常情况,比如被0除.对负数计算平方根等,还有可能会出现 ...
- idea和androidstudio的首次git配置一些问题
网上都有很清楚的步骤 但是 都是教怎么使用 但是对第一次应用idea内部vcs的git 则很少有详细说明 首先要在网上创建个项目 然后本地git clone下来 不建议内部vcs的fetch from ...
- UML总结4---UML九种图关系说明
转自:http://blog.csdn.NET/chenyujing1234/article/details/8173519 UML中包括九种图:用例图.类图.对象图.状态图.时序图.协作图.活动图. ...
- 面向对象+canvas 倒计时
效果参照网上的,用面向对象改写了一下,只写了自己需要的部分. 1.效果: 实现: //html <canvas id="canvas" width="800px&q ...
- java中的构造,封装
今天给大家讲一下面向对象中的构造,封装: 构造:构造方法有以下几个特点:1.方法名和类名一致.2.无返回类型.接下来的几种构造样式,直接上代码吧: //这是一个宠物类 有一个属性:名字(name) p ...
- Android POJO 转换器 —> RapidOOO
博客搬迁至https://blog.wangjiegulu.com RSS订阅:https://blog.wangjiegulu.com/feed.xml 原文链接:https://blog.wang ...