Skip to main content
This document covers the error capture mechanisms of the Android RUM SDK, helping you monitor and diagnose crashes and errors in Android applications.
The SDK supports automatic capture of Java/Kotlin crashes, NDK native crashes, and ANR (Application Not Responding), while also providing manual error reporting and symbolicated stack trace features.

Error Types

Android RUM can monitor the following types of errors:

Java/Kotlin Crashes

The SDK automatically captures unhandled Java/Kotlin exceptions, including:
  • Runtime exceptions (e.g., NullPointerException, IndexOutOfBoundsException)
  • Uncaught exceptions
  • Application crashes

NDK Crashes (Native Crash)

If your application uses native code (C/C++), the SDK supports capturing NDK crashes and including them in error tracking.

ANR (Application Not Responding)

The SDK can detect and report ANR issues, helping you identify user experience problems caused by main thread blocking.

Custom Errors

In addition to automatically captured exceptions, you can use the RUM SDK to manually report custom errors for tracking business logic errors and other specific issues.

Configure Crash Reporting

Basic Configuration

Crash reporting is enabled by default. After completing basic SDK integration following the SDK Integration Guide, the SDK will automatically capture unhandled exceptions in your application.

Add NDK Crash Reporting

If your application contains native code (C/C++), you need to add the NDK crash reporting module to capture native crashes.
1

Add Dependency

Add the NDK crash reporting dependency in your app module’s build.gradle file:
build.gradle
dependencies {
    implementation "cloud.flashcat:fc-sdk-android-ndk:0.1.0"
}
2

Enable NDK Crash Reporting

Enable NDK crash reporting after SDK initialization:
import cloud.flashcat.android.ndk.NdkCrashReports

// Call after Flashcat.initialize()
NdkCrashReports.enable()

Add ANR Reporting

ANR (Application Not Responding) occurs when the application’s main thread is blocked for more than a certain time, causing the application to become unresponsive to user input.

Enable ANR Detection

Enable ANR detection in the RUM configuration:
import cloud.flashcat.android.rum.RumConfiguration

val rumConfig = RumConfiguration.Builder(applicationId)
    .trackNonFatalAnrs(true) // Track non-fatal ANRs
    .build()
ANR detection monitors main thread responsiveness. When the main thread is blocked beyond the threshold, the SDK automatically records an ANR event.

Manual Error Reporting

Using the addError API, you can manually report handled exceptions, custom errors, or other errors not automatically captured.

Error Reporting Example

import cloud.flashcat.android.rum.GlobalRum
import cloud.flashcat.android.rum.RumErrorSource

// Report an error with context
try {
    riskyOperation()
} catch (e: Exception) {
    GlobalRum.get().addError(
        message = "Operation failed",
        source = RumErrorSource.SOURCE,
        throwable = e,
        attributes = mapOf(
            "operation" to "riskyOperation",
            "userId" to "12345"
        )
    )
}

Error Source Types

RumErrorSource options:
ValueDescription
RumErrorSource.NETWORKNetwork error
RumErrorSource.SOURCESource error
RumErrorSource.CONSOLEConsole error
RumErrorSource.LOGGERLogger error
RumErrorSource.AGENTAgent error
RumErrorSource.WEBVIEWWebView error
RumErrorSource.CUSTOMCustom error

Network Error Reporting Example

import cloud.flashcat.android.rum.GlobalRum
import cloud.flashcat.android.rum.RumErrorSource

fun onNetworkError(url: String, statusCode: Int, error: Throwable) {
    GlobalRum.get().addError(
        message = "Network request failed: $url",
        source = RumErrorSource.NETWORK,
        throwable = error,
        attributes = mapOf(
            "url" to url,
            "status_code" to statusCode,
            "method" to "GET"
        )
    )
}

Get Deobfuscated Stack Traces

If your application has code obfuscation enabled (ProGuard/R8), reported crash stacks will be obfuscated. By uploading mapping files, you can restore obfuscated stacks to original class names, method names, and line numbers.

Configure Gradle Plugin

1

Add Plugin Dependency

Add the Flashcat Gradle plugin in your project root build.gradle file:
build.gradle
buildscript {
    dependencies {
        classpath "cloud.flashcat:fc-gradle-plugin:0.1.0"
    }
}
2

Apply Plugin

Apply the plugin in your app module’s build.gradle file:
build.gradle
plugins {
    id 'cloud.flashcat.android'
}
3

Configure Plugin

Configure the Flashcat plugin in your build.gradle file:
build.gradle
flashcat {
    site = "FLASHCAT_SITE"         // Data reporting site
    clientToken = "<CLIENT_TOKEN>" // Client token
    serviceName = "<SERVICE_NAME>" // Service name (optional)
    versionName = "1.0.0"          // App version (optional, defaults to android.defaultConfig.versionName)
}

Upload Mapping Files

After configuration, the plugin will automatically upload mapping files during the build process. You can also manually run the upload task:
./gradlew uploadMapping<Variant>
For example, for the release variant:
./gradlew uploadMappingRelease

Upload NDK Symbol Files

If you’re using NDK crash reporting, you also need to upload NDK symbol files to get readable native stacks:
./gradlew uploadNdkSymbolFiles<Variant>

Plugin Configuration Options

PropertyDescription
versionNameApp version name (defaults to version declared in android block)
serviceNameService name (defaults to app package name)
siteData reporting site
checkProjectDependenciesControls whether the plugin checks Flashcat SDK dependencies. Options: none (ignore), warn, fail (default)

Mapping File Size Limits

Mapping file size is limited to 500 MB. If the file is too large, you can use the following options to reduce file size:
build.gradle
flashcat {
    mappingFileTrimIndents = true  // Remove indentation, reduces file size by ~5% on average

    mappingFilePackageAliases = [
        "kotlinx.coroutines": "kx.cor",
        "com.google.android.material": "material",
        "com.google.gson": "gson"
    ]
}
When using mappingFilePackageAliases, stacks in Flashcat error tracking will use aliases instead of original package names. It’s recommended to only use this option for third-party dependencies.

Track Background Events

By default, only crashes that occur when a view is active are tracked. If you want to track crashes that occur when the app is in the background, enable background event tracking:
import cloud.flashcat.android.rum.RumConfiguration

val rumConfig = RumConfiguration.Builder(applicationId)
    .trackBackgroundEvents(true)
    .build()
Tracking background events may generate additional sessions, which could affect billing. If you have questions, please contact the Flashcat support team.

Limitations and Considerations

Crash Detection Limitations

  • SDK Initialization Timing: Crashes can only be detected after SDK initialization. It’s recommended to initialize the SDK as early as possible in Application.onCreate().
  • View Association: Crashes must be associated with a RUM view. Crashes that occur before a view is displayed or after the app is backgrounded may not be reported. This can be mitigated with trackBackgroundEvents(true).
  • Sampling Rate Impact: Only crashes in sampled sessions are retained. If the session sampling rate is not 100%, some crashes may not be reported.

Symbolication Limitations

  • Ensure mapping files are correctly uploaded with each new version release.
  • Different build variants (e.g., debug/release) require separate mapping file uploads.
  • NDK symbol files must contain debug information for proper symbolication.

Testing and Verification

Verify Java/Kotlin Crashes

  1. Add test code to trigger a crash in your app:
fun onEvent() {
    throw RuntimeException("Test crash")
}
  1. Run the app and trigger the crash
  2. Restart the app and wait for the SDK to upload the crash report
  3. View the crash report in the Flashcat console’s Error Tracking module

Verify NDK Crashes

  1. Add a test crash in native code:
void crash() {
    int* ptr = nullptr;
    *ptr = 42;  // Trigger null pointer crash
}
  1. Call this native method from Java/Kotlin code
  2. Restart the app and wait for the SDK to upload the crash report
  3. Confirm the stack is properly symbolicated (showing function names, file names, and line numbers)

Verify ANR

  1. Execute a time-consuming operation on the main thread:
fun blockMainThread() {
    Thread.sleep(10000)  // Block main thread for 10 seconds
}
  1. Trigger this operation and try to interact with the app
  2. Check if the Flashcat console received the ANR report

Error Data Structure

Each error record contains the following attributes:
AttributeTypeDescription
error.sourcestringError source (e.g., source, network, custom)
error.typestringError type or code (e.g., NullPointerException)
error.messagestringError message
error.stackstringError stack trace
error.is_crashbooleanWhether it’s a crash
contextObjectCustom context information passed via addError’s attributes

Best Practices

  1. Initialize SDK Early: Initialize the SDK in Application.onCreate() to capture as many crashes as possible.
  2. Enable Background Event Tracking: If your app has significant background operations, consider enabling trackBackgroundEvents.
  3. Properly Upload Symbol Files:
    • Upload corresponding mapping files for each release version
    • If using NDK, also upload NDK symbol files
    • Integrate symbol file upload into your CI/CD pipeline
  4. Enrich Error Context: When manually reporting errors, attach business-related context information (e.g., user ID, operation type).
  5. Filter Irrelevant Errors: Use setErrorEventMapper to filter third-party SDK or irrelevant errors to reduce noise.

Next Steps