如何为不同Build Flavors打包对应*.so文件?求gradle脚本
Got it, let's get your ABI-specific APKs sorted out. You want each build flavor to only package the corresponding .so files, right? Here's how to tweak your Gradle scripts to make that work perfectly.
Step 1: Update your library.gradle (minor adjustments)
Your library module is already set up correctly to serve all pre-compiled .so files, so we only need to confirm the jniLibs path stays intact. No major changes here—just keep the existing configuration since it points to your pre-built .so directories:
apply plugin: 'com.android.library' import com.android.builder.core.DefaultManifestParser android { compileSdkVersion rootProject.ext.compileSdkVersion buildToolsVersion rootProject.ext.buildToolsVersion sourceSets { main { jni.srcDirs = [] // Prevent gradle from building native code with ndk; we have our own Makefile for it. jniLibs.srcDirs = ['jni/libs', 'jni/loader/libs', 'private_libs/libs'] // Where generated .so files are placed. manifest.srcFile 'AndroidManifest.xml' java.srcDirs = ['src'] resources.srcDirs = ['src'] aidl.srcDirs = ['src'] renderscript.srcDirs = ['src'] res.srcDirs = ['res'] assets.srcDirs = ['assets'] } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' } } // Make per-variant version code libraryVariants.all { variant -> def manifestParser = new DefaultManifestParser(android.sourceSets.main.manifest.srcFile) // get the version code of each flavor def version = manifestParser.getVersionName() //Custom APK name variant.outputs.all { output -> if (outputFileName != null && outputFileName.endsWith('.aar')) { outputFileName = "lib-${version}.aar" } } } } // Keep all your BuildNative tasks and other existing configurations below this point
Step 2: Modify app.gradle to enable ABI-specific packaging
This is where the magic happens. We'll add ABI filters to each flavor and dynamically configure packaging rules to only include the relevant .so files:
apply plugin: 'com.android.application' android { packagingOptions { // Base placeholder—we'll override this per variant } dexOptions { maxProcessCount 8 javaMaxHeapSize "2g" preDexLibraries true keepRuntimeAnnotatedClasses false } compileSdkVersion rootProject.ext.compileSdkVersion buildToolsVersion rootProject.ext.buildToolsVersion flavorDimensions "target", "abi" defaultConfig { applicationId "com.example" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode rootProject.ext.versionCode versionName rootProject.ext.versionName vectorDrawables.useSupportLibrary true multiDexEnabled true } signingConfigs { release { storeFile file("D:\\Keystore\\aaaaaaaa.jks") storePassword "aaaaaaa" keyAlias "avbbaaaaaa" keyPassword "ababababa" } } buildTypes { release { signingConfig null minifyEnabled true shrinkResources false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } lintOptions { checkReleaseBuilds false abortOnError false } dataBinding { enabled = true } productFlavors { vanilla { dimension "target" versionCode = 1 } chrome { minSdkVersion 19 dimension "target" versionCode = 2 } ARMv7 { dimension "abi" versionCode = 4 ndk { abiFilters "armeabi-v7a" } } x86 { dimension "abi" versionCode = 5 ndk { abiFilters "x86" } } // Optional: Remove MIPS flavors (no modern Android devices support them) // MIPS { // dimension "abi" // versionCode = 6 // ndk { // abiFilters "mips" // } // } ARMv8 { dimension "abi" versionCode = 7 ndk { abiFilters "arm64-v8a" } } x86_64 { dimension "abi" versionCode = 8 ndk { abiFilters "x86_64" } } // MIPS64 { // dimension "abi" // versionCode = 9 // ndk { // abiFilters "mips64" // } // } } // Dynamically configure packaging for each variant applicationVariants.all { variant -> def abiFlavor = variant.productFlavors.find { it.dimension == "abi" } if (abiFlavor != null) { def targetAbi = "" switch(abiFlavor.name) { case "ARMv7": targetAbi = "armeabi-v7a" break case "ARMv8": targetAbi = "arm64-v8a" break case "x86": targetAbi = "x86" break case "x86_64": targetAbi = "x86_64" break // case "MIPS": // targetAbi = "mips" // break // case "MIPS64": // targetAbi = "mips64" // break } // Ensure only the target ABI is packaged variant.ndk.abiFilters.clear() variant.ndk.abiFilters.add(targetAbi) // Exclude all other ABI directories, keep only the target variant.packagingOptions.exclude("lib/*") variant.packagingOptions.include("lib/${targetAbi}/**") } } } // Keep your dependencies block unchanged here
Key Changes Explained
- ABI Filters per Flavor: Each ABI flavor now has an
ndk.abiFilterssetting that tells Gradle exactly which architecture's .so files to include. - Dynamic Packaging Rules: The
applicationVariants.allblock ensures every build variant only keeps the relevant .so directory, eliminating any chance of extra files being bundled. - MIPS Removal: MIPS/MIPS64 architectures are no longer supported by modern Android devices—removing these flavors reduces unnecessary build time and APK bloat.
How to Test
Build any ABI-specific variant (e.g., vanillaARMv7Release), then extract the APK and check the lib directory. You'll only see the corresponding architecture folder and its .so files.
内容的提问来源于stack exchange,提问作者Jitendra Singh

