⚙️ Configure Error, Exception, and Crash Monitoring for Android
📖 Overview
The GermainUX Mobile App library can collect:
|
Item |
|---|
|
Crashes caused by unhandled exceptions |
|
Handled exceptions reported by application code |
|
Application errors that do not throw an exception |
|
Selected Android StrictMode violations, when enabled and supported |
|
Application uptime and closure context associated with a crash |
Error data can be correlated with the application version, Android version, device, user session, screen, fragment, transaction, and preceding application events.
Error Types
Use the appropriate GermainUX event for each condition:
|
Type |
When to use |
|---|---|
|
Crash |
The application terminates because of an unhandled failure |
|
Handled exception |
An exception occurred but the application caught and handled it |
|
Application error |
A meaningful failure occurred without a Java or Kotlin exception |
|
StrictMode violation |
Android detected a configured development or runtime policy violation |
Do not report expected user validation, such as a required field left empty, as an application error unless the software itself is failing to operate as intended.
🤖 Automatic Crash Detection
Unhandled-exception monitoring is enabled automatically after GermainUX initialization unless it is explicitly disabled:
config.setAutomaticUnhandledExceptionsMonitoring(false);
When an unhandled exception terminates the application, GermainUX attempts to capture:
|
Attribute |
|---|
|
Exception type |
|
Error message |
|
Stack trace |
|
Crash timestamp |
|
Application version |
|
Android and device context |
|
Active user session |
|
Related screen or fragment |
|
Application uptime |
|
Application-closure event |
Delivery is attempted before the application process terminates, but Android does not guarantee enough execution time to transmit crash telemetry immediately.
⛔ Disable Automatic Crash Detection
Disable automatic monitoring only when required, such as when:
|
Scenario |
|---|
|
Another crash handler must remain solely responsible for uncaught exceptions. |
|
The application implements a custom crash-reporting workflow. |
|
Crash reporting is disabled for a specific build type. |
|
Consent or privacy requirements prevent automatic collection. |
☕ Java
GermainAPMConfiguration config =
new GermainAPMConfiguration(
"https://YOUR_GERMAINUX_HOST/ingestion/fact"
);
config.setAutomaticUnhandledExceptionsMonitoring(false);
GermainAPM.init(this, config);
🚀 Kotlin
val config = GermainAPMConfiguration(
"https://YOUR_GERMAINUX_HOST/ingestion/fact"
)
config.setAutomaticUnhandledExceptionsMonitoring(false)
GermainAPM.init(this, config)
When multiple crash libraries are installed, verify that their uncaught-exception handlers are compatible and that the original handler chain is preserved.
🤝 Report a Crash Explicitly
Use collectCrash() only when the application is treating the condition as a crash or terminal failure.
☕ Java
try {
runCriticalOperation();
} catch (Throwable error) {
GermainAPM.collectCrash(
"CriticalOperationCrash",
error,
false
);
throw error;
}
🚀 Kotlin
try {
runCriticalOperation()
} catch (error: Throwable) {
GermainAPM.collectCrash(
"CriticalOperationCrash",
error,
false
)
throw error
}
Parameters:
|
Parameter |
Description |
|---|---|
|
Name |
Stable category used to identify the crash |
|
Throwable |
Exception and stack-trace information |
|
StrictMode flag |
|
collectCrash() also records application closure and uptime context. Do not use it for a condition after which the application continues normally. Use collectException() or collectError() instead.
Avoid catching Throwable solely for monitoring in normal application code. The preceding example represents a terminal boundary where the failure is reported and rethrown.
💡 Report Handled Exceptions
Use collectException() inside existing exception-handling logic when the exception is operationally meaningful.
📝 Basic example
Java:
try {
loadCustomerData();
} catch (IOException error) {
GermainAPM.collectException(error);
showCachedData();
}
Kotlin:
try {
loadCustomerData()
} catch (error: IOException) {
GermainAPM.collectException(error)
showCachedData()
}
The application remains responsible for handling the exception. Reporting it to GermainUX does not recover the failed operation or alter the application flow.
🏷️ Custom exception name
Use a stable custom name when the default exception class does not provide enough business or technical context.
Java:
try {
submitOrder();
} catch (IOException error) {
GermainAPM.collectException(
"OrderSubmissionException",
error,
false
);
displayRetryOption();
}
Kotlin:
try {
submitOrder()
} catch (error: IOException) {
GermainAPM.collectException(
"OrderSubmissionException",
error,
false
)
displayRetryOption()
}
The third parameter identifies whether the reported exception represents a StrictMode violation.
Use consistent names rather than including record IDs, user names, timestamps, or dynamic error values in the event name.
❗ Report Application Errors
Use collectError() when an important failure occurs without an exception.
Examples include:
|
Example |
|---|
|
Invalid response received from a service |
|
Required application data missing |
|
Business transaction rejected unexpectedly |
|
Local data synchronization failed |
|
Expected result not produced |
|
Application entered an invalid state |
☕ Java
if (!response.isSuccessful()) {
GermainAPM.collectError(
"CustomerSyncFailed",
"The customer synchronization request failed."
);
displayRetryOption();
}
🚀 Kotlin
if (!response.isSuccessful) {
GermainAPM.collectError(
"CustomerSyncFailed",
"The customer synchronization request failed."
)
displayRetryOption()
}
Keep error content concise and free of sensitive data.
Do not pass:
|
Do not pass |
|---|
|
Passwords |
|
Authentication tokens |
|
Payment information |
|
Personal or health information |
|
Full request or response bodies |
|
Database records |
|
Secret URLs or query parameters |
🔍 StrictMode Violations
Android StrictMode can identify development and runtime policy violations such as:
|
Violation |
|---|
|
Disk reads or writes on monitored threads |
|
Network operations on the main thread |
|
Slow calls |
|
Resource mismatches |
|
Leaked closable objects |
|
Leaked activities or registrations |
|
File URI exposure |
|
Cleartext network use |
|
Untagged sockets |
|
Unsupported non-SDK API usage |
The violations available depend on the Android version and the StrictMode policies enabled by the application.
StrictMode findings are not automatically equivalent to production crashes. Some violations log a warning, while others can be configured to terminate the application. Categorize them according to their actual behavior and impact.
Use StrictMode cautiously in production. Validate the selected policies and penalties in a test environment before rollout.
🏷️ Categorize Errors in GermainUX
Configure categories that distinguish:
|
Category |
|---|
|
Application crashes |
|
Handled exceptions |
|
Application errors |
|
StrictMode violations |
|
User-facing software errors |
|
Silent software errors |
|
Expected user validation |
|
Network and integration failures |
|
Data and synchronization failures |
This prevents user validation and low-value diagnostic events from inflating the KPI used for software failures.
📈 Analyze Errors
Use GermainUX dashboards to analyze errors by:
|
Dimension |
|---|
|
Error or exception name |
|
Exception class |
|
Application version |
|
Android version |
|
Device manufacturer and model |
|
Screen or fragment |
|
Transaction |
|
User session |
|
User or role, when approved |
|
First and last occurrence |
|
Affected users and sessions |
|
Frequency and trend |
Prioritize errors based on user impact, recurrence, severity, affected business process, and whether they were introduced by a recent release.
🔔 Alerts
Configure alerts for conditions such as:
|
Alert condition |
|---|
|
New crash signature |
|
Increased crash rate |
|
Critical transaction failure |
|
Repeated handled exception |
|
Application-version regression |
|
Error affecting many users |
|
Sudden increase in StrictMode violations |
|
Missing crash data after a known failure |
Avoid sending an alert for every individual occurrence of a high-volume error. Use aggregation, minimum affected-user counts, persistence, and severity rules.
🔒 Privacy and Obfuscation
Before enabling error reporting:
|
Action |
|---|
|
Review exception messages and stack traces for sensitive data. |
|
Anonymize or exclude sensitive fields. |
|
Avoid dynamic personal data in exception names. |
|
Restrict access to diagnostic information. |
|
Retain R8 or ProGuard mapping files for each release. |
|
Protect mapping files because they reveal application structure. |
|
Apply an appropriate retention period. |
Obfuscated stack traces may require the corresponding mapping file to identify the original classes and methods.
✅ Validation
Test the integration in a nonproduction build:
-
Initialize GermainUX.
-
Report a controlled application error.
-
Report a handled exception.
-
Trigger an unhandled exception in a safe test scenario.
-
Confirm that the crash is associated with the correct session.
-
Verify application, version, device, screen, and transaction context.
-
Confirm that the release build provides usable stack traces.
-
Verify that sensitive values are excluded.
-
Test alert thresholds and recipients.
-
Confirm that another installed crash handler still works, if applicable.
🔧 Troubleshooting
💥 Unhandled crashes are not collected
Verify that:
|
Check |
|---|
|
GermainUX initializes before the crash occurs. |
|
Automatic unhandled-exception monitoring is enabled. |
|
Another library has not replaced the GermainUX exception handler. |
|
The device can reach the ingestion endpoint. |
|
The release build includes the GermainUX library. |
|
Privacy or processing rules do not discard the event. |
A crash that terminates the process immediately may not be transmitted until the library has another opportunity to send retained telemetry, if supported by the installed version.
🔎 Handled exceptions are missing
Confirm that:
|
Check |
|---|
|
|
|
The exception is not filtered by configuration. |
|
The application remains active long enough to distribute telemetry. |
|
The GermainUX application and environment are enabled. |
|
The device has network connectivity. |
📄 Stack traces are unreadable
Check:
|
Check |
|---|
|
R8 or ProGuard configuration |
|
Preservation of source and line-number attributes |
|
Mapping-file retention |
|
Installed library compatibility |
|
Whether the exception was created without a meaningful stack trace |
🔁 Duplicate crashes appear
Verify that:
|
Check |
Notes |
|---|---|
|
The same failure is not reported manually and automatically. |
|
|
Multiple crash libraries are not forwarding the same event. |
|
|
Retry or retained-event delivery is deduplicated by the configured processing rules. |
|
ℹ️ Get More Information
GermainUX can help determine which monitoring, analytics and automation capabilities are appropriate for your Android App environment.
Component: Engine, Mobile App
Feature Availability: 2022.1 or later