Android特有配置:minSdk/targetSdk/compileSdk、ndkVersion、aaptOptions、dexOptions、资源优化

说实话,Android的Gradle配置里,有一块内容是纯纯的「Android味儿」。不像依赖管理或者构建变体那样通用,这些配置只属于Android生态。今天我们就来聊聊这些特有配置,我把它们分成三块:SDK版本三兄弟、NDK与AAPT、以及Dex与资源优化。

1. SDK版本三兄弟:minSdk、targetSdk、compileSdk

这三个字段,几乎是每个Android项目的标配。但很多人只是照着模板填,并不清楚它们各自管什么。我刚开始做Android时也犯过糊涂——把compileSdk和targetSdk当成一回事,结果踩了不少坑。

核心区别一句话总结:

  • compileSdk:告诉Gradle,你可以用哪个版本的API来编译代码。
  • minSdk:你的App最低能跑在哪个Android版本上。
  • targetSdk:你声明自己已经针对哪个API版本做过充分测试。

举个例子,你compileSdk设成34,就能用Android 14的新API。但minSdk设成21,意味着App在Android 5.0上也能安装。targetSdk设成33,表示你在Android 13上测试过,系统不会对你做向后兼容的行为变更。

我个人习惯是:compileSdk永远用最新,这样能第一时间用上新API和lint检查。targetSdk我会比compileSdk低一个版本,等充分测试后再追平。minSdk则根据产品需求定,一般我会设成当前市场占有率前95%的最低版本。

我曾经踩过的坑:有一次我把targetSdk从30升到31,结果App在Android 12上启动就崩溃。查了半天,原来是Android 12对PendingIntent的FLAG_IMMUTABLE要求更严格了。所以升级targetSdk时,一定要仔细看行为变更文档。

2. ndkVersion:NDK版本锁定

如果你的项目用到了C/C++代码(比如通过JNI调用),那就需要配置NDK版本。以前很多人不写ndkVersion,让Gradle自动选。但这样有个问题——不同开发机上的NDK版本可能不一样,导致编译结果不一致。

我建议在android块里显式声明:

android {
    ndkVersion "25.1.8937393"
}

这样团队里所有人都用同一个NDK版本,避免「我这儿能编译,你那儿不行」的尴尬。你可以在local.properties里指定本地NDK路径,但版本号还是写在build.gradle里更靠谱。

3. aaptOptions:资源打包的精细控制

aaptOptions控制的是Android资源打包工具(AAPT2)的行为。说实话,大部分项目不需要动它。但如果你遇到资源冲突或者想压缩资源,这里就有用武之地了。

常用的几个配置:

android {
    aaptOptions {
        // 忽略某些资源文件
        ignoreAssetsPattern "!*.bak:!*.swp"
        // 关闭PNG压缩(加快构建速度)
        cruncherEnabled false
        // 额外传递给AAPT的参数
        additionalParameters "--no-version-vectors"
    }
}

我记得有个项目,资源文件里混入了很多.bak备份文件,导致APK体积莫名其妙变大。加上ignoreAssetsPattern后,问题立刻解决。

小技巧:如果你用Vector Drawable,可以加上--no-version-vectors参数。这样AAPT不会为低版本生成PNG回退图,能省不少APK体积。

4. dexOptions:DEX文件的调优

DEX是Android的可执行文件格式。当你的代码量很大时,DEX配置就变得重要了。尤其是方法数超过65535时,你需要开启MultiDex。

常见的dexOptions配置:

android {
    dexOptions {
        // 最大堆内存,防止OOM
        javaMaxHeapSize "4g"
        // 是否预编译DEX(加快构建)
        preDexLibraries true
        // 线程数
        maxProcessCount 4
    }
}

这里我要特别说一下javaMaxHeapSize。如果你在构建时遇到OutOfMemoryError,八成是DEX编译时堆内存不够。我一般设成4g,如果项目特别大,可以设到6g甚至8g。

注意:preDexLibraries在Android Gradle Plugin 3.0以后默认就是true,而且效果有限。如果你用Instant Run或者新版的构建缓存,这个配置基本不用动。

5. 资源优化:shrinkResources与resConfigs

资源优化是APK瘦身的利器。两个最常用的配置:shrinkResourcesresConfigs

shrinkResources:配合ProGuard/R8使用,自动移除未引用的资源。

android {
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

resConfigs:只保留你需要的语言资源,去掉那些用不上的翻译。

android {
    defaultConfig {
        resConfigs "zh", "en"
    }
}

我做过一个项目,只支持中文和英文,但依赖的第三方库带了30多种语言资源。加上resConfigs "zh", "en"后,APK直接瘦了2MB。你想想看,这效果多明显。

避坑指南:shrinkResources一定要配合minifyEnabled使用,否则不会生效。而且它只移除未引用的资源,不会帮你压缩图片。图片压缩还得靠WebP或者TinyPNG。

知识体系总览

下面这张图把本章的核心知识点串了起来,方便你对照理解:

Android特有配置知识体系 Android特有配置 SDK版本三兄弟 compileSdk:编译API版本 minSdk:最低支持版本 targetSdk:目标测试版本 NDK版本锁定 ndkVersion 显式声明 团队统一版本 避免编译不一致 AAPT资源控制 ignoreAssetsPattern cruncherEnabled additionalParameters DEX调优 javaMaxHeapSize preDexLibraries maxProcessCount 资源优化 shrinkResources resConfigs 图片压缩(WebP)

这张图把五个核心配置模块串在了一起。你可以看到,SDK版本是基础,NDK和AAPT是进阶控制,DEX和资源优化则是构建后期的调优手段。每个模块之间没有强依赖关系,但组合起来能让你的构建配置更健壮、更高效。

好了,这一章的内容就到这里。配置这东西,光看文档是不够的,建议你打开自己的项目,对照着检查一遍。尤其是shrinkResourcesresConfigs,改完立竿见影。

公众号:蓝海资料掘金营,微信deep3321