أخبار المنتجات

ما وراء الميزات الفردية: ضمان توافق مجموعات الميزات مع CameraX 1.5

قراءة لمدة 6 دقائق
Tahsin Masrur
Software Engineer

تتميّز تطبيقات الكاميرا الحديثة بميزات قوية ومتداخلة. يتوقّع المستخدمون تسجيل فيديو بنطاق عالي الديناميكية مذهل، والتقاط حركة سلسة بسرعة 60 لقطة في الثانية، والحصول على لقطات سلسة للغاية باستخدام ميزة "تثبيت المعاينة"، وغالبًا ما يحدث كل ذلك في الوقت نفسه.

بصفتنا مطوّرين، ندرك أنّ الواقع أكثر تعقيدًا. كيف يمكنك ضمان أنّ جهازًا معيّنًا يتوافق فعلاً مع مجموعة معيّنة؟ حتى الآن، كان تفعيل ميزات متعددة غالبًا ما يكون أمرًا محفوفًا بالمخاطر. يمكنك التحقّق من توافق كل ميزة على حدة، ولكن قد يؤدي الجمع بينها إلى سلوك غير محدّد أو، الأسوأ من ذلك، إلى فشل جلسة الكاميرا.  ويجبر هذا الغموض المطوّرين على توخّي الحذر، ما يمنع المستخدمين على الأجهزة المتوافقة من الحصول على أفضل تجربة ممكنة.

على سبيل المثال، لا تتوافق سوى أجهزة قليلة جدًا من الفئة الممتازة مع فيديوهات HDR و60 لقطة في الثانية في الوقت نفسه. نتيجةً لذلك، تتجنّب معظم التطبيقات تفعيل كليهما في الوقت نفسه لتجنُّب تقديم تجربة سيئة للمستخدم على معظم الهواتف.

لمعالجة هذه المشكلة، نقدّم مجموعة الميزات في CameraX، وهي واجهة برمجة تطبيقات جديدة مصمَّمة لإزالة هذه التخمينات. يمكنك الآن الاستعلام عمّا إذا كانت مجموعة معيّنة من الميزات متوافقة قبل ضبط الكاميرا، أو يمكنك ببساطة إخبار CameraX بأولوياتك والسماح لها بتفعيل أفضل مجموعة متوافقة لك.

لمن لا يعرفون CameraX

قبل أن نتعمق في واجهة برمجة التطبيقات الجديدة لمجموعة الميزات، لنراجع سريعًا ما هي CameraX. CameraX هي مكتبة دعم Jetpack، تم إنشاؤها لمساعدتك في تسهيل عملية تطوير تطبيقات الكاميرا. وتوفّر هذه المكتبة مساحة سطح لواجهة برمجة التطبيقات تتسم بالتناسق وسهولة الاستخدام وتعمل على معظم أجهزة Android، مع إمكانية التوافق مع الإصدارات القديمة حتى Android 6.0 (مستوى واجهة برمجة التطبيقات 23). إذا كنت لا تزال مبتدئًا في استخدام CameraX، ننصحك بالاطّلاع على المستندات الرسمية وتجربة الدرس التطبيقي حول الترميز للبدء.

ما يمكنك إنشاؤه باستخدام Feature Group API

لم يعُد عليك التخمين بشأن توافق الميزات، بل يمكنك تقديم أفضل تجارب ممكنة للكاميرا بثقة، مثل تسجيل فيديو بنطاق عالي الديناميكية (HDR) وبمعدّل 60 لقطة في الثانية في الوقت نفسه على أجهزة متوافقة (مثل Pixel 10 Pro)، مع تجنُّب الأخطاء على الأجهزة التي لا يمكنها دعم هذه الميزات.

unnamed.png

هاتف Pixel 10 Pro يتيح استخدام كلّ من النطاق الديناميكي العالي و60 لقطة في الثانية في الوقت نفسه

unnamed (1).png

على جهاز قديم لا يمكن فيه تشغيل النطاق العالي الديناميكية و60 لقطة في الثانية في الوقت نفسه، يتم تفعيل النطاق العالي الديناميكية فقط مع إيقاف خيار 60 لقطة في الثانية.

باستخدام Feature Group API، يمكنك إجراء ما يلي:

  • إنشاء واجهات مستخدم ديناميكية وأكثر ذكاءً: يمكنك تفعيل الإعدادات أو إيقافها بذكاء في واجهة المستخدم استنادًا إلى توافق الأجهزة في الوقت الفعلي. على سبيل المثال، إذا فعّل المستخدم HDR، يمكنك إيقاف خيار 60 إطارًا في الثانية على الفور إذا كان الجهاز لا يتيح استخدام هذا الخيار مع HDR. 
unsupported-features-disabled.gif
  • توفير وضع "جودة عالية" موثوق: اضبط الكاميرا باستخدام قائمة ذات أولوية للميزات المطلوبة. تعثر CameraX تلقائيًا على أفضل مجموعة متوافقة مع أي جهاز وتفعّلها، ما يضمن الحصول على نتيجة رائعة بدون منطق معقّد خاص بالجهاز.
  • منع حدوث أعطال في جلسة الكاميرا: من خلال التحقّق من التوافق مسبقًا، يمكنك منع الكاميرا من محاولة ضبط إعدادات غير متوافقة، ما يحدّ من أحد الأسباب الشائعة لحدوث الأعطال ويوفّر تجربة سلسة للمستخدم.

طريقة العمل: المكوّنات الأساسية

ترتكز واجهة برمجة التطبيقات الجديدة على إضافات رئيسية إلى SessionConfig وCameraInfo.

  1. GroupableFeature: تقدّم واجهة برمجة التطبيقات هذه مجموعة من الميزات المحدّدة مسبقًا والقابلة للتجميع، مثل HDR_HLG10 وFPS_60 وPREVIEW_STABILIZATION وIMAGE_ULTRA_HDR. بسبب القيود الحسابية، لا يمكن تجميع سوى مجموعة معيّنة من الميزات بدرجة الموثوقية العالية التي توفّرها واجهة برمجة التطبيقات هذه. نحن نعمل بنشاط على توسيع هذه القائمة وسنوفّر المزيد من الميزات في الإصدارات المستقبلية.
     
  2. مَعلمات SessionConfig الجديدة: يقبل هذا الصف، المستخدَم لبدء جلسة كاميرا، الآن مَعلمتَين جديدتَين:
    • requiredFeatureGroup: استخدِم هذا الخيار للميزات التي يجب أن تكون متوافقة لكي ينجح الإعداد، وهو خيار مثالي للميزات التي يفعّلها المستخدم بشكل صريح، مثل تفعيل خيار "النطاق الديناميكي العالي" (HDR). لضمان تجربة حتمية ومتسقة، ستطرح الدالة bindToLifecycle الخطأ IllegalArgumentException إذا كان الجمع المطلوب غير متاح، بدلاً من تجاهل طلب ميزة بدون إشعار. يجب استخدام واجهة برمجة التطبيقات CameraInfo#isFeatureGroupSupported (التفاصيل أدناه) للبحث عن هذه النتيجة مسبقًا.
    • preferredFeatureGroup: استخدِم هذا الخيار للميزات المرغوب فيها ولكنها اختيارية، على سبيل المثال عندما تريد تنفيذ وضع "عالي الجودة" تلقائي. يمكنك تقديم قائمة بالميزات المطلوبة مرتّبة حسب أولوياتك، وتفعّل CameraX تلقائيًا المجموعة ذات الأولوية الأعلى التي يتيحها الجهاز.
  3. CameraInfo#isFeatureGroupSupported()‎: هذه هي طريقة طلب البحث الأساسية للتحقّق بشكل صريح مما إذا كانت مجموعة ميزات متوافقة، وهي مناسبة تمامًا لتوفير خيارات الميزات المتوافقة فقط للمستخدمين في واجهة مستخدم تطبيقك. يتم تمرير SessionConfig إليه، ويعرض قيمة منطقية تشير إلى ما إذا كانت المجموعة متوافقة. إذا كنت تنوي ربط SessionConfig بميزات مطلوبة، عليك استخدام واجهة برمجة التطبيقات هذه أولاً للتأكّد من أنّها متوافقة. 

التنفيذ في الواقع

لنلقِ نظرة على كيفية استخدام هذه المكوّنات لتقديم تجربة أفضل في استخدام الكاميرا.

السيناريو 1: وضع "أفضل جهد" للجودة العالية

إذا أردت تفعيل أفضل الميزات المتاحة تلقائيًا، يمكنك تقديم قائمة ذات أولوية إلى preferredFeatureGroup. في هذا المثال، نطلب من CameraX إعطاء الأولوية لتقنية HDR، ثم 60 لقطة في الثانية، وأخيرًا ميزة "تثبيت المعاينة". تتولّى CameraX مهمة التحقّق من جميع المجموعات المحتملة واختيار أفضل مجموعة يتيحها الجهاز.

على سبيل المثال، إذا كان الجهاز يمكنه التعامل مع النطاق الديناميكي العالي و60 لقطة في الثانية معًا ولكن ليس مع ميزة "تثبيت المعاينة"، ستفعّل CameraX الميزتَين الأوليَين وتتجاهل الميزة الثالثة. بهذه الطريقة، ستحصل على أفضل تجربة ممكنة بدون كتابة عمليات تحقّق معقّدة خاصة بالجهاز.

cameraProvider.bindToLifecycle(

    lifecycleOwner,

    cameraSelector,

    SessionConfig(

        useCases = listOf(preview, videoCapture),

        // The order of features in this list determines their priority. 

        // CameraX will enable the best-supported combination based on these

        // priorities: HDR_HLG10 > FPS_60 > Preview Stabilization.  

        preferredFeatureGroup =

           listOf(HDR_HLG10, FPS_60, PREVIEW_STABILIZATION),

    ).apply {

        // (Optional) Get a callback with the enabled features

        // to update your UI. 

        setFeatureSelectionListener { selectedFeatures ->

            updateUiIndicators(selectedFeatures)

        }

    }

)

بالنسبة إلى مقتطف الرمز البرمجي هذا، ستحاول CameraX تفعيل مجموعات الميزات بترتيب الأولوية التالي، مع اختيار المجموعة الأولى التي يتوافق معها الجهاز بشكل كامل:

  1. ‫HDR + 60 لقطة في الثانية + تثبيت المعاينة
  2. النطاق الديناميكي العالي + 60 لقطة في الثانية
  3. تثبيت حركة الفيديو أثناء المعاينة باستخدام تقنية HDR
  4. نطاق عالي الديناميكية
  5. ‫60 لقطة في الثانية + تثبيت المعاينة
  6. 60 لقطة في الثانية
  7. تثبيت المعاينة
  8. لا شيء من الميزات المذكورة أعلاه

السيناريو 2: إنشاء واجهة مستخدم تفاعلية

لإنشاء واجهة مستخدم تستجيب لاختيارات المستخدمين وتمنعهم من تحديد مجموعة ميزات غير متوافقة، يمكنك الاستعلام عن التوافق مباشرةً. تتحقّق الدالة أدناه من الميزات غير المتوافقة مع اختيارات المستخدم الحالية، ما يتيح لك إيقاف عناصر واجهة المستخدم ذات الصلة.

/**

 * Returns a list of features that are NOT supported in combination

 * with the currently selected features.

 */

fun getUnsupportedFeatures(

    currentFeatures: Set<GroupableFeature>

): Set<GroupableFeature> {

    val unsupportedFeatures = mutableSetOf<GroupableFeature>()

    val appFeatureOptions = setOf(HDR_HLG10, FPS_60, PREVIEW_STABILIZATION)


    // Iterate over every available feature option in your app. 

    appFeatureOptions.forEach { featureOption ->

        // Skip features the user has already selected. 

        if (currentFeatures.contains(featureOption)) return@forEach


        // Check if adding this new feature is supported. 

        val isSupported = cameraInfo.isFeatureGroupSupported(

            SessionConfig(

                useCases = useCases,

                // Check the new feature on top of existing ones.

                requiredFeatureGroup = currentFeatures + featureOption

            )

        )


        if (!isSupported) {

            unsupportedFeatures.add(featureOption)

        }

    }


    return unsupportedFeatures

}

يمكنك بعد ذلك ربط هذا المنطق في ViewModel أو وحدة التحكّم في واجهة المستخدم للردّ على بيانات أدخلها المستخدم وإعادة ربط الكاميرا بإعدادات مضمونة العمل.

// Invoked when user turns some feature on/off.

fun onFeatureChange(currentFeatures: Set<GroupableFeature>) {

    // Identify features that are unsupported with the current selection.

    val unsupportedFeatures = getUnsupportedFeatures(currentFeatures)



    // Update app UI so that users can't enable them.

    updateDisabledFeatures(unsupportedFeatures)



    // Since the UI now only allows selecting supported feature combinations, 

    // `currentFeatures` is always valid. This allows setting

    // `requiredFeatureGroup` directly, without needing to re-check for

    // support or set a feature selection listener.  

    cameraProvider.bindToLifecycle(

        lifecycleOwner,

        cameraSelector,

        SessionConfig(

            useCases = listOf(preview, videoCapture),

            requiredFeatureGroup = currentFeatures,

        )

    )

}

للاطّلاع على هذه المفاهيم في تطبيق عملي، يمكنك استكشاف تطبيق الاختبار الداخلي الذي يوفّر تنفيذًا كاملاً لكلّ من سيناريوهات "أفضل جهد" و "واجهة مستخدم تفاعلية" الموضّحة أعلاه.

يُرجى العِلم أنّ هذا التطبيق تجريبي وليس نموذجًا متاحًا رسميًا. على الرغم من أنّها مرجع رائع لواجهة برمجة التطبيقات Feature Group API، لم يتم تحسينها للاستخدام في مرحلة الإنتاج.

ابدأ اليوم

تزيل Feature Group API الغموض بشأن استخدام إمكانات الكاميرا المتقدّمة. من خلال توفير طريقة حتمية للاستعلام عن مدى توفّر الميزات، يمكنك إنشاء تطبيقات كاميرا أكثر فعالية وموثوقية بثقة.

تتوفّر واجهة برمجة التطبيقات كتجريبية في الإصدار 1.5 من CameraX، ومن المقرر أن تصبح ثابتة تمامًا في الإصدار 1.6، مع توفّر المزيد من الميزات والتحسينات قريبًا.

لمزيد من المعلومات، يُرجى الاطّلاع على المستندات الرسمية. نتطلّع إلى رؤية ابتكاراتك، ونتطلع إلى معرفة ملاحظاتك. يُرجى مشاركة آرائك والإبلاغ عن أي مشاكل من خلال القنوات التالية:

متابعة القراءة