Search code examples
androidandroid-studiogradleandroid-gradle-pluginproguard

Android ProGuard multiple mapping files for split APKs?


I am successfully generating signed APKs in Android studio, splitting them by ABI and assigning a different versionCode for each, by adding the following code to my build.gradle file:

// Map for the version code that gives each ABI a value.
ext.abiCodes = ["armeabi-v7a":1, "arm64-v8a":2, "x86":3, "x86_64":4]

import com.android.build.OutputFile

// For each APK output variant, override versionCode with a combination of
// ext.abiCodes + variant.versionCode. In this example, variant.versionCode
// is equal to defaultConfig.versionCode. If you configure product flavors that
// define their own versionCode, variant.versionCode uses that value instead.
android.applicationVariants.all { variant ->

    // Assigns a different version code for each output APK
    // other than the universal APK.
    variant.outputs.each { output ->
        // Stores the value of ext.abiCodes that is associated with the ABI for this variant.
        def baseAbiVersionCode =
                // Determines the ABI for this variant and returns the mapped value.
                project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))

        // Because abiCodes.get() returns null for ABIs that are not mapped by ext.abiCodes,
        // the following code does not override the version code for universal APKs.
        // However, because we want universal APKs to have the lowest version code,
        // this outcome is desirable.
        if (baseAbiVersionCode != null) {

            // Assigns the new version code to versionCodeOverride, which changes the version code
            // for only the output APK, not for the variant itself. Skipping this step simply
            // causes Gradle to use the value of variant.versionCode for the APK.
            output.versionCodeOverride =
                    baseAbiVersionCode + variant.versionCode
        }
    }
}

Now, I want to use ProGuard (minifyEnabled true) to obfuscate my code. As stated in the official android documentation, it is important to keep the mapping.txt files for each APK you release in order to decrypt a crash report's obfuscated stack trace received via the Google Play Developer Console. But when I generate the APKs split by ABI, I only find one mapping.txt file in the <module-name>/build/outputs/mapping/release/ directory.

My question: Could someone please confirm that this single mapping.txt file will allow me to decode obfuscated stack traces for the 4 APKs which were split by ABI? If not, how can I generate the 4 different mapping files?

I tried generating the different mapping files based on a snippet I found in this post, essentially trying to copy and rename the mapping.txt files as they are created during the multi APK generation process but I still only get one single mapping file:

applicationVariants.all { variant ->
    if (variant.getBuildType().isMinifyEnabled()) {
        variant.assemble.doLast {
            copy {
                from variant.mappingFile
                into "${rootDir}/proguardTools"
                rename { String fileName ->
                    "mapping-${variant.name}.txt"
                }
            }
        }
    }
}

I am very new to gradle and I find its syntax quite confusing. Any help would be very much appreciated.


Solution

  • I ended up testing the stack trace deobfuscation with Firebase Crash Reporting (i.e. without having to deploy a crash test version of my app to the google play store) and I can confirm that the one mapping.txt file created when generating the signed APKs in Android Studio does correctly deobfuscate stack traces for crashes occurring on APKs corresponding to different ABI types.