AppMetrica Gradle Plugin

AppMetrica lets you collect information about native and Java crashes. You can analyze them in the Crashes report. See also Crashes/errors.

To reduce the size of an app, optimize the code during a release build.

If the code was compressed and obfuscated during the build of an Android application, information about crashes is transmitted in obfuscated form. To extract data for analysis from such crash logs, AppMetrica performs server-side deobfuscation.

To do this, upload the mapping files or debug symbols of SO files to AppMetrica, either automatically when building the app or manually via the web interface.

To send files, enable the AppMetrica Gradle Plugin.

Restrictions

  • The plugin is applied only to modules with com.android.application. It is not applied to com.android.library modules.

  • Upload mapping files if you use ProGuard or R8. If you don't compress or obfuscate the code, don't enable the plugin.

  • The plugin's operation depends on the versions of com.android.tools.build:gradle (AGP) and gradle. The plugin is compatible with the following versions:

    • com.android.tools.build:gradle from 7.2.0 to 8.13.+ (except for 8.0.+);
    • gradle from 7.4 to 9.2.1. We don't guarantee that the plugin will work with other versions.

    The plugin's functionality is not guaranteed when using Gradle 8.0 and AGP 7.4.* together.

  • For local builds, it is recommended to disable the plugin — this speeds up the build. Enable it only on CI. A convenient pattern is to control the enable flag through an environment variable:

    appmetrica {
        enable.set(providers.environmentVariable("CI").map { it == "true" }.orElse(false))
    }
    

Connecting the plugin

To enable the plugin:

  1. Add the following dependency to the Gradle root file:

    plugins {
        id("io.appmetrica.analytics") version "2.1.0" apply false
    }
    
    Enabling plugin using buildscript

    Add the following dependency to the Gradle root file:

    buildscript {
       repositories {
           mavenCentral()
       }
       dependencies {
           classpath("io.appmetrica.analytics:gradle:2.1.0")
       }
    }
    
  2. Add the plugin and a minimal configuration to the app's Gradle file:

    plugins {
        id("com.android.application")
        id("io.appmetrica.analytics")
    }
    
    appmetrica {
        postApiKey.set("Post Api key")
        ndk {
            enable.set(true) // Optional. Enable if your project has native code and you need native crashes
        }
    }
    

    The rest of the parameters and their default values are described in Plugin parameters.

Common tasks

In the typical case, you don't need to change any settings: enable defaults to true only for buildType = 'release', and ndk.enable defaults to false (enable it only if your project has native code and you need native crashes). So for a project without obfuscation outside of release and without NDK symbols, the plugin already works optimally out of the box.

Collect mapping and NDK symbols for a separate non-release buildType without spending the upload quota

This is needed, for example, if a separate non-release buildType (say, snapshot) also needs mapping and NDK symbols — but you don't want to spend the daily upload quota on that build. Since enable, offline, and ndk.enable are resolved separately for each build variant, override them for the specific buildType through hierarchical configuration (see Hierarchical configuration):

android {
    buildTypes {
        // Besides release, mapping and NDK symbols are also needed for the snapshot build
        named("snapshot") {
            appmetrica {
                // By default enable=true only for release — enable it explicitly for snapshot,
                // otherwise mapping will neither be collected nor uploaded
                enable.set(true)

                ndk {
                    // By default ndk.enable=false — enable it explicitly for snapshot,
                    // otherwise NDK symbols won't be collected
                    enable.set(true)
                }

                // To avoid spending the daily upload quota on snapshot, don't upload mapping
                // and symbols automatically. They will still be collected locally in
                // build/appmetrica/<variant>/result, and you can upload them manually later,
                // see "Manual loading"
                offline.set(true)
            }
        }
    }
}

appmetrica {
    // postApiKey is set once in the global block and applies to all variants,
    // including snapshot above — no need to set it again in a per-buildType block
    // (otherwise, with different values, you'll get "Conflicting values for postApiKey")
    postApiKey.set("Post Api key")
}

Plugin parameters

Example configuration with all available parameters:

appmetrica {
    postApiKey.set("Post Api key")
    enable.set(true)                                    // Optional
    offline.set(false)                                  // Optional
    mappingFile.set(file("path/to/mapping.txt"))        // Optional
    enableAnalytics.set(true)                           // Optional
    allowTwoAppMetricas.set(false)                      // Optional
    ndk {                                               // Optional
        enable.set(false)
        soFiles.from(file("path/to/so"))                // Optional
        additionalSoFiles.from(file("path/to/extra"))   // Optional
        addNdkCrashesDependency.set(true)               // Optional
    }
}

Parameter

Description

postApiKey*

Post API key. String.
You can get the Post API key in the Settings section in AppMetrica. It's used to identify your app.

If offline = true, the parameter is optional.

Note on hierarchical configuration: the value must match across all sources where it is set. If different sources specify different values, the plugin logs an error and treats the key as not set (see Hierarchical configuration).

enable

Enables or disables the plugin for the given build variant. Boolean.
If the plugin is disabled, the apk is not changed, mapping is neither collected nor uploaded, and resource generation is not performed.

Doesn't affect collecting or uploading NDK symbols — that's controlled by the independent ndk.enable parameter (see below).

By default, true only for buildType = 'release', otherwise false.

Supports hierarchical configuration (see Hierarchical configuration).

offline

Enables the offline mode. Boolean.

Affects the upload of both mapping and NDK symbols at the same time (regardless of whether enable or ndk.enable is on — offline mode is shared between both).

Acceptable values:

  • true — Doesn't upload either mapping or symbols to AppMetrica. Archives are placed in build/appmetrica/<variant>/result/, paths are written to the log. You can upload the archives manually via the web interface.
  • false — Automatically uploads mapping and symbols.

The default value is false.

Supports hierarchical configuration (see Hierarchical configuration).

mappingFile

Path to the mapping file. RegularFileProperty (in Kotlin DSL set via file("...")).

The default value is the mapping file from the build (the OBFUSCATION_MAPPING_FILE AGP artifact). Override it only if you want to upload mapping from a non-standard location.

Supports hierarchical configuration (see Hierarchical configuration).

enableAnalytics

Lets plugin usage statistics be sent to AppMetrica. Boolean.

Acceptable values:

  • true — Sending statistics is enabled.
  • false — Sending statistics is disabled.

The default value is true.

allowTwoAppMetricas

Behavior when two different AppMetrica libraries (io.appmetrica.analytics:analytics and com.yandex.android:mobmetricalib) are present in the project at the same time. Boolean.

Acceptable values:

  • false — If both libraries are found, the build fails with an error.
  • true — The presence of both libraries is allowed, a warning is written to the log.

The default value is false.

Supports hierarchical configuration (see Hierarchical configuration).

ndk

This parameter is required to load symbols from the SO file to track native crashes.

ndk.enable

Enables or disables processing and uploading symbols from SO files. Boolean.

If enabled, symbol processing and upload tasks run automatically after the build.

The default value is false.

Supports hierarchical configuration (see Hierarchical configuration).

ndk.soFiles

SO files to process. ConfigurableFileCollection. Use .from(...) to add files.

By default, the plugin takes SO files from the MERGED_NATIVE_LIBS AGP artifact — this already includes src/main/jniLibs/** and the output of CMake/ndk-build.

Override it if your SO files are in a non-standard location or the plugin can't find them.

Hierarchical configuration behavior: collections from all sources are merged (see Hierarchical configuration).

ndk.additionalSoFiles

Additional SO files. ConfigurableFileCollection. Use .from(...) to add files.

Unlike soFiles, it doesn't replace the default but extends it.

Hierarchical configuration behavior: collections from all sources are merged.

ndk.addNdkCrashesDependency

Automatically add the io.appmetrica.analytics:analytics-ndk-crashes dependency to the <variant>Implementation configuration. Boolean.

The default value is true.

Supports hierarchical configuration (see Hierarchical configuration).

Note

If the ndk.enable parameter is enabled, symbol processing and upload tasks run automatically after the build. No additional manual configuration is required.

Hierarchical configuration

The plugin supports four configuration levels:

appmetrica {
    // Global configuration
    variants {
        create("<variantName>") {
            // Variant configuration
        }
    }
}

android {
    buildTypes {
        named("<buildTypeName>") {
            appmetrica {
                // buildType configuration
            }
        }
    }
    productFlavors {
        named("<flavorName>") {
            appmetrica {
                // flavor configuration
            }
        }
    }
}

Note

For each build variant, the plugin collects values from all levels and applies a resolution strategy to them — each parameter has its own. This is not the "usual" priority where "the top level wins" — the behavior depends on the parameter type.

enable, offline, ndk.enable, allowTwoAppMetricas, enableAnalytics, ndk.addNdkCrashesDependency

Logic: "disabling always wins".

  • If at least one source has the value false — the result is false.
  • Otherwise, if at least one source has the value true — the result is true.
  • Otherwise, the default value is used.

Example:

appmetrica {
    enable.set(true)
}

android {
    buildTypes {
       debug {
           appmetrica {
               enable.set(false)
           }
       }
    }
}

As a result, enable is false for debug and true for all other variants.

postApiKey

Logic: "the value must be unique".

  • If the parameter is set in only one source — that value is used.
  • If it is set in several sources with the same value — that value is used.
  • If different sources specify different values — the error Conflicting values for postApiKey is logged, and the default value (an empty string) is used. Upload then won't happen — the plugin additionally emits the warning postApiKey is not set.

Therefore, set postApiKey only in one place — usually in the global block or in the relevant flavor.

mappingFile

Logic: "priority lookup".

Source priority: global block > per-variant > per-buildType > the first configured flavor > default value (mapping from the build). The value from the first source where the parameter is set is used.

ndk.soFiles, ndk.additionalSoFiles

Logic: "collection merging".

All non-empty .from(...) from all levels are merged into a single collection. If the collection is not configured at any level — soFiles falls back to the AGP default, and additionalSoFiles falls back to an empty collection. To replace the default set of files, set soFiles.from(...) in one of the sources — the default is then not used.

Example

// Global settings for all variants
appmetrica {
    enableAnalytics.set(true)
}

android {
    buildTypes {
        release {
            // NDK symbol upload is needed only for release builds
            appmetrica {
                ndk {
                    enable.set(true)
                }
            }
        }
    }

    productFlavors {
        // Each flavor has its own key — for example, different apps for prod and dev
        create("prod") {
            appmetrica {
                postApiKey.set("prod-post-api-key")
            }
        }
        create("dev") {
            appmetrica {
                postApiKey.set("dev-post-api-key")
            }
        }
    }
}

// Per-variant: targeted override for a specific variant
appmetrica {
    variants.create("prodRelease") {
        ndk {
            additionalSoFiles.from(file("extra-symbols"))
        }
    }
}

Tip

To find out which values the plugin actually applied to a variant, look at the build log: for each parameter, a line is written in the form Using value 'X' from <source> for <parameter> or Using default value '...' for ....

Manual loading

For manual upload, set offline = true mode. This is needed so that the plugin generates info.txt with meta information, by which the server will associate the archive with the build.

  1. In the app/build.gradle file, turn on offline mode:

    appmetrica {
        offline.set(true)
    }
    

    In offline mode, the postApiKey parameter is optional.

  2. Build the desired variant of the application (for example, ./gradlew assembleRelease). Archives will appear in <appModule>/build/appmetrica/<variant>/result/:

    • mapping.zip — for Java crashes;
    • symbols.zip — for native crashes, if ndk.enable is enabled.
  3. In the AppMetrica interface, go to the app settings from the menu on the left.

  4. Go to the CrashesAndroid tab.

  5. Click Choose file and upload the desired archive.

Plugin tasks

For each build variant <variant> (Release, ProdRelease, etc.), the plugin registers the following tasks:

Task name

Purpose

check<variant>AppMetricaDependencies

Checks that exactly one AppMetrica library is used in the project (see allowTwoAppMetricas).

create<variant>AppMetricaRes

Generates resources in build/appmetrica/<variant>/res/; the result is merged into the application resources.

zip<variant>AppMetricaFiles

Builds mapping.zip (info.txt + mapping).

upload<variant>AppMetricaMapping

Uploads mapping.zip to AppMetrica (in offline mode — skipped, the archive remains in result/).

generate<variant>AppMetricaNdkSymbols

Converts SO files to .ysym.

zip<variant>AppMetricaNdkFiles

Builds symbols.zip (info.txt + .ysym).

upload<variant>AppMetricaNdkSymbols

Uploads symbols.zip to AppMetrica.

Upload tasks are wired as finalizedBy on assemble<variant> and bundle<variant>. Therefore, a regular build (./gradlew assembleRelease or ./gradlew bundleRelease) automatically triggers the upload. You can run the upload manually like this:

./gradlew uploadReleaseAppMetricaMapping
./gradlew uploadReleaseAppMetricaNdkSymbols

Build errors and warnings

Errors that interrupt the build

  • IllegalStateException — Code obfuscation is not enabled. Enable ProGuard or R8.
  • HttpResponseException — The archive could not be uploaded. Check your internet connection and the correctness of postApiKey.
  • Dependency check error — Two AppMetrica libraries (io.appmetrica.analytics:analytics and com.yandex.android:mobmetricalib) are found in the project at the same time. Remove one of them or, temporarily, set allowTwoAppMetricas = true.

Warnings (the build does not fail, but upload may not happen)

These messages are important to monitor, especially on CI — they mean that something went wrong, but Gradle won't report it.

  • AppMetrica plugin is enabled for variant '<variant>' but postApiKey is not set. Upload will fail. Set postApiKey or enable offline mode. — Upload is enabled for the variant, but the key is empty. Set postApiKey or enable offline.
  • Conflicting values for postApiKey: ...postApiKey is set in different sources with different values. The plugin uses an empty key — the upload will fail. Set the key in only one place or synchronize the values.
  • Using default value '...' for <parameter> — The parameter is not set in any source, the default is used. Useful for debugging if it seems that a setting "did not apply".

If you encounter other errors, please contact technical support.

Learn more

If you didn't find the answer you were looking for, you can use the feedback form to submit your question. Please describe the problem in as much detail as possible. Attach a screenshot if possible.

Contact support Suggest an improvement for documentation