אחרי שמבקשים ומקבלים את ההרשאות הנדרשות, האפליקציה יכולה לגשת לחומרה של משקפי ה-AI. כדי לגשת לחומרה של המשקפיים (במקום לחומרה של הטלפון), צריך להשתמש בהקשר מוקרן.
יש שתי דרכים עיקריות לקבל הקשר משוער, בהתאם למקום שבו הקוד מופעל:
קבלת הקשר משוער אם הקוד פועל בפעילות של משקפי AI
אם הקוד של האפליקציה פועל מתוך הפעילות במשקפי ה-AI, הקשר של הפעילות שלה כבר מתוכנן. בתרחיש הזה, לשיחות שמתבצעות במסגרת הפעילות הזו כבר יש גישה לחומרה של המשקפיים.
קבלת הקשר המוקרן אם הקוד פועל ברכיב של אפליקציית טלפון
אם חלק מהאפליקציה שלכם מחוץ לפעילות המשקפיים מבוססת-AI (כמו פעילות בטלפון או שירות) צריך לגשת לחומרה של המשקפיים, הוא צריך לקבל הקשר מוקרן באופן מפורש. כדי לעשות את זה, משתמשים בשיטה 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
}
בדיקת התוקף
אחרי שיוצרים את ההקשר המשוער, עוקבים אחרי ProjectedContext.isProjectedDeviceConnected. למרות שהשיטה הזו מחזירה את הערך true, ההקשר המוקרן נשאר תקף למכשיר המחובר, והפעילות או השירות באפליקציית הטלפון (כמו CameraManager) יכולים לגשת לחומרה של משקפי ה-AI.
ניקוי לאחר ניתוק
ההקשר המוקרן קשור למחזור החיים של המכשיר המחובר, ולכן הוא נמחק כשהמכשיר מתנתק. כשהמכשיר מתנתק,
ProjectedContext.isProjectedDeviceConnected מחזיר false. האפליקציה שלכם צריכה להאזין לשינוי הזה ולנקות את כל שירותי המערכת (כמו CameraManager) או המשאבים שהאפליקציה יצרה באמצעות ההקשר המוקרן הזה.
הפעלה מחדש של האתחול בחיבור מחדש
כשמכשיר משקפי ה-AI מתחבר מחדש, האפליקציה יכולה לקבל עוד מופע של הקשר המוקרן באמצעות createProjectedDeviceContext(), ואז לאתחל מחדש את כל שירותי המערכת או המשאבים באמצעות ההקשר המוקרן החדש.
גישה לאודיו באמצעות Bluetooth
בשלב הזה, משקפי AI מתחברים לטלפון כמכשיר שמע Bluetooth רגיל. יש תמיכה גם באוזניות וגם בפרופיל A2DP (פרופיל מתקדם להפצת אודיו). הגישה הזו מאפשרת לכל אפליקציית Android שתומכת בקלט או בפלט אודיו לפעול במשקפיים, גם אם היא לא פותחה במיוחד כדי לתמוך במשקפיים. במקרים מסוימים, שימוש ב-Bluetooth עשוי להתאים יותר לתרחיש השימוש באפליקציה שלכם כחלופה לגישה לחומרה של המשקפיים באמצעות הקשר מוקרן.
כמו בכל מכשיר אודיו רגיל עם Bluetooth, ההרשאה להעניק את ההרשאה RECORD_AUDIO נשלטת על ידי הטלפון ולא על ידי המשקפיים.
צילום תמונה באמצעות המצלמה של משקפי ה-AI
כדי לצלם תמונה באמצעות המצלמה של משקפי ה-AI, צריך להגדיר ולקשור את תרחיש השימוש של CameraX ImageCapture למצלמה של המשקפיים באמצעות ההקשר הנכון לאפליקציה:
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))
}
מידע חשוב על הקוד
- מקבלים מופע של
ProcessCameraProviderבאמצעות הקשר המכשיר המוקרן. - במסגרת ההקשר המוקרן, המצלמה הראשית של משקפי ה-AI, שמכוונת החוצה, ממופה ל-
DEFAULT_BACK_CAMERAכשבוחרים מצלמה. - בדיקה לפני קישור משתמשת ב-
cameraProvider.hasCamera(cameraSelector)כדי לוודא שהמצלמה שנבחרה זמינה במכשיר לפני שממשיכים. - הוא משתמש ב-Camera2 Interop עם
Camera2CameraInfoכדי לקרוא אתCameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAPהבסיסי, שיכול להיות שימושי לבדיקות מתקדמות של רזולוציות נתמכות. ResolutionSelectorבהתאמה אישית נוצר כדי לשלוט בדיוק ברזולוציית התמונה של הפלט ב-ImageCapture.- יוצרת
ImageCaptureתרחיש שימוש שמוגדר עםResolutionSelectorמותאם אישית. - קושר את תרחיש השימוש
ImageCaptureלמחזור החיים של הפעילות. הוא מנהל אוטומטית את הפתיחה והסגירה של המצלמה בהתאם למצב הפעילות (לדוגמה, עצירת המצלמה כשהפעילות מושהית).
אחרי שמגדירים את המצלמה של משקפי ה-AI, אפשר לצלם תמונה באמצעות המחלקה ImageCapture של CameraX. במאמרי העזרה של CameraX מוסבר איך משתמשים ב-takePicture() כדי לצלם תמונה.
צילום סרטון באמצעות המצלמה של משקפי ה-AI
כדי לצלם סרטון במקום תמונה באמצעות המצלמה של משקפי ה-AI, מחליפים את הרכיבים ImageCapture ברכיבים התואמים VideoCapture ומשנים את הלוגיקה של ביצוע הצילום.
השינויים העיקריים כוללים שימוש בתרחיש שימוש אחר, יצירת קובץ פלט אחר והתחלת הצילום באמצעות שיטת הקלטת הווידאו המתאימה.
מידע נוסף על VideoCapture API ועל אופן השימוש בו זמין במאמרי העזרה בנושא צילום וידאו ב-CameraX.
בטבלה הבאה מוצגים הרזולוציה וקצב הפריימים המומלצים בהתאם לתרחיש השימוש באפליקציה:
| תרחיש לדוגמה | רזולוציה | קצב פריימים |
|---|---|---|
| תקשורת בווידאו | 1280 x 720 | 15 פריימים לשנייה (FPS) |
| ראייה ממוחשבת | 640 x 480 | 10 פריימים לשנייה (FPS) |
| סטרימינג של סרטוני AI | 640 x 480 | 1 FPS |
גישה לחומרה של הטלפון מפעילות במשקפי AI
פעילות במשקפיים עם AI יכולה גם לגשת לחומרה של הטלפון (כמו המצלמה או המיקרופון) באמצעות createHostDeviceContext(context) כדי לקבל את ההקשר של מכשיר המארח (הטלפון):
// 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
כשניגשים לחומרה או למשאבים שספציפיים למכשיר המארח (הטלפון) באפליקציה היברידית (אפליקציה שמכילה גם חוויות בנייד וגם במשקפי AI), צריך לבחור במפורש את ההקשר הנכון כדי לוודא שהאפליקציה יכולה לגשת לחומרה הנכונה:
- משתמשים בהקשר
ActivityמהטלפוןActivityאו ב-ProjectedContext.createHostDeviceContext()כדי לקבל את ההקשר של הטלפון. - אל תשתמשו ב-
getApplicationContext()כי הקשר האפליקטיבי יכול להחזיר באופן שגוי את ההקשר של משקפי ה-AI אם פעילות המשקפיים הייתה הרכיב שהופעל לאחרונה.