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

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

مدّة القراءة: 6 دقائق
عرض الملف الشخصي لـ "تحسين مسرور"
Tahsin Masrur مهندس برمجيات

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

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

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

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

للمستخدمين الجدد في CameraX

قبل أن نتعمّق في واجهة برمجة التطبيقات الجديدة Feature Group API، لنستعرض سريعًا ما هي 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
على الأجهزة القديمة التي لا يمكنها تشغيل نطاق عالي الديناميكية وعدد اللقطات في الثانية في الوقت نفسه، يتم تفعيل نطاق عالي الديناميكية فقط بينما يتم إيقاف خيار عدد اللقطات في الثانية.

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

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

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

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

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

التنفيذ في الممارسة العملية

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

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

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

على سبيل المثال، إذا كان الجهاز يمكنه التعامل مع HDR و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. ‫HDR +‏ 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 الغموض المتعلّق بالتعامل مع إمكانات الكاميرا المتقدّمة. من خلال توفير طريقة حتمية للاستعلام عن الميزات المتاحة، يمكنك إنشاء تطبيقات كاميرا أكثر فعالية وموثوقية بثقة.

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

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

من كتابة:
متابعة القراءة