在成为一个Android Developer后,其实一直都很好奇,一个.apk文件是怎么产生的,它是怎么从一堆.java、.xml等文件变成一个.apk的呢,随着知识体系的完善,这个问题貌似越来越清楚,但是一直未曾认认真真的梳理过一遍流程,恰好最近碰到相关问题,就借此机会总结一下,题其衣裳,以记其事~
环境准备
- Mac OS
- Java
- Android SDK
准备项目
创建工程
直接使用Android Studio创建一个新的工程,比如:HelloAPK,这样创建出来的工程应该包含如下内容:
1 | [min@TATEMIN-MB0:] HelloAPK $ ls -al |
但是实际上决定APK的生成主要依赖于目录app/src/main
,所以此目录就是我们编译APK的workspace。
修改工程
因为此次编译仅是向大家解释Android APK的生成过程,为了尽可能的方便,我们需要删除工程中的一些androidx的非Frameword的依赖,具体细节如下:
资源文件
删除
res/values/styles.xml
;修改
res/layout/activity_main.xml
文件:
代码文件
修改
java/com/min/helloapk/MainActivity.java
文件
Manifest
修改
AndroidManifest.xml
文件
编译项目
生成签名
1
[min@TATEMIN-MB0:] main $ keytool -genkey -alias android.keystore -keyalg RSA -validity 1000 -keystore android.keystore
查看签名
1
[min@TATEMIN-MB0:] main $ keytool -list -v -keystore android.keystore
生成R.java
1
[min@TATEMIN-MB0:] main $ aapt package -v -f -m -S res/ -J java/ -M AndroidManifest.xml -I /Users/min/Library/Android/sdk/platforms/android-26/android.jar
编译代码
1
2[min@TATEMIN-MB0:] main $ mkdir gen # 创建一个中间文件目录
[min@TATEMIN-MB0:] main $ javac java/com/min/helloapk/*.java -verbose -classpath $ANDROID_HOME/platforms/android-26/android.jar -d gen此时会在bin目录下生成如下文件:
1
2
3
4
5
6
7
8
9
10
11
12
13[min@TATEMIN-MB0:] main $ tree gen/
gen/
└── com
└── min
└── helloapk
├── MainActivity.class
├── R$attr.class
├── R$color.class
├── R$drawable.class
├── R$layout.class
├── R$mipmap.class
├── R$string.class
└── R.class创建Dex文件
1
2[min@TATEMIN-MB0:] main $ mkdir bin
[min@TATEMIN-MB0:] main $ dx --dex --verbose --output=bin/classes.dex gen此时会在bin目录下生成如下文件:
1
2
3[min@TATEMIN-MB0:] main $ tree bin/
bin/
└── classes.dex创建APK文件
1
[min@TATEMIN-MB0:] main $ aapt package -v -f -M AndroidManifest.xml -S res -I $ANDROID_HOME/platforms/android-26/android.jar -F bin/HelloAPK.unsigned.apk bin
此时会在bin目录下文件列表如下:
1
2
3
4[min@TATEMIN-MB0:] main $ tree bin/
bin/
├── HelloAPK.unsigned.apk
└── classes.dexAPK签名
1
[min@TATEMIN-MB0:] main $ jarsigner -verbose -keystore android.keystore -signedjar bin/HelloAPK.signed.apk bin/HelloAPK.unsigned.apk android.keystore
zipalign APK
1
zipalign -v -f 4 bin/HelloAPK.signed.apk bin/HelloAPK.apk
安装APK
1
[min@TATEMIN-MB0:] main $ adb install bin/HelloAPK.apk
运行APK
附录
如下是整个编译工程的Workspace:
1 | min@TATEMIN-MB0:] main $ tree |