Integrate Wearables Device Access Toolkit into your iOS app
Updated: May 14, 2026
Overview
This guide explains how to add Wearables Device Access Toolkit registration, streaming, and photo capture to an existing iOS app. For a complete working sample, compare with the provided sample app.
Prerequisites
Complete the environment and glasses steps in Setup.
Your integration must use a registered bundle identifier. To register or manage bundle IDs, see Apple’s Register an App ID and Bundle IDs documentation.
App Store Submission Warning: Publishing to the App Store is not currently supported, but we plan to do so in the future. In the meantime, you can share your integration with test users via our release channels. As a result, since the SDK currently uses the ExternalAccessory framework, it will lead to App Store rejection due to Apple’s MFi program and privacy manifest requirements.
Step 1: Add info properties
In your app’s Info.plist, or using Xcode UI, provide the Wearables Device Access Toolkit with the required keys (AppLinkURLScheme, MetaAppID, ClientToken, TeamID). AppLinkURLScheme enables the Meta AI app to callback to your app during registration. The example below uses myexampleapp as a placeholder, but the real one should be a universal link registered with Apple. Adjust the scheme to match your project.
These same identifiers are needed for attestation of your app, which ensures its authenticity. While app attestation is not used in Developer Mode, if you use incorrect identifiers or your app is misconfigured, it won’t connect, and you will receive an error.
Note: If you pre-process Info.plist, the :// suffix will be stripped unless you add the -traditional-cpp flag. See Apple Technical Note TN2175.
<!-- Configure custom URL scheme for Meta AI callbacks -->
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleURLSchemes</key>
<array>
<string>myexampleapp</string>
</array>
</dict>
</array>
<!-- Wearables Device Access Toolkit Configuration -->
<key>MWDAT</key>
<dict>
<!-- Tell DAT your URL scheme so it can be called back from Meta AI -->
<key>AppLinkURLScheme</key>
<string>myexampleapp://</string>
<!-- Unless using Developer Mode, set this key using the ID from the app registered in Wearables Developer Center -->
<key>MetaAppID</key>
<string>$(META_APP_ID)</string>
<!-- As with Meta App ID, set this key using the ClientToken in Wearables Developer Center -->
<key>ClientToken</key>
<string>$(CLIENT_TOKEN)</string>
<!-- Your Apple Developer Team ID - Set this in Xcode under Signing & Capabilities -->
<key>TeamID</key>
<string>$(DEVELOPMENT_TEAM)</string>
<!-- Enable the Device Access Toolkit App Model (DAM) -->
<key>DAMEnabled</key>
<true/>
</dict>
<!-- External Accessory protocol for Meta Wearables -->
<key>UISupportedExternalAccessoryProtocols</key>
<array>
<string>com.meta.ar.wearable</string>
</array>
<!-- Background modes for Bluetooth and external accessories -->
<key>UIBackgroundModes</key>
<array>
<string>bluetooth-peripheral</string>
<string>external-accessory</string>
</array>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Needed to connect to Meta Wearables</string>
<key>NSCameraUsageDescription</key>
<string>This app needs camera access to stream from your phone's camera as a mock device feed.</string>
Note: Both the Device Access Toolkit App Model (DAM) flow and older flow are supported for camera functionality on Meta AI glasses.
Step 2: Add the SDK Swift package
Add the SDK through Swift Package Manager.
In Xcode, select File > Add Package Dependencies...
Search for https://github.com/facebook/meta-wearables-dat-ios in the top right corner.
let wearables = Wearables.shared
Task {
for await state in wearables.registrationStateStream() {
// Update your registration UI or model
}
}
Task {
for await devices in wearables.devicesStream() {
// Update the list of available glasses
}
}
Important: A device will not appear in the devicesStream until the user has granted at least one permission (for example, camera) through the Meta AI app. If your devicesStream is empty after registration, ensure you are calling wearables.requestPermission(.camera), as shown in Step 5 below.
Step 5: Manage camera permissions
Check permission status before streaming and request access if necessary.
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 manually select a specific device.
let deviceSelector = AutoDeviceSelector(wearables: wearables)
let session = try wearables.createSession(deviceSelector: deviceSelector)
let stateStream = session.stateStream()
try session.start()
for await state in stateStream {
if state == .started {
...
} else if state == .stopped {
...
}
}
Step 7: Start a camera stream
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. resolution can be set to:
high: 720 x 1280 pixels
medium: 504 x 896 pixels
low: 360 x 640 pixels
StreamState transitions through stopping, stopped, waitingForDevice, starting, streaming, and paused.
Register callbacks to collect frames and state events.
let config = StreamConfiguration(
videoCodec: VideoCodec.raw,
resolution: StreamingResolution.low,
frameRate: 24)
guard let stream = try? session.addStream(config: config) else { return }
let stateToken = stream.statePublisher.listen { state in
Task { @MainActor in
// Update your streaming UI state
}
}
let frameToken = stream.videoFramePublisher.listen { frame in
guard let image = frame.makeUIImage() else { return }
Task { @MainActor in
// Render the frame in your preview surface
}
}
Task { await stream.start() }
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.
_ = stream.photoDataPublisher.listen { photoData in
let data = photoData.data
// Convert to UIImage or hand off to your storage layer
}
stream.capturePhoto(format: .jpeg)