ملاحظة: تشير هذه الصفحة إلى حزمة Camera2. ننصحك باستخدام الكاميراX ما لم يكن تطبيقك يتطلب ميزات محدَّدة منخفضة المستوى من تطبيق Camera2. يتوافق كل من CameraX و Camera2 مع نظام التشغيل Android 5.0 (المستوى 21 لواجهة برمجة التطبيقات) والإصدارات الأحدث.
لا يتم عرض الكاميرات ومعاينات الكاميرا دائمًا في الاتجاه نفسه على نظام التشغيل Android الأجهزة.
تكون الكاميرا في موضع ثابت على الجهاز، بغض النظر عمّا إذا كان الجهاز هي هاتف أو جهاز لوحي أو جهاز كمبيوتر. فعندما يتغير اتجاه الجهاز، تغييرات اتجاه الكاميرا.
ونتيجةً لذلك، تفترض تطبيقات الكاميرا بشكل عام أنّ هناك علاقة ثابتة بين اتجاه الجهاز ونسبة العرض إلى الارتفاع لمعاينة الكاميرا. عندما الهاتف في الاتجاه العمودي، ومن المفترض أن تكون معاينة الكاميرا أطول. مما هو عريض. عند تدوير الهاتف (والكاميرا) إلى الوضع الأفقي، ينبغي أن تكون معاينة الكاميرا أعرض من طولها.
مع ذلك، تتحدى هذه الافتراضات أشكال أجهزة جديدة، مثل الأجهزة القابلة للطيّ. والأجهزة وأوضاع العرض مثل نوافذ متعددة أو العرض المتعدّد الهواتف القابلة للطي تُغيّر حجم العرض ونسبة العرض إلى الارتفاع بدون تغيير توجهك. يؤدي وضع النوافذ المتعددة إلى حصر تطبيقات الكاميرا في جزء من الشاشة، وتغيير حجم معاينة الكاميرا بغض النظر عن اتجاه الجهاز. يتيح وضع "العرض المتعدّد" استخدام الشاشات الثانوية التي قد لا يتم في نفس اتجاه الشاشة الأساسية.
اتجاه الكاميرا
تشير رسالة الأشكال البيانية تعريف التوافق مع Android أن مستشعر صور الكاميرا "يجب أن يكون موجهًا حتى الكاميرا مع البعد الطويل للشاشة. أي، عندما إذا كان الجهاز في الاتجاه الأفقي، على الكاميرات التقاط الصور الاتجاه الأفقي. وينطبق هذا الأمر بغض النظر عن الإعدادات الاتجاه أي، ينطبق على الأجهزة ذات الوضع الأفقي الأساسي بالإضافة إلى الأجهزة الأساسية في الوضع العمودي".
يؤدي ترتيب الكاميرا إلى الشاشة إلى زيادة مساحة عرض الكاميرا عدسة الكاميرا في أحد تطبيقات الكاميرا. كما تعمل مستشعرات الصور عادةً على إخراج البيانات في ونسب العرض إلى الارتفاع الأفقية، حيث تكون 4:3 هي الأكثر شيوعًا.
![جهاز استشعار الهاتف والكاميرا في الاتجاه العمودي](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_preview_portrait_front_facing.png?authuser=6&hl=ar)
يكون الاتجاه الطبيعي لأداة الاستشعار في الكاميرا هو الوضع الأفقي. في الشكل 1، تحدد أداة الاستشعار الكاميرا الأمامية (تتوجه الكاميرا في نفس اتجاه الشاشة) يتم تدويرها بزاوية 270 درجة بالنسبة إلى الهاتف للتوافق مع تعريف التوافق مع Android
لعرض دوران أداة الاستشعار للتطبيقات، يجب
تتضمن واجهة برمجة التطبيقات camera2
SENSOR_ORIENTATION
ثابت. يشير الجهاز إلى اتجاه أداة الاستشعار في معظم الهواتف والأجهزة اللوحية.
270 درجة للكاميرات الأمامية و90 درجة (نقطة الرؤية من
الجزء الخلفي من الجهاز) للكاميرات الخلفية، والتي تعمل على محاذاة الحافة الطويلة
مستشعرًا بالحافة الطويلة للجهاز. تُبلغ كاميرات الكمبيوتر المحمول بشكل عام عن
اتجاه جهاز الاستشعار 0 أو 180 درجة.
ولأنّ أدوات استشعار صور الكاميرا تُخرج بياناتها (مخزن مؤقت للصور) في
الاتجاه الطبيعي لأداة الاستشعار (أفقية)، فيجب تدوير المخزن المؤقت للصور
عدد الدرجات التي يتم تحديدها من خلال SENSOR_ORIENTATION
لمعاينة الكاميرا
تظهر عموديًا في الاتجاه الطبيعي للجهاز. بالنسبة للكاميرات الأمامية،
دوران عكس عقارب الساعة؛ للكاميرات الخلفية، في اتجاه عقارب الساعة.
فعلى سبيل المثال، بالنسبة للكاميرا الأمامية في الشكل 1، فإن المخزن المؤقت للصور التي تنتجها أداة استشعار الكاميرا على النحو التالي:
![تم تدوير أداة استشعار الكاميرا إلى الاتجاه الأفقي مع استخدام صورة
إلى جانب الفيديو أو أعلى اليسار.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_portrait_rotated_90.png?authuser=6&hl=ar)
ويجب تدوير الصورة بزاوية 270 درجة عكس اتجاه عقارب الساعة حتى يتطابق "الاتجاه" مع اتجاه الجهاز:
![أداة استشعار الكاميرا في الاتجاه العمودي مع صورة عمودية](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_portrait_without_coordinates.png?authuser=6&hl=ar)
ستنتج الكاميرا الخلفية مخزنًا مؤقتًا للصور بنفس الاتجاه
المورد الاحتياطي أعلاه، ولكن تبلغ درجة حرارة SENSOR_ORIENTATION
90 درجة. وبالتالي،
تم تدوير المخزن المؤقت 90 درجة في اتجاه عقارب الساعة.
تدوير الجهاز
تدوير الجهاز هو عدد الدرجات التي يتم تدوير الجهاز فيها عن موضعه الطبيعي توجهك. على سبيل المثال، يشتمل الهاتف ذو الاتجاه الأفقي على جهاز التدوير 90 أو 270 درجة، اعتمادًا على اتجاه الدوران.
يجب تدوير المخزن المؤقت لصور أداة استشعار الكاميرا بنفس عدد الدرجات دوران الجهاز (بالإضافة إلى درجات اتجاه أداة الاستشعار) معاينة الكاميرا لتظهر في وضع مستقيم.
حساب الاتجاه
يضع جهاز الاستشعار في الاعتبار الاتجاه الصحيح لمعاينة الكاميرا. الاتجاه وتدوير الجهاز.
ويمكن حساب الدوران الكلي للمخزن المؤقت لصور أداة الاستشعار باستخدام المعادلة التالية:
rotation = (sensorOrientationDegrees - deviceOrientationDegrees * sign + 360) % 360
حيث sign
هو 1
للكاميرات الأمامية، و-1
للكاميرات الخلفية.
بالنسبة للكاميرات الأمامية، يتم تدوير المخزن المؤقت للصور عكس اتجاه عقارب الساعة (من الاتجاه الطبيعي لجهاز الاستشعار). بالنسبة إلى الكاميرات الخلفية، يمكن استخدام أداة الاستشعار يتم تدوير المخزن المؤقت للصور في اتجاه عقارب الساعة.
يؤدّي التعبير deviceOrientationDegrees * sign + 360
إلى تحويل دوران الجهاز.
من عكس عقارب الساعة إلى اتجاه عقارب الساعة للكاميرات الخلفية (على سبيل المثال،
تحويل 270 درجة عكس اتجاه عقارب الساعة إلى 90 درجة باتجاه عقارب الساعة). باقي القسمة
تعمل هذه العملية على تغيير النتيجة إلى أقل من 360 درجة (على سبيل المثال، التحجيم 540
درجة الدوران إلى 180).
تُبلغ واجهات برمجة التطبيقات المختلفة عن تدوير الجهاز بشكل مختلف:
Display#getRotation()
يتيح هذا الخيار تدوير الجهاز عكس عقارب الساعة (من نقطة المستخدم مشاهدة). يتم إدخال هذه القيمة في الصيغة أعلاه كما هي.OrientationEventListener#onOrientationChanged()
يؤدي إلى إرجاع تدوير الجهاز في اتجاه عقارب الساعة (من وجهة نظر المستخدم). نفي القيمة للاستخدام في الصيغة أعلاه.
الكاميرات الأمامية
![معاينة الكاميرا وجهاز الاستشعار في الاتجاه الأفقي، أداة الاستشعار
هي الجانب الأيمن إلى أعلى.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_preview_landscape_counterclockwise_front_facing.png?authuser=6&hl=ar)
إليك المخزن المؤقت للصور الذي أنتجته أداة استشعار الكاميرا في الشكل 2:
![أداة استشعار الكاميرا في الاتجاه الأفقي مع توجيه الصورة عموديًا](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_landscape.png?authuser=6&hl=ar)
يجب تدوير المخزن المؤقت 270 درجة عكس عقارب الساعة لضبطه في أداة الاستشعار الاتجاه (راجِع اتجاه الكاميرا أعلاه):
![تم تدوير أداة استشعار الكاميرا إلى اتجاه المنفذ مع صورة جانبية.
أعلى اليمين.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_landscape_rotated_270.png?authuser=6&hl=ar)
ثم يتم تدوير المخزن المؤقت 90 درجة إضافية عكس عقارب الساعة يراعي دوران الجهاز، مما يؤدي إلى الاتجاه الصحيح معاينة الكاميرا في الشكل 2:
![تم تدوير أداة استشعار الكاميرا إلى الاتجاه الأفقي مع استخدام صورة
مستقيمًا.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_landscape_without_coordinates.png?authuser=6&hl=ar)
إليك تم توجيه الكاميرا إلى اليمين باتجاه أفقي:
![تكون معاينة الكاميرا وجهاز الاستشعار في الاتجاه الأفقي، ولكن
أداة الاستشعار مقلوبة.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_preview_landscape_clockwise_front_facing.png?authuser=6&hl=ar)
إليك المخزن المؤقت للصور:
![تم تدوير أداة استشعار الكاميرا إلى الاتجاه الأفقي مع صورة مقلوبة
إلى الأسفل.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_landscape_clockwise.png?authuser=6&hl=ar)
يجب تدوير المخزن المؤقت 270 درجة عكس عقارب الساعة لضبطه في أداة الاستشعار الاتجاه:
![أداة استشعار الكاميرا مصنَّفة على الاتجاه العمودي مع تقديم صورة جانبية
أعلى اليمين.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_landscape_clockwise_rotated_270.png?authuser=6&hl=ar)
ثم يتم تدوير المخزن المؤقت 270 درجة أخرى عكس اتجاه عقارب الساعة لحساب دوران الجهاز:
![تم تدوير أداة استشعار الكاميرا إلى الاتجاه الأفقي مع استخدام صورة
مستقيمًا.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_landscape_without_coordinates.png?authuser=6&hl=ar)
الكاميرات الخلفية
عادةً ما يكون اتجاه الكاميرات الخلفية أداة الاستشعار 90 درجة (مثل يتم عرضها من الجزء الخلفي للجهاز). عند توجيه معاينة الكاميرا، يتم تدوير المخزن المؤقت لصور أداة الاستشعار في اتجاه عقارب الساعة من خلال مقدار دوران أداة الاستشعار (وليس عكس عقارب الساعة مثل الكاميرات الأمامية)، ثم يتم تدوير المخزن المؤقت عكس عقارب الساعة من خلال مقدار تدوير الجهاز.
![تكون معاينة الكاميرا وجهاز الاستشعار في الاتجاه الأفقي، ولكن
أداة الاستشعار مقلوبة.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_preview_landscape_clockwise_back_facing.png?authuser=6&hl=ar)
إليك المخزن المؤقت للصور من أداة استشعار الكاميرا في الشكل 4:
![تم تدوير أداة استشعار الكاميرا إلى الاتجاه الأفقي مع صورة مقلوبة
إلى الأسفل.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_landscape_clockwise.png?authuser=6&hl=ar)
يجب تدوير المخزن المؤقت 90 درجة في اتجاه عقارب الساعة لضبط مكانه في أداة الاستشعار الاتجاه:
![أداة استشعار الكاميرا مصنَّفة على الاتجاه العمودي مع تقديم صورة جانبية
أعلى اليمين.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_landscape_clockwise_rotated_270.png?authuser=6&hl=ar)
ثم يتم تدوير المخزن المؤقت 270 درجة عكس عقارب الساعة لحساب الجهاز التدوير:
![تم تدوير أداة استشعار الكاميرا إلى الاتجاه الأفقي مع استخدام صورة
مستقيمًا.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_landscape_without_coordinates.png?authuser=6&hl=ar)
نسبة العرض إلى الارتفاع
تتغير نسبة العرض إلى الارتفاع عند تغيير اتجاه الجهاز ولكن أيضًا عندما طيّ الهواتف القابلة للطيّ وفتحها عند تغيير حجم النوافذ في نوافذ متعددة بيئاتهم، وعند فتح التطبيقات على شاشات عرض ثانوية.
يجب توجيه المخزن المؤقت لصور أداة استشعار الكاميرا وضبط حجمه ليتناسب مع الاتجاه ونسبة العرض إلى الارتفاع لعنصر واجهة مستخدم عدسة الكاميرا كواجهة المستخدم يغير الاتجاه ديناميكيًا - مع تغيير الجهاز أو بدونه توجهك.
في أشكال الأجهزة الجديدة أو في بيئات النوافذ المتعددة أو الشاشات المتعددة، إذا كان أن التطبيق يفترض أن معاينة الكاميرا لها نفس اتجاه الجهاز (عمودي أو أفقي) قد يكون تم توجيه المعاينة بشكل غير صحيح، أو تم تغيير حجمها أو بشكل غير صحيح أو كليهما.
![جهاز قابل للطيّ غير مطوي مع تفعيل معاينة الكاميرا في وضع "بورتريه"
بانحراف.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/foldable_with_rotation_problem.png?authuser=6&hl=ar)
في الشكل 5، افترض التطبيق عن طريق الخطأ أن الجهاز تم تدويره 90 درجات عكس عقارب الساعة؛ وهكذا، قام التطبيق بإجراء تدوير للمعاينة بنفس القدر.
![جهاز قابل للطيّ غير مطوي مع معاينة الكاميرا في وضع عمودي ولكن محمرّ
بسبب التحجيم غير الصحيح.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/foldable_with_scaling_problem.png?authuser=6&hl=ar)
وفي الشكل 6، لم يضبط التطبيق نسبة العرض إلى الارتفاع للمخزن المؤقت للصور لتمكينها من التكيّف بشكل صحيح بحيث يتناسب مع الأبعاد الجديدة لواجهة مستخدم معاينة الكاميرا العنصر.
تواجه تطبيقات الكاميرا ذات الاتجاه الثابت عادةً مشاكل على الأجهزة القابلة للطي الأجهزة الأخرى ذات الشاشات الكبيرة مثل أجهزة الكمبيوتر المحمولة:
![تكون معاينة الكاميرا على الكمبيوتر المحمول في وضع عمودي ولكن واجهة مستخدم التطبيق تظهر بانحراف.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/laptop_camera_preview_fixed-orientation_app.png?authuser=6&hl=ar)
في الشكل 7، تكون واجهة المستخدم لتطبيق الكاميرا جانبية نظرًا لأن اتجاه التطبيق يقتصر على الوضع العمودي فقط. توجيه صورة عدسة الكاميرا بشكل صحيح مقارنةً بأداة استشعار الكاميرا.
إدراج وضع "بورتريه"
تطبيقات الكاميرا التي لا تتيح وضع النوافذ المتعددة
(resizeableActivity="false"
)
وتقييد اتجاههم
(screenOrientation="portrait"
)
أو screenOrientation="landscape"
)
يمكن وضعها في وضع "بورتريه" داخلي على الأجهزة ذات الشاشات الكبيرة لتوجيه الاتجاه بشكل صحيح
معاينة الكاميرا.
تم إدراج تطبيقات أفقية فقط في وضع "بورتريه" في وضع "بورتريه" الاتجاه على الرغم من أن نسبة العرض إلى الارتفاع للعرض الأفقية. يتم عرض التطبيقات باتجاه أفقي فقط في أشرطة أفقية في الاتجاه الأفقي على الرغم من تكون نسبة العرض إلى الارتفاع للعرض عموديًا. تم تدوير صورة الكاميرا للمحاذاة. مع واجهة مستخدم التطبيق، والاقتصاص لتتناسب مع نسبة العرض إلى الارتفاع لمعاينة الكاميرا ثم تحجيمها لملء المعاينة.
يتم تشغيل وضع "بورتريه" الداخلي عند نسبة العرض إلى الارتفاع لصورة الكاميرا. لا تتطابق مستشعر البيانات مع نسبة العرض إلى الارتفاع للنشاط الأساسي للتطبيق.
![معاينة الكاميرا وواجهة مستخدم التطبيق في الاتجاه العمودي الصحيح على الكمبيوتر المحمول
تم تغيير حجم صورة المعاينة العريضة واقتصاصها لتناسب الصورة العمودية
توجهك.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/laptop_inset_portrait_mode.png?authuser=6&hl=ar)
في الشكل 8، تم تدوير تطبيق الكاميرا للوضع العمودي فقط لعرض واجهة المستخدم في الوضع العمودي على شاشة الكمبيوتر المحمول. يظهر التطبيق في شاشة عريضة أفقيًا بسبب الاختلاف في نسبة العرض إلى الارتفاع بين التطبيق العمودي والعرض الأفقي الكاميرا تم تدوير صورة المعاينة لتعويض تدوير واجهة مستخدم التطبيق (بسبب داخل وضع رأسي)، وتم اقتصاص الصورة وضبطها لتلائم الاتجاه الرأسي، ما يقلل من مجال الرؤية.
تدوير، اقتصاص، ضبط الحجم
يتم استدعاء وضع "بورتريه" الداخلي لتطبيق الكاميرا في وضع "بورتريه" فقط على الشاشة. بها نسبة عرض إلى ارتفاع أفقية:
![تكون معاينة الكاميرا على الكمبيوتر المحمول في وضع عمودي ولكن واجهة مستخدم التطبيق تظهر بانحراف.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/laptop_inset_portrait_mode_fixed-orientation_app.png?authuser=6&hl=ar)
يظهر التطبيق مُعدًّا للعرض على شاشة عريضة أفقيًا في الاتجاه العمودي:
![تم تدوير التطبيق إلى الاتجاه العمودي وتم ضبطه على شاشة عريضة أفقيًا. الصورة هي
إلى جانب الفيديو أو أعلى إلى اليمين.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/laptop_inset_portrait_mode_rotate_ui.png?authuser=6&hl=ar)
تم تدوير صورة الكاميرا 90 درجة لضبط اتجاه التطبيق:
![تم تدوير صورة أداة الاستشعار 90 درجة لجعلها عمودية.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/laptop_inset_portrait_mode_rotate_sensor_image.png?authuser=6&hl=ar)
يتم اقتصاص الصورة وفقًا لنسبة العرض إلى الارتفاع في معاينة الكاميرا، ثم تحجيمها إلى ملء المعاينة (يتم تقليل مجال العرض):
![تم اقتصاص صورة الكاميرا لملء معاينة الكاميرا.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/laptop_inset_portrait_mode_crop_and_scale.png?authuser=6&hl=ar)
على الأجهزة القابلة للطي، يمكن أن يكون اتجاه أداة استشعار الكاميرا رأسيًا. بينما تكون نسبة العرض إلى الارتفاع للشاشة أفقية:
![معاينة الكاميرا وواجهة مستخدم التطبيق يتم تدويرهما إلى جانبَي شاشة عريضة غير مطوية](https://developer.android.com/static/images/training/camera/camera2/camera-preview/unfolded_phone_camera_preview_fixed-orientation_app.png?authuser=6&hl=ar)
ونظرًا لأن معاينة الكاميرا يتم تدويرها لضبط اتجاه أداة الاستشعار، يتم توجيه الصورة بشكل صحيح في عدسة الكاميرا، لكن تطبيق الوضع الرأسي فقط تكون جانبية.
لا يحتاج وضع "بورتريه" إلا إلى ضبط محتوى التطبيق على شاشة عريضة أفقيًا في الاتجاه العمودي. لتوجيه معاينة التطبيق والكاميرا بشكل صحيح:
![تطبيق مُعدّ للعرض على شاشة عريضة أفقيًا بتنسيق إطار الصورة مع معاينة الكاميرا
في وضع عمودي على الجهاز القابل للطي.](https://developer.android.com/static/images/training/camera/camera2/camera-preview/unfolded_phone_inset_portrait_mode.png?authuser=6&hl=ar)
واجهة برمجة التطبيقات
اعتبارًا من Android 12 (المستوى 31 من واجهة برمجة التطبيقات)، يمكن للتطبيقات أيضًا التحكّم بشكل صريح في الوضع العمودي الداخلي.
عن طريق
SCALER_ROTATE_AND_CROP
السمة CaptureRequest
الصف.
القيمة الافتراضية هي
SCALER_ROTATE_AND_CROP_AUTO
،
والذي يمكّن النظام من استدعاء وضع رأسي داخلي.
SCALER_ROTATE_AND_CROP_90
هو سلوك وضع رأسي الداخلي كما هو موضح أعلاه.
لا تتوافق بعض الأجهزة مع جميع قِيم SCALER_ROTATE_AND_CROP
. للحصول على قائمة
القيم المسموح بها، والإشارة إلى
CameraCharacteristics#SCALER_AVAILABLE_ROTATE_AND_CROP_MODES
الكاميراX
مكتبة Jetpack CameraX فإن إنشاء عدسة كاميرا تلائم اتجاه أداة الاستشعار على تدوير الجهاز لمهمة بسيطة.
عنصر التنسيق PreviewView
تنشئ معاينة للكاميرا، وتضبط تلقائيًا اتجاه أداة الاستشعار
وتدوير الجهاز والتحجيم. تحتفظ PreviewView
بنسبة العرض إلى الارتفاع
الكاميرا من خلال تطبيق
FILL_CENTER
نوع تغيير الحجم، والذي يوسيط الصورة ولكن قد يتم اقتصاصها لتتوافق مع الأبعاد
من PreviewView
. لضبط صورة الكاميرا على شاشة عريضة أفقيًا، يجب ضبط نوع المقياس على
FIT_CENTER
للاطّلاع على أساسيات إنشاء معاينة الكاميرا باستخدام "PreviewView
"، يُرجى الاطّلاع على
تنفيذ معاينة.
للحصول على نموذج كامل لعملية التنفيذ، يمكنك الاطّلاع على
CameraXBasic
على جيت هب.
عدسة الكاميرا
وعلى غرار حالة الاستخدام Preview، عدسة الكاميرا المكتبة مجموعة من الأدوات لتبسيط إنشاء معاينة الكاميرا. وهو لا يعتمد على CameraX Core، لذا يمكنك دمجه بسلاسة في قاعدة رموز Camera2 الحالية.
بدلاً من استخدام
Surface
مباشرةً، يمكنك استخدام
CameraViewfinder
التطبيق المصغَّر لعرض خلاصة الكاميرا على Camera2.
يستخدم CameraViewfinder
داخليًا إما TextureView
أو SurfaceView
لعرض خلاصة الكاميرا وتطبيق التحويلات المطلوبة عليها
لعرض عدسة الكاميرا بشكل صحيح.
ويتضمن ذلك تصحيح نسبة العرض إلى الارتفاع والمقياس والتدوير.
لطلب السطح من الكائن CameraViewfinder
، عليك:
إنشاء ViewfinderSurfaceRequest
يتضمّن هذا الطلب متطلبات درجة دقة السطح وجهاز الكاميرا.
معلومات واردة من CameraCharacteristics
.
جارٍ الاتصال بالرقم requestSurfaceAsync()
يرسل الطلب إلى موفّر مساحة العرض، وهو إما TextureView
أو
SurfaceView
ويحصل على ListenableFuture
مقابل Surface
.
جارٍ الاتصال بالرقم markSurfaceSafeToRelease()
إلى موفّر مساحة العرض أنّ السطح غير ضروري ذا صلة
من الموارد.
Kotlin
fun startCamera(){ val previewResolution = Size(width, height) val viewfinderSurfaceRequest = ViewfinderSurfaceRequest(previewResolution, characteristics) val surfaceListenableFuture = cameraViewfinder.requestSurfaceAsync(viewfinderSurfaceRequest) Futures.addCallback(surfaceListenableFuture, object : FutureCallback<Surface> { override fun onSuccess(surface: Surface) { /* create a CaptureSession using this surface as usual */ } override fun onFailure(t: Throwable) { /* something went wrong */} }, ContextCompat.getMainExecutor(context)) }
Java
void startCamera(){ Size previewResolution = new Size(width, height); ViewfinderSurfaceRequest viewfinderSurfaceRequest = new ViewfinderSurfaceRequest(previewResolution, characteristics); ListenableFuture<Surface> surfaceListenableFuture = cameraViewfinder.requestSurfaceAsync(viewfinderSurfaceRequest); Futures.addCallback(surfaceListenableFuture, new FutureCallback<Surface>() { @Override public void onSuccess(Surface result) { /* create a CaptureSession using this surface as usual */ } @Override public void onFailure(Throwable t) { /* something went wrong */} }, ContextCompat.getMainExecutor(context)); }
تقنية SurfaceView
SurfaceView
هو
مباشرةً لإنشاء معاينة للكاميرا إذا لم يتم
تتطلب معالجة ولا تكون متحركة.
يعمل SurfaceView
تلقائيًا على تدوير المخزن المؤقت للصور في أداة استشعار الكاميرا ليتطابق مع
اتجاه الشاشة، مع مراعاة كل من اتجاه أداة الاستشعار والجهاز
تدوير. ومع ذلك، يتم تغيير حجم المخزن المؤقت للصور ليلائم SurfaceView
الأبعاد دون أي اعتبار لنسبة العرض إلى الارتفاع.
يجب التأكد من أن نسبة العرض إلى الارتفاع للمخزن المؤقت للصور تطابق العرض إلى الارتفاع
نسبة SurfaceView
، التي يمكنك تحقيقها من خلال تغيير حجم المحتوى
SurfaceView
في هيكل المكوِّن
onMeasure()
:
(رمز المصدر computeRelativeRotation()
متوفر في
التدوير النسبي أدناه).
Kotlin
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { val width = MeasureSpec.getSize(widthMeasureSpec) val height = MeasureSpec.getSize(heightMeasureSpec) val relativeRotation = computeRelativeRotation(characteristics, surfaceRotationDegrees) if (previewWidth > 0f && previewHeight > 0f) { /* Scale factor required to scale the preview to its original size on the x-axis. */ val scaleX = if (relativeRotation % 180 == 0) { width.toFloat() / previewWidth } else { width.toFloat() / previewHeight } /* Scale factor required to scale the preview to its original size on the y-axis. */ val scaleY = if (relativeRotation % 180 == 0) { height.toFloat() / previewHeight } else { height.toFloat() / previewWidth } /* Scale factor required to fit the preview to the SurfaceView size. */ val finalScale = min(scaleX, scaleY) setScaleX(1 / scaleX * finalScale) setScaleY(1 / scaleY * finalScale) } setMeasuredDimension(width, height) }
Java
@Override void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); int relativeRotation = computeRelativeRotation(characteristics, surfaceRotationDegrees); if (previewWidth > 0f && previewHeight > 0f) { /* Scale factor required to scale the preview to its original size on the x-axis. */ float scaleX = (relativeRotation % 180 == 0) ? (float) width / previewWidth : (float) width / previewHeight; /* Scale factor required to scale the preview to its original size on the y-axis. */ float scaleY = (relativeRotation % 180 == 0) ? (float) height / previewHeight : (float) height / previewWidth; /* Scale factor required to fit the preview to the SurfaceView size. */ float finalScale = Math.min(scaleX, scaleY); setScaleX(1 / scaleX * finalScale); setScaleY(1 / scaleY * finalScale); } setMeasuredDimension(width, height); }
للحصول على مزيد من التفاصيل حول تنفيذ SurfaceView
كمعاينة للكاميرا، يمكنك الاطّلاع على
اتجاهات الكاميرا:
عرض الهيئة
TextureView
أقل أداءً من
SurfaceView
والمزيد من العمل، إلا أنّ TextureView
يمنحك الحد الأقصى
التحكم في معاينة الكاميرا.
يعمل TextureView
على تدوير المخزن المؤقت لصور أداة الاستشعار بناءً على اتجاه أداة الاستشعار، ولكن
لا يتعامل مع دوران الجهاز أو تحجيم المعاينة.
يمكن تشفير التوسيع والتدوير في
تحويل المصفوفة. للتعرّف على كيفية
تغيير حجم TextureView
وتدويره بشكل صحيح، راجع
إتاحة الأسطح التي يمكن تغيير حجمها في تطبيق الكاميرا
التدوير النسبي
التدوير النسبي لأداة استشعار الكاميرا هي مقدار التدوير المطلوب محاذاة مخرجات أداة استشعار الكاميرا مع اتجاه الجهاز
يتم استخدام التدوير النسبي بواسطة مكونات مثل SurfaceView
وTextureView
لتحديد عاملي التحجيم x وy لصورة المعاينة. إنها تستخدم أيضًا
تحديد دوران المخزن المؤقت لصور أداة الاستشعار.
تشير رسالة الأشكال البيانية
CameraCharacteristics
أو
تتيح صفوف Surface
احتساب
التدوير النسبي لأداة استشعار الكاميرا:
Kotlin
/** * Computes rotation required to transform the camera sensor output orientation to the * device's current orientation in degrees. * * @param characteristics The CameraCharacteristics to query for the sensor orientation. * @param surfaceRotationDegrees The current device orientation as a Surface constant. * @return Relative rotation of the camera sensor output. */ public fun computeRelativeRotation( characteristics: CameraCharacteristics, surfaceRotationDegrees: Int ): Int { val sensorOrientationDegrees = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION)!! // Reverse device orientation for back-facing cameras. val sign = if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT ) 1 else -1 // Calculate desired orientation relative to camera orientation to make // the image upright relative to the device orientation. return (sensorOrientationDegrees - surfaceRotationDegrees * sign + 360) % 360 }
Java
/** * Computes rotation required to transform the camera sensor output orientation to the * device's current orientation in degrees. * * @param characteristics The CameraCharacteristics to query for the sensor orientation. * @param surfaceRotationDegrees The current device orientation as a Surface constant. * @return Relative rotation of the camera sensor output. */ public int computeRelativeRotation( CameraCharacteristics characteristics, int surfaceRotationDegrees ){ Integer sensorOrientationDegrees = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION); // Reverse device orientation for back-facing cameras. int sign = characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT ? 1 : -1; // Calculate desired orientation relative to camera orientation to make // the image upright relative to the device orientation. return (sensorOrientationDegrees - surfaceRotationDegrees * sign + 360) % 360; }
مقاييس الفترة
يجب عدم استخدام حجم الشاشة لتحديد أبعاد الكاميرا. عدسة الكاميرا تطبيق الكاميرا قيد التشغيل في جزء من الشاشة، سواء في وضع النوافذ المتعددة على الأجهزة الجوّالة أو وضع "بدون قيود" في نظام التشغيل ChromeOS
WindowManager#getCurrentWindowMetrics()
(المضافة في المستوى 30 من واجهة برمجة التطبيقات) تعرض حجم نافذة التطبيق بدلاً من
حجم الشاشة. طُرق مكتبة Jetpack WindowManager
WindowMetricsCalculator#computeCurrentWindowMetrics()
أو
WindowInfoTracker#currentWindowMetrics()
توفير دعم مماثل للتوافق مع الأنظمة القديمة للمستوى 14 من واجهة برمجة التطبيقات.
التدوير بمقدار 180 درجة
تدوير الجهاز بزاوية 180 درجة (على سبيل المثال، من الاتجاه الطبيعي إلى
الاتجاه الطبيعي مقلوبًا) لا يؤدي إلى
onConfigurationChanged()
معاودة الاتصال. نتيجةً لذلك، قد تكون معاينة الكاميرا مقلوبة.
لاكتشاف الدوران بزاوية 180 درجة، نفِّذ
DisplayListener
والتحقق من دوران الجهاز من خلال طلب
Display#getRotation()
في
onDisplayChanged()
معاودة الاتصال.
مراجع حصرية
قبل الإصدار Android 10، كان النشاط الأكثر ظهورًا فقط في النوافذ المتعددة
البيئة كانت في الحالة RESUMED
. كان هذا مربكًا للمستخدمين لأن
لم يقدم النظام أي إشارة إلى النشاط الذي تم استئنافه.
في نظام Android 10 (مستوى واجهة برمجة التطبيقات 29)، تم توفير ميزة السير الذاتية المتعدّدة التي تتيح لجميع الأنشطة المرئية
في الحالة RESUMED
. سيظل بإمكان الأنشطة المرئية إدخال PAUSED
على سبيل المثال، إذا كان هناك نشاط شفاف أعلى النشاط أو
لا يمكن التركيز على النشاط، كما هو الحال في وضع "نافذة ضمن النافذة" (راجع
إتاحة الميزة "نافذة ضمن النافذة").
تطبيق يستخدم الكاميرا أو الميكروفون أو أي ميزات حصرية أو
يجب أن يتيح مورد سينغلتون على واجهة برمجة التطبيقات 29 أو أعلى إمكانية الاستئناف المتعدد. بالنسبة
على سبيل المثال، إذا أرادت ثلاثة أنشطة تم استئنافها استخدام الكاميرا، فلا يمكن إلا إجراء واحد
للوصول إلى هذا المورد الحصري. يجب أن ينفذ كل نشاط
onDisconnected()
لمعاودة الاتصال بك بشأن الوصول الاستباقي إلى الكاميرا بأولوية أعلى
الأخرى.
لمزيد من المعلومات، يُرجى مراجعة السير الذاتية المتعددة:
مصادر إضافية
- للاطّلاع على عيّنة من Camera2، يُرجى الاطّلاع على تطبيق Camera2Basic. على GitHub.
- للتعرّف على حالة استخدام معاينة CameraX، يمكنك الاطّلاع على CameraX. تنفيذ معاينة.
- للحصول على نموذج لتنفيذ معاينة كاميرا CameraX، يمكنك الاطّلاع على كاميراXBasic على جيت هب.
- للحصول على معلومات عن معاينة الكاميرا على نظام التشغيل ChromeOS، يُرجى الاطّلاع على اتجاهات الكاميرا:
- للحصول على معلومات حول تطوير التطبيقات للأجهزة القابلة للطي، يُرجى الاطّلاع على مزيد من المعلومات حول الهواتف القابلة للطي