بعد طلب الأذونات اللازمة والحصول عليها، يمكن لتطبيقك الوصول إلى أجهزة نظارات الذكاء الاصطناعي. للوصول إلى أجهزة النظارات (بدلاً من أجهزة الهاتف)، يجب استخدام سياق معروض.
هناك طريقتان أساسيتان للحصول على سياق متوقّع، وذلك حسب مكان تنفيذ الرمز البرمجي:
الحصول على سياق متوقّع إذا كان الرمز البرمجي يعمل في نشاط نظارات الذكاء الاصطناعي
إذا كان رمز تطبيقك يعمل من داخل نشاط نظارات الذكاء الاصطناعي، سيكون سياق النشاط الخاص به سياقًا معروضًا. في هذا السيناريو، يمكن للمكالمات التي يتم إجراؤها ضمن هذا النشاط الوصول إلى أجهزة النظارات الذكية.
الحصول على سياق متوقع للرمز الذي يتم تشغيله في أحد مكونات تطبيق الهاتف
إذا كان جزء من تطبيقك خارج نطاق نشاط نظارات الذكاء الاصطناعي (مثل نشاط على الهاتف أو خدمة) يحتاج إلى الوصول إلى أجهزة النظارات، يجب أن يحصل صراحةً على سياق معروض. لإجراء ذلك، استخدِم طريقة
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 } }
التحقّق من الصلاحية
بعد إنشاء السياق المتوقّع، راقِب
ProjectedContext.isProjectedDeviceConnected. على الرغم من أنّ هذه الطريقة تعرض
true، يظل السياق المعروض صالحًا للجهاز المتصل، ويمكن للنشاط على التطبيق أو الخدمة (مثل CameraManager) الوصول إلى أجهزة نظارات الذكاء الاصطناعي.
تنظيف البيانات عند قطع الاتصال
يرتبط السياق المعروض بدورة حياة الجهاز المتصل، لذا يتم إتلافه عند قطع اتصال الجهاز. عندما ينقطع اتصال الجهاز، تعرض الدالة ProjectedContext.isProjectedDeviceConnected القيمة false. يجب أن يستجيب تطبيقك لهذا التغيير وأن يوقف أي خدمات نظام (مثل CameraManager) أو موارد أنشأها تطبيقك باستخدام سياق العرض هذا.
إعادة التهيئة عند إعادة الاتصال
عند إعادة توصيل نظارات الذكاء الاصطناعي، يمكن لتطبيقك الحصول على مثيل آخر للسياق المعروض باستخدام createProjectedDeviceContext()، ثم إعادة تهيئة أي خدمات أو مراجع للنظام باستخدام السياق المعروض الجديد.
الوصول إلى الصوت باستخدام البلوتوث
في الوقت الحالي، تتصل نظارات الذكاء الاصطناعي بهاتفك كجهاز صوت عادي يعمل بالبلوتوث. يتوافق الجهاز مع كل من سمّاعة الرأس وملف A2DP (ملف توزيع الصوت المتقدّم). تتيح هذه الطريقة تشغيل أي تطبيق Android متوافق مع إدخال الصوت أو إخراجه على النظارات، حتى إذا لم يتم تصميمه خصيصًا ليتوافق مع النظارات. في بعض الحالات، قد يكون استخدام البلوتوث خيارًا أفضل لحالة استخدام تطبيقك كبديل للوصول إلى أجهزة النظارات باستخدام سياق معروض.
كما هو الحال مع أي جهاز صوتي عادي يتضمّن بلوتوث، يتم التحكّم في إذن منح الإذن RECORD_AUDIO من خلال الهاتف وليس النظارات.
التقاط صورة باستخدام كاميرا النظارات المزودة بالذكاء الاصطناعي
لالتقاط صورة باستخدام كاميرا النظارات بالذكاء الاصطناعي، يجب إعداد حالة استخدام ImageCapture CameraX وربطها بكاميرا النظارات باستخدام السياق الصحيح لتطبيقك:
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)) }
النقاط الرئيسية حول الرمز
- يحصل على مثيل من
ProcessCameraProviderباستخدام سياق الجهاز المتوقّع. - ضمن نطاق السياق المتوقّع، تتطابق الكاميرا الأساسية في النظارات الذكية التي تعمل بالذكاء الاصطناعي والموجّهة إلى الخارج مع
DEFAULT_BACK_CAMERAعند اختيار كاميرا. - يستخدم فحص الربط المُسبَق
cameraProvider.hasCamera(cameraSelector)للتأكّد من أنّ الكاميرا المحدّدة متاحة على الجهاز قبل المتابعة. - يستخدم Camera2 Interop مع
Camera2CameraInfoلقراءةCameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAPالأساسي، وهو ما قد يكون مفيدًا لإجراء عمليات تحقّق متقدّمة من درجات الدقة المتوافقة. - تم إنشاء
ResolutionSelectorمخصّص للتحكّم بدقة في درجة دقة الصورة الناتجة عنImageCapture. - تنشئ هذه الطريقة
ImageCaptureحالة استخدام تم ضبطها باستخدامResolutionSelectorمخصّص. - يربط حالة استخدام
ImageCaptureبدورة حياة النشاط. تتولّى هذه السمة تلقائيًا إدارة فتح الكاميرا وإغلاقها استنادًا إلى حالة النشاط (على سبيل المثال، إيقاف الكاميرا مؤقتًا عند إيقاف النشاط مؤقتًا).
بعد إعداد كاميرا نظارات الذكاء الاصطناعي، يمكنك التقاط صورة باستخدام الفئة ImageCapture في CameraX. راجِع مستندات CameraX للتعرّف على كيفية استخدام takePicture() من أجل التقاط صورة.
تسجيل فيديو باستخدام كاميرا نظارات بالذكاء الاصطناعي
لالتقاط فيديو بدلاً من صورة باستخدام كاميرا نظارات الذكاء الاصطناعي، استبدِل المكوّنات ImageCapture بمكوّنات VideoCapture المقابلة وعدِّل منطق تنفيذ عملية الالتقاط.
تتضمّن التغييرات الرئيسية استخدام حالة استخدام مختلفة، وإنشاء ملف إخراج مختلف، وبدء عملية الالتقاط باستخدام طريقة تسجيل الفيديو المناسبة.
لمزيد من المعلومات حول واجهة برمجة التطبيقات VideoCapture وكيفية استخدامها، يُرجى الاطّلاع على
مستندات التقاط الفيديو في CameraX.
يعرض الجدول التالي درجة الدقة وعدد اللقطات في الثانية المقترَحة استنادًا إلى حالة استخدام تطبيقك:
| حالة الاستخدام | درجة الدقة | عدد اللقطات في الثانية |
|---|---|---|
| التواصل عبر الفيديو | 1280 x 720 | 15 لقطة في الثانية |
| الرؤية الحاسوبية | 640 x 480 | 10 لقطات في الثانية |
| بث الفيديوهات بالذكاء الاصطناعي | 640 x 480 | لقطة واحدة في الثانية |
الوصول إلى أجهزة الهاتف من خلال نشاط على نظارات الذكاء الاصطناعي
يمكن أن يصل نشاط نظارات الذكاء الاصطناعي أيضًا إلى أجهزة الهاتف (مثل الكاميرا أو الميكروفون) باستخدام createHostDeviceContext(context) للحصول على سياق الجهاز المضيف (الهاتف):
@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 } }
عند الوصول إلى أجهزة أو مراجع خاصة بالجهاز المضيف (الهاتف) في تطبيق مختلط (تطبيق يتضمّن تجارب على الأجهزة الجوّالة ونظارات الذكاء الاصطناعي)، عليك اختيار السياق الصحيح بشكل صريح للتأكّد من أنّ تطبيقك يمكنه الوصول إلى الأجهزة الصحيحة:
- استخدِم سياق
Activityمن الهاتفActivityأوProjectedContext.createHostDeviceContext()للحصول على سياق الهاتف. - لا تستخدِم
getApplicationContext()لأنّ سياق التطبيق قد يعرض بشكل غير صحيح سياق نظارات الذكاء الاصطناعي إذا كان نشاط النظارات هو المكوّن الذي تم إطلاقه مؤخرًا.