Mac中用Ant实现Android的批量打包碰到的一些问题以及解决方法
Hello!各位新年好!
昨天下午开始上班,开始整理以前的笔记,留个印记,以免遗忘,当然若能对别人有帮助也再好不过了,今日深圳天气好的不像话,阳光透过玻璃洒在脸上,舒爽!
首先打包需要准备的情况:
1,Ant和JDK得安装好了,Ant去官网下http://ant.apache.org/
测试java环境,在控制台输入java -version
返回java版本号则表示成功
java version "1.6.0_65"
Java(TM) SE Runtime Environment (build 1.6.0_65-b14-466.1-11M4716)
Java HotSpot(TM) 64-Bit Server VM (build 20.65-b04-466.1, mixed mode)
测试ant安装成功了没有,在控制台输入ant回车如果显示如下则表示成功
Buildfile: build.xml does not exist!
Build failed
2,Android SDK下的 /sdk/tools/ant/build.xml
这个文件得存在,如果不存在则是你的ADT可能不完善,最好是找别人把SDK下的ant这个文件传给你,或者自己重新下一个ADT
3,在/sdk/tools/lib
下放一个ant-contrib-1.0b3.jar包,如果没有则去下载1.0b3
4,项目中放置第三方jar包的文件夹不能是lib以免冲突
5,在AndroidManifest.xml中application标签下添加一个用来识别渠道的标签,比如
<meta-data android:name="UMENG_CHANNEL" android:value=“channel" />
以上准备工作完成后,接下来按照步骤来一步一步实现批量打包:
通过终端(cmd)命令自动生成build.xml和local.properties两个文件,方法如下:
[sdk]/tools/android update project -p [project] -t [target]
例如:
/Users/hl/Develop/adt-l/sdk/tools/android update project -p /Users/hl/Documents/workspace/AA -t 19
其中[sdk]为SDK全路径,[project]为项目全路径,[target]为API版本。
注:如果提示 Error: Target id ‘19’ is not valid. Use ‘android list targets’ to get the target ids.
那么就执行一下 /Users/hl/Develop/adt-l/sdk/tools/android list target 这条命令
[sdk] list target
我的执行后返回是:
Available Android targets:
----------
id: 1 or "android-8"
Name: Android 2.2
Type: Platform
API level: 8
Revision: 3
Skins: HVGA, QVGA, WQVGA400, WQVGA432, WVGA800 (default), WVGA854
Tag/ABIs : default/armeabi
----------
id: 2 or "android-18"
Name: Android 4.3.1
Type: Platform
API level: 18
Revision: 3
Skins: HVGA, QVGA, WQVGA400, WQVGA432, WSVGA, WVGA800 (default), WVGA854, WXGA720, WXGA800, WXGA800-7in
Tag/ABIs : default/armeabi-v7a
----------
id: 3 or "android-19"
Name: Android 4.4.2
Type: Platform
API level: 19
Revision: 4
Skins: HVGA, QVGA, WQVGA400, WQVGA432, WSVGA, WVGA800 (default), WVGA854, WXGA720, WXGA800, WXGA800-7in
Tag/ABIs : default/armeabi-v7a
----------
id: 4 or "android-21"
Name: Android 5.0.1
Type: Platform
API level: 21
Revision: 2
Skins: HVGA, QVGA, WQVGA400, WQVGA432, WSVGA, WVGA800 (default), WVGA854, WXGA720, WXGA800, WXGA800-7in
Tag/ABIs : no ABIs.
----------
id: 5 or "Google Inc.:Google APIs:8"
Name: Google APIs
Type: Add-On
Vendor: Google Inc.
Revision: 2
Description: Android + Google APIs
Based on Android 2.2 (API level 8)
Libraries:
* com.google.android.maps (maps.jar)
API for Google Maps
Skins: HVGA, QVGA, WQVGA400, WQVGA432, WVGA800 (default), WVGA854
Tag/ABIs : default/armeabi
----------
id: 6 or "Google Inc.:Google APIs:18"
Name: Google APIs
Type: Add-On
Vendor: Google Inc.
Revision: 3
Description: Android + Google APIs
Based on Android 4.3.1 (API level 18)
Libraries:
* com.android.future.usb.accessory (usb.jar)
API for USB Accessories
* com.google.android.media.effects (effects.jar)
Collection of video effects
* com.google.android.maps (maps.jar)
API for Google Maps
Skins: HVGA, QVGA, WQVGA400, WQVGA432, WSVGA, WVGA800 (default), WVGA854, WXGA720, WXGA800, WXGA800-7in
Tag/ABIs : default/armeabi-v7a
此时我们把id改为6就可以运行了,如下图
执行完成后,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/hl/Develop/adt-l/sdk
build.xml
的内容如下`
<?xml version="1.0" encoding="UTF-8"?>
<project name="SplashAcivity" default="help">
<!-- The local.properties file is created and updated by the ‘android‘ tool.
It contains the path to the SDK. It should *NOT* be checked into
Version Control Systems. -->
<property file="local.properties" />
<!-- The ant.properties file can be created by you. It is only edited by the
‘android‘ tool to add properties to it.
This is the place to change some Ant specific build properties.
Here are some properties you may want to change/update:
source.dir
The name of the source directory. Default is ‘src‘.
out.dir
The name of the output directory. Default is ‘bin‘.
For other overridable properties, look at the beginning of the rules
files in the SDK, at tools/ant/build.xml
Properties related to the SDK location or the project target should
be updated using the ‘android‘ tool with the ‘update‘ action.
This file is an integral part of the build system for your
application and should be checked into Version Control Systems.
-->
<property file="ant.properties" />
<!-- if sdk.dir was not set from one of the property file, then
get it from the ANDROID_HOME env var.
This must be done before we load project.properties since
the proguard config can use sdk.dir -->
<property environment="env" />
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
<isset property="env.ANDROID_HOME" />
</condition>
<!-- The project.properties file is created and updated by the ‘android‘
tool, as well as ADT.
This contains project specific properties such as project target, and library
dependencies. Lower level build properties are stored in ant.properties
(or in .classpath for Eclipse projects).
This file is an integral part of the build system for your
application and should be checked into Version Control Systems. -->
<loadproperties srcFile="project.properties" />
<!-- quick check on sdk.dir -->
<fail
message="sdk.dir is missing. Make sure to generate local.properties using ‘android update project‘ or to inject it through the ANDROID_HOME environment variable."
unless="sdk.dir"
/>
<!--
Import per project custom build rules if present at the root of the project.
This is the place to put custom intermediary targets such as:
-pre-build
-pre-compile
-post-compile (This is typically used for code obfuscation.
Compiled code location: ${out.classes.absolute.dir}
If this is not done in place, override ${out.dex.input.absolute.dir})
-post-package
-post-build
-pre-clean
-->
<import file="custom_rules.xml" optional="true" />
<!-- Import the actual build file.
To customize existing targets, there are two options:
- Customize only one target:
- copy/paste the target into this file, *before* the
<import> task.
- customize it to your needs.
- Customize the whole content of build.xml
- copy/paste the content of the rules files (minus the top node)
into this file, replacing the <import> task.
- customize to your needs.
***********************
****** IMPORTANT ******
***********************
In all cases you must update the value of version-tag below to read ‘custom‘ instead of an integer,
in order to avoid having your file be overridden by tools such as "android update project"
-->
<!-- version-tag: 1 -->
<import file="${sdk.dir}/tools/ant/build.xml" />
</project>
手动为项目新建一个File,该文件名为:ant.properties
创建完成项目的目录结构如下图:
key.store=/Users/hl/Develop/tmacsky
key.alias=tmacsky
key.store.password=987884492
key.alias.password=987884492
market_channels=10035,10034,10001,10002
app_version=1.2
keystore为签名文件的全路径
key.alias为签名需要使用的私钥
key.store.password为私钥库的密码
key.alias.password为私钥的密码
market_channels为渠道集合
app_version为apk的版本(此字段可根据自己喜好编写)。
现在开始build.xml文件的配置:
1,修改build.xml的第二行,修改方法如下:
其中name为你项目的名称,default设置为release。
例:<project name="AA" default="release">
2,循环替换AndroidManifest.xml中UMENG_CHANNEL的value值并进行自动签名打包,方法如下:
<import file="${sdk.dir}/tools/ant/build.xml" />
<property name="out.unaligned.dir" value="/Users/hl/Desktop/AA_${app_version}/" />
<mkdir dir="${out.unaligned.dir}" />
<target name="modify_update_file">
<echo>*********************** make channel ${channel}</echo>
<replaceregexp file="AndroidManifest.xml"
match=‘channel‘
replace=‘${channel}‘
byline="false"
encoding="utf-8"
/>
<property name="out.unaligned.file" location="${out.unaligned.dir}/HelloWorld_${app_version}_${channel}_android.apk"/>
</target>
<target name="make_one_channels" depends="savemanifest,modify_update_file,release,replacemanifest,deletebin" description="description">
</target>
<target name="replacemanifest">
<echo>*********************** replacemanifest</echo>
<delete file="${basedir}\AndroidManifest.xml"/>
<copy file="..\temp\build\META-INF\AndroidManifest.xml" todir="${basedir}" encoding="utf-8"/>
</target>
<target name="savemanifest">
<echo>*********************** savemanifest</echo>
<copy file="${basedir}\AndroidManifest.xml" todir="..\temp\build\META-INF" encoding="utf-8" />
</target>
<target name="deletebin">
<delete dir="${basedir}\bin" />
</target>
<taskdef name="foreach" classname="net.sf.antcontrib.logic.ForEach" classpath="/Users/hl/Develop/adt-l/sdk/tools/lib/ant-contrib-1.0b3.jar" />
<target name="make_channels">
<foreach target="make_one_channels" list="${market_channels}" delimiter="," param="channel">
</foreach>
</target>
out.unaligned.dir的value值为apk输出文件夹的绝对路径,文件夹采用HelloWorld结合app_version命名,app_version为ant.properties中的app_version
out.unaligned.file的location为apk最终的输出路径,apk命名采用HelloWorld加app_version加当前的channel加android方式
打包的过程
第125行make_channels的target是ant的入口,该target中使用foreach循环调用名为make_one_channels的target(第106行)并把market_channels集合中的每个值替换给channel
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,当时做这块的时候碰到的问题)
- 第124行taskdef标签下的classpath是ant-contrib-1.0b3.jar的绝对路径
至此所有配置全部弄好了
下面开始打包
1,打开终端找到你的项目目录,例如:cd /Users/hl/Documents/workspace/AA/
2,然后执行ant make_channels
* 如果报如下的错误则说明你的Android SDK有问题,首先/sdk/tools/ant/build.xml
这个文件得存在,不存在则去重新下一个ADT,如果存在则看看是否是Android SDK的路径没设置好
Buildfile: /Users/hl/Documents/workspace/AA/build.xml
BUILD FAILED
/Users/hl/Documents/workspace/AA/build.xml:90: Cannot find /Users/hl/Develop/adt-l/sdk/tools/ant/build.xml imported from /Users/hl/Documents/workspace/AA/build.xml
- 当出现BUILD SUCCESSFUL代表打包成功!可以看到路径下生成了四个apk,
我安装了其中的一个10034测试,安装后在友盟后台看到,显示出这个渠道,如下图:
注意:
1,每次打包前一定要删除掉temp/build/META-INF中的AndroidManifest.xml,特别是在给不同项目做打包时
2,打包前请检查AndroidManifest.xml中qudao的value值是否为channel,特别是打包失败后再次重新打包的时候一定要将value值改为channel
3,如果打包时出现Cannot recover key错误导致BUILDFAILD的话,请检查ant.properties中key.alias.password的值后面是否有多余的空格!有的话请把空格删除掉!
在代码中获取渠道值,方法如下:
public static String getAppChannel(Context context) {
String channel = "UMENG_CHANNEL";
try {
ApplicationInfo appInfo = context.getPackageManager()
.getApplicationInfo(context.getPackageName(),
PackageManager.GET_META_DATA);
channel = appInfo.metaData.getString("UMENG_CHANNEL");
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return channel;
}
测试项目:https://github.com/tmacsky/AA
参考:http://www.eoeandroid.com/thread-323111-1-1.html
http://blog.csdn.net/ljb_blog/article/details/12709947
http://blog.csdn.net/ljb_blog/article/details/12709983
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。