Set Up Snapshots

Set up snapshots for Android apps with the Sentry Android Gradle Plugin.

Set up Snapshots for your Android app with the Sentry Android Gradle Plugin. Generate snapshots locally or in your own CI using your preferred snapshot library, then upload the generated images to Sentry for image diffing, visual review, and GitHub status checks.

Ensure the Sentry Android Gradle Plugin version 6.6.0 or higher is applied and configured.

Then enable snapshots in your build.gradle:

Copied
sentry {
  snapshots {
    enabled = true
  }
}

On Android you can either generate images from compose previews (recommended) or from an existing snapshot tool like Roborazzi or Paparazzi.

These methods are not mutually exclusive — you can generate and upload snapshots from your previews and any existing snapshot tests.

Paparazzi and ComposePreviewScanner automatically turns every @Preview composable in your project into a snapshot image, so you don't have to maintain explicit snapshot tests.

First, choose a Paparazzi version compatible with your project:

VersionGradlecompileSdkJDKcompose-bom
2.0.0-alpha049.1+3621+> 2025.05.00
1.3.58.x or 9.x≤ 3517+≤ 2025.04.00

Then apply the plugin:

Copied
plugins {
  // existing plugins
  id("app.cash.paparazzi") version "<paparazzi_version>"
}

Continue to Step 3.

Use this path if you already generate snapshots with another tool. The configuration depends on which tool you use.

If you already have Paparazzi configured, set generateTests = false inside the previews block so Sentry uses your existing tests instead of auto-generating preview-based ones:

Copied
sentry {
  snapshots {
    enabled = true
    previews {
      generateTests = false
    }
  }
}

Continue to Step 3.

If you already have Roborazzi configured, wire the Sentry upload task to the output of your Roborazzi record task:

Copied
afterEvaluate {
  tasks.named<SentryUploadSnapshotsTask>("sentryUploadSnapshotsDebug") {
    dependsOn(tasks.named("recordRoborazziDebug"))
    snapshotsPath.set(
      project.extensions.getByType<RoborazziExtension>().outputDir
    )
  }
}

Continue to Step 3.

The same pattern works with any snapshot tool. Set snapshotsPath to the directory your tool writes images to, and add a dependsOn for the task that generates them:

Copied
afterEvaluate {
  tasks.named<SentryUploadSnapshotsTask>("sentryUploadSnapshotsDebug") {
    dependsOn(tasks.named("yourSnapshotTask"))
    snapshotsPath.set(layout.projectDirectory.dir("path/to/snapshots"))
  }
}

Alternatively, you can skip the Gradle plugin entirely and upload with sentry-cli build snapshots:

Copied
sentry-cli build snapshots ./build/paparazzi/snapshots \
  --app-id android-app

Use this path if your build pipeline doesn't use Gradle, or if you want to run the upload outside of a Gradle task. See Uploading Snapshots for the expected directory layout.

Verify your setup by running:

Copied
./gradlew sentryUploadSnapshotsDebug

Once the local upload succeeds, wire the same command into your CI. See Integrating Into CI for an example GitHub Actions workflow.

The options below apply when using the Compose Previews path with generateTests = true (the default).

The previews block inside snapshots exposes options that shape the generated Paparazzi tests.

Copied
sentry {
  snapshots {
    enabled = true
    previews {
      theme = "@style/Theme.MyApp"          // optional
      includePrivatePreviews = false        // optional, defaults to true
      packageTrees = listOf("com.example")  // optional, defaults to Android namespace
    }
  }
}
OptionDefaultDescription
themePaparazzi default (android:Theme.Material.NoActionBar.Fullscreen)Android theme resource used when rendering previews. Set this if your previews rely on a specific theme.
includePrivatePreviewstrueWhether @Preview composables declared private are snapshotted. Set to false to exclude in-progress or internal-only previews.
packageTrees[] (falls back to Android namespace)Package prefixes to scan for @Preview composables. When empty, the plugin uses the Android namespace from the build variant.

If you don't set a theme, Paparazzi uses its own default (android:Theme.Material.NoActionBar.Fullscreen). If the background of your previews isn't important — for example, when you just want to compare component geometry — you can use a translucent platform theme such as android:Theme.Translucent.NoTitleBar:

Copied
sentry {
  snapshots {
    enabled = true
    previews {
      theme = "android:Theme.Translucent.NoTitleBar"
    }
  }
}

To ignore small pixel changes across all snapshots, set diffThreshold in the plugin configuration:

Copied
sentry {
  snapshots {
    enabled = true
    diffThreshold = 0.01 // ignore changes of 1% or less
  }
}

The diffThreshold is a value between 0.0 and 1.0. Sentry reports a snapshot as changed only when the share of changed pixels exceeds this value. The default is 0.0 (report any difference).

To override the global threshold for specific previews, annotate them with @SentrySnapshot and set a diff threshold. First, add the runtime dependency:

Copied
dependencies {
  testImplementation("io.sentry:sentry-snapshots-runtime:6.7.0")
}

Then annotate any @Preview composable:

Copied
import io.sentry.snapshots.runtime.SentrySnapshot

@SentrySnapshot(diffThreshold = 0.01f) // ignore changes of 1% or less
@Preview
@Composable
fun BillingPagePreview() {
  BillingPage()
}

Per-preview values take precedence over the global diffThreshold. See Diff Thresholds for other ways to configure thresholds.

Was this helpful?
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").