Mobile
Full-fidelity crash reporting and observability for native and cross-platform mobile apps. Every mobile SDK shares the same architecture, so what you learn on one platform carries to the others.
What the mobile SDKs give youlink
- Crash capture - uncaught JVM/Swift exceptions, native signals (Android NDK C/C++, iOS/macOS Mach signals), ANRs (Android) and app hangs (iOS), captured with the context needed for server-side symbolication.
- Release health - sessions are tracked automatically so every release shows its crash-free rate.
- Breadcrumbs - app lifecycle and network requests are recorded automatically and attached to the next event, so you see what led up to a crash.
- Offline-first delivery - events persist to an on-device queue and upload in batches (50 events / 5 s by default) when the network allows, with exponential-backoff retry. A crash captured on the subway arrives when the user resurfaces.
- Redaction on device - sensitive keys (passwords, tokens, card numbers and your own
sensitiveFields) are scrubbed before anything leaves the phone.
Credentials - no secrets in the applink
Mobile apps are decompilable, so they never carry your DSN secret. Each project has dedicated mobile credentials:
- Dashboard → Org → BugWatch → your project → Mobile credentials → Reveal.
- Copy the
projectId(bwp_…) and theappSecretinto your app's build configuration. - On every batch the SDK signs a 5-minute HMAC token on device (
x-bugwatch-token) - theappSecretitself is never transmitted. - Suspect a leak? Rotate invalidates the old secret; ship the new one in your next build. Older builds keep reporting until their token version is retired.
Clock skew matters: tokens more than 60 seconds in the future (or past their 5-minute expiry) are rejected - a device with a badly wrong clock will drop events until it syncs.
Diagnosing a silent SDKlink
Both native SDKs perform a handshake (POST /api/v1/bugwatch/ingest/mobile/hello, same token, empty or identity-only body, nothing ingested or billed) when they start, and expose the outcome through connectionState / testConnection(). A refusal is never silent: the response names the reason and the dashboard records it.
| Reason | Meaning | Fix |
|---|---|---|
signature_invalid | The app secret in this build does not match the project | Copy the current secret from Settings, Mobile credentials, and rebuild. Rotated the secret? Older builds keep failing until updated |
project_unavailable | No active project has this projectId | Check the projectId; the project may have been deleted or deactivated |
mobile_ingest_disabled | Mobile ingest is switched off for the project | Enable it under Settings, Mobile credentials |
token_expired | The token had already expired on arrival | The device clock is behind |
clock_ahead | The token was issued more than 60 s in the future | The device clock is ahead |
token_missing / token_malformed | No or unreadable x-bugwatch-token | Initialise the SDK with projectId and app secret; use a supported SDK version |
The project's setup page shows a Mobile SDK connection panel: per platform, the last accepted handshake (SDK version, device model, OS, app version, time) and the last rejected one with its reason and hint. Accepted and rejected are tracked separately, so a working production fleet and one developer with a stale secret are both visible at once.
Pick your platformlink
| Platform | Package | Page |
|---|---|---|
| Android (Kotlin/Java, NDK) | cloud.newinstance:bugwatch - Maven Central | Android |
| iOS & macOS (Swift) | BugWatch - CocoaPods / Swift PM | iOS & macOS |
| React Native (+ Expo) | @newinstance/bugwatch-react-native - npm | React Native |
| Flutter | bugwatch - pub.dev | Flutter |
Each page covers installation, initialisation, configuration, automatic capture, symbolication and troubleshooting.
Readable stack traceslink
Release builds are minified/obfuscated, so upload symbolication artifacts per release in CI - R8/ProGuard mappings and native .so symbols (Android), dSYMs (iOS/macOS), JS source maps (React Native), --split-debug-info output (Flutter). The per-platform pages give the exact commands; the wire contract lives in Source Maps & Symbols.