Integrate Wearables Device Access Toolkit into your Android app
Updated: Oct 8, 2026
Overview
This guide explains how to add Wearables Device Access Toolkit registration, streaming, and photo capture to an existing Android app. For a complete working sample, compare with the provided sample app.
Build with AI
Install the Device Access Toolkit plugin for Android first. It gives your AI coding tool the Android setup, implementation, and Mock Device Kit testing guidance from the Android GitHub repo, and connects the Wearables MCP server for search_dat_docs:
# Claude Code
claude plugin marketplace add facebook/meta-wearables-dat-android
claude plugin install mwdat-android@mwdat-android-marketplace
# Codex
codex plugin marketplace add facebook/meta-wearables-dat-android
codex plugin add mwdat-android@mwdat-android-marketplace
Then copy this prompt into your AI coding tool to build a first Android integration slice from this guide:
>_Build minimal Android integration from guide
Use https://wearables.developer.meta.com/docs/develop/dat/build-integration-android/, then use the Wearables MCP endpoint https://mcp.developer.meta.com/wearables to call search_dat_docs for current Android Wearables Device Access Toolkit setup, registration, permissions, session lifecycle, MockDeviceKit, and camera guidance. If the Device Access Toolkit Android plugin is not installed, install it from https://github.com/facebook/meta-wearables-dat-android (see https://wearables.developer.meta.com/docs/develop/dat/getting-started-toolkit/#set-up-ai-coding-tools) and use its skills. If search_dat_docs is unavailable, help me configure the Wearables MCP server from https://wearables.developer.meta.com/docs/develop/dat/ai-assisted-mcp/ before editing code. Inspect my Android app first, then add the smallest working Device Access Toolkit integration slice: manifest permissions and metadata, Gradle dependencies, SDK initialization, app registration launch, and connection lifecycle wiring. Call out application ID, client token, callback scheme, Developer Mode assumptions, and local verification steps before making larger changes.
Prerequisites
Complete the environment and glasses configuration steps in Setup.
Step 1: Add manifest entries
In your app’s AndroidManifest.xml, add the permissions required to allow your app to communicate with the glasses through Bluetooth. The intent filter with the URI scheme is required so that the Meta AI app can call back to your application. The example below uses myexampleapp as a placeholder. Adjust the scheme to match your project.
Provide the Wearables Device Access Toolkit with APPLICATION_ID and CLIENT_TOKEN metadata. Both are needed for attestation of your app, which ensures its authenticity, and they can be found in the Wearables Developer Center (see Manage projects).
While an App Signature is not required for attestation, the Meta AI app will use it to verify the authenticity of your app. If incorrect identifiers are used or your app is misconfigured, it won’t connect, and you will receive an error.
Note: App attestation is not used in Developer Mode, since these apps rely on local logic, rather than connecting to a release channel. If you are using Developer Mode, you can omit these values or simply use 0.
<manifest ...>
<!-- Runtime permissions used by Device Access Toolkit -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- Required if you want to use your phone's camera as a mock device feed -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<application ...>
<!-- Meta Wearables Device Access Toolkit Setup -->
<!-- Without Developer Mode, these values need to be set with credentials from the app registered in Wearables Developer Center -->
<meta-data
android:name="com.meta.wearable.mwdat.APPLICATION_ID"
android:value="${mwdat_application_id}"
/>
<meta-data
android:name="com.meta.wearable.mwdat.CLIENT_TOKEN"
android:value="${mwdat_client_token}"
/>
<!-- Callback scheme Meta AI uses to return to your app -->
<activity android:name=".MainActivity" ...>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myexampleapp" />
</intent-filter>
</activity>
</application>
</manifest>
Step 2: Add the SDK to Gradle
The Wearables Device Access Toolkit is distributed through Maven Central.
Declare the Wearables Device Access Toolkit artifacts in libs.versions.toml, setting mwdat to one of the available versions. Every artifact shares the same version reference.
[versions]
mwdat = "<latest version>"
[libraries]
mwdat-core = { group = "com.meta.wearable", name = "mwdat-core", version.ref = "mwdat" }
mwdat-camera = { group = "com.meta.wearable", name = "mwdat-camera", version.ref = "mwdat" }
mwdat-display = { group = "com.meta.wearable", name = "mwdat-display", version.ref = "mwdat" }
mwdat-mockdevice = { group = "com.meta.wearable", name = "mwdat-mockdevice", version.ref = "mwdat" }
Then, add them as dependencies in your app’s build.gradle.kts.
Before streaming, check the Wearables camera permission and launch the SDK contract if required.
var permissionStatus = Wearables.checkPermissionStatus(Permission.CAMERA)
if (permissionStatus == PermissionStatus.Granted) {
// start streaming
}
permissionStatus = requestWearablesPermission(Permission.CAMERA)
...
private var permissionContinuation: CancellableContinuation<PermissionStatus>? = null
private val permissionMutex = Mutex()
// Requesting wearable device permissions via the Meta AI app
private val permissionsResultLauncher =
registerForActivityResult(Wearables.RequestPermissionContract()) { result ->
permissionContinuation?.resume(result)
permissionContinuation = null
}
// Convenience method to make a permission request in a sequential manner
// Uses a Mutex to ensure requests are processed one at a time, preventing race conditions
suspend fun requestWearablesPermission(permission: Permission): PermissionStatus {
return permissionMutex.withLock {
suspendCancellableCoroutine { continuation ->
permissionContinuation = continuation
continuation.invokeOnCancellation { permissionContinuation = null }
permissionsResultLauncher.launch(permission)
}
}
}
Step 6: Create device session
Use createSession to create a device session and access the capabilities of a Meta Wearable Device. You can also add a stream to a previously created session.
You can use AutoDeviceSelector to make a smart decision for the user to select a device. Alternatively, you can use SpecificDeviceSelector if you provide a UI for the user to select a device.
Create a stream by adding it to an existing DeviceSession, and observe its state and display frames.
You can request resolution and frame rate control using StreamConfiguration. Valid frameRate values are 2, 7, 15, 24, or 30 FPS. videoQuality can be set to:
HIGH: 720 x 1280 pixels
MEDIUM: 504 x 896 pixels
LOW: 360 x 640 pixels
StreamState transitions through STARTING, STARTED, STREAMING, PAUSED, STOPPING, STOPPED, and CLOSED.
Register callbacks to collect frames and state events.
fun start(deviceId: DeviceIdentifier) {
val config = StreamConfiguration(videoQuality = VideoQuality.MEDIUM, frameRate = 24)
session.addCamera(config).fold(
onSuccess = { camera ->
val stream = camera.stream
scope.launch {
stream.videoStream.collect { frame ->
displayFrame(frame)
}
}
scope.launch {
stream.state.collect { state ->
updateStreamUi(state)
if (state == StreamState.STOPPED) {
stopStream()
}
}
}
stream.start()
},
onFailure = { error, _ ->
showError(error.description)
},
)
}
Resolution and frame rate are constrained by the Bluetooth Classic connection between the user’s phone and their AI glasses. To manage limited bandwidth, an automatic ladder reduces quality as needed. It first lowers the resolution by one step (for example, from HIGH to MEDIUM). If bandwidth remains constrained, it then reduces the frame rate (for example, 30 to 24), but never below 15 fps.
The image delivered to your app may appear lower quality than expected, even when the resolution reports HIGH or MEDIUM. This is due to per‑frame compression that adapts to available Bluetooth Classic bandwidth. Requesting a lower resolution, a lower frame rate, or both can yield higher visual quality with less compression loss.
Step 8: Capture and share photos
When a stream session is active, call capturePhoto and handle the returned PhotoData. Add app/src/main/res/xml/file_paths.xml so that the FileProvider can expose cached images.
stream.capturePhoto()
.onSuccess { data ->
...
}
.onFailure(onError)