ملاحظة: تشير هذه الصفحة إلى حزمة camera2. ننصحك باستخدام cameraX ما لم يكن تطبيقك يتطلب ميزات محدّدة ومنخفضة المستوى من Camera2. يتوافق كل من CameraX و Camera2 مع الإصدار Android 5.0 (المستوى 21 من واجهة برمجة التطبيقات) والإصدارات الأحدث.
لا تكون معاينات الكاميرات والكاميرا دائمًا في الاتجاه نفسه على أجهزة Android.
تكون الكاميرا في موضع ثابت على الجهاز، بصرف النظر عمّا إذا كان الجهاز هو الهاتف أو الجهاز اللوحي أو الكمبيوتر. عندما يتغير اتجاه الجهاز، يتغير اتجاه الكاميرا.
ونتيجةً لذلك، تفترض تطبيقات الكاميرا بشكل عام وجود علاقة ثابتة بين اتجاه الجهاز ونسبة العرض إلى الارتفاع لمعاينة الكاميرا. عندما يكون الهاتف في الاتجاه الرأسي، يُفترض أن تكون معاينة الكاميرا أطول من عرضها. عند تدوير الهاتف (والكاميرا) إلى الوضع الأفقي، من المتوقّع أن تكون معاينة الكاميرا أعرض من طولها.
ومع ذلك، تواجه هذه الافتراضات أشكالاً جديدة من أشكال الأجهزة، مثل الأجهزة القابلة للطي وأوضاع العرض، مثل النوافذ المتعددة وشاشات العرض المتعددة. تغيّر الأجهزة القابلة للطي حجم الشاشة ونسبة العرض إلى الارتفاع بدون تغيير الاتجاه. يؤدي وضع النوافذ المتعددة إلى تقييد تطبيقات الكاميرا بجزء من الشاشة، وتغيير حجم معاينة الكاميرا بغض النظر عن اتجاه الجهاز. يتيح وضع الشاشات المتعددة استخدام شاشات العرض الثانوية التي قد لا تكون في الاتجاه نفسه للشاشة الأساسية.
اتجاه الكاميرا
بينما يحدد تعريف التوافق مع Android أنه يجب توجيه مستشعر صور الكاميرا "حتى يتوافق البُعد الطويل للكاميرا مع البُعد الطويل للشاشة. أي، عندما يتم تثبيت الجهاز في الاتجاه الأفقي، يجب أن تلتقط الكاميرات الصور في الاتجاه الأفقي. وينطبق ذلك بغض النظر عن الاتجاه الطبيعي للجهاز، أي أنّه ينطبق على الأجهزة الأساسية في الوضع الأفقي وعلى الأجهزة الأساسية في الوضع العمودي".
تؤدي إعدادات الكاميرا إلى الشاشة إلى زيادة مساحة عرض عدسة الكاميرا في تطبيق الكاميرا. بالإضافة إلى ذلك، تُخرج أجهزة استشعار الصور بياناتها عادةً بنِسب عرض إلى ارتفاع أفقية، وتكون نسبة العرض إلى الارتفاع 4:3 هي الأكثر شيوعًا.
يكون الاتجاه الطبيعي لجهاز استشعار الكاميرا في الوضع الأفقي. في الشكل 1، تم تدوير أداة استشعار الكاميرا الأمامية (الكاميرا الموجهة في نفس اتجاه الشاشة) بمقدار 270 درجة بالنسبة إلى الهاتف للتوافق مع تعريف التوافق مع Android.
لعرض دوران أداة الاستشعار على التطبيقات، تتضمّن واجهة برمجة التطبيقات
camera2
قيمة ثابتة
SENSOR_ORIENTATION
ثابتة. بالنسبة إلى معظم الهواتف والأجهزة اللوحية، يبلغ الجهاز عن اتجاه أداة الاستشعار
بمقدار 270 درجة للكاميرات الأمامية و90 درجة (نقطة رؤية من
الجزء الخلفي من الجهاز) للكاميرات الخلفية، ما يؤدي إلى محاذاة الحافة الطويلة
لأداة الاستشعار مع الحافة الطويلة للجهاز. تبلغ كاميرات الكمبيوتر المحمول بشكل عام
اتجاه أداة الاستشعار 0 أو 180 درجة.
بما أنّ أدوات استشعار صور الكاميرا تُخرج بياناتها (مخزن صور مؤقت) في
الاتجاه الطبيعي للمستشعر (أفقي)، يجب تدوير المخزن المؤقت للصور
عدد الدرجات المحددة في SENSOR_ORIENTATION
لكي تظهر معاينة الكاميرا
في وضع عمودي في الاتجاه الطبيعي للجهاز. بالنسبة للكاميرات الأمامية، يكون الدوران عكس اتجاه عقارب الساعة، وبالنسبة للكاميرات الأمامية، يتم الدوران في اتجاه عقارب الساعة.
على سبيل المثال، بالنسبة للكاميرا الأمامية في الشكل 1، يبدو المخزن المؤقت للصور الذي أنتجه أداة استشعار الكاميرا على النحو التالي:
يجب تدوير الصورة بزاوية 270 درجة عكس اتجاه عقارب الساعة بحيث يتطابق اتجاه المعاينة مع اتجاه الجهاز:
تُنتج الكاميرا الخلفية مخزنًا مؤقتًا للصور بنفس اتجاه المخزن المؤقت أعلاه، ولكن تبلغ درجة 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()
لعرض تدوير الجهاز في اتجاه عقارب الساعة (من وجهة نظر المستخدم). قم بإبطال القيمة للاستخدام في الصيغة أعلاه.
الكاميرات الأمامية
في ما يلي المخزن المؤقت للصور الذي أنشأه مستشعر الكاميرا في الشكل 2:
يجب تدوير المخزن المؤقت بمقدار 270 درجة عكس اتجاه عقارب الساعة لضبط اتجاه أداة الاستشعار (راجع اتجاه الكاميرا أعلاه):
ثم يتم تدوير المخزن المؤقت بمقدار 90 درجة عكس اتجاه عقارب الساعة لحساب دوران الجهاز، مما يؤدي إلى الاتجاه الصحيح لمعاينة الكاميرا في الشكل 2:
في ما يلي الكاميرا تم تحويلها من اليمين إلى الاتجاه الأفقي:
إليك المخزن المؤقت للصور:
يجب تدوير المخزن المؤقت بمقدار 270 درجة عكس اتجاه عقارب الساعة لضبط اتجاه أداة الاستشعار:
ثم يتم تدوير المخزن المؤقت بمقدار 270 درجة عكس اتجاه عقارب الساعة لحساب دوران الجهاز:
الكاميرات الخلفية
يكون اتجاه الكاميرات الخلفية عادةً في اتجاه أداة الاستشعار يتجه بمقدار 90 درجة (كما هو موضّح من الجزء الخلفي من الجهاز). عند توجيه معاينة الكاميرا، يتم تدوير المخزن المؤقت للصور الخاص بأداة الاستشعار في اتجاه عقارب الساعة وفقًا لحجم دوران أداة الاستشعار (بدلاً من عكس اتجاه عقارب الساعة مثل الكاميرات الأمامية)، ثم يتم تدوير المخزن المؤقت للصور عكس اتجاه عقارب الساعة حسب مقدار دوران الجهاز.
في ما يلي المورد الاحتياطي للصور من مستشعر الكاميرا في الشكل 4:
يجب تدوير المخزن المؤقت بمقدار 90 درجة في اتجاه عقارب الساعة لضبط اتجاه أداة الاستشعار:
ثم يتم تدوير المخزن المؤقت بمقدار 270 درجة عكس اتجاه عقارب الساعة لحساب دوران الجهاز:
نسبة العرض إلى الارتفاع
تتغيّر نسبة العرض إلى الارتفاع عند تغيير اتجاه الجهاز، وأيضًا عند طي الجهاز القابل للطي وفتحه، وعند تغيير حجم النوافذ في بيئات متعددة النوافذ، وعند فتح التطبيقات على شاشات ثانوية.
يجب توجيه المخزن المؤقت للصور وقياسه ليلائم الاتجاه ونسبة العرض إلى الارتفاع لعنصر واجهة المستخدم في عدسة الكاميرا عندما تغيّر واجهة المستخدم الاتجاه ديناميكيًا، مع تغيير اتجاه الجهاز أو بدونه.
في أشكال الأجهزة الجديدة أو في البيئات التي تضمّ شاشات متعددة أو شاشات متعددة، إذا كان تطبيقك يفترض أنّ معاينة الكاميرا لها الاتجاه نفسه للجهاز (عمودي أو أفقي)، قد يتم توجيه المعاينة بشكل غير صحيح أو تغيير حجمها بشكل غير صحيح أو كليهما.
في الرسم 5، افترض التطبيق عن طريق الخطأ أنه تم تدوير الجهاز بمقدار 90 درجة عكس اتجاه عقارب الساعة، وبالتالي، قام التطبيق بتدوير المعاينة بنفس المقدار.
في الشكل 6، لم يضبط التطبيق نسبة العرض إلى الارتفاع للمخزن المؤقت للصور لتمكينه من تغيير حجمه بشكل صحيح ليلائم الأبعاد الجديدة لعنصر واجهة المستخدم لمعاينة الكاميرا.
عادةً ما تواجه تطبيقات الكاميرا ذات الاتجاه الثابت مشاكل على الأجهزة القابلة للطي وغيرها من الأجهزة ذات الشاشات الكبيرة، مثل أجهزة الكمبيوتر المحمول:
في الشكل 7، تظهر واجهة المستخدم لتطبيق الكاميرا بشكل جانبي لأن اتجاه التطبيق يقتصر على الوضع العمودي فقط. يتم توجيه صورة عدسة الكاميرا بشكل صحيح بالنسبة إلى مستشعر الكاميرا،
إدراج وضع "بورتريه"
تطبيقات الكاميرا التي لا تتيح وضع النوافذ المتعددة
(resizeableActivity="false"
)
والتي تُقيِّد اتجاهها
(screenOrientation="portrait"
أو screenOrientation="landscape"
)
يمكن وضعها في وضع "بورتريه" الداخلي على الأجهزة ذات الشاشات الكبيرة لتوجيه
معاينة الكاميرا بشكل صحيح.
إدراج تطبيقات أفقية فقط في الوضع العمودي في الاتجاه العمودي حتى لو كانت نسبة العرض إلى الارتفاع للعرض أفقي يتم عرض التطبيقات ذات الوضع الأفقي فقط على أشرطة أفقية في الاتجاه الأفقي على الرغم من أن نسبة العرض إلى الارتفاع للعرض عمودي. يتم تدوير صورة الكاميرا لتتوافق مع واجهة مستخدم التطبيق، ويتم اقتصاصها لتتناسب مع نسبة العرض إلى الارتفاع لمعاينة الكاميرا، ثم تحجيمها لملء المعاينة.
يتم تفعيل وضع "بورتريه" المُدرج عندما لا تتطابق نسبة العرض إلى الارتفاع في أداة استشعار الصور في الكاميرا مع نسبة العرض إلى الارتفاع للنشاط الأساسي للتطبيق.
في الشكل 8، تم تدوير تطبيق الكاميرا العمودية فقط لعرض واجهة المستخدم في وضع عمودي على شاشة الكمبيوتر المحمول. تم عرض التطبيق على شاشة عريضة أفقيًا بسبب الفرق في نسبة العرض إلى الارتفاع بين تطبيق العرض العمودي والعرض الأفقي. تم تدوير صورة معاينة الكاميرا لتعويض تدوير واجهة مستخدم التطبيق (بسبب الوضع العمودي المُدرج)، وتم اقتصاص الصورة وتغيير حجمها لتلائم الاتجاه الرأسي، مما يقلل من مجال الرؤية.
التدوير، الاقتصاص، تغيير الحجم
يتم استدعاء وضع "بورتريه" المدرَج في تطبيق كاميرا عمودي فقط على شاشة تتضمّن نسبة عرض إلى ارتفاع أفقية:
يظهر التطبيق على شاشة عريضة أفقيًا بتنسيق عمودي:
تم تدوير صورة الكاميرا بمقدار 90 درجة لتعديل اتجاه التطبيق:
يتم اقتصاص الصورة إلى نسبة العرض إلى الارتفاع لمعاينة الكاميرا، ثم يتم تغيير حجمها لملء المعاينة (يتم تقليل مجال الرؤية):
على الأجهزة القابلة للطي، يمكن أن يكون اتجاه أداة استشعار الكاميرا عموديًا بينما تكون نسبة العرض إلى الارتفاع للشاشة في الوضع الأفقي:
نظرًا لتدوير معاينة الكاميرا لضبط اتجاه أداة الاستشعار، يتم توجيه الصورة بشكل صحيح في نطاق عدسة الكاميرا، ولكن يتم توجيه التطبيق في الوضع الرأسي فقط إلى الجانبين.
في وضع "بورتريه"، يجب إدراج التطبيق في شاشة عريضة أفقيًا من أجل توجيه التطبيق ومعاينة الكاميرا بشكل صحيح:
واجهة برمجة التطبيقات
بدءًا من نظام التشغيل 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
على GitHub.
عدسة الكاميرا
وعلى غرار حالة استخدام Preview (معاينة)، توفر مكتبة cameraViewfinder مجموعة من الأدوات لتبسيط عملية إنشاء معاينة للكاميرا. ولا يعتمد ذلك على CameraX Core، لذا يمكنك دمجه بسلاسة مع قاعدة رموز Camera2 الحالية.
بدلاً من استخدام
Surface
بشكل مباشر، يمكنك استخدام
التطبيق المصغّر
CameraViewfinder
لعرض خلاصة الكاميرا للكاميرا2.
تستخدم 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، يُرجى مراجعة مستودع CameraXBasic على GitHub.
- للحصول على معلومات حول معاينة الكاميرا في نظام التشغيل ChromeOS، يُرجى الاطّلاع على اتجاهات الكاميرا.
- للحصول على معلومات حول التطوير للأجهزة القابلة للطي، يُرجى الاطّلاع على التعرّف على الأجهزة القابلة للطي.