使用 Ant 實現批量打包Android應用

openkk 13年前發布 | 37K 次閱讀 Ant Android開發 移動開發

由于公司運維需要以及應用中需要加上應用推廣的統計,往往要對應二三十個渠道,按照正常方法一個一個的去生成不同渠道包的應用,不僅浪費了時間,而且大大降低了效率.

上一篇講到使用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;
            }
        }
    }
}

}</pre>

然后是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</span><meta-data android:name="UMENG_CHANNEL" android:value="@market@"></meta-data>

 本文由用戶 openkk 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!