The Problem

Users need an offline‑first Android tool that can predict when radio‑communication satellites will be visible from a given location. Existing desktop utilities (e.g., Gpredict) require a PC and manual TLE updates, which is inconvenient for field operators who rely on a mobile device.

What This Does

Look4Sat is a pure‑Kotlin Android app that downloads TLE data from Celestrak/SatNOGS, stores it locally (core/data/src/main/java/com/rtbishop/look4sat/core/data/database/Look4SatDb.kt), and computes orbital positions and passes on‑device using the domain model in core/domain/src/main/java/com/rtbishop/look4sat/core/domain/predict/*.kt. The UI is built with Jetpack Compose (core/presentation/src/main/java/com/rtbishop/look4sat/core/presentation/*.kt) and shows a map (feature/map/src/main/...) and a pass list (feature/passes/...). Custom TLE files can be imported via a simple file‑picker UI.

How It Is Wired

Entry point – app/src/main/java/com/rtbishop/look4sat/MainActivity.kt creates the MainApplication (which installs the Dagger/Hilt‑style MainContainer from core/data/src/main/java/com/rtbishop/look4sat/core/data/injection/MainContainer.kt).

Data flow

  1. MainContainer builds the repository graph: SatelliteRepo (core/data) ↔ ISatelliteRepo (core/domain).
  2. SatelliteRepo reads/writes SatEntry and SatRadio via Look4SatDao (Room).
  3. UI screens (MainScreen.kt, PassesScreen.kt) request satellite lists through core/domain/src/main/java/com/rtbishop/look4sat/core/domain/usecase/* which delegate to the repository.
  4. Orbital calculations are performed in core/domain/src/main/java/com/rtbishop/look4sat/core/domain/predict/OrbitalObject.kt and related classes; results are exposed as LiveData/StateFlow to the Compose UI.

Side effects

  • Network fetches (RemoteSource.kt) populate the DB on start‑up.
  • AddToCalendar.kt and ShowToast.kt invoke Android framework APIs from the data layer.

Hot spots – PassesScreen.kt, MainScreen.kt, and SatelliteRepo.kt have a maximum indentation depth of 8, making the control flow hard to follow. The same 6‑line helper block appears in 73 files (e.g., MainActivity.kt, ApplicationPlugin.kt), indicating duplicated logic. DeepSpaceObject.kt (781 lines) aggregates many responsibilities, increasing change‑impact risk.

No circular module imports were detected; the import graph is flat across the 76 Kotlin files.

How To Use It

# Clone the exact repo
git clone https://github.com/moses-y/Look4Sat.git
cd Look4Sat

# Build the debug APK (requires Android SDK & Gradle wrapper)
./gradlew assembleDebug

# Install on a connected device or emulator
adb install app/build/outputs/apk/debug/app-debug.apk

Configuration lives in the Android settings UI; no external environment variables or secret files are required. The Gradle build is driven by the top‑level build.gradle.kts and the module‑specific scripts under core/* and feature/*.

Real‑World Use

A field technician installs the APK on a rugged Android phone, opens the app, sets the ground station coordinates in Settings, and taps “Refresh” to pull the latest TLE set. The UI instantly shows the next visible passes for the next 10 days, allowing the technician to schedule antenna pointing without any network connectivity.

Code Health & Issues

  • High – Pin GitHub Actions – .github/workflows/release.yml uses mutable tags (gradle/actions/setup-gradle@v5, r0adkll/sign-android-release@v1). Replace each @vN with a fixed 40‑char SHA to avoid supply‑chain risk.
  • Medium – Expand Test Suite – Only 2 test files (DataParserTest.kt, QthConverterTest.kt) cover 89 source files (≈2 % coverage). Add unit tests for high‑fan‑in modules such as SatelliteRepo, OrbitalObject, and the Compose screens.
  • Low – Set Workflow Timeouts – release.yml lacks timeout-minutes on jobs; set a reasonable bound (e.g., timeout-minutes: 30) to prevent overlapping runs.
  • High – Deep Nesting – Files PassesScreen.kt, MainScreen.kt, SatelliteRepo.kt reach 8 levels of indentation; refactor with early returns and extracted helper functions.
  • High – Duplicated Code – Repeated 6‑line blocks appear in 73 files (e.g., activity/application setup). Consolidate into shared utilities under build-logic/convention.
  • Medium – Oversized File – DeepSpaceObject.kt (781 lines) mixes parsing, coordinate conversion, and orbital math. Split into focused classes (e.g., DeepSpaceParser, DeepSpaceCalculator).

All required CI files, license, and a README are present; no Dockerfile or lockfile exists, which is acceptable for an Android‑only project.

The Bottom Line

Look4Sat delivers a functional offline satellite pass predictor on Android, with a clean modular layout and modern Kotlin/Compose stack. However, deep nesting, duplicated helpers, and a monolithic orbital model raise maintenance costs, and test coverage is minimal. The project is suitable for teams that need a ready‑made mobile tracker and are prepared to invest in refactoring and testing to improve long‑term stability.