如何在手机上打包生成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/
如何在手机上打包生成APK相关推荐
- androidstudio打包apk 文件_Android 打包生成APK文件时报lintOptions配置错误
问题描述: 今天在原来得基础上优化了部分功能,想打包成apk文件安装到手机上运行一下,结果在打包时发生了异常.具体异常如下图所示: 翻译右边的错误: Lint在组装释放目标时发现致命错误. 要继续下去 ...
- linux(以ubuntu为例)下Android利用ant自动编译、修改配置文件、批量多渠道,打包生成apk文件...
原创,转载请注明:http://www.cnblogs.com/ycxyyzw/p/4555328.html 之前写过一篇<windows下Android利用ant自动编译.修改配置文件.批量 ...
- Android Studio打包生成APK
Android Studio打包生成APK 当我们编写好代码,测试号应用后,需要在真机环境下测试,这个时候要生成apk,具体步骤如下: 如图,点击Build > Generate Signed ...
- as将安卓应用打包_Android Studio打包生成apk的方法(超级简单哦)
释放双眼,带上耳机,听听看~! 打包文件是需要生成APK文件,其他人可以通过APK安装和使用,一般来说,包是指APK生成的发布版本,下文技术狗小编还介绍了Android Studio 超级简单的打包生 ...
- Android Studio 超级简单的打包生成apk
为什么要打包: apk文件就是一个包,打包就是要生成apk文件,有了apk别人才能安装使用.打包分debug版和release包,通常所说的打包指生成release版的apk,release版的apk ...
- AndroidStudio打包生成apk
AndroidStudio打包生成apk 1. 点击Build->Generate 2. 点击Create new,新建keystore 3. 填写相关内容 4. 填写路径,选择签名版本 注意 ...
- Android项目打包生成apk文件
Android开发打包生成APK文件 打包apk文件分为两种 无需密钥的apk 有密钥的apk(常规) 他们的区别只是就是安全问题. 1.没有密钥的apk 点击之后会自动生成没有密钥的APK. 在编辑 ...
- Android开发超级简单的打包生成apk
Androidk开发超级简单的打包生成apk 为什么要打包: apk文件就是一个包,打包就是要生成apk文件,有了apk别人才能安装使用.打包分debug版和release包,通常所说的打包指生成re ...
- 《Android studio 创建生成keystore SHA1值的申请 高德地图key值申请 android studio 打包生成apk》
开发背景:目前做车载项目,领导要求用高德地图.整理了一下,差不多就是下面的目录: 一.创建生成keystore: 二.SHA1值的申请: 三.高德地图key值申请: 四.android studio ...
最新文章
- Python开发基础总结之XML+time+OO
- 花了几百万,创业一年学到了什么
- JS页面跳转的各种形式
- imgageJ开发【Java】
- es6 Class的严格模式
- HDFS源码解析:教你用HDFS客户端写数据
- [转]设定version 更新js缓存
- [原创]c# 加解密通用类
- 小米出品的最干净的APP,浏览器界的一股“清流”!
- linux的ip是什么,Linux-IP地址后边加个/8(16,24,32)是什么意思?
- Apache Kafka教程A系列:与Storm整合
- 怎样设置图片大小php,php调整图片大小的方法
- win10蓝牙鼠标、耳机无法连接,无蓝牙开关标志解决方案
- 期待已久的Apple Tablet PC - iPad 发布了
- 图片作为背景的相关方法
- 关于mysql的timestamp时间范围
- 数据库设计之物理结构设计
- linux替换文件中内容
- 夜深人静学32系列16——RTC实时时钟
- 凑够3000字畅聊我国大气污染当下严峻的形势