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 ... 
