Dopo aver richiesto e ottenuto le autorizzazioni necessarie, la tua app può accedere all'hardware degli occhiali con AI. La chiave per accedere all'hardware degli occhiali (anziché a quello dello smartphone) è utilizzare un contesto proiettato.
Esistono due modi principali per ottenere un contesto proiettato, a seconda di dove viene eseguito il codice:
Ottieni un contesto proiettato se il tuo codice viene eseguito in un'attività di occhiali AI
Se il codice della tua app viene eseguito dall'attività degli occhiali AI, il suo contesto di attività è già un contesto proiettato. In questo scenario, le chiamate effettuate all'interno di questa attività possono già accedere all'hardware degli occhiali.
Ottenere un contesto proiettato se il codice viene eseguito nel componente dell'app Telefono
Se una parte della tua app al di fuori dell'attività degli occhiali AI (ad esempio un'attività
di smartphone o un servizio) deve accedere all'hardware degli occhiali, deve ottenere
esplicitamente un contesto proiettato. Per farlo, utilizza il
metodo 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
}
Controllare la validità
Dopo aver creato il contesto proiettato, monitora
ProjectedContext.isProjectedDeviceConnected. Anche se questo metodo restituisce
true, il contesto proiettato rimane valido per il dispositivo connesso e l'attività o il servizio dell'app per smartphone (ad esempio un CameraManager) può accedere all'hardware degli occhiali AI.
Pulizia alla disconnessione
Il contesto proiettato è legato al ciclo di vita del dispositivo connesso, quindi viene
eliminato quando il dispositivo si disconnette. Quando il dispositivo si disconnette,
ProjectedContext.isProjectedDeviceConnected restituisce false. La tua app
deve rilevare questa modifica ed eliminare eventuali servizi di sistema (ad esempio un
CameraManager) o risorse che ha creato utilizzando il contesto
proiettato.
Reinizializza alla riconnessione
Quando il dispositivo AI Glasses si riconnette, la tua app può ottenere un'altra istanza di contesto proiettata utilizzando createProjectedDeviceContext() e poi reinizializzare qualsiasi servizio o risorsa di sistema utilizzando il nuovo contesto proiettato.
Accedere all'audio tramite Bluetooth
Al momento, gli occhiali AI si connettono allo smartphone come un dispositivo audio Bluetooth standard. Sono supportati sia il profilo del visore sia il profilo A2DP (Advanced Audio Distribution Profile). Con questo approccio, qualsiasi app per Android che supporta l'input o l'output audio funziona sugli occhiali, anche se non sono stati appositamente progettati per supportarli. In alcuni casi, l'utilizzo del Bluetooth potrebbe funzionare meglio per lo scenario di utilizzo della tua app come alternativa all'accesso all'hardware degli occhiali utilizzando un contesto proiettato.
Come per qualsiasi dispositivo audio Bluetooth standard, l'autorizzazione per concedere l'autorizzazione
RECORD_AUDIO è controllata dallo smartphone e non dagli occhiali.
Acquisire un'immagine con la fotocamera degli occhiali con l'AI
Per acquisire un'immagine con la fotocamera degli occhiali AI, configura e associa lo scenario d'uso
ImageCapture di CameraX alla fotocamera degli occhiali utilizzando il contesto
corretto per la tua app:
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))
}
Punti chiave sul codice
- Ottiene un'istanza di
ProcessCameraProviderutilizzando il contesto del dispositivo proiettato. - Nell'ambito del contesto proiettato, la fotocamera principale degli occhiali AI, rivolta verso l'esterno, corrisponde a
DEFAULT_BACK_CAMERAquando selezioni una fotocamera. - Un controllo pre-binding utilizza
cameraProvider.hasCamera(cameraSelector)per verificare che la videocamera selezionata sia disponibile sul dispositivo prima di procedere. - Utilizza Camera2 Interop con
Camera2CameraInfoper leggere l'CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAPsottostante, che può essere utile per controlli avanzati sulle risoluzioni supportate. - Un
ResolutionSelectorpersonalizzato è creato per controllare con precisione la risoluzione dell'immagine di output perImageCapture. - Crea un caso d'uso
ImageCaptureconfigurato con unResolutionSelectorpersonalizzato. - Collega il caso d'uso
ImageCaptureal ciclo di vita dell'attività. In questo modo la videocamera si apre e si chiude automaticamente in base allo stato dell'attività (ad esempio, la videocamera si ferma quando l'attività è in pausa).
Dopo aver configurato la fotocamera degli occhiali con AI, puoi acquisire un'immagine con la classe ImageCapture di CameraX. Consulta la documentazione di CameraX per scoprire come utilizzare takePicture() per acquisire un'immagine.
Acquisire un video con la fotocamera degli occhiali con AI
Per acquisire un video anziché un'immagine con la fotocamera degli occhiali AI, sostituisci i
componenti ImageCapture con i componenti VideoCapture corrispondenti
e modifica la logica di esecuzione dell'acquisizione.
Le modifiche principali riguardano l'utilizzo di un caso d'uso diverso, la creazione di un file di output diverso e l'avvio dell'acquisizione utilizzando il metodo di registrazione video appropriato.
Per saperne di più sull'API VideoCapture e su come utilizzarla, consulta la
documentazione relativa all'acquisizione video di CameraX.
La tabella seguente mostra la risoluzione e la frequenza fotogrammi consigliate a seconda del caso d'uso della tua app:
| Caso d'uso | Risoluzione | Frequenza fotogrammi |
|---|---|---|
| Videochiamata | 1280 x 720 | 15 FPS |
| Computer Vision | 640 x 480 | 10 FPS |
| Streaming video AI | 640 x 480 | 1 FPS |
Accedere all'hardware di uno smartphone da un'attività degli occhiali AI
Un'attività degli occhiali con AI può accedere anche all'hardware dello smartphone (come la fotocamera
o il microfono) utilizzando createHostDeviceContext(context) per ottenere il contesto
del dispositivo host (smartphone):
// 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
Quando accedi a hardware o risorse specifici del dispositivo host (smartphone) in un'app ibrida (un'app che contiene esperienze sia per dispositivi mobili che per occhiali AI), devi selezionare esplicitamente il contesto corretto per assicurarti che la tua app possa accedere all'hardware corretto:
- Utilizza il contesto
Activitydello smartphoneActivityoProjectedContext.createHostDeviceContext()per ottenere il contesto dello smartphone. - Non utilizzare
getApplicationContext()perché il contesto dell'applicazione può restituire in modo errato il contesto degli occhiali con AI se un'attività degli occhiali è stato il componente avviato più di recente.