Skip to content

Latest commit

 

History

History
60 lines (42 loc) · 4.75 KB

File metadata and controls

60 lines (42 loc) · 4.75 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project

Java/Swing desktop app for managing many Android devices over adb. Packaged for Mac/Windows/Linux via jdeploy. Tested with up to 45 devices over USB hubs.

Build & Run

Java 17+, Maven. Entry point: com.jpage4500.devicemanager.MainApplication.

  • mvn compile exec:java — run from source (or scripts/run.sh)
  • mvn -B package — build fat jar to target/AndroidDeviceManager.jar (or scripts/build.sh)
  • mvn install — also bundles a native .app for macOS via macosappbundler-maven-plugin
  • scripts/createMacApp.sh — full Mac packaging + zip + copy to /Applications
  • scripts/clear-preferences.sh — wipes saved Java Preferences
  • No test suite is set up (package.json's test script is a stub).

CI: .github/workflows/jdeploy.yml runs on push to develop — builds, publishes via jdeploy, creates a GitHub release. Version is the Maven build timestamp (yy.M.d-Hmm) injected into app.properties.

External tooling assumed on PATH

  • adb (Android platform-tools)
  • scrcpy (for device mirroring)

The app shells out to platform-specific scripts in src/main/resources/scripts/ (mirror.sh/.bat, terminal.sh/.bat, start-server.sh/.bat, record-screen.sh/.bat, run-custom.sh, shell.sh). They are extracted to a temp dir at runtime; see DeviceManager constants SCRIPT_*.

Architecture

Packages (com.jpage4500.devicemanager)

  • MainApplication — boot, FlatLaf setup, taskbar icon, file-open handler (apk/xapk drag-onto-app), creates DeviceScreen.
  • ui/ — Swing screens. Each top-level screen extends BaseScreen: DeviceScreen (main list), ExploreScreen (file browser), ViewLogsScreen, SaveLogsScreen, InputScreen, MessageViewScreen. ui/dialog/ and ui/views/ hold dialogs and reusable Swing widgets.
  • manager/ — non-UI business logic. DeviceManager is a singleton coordinating adb via the bundled jadb library, holding the device list, scheduled refresh, and per-device logging state. RemoteConnectionManager + RemoteConnection connect to other ADM instances; RemoteServerManager + RemoteHttpServer (NanoHTTPD) expose this instance's devices over HTTP so another ADM instance can use them. NetworkDiscoveryManager uses jmDNS/SSDP to find peers.
  • data/ — POJOs (Device, DeviceFile, LogEntry, RemoteServerConfig, etc.). Annotate fields with @ExcludeFromSerialization to keep Gson from persisting them (see AnnotationExclusionStrategy).
  • table/TableModels; table/utils/ holds matching CellRenderers, RowSorters, RowFilters.
  • logging/ — custom SLF4J binding (AppLoggerFactory registered via META-INF/services/org.slf4j.spi.SLF4JServiceProvider). Levels are the Android-style ints in Log (VERBOSE=2 … ASSERT=7). File logs go to ~/.device_manager/device_manager_log.txt.
  • utils/ — Swing helpers, file I/O, Gson wrapper, network/UPnP helpers, PreferenceUtils.

Bundled adb client (se.vidstige.jadb)

A vendored copy of jadb — a pure-Java ADB client. The app talks to the local adb server via JadbConnection/JadbDevice rather than spawning adb for every command. Treat this package as a third-party dep; prefer not to modify it.

Remote-server feature (recent area of active work)

ADM can act as both client and server. RemoteServerManager runs RemoteHttpServer on port 8765 with bearer-token auth and exposes /api/devices, /api/execute, /api/files/list|download|upload, /api/screenshot. Headers x-client-ip / x-client-name / authorization identify the caller. RemoteConnectionManager is the matching client. UpnpUtils does optional port forwarding; jmDNS handles LAN discovery.

Persistence

  • Java Preferences API via PreferenceUtils — keys are enums (Pref, PrefBoolean, PrefInt). scripts/clear-preferences.sh wipes them.
  • ~/.device_manager/ (from Utils.getDeviceManagerFolder()) — log file, downloaded files, etc.

Threading

  • All Swing work goes through SwingUtilities.invokeLater.
  • DeviceManager owns two pools: commandExecutorService (blocking shell-outs like mirror/terminal) and scheduledExecutorService (periodic device refresh on DEVICE_REFRESH_MINS).

Conventions

  • Use SLF4J: private static final Logger log = LoggerFactory.getLogger(Foo.class); — call log.debug/info/warn/error with {} placeholders.
  • Layouts use MigLayout (net.miginfocom.swing.MigLayout).
  • TextUtils mirrors Android's helper (use isEmpty, equalsIgnoreCase, etc. instead of rolling your own).
  • Gson via GsonHelper; respect @ExcludeFromSerialization.
  • Log filter syntax (used in ViewLogsScreen) is documented in LOGS.md.