Android SDK
Automatically capture crashes, ANRs, and custom analytics events from your Android app. One initialization line. No configuration required.
Installation
The SDK is distributed via JitPack — free, no account needed.
Step 1 — Add JitPack repository
In your project-level settings.gradle.kts, add JitPack inside dependencyResolutionManagement:
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url = uri("https://jitpack.io") } // add this
}
}Using the legacy Groovy DSL? Add to your project-level build.gradle instead:
allprojects {
repositories {
maven { url 'https://jitpack.io' }
}
}Step 2 — Add the dependency
In your app-level build.gradle.kts:
dependencies {
implementation("com.github.dmsyudha:gatiflow-android:v1.0.0")
}Or using the legacy Groovy DSL:
dependencies {
implementation 'com.github.dmsyudha:gatiflow-android:v1.0.0'
}The SDK requires INTERNETpermission. This is automatically merged into your app's manifest via manifest merger.
Initialization
Initialize in your Application.onCreate() — not in an Activity. This ensures crashes that happen before any Activity starts are still captured.
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
GatiFlow.start(
app = this,
appToken = "mhub_YOUR_APP_TOKEN",
services = listOf(Crashes::class.java, Analytics::class.java),
)
}
}Where to find your token: Go to Settings → API Tokens in your GatiFlow dashboard and create a token scoped to your app.
Register Application class
Make sure your custom Application class is declared in AndroidManifest.xml:
<application
android:name=".MyApp"
...
/>Crash Reporting
The Crashes service installs a global uncaught exception handler and an ANR watchdog automatically. No extra code is required for unhandled crashes.
Handled exceptions
Use trackError to report exceptions you catch and recover from:
try {
riskyOperation()
} catch (e: Exception) {
GatiFlow.crashes?.trackError(e)
// or with metadata:
GatiFlow.crashes?.trackError(e, metadata = mapOf(
"screen" to "CheckoutScreen",
"userId" to currentUser.id,
))
}ANR detection
ANRs are detected automatically when the main thread is blocked for more than 5 seconds (configurable). The stack trace at the time of the ANR is captured and reported as a handled error.
Offline behaviour
Crashes are serialized to disk immediately on the crashing thread — before any network call. On the next app launch, pending crashes are flushed to the API automatically. Up to 50 crashes are queued (configurable via Config.Builder.maxCrashQueueSize).
Disable crash reporting
// Opt out (e.g. based on user consent) GatiFlow.crashes?.setEnabled(false) // Re-enable GatiFlow.crashes?.setEnabled(true)
Analytics
Track custom events with optional properties. Events are batched and flushed automatically.
Track an event
// Simple event
GatiFlow.analytics?.trackEvent("app_open")
// Event with properties (String, Number, Boolean values supported)
GatiFlow.analytics?.trackEvent("purchase_completed", mapOf(
"product_id" to "prod_abc123",
"price" to 9.99,
"currency" to "USD",
))Flush manually
// Force-flush before a critical transition (e.g. logout) GatiFlow.analytics?.flush()
Session tracking
Sessions are tracked automatically using ActivityLifecycleCallbacks. A new session starts when the app comes to the foreground and ends when it fully backgrounds. Each event is associated with the active session automatically.
User Identity
Associate a user ID with all crashes and events. Call this after login and clear it on logout:
// On login GatiFlow.setUserId(currentUser.id) // On logout GatiFlow.setUserId(null)
The user ID is persisted to disk and survives app restarts. It is attached to every crash and event until cleared.
Advanced Configuration
val config = Config.Builder(appToken = "mhub_YOUR_TOKEN")
// Point at a self-hosted instance
.baseUrl("https://your-domain.com")
// Enable verbose SDK logging (disable in production)
.debugLogging(BuildConfig.DEBUG)
// Max crashes to queue when offline (default: 50)
.maxCrashQueueSize(100)
// Max events per batch before force-flush (default: 100)
.maxEventBatchSize(200)
// How often to flush events to the API in ms (default: 30s)
.flushIntervalMs(15_000)
// ANR detection threshold in ms (default: 5s, min: 1s)
.anrTimeoutMs(3_000)
.build()
GatiFlow.start(this, config, listOf(Crashes::class.java, Analytics::class.java))Custom service
Extend GatiFlowService to create your own service and register it alongside the built-in ones:
class MyFeatureService : GatiFlowService() {
override fun onCreate(app, config, deviceInfo, storage, http) {
// inject dependencies
}
override fun onStart() { /* begin work */ }
override fun onStop() { /* release resources */ }
}
GatiFlow.start(this, config, listOf(
Crashes::class.java,
Analytics::class.java,
MyFeatureService::class.java,
))API Reference
| Method | Description |
|---|---|
| GatiFlow.start(app, appToken, services) | Initialize the SDK with a token and service list |
| GatiFlow.start(app, config, services) | Initialize with a full Config object |
| GatiFlow.setUserId(id) | Set / clear the user identity |
| GatiFlow.crashes | Access the Crashes service |
| GatiFlow.analytics | Access the Analytics service |
| GatiFlow.stop() | Stop all services (testing / opt-out) |
| Crashes.trackError(t, metadata?) | Report a handled exception |
| Crashes.setEnabled(bool) | Enable or disable crash reporting |
| Analytics.trackEvent(name, properties?) | Record a custom event |
| Analytics.flush() | Force-flush the event queue |
| Analytics.setEnabled(bool) | Enable or disable analytics |
Troubleshooting
No crashes appearing in the dashboard
Check that your app token is correct and the device has internet access. Enable debug logging with .debugLogging(true) to see SDK output in Logcat (tag: GatiFlow).
GatiFlow.start() is called but crashes field is null
You must pass Crashes::class.java in the services list. GatiFlow.crashes returns null if the service was not registered.
Crashes appear with missing stack traces
Make sure your app's ProGuard/R8 config keeps SourceFile and LineNumberTable attributes, and that you upload a mapping file to your build provider.
ANR detector fires too often in debug builds
Increase the ANR timeout via .anrTimeoutMs(10_000) for debug, or disable it by not including Crashes in debug builds.