# Android
> https://docs.errora.org/en/platforms/android
Errora works with the official [Sentry Android SDK](https://docs.sentry.io/platforms/android/)
and the Sentry Android Gradle plugin, unchanged. The SDK reports Java/Kotlin crashes, NDK
(native) crashes and ANRs; the Gradle plugin uploads the files Errora needs to turn an
obfuscated or native stack back into your code.
Create the project with the **Android** platform so the UI shows the right snippets.
## Install
The recommended route is the Gradle plugin, which adds the SDK for you and uploads mappings
and symbols on every release build:
```kotlin
// app/build.gradle.kts
plugins {
id("com.android.application")
id("io.sentry.android.gradle") version "5.+" // pin an exact version in real builds
}
```
Without the plugin, add the SDK yourself (it bundles NDK crash reporting):
```kotlin
dependencies {
implementation("io.sentry:sentry-android:8.+")
}
```
## Initialize
### Option 1 — the manifest
The SDK initializes itself from `AndroidManifest.xml`:
```xml
```
### Option 2 — in code
Turn auto-init off in the manifest, then call `SentryAndroid.init` from your `Application`:
```xml
```
```kotlin
import io.sentry.android.core.SentryAndroid
class App : Application() {
override fun onCreate() {
super.onCreate()
SentryAndroid.init(this) { options ->
options.dsn = "https://@/"
options.environment = "production"
options.tracesSampleRate = 0.2 // tracing
options.profilesSampleRate = 1.0 // profiling (of sampled transactions)
options.isAttachScreenshot = true // screenshot on error
options.isAttachViewHierarchy = true // view hierarchy on error
options.sessionReplay.onErrorSampleRate = 1.0
options.sessionReplay.sessionSampleRate = 0.1
options.isAnrEnabled = true // default: on
options.isEnableAutoSessionTracking = true // default: on — feeds release health
}
}
}
```
## Options worth enabling
| Option | What you get in Errora |
| --- | --- |
| `tracesSampleRate` | [Performance](/en/products/performance): app start, activity and fragment transactions, HTTP spans |
| `profilesSampleRate` | [Profiling](/en/products/profiling) of sampled transactions (ART method traces) |
| `isAttachScreenshot` | A screenshot stored with each error, previewed on the issue page |
| `isAttachViewHierarchy` | The view tree at the moment of the error, rendered as a tree on the issue page |
| `sessionReplay.*SampleRate` | [Mobile session replay](/en/products/session-replay#mobile-replays) |
| `isAnrEnabled` | ANRs arrive as ordinary errors and group/alert like any issue; they also feed the ANR rate |
| `isEnableAutoSessionTracking` | Sessions for [release health](/en/products/release-health) — on by default |
You don't need to set `release`: the SDK sets it to `@+`
automatically, and that is the string release health and debug-file matching key on.
Screenshots and view hierarchies are [attachments](/en/products/issues#attachments): they
are stored with their event, follow the organization's [data retention](/en/account/retention),
and are dropped with the event when it is sampled out or spike-limited.
## Upload ProGuard/R8 mappings and NDK symbols
A minified release build reports frames like `a.b.c.d(SourceFile)`, and native crashes
report bare addresses. Errora deobfuscates and symbolicates them **before grouping** using the
files you upload — see [Debug files](/en/products/debug-files) for how matching works.
Point the Gradle plugin at Errora:
```kotlin
// app/build.gradle.kts
sentry {
url.set("https://")
org.set("")
projectName.set("")
authToken.set(System.getenv("SENTRY_AUTH_TOKEN")) // errora_pat_…
includeProguardMapping.set(true) // ProGuard/R8 mapping.txt
autoUploadProguardMapping.set(true) // upload it as part of the build
uploadNativeSymbols.set(true) // NDK .so debug symbols
includeNativeSources.set(false)
telemetry.set(false) // don't report build telemetry to sentry.io
}
```
- `authToken` is an Errora [personal access token](/en/account/tokens) (`errora_pat_…`)
whose owner is a **member** (or higher) of the organization. Keep it in your CI's secret
store, not in the repository.
- `org` is the organization slug from your dashboard URL (`/organizations//…`);
`projectName` is the project's slug.
- The plugin also reads `sentry.properties` and the `SENTRY_URL`, `SENTRY_ORG`,
`SENTRY_PROJECT` and `SENTRY_AUTH_TOKEN` environment variables, if you'd rather keep the
block empty.
The plugin stamps every build with a ProGuard UUID that the SDK reports, so each crash is
deobfuscated with the mapping of the exact build that produced it. You can check what
arrived under **Settings → Debug files**.
### Without the Gradle plugin
Use `sentry-cli` with the same four settings:
```bash
export SENTRY_URL=https://
export SENTRY_AUTH_TOKEN=errora_pat_…
export SENTRY_ORG=
export SENTRY_PROJECT=
sentry-cli upload-proguard --uuid app/build/outputs/mapping/release/mapping.txt
sentry-cli debug-files upload app/build/intermediates/merged_native_libs/release/
```
The `--uuid` must be the ProGuard UUID the app reports — which is why the plugin is the
easier path.
## Verify
Build a **release** variant (so minification and the upload both run), then:
```kotlin
Sentry.captureException(RuntimeException("Errora smoke test"))
// or crash for real:
throw RuntimeException("Errora crash test")
```
An unhandled crash is sent the next time the app starts. Open the issue: frames should show
real class and method names with line numbers. If a frame is still obfuscated, the issue page
says which mapping (debug id) is missing.
## Troubleshooting
| Symptom | Cause / fix |
| --- | --- |
| Frames still look like `a.b.c` | The mapping wasn't uploaded for that build — check the Gradle output and **Debug files** |
| Native frames show only addresses | Upload NDK symbols (`uploadNativeSymbols`), from the **unstripped** `.so` files |
| Upload fails with `401` | Wrong or revoked token, or `url` still points to sentry.io |
| Upload fails with `403` | The token's owner isn't a member of that organization |
| No release health data | Auto session tracking was turned off |
| No crash after `throw` | Crashes are sent on the **next** launch — reopen the app |