一个使用命令行编译Android项目的工具类

一个使用命令行编译Android项目的工具类

简介

编译apk项目需要使用的几个工具,基本都在sdk中,它们分别是(Windows系统):

  • 1.aapt.exe

    资源打包工具

  • 2.android.jar

    Android编译工具

  • 3.dx.bat

    dex文件生成工具

  • 4.sdklib.jar

    生成apk

  • 5.jarsigner

    签名工具

准备

在打包前,需要的环境如下:

1.JDK1.6+

2.Android SDK

3.上述5个工具的路径

打包过程

1.生成R.java文件

比如:

aapt package -f -m -J ./gen -S res -M AndroidManifest.xml -I D:\android_sdk_for_studio\platforms\android-22\android.jar

2.清空bin目录

清空上次生成的文件

3.编译java文件和jar包

javac -encoding GBK -target 1.5 -bootclasspath D:\android_sdk_for_studio\platforms\android-22\android.jar -d bin src\net\mobctrl\normal\apk\*.java gen\net\mobctrl\normal\apk\R.java -classpath libs\*.jar

4.使用dx工具打包成classes.dex

dx --dex --output=C:\Users\mochuan.zhb\newworkspace\BundleApk5\bin\classes.dex C:\Users\mochuan.zhb\newworkspace\BundleApk5\bin\

5.编译成资源文件

aapt package -f -M AndroidManifest.xml -S res -I D:\android_sdk_for_studio\platforms\android-22\android.jar -F bin\resources.ap_ --non-constant-id

6.使用sdklib.jar工具生成未签名的apk

java -cp D:\android_sdk_for_studio\tools\lib\sdklib.jar com.android.sdklib.build.ApkBuilderMain bin\MyCommond.apk -v -u -z bin\resources.ap_ -f bin\classes.dex -rf C:\Users\mochuan.zhb\newworkspace\BundleApk5\src

7.使用jarsigner对apk进行签名

jarsigner -verbose -keystore C:\test.keystore -storepass 123456 -keypass 123456 -signedjar C:\projectdemo-signed.apk C:\test.apk test

BuildApkUtils源码,自动生成命令并执行

package com.taobao.trip;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

/**
 * @Author Zheng Haibo (mochuan)
 * @Company Alibaba Group
 * @PersonalWebsite http://www.mobctrl.net
 * @version $Id: BuildUtils.java, v 0.1 2016年1月8日 下午8:47:42 mochuan.zhb Exp $
 * @Description 在Windows平台,如何使用命令行编译android项目
 */
public class BuildApkUtils {

    private static final String ANDROID_JAR_PATH = "D:\\android_sdk_for_studio\\platforms\\android-22\\android.jar";

    private static final String AAPT_PATH = "D:\\mochuan.zhb\\android-sdks\\build-tools\\22.0.1\\aapt_alitrip.exe";

    private static final String DX_PATH = "D:\\android_sdk_for_studio\\build-tools\\22.0.1\\dx.bat";

    private static final String SDK_LIB_JAR_PATH = "D:\\android_sdk_for_studio\\tools\\lib\\sdklib.jar";

    private static final String batchDir = System.getProperty("user.dir")
            + "\\batch\\";

    private String projectDir;
    private int packageId = 127;

    public BuildApkUtils() {

    }

    public BuildApkUtils(String projectDir) {
        this.projectDir = projectDir;
    }

    public BuildApkUtils(String projectDir, int packageId) {
        this.projectDir = projectDir;
        this.packageId = packageId;
    }

    public void buildUnsingedApk() {
        clearDir(batchDir);
        clearDir(projectDir + "\\bin");
        generateR(projectDir, packageId);
        compileJavaFiles(projectDir);
        buildDexFile(projectDir);
        complieResources(projectDir, packageId);
        buildUnsignedApk(projectDir, "unsigned.apk");
        mergeExeBatchFiles();
    }

    /**
     * 第一步:产生R文件
     *
     * @param projectDir
     * @param packageId
     */
    private static void generateR(String projectDir, int packageId) {
        StringBuffer command = new StringBuffer();
        command.append(AAPT_PATH).append(" package -f -m -J ")
                .append(projectDir).append("\\gen ").append("-S ")
                .append(projectDir).append("\\res ").append("-M ")
                .append(projectDir).append("\\AndroidManifest.xml ")
                .append(" -A ").append(projectDir).append("\\assets ")
                .append("-I ").append(ANDROID_JAR_PATH)
                .append(" --non-constant-id -x --package-id ")
                .append(packageId);
        buildExeBatchFiles(command.toString(), "1.bat");
    }

    /**
     * 编译java文件
     *
     * @param projectDir
     */
    private static void compileJavaFiles(String projectDir) {
        StringBuffer command = new StringBuffer();
        command.append("javac -target 1.5 -bootclasspath ")
                .append(ANDROID_JAR_PATH).append(" -d ").append(projectDir)
                .append("\\bin ");
        List<String> javaFilePaths = new ArrayList<String>();
        findJavaFiles(projectDir + "\\src", javaFilePaths);
        findJavaFiles(projectDir + "\\gen", javaFilePaths);
        for (String javaPath : javaFilePaths) {
            command.append(javaPath).append(" ");
        }
        command.append("-classpath ").append(projectDir)
                .append("\\libs\\.*jar");
        buildExeBatchFiles(command.toString(), "2.bat");
    }

    /**
     * 创建dex文件
     *
     * @param projectDir
     */
    private static void buildDexFile(String projectDir) {
        StringBuffer command = new StringBuffer();
        command.append(DX_PATH).append(" --dex --output=").append(projectDir)
                .append("\\bin\\classes.dex").append(" ").append(projectDir)
                .append("\\bin");
        buildExeBatchFiles(command.toString(), "3.bat");
    }

    /**
     * 编译资源文件
     *
     * @param projectDir
     */
    private static void complieResources(String projectDir, int packageId) {
        StringBuffer command = new StringBuffer();
        command.append(AAPT_PATH).append(" package -f -M ").append(projectDir)
                .append("\\AndroidManifest.xml ").append("-S ")
                .append(projectDir).append("\\res ").append("-I ")
                .append(ANDROID_JAR_PATH).append(" -A ").append(projectDir)
                .append("\\assets ").append(" -F ").append(projectDir)
                .append("\\bin\\resources.ap_")
                .append(" --non-constant-id -x --package-id ")
                .append(packageId);
        buildExeBatchFiles(command.toString(), "4.bat");
    }

    /**
     * 生成未签名的apk
     *
     * @param projectDir
     * @param apkName
     */
    private static void buildUnsignedApk(String projectDir, String apkName) {
        StringBuffer command = new StringBuffer();
        command.append("java -cp ").append(SDK_LIB_JAR_PATH)
                .append(" com.android.sdklib.build.ApkBuilderMain ")
                .append(projectDir).append("\\bin\\").append(apkName)
                .append(" -v -u -z ").append(projectDir)
                .append("\\bin\\resources.ap_").append(" -f ")
                .append(projectDir).append("\\bin\\classes.dex")
                .append(" -rf ").append(projectDir).append("\\src");
        buildExeBatchFiles(command.toString(), "5.bat");
    }

    /**
     * 递归查找
     *
     * @param projectDir
     * @param javaFilePaths
     */
    private static void findJavaFiles(String projectDir,
            List<String> javaFilePaths) {
        File file = new File(projectDir);
        File[] files = file.listFiles();
        if (files == null || files.length == 0) {
            return;
        }
        for (File f : files) {
            if (f.isDirectory()) {
                findJavaFiles(f.getAbsolutePath(), javaFilePaths);
            } else {
                if (f.getAbsolutePath().endsWith(".java")) {
                    javaFilePaths.add(f.getAbsolutePath());
                }
            }
        }
    }

    /**
     * 清理目录
     *
     * @param projectDir
     */
    private static void clearDir(String projectDir) {
        File file = new File(projectDir);
        File[] files = file.listFiles();
        if (files == null || files.length == 0) {
            return;
        }
        for (File f : files) {
            if (f.isDirectory()) {
                clearDir(f.getAbsolutePath());
            } else {
                f.delete();
            }
        }
    }

    /**
     * 创建批处理文件
     *
     * @param command
     * @param file
     */
    private static void buildExeBatchFiles(String command, String fileName) {
        System.out.println(command);
        if (!new File(batchDir).exists()) {
            new File(batchDir).mkdirs();
        }
        String filePath = batchDir + fileName;
        try {
            writeFile(filePath, command);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void mergeExeBatchFiles() {
        File file = new File(batchDir);
        System.out.println("debug:current path = " + file.getAbsolutePath());
        File[] files = file.listFiles();
        if (files == null || files.length == 0) {
            return;
        }
        Arrays.sort(files, new Comparator<File>() {
            public int compare(File file1, File file2) {
                if (file1.lastModified() > file2.lastModified()) {
                    return 1;
                } else if (file1.lastModified() < file2.lastModified()) {
                    return -1;
                } else {
                    return 0;
                }
            }
        });
        StringBuffer command = new StringBuffer();
        for (File f : files) {
            command.append("call ").append(f.getAbsolutePath()).append("\n");
        }
        try {
            String filePath = batchDir + "build.bat";
            writeFile(filePath, command.toString());
            Runtime.getRuntime().exec("cmd /c start " + filePath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 写文件
     *
     * @param filePath
     * @param sets
     * @throws IOException
     */
    private static void writeFile(String filePath, String content)
            throws IOException {
        FileWriter fw = new FileWriter(filePath);
        PrintWriter out = new PrintWriter(fw);
        out.write(content);
        out.println();
        fw.close();
        out.close();
    }

}

使用

运行的时候,我们只需要传入项目路径即可:


public class BuildMain {

    private static final String PROJECT_PATH = "C:\\Users\\mochuan.zhb\\newworkspace\\BundleApk5";

    private static final int PACKAGE_ID = 5;

    public static void main(String[] args) {
        new BuildApkUtils(PROJECT_PATH, PACKAGE_ID).buildUnsingedApk();
    }

}

运行过程中,会将生成的命令打印出来:


D:\mochuan.zhb\android-sdks\build-tools\22.0.1\aapt_alitrip.exe package -f -m -J C:\Users\mochuan.zhb\newworkspace\BundleApk5\gen -S C:\Users\mochuan.zhb\newworkspace\BundleApk5\res -M C:\Users\mochuan.zhb\newworkspace\BundleApk5\AndroidManifest.xml  -A C:\Users\mochuan.zhb\newworkspace\BundleApk5\assets -I D:\android_sdk_for_studio\platforms\android-22\android.jar --non-constant-id -x --package-id 5
javac -target 1.5 -bootclasspath D:\android_sdk_for_studio\platforms\android-22\android.jar -d C:\Users\mochuan.zhb\newworkspace\BundleApk5\bin C:\Users\mochuan.zhb\newworkspace\BundleApk5\src\net\mobctrl\normal\apk\BaseActivity.java C:\Users\mochuan.zhb\newworkspace\BundleApk5\src\net\mobctrl\normal\apk\BundleActivity.java C:\Users\mochuan.zhb\newworkspace\BundleApk5\src\net\mobctrl\normal\apk\FileUtils.java C:\Users\mochuan.zhb\newworkspace\BundleApk5\src\net\mobctrl\normal\apk\Utils.java C:\Users\mochuan.zhb\newworkspace\BundleApk5\gen\net\mobctrl\normal\apk\BuildConfig.java C:\Users\mochuan.zhb\newworkspace\BundleApk5\gen\net\mobctrl\normal\apk\R.java -classpath C:\Users\mochuan.zhb\newworkspace\BundleApk5\libs\.*jar
D:\android_sdk_for_studio\build-tools\22.0.1\dx.bat --dex --output=C:\Users\mochuan.zhb\newworkspace\BundleApk5\bin\classes.dex C:\Users\mochuan.zhb\newworkspace\BundleApk5\bin
D:\mochuan.zhb\android-sdks\build-tools\22.0.1\aapt_alitrip.exe package -f -M C:\Users\mochuan.zhb\newworkspace\BundleApk5\AndroidManifest.xml -S C:\Users\mochuan.zhb\newworkspace\BundleApk5\res -I D:\android_sdk_for_studio\platforms\android-22\android.jar -A C:\Users\mochuan.zhb\newworkspace\BundleApk5\assets  -F C:\Users\mochuan.zhb\newworkspace\BundleApk5\bin\resources.ap_ --non-constant-id -x --package-id 5
java -cp D:\android_sdk_for_studio\tools\lib\sdklib.jar com.android.sdklib.build.ApkBuilderMain C:\Users\mochuan.zhb\newworkspace\BundleApk5\bin\unsigned.apk -v -u -z C:\Users\mochuan.zhb\newworkspace\BundleApk5\bin\resources.ap_ -f C:\Users\mochuan.zhb\newworkspace\BundleApk5\bin\classes.dex -rf C:\Users\mochuan.zhb\newworkspace\BundleApk5\src

参考

1.Android应用程序资源的编译和打包过程分析

2.Android 自动编译、打包生成apk文件 1 - 命令行方式

3.使用ANT打包Android应用

4.如何修改android aapt源码实现自定义package ID

Author

郑海波-莫川

未经允许,不得转载

时间: 2024-10-12 08:24:38

一个使用命令行编译Android项目的工具类的相关文章

Ant 命令行编译Android项目

首先把android sdk下的tools目录加到系统path环境变量里, 要么就得直接指定android.bat的绝对路径 对于一个新项目, 可以用这个命令创建需要的ant编译环境(可以看到android项目默认的文件结构) android create project -k com.foo -a Test1 -t android-8 -p d:\temp 如果是已经存在的项目, 对主项目和子项目都运行 项目目录> android update project -s -p . -t andro

韩顺平细说Servlet视频系列意外收获之用命令行编译带有包的java类解决方案

命令行编译带有包的java类 在命令行编译这一块,基本上都是新手入门时了解一下,然后就直奔IDE而去.这样固然没错,就怕那些--.然后今天在视频中看到了这种方法,觉得可能会用到,所以就记录下来了,以备自查. 步骤如下: 在X盘新建一个java文件,编写一段内带包的代码,示例如下: package com.hsp; public class Exercise{ public static void main(String[] args){ System.out.println("Hello Wor

命令行创建Android项目

android create project -n Welcome_World -t 8 -p Welcome_World -k org.example.welcome_World  -a Welcome_World 其中,-n指定要创建的项目的名称,-t指定项目针对的Android的平台,-p指定该项目的保存路径,-k指定该项目的包名,-a选项指定Activity的名称. 现创建一名称为Example000的Android应用,其路径为当前路径,包名为org.Example.example00

打造一个全命令行的Android构建系统

IDE都是给小白程序猿的,大牛级别的程序猿一定是命令行控,终端控,你看大牛都是使用vim,emacs 就一切搞定" 这话说的尽管有些绝对.可是也不无道理.做开发这行要想效率高,自己主动化还真是缺少不了命令行工具,由于仅仅有命令行才是最佳的人机交互工具. 事实上IDE也是底层也是调用命令行工具而已,仅仅只是给普通开发人员呈现一个更友好的开发界面. 这里可不是宣扬让大家放弃IDE都改命令行,仅仅是每种事物都有他存在的理由,不管是编程语言还是工具都是一个原则 "没有最好的,仅仅有最合适的&q

用Gradle命令行编译Android工程

在Android sdk 目录下的samples/android-21/ 文件夹下,任找一个工程,如果在命令行直接编译 可能会报这种错误:gradle buile.gradle FAILURE: Build failed with an exception. 如果是这样,首先回到工程目录下,运行 ./gradlew    然后再执行进行编译 ./gradlew build ./gradlew tasks //查看android gradle的所有任务./gradlew compileReleas

命令行编译vs2013项目

echo off path %SYSTEMROOT%\Microsoft.NET\Framework\v4.0.30319 msbuild.exe .\src\ElectricManagement.sln /t:Rebuild /p:Configuration=Release /p:VisualStudioVersion=12.0 ::/l:FileLogger,Microsoft.Build.Engine;logfile=Build1.log msbuild .\src\ElectricMan

Linux命令行编译Qt项目

1.系统环境 Linux系统版本 1 cat /etc/issue 系统内核 1 uname -a 2.Qt安装完成后,添加qmake的路径到PATH路径中, 1 #添加qmake路径到PATH路径中 2 vim.tiny /home/elephantrob/.bashrc 3 4 #在打开的.bashrc最末端添加PATH 5 export PATH=$:/home/elephantrob/Qt/5.5/gcc/bin 6 7 #保存退出编辑的.bashrc文件,source重新执行该文件 8

Android 命令行编译、打包生成apk文件

一.搭建搭建环境 1. 安装JDK 和 Android SDK 2. 配置环境变量 D:\android-sdk-windows\tools C:\Program Files\Java\jdk1.6.0_20\bin3. 例子信息 项目目录:D:\ProjectDemo SDK目录 :D:\android-sdk-windows\platforms\android-8\ 二.命令行编译Android项目 1. 生成R文件 2. Java代码生成class文件 3. class文件生成dex文件

[Android] 基于 Linux 命令行构建 Android 应用(二):命令行管理项目

创建 Android 项目 在命令行创建 Android 项目需要用到 android 工具(该工具由 Android SDK 提供,位于 <sdk>/tools/ 目录下.).它能自动生成一个项目目录,其中包含若干默认应用程序文件,存案文件,配置文件和一个构建文件. 命令用法[1]: $ android create project \ --target <target_ID> \ --name <your_project_name> \ --path path/to