ما وراء الميزات الفردية: ضمان مجموعات الميزات باستخدام CameraX 1.5
مدّة القراءة: 6 دقائق
تتميّز تطبيقات الكاميرا الحديثة بميزات قوية ومتداخلة. ويتوقّع المستخدمون تسجيل فيديو بنطاق عالي ديناميكية مذهل، والتقاط حركة سلسة بمعدّل 60 لقطة في الثانية، والحصول على لقطات سلسة جدًا باستخدام ميزة "تثبيت المعاينة"، وغالبًا ما يكون ذلك في الوقت نفسه.
نحن المطوّرون نعلم أنّ الواقع أكثر تعقيدًا. كيف يمكنك ضمان أنّ جهازًا معيّنًا يتيح فعلاً استخدام مجموعة معيّنة من الميزات؟ حتى الآن، كان تفعيل ميزات متعدّدة غالبًا ما يكون محفوفًا بالمخاطر. يمكنك التحقّق من إتاحة ميزة فردية، ولكن قد يؤدي الجمع بينها إلى سلوك غير محدّد أو، ما هو أسوأ، إلى فشل جلسة الكاميرا. ويجبر هذا الغموض المطوّرين على توخي الحذر، ما يمنع المستخدمين على الأجهزة المتوافقة من الوصول إلى أفضل تجربة ممكنة.
على سبيل المثال، لا تتيح إلا عدد قليل جدًا من الأجهزة المتميزة بشكل موثوق تسجيل فيديو بنطاق عالي ديناميكية وبمعدّل 60 لقطة في الثانية في الوقت نفسه. وبالتالي، تتجنّب معظم التطبيقات تفعيل كلتيهما في الوقت نفسه لمنع تجربة سيئة للمستخدم على غالبية الهواتف.
لمعالجة هذه المشكلة، نحن بصدد طرح مجموعة الميزات في CameraX - وهي واجهة برمجة تطبيقات جديدة مصمّمة لإزالة هذا التخمين. يمكنك الآن الاستعلام عما إذا كانت مجموعة معيّنة من الميزات متاحة قبل ضبط الكاميرا، أو ما عليك سوى إخبار CameraX بأولوياتك والسماح لها بتفعيل أفضل مجموعة متاحة لك.
لمحة عن CameraX
قبل التطرّق إلى واجهة برمجة تطبيقات "مجموعة الميزات" الجديدة، لنلخّص بسرعة ما هو CameraX. إنّ CameraX هي مكتبة دعم Jetpack مصمّمة لمساعدتك في تسهيل عملية تطوير تطبيقات الكاميرا. وهي توفّر واجهة برمجة تطبيقات متّسقة وسهلة الاستخدام تعمل على معظم أجهزة Android، مع التوافق مع الإصدارات السابقة حتى Android 6.0 (المستوى 23 من واجهة برمجة التطبيقات). إذا كنت تستخدم CameraX للمرة الأولى، ننصحك بالاطّلاع على المستندات الرسمية وتجربة الدرس التطبيقي حول الترميز للبدء.
ما يمكنك إنشاؤه باستخدام واجهة برمجة تطبيقات "مجموعة الميزات"
لم يعُد عليك المخاطرة بمجموعات الميزات ويمكنك بثقة تقديم أفضل تجارب الكاميرا الممكنة، مثل تسجيل فيديو بنطاق عالي ديناميكية وبمعدّل 60 لقطة في الثانية في الوقت نفسه على أجهزة متوافقة (مثل Pixel 10 Pro)، مع تجنُّب الأخطاء بشكل سلس على الأجهزة التي لا يمكنها إتاحة هذه المجموعة.
باستخدام واجهة برمجة تطبيقات "مجموعة الميزات"، يمكنك إجراء ما يلي:
- إنشاء واجهات مستخدم أكثر ذكاءً وديناميكية: يمكنك تفعيل الإعدادات أو إيقافها بذكاء في واجهة المستخدم استنادًا إلى إتاحة الجهاز في الوقت الفعلي. على سبيل المثال، إذا فعّل المستخدم النطاق العالي الديناميكية، يمكنك على الفور تعتيم خيار 60 لقطة في الثانية وإيقافه إذا لم تكن المجموعة متاحة على هذا الجهاز.
- تقديم وضع "عالي الجودة" موثوق به: يمكنك ضبط الكاميرا باستخدام قائمة مرتبة حسب الأولوية بالميزات المطلوبة. تعثر CameraX تلقائيًا على أفضل مجموعة متاحة لأي جهاز وتفعّلها، ما يضمن الحصول على نتيجة رائعة بدون منطق معقّد خاص بالجهاز.
- منع حالات فشل جلسة الكاميرا: من خلال التحقّق من الإتاحة مسبقًا، يمكنك منع الكاميرا من محاولة ضبط مجموعة غير متاحة، ما يزيل مصدرًا شائعًا للأعطال ويوفر تجربة سلسة للمستخدم.
طريقة العمل: المكوّنات الأساسية
تتمحور واجهة برمجة التطبيقات الجديدة حول إضافات رئيسية إلى SessionConfig و CameraInfo.
- GroupableFeature: تقدّم واجهة برمجة التطبيقات هذه مجموعة من الميزات القابلة للتجميع المحدّدة مسبقًا، مثل HDR_HLG10 وFPS_60 وPREVIEW_STABILIZATION وIMAGE_ULTRA_HDR. بسبب القيود الحسابية، لا يمكن تجميع إلا مجموعة معيّنة من الميزات مع درجة الموثوقية العالية التي توفّرها واجهة برمجة التطبيقات هذه. ونحن نعمل بنشاط على توسيع هذه القائمة وسنقدّم إمكانية استخدام المزيد من الميزات في الإصدارات المستقبلية.
- معلَمات SessionConfig الجديدة: يقبل هذا الصف، المستخدَم لبدء جلسة الكاميرا، الآن معلَمتَين جديدتَين:
-
requiredFeatureGroup: استخدِم هذه المعلَمة للميزات التي يجب أن تكون متاحة لنجاح عملية الضبط، وهي مثالية للميزات التي يفعّلها المستخدم صراحةً، مثل تبديل مفتاح "النطاق العالي الديناميكية". لضمان تجربة حتمية ومتّسقة، سيؤدي طلبbindToLifecycleإلى طرحIllegalArgumentExceptionإذا لم تكن المجموعة المطلوبة غير متاحة، بدلاً من تجاهل طلب الميزة بدون إشعار. يجب استخدام واجهة برمجة التطبيقاتCameraInfo#isFeatureGroupSupported(التفاصيل أدناه) للاستعلام عن هذه النتيجة مسبقًا. -
preferredFeatureGroup: استخدِم هذه المعلَمة للميزات المرغوبة ولكنها اختيارية، على سبيل المثال عندما تريد تنفيذ وضع "عالي الجودة" تلقائي. يمكنك تقديم قائمة بالميزات المطلوبة مرتّبة حسب أولوياتك، وتفعّل CameraX تلقائيًا المجموعة ذات الأولوية الأعلى التي يتيحها الجهاز.
-
- **CameraInfo#isFeatureGroupSupported()**: هذه هي طريقة الاستعلام الأساسية للتحقّق صراحةً مما إذا كانت مجموعة ميزات متاحة، وهي مناسبة تمامًا لتوفير خيارات الميزات المتاحة فقط للمستخدمين في واجهة مستخدم تطبيقك. يمكنك تمرير
SessionConfigإليها، وتعرض قيمة منطقية تشير إلى ما إذا كانت المجموعة متاحة. إذا كنت تنوي ربطSessionConfigبميزات مطلوبة، عليك استخدام واجهة برمجة التطبيقات هذه أولاً للتأكّد من إتاحتها.
طريقة الاستخدام
لنلقِ نظرة على كيفية استخدام هذه المكوّنات لإنشاء تجربة كاميرا أفضل.
السيناريو 1: وضع "عالي الجودة" بأفضل ما يمكن
إذا كنت تريد تفعيل أفضل الميزات الممكنة تلقائيًا، يمكنك تقديم قائمة مرتبة حسب الأولوية إلى preferredFeatureGroup. في هذا المثال، نطلب من CameraX منح الأولوية للنطاق العالي الديناميكية، ثم 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 تفعيل مجموعات الميزات بترتيب الأولوية التالي، مع اختيار أول مجموعة يتيحها الجهاز بالكامل:
- النطاق العالي الديناميكية + 60 لقطة في الثانية + "تثبيت المعاينة"
- النطاق العالي الديناميكية + 60 لقطة في الثانية
- النطاق العالي الديناميكية + "تثبيت المعاينة"
- النطاق العالي الديناميكية
- 60 لقطة في الثانية + "تثبيت المعاينة"
- 60 لقطة في الثانية
- "تثبيت المعاينة"
- لا شيء من الميزات أعلاه
السيناريو 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,
)
)
}للاطّلاع على هذه المفاهيم في تطبيق عملي، يمكنك استكشاف تطبيق الاختبار الداخلي. وهو يقدّم عملية تنفيذ كاملة لكل من السيناريوهات "بأفضل ما يمكن" و "واجهة مستخدم تفاعلية" التي تمت مناقشتها أعلاه.
يُرجى العِلم أنّ هذا تطبيق اختبار وليس نموذجًا رسميًا مدعومًا. على الرغم من أنّه مرجع رائع لواجهة برمجة تطبيقات "مجموعة الميزات"، لم يتم تحسينه للاستخدام في مرحلة الإنتاج.
ابدأ اليوم
تزيل واجهة برمجة تطبيقات "مجموعة الميزات" الغموض الذي يكتنف العمل باستخدام إمكانات الكاميرا المتقدّمة. من خلال توفير طريقة محدّدة للاستعلام عن إتاحة الميزات، يمكنك إنشاء تطبيقات كاميرا أكثر قوة وموثوقية بثقة.
تتوفّر واجهة برمجة التطبيقات كإصدار تجريبي في CameraX 1.5 ومن المقرر أن تصبح مستقرة تمامًا في الإصدار 1.6، مع توفّر المزيد من الدعم والتحسينات.
لمزيد من المعلومات، يُرجى الاطّلاع على المستندات الرسمية. نحن متحمّسون لرؤية أعمالكم الإبداعية، ونتطلّع إلى ملاحظاتكم. يُرجى مشاركة آرائك والإبلاغ عن أي مشاكل من خلال القنوات التالية:
-
أخبار المنتجاتإنّ توفير تجربة آمنة على الإنترنت وحماية المستخدمين من الأذى هما من أهم الأولويات في Google Play.
Paul Feng • مدّة القراءة: دقيقتان -
أخبار المنتجاتنحتفل اليوم رسميًا بمرور خمسة أعوام على إطلاق Jetpack Compose 1.0. من الإصدار 1.0 الذي تم الإعلان عنه في 28 يوليو 2021 إلى أحدث إصدار 1.11، شهدنا تطوّر واجهات برمجة التطبيقات بشكل كبير على مرّ السنين، ونحن نأخذ لحظة للاحتفال.
Rebecca Franks, Nick Butcher, Loryn Hairston • مدّة القراءة: 5 دقائق -
أخبار المنتجاتأصبح الإصدار 2 من استوديو Android Quail مستقرًا وجاهزًا للاستخدام في مرحلة الإنتاج، ما يغيّر بيئة التطوير المتكاملة (IDE) من خلال سير عمل الوكيل المتزامن، وتحديد المشاكل المتعلقة بتسرّب الذاكرة المدمج أصلاً، وإصلاح الأعطال التي تراعي السياق.
Amman Asfaw • مدّة القراءة: 3 دقائق
يمكنك تلقّي أحدث المعلومات عن تطوير تطبيقات Android في بريدك الوارد أسبوعيًا.