• 一个使用命令行编译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_studioplatformsandroid-22android.jar

    2.清空bin文件夹
    清空上次生成的文件
    3.编译java文件和jar包

    javac -encoding GBK -target 1.5 -bootclasspath D:android_sdk_for_studioplatformsandroid-22android.jar -d bin src
    etmobctrl
    ormalapk*.java gen
    etmobctrl
    ormalapkR.java -classpath libs*.jar

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

    dx --dex --output=C:Usersmochuan.zhb
    ewworkspaceBundleApk5inclasses.dex C:Usersmochuan.zhb
    ewworkspaceBundleApk5in

    5.编译成资源文件

    aapt package -f -M AndroidManifest.xml -S res -I D:android_sdk_for_studioplatformsandroid-22android.jar -F bin
    esources.ap_ --non-constant-id

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

    java -cp D:android_sdk_for_studio	oolslibsdklib.jar com.android.sdklib.build.ApkBuilderMain binMyCommond.apk -v -u -z bin
    esources.ap_ -f binclasses.dex -rf C:Usersmochuan.zhb
    ewworkspaceBundleApk5src

    7.使用jarsigner对apk进行签名
    jarsigner -verbose -keystore C: est.keystore -storepass 123456 -keypass 123456 -signedjar C:projectdemo-signed.apk C: est.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("
    ");
            }
            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.zhbandroid-sdksuild-tools22.0.1aapt_alitrip.exe package -f -m -J C:Usersmochuan.zhb
    ewworkspaceBundleApk5gen -S C:Usersmochuan.zhb
    ewworkspaceBundleApk5
    es -M C:Usersmochuan.zhb
    ewworkspaceBundleApk5AndroidManifest.xml  -A C:Usersmochuan.zhb
    ewworkspaceBundleApk5assets -I D:android_sdk_for_studioplatformsandroid-22android.jar --non-constant-id -x --package-id 5
    javac -target 1.5 -bootclasspath D:android_sdk_for_studioplatformsandroid-22android.jar -d C:Usersmochuan.zhb
    ewworkspaceBundleApk5in C:Usersmochuan.zhb
    ewworkspaceBundleApk5src
    etmobctrl
    ormalapkBaseActivity.java C:Usersmochuan.zhb
    ewworkspaceBundleApk5src
    etmobctrl
    ormalapkBundleActivity.java C:Usersmochuan.zhb
    ewworkspaceBundleApk5src
    etmobctrl
    ormalapkFileUtils.java C:Usersmochuan.zhb
    ewworkspaceBundleApk5src
    etmobctrl
    ormalapkUtils.java C:Usersmochuan.zhb
    ewworkspaceBundleApk5gen
    etmobctrl
    ormalapkBuildConfig.java C:Usersmochuan.zhb
    ewworkspaceBundleApk5gen
    etmobctrl
    ormalapkR.java -classpath C:Usersmochuan.zhb
    ewworkspaceBundleApk5libs.*jar
    D:android_sdk_for_studiouild-tools22.0.1dx.bat --dex --output=C:Usersmochuan.zhb
    ewworkspaceBundleApk5inclasses.dex C:Usersmochuan.zhb
    ewworkspaceBundleApk5in
    D:mochuan.zhbandroid-sdksuild-tools22.0.1aapt_alitrip.exe package -f -M C:Usersmochuan.zhb
    ewworkspaceBundleApk5AndroidManifest.xml -S C:Usersmochuan.zhb
    ewworkspaceBundleApk5
    es -I D:android_sdk_for_studioplatformsandroid-22android.jar -A C:Usersmochuan.zhb
    ewworkspaceBundleApk5assets  -F C:Usersmochuan.zhb
    ewworkspaceBundleApk5in
    esources.ap_ --non-constant-id -x --package-id 5
    java -cp D:android_sdk_for_studio	oolslibsdklib.jar com.android.sdklib.build.ApkBuilderMain C:Usersmochuan.zhb
    ewworkspaceBundleApk5inunsigned.apk -v -u -z C:Usersmochuan.zhb
    ewworkspaceBundleApk5in
    esources.ap_ -f C:Usersmochuan.zhb
    ewworkspaceBundleApk5inclasses.dex -rf C:Usersmochuan.zhb
    ewworkspaceBundleApk5src
    

    參考

    1.Android应用程序资源的编译和打包过程分析
    2.Android 自己主动编译、打包生成apk文件 1 - 命令行方式
    3.使用ANT打包Android应用
    4.怎样改动android aapt源代码实现自己定义package ID

    Author

    郑海波-莫川

    未经同意,不得转载

  • 相关阅读:
    基于按annotation的hibernate主键生成策略,(本文copy的 七郎's Blog的博客,觉的不错)
    sql server与oracle常用函数对比
    如何将jar包关联到javadoc文档??
    在struts2中,每次修改了struts.xml都要重启tomcat服务器,那么怎么样设置才能修改了struts.xml而不需要重启tomcat的服务器呢??
    单链表的就地逆置
    读书笔记——尽量将引用参数设置为const类型
    二进制中1的个数
    反转单向链表
    二叉树的深度
    C/C++参数入栈顺序
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7236359.html
Copyright © 2020-2023  润新知