Android采用Ant批量打包
Posted liyx2018
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android采用Ant批量打包相关的知识,希望对你有一定的参考价值。
Ant批量打包的目的是:android应用市场繁杂,有时候可能需要统计你的app在各个渠道的下载量等信息,而统计各个渠道时是要做区分的,你需要在项目的配置文件中添加数据元,来标示我们的应用是在哪个渠道上发布的。
1、准备工作:
在正式开始Ant打包前,需要下载和配置Ant环境,下载地址:ant下载
下载后解压安装包,解压后的目录如下:
接下来就是配置Ant的环境变量:
创建ANT_HOME变量,填入路径:E:\\apache-ant-1.9.7-bin\\apache-ant-1.9.7
然后在Path中添加 %ANT_HOME%/bin;%ANT_HOME%/lib;
Ok,到这里,Ant环境变量算是配置完毕。
然后打开cmd命令行输入ant命令,看是不是出现下图的提示,是的话,就说明配置成功了。
2、开始Ant打包
(1)、新建一个项目,这里我的项目名称是:AntPackage,纯粹的一个空项目,啥也没呢。
然后就是使用android自带的命令创建我们的build.xml文件,在cmd命令行使用 cd /d path 的命令,到达我们工程的根目录,然后使用 android update project --path . 命令,在当前目录下面创建我们的build.xml文件。如下图:
注意:在输入android update project --path命令时,可能会出现下边的错误:
原因是需要配置ANDROID_HOME环境变量,ANDROID_HOME:F:\\adt-bundle-windows-x86_64-20140321\\adt-bundle-windows-x86_64-20140321\\sdk,然后在path下添加%ANDROID_HOME%/tools;
(2)、创建完build.xml文件之后,我们首先在AndroidManifest.xml文件中,添加一个数据元,代码如下:
<meta-data android:value=" " android:name="UMENG_CHANNEL" />
后面的name属性根据不同的平台各有差异,我们要做的,就是替代前面的value,并实现打包
修改好之后,我们复制清单文件,然后改名为 AndroidManifest.xml.temp ,之后修改AndroidManifest.xml.temp文件内容,将数据源换成我们的替换符,如下所示
<meta-data android:value= "@market@" android:name="UMENG_CHANNEL"/> 在之后的代码中,我们会将@market@替换成我们的渠道名称
(3)、创建好之后,我们在创建一个名为 ant.properties 的文件,在里边添加你的签名文件信息,如图所示:
分别是keystore保存路径,密码,别名,别名密码
key.store=E:\\\\glodon.keystore
key.store.password=123456
key.alias=glodon.keystore
key.alias.password=123456
注意把build.xml下的name替换成当前项目的名称:
好,到目前为止,项目需要配置的信息配置的差不多了。
此时项目目录结构为:(红框为新增部分)
(3)、创建自动打包程序
新建一个java项目,我的项目名称为:AntTest
项目结构如下:
lib下的两个jar包,可以在Ant解压目录的lib下找到,复制过来就行,复制后记得右键Build path。
接下来就是主要代码类,AntTest.java,代码如下:
package com.cn.ant;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectHelper;
/**
* Ant自动打包程序
* @author liyx-k
*
*/
public class AntTest {
private Project project;
private final static String projectBasePath = "F:\\\\GlodonProject\\\\AntPackage";// 要打包的项目根目录
private final static String copyApkPath = "E:\\\\MutilPackage";// 保存打包之后的apk的根目录
private final static String signApk = "AntPackage-release.apk";// 这里的文件名必须是准确的项目名!就是Project工程的bin目录下面的apk安装包的名字
private final static String reNameApk = "AntPackage_";// 重命名之后的项目名称前缀(地图项目不用改)
private final static String placeHolder = "@market@";// 需要修改manifest文件的地方(占位符)
@SuppressWarnings("resource")
public static void main(String args[]) {
long startTime = 0L;
long endTime = 0L;
long totalTime = 0L;
Calendar date = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd:HH:mm:ss");
try {
System.out.println("---------ant批量自动化打包开始----------");
startTime = System.currentTimeMillis();
date.setTimeInMillis(startTime);
System.out.println("开始时间为:" + sdf.format(date.getTime()));
BufferedReader br = new BufferedReader(new FileReader("market.txt"));
String flag = null;
while ((flag = br.readLine()) != null) {
// 先修改manifest文件:读取临时文件中的@market@修改为市场标识,然后写入manifest.xml中
String tempFilePath = projectBasePath + File.separator
+ "AndroidManifest.xml.temp";
String filePath = projectBasePath + File.separator
+ "AndroidManifest.xml";
write(filePath, read(tempFilePath, flag.trim()));
// 执行打包命令
AntTest mytest = new AntTest();
mytest.init(projectBasePath + File.separator + "build.xml",
projectBasePath);
mytest.runTarget("clean");
mytest.runTarget("release");
// 打完包后执行重命名加拷贝操作
File file = new File(projectBasePath + File.separator + "bin"
+ File.separator + signApk);// bin目录下签名的apk文件
File renameFile = new File(copyApkPath + File.separator
+ reNameApk + flag + ".apk");
// 将打包好的apk重命名后移动到copyApkPath位置
boolean renametag = file.renameTo(renameFile);
System.out.println("rename------>" + renametag);
System.out.println("file ------>" + file.getAbsolutePath());
System.out.println("rename------>"
+ renameFile.getAbsolutePath());
}
System.out.println("---------ant批量自动化打包结束----------");
endTime = System.currentTimeMillis();
date.setTimeInMillis(endTime);
System.out.println("结束时间为:" + sdf.format(date.getTime()));
totalTime = endTime - startTime;
System.out.println("耗费时间为:" + getBeapartDate(totalTime));
} catch (Exception e) {
e.printStackTrace();
System.out.println("---------ant批量自动化打包中发生异常----------");
endTime = System.currentTimeMillis();
date.setTimeInMillis(endTime);
System.out.println("发生异常时间为:" + sdf.format(date.getTime()));
totalTime = endTime - startTime;
System.out.println("耗费时间为:" + getBeapartDate(totalTime));
}
}
public void init(String _buildFile, String _baseDir) throws Exception {
project = new Project();
project.init();
DefaultLogger consoleLogger = new DefaultLogger();
consoleLogger.setErrorPrintStream(System.err);
consoleLogger.setOutputPrintStream(System.out);
consoleLogger.setMessageOutputLevel(Project.MSG_INFO);
project.addBuildListener(consoleLogger);
if (_baseDir == null)
_baseDir = new String(".");
project.setBasedir(_baseDir);
if (_buildFile == null)
_buildFile = new String(projectBasePath + File.separator
+ "build.xml");
ProjectHelper.configureProject(project, new File(_buildFile));
}
public void runTarget(String _target) throws Exception {
if (project == null)
throw new Exception(
"No target can be launched because the project has not been initialized. Please call the 'init' method first !");
if (_target == null)
_target = project.getDefaultTarget();
project.executeTarget(_target);
}
/**
* 根据所秒数,计算相差的时间并以**时**分**秒返回
*
* @param d1
* @param d2
* @return
*/
public static String getBeapartDate(long m) {
m = m / 1000;
String beapartdate = "";
int nDay = (int) m / (24 * 60 * 60);
int nHour = (int) (m - nDay * 24 * 60 * 60) / (60 * 60);
int nMinute = (int) (m - nDay * 24 * 60 * 60 - nHour * 60 * 60) / 60;
int nSecond = (int) m - nDay * 24 * 60 * 60 - nHour * 60 * 60 - nMinute
* 60;
beapartdate = nDay + "天" + nHour + "小时" + nMinute + "分" + nSecond + "秒";
return beapartdate;
}
public static String read(String filePath, String replaceStr) {
BufferedReader br = null;
String line = null;
StringBuffer buf = new StringBuffer();
try {
// 根据文件路径创建缓冲输入流
br = new BufferedReader(new FileReader(filePath));
// 循环读取文件的每一行, 对需要修改的行进行修改, 放入缓冲对象中
while ((line = br.readLine()) != null) {
// 此处根据实际需要修改某些行的内容
if (line.contains(placeHolder)) {
line = line.replace(placeHolder, replaceStr);
buf.append(line);
} else {
buf.append(line);
}
buf.append(System.getProperty("line.separator"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
br = null;
}
}
}
return buf.toString();
}
/**
* 将内容回写到文件中
*
* @param filePath
* @param content
*/
public static void write(String filePath, String content) {
BufferedWriter bw = null;
try {
// 根据文件路径创建缓冲输出流
bw = new BufferedWriter(new FileWriter(filePath));
// 将内容写入文件中
bw.write(content);
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭流
if (bw != null) {
try {
bw.close();
} catch (IOException e) {
bw = null;
}
}
}
}
}
其中,需要修改的地方有:
第一个是需要打包项目的根目录,第二个是生成APK的目录,第三个是生成apk的名称,一定注意- ,第四个是项目名称前缀,到这里配置应该差不多了,接下来运行看看。
三、运行AntTest项目,进行批量打包;
运行后发现下边的错误:
解决方案:
Eclipse菜单 – Window – Preferences – Java – Installed JREs – 选中栏目表格中的jre项 – Edit – Add External JARs – 选择jdk目录/lib/tools.jar - 确认其加入JRE system libraries – Finish – OK。
正确打包成功后,如图:
Ok这就打包成功了。。。。。。。。。。。。。。。。。
注意:如果项目关联的有第三方jar包,需要给依赖jar包导入build.xml和local.properties,记得把build.xml的name修改为项目的名称。否则,打包会失败的。。。。
以上是关于Android采用Ant批量打包的主要内容,如果未能解决你的问题,请参考以下文章
Android开发经验使用Ant批量打包Android应用全然指南
Ionic+Cordova WebApp Android打包及环境搭建