当前位置 : 首页 » 博文聚焦 » 正文

Android中利用ant进行多渠道循环批量打包

分类 : 博文聚焦 | 发布时间 : 2013-09-11 15:24:43 | 浏览 : 690

目前国内的安卓渠道有几百家,我们要根据不同的渠道打不同渠道的apk来统计每个渠道带来的用户数,统计每个渠道用户的存活率和活跃度等等信息,但是手动对每个渠道的APK进行签名打包实在是让人感到厌烦且低效,这时我们需要一个全自动化的打包工具----ant。Android SDK的tools中已经包括了ant的打包工具,那么我们该如何运用它达到我们的要求呢?之前卤煮做这块的时候也参考了很多前辈的文章,首先向前辈们致敬,下面说下卤煮的方法,有什么不对的地方或者疑问欢迎大家留言交流。(以下步骤均在MAC系统下完成)

一.打包前准备工作

1.首先确定你的JDK版本为1.6!

2.在AndroidManifest.xml中application标签下添加一个用来识别渠道的标签:

<meta-data  android:name="qudao"  android:value="channel" />

3.为了让ant支持循环功能,我们要在Android SDK/tools/lib下放一个ant-contrib-1.0b3.jar包

4.项目中放置第三方jar包的文件夹必须叫libs而不是lib

 

二.build.xml等文件的生成和配置

1.通过终端(cmd)命令自动生成build.xml和local.properties两个文件,方法如下:

<sdk>/tools/android update project -p <project> -t <target>

例如:

/Users/moushou/Downloads/AndroidSDK/tools/android update project -p /Users/moushou/Documents/workspace/HelloWorld -t 14

其中<sdk>为SDK全路径,<project>为项目全路径,<target>为API版本。

执行完成截图如下:

执行完成后,Refresh你的项目就会发现项目的根目录下多了两个文件:build.xml和local.properties

其中local.properties的内容是:

复制代码
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.

# location of the SDK. This is only used by Ant
# For customization when using a Version Control System, please read the
# header note.
sdk.dir=/Users/moushou/Downloads/AndroidSDK
复制代码

project.properties的内容如下:

复制代码
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system use,
# "ant.properties", and override values to adapt the script to your
# project structure.
#proguard.config=proguard.cfg
# Project target.
target=Google Inc.:Google APIs:14
proguard.config=proguard.cfg
复制代码

项目的目录结构如下图所示:

:project.properties中target=GoogleInc.:GoogleAPIs:14代表所使用的SDK的版本,可进行手动修改。

2.手动为项目新建一个File,该文件名为:ant.properties,创建完成项目的目录结构如下图:

创建完成后在ant.properties中添加如下内容:

复制代码
key.store=<keystore>
key.alias=<key>
key.store.password=<keystore pwd>
key.alias.password=<key pwd>
market_channels=xx,yy,zz
app_version=1_0_build_0
复制代码

例如:

复制代码
key.store=/Users/moushou/Desktop/qianming
key.alias=meilihuaduo
key.store.password=123456xx
key.alias.password=123456xx 
market_channels=anzhuoshichang,jifengshichang,baiduyingyongzhongxin
app_version=1_0_build_0
复制代码

其中:

keystore为签名文件的全路径。

key.alias为签名需要使用的私钥。

key.store.password为私钥库的密码。

key.alias.password为私钥的密码。

market_channels为渠道集合。

app_version为apk的版本(此字段可根据自己喜好编写)。

 

--------------------------------------------------------------------------------------------------

 

至此,除build.xml外,其余文件配置完成,夜深人静的让我有些犯困啦,明天会把build.xml中使用for循环替换AndroidManifest.xml中渠道value的方法分享给大家。


三.下面我来说下build.xml的编写方法:

1.修改build.xml的第二行,修改方法如下:

<project name="HelloWorld" default="release">

其中name为你项目的名称,default设置为release。

2.循环替换AndroidManifest.xml中qudao的value值并进行自动签名打包,方法如下:

复制代码
 1 <import file="${sdk.dir}/tools/ant/build.xml" />
 2     <property name="out.unaligned.dir" value="/Users/moushou/Desktop/HelloWorld_${app_version}/" />
 3     <mkdir dir="${out.unaligned.dir}" />
 4     <target name="modify_update_file">
 5         <echo>*********************** make channel ${channel}</echo>
 6         
 7         <replaceregexp file="AndroidManifest.xml"
 8             match='channel'
 9             replace='${channel}'
10             byline="false"
11             encoding="utf-8"
12         />
13         <property name="out.unaligned.file" location="${out.unaligned.dir}/HelloWorld_${app_version}_${channel}_android.apk"/>
14         
15     </target>
16 
17     <target name="make_one_channels" depends="savemanifest,modify_update_file,release,replacemanifest,deletebin" description="description">
18     </target>
19 
20     <target name="replacemanifest">
21         <echo>*********************** replacemanifest</echo>
22         <delete file="${basedir}\AndroidManifest.xml"/>
23         <copy file="..\temp\build\META-INF\AndroidManifest.xml" todir="${basedir}" encoding="utf-8"/>
24     </target>
25 
26     <target name="savemanifest">
27         <echo>*********************** savemanifest</echo>
28         <copy file="${basedir}\AndroidManifest.xml" todir="..\temp\build\META-INF" encoding="utf-8" />
29     </target>
30 
31     <target name="deletebin">
32         <delete dir="${basedir}\bin" />
33     </target>
34 
35     <taskdef name="foreach" classname="net.sf.antcontrib.logic.ForEach" classpath="/Users/moushou/Downloads/AndroidSDK/tools/lib/ant-contrib-1.0b3.jar" />
36     <target name="make_channels">
37         <foreach target="make_one_channels" list="${market_channels}" delimiter="," param="channel">
38         </foreach>
39     </target>
复制代码

其中:

1.out.unaligned.dir的value值为apk输出文件夹的绝对路径,文件夹采用HelloWorld结合app_version命名,app_version为ant.properties中的app_version

2.out.unaligned.file的location为apk最终的输出路径,apk命名采用HelloWorld加app_version加当前的channel加android方式

3.说一下打包的过程:

(1)第36行make_channels的target是ant的入口,该target中使用foreach循环调用名为make_one_channels的target(第17行)并把market_channels集合中的每个值替换给channel

(2)make_one_channels的target指定了每次打包的过程:

   savemanifest:打包前先将原始的AndroidManifest.xml复制到与项目同一层级目录下的temp下build下META-INF中

   modify_update_file:匹配到AndroidManifest.xml中的channel并将其替换

   release:自动编译加签名

   replacemanifest:删除AndroidManifest.xml,将temp/build/META-INF中的原始AndroidManifest.xml复制回项目根目录下

   deletebin:删除bin文件(:这步很重要,否则只能打出一个渠道的APK,当时做这块的时候碰到的问题)

4.第35行taskdef标签下的classpath是ant-contrib-1.0b3.jar的绝对路径

 

四.打包方法的使用

打开终端(cmd),执行:

cd /Users/moushou/Documents/workspace/HelloWorld

然后执行:

ant make_channels

此时,打包就开始进行啦!当出现BUILD SUCCESSFUL代表打包成功!如下图所示:

此时你会发现你输出的文件夹中多了三个APK,如下图:

 1.每次打包前一定要删除掉temp/build/META-INF中的AndroidManifest.xml,特别是在给不同项目做打包时

   2.打包前请检查AndroidManifest.xml中qudao的value值是否为channel,特别是打包失败后再次重新打包的时候一定要将value值改为channel

   3.如果打包时出现Cannot recover key错误导致BUILD FAILD的话,请检查ant.properties中key.alias.password的值后面是否有多余的空格!有的话请把空格删除掉!

 

五.在代码中获取渠道值,方法如下:

复制代码
       try {
                 ApplicationInfo appInfo = getPackageManager().getApplicationInfo
                         (getPackageName(),PackageManager.GET_META_DATA);
                 qudao = appInfo.metaData.getString("qudao");
            } catch (NameNotFoundException e) {
                e.printStackTrace();
            }
复制代码

 

参考:http://www.cnblogs.com/MrShi/archive/2013/04/16/3023485.html

相关阅读:

What is 'Context' on Android?

Location of sqlite database on the device

Set the layout weight of a TextView programmatically

Disabling of EditText in android

How to print all key and values from HashMap in Android?

How To Set Text In An EditText

With android studio no jvm found, JAVA_HOME has been set

ADB Android Device Unauthorized

How to insert a SQLite record with a datetime set to 'now' in Android application?

XXHDPI and XXXHDPI dimensions in dp for images and icons in android