最近刚刚忙完公司项目,比较轻松一点,抽个时间总结一下Android打包apk相关的知识点,也从网上看了一些前辈的资料,但是感觉看一遍印象不会特别深刻,所以决定写篇文章加深一下记忆,以希望能帮助一批想了解相关信息的同志们... ... 那就开始吧。

一、Ant原始命令行打包流程。

首先总结一下apk打包的一个大致流程,方便后边大家理解。大致分为三步:1.打包生成.dex文件。2.打包生成resouse.zip文件。3.生成.apk文件并签名。每一步中又包含了一些详细的操作步骤,下面一起来看一下。

一.打包生成.dex文件。

我们如果想要生成.dex文件,必须通过工具将一些资源与java代码生成.class文件,其中包含一些资源文件、所有java代码文件、aidl文件等。首先需要在环境变量中配置好我们将要用到的工具,包括JDK、SDK、ANT,配置方法在这里就不多说了,网上一查一大片。然后我们先要用到SDK包下的一个aapt()工具,这个工具后面还会被用到一次,工具在/SDK/build-tools/目录下,我们先用它生成应用的R.java文件。先cd到当前目录下然后输入输入aapt工具相关命令行及相关参数,如下:

aapt package -f -m -J C:\Users\jason\Desktop\ -S D:\lylsoft\android\androidstudio\opensource\MyButterKnifeDemo\app\src\main\res -M D:\lylsoft\android\androidstudio\opensource\MyButterKnifeDemo\app\src\main\AndroidManifest.xml -I D:\lylsoft\android\androidstudio\sdk\platforms\android-24\android.jar

参数含义如下:

-f 如果编译生成的文件已经存在,强制覆盖。

-m 使生成的包的目录存放在-J参数指定的目录

-J 指定生成的R.java 的输出目录路径(存放在桌面的gen)

-S 指定目标项目res文件夹的路径

-M 指定目标项目AndroidManifest.xml文件的路径

-I 指定某个版本平台的android.jar文件的路径

回车执行,便会在我的桌面上生成如下目录结构及R.java文件


到这我们第一小步,了解一下它的实现过程:aapt工具的源码在android系统源码的frameworks\base\tools\aapt目录下,生成的过程主要是调用了aapt源码目录下Resource.cpp文件中的buildResources()函数,该函数首先检查AndroidManifest.xml的合法性,然后对res目录下的资源子目录进行处理,处理的函数为makeFileResources(),处理的内容包括资源文件名的合法性,向资源表table添加条目等,处理完后调用complieResourceFlie()函数编译res与asserts目录下的资源并生成resources.arsc文件,compileResourceFile()函数位于aapt源码目录的ResourceTable.cpp文件中,该函数最后会调用parseAndAddEntry()函数生成R.java文件,完成资源编译后,接下来调用compileXmlFile()函数对res目录的子目录下的xml文件分别进行编译,这样处理过得xml文件就简单的被“加密”过了,最后将所有的资源与编译生成的resources.arsc文件以及“加密”过的AndroidManifest.xml文件打包压缩成resources.ap_文件(使用ant工具命令行编译则会生成与buiild.xml中“project name”指定的属性同名的ap_文件)。资源文件中res/animator、res/anim、res/color、res/drawable(非Bitmap文件,即非.png、.9.png、.jpg、.gif文件)、res/layout、res/menu、res/values和res/xml的资源文件均会从文本格式的XML文件编译成二进制格式的XML文件,assets和res/raw原封不动打包进去。除了assets资源之外,其它的资源都会被赋予一个资源ID。

第二小步是处理aidl文件,

aidl -ID:/JavaTest/Demos/src D:/JavaTest/Demos/src/com/example/android/apis/app/IRemoteService.aidl

"-I"与"D:/JavaTest/***"之间是没有空格的。执行此条命令后,生成的.java会与.aidl文件在同一目录下。 对于没有使用到aidl的Android工程,这一步可以跳过。这一步使用到的工具为aidl,位于android-sdk\platform-tools目录下,aidl工具解析接口定义文件(aidl为android interface definition language的首字母缩写,即android接口描述语言)并生成相应的java代码供程序调用,源码位于Android源码的frameworks\base\tools\aidl目录下。

第三小步通过javac命令将所有的.java文件编译成.class文件包括上边生成的R.java文件。

javac -target 1.8 -bootclasspath D:\lylsoft\android\androidstudio\sdk\platforms\android-24\android.jar -d C:\Users\jason\Desktop\com\demo\jason\mybutterknifedemo -sourcepath D:\lylsoft\android\androidstudio\opensource\MyButterKnifeDemo\app\src C:\Users\jason\Desktop\com\demo\jason\mybutterknifedemo\R.java

执行完上述命令后在桌面上的文件夹中就会出现如下目录

参数含义如下:
-target <jdk版本>            生成特定 jdk 版本的类文件
-bootclasspath <路径>   覆盖引导类文件的位值
-d <目录>                       指定存放生成的类文件的位置
-sourcepath <路径>       指定查找输入源文件的位置(这里包含两个地方一个是src,一个是桌面gen生成的R.java)

第四小步就是生成我们的.dex文件了,这个相对简单,主要用到SDK/build-tools中的dx工具。命令如下:

dx --dex --output=\Users\jason\Desktop\com\demo\jason\mybutterknifedemo\classes.dex C:\Users\jason\Desktop\com\demo\jason\mybutterknifedemo\com\demo\jason\mybutterknifedemo

--output=<要生成的classes.dex路径>  <要处理的class文件的路径> 这样便会生成我们的.dex文件了,这里如果可能会报一个RuntimeException----ParseException这是由于我们引入的jar包编译环境(比如是1.8)要高于android中默认的jdk编译版本(我用的是1.7)。要解决这个问题,只要android项目的编译jdk版本要高于等于引入jar包的编译jdk版本,然后重新编译就好了。既然如此修改eclipse的jdk编译版本改为1.8就好了。

这样我们的第一步生成.dex文件就算是完成了,下边就开始我们的第二步 打包生成Resource.zip

二.打包生成Resource.zip文件。

在这里就第二次用到了我们sdk中的aapt工具了,命令如下:

aapt package -f -M AndroidManifest.xml -S D:\lylsoft\android\androidstudio\opensource\MyButterKnifeDemo\app\src\main\res -I D:\lylsoft\android\androidstudio\sdk\platforms\android-24\android.jar -A D:\lylsoft\android\androidstudio\opensource\MyButterKnifeDemo\app\src\main -F C:\Users\jason\Desktop\com\demo\jason\mybutterknifedemo\Resource.zip

参数介绍如下,跟生成R.java文件差不多:

-f 如果编译生成的文件已经存在,强制覆盖。
-m 使生成的包的目录存放在-J参数指定的目录
-S 指定res文件夹的路径
-I 指定某个版本平台的android.jar文件的路径
-A 指定assert文件夹的路径
-F 指定输出文件完整路径。

回车执行,我们的Resource.zip文件夹就算是生成了,这个名字是可以指定的。这一步比较简单,没有太多要说的。接着往下看。第三步就是生成我们的.apk文件了,这里的.apk文件是没有签名没有优化的.apk文件。

二.生成.apk文件并签名优化。

这里需要组合我们上边生成的两大文件,即.dex文件和Resource.zip文件。这里主要使用apkbuilder脚本,其实是个批处理文件,不过android 3.0后已经被删除,但网上还是可以找到这个脚本的,直接拷贝放到/SDK/tools下即可。其实里面执行的就是sdklib.jar。

apkbuilder C:\Users\jason\Desktop\com\demo\jason\mybutterknifedemo\demo.apk -v -u -z C:\Users\jason\Desktop\com\demo\jason\mybutterknifedemo\Resource.zip -f C:\Users\jason\Desktop\com\demo\jason\mybutterknifedemo\classes.dex

参数含义如下:

第一个参数是存放打包后的文件完整路径

-v Verbose 显示过程信息

-u 创建一个无签名的包

-z 指定apk资源路径

-f 指定dex文件路径

回车执行:在我们指定的路径下就会生成我们没有优化签名的apk文件,如下图:

打包的工具为apkbuilder,它位于android-sdk\tools目录下,apkbuilder为一个脚本文件,实际调用的是android-sdk\tools\lib\sdklib.jar文件中的com.android.sdklib.build.apkbuilderMain类。它的实现代码位于android系统源码的sdk\sdkmanager\libs\sdklib\src\com\android\sdklib\build\akpbuilderMain.java文件,代码构建了一个apkbuilder类,然后以包含resources.arec的文件为基础生成apk文件,这个文件一般为ap_结尾的文件,接着调用addSourceFolder()函数添加的资源,addSourceFolder()会调用processFileForResource()函数往apk文件中添加资源,处理的内容包括res目录与assets目录中的文件,添加完整源后调用addResourcesFromJar()函数往apk文件中写入依赖库,接着调用addNativeLibraries()函数添加工程libs目录下的Native库(通过androidDNK编译生成的so或bin文件),最后条用sealApk()关闭apk文件。

接下来就是给我们的demo.apk进行签名了,用到了jarsigner命令,java的签名工具,如下:

jarsigner -verbose -keystore C:\Users\jason\Desktop\demo.keystore -storepass android -keypass android -signedjar C:\Users\jason\Desktop\com\demo\jason\mybutterknifedemo\demo.apk C:\Users\jason\Desktop\com\demo\jason\demo.apk demo1

各个参数的意义如下:

-verbose  签名/验证时输出详细信息

-keystore  密钥库路径

-storepass  用于密钥库完整性的口令(密码)

-keypass    专用密钥的口令(密码)

-signedjar   已签名的 apk 文件的名称 (第一个apk是签名之后的文件, 第二个apk是需要签名的文件)

回车执行,稍等片刻,在我们指定的文件架下就会生成我们已经打包好的apk文件了,这个已经是签名好的apk文件了。

下一步就是用zipalign对我们的apk进行优化了,我们可以通过zipalign对apk进行检测。如下:

zipalign -c -v 4 C:\Users\jason\Desktop\com\demo\jason\demo.apk

-c 表示进行zipalign优化检测

-v 输出过程信息

如果我们没有优化过我们的apk文件,则会认证失败,会看到Verification FAILED的相关信息。然后我们就可以优化我们的apk文件了。如下:

zipalign -f -v 4 C:\Users\jason\Desktop\com\demo\jason\demo.apk C:\Users\jason\Desktop\com\demo\jason\demo1.apk

-f  如果文件已经存在,强制覆盖

-v 输出详细信息

- 需要zipalign优化的apk  优化后的apk名称以及存放位置

运行完成后我们的指定文件架下就出现了我们已经优化好的apk文件了。如下图

我们这次执行我们的检测命令发现最后验证成功了(打印出Verification succesful)。

zipalign工具位于android-sdk\tools目录,源码位于android系统源码的build\tools\zipalign,它的主要工作是将apk包进行对齐处理,使apk包中的所有资源文件距离文件起始偏移为4字节整数倍,这样通过内存映射访问Apk文件时的速度会更快,验证apk文件是否对齐过的工作由ZipAlign.cpp文件的verify()函数完成,处理对齐的工作则由process()函数完成。

好了以上就是我们用纯命令行的方式打包一个apk文件的过程,是不是感觉很麻烦,我们一般在开发者没人这么搞,写这么多,主要是自己屡一下打包逻辑,同时帮助大家总结一下,让大家都知道整个apk是如何创建成功并进行签名优化的,其中用到了哪些工具。过程中也从巨人的肩膀上割了块肉过来,希望对大家有帮助,谢谢!

Android打包apk实现原理与流程(雷惊风)相关推荐

  1. Android签名机制及PMS中校验流程(雷惊风)

    @Android签名机制及PMS中校验流程(雷惊风) 网上看到一篇比较好的关于Android签名的文章,但是文章链接不安全,不知道哪天会不会找不到了,而且需要关注才能查看完整版,所以在这里记录一下,原 ...

  2. android打包apk时混淆遇到的问题

    android打包apk的时候一般会选择混淆,而在eclipse中常使用的是proguard来混淆.有很多时候引用了第三方包的时候会导致打包不成功,或者打包成功不能运行的情况. 首先看看正常的prog ...

  3. 关于Mac Android 打包 APK

    目录 关于Mac Android 打包 APK 方式一:使用Android Studio生成 1.点击Build->Generate Signed apk,首次点击可能会提示输入操作系统密码 2 ...

  4. android打包apk不能安装程序,Android Studio 打包apk后应用未安装

    本文转载地址 http://blog.csdn.net/sinat_14849739/article/details/76383281 前言 Android 要求所有 APK 必须先使用证书进行数字签 ...

  5. Android打包APK流程及原理描述

    Android的包文件APK分为两个部分:代码和资源,所以打包方面也分为资源打包和代码打包两个方面,这篇文章就来分析资源和代码的编译打包原理. APK整体的的打包流程如下图所示: 具体说来: 通过AA ...

  6. android打包apk进程序闪退,解决安卓打包apk安装后打开闪退的问题

    系统版本 Android Studio版本 Build APK方式生成APK 调试的时候好好的,将打完的包传输到手机上进行安装,安装成功,但是一打开就闪退. 没办法,只好通过在命令行运行adb log ...

  7. Android深入源代码分析理解Aidl总体调用流程(雷惊风)

    2017年開始上班的第一天.老不想工作了,假期感觉还没開始就已经结束了,唉,时间就是这样,新的一年開始了,尽管非常不想干正事,没办法,必须干起来.由于后边的路还非常长,距离六十岁还非常远. 刚上班也没 ...

  8. Android 打包apk出错问题

    记录我的一次解决错误的过程 前天写了一个小东西,能运行但是打包的时候 出错了:  由于我是刚学安卓,不知道这是啥问题,查了好长时间百度,才大概知道 我引用的json jar有两个jar 引用的类重复, ...

  9. Android 打包apk不能覆盖安装

    首先通过日志排查错误 发现是签名不一致问题 我是debug模式下安装release包不能覆盖 release包下可以覆盖安装 这时候配置一下就可以debug模式下的签名就可以了 https://www ...

  10. android打包apk、apk签名及360加固工具的使用

最新文章

  1. 36.两个链表的第一个公共结点——剑指offer
  2. Java API —— Collections类
  3. Socket拉屎模型之二--实践篇
  4. SparkStreaming读取Socket数据
  5. windows server 2012 R2 standard 评估版过期重启
  6. Android--------从一个包中的Avtivity创建另外另外一个包的Context
  7. 实战 | webmagic爬取实战之爬取保险经纪人信息
  8. jmeter校验结果_JMeter(1)--请求内容验证
  9. 读zac老哥《网络营销实战密码》一章有感
  10. svm loss function是什么
  11. python 关于Python看金庸小说的实验
  12. 在html中制作多彩照片墙,60个照片墙布置方案 记录浪漫时刻
  13. c语言五行星型图案,五行图非五方星形图
  14. Life of Pie 少年派的奇幻漂流
  15. 联想计算机系统重装,联想笔记本电脑重装系统教程
  16. 帝都机器人便利店_我把北京80%的便利店吃了个遍!吐血整理出这份帝都便利店大攻略!...
  17. 【C++】模板特化、偏特化
  18. GD32F470之串口空闲中断+DMA篇
  19. 扬帆际海:shopee店铺关键词广告怎么获得流量?
  20. 使用正则表达式进行身份证号匹配

热门文章

  1. 蓝牙协议5.0 第6卷 翻译
  2. 魔方机器人-复原步骤(一)
  3. java验证密码_java实现验证用户账号密码的功能
  4. 网站云服务器资料本地备份,云服务器数据备份到本地
  5. python程序turtle雪人_用turtle画一个雪人
  6. 电脑更换硬盘应该注意什么?
  7. 如何在PS中为图片添加塑料布效果
  8. 电脑重装系统需要多少钱?
  9. 【unity shader】unity游戏特效-仿《崩坏3》希儿魇夜星渊大招特效(运用CommandBuffer和屏幕后处理)
  10. 计算机画图照片大小,电脑自带的画图工具怎么调整图片的大小?