APK 瘦身是很多公司忽略的问题,因为现在网速快速发展以及流量的降费,这个问题也越来越被忽略。但是大项目还是很在意瘦身的,支付宝对瘦身就做到了极致( 参考链接 )。
网上大部分的方案都是:
这些方案大部分都是在编写代码时期做的操作,容易出错和遗漏,我觉得这都算不上什么瘦身只能说是常识。于是我想能不能开发一款插件,在 APK 编译期间对 Apk 进行一系列的优化呢?
现在的 Android 集成开发工具 Android Studio 构建 APK 是通过 Gralde 脚本去构建, Gradle 完美兼容 Groovy Java Kotlin 语法。所以说 Android Studio 只是一个集成开发工具,没有这个工具我们也能 打包 运行 安装 APK 。
我们每个项目根路径都有一个 build.gradle 配置文件。开发 Android 根目录里面会配置一个 classpath 'com.android.tools.build:gradle:x.x.x' 的配置。这意思就是要 Android 的编译插件,这里面定义了所有的 Apk 打包,签名,安装等的一系列 Task 。
buildscript {
....
dependencies {
....
classpath 'com.android.tools.build:gradle:x.x.x'
}
}
复制代码
classpath 'com.android.tools.build:gradle:x.x.x' 是基于 Gralde 开发的,所以他们是有一个对应版本对象关系的。
一般我们升级自己项目的 Gralde 也需要去升级下 Android 编译插件。 查看版本对应关系
最后我们会在项目的 build.gradle 配置使用插件, apply plugin: 'com.android.application' 或 apply plugin: 'com.android.library' ,也就是使用插件啦。
根据上面的内容,我们知道了 APK 的打包流程,都是通过 apply plugin: 'com.android.application' 顺序执行 Task 完成的。我们来看看输出的有哪些 Task 吧。
在 App 项目中 build.gradle 编写以下代码。
project.afterEvaluate {
def tasks = ['preDebugBuild',
'compileDebugAidl',
'compileDebugRenderscript',
'checkDebugManifest',
'generateDebugBuildConfig',
'prepareLintJar',
'generateDebugResValues',
'generateDebugResources',
'mergeDebugResources',
'createDebugCompatibleScreenManifests',
'processDebugManifest',
'splitsDiscoveryTaskDebug',
'processDebugResources',
'generateDebugSources',
'javaPreCompileDebug',
'compileDebugJavaWithJavac',
'compileDebugNdk',
'compileDebugSources',
'mergeDebugShaders',
'compileDebugShaders',
'generateDebugAssets',
'mergeDebugAssets',
'transformClassesWithDexBuilderForDebug',
'transformDexArchiveWithExternalLibsDexMergerForDebug',
'transformDexArchiveWithDexMergerForDebug',
'mergeDebugJniLibFolders',
'transformNativeLibsWithMergeJniLibsForDebug',
'processDebugJavaRes',
'transformResourcesWithMergeJavaResForDebug',
'validateSigningDebug',
'packageDebug',
'assembleDebug'
]
for (String taskName : tasks) {
printTaskInputsOutputs(taskName)
}
}
def printTaskInputsOutputs(String taskName) {
def realTask = project.tasks.findByName(taskName)
if (realTask) {
println 'find ' + taskName + ' task -----------------------'
realTask.doLast {
realTask.inputs.files.each { fileTemp ->
println 'input file:' + fileTemp.absolutePath
}
println '---------------------------------------------------'
realTask.outputs.files.each { fileTemp ->
println 'output file:' + fileTemp.absolutePath
}
}
}
}
复制代码
我查看了部分 Task 的输入输出,并不是所有哦,大家可以自行输出一个项目的所有 Task 或者官网 Task 依赖关系(相信我你会疯掉的)。
大家用什么工具开发呢?我反正用的是 Android studio ,当然你也可以用 InteliJ IDEA 他俩兄弟都是可以通过 Gralde 构建项目的。
我用的是 Android studio ,因为是给 APP 用比较方便调试。
在工程目录中创建文件夹 buildSrc ,一定要是 buildSrc 文件夹哦。因为这样命名的项目,无需将插件项目打包在本地也可以在任意子项目使用插件(相当方便哦)。
创建 buildSrc/build.gradle 文件,编写以下内容,由于我用的是 Kotlin 编写,所以我依赖了 Kotlin 插件(也可以用 Groovy 语法哦)。
apply plugin: 'java'
apply plugin: 'kotlin'
sourceCompatibility = 1.8
buildscript {
ext.kotlin_version = '1.3.50'
repositories {
jcenter()
google()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
jcenter()
google()
}
}
dependencies {
implementation gradleApi()
implementation localGroovy()
implementation 'com.android.tools.build:gradle:3.3.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2'
implementation "pink.madis.apk.arsc:android-chunk-utils:0.0.7"
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
复制代码
buildSrc/src/main/java/com/qihoo/koimg/KoImgPlugin.kt ,插件的入口,所有的开始都是从个类出发。 class KoImgPlugin : Plugin<Project> {
override fun apply(project: Project) {
println("我要起飞来!!")
}
}
复制代码
项目创建路径 buildSrc/src/main/resources/META-INF/gradle-plugins/KoImg.properties (记住 KoImg.properties 的文件昵称,因为在子项目使用的的 apply plugin: 'XXX' ,用的就是这个文件的昵称) 文件里面的内容写 implementation-class=com.qihoo.koimg.KoImgPlugin ,第 2 步骤创建类的全路径名。
直接在应用项目的 build.gradle 加入 apply plugin: 'KoImg' 即可。
好啦,随便运行下,就能在 Build 控制台中看到。
这章节只负责教大家搭建一个简单的 Plugin 工程,以及 Apk 是如何编译的,下一篇正式讲解资源优化。