Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 37 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
[![Android](https://img.shields.io/badge/Platform-Android-green.svg)](https://developer.android.com/)
[![Kotlin](https://img.shields.io/badge/Language-Kotlin-purple.svg)](https://kotlinlang.org/)
[![Jetpack Compose](https://img.shields.io/badge/UI-Jetpack%20Compose-blue.svg)](https://developer.android.com/jetpack/compose)
[![API](https://img.shields.io/badge/API-21%2B-brightgreen.svg)](https://android-arsenal.com/api?level=21)
[![API](https://img.shields.io/badge/API-23%2B-brightgreen.svg)](https://android-arsenal.com/api?level=23)
[![Version](https://img.shields.io/badge/Version-0.1.0--alpha-orange.svg)](https://github.com/jonathanlee06/StackLens/releases)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)

*A powerful Android crash log viewer that reads system crash logs directly from your device. Built with Jetpack Compose and Material 3.*
Expand All @@ -21,32 +22,43 @@
## Features

- **View Crash Logs** - Read app crashes, ANRs, and native crashes from the system DropBox
- **Filter & Search** - Filter by crash type (Crashes, ANRs, Native) and search through logs
- **Sort Options** - Sort by newest or oldest first
- **Time Range** - Filter crashes from the last hour to the last 7 days
- **Detailed View** - View full stack traces with syntax highlighting
- **Share & Copy** - Easily share or copy crash logs
- **Dark Mode** - Full dark mode support with system theme following
- **Dynamic Colors** - Material You dynamic colors on Android 12+
- **AI Crash Insights** - On-device Gemini Nano (ML Kit GenAI) explains stack traces, flags the
probable cause, and suggests fixes — no network required
- **Natural-Language Search** - Ask things like *"NullPointer from Gmail"* or *"ANRs from last 3
days"*; suggested prompts appear in AI mode
- **Crash Grouping** - Similar crashes are grouped by signature with occurrence counts and
expandable detail
- **Events Trend** - 7-day activity sparkline on the list screen
- **Rich Filters** - Bottom sheet with categories and per-package selection, plus quick Crashes /
ANRs / Native chips
- **Sort & Time Range** - Newest / oldest, and last hour through last 7 days
- **Detailed View** - Full stack traces with syntax highlighting and frame parsing
- **Background Detection** - WorkManager-driven scans surface new crashes via notifications
- **Local Persistence** - Crashes are stored in Room so they survive DropBox eviction
- **Share & Copy** - One-tap share or copy of any crash
- **Loading Skeletons** - Shimmer placeholders while data loads
- **Dark Mode & Material You** - Full dark support with dynamic colors on Android 12+

---

## Requirements

- Android 5.0 (API 21) or higher
- Android 6.0 (API 23) or higher
- ADB access for granting special permissions
- Android 14+ with a compatible device (Pixel 8+, etc.) for on-device AI insights — gracefully
degrades on unsupported devices

---

## Permissions

StackLens requires special permissions that must be granted via ADB:

| Permission | Purpose |
|------------|---------|
| `READ_LOGS` | Read system crash logs |
| `READ_DROPBOX_DATA` | Access crash data from DropBoxManager |
| `PACKAGE_USAGE_STATS` | Get app names and icons (granted via Settings) |
| Permission | Purpose | How it's granted |
|-----------------------|---------------------------------------|------------------|
| `READ_LOGS` | Read system crash logs | ADB |
| `READ_DROPBOX_DATA` | Access crash data from DropBoxManager | ADB |
| `PACKAGE_USAGE_STATS` | Get app names and icons | System settings |

---

Expand Down Expand Up @@ -84,16 +96,24 @@ After installing the app, you need to grant the required permissions:

> **Note:** The app will close automatically when granting ADB permissions. This is expected Android behavior - simply reopen the app.

> **Debug builds:** `installDebug` installs with the `.dev` application-id suffix. Grant permissions
> against `com.devbyjonathan.stacklens.dev` instead of `com.devbyjonathan.stacklens`.

---

## Tech Stack

- **Kotlin** - 100% Kotlin
- **Jetpack Compose** - Modern declarative UI
- **Material 3** - Material Design 3 with dynamic colors
- **Navigation Compose** - Single activity navigation
- **Hilt** - Dependency injection
- **Coroutines & Flow** - Asynchronous programming
- **Navigation Compose** - Single activity navigation
- **Room** - Local persistence for crash history
- **WorkManager + Hilt Worker** - Background crash detection
- **ML Kit GenAI (Gemini Nano)** - On-device AI crash insights
- **AndroidX WebKit** - In-app WebView with theme-aware rendering
- **Firebase Analytics & Crashlytics** - Usage and stability telemetry
- **DropBoxManager** - System crash log access

---
Expand Down Expand Up @@ -155,7 +175,8 @@ own.

<div align="center">

**⭐ [Star](https://github.com/jonathanlee06/Teleport/stargazers) this repo if you find it helpful!**
**⭐ [Star](https://github.com/jonathanlee06/StackLens/stargazers) this repo if you find it helpful!
**

Made with ❤️ and ☕ by Jonathan

Expand Down
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ dependencies {
implementation(libs.coroutines.android)
implementation(libs.androidx.browser)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.webkit)
testImplementation(libs.coroutines.test)

// Firebase
Expand Down
Binary file added app/src/debug/ic_launcher-playstore.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 6 additions & 6 deletions app/src/debug/res/drawable/ic_launcher_foreground.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@
android:translateY="150.08">
<path
android:pathData="M177.43,156H49V204H163.3L174.22,185.71L163.3,173.52L177.43,156Z"
android:fillColor="#ffffff"/>
android:fillColor="#FF8975" />
<path
android:pathData="M311,156H203.11L188.99,173.52L198.62,185.71L185.13,204H311V156Z"
android:fillColor="#ffffff"/>
android:fillColor="#FF8975" />
<path
android:pathData="M81,97h198v35h-198z"
android:fillColor="#FFDBB2"/>
android:fillColor="#6B655A" />
<path
android:pathData="M81,228h198v35h-198z"
android:fillColor="#FFDBB2"/>
android:fillColor="#6B655A" />
<path
android:pathData="M330,180C330,97.16 262.84,30 180,30C97.16,30 30,97.16 30,180C30,262.84 97.16,330 180,330V360C80.59,360 0,279.41 0,180C0,80.59 80.59,0 180,0C279.41,0 360,80.59 360,180C360,279.41 279.41,360 180,360V330C262.84,330 330,262.84 330,180Z"
android:fillColor="#ffffff"/>
android:fillColor="#191613" />
<path
android:pathData="M293.3,287L425.78,419.47C436.91,430.6 436.91,448.65 425.78,459.78C414.65,470.91 396.6,470.91 385.47,459.78L253,327.3L293.3,287Z"
android:fillColor="#ffffff"/>
android:fillColor="#191613" />
</group>
</vector>
5 changes: 5 additions & 0 deletions app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
Binary file added app/src/debug/res/mipmap-hdpi/ic_launcher.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/debug/res/mipmap-mdpi/ic_launcher.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/debug/res/mipmap-xhdpi/ic_launcher.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/debug/res/mipmap-xxhdpi/ic_launcher.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/src/debug/res/mipmap-xxxhdpi/ic_launcher.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion app/src/debug/res/values/ic_launcher_background.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#FF8800</color>
<color name="ic_launcher_background">#F0EAE1</color>
</resources>
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
<application
android:name=".StackLensApp"
android:allowBackup="true"
android:enableOnBackInvokedCallback="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
Expand Down
Binary file added app/src/main/ic_launcher-playstore.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading