Używanie prognozowanego kontekstu do uzyskiwania dostępu do sprzętu okularów AI

Odpowiednie urządzenia XR
Te wskazówki pomogą Ci tworzyć treści na te urządzenia XR.
Okulary AI

Gdy poprosisz o niezbędne uprawnienia i je uzyskasz, Twoja aplikacja będzie mieć dostęp do sprzętu okularów z AI. Kluczem do uzyskania dostępu do hardware okularów (zamiast hardware telefonu) jest użycie prognozowanego kontekstu.

Istnieją 2 podstawowe sposoby uzyskiwania prognozowanego kontekstu, w zależności od tego, gdzie jest wykonywany kod:

Jak uzyskać prognozowany kontekst, jeśli kod jest uruchamiany w aktywności związanej z okularami AI

Jeśli kod aplikacji jest uruchamiany w ramach aktywności okularów z AI, własny kontekst aktywności jest już prognozowanym kontekstem. W takim przypadku połączenia wykonywane w ramach tej aktywności mogą już korzystać z hardware okularów.

Jak uzyskać prognozowany kontekst, jeśli kod jest uruchamiany w komponencie aplikacji na telefon

Jeśli część aplikacji poza aktywnością związaną z okularami z AI (np. aktywność na telefonie lub usługa) musi mieć dostęp do hardware okularów, musi wyraźnie uzyskać prognozowany kontekst. Aby to zrobić, użyj metody createProjectedDeviceContext():

// From a phone Activity, get a context for the AI glasses
try {
    val glassesContext = ProjectedContext.createProjectedDeviceContext(this)
    // Now use glassesContext to access glasses' system services
} catch (e: IllegalStateException) {
    // Projected device was not found
}

Sprawdzanie ważności

Po utworzeniu prognozowanego kontekstu monitoruj ProjectedContext.isProjectedDeviceConnected. Chociaż ta metoda zwraca wartość true, prognozowany kontekst pozostaje ważny dla połączonego urządzenia, a aktywność lub usługa aplikacji na telefonie (np. CameraManager) może uzyskać dostęp do sprzętu okularów AI.

Czyszczenie po odłączeniu

Prognozowany kontekst jest powiązany z cyklem życia połączonego urządzenia, więc jest niszczony, gdy urządzenie zostanie odłączone. Gdy urządzenie zostanie odłączone, funkcja ProjectedContext.isProjectedDeviceConnected zwróci wartość false. Aplikacja powinna nasłuchiwać tej zmiany i czyścić wszystkie usługi systemowe (np. CameraManager) lub zasoby utworzone przez aplikację przy użyciu tego kontekstu.

Ponowna inicjalizacja po ponownym połączeniu

Gdy urządzenie z okularami AI ponownie się połączy, aplikacja może uzyskać kolejną instancję kontekstu projecji za pomocą createProjectedDeviceContext(), a następnie ponownie zainicjować dowolne usługi systemowe lub zasoby przy użyciu nowego kontekstu projecji.

Dostęp do dźwięku przez Bluetooth

Obecnie okulary AI łączą się z telefonem jako standardowe urządzenie audio Bluetooth. Obsługiwane są zarówno profile zestawu słuchawkowego, jak i A2DP (Advanced Audio Distribution Profile). Dzięki temu każda aplikacja na Androida, która obsługuje wejście lub wyjście audio, może działać na okularach, nawet jeśli nie została specjalnie zaprojektowana do ich obsługi. W niektórych przypadkach używanie Bluetootha może być lepszym rozwiązaniem dla Twojej aplikacji niż uzyskiwanie dostępu do hardware okularów za pomocą prognozowanego kontekstu.

Podobnie jak w przypadku każdego standardowego urządzenia audio Bluetooth, uprawnienie do przyznania uprawnienia RECORD_AUDIO jest kontrolowane przez telefon, a nie przez okulary.

Robienie zdjęć aparatem okularów z AI

Aby zrobić zdjęcie aparatem okularów AI, skonfiguruj i powiąż przypadek użycia ImageCapture CameraX z aparatem okularów, używając kontekstu odpowiedniego dla aplikacji:

private fun startCamera() {
    // Get the CameraProvider using the projected context.

    val cameraProviderFuture = ProcessCameraProvider.getInstance(
        ProjectedContext.createProjectedDeviceContext(this)
    )

    cameraProviderFuture.addListener({
        // Used to bind the lifecycle of cameras to the lifecycle owner
        val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()

        // Select the camera. When using the projected context, DEFAULT_BACK_CAMERA maps to the AI glasses' camera.
        val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
    
        // Check for the presence of a camera before initializing the ImageCapture use case.
       if (!cameraProvider.hasCamera(cameraSelector)) {
            Log.w(TAG, "The selected camera is not available.")
            return@addListener
        }

        // Get supported streaming resolutions.
        val cameraInfo = cameraProvider.getCameraInfo(cameraSelector)
        val camera2CameraInfo = Camera2CameraInfo.from(cameraInfo)
        val cameraCharacteristics = camera2CameraInfo.getCameraCharacteristic(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)

        // Define the resolution strategy.
        val targetResolution = Size(1920, 1080)
        val resolutionStrategy = ResolutionStrategy(
            targetResolution,
            ResolutionStrategy.FALLBACK_RULE_CLOSEST_LOWER)

        val resolutionSelector = ResolutionSelector.Builder()
            .setResolutionStrategy(resolutionStrategy)
            .build()

        // If you have other continuous use cases bound, such as Preview or ImageAnalysis, you can use  Camera2 Interop's CaptureRequestOptions to set the FPS
        val fpsRange = Range(30, 30)
        val captureRequestOptions = CaptureRequestOptions.Builder()
                .setCaptureRequestOption(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE,fpsRange)
                .build()

        // Initialize the ImageCapture use case.
        val imageCapture = ImageCapture.Builder()
            // Optional: Configure resolution, format, etc.
            .setResolutionSelector(resolutionSelector)
            .build()

        try {
            // Unbind use cases before rebinding
            cameraProvider.unbindAll()

            // 4. Bind use cases to camera
            cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, imageCapture)

        } catch(exc: Exception) {
            // This catches exceptions like IllegalStateException if use case binding fails
            Log.e(TAG, "Use case binding failed", exc)
        }

    }, ContextCompat.getMainExecutor(this))
}

Najważniejsze informacje o kodzie

  • Pobiera instancję ProcessCameraProvider za pomocą prognozowanego kontekstu urządzenia.
  • W zakresie prognozowanego kontekstu główny aparat okularów AI skierowany na zewnątrz jest mapowany na DEFAULT_BACK_CAMERA podczas wybierania aparatu.
  • Sprawdzanie przed powiązaniem wykorzystuje cameraProvider.hasCamera(cameraSelector), aby zanim przejdziesz dalej, było wiadomo, czy wybrany aparat jest dostępny na urządzeniu.
  • Używa Camera2 InteropCamera2CameraInfo do odczytywania podstawowej CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP, co może być przydatne w przypadku zaawansowanych kontroli obsługiwanych rozdzielczości.
  • Niestandardowy ResolutionSelector został opracowany, aby precyzyjnie kontrolować rozdzielczość obrazu wyjściowego w przypadku ImageCapture.
  • Tworzy przypadek użycia ImageCapture skonfigurowany za pomocą niestandardowego ResolutionSelector.
  • Wiąże przypadek użycia ImageCapture z cyklem życia aktywności. Ta funkcja automatycznie zarządza otwieraniem i zamykaniem aparatu na podstawie stanu aktywności (np. zatrzymuje aparat, gdy aktywność jest wstrzymana).

Po skonfigurowaniu aparatu w okularach z AI możesz zrobić zdjęcie za pomocą klasy ImageCapture CameraX. Więcej informacji o używaniu takePicture() do robienia zdjęć znajdziesz w dokumentacji CameraX.

Nagrywanie filmów aparatem okularów AI

Aby nagrać film zamiast zrobić zdjęcie za pomocą aparatu w okularach z AI, zastąp komponenty ImageCapture odpowiednimi komponentami VideoCapture i zmodyfikuj logikę wykonywania przechwytywania.

Główne zmiany polegają na zastosowaniu innego przypadku użycia, utworzeniu innego pliku wyjściowego i rozpoczęciu przechwytywania za pomocą odpowiedniej metody nagrywania wideo. Więcej informacji o interfejsie VideoCapture API i sposobie jego używania znajdziesz w dokumentacji CameraX dotyczącej nagrywania filmów.

W tabeli poniżej znajdziesz zalecaną rozdzielczość i liczbę klatek w zależności od zastosowania aplikacji:

Przypadek użycia Rozdzielczość Liczba klatek
Komunikacja wideo 1280 x 720 15 kl./s
Rozpoznawanie obrazów 640 x 480 10 kl./s
Strumieniowe przesyłanie wideo z wykorzystaniem AI 640 x 480 1 kl./s

Dostęp do hardware telefonu z poziomu aktywności na okularach AI

Aktywność na okularach z AI może też uzyskać dostęp do hardware telefonu (np. aparatu lub mikrofonu) za pomocą createHostDeviceContext(context), aby zdobyć kontekst urządzenia hosta (telefonu):

// From an AI glasses Activity, get a context for the phone
val phoneContext = ProjectedContext.createHostDeviceContext(this)
// Now use phoneContext to access the phone's hardware

Gdy w aplikacji hybrydowej (zawierającej zarówno funkcje mobilne, jak i funkcje na okulary AI) uzyskujesz dostęp do hardware lub zasobów, które są specyficzne dla urządzenia hosta (telefonu), musisz wyraźnie wybrać odpowiedni kontekst, aby aplikacja mogła mieć dostęp do właściwego hardware: