Install the Android SDK
Add the Extentos Android SDK to your Gradle project from Maven Central. Coordinates, minSdk 31, Kotlin/AGP/Gradle floors, and the assistant runtime.
The Extentos Android SDK ships five artifacts on Maven Central. Most apps need the first two:
com.extentos:glasses— the core runtime (ExtentosGlasses, capability clients, transports)com.extentos:glasses-ui— the prebuilt connection page (ExtentosConnectionPage). Optional on a voice-only app, which renders no connection page.com.extentos:glasses-meta— optional; the Meta Ray-Ban transport (camera, display, the DAT device session). Only apps that use camera or display need it.com.extentos:glasses-local— optional; on-device text models for the local tier.com.extentos:glasses-local-voice— optional; on-device speech for the local tier.
The Extentos artifacts resolve from the default mavenCentral() repository. com.extentos:glasses and glasses-ui have no vendor dependency, so a voice-only app needs nothing beyond a normal Gradle dependency — no extra repository, no token.
The Meta DAT dependencies (com.meta.wearable:mwdat-*) come in through com.extentos:glasses-meta only. They live on Meta's GitHub Packages, which needs one extra repo declaration plus a GitHub token (step 1). Skip that step entirely if your app doesn't use camera or display.
1. Declare the repositories
Voice-only apps can skip this whole step. Extentos resolves from Maven Central, which is already in the default Android template.
If you add com.extentos:glasses-meta for camera or display, its Meta DAT artifacts resolve from Meta's GitHub Packages, which requires a GitHub personal access token with the read:packages scope. Add both to your settings.gradle.kts:
// pluginManagement MUST be the first block in a settings script — Gradle
// aborts configuration otherwise. Without it, `id("com.android.application")`
// can't resolve: AGP lives on google(), and Gradle's default plugin repo is
// gradlePluginPortal() only.
pluginManagement {
repositories { google(); mavenCentral(); gradlePluginPortal() }
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
// Transitive Meta DAT artifacts (com.meta.wearable:mwdat-*) live here:
maven {
url = uri("https://maven.pkg.github.com/facebook/meta-wearables-dat-android")
credentials {
username = "token"
password = (providers.gradleProperty("github_token").orNull
?: System.getenv("GITHUB_TOKEN")) ?: ""
}
}
}
}…followed by your module declarations:
rootProject.name = "myapp"
include(":app")FAIL_ON_PROJECT_REPOS means a repositories { } block in app/build.gradle.kts becomes a hard build failure — declare every repository here instead.
Create the token at github.com → Settings → Developer settings → Personal access tokens with the read:packages scope, then export it as GITHUB_TOKEN. That is the one location every surface agrees on — the block above reads it, the scaffold's variant reads it, and extentos-mcp setup checks it. (~/.gradle/gradle.properties as github_token=... also satisfies the block above, but the scaffold's variant and the diagnostic don't look there, so you can end up with a working build and a diagnostic that reports it missing — or the reverse.) To check your setup, run npx -p @extentos/mcp-server extentos-mcp setup from the project root — a read-only diagnostic that validates the token against GitHub Packages and prints exact remediation; it reads GITHUB_TOKEN or the project's local.properties and does not store the token for you. (generateConnectionModule emits a variant of this repo block that reads local.properties/env instead of the Gradle property — same URL, same key names.) Without the token the build fails at first sync with Could not resolve com.meta.wearable:mwdat-core.
2. Add the dependency
dependencies {
implementation("com.extentos:glasses:2.1.2")
implementation("com.extentos:glasses-ui:2.1.2")
// ONLY if your app uses the camera or the display. This is what brings the
// Meta DAT artifacts (and therefore the repository + token in step 1).
// Voice-only apps omit it entirely.
implementation("com.extentos:glasses-meta:2.1.2")
}You don't declare the Meta DAT SDK (com.meta.wearable) yourself — it comes in transitively through com.extentos:glasses-meta, and only through that module. It resolves from the GitHub Packages repo added in step 1, so the read:packages token must be in place for a camera/display build to succeed. A voice-only app never pulls those artifacts and needs no token.
glasses-meta registers itself at app start, so adding the dependency is the whole integration — TransportChoice.Auto resolves to real glasses with no extra code.
3. Set the build floors
The library is built against these versions. Match or exceed them.
| Requirement | Value | Why |
|---|---|---|
minSdk | 31 (Android 12) | Meta DAT mandates it. The Bluetooth runtime-permission model the SDK uses is Android 12+. |
compileSdk | 35 | Transitive deps require it. |
| Kotlin | 2.1.20 | The AAR is compiled with 2.1.20; older Kotlin emits Class file was compiled with a newer version metadata warnings. |
| Android Gradle Plugin | 8.6.0+ | Compose deps in glasses-ui declare an AGP 8.6 floor. |
| Gradle | 8.7+ | Required by AGP 8.6. |
| Java/Kotlin target | 17 | The library targets JVM 17. |
The library does not declare a targetSdk — your app's targetSdk is inherited as-is. targetSdk 34 or 35 both work for most apps. (getPermissions reports 34 as the value it derived its permission advice against; that's the floor it reasoned from, not a requirement on you.)
You also need two build features that a fresh AGP 8 project leaves off by default:
plugins {
id("com.android.application") version "8.6.0"
id("org.jetbrains.kotlin.android") version "2.1.20"
// Required if you use ExtentosConnectionPage or any Compose UI. From Kotlin
// 2.0 the Compose compiler is a separate plugin — same version as Kotlin.
id("org.jetbrains.kotlin.plugin.compose") version "2.1.20"
}
android {
// AGP 8 removed the manifest-package fallback: without a namespace the build
// fails with "Namespace not specified."
namespace = "com.example.myapp"
compileSdk = 35
defaultConfig {
minSdk = 31
// targetSdk = 35 // your choice; the library doesn't impose one
}
buildFeatures {
// AGP 8 defaults this to false. The SDK's own initialization snippet
// reads BuildConfig.DEBUG, and the MCP scaffold emits buildConfigField
// entries (EXTENTOS_SESSION_URL), so this must be on.
buildConfig = true
compose = true // only if you use Compose / ExtentosConnectionPage
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions { jvmTarget = "17" }
}buildConfig = true is not optional. Every canonical initialization
snippet branches on BuildConfig.DEBUG to pick the environment, and the
browser-simulator loop reads BuildConfig.EXTENTOS_SESSION_URL. On AGP 8 with
the feature off, BuildConfig does not exist and those lines don't resolve.
The project key (production gateway attribution)
If your app uses the assistant, add your account-bound project key as a buildConfigField so production gateway usage attributes to your Extentos account:
android {
defaultConfig {
buildConfigField("String", "EXTENTOS_PROJECT_KEY", "\"pk_your_project_key\"")
}
}The SDK reads it reflectively and sends it as the x-extentos-project-key header. (Meta's App ID and Client Token go through resValue / R.string instead, not buildConfigField — those rotate, and BuildConfig string constants are compile-time-inlined so a stale one can survive a rotation. The project key is regenerated by re-running the scaffold, which rewrites this line, so the same hazard doesn't apply.) generateConnectionModule mints the key and emits this exact line for you (it appears in the response's buildConfigFields[]); if you are wiring the project by hand, get the key from your dashboard project. In the simulator it is unused — attribution there comes from the session token. On a sideloaded development build on a real phone it is load-bearing: such a build can't attest (Play Integrity doesn't recognise it), so the key is how the gateway identifies the caller. Without it, and without a simulator-session binding, assistant.start(...) fails with AssistantError.NoApiKey. It never causes a build error, so the only symptom is at runtime — see gateway identity. Don't commit it to a public repo; re-run generateConnectionModule to rotate.
Some dependencies are yours, not the SDK's. glasses-ui brings the Compose runtime it needs, not the ones your UI code uses:
// The SDK's suspend surface needs a dispatcher from your side
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0")
// Only if you follow the docs' Compose idiom (collectAsStateWithLifecycle)
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.8.6")
// Your own Compose stack, if you have UI of your own
implementation(platform("androidx.compose:compose-bom:2024.09.03")) // any recent BOM works — declare only one
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.material3:material3")
implementation("androidx.activity:activity-compose:1.9.2")If you started from the Android Studio template, its root build.gradle.kts already declares these plugins with apply false and a version. Declaring a version in both places fails with "plugin request must not include a version" — keep one. Either drop the version from the block above, or delete the root declarations. A libs.versions.toml catalog works too; the SDK doesn't care which you pick.
4. Sync and verify
Run a Gradle sync (or ./gradlew :app:dependencies) and confirm com.extentos:glasses resolves. Next, wire it up:
- Manifest setup — add
CAMERA/RECORD_AUDIO/INTERNET - Initialization —
ExtentosGlasses.create(...)
The assistant runtime
The end-to-end voice assistant (glasses.assistant.* — wake/sleep state machine, barge-in, session.say(...)) ships in the stable 1.4.0 release on Maven Central — the standard dependency above includes it. No snapshot, no extra repository, no special setup. See the assistant page for the API surface and the voice-assistant guide for an end-to-end build.
Source
- Artifact:
com.extentos:glasseson Maven Central
Related
Android manifest setup
Which permissions the Extentos Android SDK auto-merges for you and which capability permissions (CAMERA, RECORD_AUDIO, INTERNET) your app must declare, plus the bundled foreground service.
Initialize the Android SDK
Create ExtentosGlasses with ExtentosGlasses.create, configure ExtentosConfig (environment, applicationContext, transport), reach the sub-clients, and pattern-match ExtentosResult.
Android quickstart
Add the Extentos Android SDK by hand — Gradle install, manifest permissions, and your first capability call. Voice apps need no vendor token.
Android runtime internals
How the Extentos Android SDK is a thin Kotlin shell over a shared Rust core (uniffi + jniLibs), the four transports and how TransportChoice.Auto resolves, and the Meta DAT bridge.
Android SDK
Add Extentos to your Android app via Gradle. Smart-glasses capabilities for Meta Ray-Ban, Android 12+ (API 31), Kotlin, coroutines.
Android manifest setup
Which permissions the Extentos Android SDK auto-merges for you and which capability permissions (CAMERA, RECORD_AUDIO, INTERNET) your app must declare, plus the bundled foreground service.