Android 如何使用ant批量打包

来源:互联网 发布:淘宝买高压气瓶犯法吗 编辑:程序博客网 时间:2024/05/20 22:00

由于公司运维需要,每次上线都需要打几十个市场版的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;                  }              }          }      }  }  
0 0
原创粉丝点击