如何在手机上打包生成APK

本文详细介绍如何在手机上完成Android应用的编译打包过程,包括使用aapt处理资源文件、aidl生成接口定义文件、javac编译Java源代码、dx将class文件转换为dex格式、apkbuilder构建未签名APK以及对APK进行签名。
部署运行你感兴趣的模型镜像


by Amour.wang

通常我们都是在电脑上开发android应用,但是有些情况下不方便带电脑,又想临时修改一些参数重新生成apk,于是就发现了一个神器 AIDE(http://www.android-ide.com/)。有免费的版本基本够用了,还有高级版需要$.

然而本篇文章并不是要介绍AIDE,出于程序猿一贯的好奇心,于是决定研究一下这当中的奥秘。本篇文章主要就是介绍apk 打包的流程及如何在手机上生成一个apk 的过程。

 

一、apk 的打包过程分析

既然是要生成Apk 那就得来了解一下APK 的生成过程,以往我们都是在eclipse 中点一下run 然后就可以在bin 文件夹下找到xxx.apk. 再高级一点的使用ant 编译,或者谷歌家大力推崇的 android studio 中的gradle build,都大致是这样。

       但是没有过程啊,于是开始研究这个过程,基本可以分为如下几步


从这个图就可以很明确的看出蓝色的小方块就是我们需要的工具了,白色的小方块是输入,浅蓝色的小方块是中间产物。有了这个流程不管在什么平台上只要找到相应的工具都可以完成apk 的编译打包过程了,目前在 windows,OSX,linux 上网上都已经有很多人有分享了相关的资料的,这边我就不再重复了。下面重点来了,这个目前在网上很少有相关的资料,所以特别整理一下分享给大家。

一、在手机上完成APK 的编译打包。

按照上述的流程分为如下几个步骤,待我一一详细介绍

1.      aapt

google 官方有提供windows 下的aapt.exe 和 linux/mac 的aapt,可是这个aapt 是X86 架构的,在arm 下无法使用,于是想到可以自己编译一个arm 版的。

于是开始各种折腾,aapt 谷歌是有提供官方源码在frameworks/base/tools/aapt/下,又是各种折腾,最后还是直接用别人生成的的比较好用(以后有时间再折腾,还得看下aapt 的源码更深入了解apk 资源的编译原理,这个包含的内容较多就不在这篇详细介绍了)。

Aapt 的基本用法

Aapt  package

-f  overwrite file

-m  make package directoriesunder location specified by –J

[-S resource-sources [-S resource-sources ...]] \

-J  specify where to outputR.java resource constant definitions

-M  specify full path toAndroidManifest.xml to include in zip

-I  add an existing package tobase include set

-F  specify the apk file tooutput

在使用之前必须先把aapt 拷贝到自己应用的目录下,再chmod 为可执行,

String[] chmod = {"chmod", "744", aaptLoc.getAbsolutePath()};
Process chmodProcess = Runtime.getRuntime().exec(chmod);

 

private boolean runaapt(File aaptLoc, File androidJarLoc,String actName) {
    try {
       String[] args = {
               aaptLoc.getAbsolutePath(), //Thelocation of AAPT
               
"package", "-v", "-f", "-m",
                "-S", buildFolder.getAbsolutePath() + "/res/",                

 "-J", genFolder.getAbsolutePath(),
               
"-A", assetsFolder.getAbsolutePath(),              

 "-M", buildFolder.getAbsolutePath() + "/AndroidManifest.xml",               

"-I", androidJarLoc.getAbsolutePath(),

                "-F", binFolder.getAbsolutePath() + "/" + actName + ".apk.res"/

        };
        Process aaptProcess = Runtime.getRuntime().exec(args);
        int code =aaptProcess.waitFor();
        if (code!= 0){
            System.err.println("AAPTexited with error code " +code);
            copyStream(aaptProcess.getErrorStream(),System.out);
            return false;
        }
        return true;
    } catch (IOExceptione) {
       
System.out.println("AAPT failed");
        e.printStackTrace();
        return false;
    } catch (InterruptedException e) {
       
System.out.println("AAPT failed");
        e.printStackTrace();
        return false;
    }
}

 

2.      aidl

源码在frameworks/base/tools/aidl/,这个跟aapt 差不多,依葫芦画瓢,这边就不再详细描述。

 

3.      javac compiler

把java 变成class 文件,这个比较简单了,从SDK tools里面抠出来,直接就用了 ecj.jar

private boolean ecj(File androidJarLoc, String actName, String mainActivityLoc) {
    {
        System.out.println("Compiling with ECJ...");
        Main main = new Main(new PrintWriter(System.out), new PrintWriter(System.err), false, null, null);
        String[] args = {
                ("-verbose"), 
                "-extdirs", libsFolder.getAbsolutePath(),
                "-bootclasspath", androidJarLoc.getAbsolutePath(),
                "-classpath", srcFolder.getAbsolutePath()
                + ":" + genFolder.getAbsolutePath()  
                + ":" + libsFolder.getAbsolutePath(),
                "-1.6",
                "-target", "1.6", 
                "-proc:none", 
                "-d", binFolder.getAbsolutePath() + "/classes/", 
                srcFolder.getAbsolutePath() + "/" + mainActivityLoc + "/" + actName + ".java", 
        };
        System.out.println("Compiling: " + srcFolder.getAbsolutePath() + "/" + mainActivityLoc + "/" + actName + ".java");

        if (main.compile(args)) {
            System.out.println();
            return true;
        } else {
            System.out.println();
            System.out.println("Compilation with ECJ failed");
            return false;
        }
    }
}

 

       4.dex

这个也是一样从SDK buildtools 里面抠出来 dx.jar,这些个jar的用法参数都是参考各路大神,时间有限也没再多去研究

private boolean dexer(int cores) {
    try {
        System.out.println("Dexing with DX Dexer...");
        String[] args;
        args = new String[]{
                "--verbose",
                "--num-threads=" + cores,
                "--output=" + binFolder.getAbsolutePath() + "/classes.dex", // 
                binFolder.getAbsolutePath() + "/classes/" 
        };
         com.android.dx.command.dexer.Main.Arguments dexArgs = new com.android.dx.command.dexer.Main.Arguments();
        dexArgs.parse(args);

        int resultCode = com.android.dx.command.dexer.Main.run(dexArgs);

        if (resultCode != 0) {
            System.err.println("DX Dexer result code: " + resultCode);
            return false;
        }
        return true;
    } catch (Exception e) {
        System.out.println("DX Dexer failed");
        e.printStackTrace();
        return false;
    }
}

5.      apkbuilder

一样的套路在 SDK 的tools 目录下 sdklib.jar,执行完这步,就已经生成了一个未签名的APK

private boolean buildapk(String sketchName, boolean verbose) {
    try {
        System.out.println("Building APK file with APKBuilder...");

        com.android.sdklib.build.ApkBuilder builder = new com.android.sdklib.build.ApkBuilder(new File(binFolder.getAbsolutePath() + "/" + sketchName + ".apk.unsigned"),
                new File(binFolder.getAbsolutePath() + "/" + sketchName + ".apk.res"), 
                new File(binFolder.getAbsolutePath() + "/classes.dex"), 
                null, (verbose ? System.out : null)        );
        
        builder.addSourceFolder(srcFolder); 
        builder.sealApk();
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("APKBuilder failed");
        return false;
    }
}

6.      sign

这个eclipse中是调用java 来对apk 进行签名的没有现成的jar包可以用。从谷歌家拿 https://code.google.com/archive/p/zip-signer/,好了一切顺利的话(通常这种情况发生的概率跟中500万差不多),你就可以看到你在手机上生成的apk了

 

private boolean signApk(String actName) {
    String mode = "testkey";
    String inFilename = binFolder.getAbsolutePath() + "/" + actName + ".apk.unsigned";
    String outFilename = binFolder.getAbsolutePath() + "/" + actName + ".apk";
    ZipSigner signer;
    try {
        signer = new ZipSigner();
        signer.setKeymode(mode);
        signer.signZip(inFilename, outFilename);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}

 

二、小结

遗留的一些已知的问题:

1.      aidl 没有处理,这个应该跟aapt 类似,不过过程太折腾了,暂时没有时间弄

2.      多个dex 合并,这个部分没有处理,但是在SDK里面有看到对应的jar包,这部分应该还好

3.      JNI 编译,这个估计只有大神才可以做到

当中还有很多未知的问题,因个人精力所限,暂时也不能一一查明。

 

 

 

引用查询资料出处

http://www.cnblogs.com/royi123/p/3576746.html

http://1025250620.iteye.com/blog/1974214

https://code.google.com/archive/p/zip-signer/


您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

Android Studio中重新打包一个已有的外部APK文件,通常涉及到反编译、修改源码、重新编译以及签名等步骤。这个过程可以用于调试、修改现有应用的功能或资源,或者进行安全性研究。以下是详细的步骤: ### 反编译APK文件 首先,需要将APK文件反编译为可读的源代码和资源文件。这一步通常使用第三方工具如`APKTool`完成。APKTool能够解码资源文件,使它们变得可编辑,并保留原始的文件结构。 ```bash apktool d your_app.apk -o output_folder ``` 此命令会将`your_app.apk`反编译到指定的输出文件夹中[^2]。 ### 修改源代码和资源 一旦APK被成功反编译,就可以对源代码和资源文件进行必要的修改。这些修改可能包括更改应用界面、添加新功能或修复安全漏洞。 ### 重新编译APK 完成修改后,使用APKTool重新编译APK文件。这一步骤将修改后的源代码和资源文件转换回APK格式。 ```bash apktool b output_folder -o new_app.apk ``` 这条命令会从指定的输出文件夹重新编译APK,并保存为`new_app.apk`[^2]。 ### 签名APK 重新编译后的APK需要使用开发者密钥进行签名,才能在设备上安装和运行。可以通过`jarsigner`工具来完成这一过程。 ```bash jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore your_keystore.jks new_app.apk alias_name ``` 这里,`your_keystore.jks`是包含私钥的密钥库文件,`alias_name`是你在创建密钥时指定的别名[^4]。 ### 对齐APK 最后,使用`zipalign`工具优化APK,确保其在设备上的高效运行。 ```bash zipalign -v 4 new_app.apk final_app.apk ``` 此命令将创建一个优化过的APK文件`final_app.apk`,准备用于分发或安装[^2]。 ### 注意事项 - 在进行上述操作时,请确保遵守相关法律法规,尊重软件的版权和许可协议。 - 使用正确的密钥对APK进行签名至关重要,因为这关系到应用的安全性和用户数据的保护。 - 如果遇到安装问题,检查设备是否有足够的存储空间,以及是否正确地进行了签名和对齐操作[^4]。 通过以上步骤,可以在Android Studio环境中,结合其他工具,成功地将一个外部APK重新打包生成新的APK文件。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值