文档章节

使用Ant 实现批量打包Android应用

Easince
 Easince
发布于 2012/11/27 16:25
字数 1340
阅读 577
收藏 10

由于公司运维需要以及应用中需要加上应用推广的统计,往往要对应二三十个渠道,按照正常方法一个一个的去生成不同渠道包的应用,不仅浪费了时间,而且大大降低了效率.

上一篇讲到使用Ant进行Zip/Tar包的解压缩,实际上Ant工具不仅仅具有此类功能,它更强大的地方在于自动化调用程序完成项目的编译,打包,测试等. 类似于C语言中的make脚本完成这些工作的批处理任务. 不同于MakeFile的是,Ant是纯Java编写的,因此具有很好的跨平台性.


在此我主要讲下如何自动构建工具Ant, 对应用进行批量打包, 生成对应不同市场的应用:


首先分别看一下用于打包的Java工程AntTest和需要被打包进行发布的Android工程结构:




market.txt里保存需要打包的市场标识,如:

youmeng

gfan

.......

此文件里自行根据需求添加渠道名称.


然后看一下实现批量打包AntTest类中的内容:

注意:红色标注部分需要进行修改:

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;

public class AntTest {
	private Project project;

	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);

		// Set the base directory. If none is given, "." is used.
		if (_baseDir == null)
			_baseDir = new String(".");

		project.setBasedir(_baseDir);

		if (_buildFile == null)
			_buildFile = new String(projectBasePath + File.separator
					+ "build.xml");

		// ProjectHelper.getProjectHelper().parse(project, new
		// File(_buildFile));
		<span style="color:#FF0000;">// 关键代码</span>
		ProjectHelper.configureProject(project, new File(_buildFile));
	}

	public void runTarget(String _target) throws Exception {
		// Test if the project exists
		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 no target is specified, run the default one.
		if (_target == null)
			_target = project.getDefaultTarget();

		// Run the target
		project.executeTarget(_target);

	}

	<span style="color:#FF0000;">private final static String projectBasePath = "D:\\android\\workspace3\\XXX";//要打包的项目根目录
	private final static String copyApkPath = "D:\\android\\apktest";//保存打包apk的根目录
	private final static String signApk = "XXX-release.apk";//这里的文件名必须是准确的项目名!
	private final static String reNameApk = "XXX_";//重命名的项目名称前缀(地图项目不用改)
	private final static String placeHolder = "@market@";//需要修改manifest文件的地方(占位符)
</span>
	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");
				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));
		}
	}

	/**
	 * 根据所秒数,计算相差的时间并以**时**分**秒返回
	 * 
	 * @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;
				}
			}
		}
	}
}

然后是Android工程中需要进行修改的部分:


1. 修改local.properties中的sdk根目录:

    sdk.dir=D:\\android\\android-sdk-windows-r17\\android-sdk-windows-r17

2. 修改ant.properties中签名文件的路径和密码(如果需要)
    key.store=D:\\android\\mykeystore
    key.store.password=123456
    key.alias=mykey
    key.alias.password=123456

3. 修改AndroidManifest.xml.temp
    拷贝AndroidManifest.xml一份,命名为AndroidManifest.xml.temp
    将需要替换的地方改为占位符,需与打包工程AntTest中的placeHolder常量一致

  如: <meta-data android:value="@market @" android:name="UMENG_CHANNEL"/>

4. Build.xml中:

    <project name="XXX" default="help">,XXX必须为Android工程名称.


如果机器没有配置过Ant环境变量,可根据如下步骤进行配置:


ANT环境变量设置:

Windows下ANT用到的环境变量主要有2个,ANT_HOME 、PATH

设置ANT_HOME指向ant的安装目录。

设置方法:
ANT_HOME = D:/apache_ant_1.7.0

将%ANT_HOME%/bin; %ANT_HOME%/lib添加到环境变量的path中。

设置方法:
PATH = %ANT_HOME%/bin; %ANT_HOME%/lib 

本文转载自:http://blog.csdn.net/t12x3456/article/details/7957117

Easince
粉丝 15
博文 17
码字总数 6928
作品 6
浦东
程序员
私信 提问
Android Ant 批量多渠道打包实例

Android Ant 批量多渠道打包实例 关于批量打包,无需多言,这是每个国内Android开发者必须面对的一个问题。 下面,我就以开源项目「知乎小报」为例,详细说明如何使用ANT实现批量打渠道包。 ...

Cundong
2014/10/17
4.8K
7
在Linux下的批量打包apk方法

在Android项目需要发布的时候,经常需要发布多个渠道,这写渠道信息一般写在minifest.xml文件当中,这样的话,每次发布一个渠道的时候,需要去更改minifest.xml文件,这样显然不是一个程序员...

蜗牛TT
2012/08/28
4.5K
4
Jenkins中使用ant管理Android应用开发生命周期

软件环境 OS:CentOS 6.0 64-bit Android SDK:adt-bundle-linux-x86_64 Jenkins:1.529 Ant:1.8.2 配置管理 1.Jenkins中配置JDK,直接配置1.7+以上JDK。过程略。 2.把Android工程改造成具有A...

miscellanea
2013/11/19
3.8K
0
Linux,maven,redis,android,java,yum,ant部署相关命令

(linux系统查看) getconf LONG_BIT 查看系统位数 (java环境变量) export JAVAHOME=/home/gcweb/usr/java/jdk1.7.045 export PATH=$JAVA_HOME/bin:$PATH 如果需要修改到系统变量中: cd ~ vi .......

shengguimin
2018/06/26
0
0
android使用ant重新编译打包apk

最近在一个android项目中遇到了这样一个需求,对于不同的客户需要不同的apk名称,icon,并对apk进行不同的配置。 从原理上讲,这是比较简单的,无非是对values/string.xml中相关字段进行修改...

bigtiger02
2014/02/21
9.7K
7

没有更多内容

加载失败,请刷新页面

加载更多

yapi上传接口idea插件

YapiIdeaUploadPlugin 插件使用 目的 减少手动维护yapi接口文档的时间成本,通过idea插件快速提交接口文档到yapi; 保证接口文档的准确性,方便后台、前端、测试等查看接口文档; 反向规范代...

狂奔的熊二
2分钟前
0
0
最近学习到的Lambda表达式

前言 只有光头才能变强。 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 中秋去了躺上海,在外滩上打了个卡: 紧接着学了一下Java的函数式编程,给大家整理了...

Java3y
13分钟前
6
0
一条insert语句批量插入多条记录

-- 一条insert只能插入一条数据 insert into person (id, personCode, personName , telNumber)values(1,'5112403' , '张三' , '1378902134'); 一次插入多条数据的方法: 方式一: insert i......

葬-花
25分钟前
1
0
IT兄弟连 HTML5教程 HTML5的基本语法 简单HTML实例制作

现在学习HTML5的方式 目前HTML还处于HTML4与HTML5之间的过渡使用阶段。移动端的Web界面开发已经全面使用HTML5的技术,而在PC端由于用户升级浏览器周期较长,面临着页面的兼容性问题,以及开发...

老码农的一亩三分地
39分钟前
4
0
[Android] 【每日更新书源】「阅读」APP -100+ 精品书源一键导入!每天自动更新最新书源!

我特地写了个爬虫爬取书源,每天自动更新书源(URL是固定的)!大家也可以定期导入一下! 放心!导入时会自动去除重复书源的! 前段时间我发过一个书源大礼包的帖子,不过现在已经无法编辑修...

xiaogg
43分钟前
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部