2024年大规模项目完全 gradle 化的一次落地总结(1),这些年我所经历的所有面试英文

写在最后

最后我想说:对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!

这里附上上述的技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。

相信它会给大家带来很多收获:

当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

def mustRunAfter(String dependentTaskName, Task task) {

Task dependentTask = tasks.findByPath(dependentTaskName)

if (dependentTask != null) {

dependentTask.mustRunAfter(task)

}

}

project.afterEvaluate {

def ndkBuildCmdArgs = project.hasProperty(“ndkBuildCmdArgs”) ? project.ndkBuildCmdArgs : []

def buildTypes = android.buildTypes.collect { type -> type.name }

def productFlavors = android.productFlavors.collect { flavor -> flavor.name }

if (!productFlavors) {

productFlavors.add(‘’)

}

productFlavors.each { productFlavorName ->

buildTypes.each { buildTypeName ->

def flavorNameCapitalized = “${productFlavorName.capitalize()}”

def buildNameCapitalized = “${buildTypeName.capitalize()}”

def targetName = “ f l a v o r N a m e C a p i t a l i z e d {flavorNameCapitalized} flavorNameCapitalized{buildNameCapitalized}”

def ndkCmdBuildTaskName = “compile${targetName}NdkBuildCmd”

def ndkCmdBuildTask = tasks.create(name: ndkCmdBuildTaskName, type: Exec) {

group = “other”

description = “ndk build with cmd style for ${targetName}.”

doFirst {

println(“${project.name} start ndk build use cmd…”)

def ndkDir = System.getenv(“ANDROID_NDK_HOME”)

if (ndkDir == null) {

Properties properties = new Properties()

properties.load(new FileReader(“$rootDir/local.properties”))

ndkDir = properties.getProperty(“ndk.dir”)

}

println(“#command is# ${ndkDir}/ndk-build ${ndkBuildCmdArgs}”)

if (ndkDir != null) {

if (org.gradle.internal.os.OperatingSystem.current().isWindows()) {

commandLine(“${ndkDir}\ndk-build.cmd”, *ndkBuildCmdArgs)

} else {

commandLine(“${ndkDir}/ndk-build”, *ndkBuildCmdArgs)

}

} else {

commandLine “echo”, “ndk path is null, please check you environment(example: export ANDROID_NDK_HOME=/opt/android-ndk-r10d, the key must named as ANDROID_NDK_HOME)!”

}

}

if (ndkBuildCmdArgs.size() == 0) {

enabled = false

}

}

//runBefore(“pre${targetName}Build”, ndkCmdBuildTask)

runBefore(“compile${targetName}Ndk”, ndkCmdBuildTask)

//按照源码里几个 task 都处理下!

mustRunAfter(“compile${targetName}Renderscript”, ndkCmdBuildTask)

mustRunAfter(“merge${targetName}JniLibFolders”, ndkCmdBuildTask)

mustRunAfter(“transformNativeLibsWithIntermediateJniLibsFor${targetName}”, ndkCmdBuildTask)

mustRunAfter(“transformNativeLibsWithMergeJniLibsFor${targetName}AndroidTest”, ndkCmdBuildTask)

mustRunAfter(“transformNativeLibsWithMergeJniLibsFor${targetName}”, ndkCmdBuildTask)

mustRunAfter(“transformNativeLibsWithStripDebugSymbolFor${targetName}”, ndkCmdBuildTask)

mustRunAfter(“transformNativeLibsWithSyncJniLibsFor${targetName}”, ndkCmdBuildTask)

}

}

def ndkCmdBuildCleanTask = tasks.create(name: “ndkCmdBuildClean”, type: Delete) {

group = “build”

description = “clean the build of ndk build with cmd.”

def ndkBuildCmdClean = project.hasProperty(“ndkBuildCmdClean”) ? project.ndkBuildCmdClean : []

if (ndkBuildCmdClean.size() == 0) {

enabled = false

}

doFirst {

delete ndkBuildCmdClean

}

}

runBefore(“clean”, ndkCmdBuildCleanTask)

}

如上实现了一个全新的构建 task,叫做compile${targetName}NdkBuildCmd,so 的构建都通过他来处理,需要构建项目如下配置即可:

apply from: ‘…/…/build_common.gradle’

apply from: ‘…/…/ndk_cmd_build.gradle’

ext {

ndkBuildCmdArgs = [‘-C’, file(‘jni’).absolutePath, ‘-j’, Runtime.runtime.availableProcessors(), ‘NDK_DEBUG=0’]

ndkBuildCmdClean = [file(‘libs’), file(‘obj’)]

}

android {

sourceSets {

main {

jniLibs.srcDir ‘libs’

java.srcDirs = [‘src’, ‘androidImpl’]

}

}

}

这样在构建时就能看到 so 了,也就解决这个问题。还是要升级 gradle 就美了,就能迁移到官方标准参数了,因为高版本 gradle 已经完美支持参数配置了。

多 dex 爆炸问题

我们的 dex 分包是在主项目合并后的结果中依据包目录结构和 jar 包路径进行划分剪切到对应 dex 目录实现的,原来 ant 构建很多路径在现有的多 dex 插件分包规则中已经不匹配,所以一上来构建就炸了,按照规则重新适配即可解决。

apk 大小对比分析及 dex 打错问题

一切构建都通过了,接下来就是二次确认,所以确认操作就是通过我们多 dex 构建的 log 去排查有没有打串或者打错 dex 目录结构的,确认后进行微调即可。

apk 大小是通过 AS 的分析工具进行处理的,简单来说就是对比即可,首先构建一个 ant 包,接着构建一个同一基线的 gradle 包,然后通过 AS 分析工具的 compare 进行对比生成差异清单,看下多打了什么,然后删除多打的东西即可。

定位 apk 多打入莫名其妙东西和少打入一些东西的问题

通过 gradle 构建后的包确实多了一些东西,譬如 xml、assert、okhttp 的一些文件等。这些文件需要处理掉,如下:

android {

//打包时不打入assert目录下的指定资源

aaptOptions {

//https://stackoverflow.com/questions/25910206/gradle-exclude-file-from-android-assets-folder

ignoreAssetsPattern “!xxxx”

}

//不打包的东西

packagingOptions {

exclude ‘xxx/xxx/*.xml’

//…

}

}

接着就是少打入东西的问题,原因其实就是原来 eclipse 项目,有一些配置文件放在项目的 src 目录下的,所以 gradle java 构建 jar 默认是不包含的,因此想让这些位于 src 下的配置文件打入最终 apk 的根目录就需要如下配置:

apply from: ‘…/build_java.gradle’

processResources {

from(‘src’) {

include ‘xxxx.json’

include ‘xxxx.types’

include ‘sdk-xxx.txt’

include ‘xxx-certs.crt’

}

}

如上方式打包出来的 apk 根目录下就自动有这些配置文件了。

启动 apk 加载 assert 下指定文件崩溃

这个问题是因为 aapt 在打包时会对 assert 目录下的一些非特定后缀文件进行压缩,所以 app 中直接 assert 读取时就会提示格式错误异常,解决这个问题也很容易,如下:

android {

//指定后缀文件不压缩

aaptOptions {

noCompress “tflite”

}

}

sourceSet 不覆盖问题

这个问题是因为 apply 了一些 common 的 gradle 文件,其中已经定义了 sourceSet,如果当前文件对 sourceSet 进行 include 新目录会导致原来 common 里面的目录失效,所以需要完全重写即可。

windows ndk 问题

这个问题十分坑爹,linux 构建完全没问题,windows 下构建 ndk 出问题,构建 log 看到的 path 总是没转义的,奇怪了很久,发下那是自己修改的问题,其实就是Android.mk中的路径结尾少加了字符串换行连接操作,如下:

//缩略样例

export include = $(path)/ \

Application.mkAPP_PLATFORM := android-14无效问题

最后

Android学习是一条漫长的道路,我们要学习的东西不仅仅只有表面的 技术,还要深入底层,弄明白下面的 原理,只有这样,我们才能够提高自己的竞争力,在当今这个竞争激烈的世界里立足。

人生不可能一帆风顺,有高峰自然有低谷,要相信,那些打不倒我们的,终将使我们更强大,要做自己的摆渡人。

资源持续更新中,欢迎大家一起学习和探讨。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

我们要学习的东西不仅仅只有表面的 技术,还要深入底层,弄明白下面的 原理,只有这样,我们才能够提高自己的竞争力,在当今这个竞争激烈的世界里立足。

人生不可能一帆风顺,有高峰自然有低谷,要相信,那些打不倒我们的,终将使我们更强大,要做自己的摆渡人。

资源持续更新中,欢迎大家一起学习和探讨。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值