---
title: HTC VIVE Eagle (preview)
seoTitle: HTC VIVE Eagle — Extentos support status
description: "HTC VIVE Eagle support in Extentos: the Android transport is built and proven end to end against HTC's own first-party simulator, and ships as com.extentos:glasses-htc. No hardware has run it, HTC must register your app before real glasses answer, and iOS is not built yet. Eagle is selectable in the simulator today."
type: reference
platform: all
vendor: htc
related:
  - /docs/vendors
  - /docs/vendors/brilliant
  - /docs/vendors/android-xr
  - /docs/ecosystem/platforms/htc-vive-eagle
  - /docs/concepts/capabilities
  - /docs/getting-started/choose-your-path
---

HTC VIVE Eagle is the fourth vendor Extentos targets, and it is the one where **the vendor ships a simulator**. HTC's `ViveGlassSimulator` implements the very same `ViveGlassClient` interface as the real kit, so the Extentos transport is driven end to end by HTC's own binary with only the substrate simulated. That is a stronger position than a vendor with no hardware to buy and no emulator to stand in for it — and it is still not hardware verification.

This page is the honest status: what runs, what has never run, and the two things HTC controls that no amount of code on our side can resolve.

## TL;DR

- **Built and simulator-proven on Android**: connect, photo, video frames, a muxed MP4 clip, the microphone stream, transcription and speech — 8/8 against HTC's own simulator binary.
- **Publishes as `com.extentos:glasses-htc`** — the module and its publishing config are done, and the artifact goes to Maven Central with the next release cut, alongside the rest of the SDK. It is **our transport code only**: HTC's SDK is not inside it and never will be, because HTC publishes no licence permitting redistribution, so you install theirs from HTC.
- **Never run on hardware.** Eagle was Asia-only until HTC announced US availability from September 2026, so nobody on our side could buy one.
- **HTC must register your app.** There is no self-serve route, and an unregistered app does not error — it silently fails to connect. Extentos turns that silence into a typed `ConnectError.RegistrationRequired`.
- **Both platforms are simulator-proven** — 8/8 against HTC's own simulator on each. iOS ships as a separate `swift-glasses-htc` package so existing `swift-glasses` consumers are untouched, and that isolation is verified: `swift-glasses` still builds with no HTC framework present anywhere.
- **Testable today**: `vive_eagle` is selectable in the simulator, so an app's behaviour under a second camera-and-audio vendor is verifiable now.
- **Meta is unaffected.** A Meta-only app never inherits any of this — HTC's binary must never reach `com.extentos:glasses`.

## Extentos support

The same eleven rows appear on every vendor page, in the same order, so vendors can be
compared directly rather than by reading differently-shaped tables. Depth
specific to this vendor follows below.

| | State | Detail |
|---|---|---|
| **Hardware you can buy** | 🟡 Expanding | Sold in Taiwan, Hong Kong, Singapore and Japan. HTC has announced **US availability from September 2026 at $499**; the UK and EU have no dated purchase path. This is the row that changed — Eagle was unbuyable in the West for the whole time this transport was being written. |
| **Distribution** | 🟡 Gated by HTC | Your app is an ordinary phone app and ships through the App Store and Play on their usual terms — there is no HTC store. But the **glasses half** is gated: HTC must register your app before real glasses will answer it, and the registration route is not documented. This is the same first-party coupling Meta has, without Meta's published process. |
| **Transport** | ✅ Both platforms | `HtcEagleTransport` over the shared Rust core through `HardwareBridge` — `:glasses-htc` on Android, `GlassesHtc` (the `swift-glasses-htc` package) on iOS. The two differ only where HTC's own two SDKs do: iOS collapses Android's two refusal connection-states into a thrown error, delivers media as `CMSampleBuffer`, and returns permissions `async`. |
| **Published** | 🟡 Ships next release | The module and its publish config are done and the POM is verified; `com.extentos:glasses-htc` reaches Maven Central with the next release cut. HTC's AAR is **not** in it and is not redistributed by us. Their coordinates are named in our POM, so a build without their SDK fails at dependency resolution with the coordinate in the error rather than at runtime on first connect. |
| **Verified on hardware** | ⛔ None | Both platforms are proven against HTC's own simulator — 8/8 each, driving their real client interface — which is a genuinely different claim from unverified. It is still not hardware-green, and that rule does not bend for this vendor. |
| **Camera** | ✅ Built | 12 MP stills via `capturePhoto()` (HEIC, reported honestly rather than re-encoded behind your back), live frames via `videoFrames()`, and `captureVideo()`. HTC has **no record-to-file API at all**, so the SDK muxes their live H.264 + AAC stream into an MP4 itself and honours `maxDurationSeconds`; HTC caps a clip at ten minutes regardless of what you ask for. |
| **Display** | ⛔ None, permanently | Eagle has no display and the SDK has no render or overlay surface anywhere in it. `glasses.display.isAvailable` is false and display calls no-op per the degradation policy — the same shape as every Meta model except Ray-Ban Display. |
| **Microphone** | ✅ Built | `audioChunks()`, `transcriptions()` and `recordDiscrete()` from the **four-mic beamforming array** (1 directional + 3 omnidirectional), not the phone's microphone. HTC delivers it AAC-encoded and Extentos decodes to i16 PCM at 16 kHz, so what reaches your handler is the shape every other vendor emits. Transcription is **final-only** — HTC's API has no partial result, so interim UI has nothing to render here. |
| **Speaker** | 🟡 Built, two limits | Open-ear stereo speakers via HTC's `speakText(text, locale)`, which is the **entire** outbound audio surface of their SDK. There is no raw audio-out API, so the assistant's streamed PCM rides the OS's Bluetooth route through `SystemAudioBridge` — the same substrate Ray-Ban audio uses. And there is **no cancel**: `cancelSpeak` is a no-op on this vendor, so barge-in cannot stop an utterance mid-sentence. |
| **Simulator** | ✅ `vive_eagle` | Selectable in the browser simulator with its real capability set — camera, microphone, speaker, no display. |
| **Integration** | 🟡 Manual, both platforms | Not scaffolded, and could not be: the steps that matter are HTC's to grant. Android adds a Gradle module; iOS adds a second SwiftPM package and one `register()` call. See [Adding it](#adding-it). |

### Beyond the spine

Detail with no counterpart on other vendors, kept separate so the table above stays comparable.

| Thing | State | What it means |
|---|---|---|
| HTC's own simulator | ✅ The reason this vendor was picked | `ViveGlassSimulator` implements the same `ViveGlassClient` interface as the real kit, so the transport is written once and the substrate is a constructor argument. It is what turned "we cannot buy one" into "we can prove the whole path anyway". |
| Licence | ⛔ None published | HTC publishes no licence or EULA — not on the download page, and not inside either archive. Commercial terms are simply unstated. This is why their binary is never redistributed by us, and why you fetch it yourself. |
| App registration | ⛔ Off-document | No self-serve form. How it is keyed — package id, signing certificate or publisher — is undocumented: HTC's iOS `AppInfo` carries `teamId`, `bundleId`, a certificate common name and a sha256, while the Android handshake sends no explicit app identity at all. |
| VIVE Connect | ⚠️ Hard runtime dependency | It owns pairing, the auth handshake and the user's language setting, exactly as the Meta AI app does for Ray-Bans. Not optional infrastructure. |
| Encoded media | ✅ Handled in the bridge | HTC hands us AAC audio and H.264 video where every other transport hands us decoded data. Extentos decodes both, so your handler sees the same PCM and the same frames it sees everywhere else. |
| Device identity | 🟡 Static | Battery level, wear state and the connected model sit below HTC's public API and are unreachable from it. `glasses.device.type` reports `vive_eagle` statically rather than resolving it from the glasses. |
| Physical inputs | ⛔ One of four | The SDK exposes only the AI button. Touchpad, capture button and voice control are reserved to HTC's own assistant. |
| Simulator artifact in release builds | ⚠️ Known wart | `com.extentos:glasses-htc` names HTC's simulator as a runtime dependency, so it resolves into release builds too, even though HTC's simulator refuses to run outside a debuggable build. Splitting it out is deliberate future work, not a blocker for a preview vendor. |

## What Eagle breaks that Meta does not

Three assumptions a Meta-shaped app makes quietly.

**Failure is silent, not loud.** An app HTC has not registered does not throw and does not crash — the connection simply never completes. This is the single most likely thing you will hit, and it is why the transport turns `ERROR_UNREGISTER_APP` into a typed `ConnectError.RegistrationRequired` rather than letting it read as a timeout.

**Barge-in does not work.** `cancelSpeak` is the primitive an assistant uses to stop talking when the wearer starts. HTC exposes no way to stop an utterance, so on Eagle it is a no-op. If your voice loop depends on interrupting playback, it degrades here — design the turn-taking so that waiting out a long utterance is not the only escape.

**Two privacy behaviours are enforced in hardware, with no API and no reason code.** The camera auto-disables when the glasses are not worn or the capture LED is covered, and connecting throws `GlassesNotWornException` if they are not on the wearer. Neither is something your app can detect in advance or work around; both are states to handle, not bugs to fix.

## Adding it

Neither platform is scaffolded by `generateConnectionModule`, and that is deliberate: the steps that decide whether this works at all are HTC's to grant, not ours to generate.

### Android

Three steps.

**1. Install HTC's SDK into your `mavenLocal`.** HTC ships it as a `.7z` containing a file-based Maven repository, from [their download page](https://developer.vive.com/resources/vive-ai-glasses-sdk/) — free, no sign-in, no approval. Extract it and install `com.htc.viveglass.sdk:viveglass_client` and `:viveglass_simulator` into `~/.m2/repository`. There is no remote repository to point Gradle at, and we cannot mirror one for you.

**2. Let Gradle see it, scoped to HTC's group alone** — in `settings.gradle.kts`:

```kotlin
dependencyResolutionManagement {
    repositories {
        mavenLocal {
            content { includeGroup("com.htc.viveglass.sdk") }
        }
        google()
        mavenCentral()
    }
}
```

**3. Add the module.**

```kotlin
dependencies {
    implementation("com.extentos:glasses-htc:2.7.0")
}
```

<Callout type="warn">
  This coordinate **ships next release** — it is not on Maven Central yet. Until
  it lands, build `:glasses-htc` from the repo as a local module. Everything
  else on this page is accurate today.
</Callout>

It self-registers through `androidx.startup`, so adding the module *is* the integration. `TransportChoice.Auto` resolves to it once Eagle is the connected device, and your handler code does not change — the same `glasses.camera.capturePhoto()` and `glasses.audio.transcriptions()` you write for Meta.

<Callout type="warn">
  Then get HTC to register your app. Until they do, everything above builds and
  runs and the glasses never answer, silently. There is no self-serve form; HTC
  grants it on request.
</Callout>

### iOS

Two steps, plus the same HTC registration.

**1. Install HTC's SDK.** Same archive, different half — run `scripts/install-viveglass-sdk-ios.sh` from the `swift-glasses-htc` package, which fetches HTC's `.7z` and stages `ViveGlassKit.xcframework` and `ViveGlassSimulator.xcframework` into `Artifacts/`. HTC nests `.7z` inside `.7z` on iOS, so you need a 7-Zip tool (`brew install sevenzip`).

**2. Add the package and register it.**

```swift
// Package.swift
.package(url: "https://github.com/extentos/swift-glasses-htc", from: "2.7.0"),
```

```swift
// in your App's init, before Extentos.create(...)
import GlassesHtc

ExtentosHtc.register()
```

Android's module self-registers through `androidx.startup`, so adding it *is* the integration there. iOS has no equivalent — nothing runs a library's code before the app's — so registration is one explicit call. Handler code is identical to Meta's on both platforms.

<Callout type="warn">
  `swift-glasses-htc` is a **second package**, not a product of `swift-glasses`.
  SwiftPM validates every binary target when it loads a manifest, so declaring
  HTC's frameworks inside the main package would break `swift build` for every
  existing consumer the moment they resolved without those frameworks staged.
  This split is what keeps your build unaffected if you never touch Eagle. It
  is not published yet — it ships alongside the next release cut.
</Callout>

## Why the module is separate

Meta's transport lives in `com.extentos:glasses-meta` because Meta's artifacts sit behind a credentialed repository. HTC's lives in `com.extentos:glasses-htc` for a sharper reason: **their binary has no stated licence**, so it must never become something a Meta customer inherits by depending on `com.extentos:glasses`. A voice-only app, or a Meta app, pulls none of it and needs nothing from HTC.

The same boundary is why the artifact we publish contains our code and not theirs.
