一款Android APK的结构构成解析

目录
  • 一、 APK 组成解析
    • 1.1 Apk 分析工具
    • 1.2 Dex 知识点拓展
  • 二、 构建源码导读
    • 2.1 源码引入
    • 2.2 BuildConfig Task 详解
    • 2.3 获取所有 task 对应的类名
  • 三、构建流程梳理
  • 四、手动构建 APK

作者:hockeyli,腾讯 PCG 客户端开发工程师

一、 APK 组成解析

在开始解析 Android 构建流程之前,我们先来看下构建的最终产物 APK 的整体组成:

APK 主要由五个部分组成,分别是:

  • Dex:.class 文件处理后的产物,Android 系统的可执行文件
  • Resource:资源文件,主要包括 layout、drawable、animator,通过 R.XXX.id 引用
  • Assets:资源文件,通过 AssetManager 进行加载
  • Library:so 库存放目录
  • META-INF:APK 签名有关的信息

1.1 Apk 分析工具

工欲善其事,必先利其器,既然想分析 APK 必然少不了好用的工具。

① Android Studio 自带的 APK 分析器

通过 APK 分析器,我们可以完成这些操作:

  • 查看 APK 中文件(如 DEX 和 Android 资源文件)的绝对大小和相对大小
  • 了解 DEX 文件的组成
  • 快速查看 APK 中文件(如 AndroidManifest.xml)的最终版本
  • 对两个 APK 进行并排比较

② ClassyShark 可以做为 AS 自带 APK 分析器的补充,帮我们分析 dex 中的详细数据,以及查看 APK 中的总方法数以及各个模块的方法数分布。

1.2 Dex 知识点拓展

当我们在 Android 查看一个 APK 的时候,可以看到右上角有 Defined Methods 和 Referenced Methods,但大多数人可能不知道这两者的区别,这里简单说明下:

Defined Methods:在这个 Dex 中定义的方法;Referenced Methods:Defined Methods 以及 Defined Methods 引用到的方法。

Android 有 64K 引用限制,当 type_ids、method_ids 或者 field_ids 超过 65536(64 * 1024)的时候,需要进行 dex 分包,为了 Dex 的数量尽可能少,我们需要尽量实现「Dex 信息有效率」的提升。

Dex 信息有效率 = Defined Methods 数量 / Referenced Methods 数量

二、 构建源码导读

当我们用 Android Studio 进行安装包构建的时候,会发现其实是运行了一连串的 Task,也就是说其实是这些 task 的配合,最终构建出我们的 APK 的。

2.1 源码引入

如果我们想更了解 Android 的构建流程,对于相关的源码肯定是要有所了解的。那我们如何看到这些 Task 相关的源码呢,我们知道 Android 是用 Gradle 进行构建的,也就意味着这些 task 其实都是放在 Gradle 中,我们想看 Gradle 中源码的话,可以在 build.gradle 将 Gradle 进行编译。

compileOnly "com.android.tools.build:gradle:3.0.1"

编译完之后,可以在 ApplicationTaskManager#createTasksForVariantScope 中找到创建这些 Task 相关的代码,也就意味着顺藤摸瓜找到这些 Task 的真正实现逻辑。

2.2 BuildConfig Task 详解

这里以 BuildConfig 文件的生成为例,来梳理下如何查看某个 task 的代码逻辑。

生成 BuildConfig 文件,是通过 ApplicationTaskManager 中通过 createBuildConfigTask 来创建对应的 task。

顺着代码逻辑,我们找到最终真正实现这个逻辑的是:GenerateBuildConfig 这个 task,GenerateBuildConfig 是继承自 BaseTask,这里有个小技巧是,Task 中真正的执行逻辑都是在带着 @TaskAction 注解的方法上的,所以我们能很快找到对应的 generate() 方法。可以看到生成 BuildConfig 整体的逻辑还是比较简单的,其实就是将 build.gradle 中自带的属性以及我们自定义的属性进行读取,然后通过 JavaWriter 生成对应的 BuildConfig 文件。

2.3 获取所有 task 对应的类名

看到上面的例子,可能有些人会抛出一个疑问就是那我们怎么确定构建中执行的 task 具体对应哪个类呢,这里提供一个小技巧,其实我们可以在 taskGraph 构建完成之后,将所有 task name 以及对应的 class 进行打印。例如在 build.gradle 中加入这个代码之后,我们在运行的时候,就会把 task 所对应的类名也都一起打印出来。

三、构建流程梳理

可以看到 Android 构建中会涉及到多个工具,我们可以通过 open $ANDROID_HOME/build-tools 来查看相关的构建工具。

四、手动构建 APK

最后我们通过命令行来手动打包一个可执行的 APK,能让我们对 APK 构建的理解更加深入。首先需要准备下 代码、资源文件、AndroidManifest 这些构建 APK 的必要文件。

① 通过 aapt2 compile 将 res 资源编译成 .flat 的二进制文件:

aapt2 compile -o build/res.zip --dir res

② 通过 aapt2 link 将 .flat 和 AndroidManifest 进行连接,转化成不包含 dex 的 apk 和 R.java:

aapt2 link build/res.zip -I $ANDROID_HOME/platforms/android-30/android.jar --java build --manifest AndroidManifest.xml -o build/app-debug.apk

③ 通过 javac 将 Java 文件编译成 .class 文件:

javac -d build -cp $ANDROID_HOME/platforms/android-30/android.jar com/**/**/**/*.java

④ 通过 d8 将 .class 文件转化成 dex 文件:

d8 --output build/ --lib $ANDROID_HOME/platforms/android-30/android.jar build/com/tencent/hockeyli/androidbuild/*.class

⑤ 合并 dex ⽂件和资源⽂件:

zip -j build/app-debug.apk build/classes.dex

⑥ 对 apk 通过 apksigner 进行签名:

apksigner sign -ks ~/.android/debug.keystore build/appdebug.apk

欢迎点赞

到此这篇关于一款Android APK的结构构成解析的文章就介绍到这了,更多相关Android apk 结构内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android 通过代码安装 APK的方法详解

    在 APK 开发中,通过 Java 代码来打开系统的安装程序以安装 APK 并不是什么难事,一般的 Android 系统都有开放这一功能. 但随着 Android系统版本的迭代,其对于权限的把控越来越严格,或者说是变得越来越注重安全性.这就导致了以前可以通过很简单的几行代码就能实现的功能,现在要复杂很多. 对于通过代码打开系统安装程序这一功能的限制,其分水岭在 Android7.0,即 Android N 上.通常在 Android N以上的系统使用一种做法,以下则使用另一种做法. 传统的通过代

  • Android Studio如何打包生成APK

    一.修改版本和指定生成APK文件名[可选] 将项目切换到Project视图,打开app目录下的build.gradle文件 1.1 修定软件版本 如1.2图所示. versionCode是app的大版本号,为数值类型,默认为1我这里改为2. versionName是app的具体版本号,为际符串类型,默认为1.0我这里改为2.3. 1.2 指定生成的APK文件名 一样是在build.gradle文件中修改,默认生成的release版apk名为app-release.apk. 在android内部d

  • Android串口通信apk源码详解(附完整源码)

    1.SerialPortHelper「Android串口通信」介绍 原项目地址 https://github.com/freyskill/SerialPortHelper Android串口通讯助手可以用于需要使用串口通信的Android外设,该库有如下特点: 1.串口通信部分使用C++实现,在笔者接触的部分设备上实测,使用C++实现与Google官方提供的Demo的方式要快: 2.支持且必须设置串口接收最大数据长度,初始化库时填入该参数,这样设置的原因是考虑在实际使用中,规定的串口通信协议格式

  • Android Studio打包APK文件具体实现步骤解析

    Android Studio是谷歌推出一个Android集成开发工具,基于IntelliJ IDEA.它类似于Eclipse ADT,Android Studio 提供了集成的Android开发工具用于开发和调试.那么今天我们就来讲讲如何通过Android Studio打包APK文件,相信有很多用户还不是非常了解,下面通过这篇文章给大家介绍一下. Android Studio软件版本:2.3.0.8 官方版编程开发立即查看 前面一直使用的是out文件夹里面的那个apk文件(debug版本),最近

  • Android Studio将程序打包成APK的步骤详解

    第一步:先点击Build选择GenerateSigned APK 第二步:如果之前有编译成APK的话,就直接选择Choose existing已经存在的key:如果没有编译成APK那就选择Create new创建一个新的key的存放路径,然后填上密码,其中First and Last Name填一下,其他的无所谓.如图 尽量保证图中所指的两处密码相同,这样可以避免混淆,然后点击ok.下图的红圈之内填的是存储key的文件名. 做完上述的操作,会返回下图,然后点击next 接下来,一定要点击下图标记

  • 一款Android APK的结构构成解析

    目录 一. APK 组成解析 1.1 Apk 分析工具 1.2 Dex 知识点拓展 二. 构建源码导读 2.1 源码引入 2.2 BuildConfig Task 详解 2.3 获取所有 task 对应的类名 三.构建流程梳理 四.手动构建 APK 作者:hockeyli,腾讯 PCG 客户端开发工程师 一. APK 组成解析 在开始解析 Android 构建流程之前,我们先来看下构建的最终产物 APK 的整体组成: APK 主要由五个部分组成,分别是: Dex:.class 文件处理后的产物,

  • Android APK应用安装原理解析之AndroidManifest使用PackageParser.parserPackage原理分析

    本文实例讲述了Android APK应用安装之AndroidManifest使用PackageParser.parserPackage原理.分享给大家供大家参考,具体如下: Android 安装一个APK的时候首先会解析APK,这里要做很多事情,其中一个事情就是解析Manifest.xml文件,并将所有APK的Manifest封装到各种对象中并保存在内存当中 解析Manifest的类是非常重要的,该类就是frameworks\base\core\java\android\content\pm\P

  • Android编程使用pull方式解析xml格式文件的方法详解

    本文实例讲述了Android编程使用pull方式解析xml格式文件的方法.分享给大家供大家参考,具体如下: 上次已经说过使用Android sax解析xml,实际上还可以使用pull解析xml.这样的方式效率也是比较高的.pull不仅可以在Android上使用也可以用在javaee里面,需要的就是pull的jar包.这次的xml也使用上次的那个,如下所示 <?xml version="1.0" encoding="UTF-8"?> <persons

  • android apk反编译到java源码的实现方法

    Android由于其代码是放在dalvik虚拟机上的托管代码,所以能够很容易的将其反编译为我们可以识别的代码. 之前我写过一篇文章反编译Android的apk包到smali文件 然后再重新编译签名后打包实现篡改apk的功能. 最近又有一种新的方法来实现直接从Android apk包里的classes.dex文件,把dex码反编译到java的.class二进制码,然后从.class二进制码反编译到java源码想必就不用我来多说了吧. 首先我们需要的工具是dex2jar和jd-gui 其中第一个工具

  • android编程之XML文件解析方法详解(附源码)

    本文实例讲述了android编程之XML文件解析方法.分享给大家供大家参考,具体如下: 在android开发中,经常用到去解析xml文件,常见的解析xml的方式有一下三种:SAX.Pull.Dom解析方式.最近做了一个android版的CSDN阅读器,用到了其中的两种(sax,pull),今天对android解析xml的这三种方式进行一次总结. 今天解析的xml示例(channels.xml)如下: <?xml version="1.0" encoding="utf-8

  • Android 滑动拦截实例代码解析

    废话不多说了,直接给大家贴代码了,具体代码如下所示: package demo.hq.com.fby; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.widget.LinearLayout; /** * Created by huqing on 2016/12/7.

  • Android编程简易实现XML解析的方法详解

    本文实例讲述了Android编程简易实现XML解析的方法.分享给大家供大家参考,具体如下: 首先创建在Android工程中创建一个Assets文件夹 app/src/main/assets 在这里添加一个名为 data.xml的文件,然后编辑这个文件,加入如下XML格式内容 <?xml version="1.0" encoding="utf-8"?> <apps> <app> <id>1</id> <

  • Gradle编译打包Android apk详细介绍

    Gradle编译打包Android apk详细介绍 理解Gradle构建过程,解读Android Gradle插件的配置 阅读本文一定是要使用过Gradle生成apk,文中不会讲如何安装运行Gradle,如有需要可先看文末的参考文章. APK包是一个ZIP压缩包,从Java源代码.资源文件到生成这个APK,经过了编译打包一系列特定的过程,SDK文档(/docs/tools/building/index.html)中找到.而这一系列特定的过程,重复繁琐,构建工具(build tool)就是来流程化

  • android BottomSheetDialog新控件解析实现知乎评论列表效果(实例代码)

    BottomSheetDialog使用解析 Android Support Library 23.2里的 Design Support Library新加了一个Bottom Sheets控件,Bottom Sheets顾名思义就是底部操作控件,用于在屏幕底部创建一个可滑动关闭的视图,可以替代对话框和菜单.其中包含BottomSheets.BottomSheetDialog和BottomSheetDialogFragment三种可以使用.其中应用较多的控件是BottomSheetDialog,主要

  • Java实现Android拼图游戏设计过程解析

    目录 1.项目介绍 2.项目原理 3.项目设计 4.项目实现 5.获取布局 6.准备图片 7.初始化item 8.游戏图片的切换 9.游戏胜利的判断 10.游戏封面 1.项目介绍 这是一款基于 Java 开发的移动端安卓小游戏——大家来拼图 2.项目原理 把选定的一张图片切分很多份,先是 33 格式,在一定的时间内点击格子交换使图形拼成一张完整的图片就算闯关成功,这样关卡也很容易设计,33:44:55:6*6: 3.项目设计 我们需要一个容器,可以放这些图片的块块,为了方便,我们准备使用Rela

随机推荐