Android 如何使用ant批量打包

由于公司运维需要,每次上线都需要打几十个市场版的apk文件,主要修改就只有一处,就是manifest中的一个市场标识属性,因为对ant批量打包不了解,一直使用手动打包,感觉既枯燥机械又低效,由于厌倦了手动打包,感觉再有这么多好工具的情况下,居然还手动打apk,未免显的太原始了吧,闲来无事,就研究了一下如何使用ant来批量打apk


因为已经有了使用ant打一个签名apk的基础,见博客http://blog.csdn.net/guonanyun/article/details/7382843(android使用ant自动化打包),所以一开始的想法是使用ant中的循环语法:循环遍历市场标识文件,依次执行相同命令,发现ant似乎对循环命令支持不够,再加上本身对ant不了解,只是或多或少的接触过一些,从来没有深入的研究过,只找到一种在ant中使用javascript语法来实现循环的语法,从网上找的测试程序本身是OK的,但是要想实现我的需求,需要熟悉运用ant api,所以只好作废,此时陷入了僵局


后来突发奇想,既然ant可以调用java代码,那反过来java是不是也也可以调用ant命令呀,不查不知道,一查吓一跳,网上果然有人写出了使用java调用ant脚本http://hilary3113.iteye.com/blog/1155517的博客,似乎看到了胜利的曙光.马上果断的把例子代码粘贴过来,引入相关的jar文件,自己运行一下.发现运行报错,是如下错误信息
E:\other\mapbarmaps_5.6_backup\build.xml:83: import requires support in ProjectHelper(ps:因为我的build.xml文件引入了android自身的build.xml)


后来将该错误信息作为关键字进行google搜索,找到如下博客http://yxhcquedu.iteye.com/blog/861110,也是一个测试demo,拷贝代码并做相应修改,发现出现了新的报错,

com.sun.tools.javac.Main is not on the classpath.
Perhaps JAVA_HOME does not point to the JDK.
It is currently set to "C:/Program Files/Java/jre1.5.0_11"


继续google搜索,发现网上给的比较多的解答是这种方式:http://blog.csdn.net/lhjlhj123123/article/details/5607106,尝试后发现仍然不好使,并且多次确信java环境变量是OK的,后来看了一下java project的依赖jar包,发现都是jre下面lib中的jar文件


说明一下,该图中jdk\lib下的jar包是后来引入的,一开始是没有的

会不是是引入jar包的问题呢?凡事都要尝试一下呀,.实践才是检验真理的唯一标准啊!把C:\Java\jdk1.6.0_21\lib下的jar包引入后,再次运行,OK,虽然还是不明白ant为啥会出现这种问题,但是问题总算是得到了圆满的解决,以后再去知其所以然吧

到此,使用java调用ant脚本打包算是可以正常使用了

下面,就开始考虑如何来批量打包了

首先明确一下项目需求:修改mainfest.xml中的一个属性,打成apk

其次执行步骤依次如下:

1)先修改manifest文件,考虑到若直接把占位符放到manifest文件中,第一次替换成市场标识后,还是需要再替换回占位符的,这相当于多做了一步操作,联想到昨天看的使用ant脚本替换文件中某项的例子,发现先声明一个manifest临时文件,读取该文件中的内容,替换占位符后,将新的内容再次写入manifest中是个不错的方案,尝试一下证明是OK的

ps:上述步骤使用了java中文件操作的相关知识,由于io基础不扎实,为了把重点放到ant打包上,所以继续奉行拿来主义,从网上找了java修改文件内容的相关博客,http://www.iteye.com/problems/56425,直接拷贝代码使用

2)初始化ant项目的相关配置并执行打包命令

3)将打完的apk进行重命名(加入市场标识的后缀)和拷贝操作

4)继续遍历市场标识数组或集合,依次执行步骤1),2),3)

至此,ant批量打包总算是可以正常使用了

如果要抽样测试打出的apk是否已经修改了manifest文件中指定的属性,可以反编译aok后查看,请参考如下博客:

Android APK反编译详解(附图)http://blog.csdn.net/sunboy_2050/article/details/6727581
ps :后期熟悉ant的话,可以使用纯ant脚本或者使用另一种更好的自动化打包工具(maven)

关键代码如下:

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.util.ArrayList;


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 ArrayList<String> flagList = new ArrayList<String>(); //也可以使用集合,不过需要手动添加项
    private final static String[] flagList = new String[]{"htc","moto","oppo"};//此处初始化市场标识
    
   private final static String projectBasePath = ""; //项目的根目录,需要配置
    private final static String copyApkPath = ""; //要改名后拷贝的目录,需要配置
    private final static String placeHolder = ""; //占位符,需要配置
    
    public static void main(String args[]) {   
    	//flagList.add("htc");
    	//flagList.add("moto");
    	//flagList.add("oppo");
        try {   
             System.out.println("---------ant批量自动化打包开始----------");
            for(String flag : flagList){
            	//先修改manifest文件:读取临时文件中的@market@修改为市场标识,然后写入manifest.xml中
            	String tempFilePath = projectBasePath + File.separator + "AndroidManifest.xml.temp";
            	String filePath = projectBasePath + File.separator + "AndroidManifest.xml";
            	write(filePath,read(tempFilePath, flag));
            	//执行打包命令
            	AntTest mytest = new AntTest();   
                mytest.init(   
                        projectBasePath + File.separator + "build.xml",   
                        projectBasePath); 
            	mytest.runTarget("clean");
            	mytest.runTarget("release");   
            	//打完包后执行重命名加拷贝操作
    			//String flag = "htc";
            	File file = new File(projectBasePath + File.separator +"bin"+File.pathSeparator+"MainActivity-release.apk");//bin目录下签名的apk文件
            	file.renameTo(new File(copyApkPath + File.separator + "MainActivity_"+flag+".apk"));
            }
            System.out.println("---------ant批量自动化打包结束----------");
        } catch (Exception e) {   
            e.printStackTrace();  
            System.out.println("---------ant批量自动化打包中发生异常----------");
        }   
    }   
    
    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;  
                }  
            }  
        }  
    }  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值