ملاحظة: تشير هذه الصفحة إلى حزمة 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
على جيت هب.
عدسة الكاميرا
على غرار حالة استخدام المعاينة، توفر مكتبة CameraViewfinder مجموعة من الأدوات لتبسيط إنشاء معاينة الكاميرا. ولا يعتمد هذا الإصدار على CameraX Core، لذا يمكنك دمجه بسلاسة في قاعدة بيانات Camera2 الحالية.
بدلاً من استخدام
Surface
مباشرةً، يمكنك استخدام
CameraViewfinder
التطبيق المصغَّر لعرض خلاصة الكاميرا على Camera2.
يستخدم CameraViewfinder
داخليًا إما TextureView
أو SurfaceView
لعرض خلاصة الكاميرا، ويطبّق عليها عمليات التحويل المطلوبة
لعرض عدسة الكاميرا بشكل صحيح.
ويتضمن ذلك تصحيح نسبة العرض إلى الارتفاع والمقياس والتدوير.
لطلب السطح من الكائن CameraViewfinder
، عليك:
إنشاء ViewfinderSurfaceRequest
يتضمّن هذا الطلب متطلبات درجة دقة السطح وجهاز الكاميرا.
معلومات واردة من CameraCharacteristics
.
جارٍ الاتصال بالرقم requestSurfaceAsync()
يرسل الطلب إلى موفّر مساحة العرض، وهو إما TextureView
أو
SurfaceView
ويحصل على ListenableFuture
مقابل Surface
.
جارٍ الاتصال بالرقم markSurfaceSafeToRelease()
إلى موفّر مساحة العرض أنّ السطح غير ضروري ذا صلة
من الموارد.
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)) }
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()
متوفر في
التدوير النسبي أدناه).
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) }
@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
TextureView
أقل أداءً من
SurfaceView
والمزيد من العمل، إلا أنّ TextureView
يمنحك الحد الأقصى
التحكم في معاينة الكاميرا.
TextureView
تُدير وحدة تخزين مؤقت لصور المستشعر استنادًا إلى اتجاه المستشعر، ولكنها
لا تتعامل مع تدوير الجهاز أو تغيير حجم المعاينة.
يمكن ترميز عمليات التكبير والتصغير والدوران في عملية تحويل
مصفوفة. للتعرّف على كيفية
تغيير حجم TextureView
وتدويره بشكل صحيح، راجع
إتاحة الأسطح التي يمكن تغيير حجمها في تطبيق الكاميرا
التدوير النسبي
التدوير النسبي لأداة استشعار الكاميرا هي مقدار التدوير المطلوب محاذاة مخرجات أداة استشعار الكاميرا مع اتجاه الجهاز
يتم استخدام التدوير النسبي بواسطة مكونات مثل SurfaceView
وTextureView
لتحديد عاملي التحجيم x وy لصورة المعاينة. ويُستخدَم أيضًا لتحديد دوران مخزن مؤقت لصورة أداة الاستشعار.
تتيح فئتَا
CameraCharacteristics
و
Surface
احتساب الزاوية النسبية للدوران في
أداة استشعار الكاميرا:
/** * 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 }
/** * 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()
معاودة الاتصال.
المراجع الحصرية
قبل الإصدار 10 من Android، كان النشاط المرئي في أعلى الشاشة فقط في بيئة النوافذ المتعدّدة
في حالة RESUMED
. كان هذا مربكًا للمستخدمين لأن
لم يقدم النظام أي إشارة إلى النشاط الذي تم استئنافه.
طرح نظام التشغيل Android 10 (المستوى 29 من واجهة برمجة التطبيقات) ميزة "استئناف التطبيقات المتعدّدة" التي تكون فيها جميع الأنشطة المرئية
في الحالة RESUMED
. يمكن أن تنتقل الأنشطة المرئية إلى الحالة PAUSED
إذا كان هناك نشاط شفاف فوق النشاط أو
إذا كان النشاط لا يمكن التركيز عليه، مثل وضع "نافذة ضمن النافذة" (راجِع
إتاحة وضع "نافذة ضمن النافذة").
يجب أن يتيح التطبيق الذي يستخدم الكاميرا أو الميكروفون أو أي مورد حصري أو
وحيد على مستوى واجهة برمجة التطبيقات 29 أو إصدار أحدث ميزة "استئناف التطبيقات المتعددة". بالنسبة
على سبيل المثال، إذا أرادت ثلاثة أنشطة تم استئنافها استخدام الكاميرا، فلا يمكن إلا إجراء واحد
للوصول إلى هذا المورد الحصري. يجب أن ينفِّذ كل نشاط callback
onDisconnected()
للتأكّد من الوصول المُسبَق إلى الكاميرا من خلال نشاط
ذو أولوية أعلى.
لمزيد من المعلومات، يُرجى مراجعة السير الذاتية المتعددة:
مصادر إضافية
- للحصول على نموذج Camera2، يُرجى الاطّلاع على تطبيق Camera2Basic على GitHub.
- للتعرّف على حالة استخدام معاينة CameraX، يمكنك الاطّلاع على CameraX. تنفيذ معاينة.
- للحصول على نموذج لتنفيذ معاينة الكاميرا في CameraX، يُرجى الاطّلاع على مستودع CameraXBasic على GitHub.
- للحصول على معلومات عن معاينة الكاميرا على ChromeOS، يُرجى الاطّلاع على مقالة اتجاهات الكاميرا.
- للحصول على معلومات حول تطوير التطبيقات للأجهزة القابلة للطي، يُرجى الاطّلاع على مزيد من المعلومات حول الهواتف القابلة للطي