Background sessions
Keep a Meta Ray-Ban session alive when your app backgrounds — the Android foreground service for mic, iOS background modes, and which capabilities survive.
By default, capability subscriptions (glasses.audio.*, the assistant) run on the SDK's coroutine scope, which is bound to your process — not to any Activity. While your app is foreground, that's enough. To keep the glasses listening (a voice assistant or live transcription) while your app is backgrounded, you need an OS-level keep-alive: a foreground service on Android, background modes on iOS. This guide covers what's required, what survives, and what doesn't.
Kotlin leads the snippets. Android uses the bundled foreground service; iOS uses background modes — a genuinely different OS mechanism, covered in its own section below.
What "background session" means
The glasses connection itself doesn't end the moment your app loses focus — but the OS will reclaim a backgrounded process (and with it your ExtentosGlasses instance and its transport) under memory pressure or after enough time, unless you hold a foreground service or background-mode budget. So "keeping the session alive" is really "keeping your process alive and the audio path running while backgrounded."
This is a separate concern from handling a disconnect when it does happen — see handle disconnects for the recovery path.
Android: the bundled foreground service
For background-surviving microphone capture, the library ships a foreground service so you don't write one:
import com.extentos.glasses.core.service.GlassesForegroundService
// AFTER RECORD_AUDIO is granted at runtime — typically in the grant callback:
GlassesForegroundService.start(this) // 'this' is any Context
// When background capture is no longer needed:
GlassesForegroundService.stop(this)The service is declared for you in the library manifest as:
<service
android:name="com.extentos.glasses.core.service.GlassesForegroundService"
android:foregroundServiceType="microphone"
android:exported="false" />You don't declare it — you start it. The rules that matter (see Android lifecycle and manifest setup):
- Permission first.
RECORD_AUDIOmust already be granted at runtime. On Android 14+, starting amicrophone-type foreground service without the grant throwsSecurityExceptionat service-create time and crashes the app. - Declare the foreground-service permissions. Your app's manifest needs
FOREGROUND_SERVICEandFOREGROUND_SERVICE_MICROPHONE(Android 14+) —getPermissionsderives these from your continuous-capture capabilities. The library declares the<service>element; the permissions are app-owned. - Start from an Activity, not
Application.onCreate. The grant can't exist that early. Start it from your permission-grant callback, or after acheckSelfPermission(...) == PERMISSION_GRANTEDcheck. - Idempotent. Calling
startagain while running just updates the notification. - Stop it when done to drop the notification and release the foreground budget.
Camera in the background is not covered by the bundled service.
GlassesForegroundServiceismicrophone-type only. Surviving avideoFrames()stream in the background requires acamera-type foreground service, which Android requires the consumer app to declare itself (the library can't declare a camera FGS on your behalf without forcing it on every app). SubclassGlassesForegroundServiceand declare your own<service android:foregroundServiceType="camera" />with the matching runtime rules. Most apps only need background mic.
iOS: background modes
iOS doesn't use foreground services — a backgrounded app keeps running only within a declared background mode budget. For an audio-driven glasses session, the relevant UIBackgroundModes entries (bluetooth-central, bluetooth-peripheral, external-accessory — plus audio, which you must add yourself when you stream the mic; generateConnectionModule emits only the three Bluetooth/accessory modes) must be present in Info.plist; generateConnectionModule(platform: "ios") includes the background-mode and UISupportedExternalAccessoryProtocols keys. iOS background execution is more constrained than an Android foreground service — validate background behavior on a real device before relying on it.
What survives backgrounding
| Capability | Backgrounded behavior |
|---|---|
glasses.audio.transcriptions() / recordDiscrete() / the assistant | Survives with the foreground service (Android) / audio background mode (iOS) running. Without it, capture stops when the process is reclaimed. |
glasses.audio.speak() | Plays while the audio path is alive; same keep-alive requirement. |
glasses.camera.* | Needs a consumer-declared camera-type FGS on Android (not the bundled mic service). |
| The connection state | Persists while the process lives; on process death you re-create(...) and reconnect — see process death. The dev-loop pairing identity is persisted to filesDir, but the live connection is re-established from scratch. |
Camera-only or strictly foreground apps don't need any of this — the foreground-service declaration is harmless if unused.
Honest limits
- The OS can still kill you. A foreground service and background modes reduce — they don't eliminate — OS reclamation. Under hard memory pressure or aggressive battery-saver/OEM policies, a backgrounded session can still be terminated. Design for it: observe
glasses.connection.state, handle theDisconnectedcause, and reconnect cleanly. See handle disconnects. - Battery cost is real. A live mic + Bluetooth audio path in the background drains both the phone and the glasses. Start the service only while you actually need background capture, and stop it as soon as you don't.
- Sim ≠ hardware here. The browser simulator does not exercise OS background lifecycle at all — there's no foreground service, no battery-saver kill, no process reclamation in a browser tab. A session that "stays alive when backgrounded" in the simulator tells you nothing about real-device background survival. Verify backgrounding on real hardware.
Related
- Android SDK lifecycle — the full foreground-service wiring and process-death behavior.
- Handle disconnects — recovering when a backgrounded session is killed.
- Sessions — the connection-state machine and what persists.
Related
Android SDK lifecycle
When to create and shut down ExtentosGlasses, how the bundled foreground service keeps the glasses mic alive in the background, and how Extentos behaves across Activity lifecycle and process death.
Handle disconnects
Observe glasses.connection.state, branch on the typed Disconnected.cause to tell a user-pulled-the-glasses-off from a Bluetooth drop, and reconnect cleanly. The connection-state spine for any Meta Ray-Ban app.
Sessions
How an Extentos session works — the glasses connection-state machine, what persists across backgrounding and reconnects, and the three browser-simulator roles.
Hardware events
What Meta Ray-Ban surfaces today via glasses.runtime.events, connection.state, and toggles — and which hardware-alert streams aren't exposed yet. No IMU API.
Handle disconnects
Observe glasses.connection.state, branch on the typed Disconnected.cause to tell a user-pulled-the-glasses-off from a Bluetooth drop, and reconnect cleanly. The connection-state spine for any Meta Ray-Ban app.