A lightweight Android library that automatically detects and logs crashes and ANRs (Application Not Responding) with detailed stack traces and device information.
- Crash Detection: Automatically captures all uncaught exceptions with detailed stack traces
- ANR Detection: Monitors main thread responsiveness using watchdog pattern
- No Permissions Required: Uses app-specific external storage (
getExternalFilesDir) - Automatic Log Rotation: Maintains configurable maximum number of log files
- Rich Metadata: Automatically collects device info, app version, thread states, and more
- Thread-Safe: Safe log writing in concurrent environments
- Lightweight: Minimal dependencies and small APK footprint
Add JitPack repository to your settings.gradle.kts:
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}Or if you're using older project structure, add to root build.gradle.kts:
allprojects {
repositories {
google()
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}Gradle (Kotlin DSL)
dependencies {
implementation("com.github.kseongbin:CrashWatcher:1.0.0")
}Gradle (Groovy)
dependencies {
implementation 'com.github.kseongbin:CrashWatcher:1.0.0'
}Download the latest AAR from Releases and add to your project:
- Download
crashwatcher-release-1.0.0.aar - Place it in
app/libs/directory - Add dependency:
dependencies {
implementation(files("libs/crashwatcher-release-1.0.0.aar"))
}Initialize in your Application class:
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
CrashLogger.initialize(this)
}
}Don't forget to declare your Application class in AndroidManifest.xml:
<application
android:name=".MyApplication"
...>
</application>CrashLogger.initialize(
context = this,
config = CrashLoggerConfig(
enableCrashDetection = true,
enableAnrDetection = true,
anrTimeoutMs = 3000L, // 3 seconds
maxLogFiles = 20, // Keep recent 20 logs
logFilePrefix = "myapp_log",
includeDeviceInfo = true,
includeAppInfo = true,
includeThreadInfo = true
)
)val logDirectory = CrashLogger.getLogDirectory()
// Location: {externalFilesDir}/crash_logs/Enable or disable crash logging at runtime:
// Disable logging (e.g., when not needed)
CrashLogger.setEnabled(false)
// Enable logging when you need to trace
CrashLogger.setEnabled(true)
// Check current status
if (CrashLogger.isEnabled()) {
// Logging is active
}Best Practice: BuildConfig-based initialization
// Automatically enable only in debug builds
CrashLogger.initialize(
context = this,
config = CrashLoggerConfig(
enabled = BuildConfig.DEBUG // Off in release, on in debug
)
)Logs are saved as text files with the following naming pattern:
crash_log_crash_20251228_153045.txt // Crash log
crash_log_anr_20251228_153112.txt // ANR log
=== CRASH LOG ===
Timestamp: 2025-12-28 15:30:45.123
Type: CRASH
=== EXCEPTION INFO ===
Thread: main (id=1)
Exception: java.lang.NullPointerException: ...
Stack Trace:
at com.example.MainActivity.onCreate(MainActivity.kt:25)
...
=== DEVICE INFO ===
Manufacturer: Samsung
Model: SM-G998B
Android Version: 14 (API 34)
Available RAM: 2048 MB
...
=== APP INFO ===
Package: com.example.myapp
Version: 1.0.0 (1)
...
| Option | Default | Description |
|---|---|---|
enabled |
true |
Master switch for entire library (runtime controllable) |
enableCrashDetection |
true |
Enable crash logging |
enableAnrDetection |
true |
Enable ANR detection |
anrTimeoutMs |
5000 |
ANR detection threshold (milliseconds) |
maxLogFiles |
10 |
Maximum number of log files to keep |
logFilePrefix |
"crash_log" |
Prefix for log file names |
includeDeviceInfo |
true |
Include device metadata |
includeAppInfo |
true |
Include app version info |
includeThreadInfo |
true |
Include all thread dumps (for ANR) |
- Min SDK: 26 (Android 8.0 Oreo)
- Target SDK: 36
- Permissions: None required
- Implements
Thread.UncaughtExceptionHandler - Chains with existing handler to maintain normal crash behavior
- Writes logs synchronously before app termination
- Watchdog thread requests tick updates from main thread
- Detects ANR if no response within timeout period
- Captures main thread stack trace + all thread dumps
- All log writes are synchronized
- ANR watchdog uses atomic counters
- Safe in multi-threaded environments
You can optionally stop ANR detection when needed:
CrashLogger.shutdown()A sample Android app is available in the sample/ directory demonstrating library usage.
See sample/README.md for details.
./gradlew testView test reports:
open app/build/reports/tests/testDebugUnitTest/index.htmlTest Coverage: 33 unit tests (100% passing)
For detailed testing guide and examples, see TESTING.md
Release AAR build:
./gradlew assembleReleaseOutput location: app/build/outputs/aar/
crashwatcher-debug-1.0.0.aarcrashwatcher-release-1.0.0.aar
Copyright 2025 Seongbin Kim
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Issues and Pull Requests are always welcome!
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
If you have any questions or encounter issues, please create a GitHub Issue.
- Remote crash reporting integration
- Custom crash callbacks
- Proguard/R8 mapping support
- Performance metrics collection