Skip to content

Mobile App Satellite

Use an Android phone as a BirdNET-NG satellite for portable bird audio capture.

Building the APK

The mobile app is built using Docker:

bash
docker build -t birdnet-mobile -f packages/mobile/Dockerfile .
docker create --name birdnet-apk birdnet-mobile
docker cp birdnet-apk:/output/app-debug.apk ./birdnet-satellite.apk
docker rm birdnet-apk

Transfer the APK to your phone and install it. The debug keystore is persistent across builds so APK updates work without uninstalling.

Android Permissions

The app requests these permissions at startup:

PermissionWhy
RECORD_AUDIOCapture audio from the microphone
ACCESS_FINE_LOCATIONGPS coordinates for geo-aware inference

If permissions are denied, the app shows an "Open Settings" button to navigate to Android's app permission screen.

Setup Flow

1. Sign In

Enter your hub URL (default: https://birdnet.owndesign.net) and log in with your credentials. The app uses a JWT Bearer token for authentication.

2. Register Satellite

Choose a name for this satellite and select the tenant it belongs to. GPS location is acquired automatically after registration — no need to enter coordinates during registration.

3. GPS Requirement

Before recording starts, the app requires a GPS fix or manually entered coordinates. This is needed because BirdNET uses location + date to filter its species list for regionally plausible species.

If GPS is unavailable:

  • A yellow "GPS Location Required" prompt appears
  • Retry GPS: attempt auto-acquisition again
  • Open Settings: enter latitude/longitude manually

4. Record

Once GPS is set, the app connects to the hub via MQTT (WebSocket over TLS) and starts capturing 3-second audio chunks. Silence is filtered on-device (RMS check).

Recording Screen

The recording screen shows:

StatDescription
Chunks SentAudio chunks uploaded to hub
FilteredChunks rejected by silence filter
Last SentTime since last successful upload
HubConnection status (Connected / Connecting / Offline)
GPSFix status (Fixed / Acquiring / Not set)
NameSatellite display name

Buttons:

  • Pause / Resume — temporarily stop recording without disconnecting
  • Settings — open settings panel

Settings Panel

Satellite Name

Editable field that syncs to the hub. Visible on the Satellites page in the web UI.

Location

ControlDescription
Latitude / LongitudeManual coordinate entry
Use GPSAcquire position from device GPS
SaveApply manually entered coordinates
Auto-update GPSToggle periodic GPS updates (on by default)
IntervalUpdate frequency: 30s, 1min, 2min, 5min, 10min

Battery Savings

For a stationary phone, turn off GPS auto-update and set coordinates manually. GPS polling is the largest battery drain after screen-on.

Keep Screen On

Toggle to prevent the phone from locking. Uses the Capacitor keep-awake plugin.

Recording Profile

Read-only display of the hub-assigned profile, with resolved sunrise/sunset times and active recording windows. Profiles are changed from the hub (Satellites page), not in-app.

Satellite Info

  • Satellite ID — UUID (read-only)
  • Hub — hub URL (read-only)

Unregister

Type UNREGISTER to confirm. This:

  • Stops recording
  • Disconnects from the hub
  • Clears the saved configuration
  • Does not delete the satellite record on the hub

To re-register: sign in again and register with the same name — the device ID matching will reconnect to the existing satellite record.

Background Mode

The app uses the Capacitor background mode plugin to continue recording when minimized. A persistent notification shows "BirdNET Satellite — Recording bird sounds..."

Battery

Background recording with screen off is the most battery-efficient mode. Keep-screen-on with background mode will drain battery faster.

Heartbeat

The app sends a heartbeat every 30 seconds via MQTT QoS 1. This keeps the satellite showing as "online" on the hub even when all audio chunks are filtered. The heartbeat reports the current state:

  • recording — actively capturing
  • paused — user pressed Pause

Telemetry

Reported every 60 seconds:

MetricSource
Battery levelCapacitor Device plugin
Storage freenavigator.storage.estimate()
GPS coordinatesGeolocation plugin (if auto-update is on)
UptimeElapsed time since app start

CPU temperature is not available on mobile — shown as "—" on the hub.

Log Viewer

Collapsible panel at the bottom of the recording screen. Captures:

  • Audio capture events (chunk sent, filtered)
  • MQTT connection changes
  • GPS updates
  • Errors and warnings

Logs are in-memory only (max 200 entries). Use "Copy All" to export, "Clear" to reset.

Troubleshooting

SymptomSolution
"Could not start audio source"Another app is using the microphone. Close other audio apps.
"Microphone permission not granted"Tap "Open Settings" and enable the microphone permission.
Satellite shows offlineCheck hub connection status. Verify hub URL and credentials.
GPS unavailableEnable location services. Try "Use GPS" in Settings. Some indoor locations have no GPS signal.
App not installed (update fails)The APK was built with a different signing key. Uninstall first, then install the new APK.
Duplicate satellitesThe device ID is preserved across reinstalls. If duplicates appear, delete the extra from the hub's Satellites page.

Distributed bird sound identification