`
coolerbaosi
  • 浏览: 726688 次
文章分类
社区版块
存档分类
最新评论

ant 批量打包

 
阅读更多

往往要对应二三十个渠道,按照正常方法一个一个的去生成不同渠道包的应用,不仅浪费了时间,而且大大降低了效率.

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


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


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

\" src=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;
}
}
}
}
}

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));
// 关键代码
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);

}

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文件的地方(占位符)

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

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

1.配置JAVA的环境变量
<wbr><wbr>(参考http://jingyan.baidu.com/article/f96699bb8b38e0894e3c1bef<wbr>.html),</wbr></wbr></wbr>

<wbr><wbr>很多Java程序员由于使用Eclipse不配置Java环境变量也能正常运行代码。但是如果想使用Ant命令<strong style="color:black; background-color:rgb(160,255,255)">批量打包</strong>本步骤必不可少。</wbr></wbr>

2.<wbr></wbr>下载Ant(这里的Ant不是eclipseandroid SDk里面自带的ant
<wbr><wbr><wbr>官方下载地址:</wbr></wbr></wbr>http://ant.apache.org/

3.<wbr></wbr>解压Ant并配置环境变量
<wbr></wbr><wbr></wbr>a)解压Ant,比如解压到D:\ant
<wbr></wbr>b)我的电脑->属性->高级->环境变量
<wbr>c)系统变量新建ANT_HOME,变量值为d:\ant</wbr>
<wbr>d)系统变量新建或修改PATH:将%ANT_HOME%\bin;%ANT_HOME%\lib添加到环境变量的PATH中 (注意以上</wbr>
路径均用反斜杠)

4.验证ant配置是否正确
<wbr><wbr></wbr></wbr>在控制台输入Cmd 回车, ant 回车,如果出现:
<wbr><wbr>Buildfile: build.xml does not exist!</wbr></wbr>
<wbr><wbr>Build failed</wbr></wbr>
<wbr><wbr>恭喜你已经ant配置成功!!</wbr></wbr>

<wbr><wbr><em><span style="font-size:22px">Ant<strong style="color:black; background-color:rgb(160,255,255)">批量打包</strong>的基本思想是,每次打包后自动替换渠道号,然后再次打包从而实现多渠道打包的目的。</span></em></wbr></wbr>
但是Ant不支持循环,怎样循环打包? 扩展包Ant-contrib能轻松解决这个问题.可以的同学可以到http://ant-contrib.sourceforge.net/自行下载,下载后直接把ant-contrib-1.0b3.jar放到Ant的lib文件夹即可.

5. <wbr><span style="line-height:33px">编写build.xml</span></wbr>
<wbr></wbr>将以下带有颜色的字体(包括路径,项目名称)都改成正确的名称
<?xml version="1.0" encoding="UTF-8"?>
<project name="ThumbPlay"default="help">

<wbr><wbr>&lt; !-- The local.properties file is created and updated by the '<strong style="color:black; background-color:rgb(255,255,102)">android</strong>' tool.</wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>It contains the path to the SDK. It should *NOT* be checked into</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>Version Control Systems. --&gt;</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr>&lt;property file=<span style="color:#020ffc"><strong>"local.properties"</strong></span>/&gt;</wbr></wbr>

<wbr><wbr>&lt; !-- The ant.properties file can be created by you. It is only edited by the</wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>'<strong style="color:black; background-color:rgb(255,255,102)">android</strong>' tool to add properties to it.</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>This is the place to change some Ant specific build properties.</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>Here are some properties you may want to change/update:</wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr>source.dir</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr>The name of the source directory. Default is 'src'.</wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>out.dir</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr>The name of the output directory. Default is 'bin'.</wbr></wbr></wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr>For other overridable properties, look at the beginning of the rules</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>files in the SDK, at tools/ant/build.xml</wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr>Properties related to the SDK location or the project target should</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>be updated using the '<strong style="color:black; background-color:rgb(255,255,102)">android</strong>' tool with the 'update' action.</wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr>This file is an integral part of the build system for your</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>application and should be checked into Version Control Systems.</wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr>--&gt;</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr>&lt; property file=<span style="color:#0e0cff"><strong>"ant.properties"</strong></span>/&gt;</wbr></wbr>

<wbr><wbr>&lt; !-- The project.properties file is created and updated by the '<strong style="color:black; background-color:rgb(255,255,102)">android</strong>'</wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>tool, as well as ADT.</wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr>This contains project specific properties such as project target, and library</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>dependencies. Lower level build properties are stored in ant.properties</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>(or in .classpath for Eclipse projects).</wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr>This file is an integral part of the build system for your</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>application and should be checked into Version Control Systems. --&gt;</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr>&lt; loadproperties srcFile="project.properties" /&gt;</wbr></wbr>

<wbr><wbr>&lt; !-- quick check on sdk.dir --&gt;</wbr></wbr>
<wbr><wbr>&lt; fail</wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr>message="sdk.dir is missing. Make sure to generate local.properties using '<strong style="color:black; background-color:rgb(255,255,102)">android</strong> update project' or to inject it through an env var"</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr>unless="sdk.dir"</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr>/&gt;</wbr></wbr>


<!-- extension targets. Uncomment the ones where you want to do custom work
<wbr><wbr><wbr>in between standard targets --&gt;</wbr></wbr></wbr>
<!--
<wbr><wbr>&lt; target name="-pre-build"&gt;</wbr></wbr>
<wbr><wbr>&lt; /target&gt;</wbr></wbr>
<wbr><wbr>&lt; target name="-pre-compile"&gt;</wbr></wbr>
<wbr><wbr>&lt; /target&gt;</wbr></wbr>

<wbr><wbr></wbr></wbr>
<wbr><wbr>&lt; target name="-post-compile"&gt;</wbr></wbr>
<wbr><wbr>&lt; /target&gt;</wbr></wbr>
-->

<wbr><wbr>&lt; !-- Import the actual build file.</wbr></wbr>

<wbr><wbr><wbr><wbr><wbr>To customize existing targets, there are two options:</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>- Customize only one target:</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr>- copy/paste the target into this file, *before* the</wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>&lt;import&gt; task.</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr>- customize it to your needs.</wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>- Customize the whole content of build.xml</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr>- copy/paste the content of the rules files (minus the top node)</wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr>into this file, replacing the &lt;import&gt; task.</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr><wbr><wbr>- customize to your needs.</wbr></wbr></wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr>***********************</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>****** IMPORTANT ******</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>***********************</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>In all cases you must update the value of version-tag below to read 'custom' instead of an integer,</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><wbr><wbr>in order to avoid having your file be overridden by tools such as "<strong style="color:black; background-color:rgb(255,255,102)">android</strong>update project"</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr>--&gt;</wbr></wbr>
<wbr><wbr>&lt; !-- version-tag: 1 --&gt;</wbr></wbr>
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<wbr>&lt;classpath&gt;</wbr>
<wbr><wbr>&lt;pathelement location=<span style="color:#0e26fd"><strong>"D:/androidDev/batch-package-tool/ant1.8.3/lib/ant-contrib-1.0b3.jar"</strong></span>/&gt;<wbr></wbr></wbr></wbr>
<wbr>&lt;/classpath&gt;</wbr>
</taskdef>
<import file="${sdk.dir}/tools/ant/build.xml" />




<target name="deploy">
<wbr>&lt;foreach target="modify_manifest" list="${market_channels}" param="channel" delimiter=","&gt;<wbr></wbr></wbr>
<wbr>&lt; /foreach&gt;<wbr></wbr></wbr>
</target>

<target name="modify_manifest">
<!--<replaceregexp file="AndroidManifest.xml" encoding="utf-8" match="android:value=&quot;(.*)&quot;" replace=""/>-->
<wbr><span style="background-color:rgb(199,223,108)"><wbr>&lt;replaceregexp flags="g" byline="false"&gt;<wbr></wbr></wbr></span></wbr>
<wbr><wbr>&lt;regexp pattern="<strong style="color:black; background-color:rgb(255,255,102)">android</strong>:name=&amp;quot;UMENG_CHANNEL&amp;quot;<strong style="color:black; background-color:rgb(255,255,102)">android</strong>:value=&amp;quot;(.*)&amp;quot;" /&gt;<wbr></wbr></wbr></wbr>
<wbr><wbr>&lt;substitution expression="<strong style="color:black; background-color:rgb(255,255,102)">android</strong>:name=&amp;quot;UMENG_CHANNEL&amp;quot;<strong style="color:black; background-color:rgb(255,255,102)">android</strong>:value=&amp;quot;${channel}&amp;quot;" /&gt;<wbr></wbr></wbr></wbr>
<wbr><wbr>&lt;fileset dir="" includes="AndroidManifest.xml" /&gt;<wbr></wbr></wbr></wbr>
<wbr><wbr>&lt;/replaceregexp&gt;</wbr></wbr>
<!--<property <wbr> name="out.release.file" value="${out.absolute.dir}/${channel}.apk"/&gt;--&gt;</wbr>
<wbr><wbr>&lt;antcall target="release"/&gt;</wbr></wbr>
<copy tofile="${gos.path}/ThumbPlay_${channel}.apk">
<wbr><wbr>&lt; fileset dir="${out.absolute.dir}/" includes="<span style="color:#4817fa"><strong>ThumbPlay</strong></span>-release.apk" /&gt;</wbr></wbr>
</copy>
<delete includeEmptyDirs="true"><wbr></wbr>
<wbr><wbr>&lt;fileset dir="${out.absolute.dir}" includes="**/*"/&gt;<wbr><wbr><wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
</delete>
<echo message="==========================="/>
</target>
</project>

6.配置local.properties
<wbr><wbr>sdk.dir=D:\\androidDev\\<strong style="color:black; background-color:rgb(255,255,102)">android</strong>-sdk改成你的SDK所在的目录,注意转义字符</wbr></wbr>

7. <wbr>配置ant.properties</wbr>
# the config file for batch package.
application.package=com.leyou.thumb <wbr><wbr><wbr><wbr><wbr><wbr><span style="font-family:微软雅黑,sans-serif; color:#2a0ff; font-size:10pt">(你的</span><span lang="EN-US" style="font-family:'Courier new'; color:#2a0ff; font-size:10pt">apk</span><span style="font-family:微软雅黑,sans-serif; color:#2a0ff; font-size:10pt">文件的包名)</span></wbr></wbr></wbr></wbr></wbr></wbr>
ant.project.name=ThumbPlay <wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><span style="font-family:微软雅黑,sans-serif; color:#2a0ff; font-size:10pt">(你的</span><span lang="EN-US" style="font-family:'Courier new'; color:#2a0ff; font-size:10pt">apk</span><span style="font-family:微软雅黑,sans-serif; color:#2a0ff; font-size:10pt">文件的工程名)</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
java.encoding=utf-8

out.absolute.dir=C:/compile
gos.path=Z:/app-version/test <wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><span style="font-family:微软雅黑,sans-serif; color:#2a0ff; font-size:10pt">(打好的渠道包要放到的目的位置)</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>

key.store=D:/androidApk/thumbplay/thumbplay.keystore <wbr><wbr><wbr><span lang="EN-US" style="font-family:'Courier new'; color:#2a0ff; font-size:10pt">(keystore</span><span style="font-family:微软雅黑,sans-serif; color:#2a0ff; font-size:10pt">文件路径</span><span lang="EN-US" style="font-family:'Courier new'; color:#2a0ff; font-size:10pt">)</span></wbr></wbr></wbr>
key.store.password=wushenshiji999<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>(keystore文件路径)
key.alias=muzhigame <wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><span style="font-family:微软雅黑,sans-serif; color:#2a0ff; font-size:10pt">(</span><span lang="EN-US" style="font-family:'Courier new'; color:#2a0ff; font-size:10pt">keystore</span><span style="font-family:微软雅黑,sans-serif; color:#2a0ff; font-size:10pt">文件别名)</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
key.alias.password=wushenshiji999 <wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><span style="font-family:微软雅黑,sans-serif; color:#2a0ff; font-size:10pt">(</span><span lang="EN-US" style="font-family:'Courier new'; color:#2a0ff; font-size:10pt">keystore</span><span style="font-family:微软雅黑,sans-serif; color:#2a0ff; font-size:10pt">文件别名密码)</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>


app_version=1.0.4 <wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><span style="font-family:微软雅黑,sans-serif; color:#2a0ff; font-size:10pt">(要打的渠道包的版本名称)</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
market_channels=guanwang,shuihu,wushen,shenhua,huawei <wbr><wbr><span style="font-family:微软雅黑,sans-serif; color:#2a0ff; font-size:10pt">(渠道名称,要以逗号分隔,必须在一行内)</span></wbr></wbr>

8.最后一步,修改AndroidManifest.xml文件:

成功:Android批量打包教程
<wbr></wbr>
<wbr>以上这一行必须在同一行内,决不能换行</wbr>,这是由于在build.xml做了如下限定

成功:Android批量打包教程

9.生成渠道包 <wbr></wbr>
<wbr><wbr></wbr></wbr>a)进入工程根目录,我的为:D:\apps\workspace\ThumbPlay
<wbr><wbr><wbr>注意这里必须要去工程根目录,因为Ant命令运行需要找到工程根目录下的build.xml</wbr></wbr></wbr>
<wbr><wbr>b)cmd输入命令:ant deploy第一次运行或许需要的时间要长些,我的为大约2分50秒</wbr></wbr>
<wbr><wbr>若控制台最后出现Build Success,说明打包成功</wbr></wbr>
<wbr><wbr>若</wbr></wbr>控制台最后出现Build Failed,查看详细信息,找出错误所在,修改它,然后重新运行命令:ant deploy

////////////////////////////////////////////////////////////prog///////////////////////////////////////////

# This is a configuration file for ProGuard.
# http://proguard.sourceforge.net/index.html#manual/usage.html

-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-verbose

# Optimization is turned off by default. Dex does not like code run
# through the ProGuard optimize and preverify steps (and performs some
# of these optimizations on its own).
-dontoptimize
-dontpreverify

# If you want to enable optimization, you should include the
# following:
# -optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
# -optimizationpasses 5
# -allowaccessmodification
#
# Note that you cannot just include these flags in your own
# configuration file; if you are including this file, optimization
# will be turned off. You'll need to either edit this file, or
# duplicate the contents of this file and remove the include of this
# file from your project's proguard.config path property.

-keep attributes *Annotation*
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgent
-keep public class * extends android.preference.Preference
-keep public class * extends android.support.v4.app.Fragment
-keep public class * extends android.app.Fragment
-keep public class com.android.vending.licensing.ILicensingService

# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
-keep classes with membernames class * {
native <methods>;
}

-keep public class * extends android.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}

-keep classes with members class * {
public <init>(android.content.Context, android.util.AttributeSet);
}

-keep classes with members class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}

-keep class members class * extends android.app.Activity {
public void *(android.view.View);
}

# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
-keep class members enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}

-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}

-keep class members class **.R$* {
public static <fields>;
}

# The support library contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version. We know about them, and they are safe.
-dontwarn android.support.**

-keep class com.baidu.mapapi.** { *; }

-keep class com.baidu.location.** { *; }

-keep class com.android.otherpackage.** { *; }//某个包下面的类混淆

//////////////////////////////////////////android 手动打包////////////////////////////////

ndroid 命令行手动编译打包过程图

【详细步骤】:

1使用aapt生成R.java类文件:
例:
E:\androidDev\android-sdk-windows2.2\tools>E:\androidDev\android-sdk-windows2.2\platforms\android-3\tools\aapt.exe package -f -m -J E:\androidDev\AndroidByread\gen -S res -I E:\androidDev\android-sdk-windows2.2\platforms\android-3\android.jar -M AndroidManifest.xml
其中 -f -m -J E:\androidDev\AndroidByread\gen 代表按覆盖的形式在gen目录下生成带包路径的R.java,-S res指定资源文件 ,-I E:\androidDev\android-sdk-windows2.2\platforms\android-3\android.jar 指定使用的android类,-M AndroidManifest.xml指定程序的配置文件

aapt Usage:

2使用android SDK提供的aidl.exe把.aidl转成.java文件:
usage: aidl OPTIONS INPUT [OUTPUT]
aidl --preprocess OUTPUT INPUT...

OPTIONS:
-I<DIR> search path for import statements.
-d<FILE> generate dependency file.
-p<FILE> file created by --preprocess to import.
-o<FOLDER> base output folder for generated files.
-b fail when trying to compile a parcelable.

INPUT:
An aidl interface file.

OUTPUT:
The generated interface files.

3第三步 编译.java类文件生成class文件:
例:E:\Androiddev\AndroidByread>javac -encoding GB18030 -target 1.5 -bootclasspath E:\Androiddev\android-sdk-windows2.2\platforms\android-3\android.jar -d bin src\com\byread\reader\*.java gen\com\byread\reader\R.java

4使用android SDK提供的dx.bat命令行脚本生成classes.dex文件:

例:
E:\Androiddev\AndroidByread>E:\Androiddev\r\android-sdk-windows2.2\platforms\android-3\tools\dx.bat --dex --output=E:\Androiddev\AndroidByread\bin\classes.dex E:\Androiddev\AndroidByread\bin\classes
其中classes.dex为生成的目标文件,E:\Androiddev\AndroidByread\bin\classes为class文件所在目录

5使用Android SDK提供的aapt.exe生成资源包文件(包括res、assets、androidmanifest.xml等):
E:\Andorid\AndroidByread>E:\Androiddev\android-sdk-windows2.2\platforms\android-3\tools\aapt.exe package -f -M AndroidManifest.xml -S res -A assets -I E:\Androiddev\android-sdk-windows2.2\platforms\android-3\android.jar -F bin\byreadreader
将AndroidManifest.xml,res和assets文件夹中的资源文件打包生成byreadreader,用法参见1

6第六步 生成未签名的apk安装文件:
apkbuilder ${output.apk.file} -u -z ${packagedresource.file} -f ${dex.file} -rf ${source.dir} -rj ${libraries.dir}

例: E:\Adnroiddev\AndroidByread>E:\Adnroiddev\android-sdk- windows2.2\tools\apkbuilder.bat E:\Adnroiddev\byreadreader.apk –v -u -z E:\Adnroiddev\AndroidByread\bin\byreadreader -f E:\Adnroiddev\AndroidByread\bin\class.dex -rf E:\Adnroiddev\AndroidByread\src 其中E:\Adnroiddev\byreadreader.apk为生成的apk ,-z E:\Adnroiddev\AndroidByread\bin\byreadreader为资源包,E:\Adnroiddev \AndroidByread\bin\class.dex为类文件包

7使用jdk的jarsigner对未签名的包进行apk签名: use jarsigner jarsigner -keystore ${keystore} -storepass ${keystore.password} -keypass ${keypass} -signedjar ${signed.apkfile} ${unsigned.apkfile} ${keyalias} 例如: E:\Adnroiddev\android-sdk-windows2.2\tools>jarsigner –keystore E:\Adnroiddev\eclipse3.5\bbyread.keystore -storepass byread002 -keypass byread002 -signedjar E:\Adnroiddev\byread.apk E:\Adnroiddev\byreadreader.apk byread 其中–keystore E:\Adnroiddev\eclipse3.5\bbyread.keystore 为密钥文件 -storepass byread002为密钥文件密码 byread 为密钥别名 -keypass byread002为密钥别名密码,-signedjar E:\Adnroiddev\byread.apk为签名后生成的apk文件 E:\Adnroiddev\byreadreader.apk为未签名的文件。
参 考:http://asantoso.wordpress.com/2009/09/15/how-to-build-android- application-package-apk-from-the-command-line-using-the-sdk-tools-continuously-integrated-using-cruisecontrol/

///////////////////////////////////////////////////////////////////////////////

android应用程序的混淆打包
1 . 在工程文件project.properties中加入下proguard.config=proguard.cfg , 如下所示:

target=android-8

proguard.config=proguard.cfg

Eclipse会通过此配置在工程目录生成proguard.cfg文件

2 . 生成keystore (如已有可直接利用)

按照下面的命令行 在D:\Program Files\Java\jdk1.6.0_07\bin>目录下,输入keytool -genkey -alias android.keystore -keyalg RSA -validity 100000 -keystore android.keystore

参数意义:-validity主要是证书的有效期,写100000天;空格,退格键 都算密码。

命令执行后会在D:\Program Files\Java\jdk1.6.0_07\bin>目录下生成 android.keystore文件。

3. 在Eclipce的操作

File -> Export -> Export Android Application -> Select project -> Using the existing keystore , and input password -> select the destinationAPK file

经过混淆后的源代码,原先的类名和方法名会被类似a,b,c。。。的字符所替换,混淆的原理其实也就是类名和方法名的映射。

但4大组件并没有混淆(所有在清单文件定义的组件不能被混淆),因为系统需要通过清单文件来查找和运行应用程序。

proguard.cfg 文件代码解读

-optimizationpasses 5 ->设置混淆的压缩比率 0 ~ 7

-dontusemixedcaseclassnames -> Aa aA

-dontskipnonpubliclibraryclasses ->如果应用程序引入的有jar包,并且想混淆jar包里面的class

-dontpreverify

-verbose ->混淆后生产映射文件 map 类名->转化后类名的映射

-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* ->混淆采用的算法.

-keep public class * extends android.app.Activity ->所有activity的子类不要去混淆

-keep public class * extends android.app.Application

-keep public class * extends android.app.Service

-keep public class * extends android.content.BroadcastReceiver

-keep public class * extends android.content.ContentProvider

-keep public class * extends android.app.backup.BackupAgentHelper

-keep public class * extends android.preference.Preference

-keep public class com.android.vending.licensing.ILicensingService

-keepclasseswithmembernames class * {

native <methods>; -> 所有native的方法不能去混淆.

}

-keepclasseswithmembers class * {

public <init>(android.content.Context, android.util.AttributeSet);

-->某些构造方法不能去混淆

}

-keepclasseswithmembers class * {

public <init>(android.content.Context, android.util.AttributeSet, int);

}

-keepclassmembers class * extends android.app.Activity {

public void *(android.view.View);

}

-keepclassmembers enum * { -> 枚举类不能去混淆.

public static **[] values();

public static ** valueOf(java.lang.String);

}

-keep class * implements android.os.Parcelable { -> aidl文件不能去混淆.

public static final android.os.Parcelable$Creator *;

}

/////////////////////////////////////////////////////////////////

在新版本的ADT创建项目时,混码的文件不再是proguard.cfg,而是project.properties和proguard-project.txt

如果需要对项目进行全局混码,只需要进行一步操作:

将project.properties的中

“# proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt”的“#”去掉就可以了。


如果有一些代码不能被混淆,比如需要加入了so文件,需要调用里面的方法,那么调用JNI访问so文件的方法就不能被混码。在导出的时候,可能不会报错。但是在手机上运行的时候,需要调用so文件的时候,就会报某某方法无法找到。这个时候就需要用到proguard-project.txt


在老版本中,创建项目的时候,会给出proguard.cfg,但是在的新版中创建项目则不会有任何提示。这个时候需要只要将proguard.cfg的内容加入到proguard-project.txt中,再根据自己的需要进行编辑即可。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics