---
title: Android SDK lifecycle
description: 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.
type: guide
platform: android
vendor: meta
related:
  - /docs/sdk/android/initialization
  - /docs/sdk/android/manifest
  - /docs/sdk/android/threading
  - /docs/reference/errors
---

`ExtentosGlasses` is a long-lived object with an explicit start and stop. You own its lifetime — it doesn't auto-register with the Android lifecycle, so where you create and release it is your decision.

## Create once, shut down once

```kotlin
// Start: hold the handle for the life of the glasses session.
val glasses = ExtentosGlasses.create(config)

// Stop: release the transport and cancel the SDK's coroutine scope.
suspend fun tearDown() {
    glasses.shutdown()
}
```

`shutdown()` is a `suspend` function — call it from a coroutine. It shuts down the active transport (closing the DAT/Bluetooth or WebSocket connection) and cancels the internal `SupervisorJob` scope that drives every `Flow` the SDK emits. After `shutdown()`, the instance is spent; create a new one if you need to reconnect.

Where to anchor it:

- **App-scoped session** (the common case — glasses connection persists across screens): create it in a holder tied to your application or a shared `ViewModel`, and call `shutdown()` when the user explicitly disconnects or the app is being torn down.
- **Screen-scoped session**: create it in a screen-level `ViewModel` and call `shutdown()` from `onCleared()`. The rule is **one live instance at a time**, not one per process — this is safe only if exactly one screen owns it and the old one is shut down before the next is created. If two screens can be alive at once, use the app-scoped holder instead; two concurrent instances each run their own auto-bind probe and telemetry registration and will fight over the transport.

  ```kotlin
  class GlassesViewModel : ViewModel() {
      val glasses = ExtentosGlasses.create(config)

      override fun onCleared() {
          viewModelScope.launch { glasses.shutdown() }
      }
  }
  ```

Don't create a fresh `ExtentosGlasses` per `Activity.onCreate` if the same glasses session should outlive configuration changes — a `ViewModel` survives rotation; the Activity does not.

## Activity and Fragment wiring

The SDK needs an Activity in two situations, both supplied through `ExtentosConfig`:

- **`applicationContext`** — required when the transport resolves to RealMeta (Meta DAT initializes against a `Context`). Pass `applicationContext`, not an Activity, so the reference is safe to hold.
- **`activityProvider: () -> Activity?`** — Meta registration (the pairing handoff) needs a *foreground* Activity. Provide a closure that returns your current top Activity (e.g. from an `ActivityLifecycleCallbacks`-tracked reference), so the SDK can launch registration when the user connects.

```kotlin
ExtentosConfig(
    applicationContext = applicationContext,
    activityProvider = { topActivityRef.get() },   // your current foreground Activity
)
```

Observe connection state from your UI through `connection.state` (a `StateFlow<GlassesState>`) — collect it lifecycle-aware with `repeatOnLifecycle` so you stop collecting when the screen is stopped. See [Threading](/docs/sdk/android/threading).

## Background capture and the foreground service

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 mic alive while your app is **backgrounded** (a voice assistant or live transcription that must keep listening), start the library's bundled foreground service:

```kotlin
import com.extentos.glasses.core.service.GlassesForegroundService

// AFTER RECORD_AUDIO is granted at runtime — typically in the grant callback:
GlassesForegroundService.start(this)

// When background capture is no longer needed:
GlassesForegroundService.stop(this)
```

The service is declared for you in the library manifest (`foregroundServiceType="microphone"`), so you only start/stop it — see [Manifest setup](/docs/sdk/android/manifest). Key rules:

- **Permission first.** `RECORD_AUDIO` must already be granted. On Android 14+, starting the service without the grant throws `SecurityException` at service-create time and kills the app before the first frame draws.
- **Not from `Application.onCreate`.** The grant can't exist that early. Start it from an Activity (or a `ViewModel` scoped to one) inside the permission-grant callback, or after a `checkSelfPermission(...) == PERMISSION_GRANTED` check.
- **Idempotent.** Calling `start` again while running just updates the notification.
- Camera-only or strictly foreground apps don't need it.

## Process death

Extentos holds no implicit cross-process state to restore: an `ExtentosGlasses` instance and its transport connection do not survive the process being killed. After process death and relaunch, you re-run `ExtentosGlasses.create(...)` and reconnect — exactly as on first launch. The dev-loop pairing identity is persisted to `filesDir`, so an `Auto`-resolved dev session can re-bind without re-pairing, but the live glasses connection itself is re-established from scratch.

Because operations return [`ExtentosResult`](/docs/reference/errors) rather than throwing, a connection lost across a lifecycle gap surfaces as a typed failure on the next call — `CaptureError`/`AudioError.NotConnected` from a capability call, or a `ConnectError` (`NoDeviceAvailable` / `TransportFailure`) from `connect()`/`reconnect()` — pattern-match and re-establish rather than guarding with try/catch.
