---
metadata:
  - name: generator
    content: Diplodoc Platform v5.50.6
alternate:
  - https://appmetrica.yandex.by/docs/en/sdk/android/analytics/android-gradle-plugin.md
  - https://appmetrica.yandex.by/docs/ru/sdk/android/analytics/android-gradle-plugin.md
---
> **Documentation Index:** Fetch the complete configuration index at https://appmetrica.yandex.by/docs/en/llms.txt

# AppMetrica Gradle Plugin

AppMetrica lets you collect information about native and Java crashes. You can analyze them in the [Crashes](https://appmetrica.yandex.by/docs/en/mobile-reports/crashes-and-errors.md) report. See also [Crashes/errors](https://appmetrica.yandex.by/docs/en/data-collection/about-crashes-and-errors.md).

To reduce the size of an app, [optimize](https://developer.android.com/studio/build/shrink-code) 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 {#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](https://www.guardsquare.com/en/products/proguard/manual) or [R8](https://r8.googlesource.com/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:

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

## Connecting the plugin {#connecting}

To enable the plugin:

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

   ```kotlin translate=no
   plugins {
       id("io.appmetrica.analytics") version "2.1.0" apply false
   }
   ```

   {% cut "Enabling plugin using `buildscript`" %}

   Add the following dependency to the Gradle root file:

   ```kotlin translate=no
   buildscript {
      repositories {
          mavenCentral()
      }
      dependencies {
          classpath("io.appmetrica.analytics:gradle:2.1.0")
      }
   }
   ```

   {% endcut %}

2. Add the plugin and a minimal configuration to the app's Gradle file:

   ```kotlin translate=no
   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](#parameters).

## Common tasks {#recipes}

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.

{% cut "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](#hierarchical-config)):

```kotlin translate=no
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")
}
```

{% endcut %}

## Plugin parameters {#parameters}

Example configuration with all available parameters:

```kotlin translate=no
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](#hierarchical-config)). ||
|| `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](#hierarchical-config)). ||
|| `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](#hierarchical-config)). ||
|| `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](#hierarchical-config)). ||
|| `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](#hierarchical-config)). ||
|| `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](#hierarchical-config)). ||
|| `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](#hierarchical-config)). ||
|| `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](#hierarchical-config)). ||
|#

{% note info %}

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

{% endnote %}

### Hierarchical configuration {#hierarchical-config}

The plugin supports four configuration levels:

```kotlin translate=no
appmetrica {
    // Global configuration
    variants {
        create("<variantName>") {
            // Variant configuration
        }
    }
}

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

{% note info %}

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.**

{% endnote %}

#### `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:

```kotlin translate=no
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

```kotlin translate=no
// 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"))
        }
    }
}
```

{% note 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 ...`.

{% endnote %}

## Manual loading {#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:

   ```kotlin translate=no
   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 **Crashes** → **Android** tab.
5. Click **Choose file** and upload the desired archive.

## Plugin tasks {#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:

```bash
./gradlew uploadReleaseAppMetricaMapping
./gradlew uploadReleaseAppMetricaNdkSymbols
```

## Build errors and warnings {#errors}

#### 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](https://appmetrica.yandex.by/docs/en/troubleshooting/feedback-new.md).

## Learn more {#learn-more}

- [Crashes and errors report](https://appmetrica.yandex.by/docs/en/mobile-reports/crashes-and-errors.md)
- [Android documentation](https://developer.android.com/topic/performance/vitals/crash)

<!-- source: en/_includes/feedback-button-3.md -->
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.

<a href="../../../troubleshooting/feedback-new">
  <span class="button">Contact support</span>
</a>

<a href="../../../troubleshooting/feedback-docs">
  <span class="button">Suggest an improvement for documentation</span>
</a>
<!-- endsource: en/_includes/feedback-button-3.md -->
