SkateSpots/packages/skatespots-background/README.md
SkateSpots 3ad214683a feat(android): native background poller plugin (no Google) - Cordn pattern
packages/skatespots-background: a local Capacitor Android plugin that polls our
own push-service /pending and raises local notifications. Modes: off / standard
(WorkManager ~15 min) / fast (foreground service ~5 min). Kotlin +
AndroidManifest (POST_NOTIFICATIONS, FOREGROUND_SERVICE_DATA_SYNC, WAKE_LOCK,
battery-exemption) + Gradle module. Client: useBackgroundDelivery (registers a
poll token via NIP-98, seeds the plugin) + a Background delivery (Android)
control in NotificationSettingsCard. The app registers by NAME, not by importing
the package, so the web bundle is unaffected. UNVERIFIED - needs cap sync + a
device.
2026-10-01 19:51:56 +07:00

2.5 KiB

skatespots-background

A local Capacitor Android plugin that gives the APK closed-app notifications without Google services — the Cordn pattern, simplified (our payloads are already content-free, so there is no Rust and no decryption here).

It polls our own push-service (GET /pending?token&since → {seq, at, changed}) and, when the cursor advances, raises a local notification.

Modes

Mode Mechanism Cadence Notes
off — — default
standard WorkManager ~15 min (OS minimum) best-effort — Doze/OEM battery managers may defer it
fast foreground service ~5 min near-live; shows a sticky notification + battery

Files

  • src/index.ts — TS↔Kotlin bridge (the app registers the plugin by name).
  • android/src/main/AndroidManifest.xml — permissions (POST_NOTIFICATIONS, FOREGROUND_SERVICE[_DATA_SYNC], WAKE_LOCK, RECEIVE_BOOT_COMPLETED, REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) + the service.
  • android/src/main/java/org/skatespots/background/:
    • SkateSpotsBackgroundPlugin.kt — the @CapacitorPlugin (configure, seed, postNotification, clearNotifications, consumePendingUrl, isBatteryExempted, requestBatteryExemption).
    • PollWorker.kt (WorkManager), PollService.kt (foreground), Poller.kt, Notifier.kt, PollPrefs.kt.
  • android/build.gradle — the plugin Gradle module.

Wiring

  1. The root package.json depends on it: "skatespots-background": "file:packages/skatespots-background".
  2. npm run android:init / android:sync (which run npx cap sync android) pick it up and add the Android module.
  3. The client enables it from Settings → Notifications → Background delivery (Android) via src/hooks/useBackgroundDelivery.ts.

⚠️ Caveats

  • Android-only and cannot be verified in CI — needs a device.
  • standard is not a guarantee (Doze/OEM). fast needs the sticky notification and the user must start it while the app is foreground.
  • build.gradle mirrors the Capacitor plugin template; align its Gradle/Kotlin versions with the app's Capacitor major if a build complains.
  • The small icon uses applicationInfo.icon; swap for a dedicated monochrome status icon if the app's launcher icon renders poorly in the shade.

Server contract

push-service (see its README): POST /native/poll/register (NIP-98 proof → poll token), GET /pending?token&since, POST /native/poll/unregister.