Android APK打包过程
打包过程如上图所示,下面具体介绍打包中涉及的每个工具的作用
aapt
aapt工具编译你的资源文件,比如AndroidManifest.xml,布局文件,字符串文件等,以此产生R.java
aidl
aidl工具则编译.aidl文件,形成对应的Java接口文件
javac
javac编译java文件,形成class文件
dex
dx工具转换.class文件、第三方library,得到dex字节码文件,最终可以打包到apk文件中
apkbuilder
apkbuilder打包未编译的资源文件,如图片、音频,还有编译过的资源文件、dex文件,形成apk文件
jarsigner
jarsigner使用keystore给apk文件签名
zipalign
zipalign工具对签名后的apk文件进行对齐操作,对齐操作可以使得应用减少内存的使用
最终打包的APK文件存放在目录app/build/outputs/apk/
内,包名为app-<flavor>-<buildtype>.apk
例如, app-full-release.apk and app-demo-debug.apk
Gradle基本配置
Android Studio项目中,包括一个位于根目录的build.gralde,另外每一个module还会包含一个build.gradle,一般情况下,我们只需要修改模块中的build.gradle【Gradle使用Groovy语法】
- 第一个例子{基本配置}
apply plugin: 'com.android.application'
android {
compileSdkVersion 19
buildToolsVersion "19.0.0"
defaultConfig {
applicationId "com.example.my.app"
minSdkVersion 8
targetSdkVersion 19
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile project(":lib")
compile 'com.android.support:appcompat-v7:19.0.1'
compile fileTree(dir: 'libs', include: ['*.jar'])
}
上方是常见的AS项目配置,apply plugin: 'com.android.application'
使得我们后面可以通过android {...}
标签做一些配置。
compileSdkVersion
指定编译Target
buildToolsVersion
指定Build工具
defaultConfig
这个参数使用AndroidManifest.xml
中的参数可以动态的配置,另外在这里配置的参数会覆盖AndroidManifest.xml
中的配置
buildTypes
这里的参数控制如何打包。默认会有release/debug两种类型。上面的例子中,release还定义了proguard信息
dependencies
定义本模块的依赖。构建系统会把依赖添加到编译中,并且放到最终的APK。其中compile project(":lib")
定义对模块的依赖,compile 'com.android.support:appcompat-v7:19.0.1'
定义对远程库的依赖,android默认使用Maven Central Repository作为远程仓库,如果你有依赖本地的jar文件,则把他们复制到<moduleName>/libs
,然后在build.gradle中写compile fileTree(dir: 'libs', include: ['*.jar'])
getDefaultProguardFile('proguard-android.txt')
获取Android SDK下默认的ProGuard设置。而你自己配置的Proguard可以放在模块根目录的proguard-rules.pro文件中
applicationId
定义了唯一的应用标识,在此定义的applicationId会覆盖AndroidManifest.xml中的package作为应该的唯一标识。但AndroidManifest.xml中的package也应该定义,它在源码中引用其他类文件(Activity/Service…)时有用到
- 第二个例子{多版本打包}
...
android {
...
defaultConfig { ... }
signingConfigs { ... }
buildTypes { ... }
productFlavors {
demo {
applicationId "com.example.creasylai19.pureandroidproject.demo"
versionName "1.0-demo"
}
full {
applicationId "com.example.creasylai19.pureandroidproject.full"
versionName "1.0-full"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
debuggable true
}
}}
...
如上所示,我们可以在同一个项目中通过productFlavors
变量构建不同的版本,如收费版、免费版,不同的版本可以有不同的功能,也可以为不同的版本使用不同的applicationId。除此之外,gradle还可以通过build types
变量应用不同的构建和打包设置。不同的productFlavors
和build type
组成不同的build variant
。Gradle根据build variant
产生不同的APK。
如上例子中,我们有demo版本、有full版本,他们SecondActivity不相同,其余的都相同,那我们只要在app/src目录下分别新建
- demo目录
app/src/demo/java
app/src/demo/res
app/src/demo/res/layout
app/src/demo/res/values
- full目录
app/src/full/java
app/src/full/res
app/src/full/res/layout
app/src/full/res/values
目录结构如下图
然后将不同的SecondActivity放在app/src/{demo|full}/java/{package}下,布局文件放在app/src/{demo|full}/res/layout下,则Android Studio会根据build.gradle中的productFlavors合并不同的资源目录,从而生成不同的demo版本APK(合并目录src/main和src/demo)和full版本APK(合并目录src/main和src/full)。src/main目录下的资源是不同的flavor公用的。