sample-app-guide

Creación de una aplicación DAT completa con transmisión de cámara y captura de fotos

npx skills add https://github.com/facebook/meta-wearables-dat-ios --skill sample-app-guide

Sample App Guide (iOS)

Build an iOS DAT app with camera streaming and photo capture.

This walkthrough covers app setup, registration, streaming, and capture. Pair it with the CameraAccess sample.

Project setup

  1. Create a new Xcode project (SwiftUI App)
  2. Add the SDK via SPM: https://github.com/facebook/meta-wearables-dat-ios
  3. Add MWDATCore, MWDATCamera, and MWDATMockDevice to your target
  4. Configure Info.plist (see Getting Started)

App architecture

A typical DAT app has these components:

MyDATApp/
├── MyDATApp.swift              # App entry point, SDK init
├── ViewModels/
│   ├── WearablesViewModel.swift    # Registration, device management
│   └── StreamViewModel.swift # Streaming, photo capture
└── Views/
    ├── MainAppView.swift           # Navigation
    ├── RegistrationView.swift      # Registration UI
    └── StreamView.swift            # Video preview, capture button

SDK initialization

import MWDATCore

@main
struct MyDATApp: App {
    init() {
        do {
            try Wearables.configure()
        } catch {
            assertionFailure("Wearables SDK configuration failed: \(error)")
        }
    }

    var body: some Scene {
        WindowGroup {
            MainAppView()
                .onOpenURL { url in
                    guard
                        let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
                        components.queryItems?.contains(where: { $0.name == "metaWearablesAction" }) == true
                    else {
                        return
                    }
                    Task {
                        _ = try? await Wearables.shared.handleUrl(url)
                    }
                }
        }
    }
}

Wearables ViewModel

devicesStream() yields [DeviceIdentifier] (a [String]), not device objects. Resolve each identifier with wearables.deviceForIdentifier(_:) when you need nameOrId(), deviceType(), linkState, or compatibility().

import MWDATCore

@MainActor
class WearablesViewModel: ObservableObject {
    @Published var registrationState: RegistrationState
    @Published var devices: [DeviceIdentifier] = []

    private let wearables = Wearables.shared

    init() {
        registrationState = Wearables.shared.registrationState
    }

    func observeState() {
        Task {
            for await state in wearables.registrationStateStream() {
                self.registrationState = state
            }
        }
        Task {
            for await deviceIds in wearables.devicesStream() {
                self.devices = deviceIds
            }
        }
    }

    func register() async {
        try? await wearables.startRegistration()
    }

    func unregister() async {
        try? await wearables.startUnregistration()
    }
}

Stream ViewModel

import MWDATCamera
import MWDATCore

@MainActor
class StreamViewModel: ObservableObject {
    @Published var currentFrame: UIImage?
    @Published var streamState: String = "Stopped"
    @Published var capturedPhoto: Data?

    private let wearables = Wearables.shared
    private var deviceSession: DeviceSession?
    private var camera: Camera?
    private var stream: Stream?

    func startStream() async {
        let config = StreamConfiguration(
            videoCodec: .raw,
            resolution: .medium,
            frameRate: 24
        )
        let selector = AutoDeviceSelector(wearables: wearables)

        do {
            let deviceSession = try wearables.createSession(deviceSelector: selector)
            try deviceSession.start()
            // Wait for the device session to reach the started state
            for await state in deviceSession.stateStream() {
                if state == .started { break }
            }
            guard let camera = try deviceSession.addCamera(config: config) else { return }
            self.deviceSession = deviceSession
            self.camera = camera
            self.stream = camera.stream
        } catch {
            return
        }

        guard let stream else { return }

        _ = stream.statePublisher.listen { [weak self] state in
            Task { @MainActor in
                self?.streamState = "\(state)"
            }
        }

        _ = stream.videoFramePublisher.listen { [weak self] frame in
            guard let image = frame.makeUIImage() else { return }
            Task { @MainActor in
                self?.currentFrame = image
            }
        }

        _ = stream.photoDataPublisher.listen { [weak self] photoData in
            Task { @MainActor in
                self?.capturedPhoto = photoData.data
            }
        }

        stream.start()
    }

    func stopStream() {
        // Stopping the camera cascades to its stream child
        camera?.stop()
        deviceSession?.stop()
        stream = nil
        camera = nil
        deviceSession = nil
    }

    func capturePhoto() {
        stream?.capturePhoto(format: .jpeg)
    }
}

Behaviors the CameraAccess sample also covers

  • Two explicit steps. "Start Session" creates and starts the DeviceSession; "Preview" adds the Camera and starts the stream. Stopping the preview leaves the session connected so the user can start it again without re-creating the session.
  • Bind the UI to the SDK's own states. Mirror DeviceSessionState and StreamState instead of maintaining a parallel state machine, and show a busy indicator while starting, waitingForDevice, or stopping.
  • Background handling. On UIApplication.didEnterBackgroundNotification, end the session. Suppress the teardown errors that the SDK emits during that intentional stop so the user does not see a false failure on return.
  • Update prompts. Watch device.compatibility() with device.addCompatibilityListener; on .deviceUpdateRequired, offer Wearables.shared.openFirmwareUpdate(). When session start reports DeviceSessionError.datAppOnTheGlassesUpdateRequired, offer Wearables.shared.openDATGlassesAppUpdate().
  • Single error surface. Present error.localizedDescription from session.errorPublisher and stream.errorPublisher in one alert rather than an app-maintained error map.

Testing with MockDeviceKit

Add mock device support to develop without glasses:

import MWDATMockDevice

func setupMockDevice() async {
    let mockDeviceKit = MockDeviceKit.shared
    mockDeviceKit.enable()

    guard let device = try? mockDeviceKit.pairGlasses(model: .rayBanMeta) else { return }
    device.powerOn()
    device.unfold()
    device.don()

    if let videoURL = Bundle.main.url(forResource: "test_video", withExtension: "mp4") {
        let camera = device.services.camera
        camera.setCameraFeed(fileURL: videoURL)
    }
}

func tearDownMockDevice() {
    MockDeviceKit.shared.disable()
}

Allowed dependencies

Your DAT app should only depend on:

  • MWDATCore — always required
  • MWDATCamera — for camera streaming
  • MWDATMockDevice — for testing (can be test-only dependency)
  • MWDATDisplay — for Display experiences

Links

Más skills de facebook

gc-safe-coding
facebook
Para la explicación completa y el fundamento, consulta doc/GCSafeCoding.md.
app-review-prep
facebook
Prepara una app de Meta para App Review: comprueba el estado actual, los requisitos pendientes, los privilegios concedidos y el historial de envíos. Úsalo antes de enviar una app…
api-health
facebook
Monitorea la salud de la API para una app de Meta: verifica límites de tasa, volumen de llamadas y deprecaciones de API. Úsalo para diagnosticar limitaciones, planificar capacidad o prepararse para versiones de API…
debug-webhooks
facebook
Soluciona problemas de webhooks para una aplicación de Meta — inspecciona las suscripciones activas, identifica configuraciones incorrectas y envía cargas de prueba para verificar la entrega. Usa cuando…
api-integration
facebook
Guía a un desarrollador para configurar una integración de la API de Meta desde cero: descubre las APIs adecuadas, obtiene guías de configuración, requisitos de autenticación,…
webhook-setup
facebook
Configura webhooks para una app de Meta de principio a fin: descubre los temas disponibles, suscríbete a campos y verifica con una carga de prueba. Úsalo al configurar webhooks para…
test-ui
facebook
Prueba el sistema de UI (PanelUI, ScreenSpace) contra el ejemplo de poke usando la CLI de iwsdk.
flags
facebook
We need to translate the given text from English to Spanish. The text describes a skill for inspecting and comparing feature flag states across React release channels. We must preserve product names, protocol names, URLs, numbers, and technical terms. The name "flags" is not in the text, so we don't include it. We translate only the text inside <text>. No extra commentary, labels, etc. The text: "Inspect and compare feature flag states across React release channels. View all flags across channels (www, www-modern, canary, next, experimental, rn variants) or compare specific channels with --diff Output formats include default table view, CSV export, and cleanup status grouping Flag states indicated by symbols: enabled (✅), disabled (❌), variant testing (🧪), profiling-only (📊) Common pitfall: __VARIANT__ flags are tested in both states on www; use --diff to spot meaningful..." We need to translate to Spanish. Keep technical terms like "React", "www", "www-modern", "canary",