Java操作Ant压缩和解压文件及批量打包Anroid应用

2019-12-10 18:57:23王冬梅

Ant 实现批量打包Android应用 
由于公司运维需要以及应用中需要加上应用推广的统计,往往要对应二三十个渠道,按照正常方法一个一个的去生成不同渠道包的应用,不仅浪费了时间,而且大大降低了效率.
上一篇讲到使用Ant进行Zip/Tar包的解压缩,实际上Ant工具不仅仅具有此类功能,它更强大的地方在于自动化调用程序完成项目的编译,打包,测试等. 类似于C语言中的make脚本完成这些工作的批处理任务. 不同于MakeFile的是,Ant是纯Java编写的,因此具有很好的跨平台性.

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

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

Java操作Ant压缩和解压文件及批量打包Anroid应用

Java操作Ant压缩和解压文件及批量打包Anroid应用

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:androidworkspace3XXX";//要打包的项目根目录 
  private final static String copyApkPath = "D:androidapktest";//保存打包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; 
        } 
      } 
    } 
  } 
}