Firebase Crashlytics — Complete Guide
In this tutorial, you'll learn about Firebase Crashlytics. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
The Problem
Crashlytics doesn't report crashes from your release build, or you can't find the root cause because logs and breadcrumbs are missing from crash reports.
Wrong Approach ❌
// No user ID — can't identify which users are affected
FirebaseCrashlytics.getInstance().recordException(Exception("Something went wrong"))
// Logging without context
FirebaseCrashlytics.getInstance().log("Button clicked") // Too vague
Output: Crashes recorded but hard to diagnose. No user context.
Right Approach ✅
class App : Application() {
override fun onCreate() {
super.onCreate()
// Initialize Crashlytics (automatic with Firebase plugin)
FirebaseCrashlytics.getInstance().apply {
// Set user identifier for tracking
setUserId(userId)
// Set custom keys for crash context
setCustomKey("app_version", BuildConfig.VERSION_NAME)
setCustomKey("build_type", if (BuildConfig.DEBUG) "debug" else "release")
setCustomKey("api_level", Build.VERSION.SDK_INT)
setCustomKey("experiment_group", "control")
// Add breadcrumbs for navigation path
log("App launched")
}
}
}
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Log breadcrumbs
FirebaseCrashlytics.getInstance().log("MainActivity.onCreate")
// Record non-fatal exceptions
try {
riskyOperation()
} catch (e: Exception) {
FirebaseCrashlytics.getInstance().recordException(e)
}
}
private fun riskyOperation() {
// ...
}
// Force a crash for testing
fun testCrash() {
FirebaseCrashlytics.getInstance().apply {
log("Testing crash")
setCustomKey("test_timestamp", System.currentTimeMillis())
}
throw RuntimeException("Test crash — verify in Firebase console")
}
}
// In ViewModel
class MyViewModel @Inject constructor(
private val crashlytics: FirebaseCrashlytics
) : ViewModel() {
fun performAction() {
crashlytics.log("User performed action X")
crashlytics.setCustomKey("current_screen", "home")
// ... do work
}
}
Output: Crashes reported with full context and breadcrumb trail.
Prevention
- Set
setUserId()to identify affected users. - Add breadcrumbs with
log()for the user's navigation path. - Record non-fatal exceptions with
recordException(). - Test Crashlytics with
crash()in debug builds. - Enable debug mode:
adb shell setprop debug.<a href="/apis/firebase/">Firebase</a>.Crashlytics.app .your.package.name.
Common Mistakes with Firebase Crashlytics
- Overlapping type class instances that cause GHC to reject the program with ambiguous dispatch errors
- Non-exhaustive pattern matches that compile with warnings then crash at runtime
- Misunderstanding that
Stringis[Char]with poor performance for large text operations
These mistakes appear frequently in real-world Android code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro