Firebase Crashlytics helps developers monitor app crashes in real-time, providing detailed reports to improve app stability. This guide covers everything you need to know about setting it up and customizing it for iOS and Android, including:
- Basic Setup: Step-by-step instructions for integrating Crashlytics on both platforms.
- Custom Data: Learn how to add custom keys and logs to crash reports for better debugging.
- Advanced Features: Track non-fatal errors, handle sensitive data securely, and work with native code.
- Testing: Simulate crashes to verify your setup and ensure accurate reporting.
Quick Overview of Key Features:
Feature | iOS | Android |
---|---|---|
Setup Tools | Xcode, CocoaPods | Android Studio, Gradle |
Custom Keys | setCustomValue() (Swift) |
setCustomKey() (Java/Kotlin) |
Non-Fatal Errors | recordError() |
recordException() |
Native Code Support | dSYM files | NDK integration |
Testing Crashes | Built-in crash methods | Simulate runtime exceptions |
Crashlytics is essential for identifying and fixing app issues quickly. Whether you’re building apps for healthcare, finance, or general use, this guide outlines everything you need to make the most of Firebase Crashlytics.
Advanced debugging with Firebase Crashlytics
1. Basic Firebase Crashlytics Setup
Getting Firebase Crashlytics up and running involves configuring both iOS and Android platforms to ensure crash reports are captured effectively. Here’s a step-by-step guide for each platform.
iOS Setup Steps
To integrate Crashlytics on iOS, you’ll need Xcode and CocoaPods. Follow these steps:
- Set Up the Environment Download the
GoogleService-Info.plist
file from your Firebase console and add it to your Xcode project. This file contains the Firebase configuration specific to your app. - Install the Required Dependencies Add the following line to your Podfile:
pod 'Firebase/Crashlytics'
Then, install the dependencies by running:
pod install
- Initialize Firebase Open your
AppDelegate
file and configure Firebase during app launch:import Firebase @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { FirebaseApp.configure() return true } }
Android Setup Steps
For Android, you’ll need Android Studio with a properly configured Gradle environment. Here’s how to set up Crashlytics:
- Configure the Project Add the Crashlytics Gradle plugin to your project-level
build.gradle
file:buildscript { dependencies { classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.5' } }
- Set Up the App-Level Configuration In your app-level
build.gradle
file, include the following:apply plugin: 'com.google.firebase.crashlytics' dependencies { implementation 'com.google.firebase:firebase-crashlytics' }
- Configure ProGuard (Optional) If you’re using ProGuard, enable automatic upload of mapping files by adding this to your
build.gradle
file:android { buildTypes { release { firebaseCrashlytics { mappingFileUploadEnabled true } } } }
Tips for Managing Multiple Environments
If your team works with sensitive data or uses separate environments (like development, staging, and production), consider creating distinct Firebase projects for each. This keeps crash data organized and ensures accurate reporting for each environment.
Verification and Best Practices
Once you’ve completed the setup, build and run your app. Then, check the Firebase console under the Crashlytics section to confirm your app is listed. Keep in mind it might take up to 24 hours for the first crash data to appear.
Platform | Configuration File | Initial Setup Tools |
---|---|---|
iOS | GoogleService-Info.plist | Xcode, CocoaPods |
Android | google-services.json | Android Studio, Gradle |
Handling Automatic Crash Collection
If your app handles sensitive data, you might need to disable automatic crash collection and enable it only after getting user consent. Here’s how you can do that:
// iOS Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(false)
// Android FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(false);
Once your setup is complete, you can start adding custom crash data to gain deeper insights into app performance.
2. Adding Custom Crash Data
Learn how to implement custom crash data for both iOS and Android platforms to better understand and troubleshoot app crashes.
Setting Custom Keys
Custom keys allow you to attach specific state information to crash reports using key-value pairs. These keys help track user states, configuration settings, and other contextual details that might be relevant during debugging.
For iOS, you can set custom keys using Swift:
// Track user session information Crashlytics.crashlytics().setCustomValue(userId, forKey: "active_user_id") Crashlytics.crashlytics().setCustomValue(true, forKey: "premium_status") // Log app configuration Crashlytics.crashlytics().setCustomValue("v2.5.1", forKey: "api_version") Crashlytics.crashlytics().setCustomValue(deviceType, forKey: "device_config")
For Android, use Java to set custom keys:
FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance(); // Track user session information crashlytics.setCustomKey("active_user_id", userId); crashlytics.setCustomKey("premium_status", true); // Log app configuration crashlytics.setCustomKey("api_version", "v2.5.1"); crashlytics.setCustomKey("device_config", deviceType);
Once custom keys are in place, you can move on to logging events to capture user actions and system behavior.
Implementing Event Logs
Event logs provide a timeline of actions and system events that occur before a crash, giving you valuable insights into what might have gone wrong.
For iOS, you can log events with Swift:
// Record user interactions Crashlytics.crashlytics().log("User initiated payment process") // Log system events with context let itemCount = 5 let totalAmount = 99.99 Crashlytics.crashlytics().log("Cart checkout started: \(itemCount) items, total: $\(totalAmount)") // Log error conditions do { try processPayment() } catch let error { Crashlytics.crashlytics().log("Payment failed: \(error.localizedDescription)") }
For Android, configure logging with Timber to integrate with Crashlytics:
// Configure Timber for Crashlytics Timber.plant(new Timber.Tree() { @Override protected void log(int priority, String tag, String message, Throwable t) { if (priority >= Log.INFO) { FirebaseCrashlytics.getInstance().log(tag + ": " + message); } } }); // Record logs throughout your application Timber.i("Payment process initiated"); Timber.d("Processing order #%s", orderId);
When adding event logs, focus on capturing:
- User interactions and system state changes
- Network requests and their responses
- Error conditions
- Execution paths within your business logic
These logs will be displayed in chronological order in the Firebase console, helping you trace the sequence of events leading to a crash.
sbb-itb-7af2948
3. Advanced Crash Reporting Options
Firebase Crashlytics helps developers track both fatal and non-fatal errors across iOS and Android, ensuring smoother app performance and a better user experience.
Tracking Non-Fatal Errors
Non-fatal errors don’t crash your app but can still interfere with how users interact with it. Tracking these issues is crucial for maintaining a seamless experience.
Here’s how you can implement non-fatal error tracking in Swift:
do { try networkOperation() } catch let error { Crashlytics.crashlytics().setCustomValue("network_call", forKey: "error_type") Crashlytics.crashlytics().record(error: error) } func handleAPIError(_ error: APIError) { Crashlytics.crashlytics().setCustomValue("api_error", forKey: "error_type") Crashlytics.crashlytics().setCustomValue(error.code, forKey: "error_code") Crashlytics.crashlytics().record(error: error) }
For Android, use Kotlin to handle exceptions:
try { processPayment() } catch (e: Exception) { FirebaseCrashlytics.getInstance().apply { setCustomKey("error_type", "payment_processing") setCustomKey("transaction_id", transactionId) recordException(e) } }
Once non-fatal error tracking is in place, you can explore platform-specific tools to further enhance your crash reporting.
Platform-Specific Tools
iOS dSYM Integration
Uploading dSYM files ensures that your crash reports are symbolicated, making them easier to debug. You can upload these files using the Firebase CLI:
firebase crashlytics:symbols:upload \ --app=YOUR_APP_ID \ /path/to/your/dSYM
To automate this process, configure Xcode with the following script:
"${PODS_ROOT}/FirebaseCrashlytics/run"
Android NDK Support
For apps using native code, you can enable NDK crash reporting by adding the following to your build.gradle
file:
android { buildTypes { release { firebaseCrashlytics { nativeSymbolUploadEnabled true } } } }
Additionally, you can log native crashes in C++:
#include "firebase/crashlytics/crashlytics.h" void processNativePayment() { try { // Payment processing code } catch (...) { firebase::crashlytics::Log("Native payment processing failed"); firebase::crashlytics::SetCustomKey("component", "native_payment"); firebase::crashlytics::Forcecrash(); } }
Comparison of Features
Feature | iOS Implementation | Android Implementation |
---|---|---|
Non-Fatal Error Tracking | recordError() with dSYM support |
recordException() with stack trace |
Native Code Support | dSYM files for symbolication | NDK integration with native symbols |
Debug Symbols | Automatic upload via build script | Configured through Gradle |
Custom Logging | Supports Swift and Objective-C | Supports Java, Kotlin, and C++ |
4. Testing Your Crashlytics Setup
Testing your Crashlytics integration ensures that crash reports are accurate and reliable in a production environment. This step is crucial for maintaining app stability and identifying areas for improvement.
Creating Test Crashes
For iOS:
To simulate crashes on iOS, you can use either of the following methods:
// Method 1: Using Crashlytics' built-in crash function func triggerTestCrash() { Crashlytics.crashlytics().setCustomValue("test_scenario", forKey: "crash_type") Crashlytics.crashlytics().setUserID("test-user-123") Crashlytics.crashlytics().crash() } // Method 2: Triggering a fatal error func triggerFatalError() { fatalError("Trigger a test crash for verification") }
For Android:
Android developers can create test crashes with these approaches:
// Method 1: Using Crashlytics' test method private fun generateTestCrash() { FirebaseCrashlytics.getInstance().apply { setCustomKey("crash_type", "test_scenario") setCustomKey("user_id", "test-user-123") crash() } } // Method 2: Throwing an uncaught exception private fun throwTestException() { throw RuntimeException("Trigger a test crash for verification") }
After generating these test crashes, move on to validating the results through the Firebase Dashboard.
Using the Firebase Dashboard
The Firebase Dashboard is your go-to tool for analyzing crash data and ensuring everything is set up correctly. Here’s what you can do:
Dashboard Feature | Purpose | Key Actions |
---|---|---|
Issue Tracking | Monitor crash frequency and impact | Filter crashes by app version or device type. |
Stack Trace Analysis | Identify root causes of crashes | Review symbolicated crash logs for debugging. |
Custom Keys | Confirm additional context data | Check the "Keys" tab for custom values like user IDs or crash types. |
Timeline View | Observe crash trends over time | Correlate crashes with specific app releases or updates. |
Tips for Effective Monitoring:
- Set Up Version Tracking: Ensure crashes are linked to specific app versions. For example:
// iOS version-based crash verification if Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String == "1.0" { Crashlytics.crashlytics().crash() }
- Monitor Crash-Free Users: Keep an eye on the crash-free user metric. A crash-free rate above 99.5% is generally considered a sign of good app stability.
- Verify Custom Data: Double-check that custom keys and values (like
crash_type
oruser_id
) appear correctly in the dashboard.
Conclusion: Maximizing Crashlytics Benefits
To fully harness the potential of Crashlytics, combining advanced setup techniques with strategic logging is key. This approach transforms raw crash data into actionable insights, helping developers maintain app stability and improve user experience.
Setting up Firebase Crashlytics effectively is more than just a technical task – it’s a way to ensure your app remains reliable and secure. Custom keys and thoughtful logging elevate crash reports from basic error lists to detailed diagnostic tools, allowing teams to pinpoint and resolve issues faster.
Security and Compliance Advantages
For industries like healthcare and finance, where protecting user data is non-negotiable, implementing data filtering and anonymized user IDs is essential. These measures not only ensure detailed crash reporting but also help meet strict privacy standards like HIPAA and GDPR.
Here’s a quick breakdown of the core benefits:
Area | Approach | Impact |
---|---|---|
Custom Keys | Add context to crashes with key-value pairs | Makes debugging easier with searchable patterns |
Strategic Logging | Use a severity-based logging system | Offers clear visibility into crash sequences |
Security Protocols | Filter data and protect sensitive information | Ensures compliance with privacy regulations |
FAQs
How can I prevent sensitive data from being included in Firebase Crashlytics reports?
To keep sensitive data out of Firebase Crashlytics reports, follow these steps:
- Be cautious with
setCustomKeys
: Avoid including any sensitive details, like user credentials or personal information, when usingsetCustomKeys
in your Crashlytics logs. - Clean up error messages: Inspect and sanitize error messages or stack traces to ensure they don’t contain sensitive information before logging them.
- Apply data scrubbing: Use filters to remove or mask sensitive data in logs before they’re sent to Crashlytics. For instance, you can target and clean specific fields in your logs.
These measures help protect user privacy and align with data protection standards. If your app deals with highly sensitive information or requires advanced security, you might want to collaborate with specialists like Sidekick Interactive, who excel at creating secure, custom mobile solutions for complex needs.
How can I test Firebase Crashlytics to ensure it reports crashes accurately?
To make sure Firebase Crashlytics is working correctly and capturing crash reports accurately, you can run a few key tests. Start by deliberately causing a test crash in your app. For Android, you can use Crashlytics.crash()
, and for iOS, try fatalError()
. This will confirm that crash reports are successfully logged in the Firebase Console.
Afterward, check that the crash reports include all the essential details, such as stack traces, device information, and the app version. It’s also smart to test Crashlytics in various environments – like development, staging, and production – to ensure it works consistently across different setups. By regularly reviewing your configuration and logs, you can keep your crash reporting accurate and dependable.
How do custom keys and event logs improve debugging in Firebase Crashlytics?
When using Firebase Crashlytics, custom keys and event logs are powerful tools for adding app-specific details to your crash reports. Custom keys allow you to attach key-value pairs, giving you valuable context about the crash, such as user interactions, the app’s state, or specific variable values at the moment the issue occurred. Meanwhile, event logs provide a timeline of user actions or app events leading up to the crash, helping you understand the sequence of events that caused the problem.
These features are especially handy for tackling tricky bugs and ensuring your app runs smoothly. They’re particularly important for apps that handle sensitive information or demand top-notch performance, where pinpointing and resolving issues quickly is a must.