Skip to content

kseongbin/CrashWatcher

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CrashLogger - Android Crash & ANR Detection Library

License JitPack Android Min SDK Kotlin

A lightweight Android library that automatically detects and logs crashes and ANRs (Application Not Responding) with detailed stack traces and device information.

한국어 문서

Features

  • 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

Installation

Step 1: Add JitPack repository

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") }
    }
}

Step 2: Add dependency

Gradle (Kotlin DSL)

dependencies {
    implementation("com.github.kseongbin:CrashWatcher:1.0.0")
}

Gradle (Groovy)

dependencies {
    implementation 'com.github.kseongbin:CrashWatcher:1.0.0'
}

Alternative: Manual AAR Installation

Download the latest AAR from Releases and add to your project:

  1. Download crashwatcher-release-1.0.0.aar
  2. Place it in app/libs/ directory
  3. Add dependency:
dependencies {
    implementation(files("libs/crashwatcher-release-1.0.0.aar"))
}

Quick Start

Basic Initialization

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>

Custom Configuration

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
    )
)

Accessing Log Files

val logDirectory = CrashLogger.getLogDirectory()
// Location: {externalFilesDir}/crash_logs/

Runtime Control (On/Off)

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
    )
)

Log Format

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

Sample Crash 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)
...

Configuration Options

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)

Requirements

  • Min SDK: 26 (Android 8.0 Oreo)
  • Target SDK: 36
  • Permissions: None required

How It Works

Crash Detection

  • Implements Thread.UncaughtExceptionHandler
  • Chains with existing handler to maintain normal crash behavior
  • Writes logs synchronously before app termination

ANR Detection

  • Watchdog thread requests tick updates from main thread
  • Detects ANR if no response within timeout period
  • Captures main thread stack trace + all thread dumps

Thread Safety

  • All log writes are synchronized
  • ANR watchdog uses atomic counters
  • Safe in multi-threaded environments

Shutdown (Optional)

You can optionally stop ANR detection when needed:

CrashLogger.shutdown()

Sample App

A sample Android app is available in the sample/ directory demonstrating library usage.

See sample/README.md for details.

Development & Testing

Running Tests

./gradlew test

View test reports:

open app/build/reports/tests/testDebugUnitTest/index.html

Test Coverage: 33 unit tests (100% passing)

For detailed testing guide and examples, see TESTING.md

Building the Library

Release AAR build:

./gradlew assembleRelease

Output location: app/build/outputs/aar/

  • crashwatcher-debug-1.0.0.aar
  • crashwatcher-release-1.0.0.aar

License

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.

Contributing

Issues and Pull Requests are always welcome!

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

Support

If you have any questions or encounter issues, please create a GitHub Issue.

Roadmap

  • Remote crash reporting integration
  • Custom crash callbacks
  • Proguard/R8 mapping support
  • Performance metrics collection