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 z 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():
@OptIn(ExperimentalProjectedApi::class) private fun getGlassesContext(context: Context): Context? { return try { // From a phone Activity or Service, get a context for the AI glasses. ProjectedContext.createProjectedDeviceContext(context) } catch (e: IllegalStateException) { Log.e(TAG, "Failed to create projected device context", e) null } }
Sprawdź ważność
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ść w aplikacji na telefonie lub usługa (np. CameraManager) może uzyskać dostęp do sprzętu okularów z AI.
Zwalnianie miejsca po odłączeniu
Przewidywany kontekst jest powiązany z cyklem życia połączonego urządzenia, więc jest usuwany po rozłączeniu urządzenia. Gdy urządzenie zostanie odłączone, ProjectedContext.isProjectedDeviceConnected zwróci wartość false. Aplikacja powinna nasłuchiwać tej zmiany i zwalniać miejsce zajmowane przez wszystkie usługi systemowe (np. CameraManager) lub zasoby, które utworzyła 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 z 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 z AI, skonfiguruj i powiąż przypadek użycia ImageCapture CameraX z aparatem okularów, używając kontekstu odpowiedniego dla aplikacji:
private fun startCameraOnGlasses(activity: ComponentActivity) { // 1. Get the CameraProvider using the projected context. // When using the projected context, DEFAULT_BACK_CAMERA maps to the AI glasses' camera. val projectedContext = try { ProjectedContext.createProjectedDeviceContext(activity) } catch (e: IllegalStateException) { Log.e(TAG, "AI Glasses context could not be created", e) return } val cameraProviderFuture = ProcessCameraProvider.getInstance(projectedContext) cameraProviderFuture.addListener({ val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get() val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA // 2. Check for the presence of a camera. if (!cameraProvider.hasCamera(cameraSelector)) { Log.w(TAG, "The selected camera is not available.") return@addListener } // 3. Query supported streaming resolutions using Camera2 Interop. val cameraInfo = cameraProvider.getCameraInfo(cameraSelector) val camera2CameraInfo = Camera2CameraInfo.from(cameraInfo) val cameraCharacteristics = camera2CameraInfo.getCameraCharacteristic( CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP ) // 4. 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() // 5. 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, 60) val captureRequestOptions = CaptureRequestOptions.Builder() .setCaptureRequestOption(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRange) .build() // 6. Initialize the ImageCapture use case with options. val imageCapture = ImageCapture.Builder() // Optional: Configure resolution, format, etc. .setResolutionSelector(resolutionSelector) .build() try { // Unbind use cases before rebinding. cameraProvider.unbindAll() // Bind use cases to camera using the Activity as the LifecycleOwner. cameraProvider.bindToLifecycle( activity, cameraSelector, imageCapture ) } catch (exc: Exception) { Log.e(TAG, "Use case binding failed", exc) } }, ContextCompat.getMainExecutor(activity)) }
Najważniejsze informacje o kodzie
- Pobiera instancję
ProcessCameraProviderza pomocą prognozowanego kontekstu urządzenia. - W zakresie prognozowanego kontekstu główny aparat okularów z AI skierowany na zewnątrz jest mapowany na
DEFAULT_BACK_CAMERApodczas 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 Interop z
Camera2CameraInfodo odczytywania podstawowejCameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP, co może być przydatne w przypadku zaawansowanych kontroli obsługiwanych rozdzielczości. - Niestandardowy
ResolutionSelectorzostał opracowany z myślą o precyzyjnym kontrolowaniu rozdzielczości obrazu wyjściowego w przypadkuImageCapture. - Tworzy przypadek użycia
ImageCaptureskonfigurowany za pomocą niestandardowegoResolutionSelector. - Wiąże przypadek użycia
ImageCapturez 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 z 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 filmów wygenerowanych przez AI | 640 x 480 | 1 kl./s |
Dostęp do sprzętu telefonu z poziomu aktywności na okularach z 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):
@OptIn(ExperimentalProjectedApi::class) private fun getPhoneContext(activity: ComponentActivity): Context? { return try { // From an AI glasses Activity, get a context for the phone. ProjectedContext.createHostDeviceContext(activity) } catch (e: IllegalStateException) { Log.e(TAG, "Failed to create host device context", e) null } }
Gdy w aplikacji hybrydowej (zawierającej zarówno funkcje mobilne, jak i funkcje na okulary z AI) uzyskujesz dostęp do sprzętu 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 sprzętu:
- Aby uzyskać kontekst telefonu, użyj kontekstu
ActivityzActivitytelefonu lubProjectedContext.createHostDeviceContext(). - Nie używaj
getApplicationContext(), ponieważ kontekst aplikacji może nieprawidłowo zwrócić kontekst okularów z AI, jeśli aktywność okularów była ostatnio uruchomionym komponentem.