Une fois que vous avez demandé et obtenu les autorisations nécessaires, votre application peut accéder au matériel des lunettes IA. Pour accéder au matériel des lunettes (au lieu du matériel du téléphone), vous devez utiliser un contexte projeté.
Il existe deux façons principales d'obtenir un contexte projeté, selon l'endroit où votre code s'exécute :
Obtenir un contexte projeté si votre code s'exécute dans une activité de lunettes IA
Si le code de votre application s'exécute à partir de l'activité de vos lunettes IA, son propre contexte d'activité est déjà un contexte projeté. Dans ce cas, les appels effectués dans cette activité peuvent déjà accéder au matériel des lunettes.
Obtenir un contexte projeté pour le code s'exécutant dans un composant d'application pour téléphone
Si une partie de votre application en dehors de l'activité de vos lunettes IA (comme une activité ou un service téléphonique) doit accéder au matériel des lunettes, elle doit obtenir explicitement un contexte projeté. Pour ce faire, utilisez la
createProjectedDeviceContext() méthode :
@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 } }
Vérifier la validité
Encapsulez l'appel createProjectedDeviceContext dans le
ProjectedContext.isProjectedDeviceConnected. Tant que cette méthode renvoie true, le contexte projeté reste valide pour l'appareil connecté, et l'activité ou le service de votre application pour téléphone (comme un CameraManager) peut accéder au matériel des lunettes IA.
Nettoyer en cas de déconnexion
Le contexte projeté est lié au cycle de vie de l'appareil connecté. Il est donc détruit lorsque l'appareil se déconnecte. Lorsque l'appareil se déconnecte,
ProjectedContext.isProjectedDeviceConnected renvoie false. Votre application doit écouter ce changement et nettoyer tous les services système (comme un CameraManager) ou les ressources que votre application a créées à l'aide de ce contexte projeté.
Réinitialiser en cas de reconnexion
Lorsque l'appareil de lunettes IA se reconnecte, votre application peut obtenir une autre instance de contexte projeté
à l'aide de createProjectedDeviceContext(), puis
réinitialiser tous les services ou ressources système à l'aide du nouveau contexte projeté.
Accéder à l'audio via Bluetooth
Actuellement, les lunettes IA se connectent à votre téléphone en tant qu'appareil audio Bluetooth standard. Les profils de casque et A2DP (Advanced Audio Distribution Profile) sont compatibles. Cette approche permet à n'importe quelle application Android compatible avec l'entrée ou la sortie audio de fonctionner sur des lunettes, même si elles n'ont pas été conçues spécifiquement pour les prendre en charge. Dans certains cas, l'utilisation du Bluetooth peut être plus adaptée au cas d'utilisation de votre application que l'accès au matériel des lunettes à l'aide d'un contexte projeté.
Comme pour tout appareil audio Bluetooth standard, l'autorisation d'accorder la
RECORD_AUDIO permission est contrôlée par le téléphone et non par les lunettes.
Capturer une image avec l'appareil photo des lunettes IA
Pour capturer une image avec l'appareil photo des lunettes IA, configurez et liez le cas d'utilisation de CameraX
ImageCapture à l'appareil photo des lunettes à l'aide du contexte approprié
pour votre application :
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)) }
Points clés concernant le code
- Obtient une instance de
ProcessCameraProviderà l'aide du contexte de l'appareil projeté. - Dans le champ d'application du contexte projeté, l'appareil photo principal des lunettes IA, orienté vers l'extérieur, correspond à
DEFAULT_BACK_CAMERAlors de la sélection d'un appareil photo. - Une vérification de pré-liaison utilise
cameraProvider.hasCamera(cameraSelector)pour vérifier que l'appareil photo sélectionné est disponible sur l'appareil avant de continuer. - Utilise Camera2 Interop avec
Camera2CameraInfopour lire leCameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAPsous-jacent, ce qui peut être utile pour les vérifications avancées des résolutions compatibles. - Un
ResolutionSelectorpersonnalisé est conçu pour contrôler précisément la résolution de l'image de sortie pourImageCapture. - Crée un cas d'utilisation
ImageCaptureconfiguré avec unResolutionSelectorpersonnalisé. - Lie le cas d'utilisation
ImageCaptureau cycle de vie de l'activité. Cela gère automatiquement l'ouverture et la fermeture de l'appareil photo en fonction de l'état de l'activité (par exemple, en arrêtant l'appareil photo lorsque l'activité est mise en pause).
Une fois l'appareil photo des lunettes IA configuré, vous pouvez capturer une image avec la classe ImageCapture de CameraX. Pour savoir comment capturer une image, consultez la documentation de CameraX pour en savoir
plus sur l'utilisation de takePicture().
Capturer une vidéo avec l'appareil photo des lunettes IA
Pour capturer une vidéo au lieu d'une image avec l'appareil photo des lunettes IA, remplacez les
ImageCapture composants par les composants VideoCapture correspondants
et modifiez la logique d'exécution de la capture.
Les principales modifications impliquent l'utilisation d'un cas d'utilisation différent, la création d'un fichier de sortie différent et le lancement de la capture à l'aide de la méthode d'enregistrement vidéo appropriée.
Pour en savoir plus sur l'API VideoCapture et son utilisation, consultez la
documentation sur la capture vidéo de CameraX.
Le tableau suivant indique la résolution et la fréquence d'images recommandées en fonction du cas d'utilisation de votre application :
| Cas d'utilisation | Résolution | Fréquence d'images |
|---|---|---|
| Communication vidéo | 1280 x 720 | 15 FPS |
| Vision par ordinateur | 640 x 480 | 10 FPS |
| Streaming vidéo IA | 640 x 480 | 1 FPS |
Accéder au matériel d'un téléphone à partir d'une activité de lunettes IA
Une activité de lunettes IA peut également accéder au matériel du téléphone (comme l'appareil photo
ou le micro) en utilisant createHostDeviceContext(context) pour obtenir le contexte de l'appareil hôte (téléphone) :
@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 } }
Lorsque vous accédez à du matériel ou à des ressources spécifiques à l'appareil hôte (téléphone) dans une application hybride (une application contenant à la fois des expériences mobiles et des expériences de lunettes IA), vous devez sélectionner explicitement le contexte approprié pour vous assurer que votre application peut accéder au matériel approprié :
- Utilisez le
Activitycontexte du téléphoneActivityou leProjectedContext.createHostDeviceContext()pour obtenir le contexte du téléphone. - N'utilisez pas
getApplicationContext(), car le contexte de l'application peut renvoyer de manière incorrecte le contexte des lunettes IA si une activité de lunettes était le composant lancé le plus récemment.