يتيح إطار عمل Android استخدام العديد من الكاميرات وميزات الكاميرا المتاحة على الأجهزة، مما يتيح لك التقاط صور ومقاطع فيديو في تطبيقاتك. يتناول هذا المستند أسلوبًا سريعًا وبسيطًا لالتقاط الصور والفيديوهات، ويوضّح أسلوبًا متقدّمًا لإنشاء تجارب مخصّصة للكاميرا للمستخدمين.
ملاحظة:
توضِّح هذه الصفحة فئة
Camera
التي تم إيقافها نهائيًا. ننصح باستخدام
مكتبة cameraX في Jetpack، أو في حالات استخدام معيّنة
camera2
,
الصف. يعمل كلّ من CameraX وCamera2 على الإصدار 5.0 من نظام التشغيل Android (المستوى 21 لواجهة برمجة التطبيقات) والإصدارات الأحدث.
يُرجى الرجوع إلى المراجع ذات الصلة التالية:
الاعتبارات
قبل تمكين تطبيقك من استخدام الكاميرات على أجهزة Android، يجب مراعاة بعض أسئلة حول الطريقة التي سيستخدم بها تطبيقك ميزة الأجهزة هذه.
- متطلبات الكاميرا - هل استخدام كاميرا مهم جدًا بالنسبة إلى تطبيق لا تريده أن يكون تطبيقك مثبّتًا على جهاز لا يحتوي على الكاميرا؟ إذا كان الأمر كذلك، عليك الإفصاح عن متطلّبات الكاميرا في ملف البيان.
- صورة سريعة أو كاميرا مخصّصة - كيف سيستخدم تطبيقك الكاميرا؟ هل تريد فقط التقاط صورة سريعة أو مقطع فيديو، أم سيقدّم تطبيقك طريقة جديدة لاستخدام الكاميرات؟ لالتقاط لقطة سريعة أو مقطع، ننصحك استخدام تطبيقات الكاميرا الحالية لتطوير ميزة مخصّصة في الكاميرا، اطّلِع على قسم إنشاء تطبيق كاميرا.
- متطلّبات الخدمات التي تعمل في المقدّمة: متى يتفاعل تطبيقك مع الكاميرا؟ في الإصدار 9 من Android (المستوى 28 لواجهة برمجة التطبيقات) والإصدارات الأحدث، لا يمكن للتطبيقات التي تعمل في الخلفية الوصول إلى الكاميرا. لذلك، يجب استخدام الكاميرا إما عندما يكون تطبيقك في المقدّمة أو كجزء من خدمة تعمل في المقدّمة.
- التخزين - هل الصور أو مقاطع الفيديو التي ينشئها تطبيقك مخصصة لتكون مرئية فقط للتطبيق أو المشاركة حتى تتمكن التطبيقات الأخرى مثل المعرض أو والوسائط والتطبيقات الاجتماعية يمكنها استخدامها؟ هل تريد أن تكون الصور والفيديوهات متاحة حتى إذا تمت إزالة التطبيق؟ اطّلِع على قسم حفظ ملفات الوسائط لاطلاع على كيفية تنفيذ هذه الخيارات.
الأساسيات
يتيح إطار عمل Android التقاط الصور والفيديوهات من خلال واجهة برمجة التطبيقات
android.hardware.camera2
أو الكاميرا Intent
. في ما يلي klassen ذات الصلة:
android.hardware.camera2
- هذه الحزمة هي واجهة برمجة التطبيقات الأساسية للتحكّم في كاميرات الأجهزة. ويمكن استخدامه لالتقاط صور أو فيديوهات عند إنشاء تطبيق كاميرا.
Camera
- هذه الفئة هي واجهة برمجة التطبيقات القديمة التي تم إيقافها نهائيًا للتحكّم في كاميرات الأجهزة.
SurfaceView
- يُستخدم هذا الصف لتقديم معاينة مباشرة للكاميرا للمستخدم.
MediaRecorder
- يُستخدَم هذا الصف لتسجيل الفيديو من الكاميرا.
Intent
- يمكن استخدام نوع إجراء القصد
MediaStore.ACTION_IMAGE_CAPTURE
أوMediaStore.ACTION_VIDEO_CAPTURE
لالتقاط صور أو فيديوهات بدون استخدام عنصرCamera
مباشرةً.
بيانات البيان
قبل بدء تطوير تطبيقك باستخدام واجهة برمجة التطبيقات Camera API، يجب التأكّد من أنّ البيان يحتوي على التصاريح المناسبة للسماح باستخدام أجهزة الكاميرا وغيرها من الميزات ذات الصلة.
- إذن الكاميرا - يجب أن يطلب التطبيق إذن استخدام أحد الأجهزة
والكاميرا.
<uses-permission android:name="android.permission.CAMERA" />
ملاحظة: إذا كنت تستخدم الكاميرا من خلال استدعاء تطبيق كاميرا حالي، لا يحتاج تطبيقك إلى طلب هذا الإذن.
- ميزات الكاميرا: يجب أن يوضّح تطبيقك أيضًا استخدام ميزات الكاميرا،
على سبيل المثال:
<uses-feature android:name="android.hardware.camera" />
للحصول على قائمة بميزات الكاميرا، يُرجى الاطّلاع على مرجع ميزات البيان.
تؤدي إضافة ميزات الكاميرا إلى البيان إلى منع Google Play من تثبيت تطبيقك على الأجهزة التي لا تتضمّن كاميرا أو لا تتيح استخدام ميزات الكاميرا التي تحديدها. لمزيد من المعلومات حول استخدام التصفية المستندة إلى الميزات في Google Play، راجع Google التشغيل والفلترة المستندة إلى الميزات:
إذا كان تطبيقك يمكنه استخدام كاميرا أو ميزة كاميرا لعمله بشكل صحيح، ولكن ليس يتطلّب ذلك، عليك تحديد ذلك في ملف البيان عن طريق تضمين السمة
android:required
وضبطها علىfalse
:<uses-feature android:name="android.hardware.camera" android:required="false" />
- إذن التخزين - يمكن لتطبيقك حفظ الصور أو مقاطع الفيديو في
مساحة التخزين الخارجية للجهاز (بطاقة SD) في حال كانت تستهدف Android 10 (المستوى 29 من واجهة برمجة التطبيقات) أو
أقل ويحدد ما يلي في البيان.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- إذن تسجيل الصوت: لتسجيل الصوت أثناء تسجيل الفيديو، يجب أن يطلب
تطبيقك إذن تسجيل الصوت.
<uses-permission android:name="android.permission.RECORD_AUDIO" />
-
إذن تحديد الموقع الجغرافي: في حال وضع التطبيق علامة على الصور مع معلومات الموقع من خلال نظام تحديد المواقع العالمي (GPS)، يجب طلب
ACCESS_FINE_LOCATION
إذن. يُرجى العلم أنّه إذا كان تطبيقك يستهدف الإصدار Android 5.0 (المستوى 21 من واجهة برمجة التطبيقات) أو في الإصدار الأحدث، يجب أيضًا توضيح أنّ تطبيقك يستخدم نظام تحديد المواقع العالمي (GPS) في الجهاز:<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> ... <!-- Needed only if your app targets Android 5.0 (API level 21) or higher. --> <uses-feature android:name="android.hardware.location.gps" />
لمزيد من المعلومات عن الحصول على الموقع الجغرافي للمستخدم، اطّلِع على استراتيجيات الموقع الجغرافي.
استخدام تطبيقات الكاميرا الحالية
هناك طريقة سريعة لتفعيل ميزة التقاط الصور أو الفيديوهات في تطبيقك بدون الكثير من الرموز البرمجية الإضافية، وهي استخدام Intent
لتشغيل تطبيق كاميرا Android حالي.
يمكن الاطّلاع على التفاصيل في الدروس التدريبية.
التقاط صور بسهولة
تسجيل الفيديوهات ببساطة:
إنشاء تطبيق كاميرا
قد يطلب بعض المطوّرين واجهة مستخدم للكاميرا مخصَّصة لمظهر التطبيق أو يوفر ميزات خاصة. يمكن أن توفّر كتابة رمزك الخاص لالتقاط الصور تجربة أكثر إقناعًا للمستخدمين.
ملاحظة: يتناول الدليل التالي واجهة برمجة التطبيقات Camera
القديمة التي تمّ إيقافها نهائيًا. بالنسبة إلى تطبيقات الكاميرا الجديدة أو المتقدّمة، يُنصح باستخدام واجهة برمجة التطبيقات android.hardware.camera2
الجديدة.
في ما يلي الخطوات العامة لإنشاء واجهة كاميرا مخصّصة لتطبيقك:
- رصد الكاميرا والوصول إليها: يمكنك إنشاء رمز للتحقّق من توفّر الكاميرات وطلب الوصول إليها.
- إنشاء صف معاينة: يمكنك إنشاء فئة معاينة للكاميرا تعمل على توسيع نطاق
SurfaceView
وتطبيق واجهةSurfaceHolder
. يعرِض هذا الصف معاينة للصور المباشرة من الكاميرا. - إنشاء تنسيق معاينة: بعد الحصول على فئة معاينة الكاميرا، أنشئ تنسيق عرض يضمّ المعاينة وعناصر التحكّم في واجهة المستخدم التي تريدها.
- إعداد أدوات معالجة الصوت لتسجيل المحتوى: يمكنك ربط المستمعين بواجهتك. عناصر التحكم لبدء التقاط الصورة أو الفيديو استجابةً لإجراءات المستخدم، مثل الضغط على .
- التقاط الملفات وحفظها: يمكنك إعداد الرمز البرمجي لالتقاط الصور أو الفيديوهات وحفظ النتيجة.
- إخلاء الكاميرا: بعد استخدام الكاميرا، يجب أن يُخلي تطبيقك سبيلها بشكل صحيح لاستخدامها من قِبل التطبيقات الأخرى.
إنّ جهاز الكاميرا هو مورد مشترَك يجب إدارته بعناية حتى لا يتعارض تطبيقك مع التطبيقات الأخرى التي قد تريد استخدامه أيضًا. تناقش الأقسام التالية كيفية اكتشاف أجهزة الكاميرا، وكيفية طلب الوصول إلى الكاميرا، وكيفية التقاط صور أو فيديو وكيفية رفع إصبعك عن الكاميرا عند انتهاء التطبيق من استخدامها.
تنبيه: لا تنسَ إطلاق Camera
عن طريق استدعاء Camera.release()
عند
الانتهاء من استخدامه. فإذا لم يفلت التطبيق الكاميرا بشكل صحيح، فسيعمل
وستفشل المحاولات اللاحقة للوصول إلى الكاميرا، بما في ذلك تلك التي يقوم بها تطبيقك الخاص وقد
إلى إيقاف تشغيل تطبيقاتك أو التطبيقات الأخرى.
رصد أجهزة الكاميرا
إذا كان تطبيقك لا يتطلب استخدام كاميرا على وجه التحديد باستخدام بيان البيان، عليك
التحقّق ممّا إذا كانت الكاميرا متاحة أثناء التشغيل. لإجراء هذا الفحص، استخدِم طريقة PackageManager.hasSystemFeature()
، كما هو موضَّح في مثال الرمز أدناه:
Kotlin
/** Check if this device has a camera */ private fun checkCameraHardware(context: Context): Boolean { if (context.packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)) { // this device has a camera return true } else { // no camera on this device return false } }
Java
/** Check if this device has a camera */ private boolean checkCameraHardware(Context context) { if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){ // this device has a camera return true; } else { // no camera on this device return false; } }
يمكن أن تتضمّن أجهزة Android كاميرات متعددة، مثل كاميرا خلفية للتصوير وكاميرا أمامية لمكالمات الفيديو. يتيح لك Android 2.3 (مستوى واجهة برمجة التطبيقات 9) والإصدارات الأحدث التحقق من
عدد الكاميرات المتاحة على أحد الأجهزة باستخدام الطريقة Camera.getNumberOfCameras()
الوصول إلى الكاميرات
إذا عرفت أن الجهاز الذي يعمل عليه التطبيق يحتوي على كاميرا،
يجب طلب الوصول إليها من خلال الحصول على نسخة افتراضية من Camera
(ما لم
هدفًا للوصول إلى الكاميرا).
للوصول إلى الكاميرا الأساسية، استخدِم الطريقة Camera.open()
وتأكَّد من رصد أي استثناءات، كما هو موضّح في الرمز البرمجي أدناه:
Kotlin
/** A safe way to get an instance of the Camera object. */ fun getCameraInstance(): Camera? { return try { Camera.open() // attempt to get a Camera instance } catch (e: Exception) { // Camera is not available (in use or does not exist) null // returns null if camera is unavailable } }
Java
/** A safe way to get an instance of the Camera object. */ public static Camera getCameraInstance(){ Camera c = null; try { c = Camera.open(); // attempt to get a Camera instance } catch (Exception e){ // Camera is not available (in use or does not exist) } return c; // returns null if camera is unavailable }
ملاحظة: تحقَّق دائمًا من الاستثناءات عند استخدام Camera.open()
. تعذّر التحقّق من الاستثناءات إذا كانت الكاميرا مفعّلة
استخدام أو غير موجود إلى إيقاف تشغيل التطبيق بواسطة النظام.
على الأجهزة التي تعمل بالإصدار 2.3 من نظام التشغيل Android (المستوى 9 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث، يمكنك الوصول إلى كاميرات معيّنة باستخدام
Camera.open(int)
. سيستخدم رمز المثال أعلاه
الكاميرا الأولى الخلفية على جهاز يتضمّن أكثر من كاميرا واحدة.
التحقّق من ميزات الكاميرا
بعد الحصول على إذن الوصول إلى كاميرا، يمكنك الحصول على مزيد من المعلومات عن إمكاناتها باستخدام Camera.getParameters()
وفحص Camera.Parameters
الذي تم إرجاعه للاطّلاع على الإمكانات المتاحة. عند استخدام
المستوى 9 من واجهة برمجة التطبيقات أو المستويات الأعلى، استخدِم Camera.getCameraInfo()
لتحديد ما إذا كانت هناك كاميرا في الأمام.
أو في الجهة الخلفية من الجهاز، واتجاه الصورة
إنشاء فئة معاينة
ولكي يتمكن المستخدمون من التقاط صور أو مقاطع فيديو بشكل فعال، يجب أن يكونوا قادرين على رؤية ما كاميرا الجهاز
يرى. فئة معاينة الكاميرا هي فئة SurfaceView
التي يمكنها عرض الصورة المباشرة.
البيانات الواردة من الكاميرا، حتى يتمكن المستخدمون من وضع إطار للصورة أو الفيديو والتقاطها.
يوضح المثال التالي كيفية إنشاء فئة أساسية لمعاينة الكاميرا يمكن
تم تضمينها في تنسيق View
. ينفِّذ هذا الصف SurfaceHolder.Callback
لتسجيل أحداث معاودة الاتصال.
لإنشاء العرض وإتلافه، وهي مطلوبة لتعيين مدخلات معاينة الكاميرا.
Kotlin
/** A basic Camera preview class */ class CameraPreview( context: Context, private val mCamera: Camera ) : SurfaceView(context), SurfaceHolder.Callback { private val mHolder: SurfaceHolder = holder.apply { // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. addCallback(this@CameraPreview) // deprecated setting, but required on Android versions prior to 3.0 setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS) } override fun surfaceCreated(holder: SurfaceHolder) { // The Surface has been created, now tell the camera where to draw the preview. mCamera.apply { try { setPreviewDisplay(holder) startPreview() } catch (e: IOException) { Log.d(TAG, "Error setting camera preview: ${e.message}") } } } override fun surfaceDestroyed(holder: SurfaceHolder) { // empty. Take care of releasing the Camera preview in your activity. } override fun surfaceChanged(holder: SurfaceHolder, format: Int, w: Int, h: Int) { // If your preview can change or rotate, take care of those events here. // Make sure to stop the preview before resizing or reformatting it. if (mHolder.surface == null) { // preview surface does not exist return } // stop preview before making changes try { mCamera.stopPreview() } catch (e: Exception) { // ignore: tried to stop a non-existent preview } // set preview size and make any resize, rotate or // reformatting changes here // start preview with new settings mCamera.apply { try { setPreviewDisplay(mHolder) startPreview() } catch (e: Exception) { Log.d(TAG, "Error starting camera preview: ${e.message}") } } } }
Java
/** A basic Camera preview class */ public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder mHolder; private Camera mCamera; public CameraPreview(Context context, Camera camera) { super(context); mCamera = camera; // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. mHolder = getHolder(); mHolder.addCallback(this); // deprecated setting, but required on Android versions prior to 3.0 mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void surfaceCreated(SurfaceHolder holder) { // The Surface has been created, now tell the camera where to draw the preview. try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); } catch (IOException e) { Log.d(TAG, "Error setting camera preview: " + e.getMessage()); } } public void surfaceDestroyed(SurfaceHolder holder) { // empty. Take care of releasing the Camera preview in your activity. } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // If your preview can change or rotate, take care of those events here. // Make sure to stop the preview before resizing or reformatting it. if (mHolder.getSurface() == null){ // preview surface does not exist return; } // stop preview before making changes try { mCamera.stopPreview(); } catch (Exception e){ // ignore: tried to stop a non-existent preview } // set preview size and make any resize, rotate or // reformatting changes here // start preview with new settings try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch (Exception e){ Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } } }
إذا أردت ضبط حجم معيّن لمعاينة الكاميرا، اضبط هذا الإجراء بالطريقة surfaceChanged()
كما هو موضّح في التعليقات أعلاه. عند ضبط حجم المعاينة، عليك
استخدام القيم من getSupportedPreviewSizes()
.
لا تضبط قيمًا عشوائية باستخدام طريقة setPreviewSize()
.
ملاحظة:
مع طرح ميزة
"وضع المتعدّد النوافذ" في نظام التشغيل Android 7.0 (المستوى 24 من واجهة برمجة التطبيقات) والإصدارات الأحدث، لن تتمكّن مجددًا
من افتراض أنّ نسبة العرض إلى الارتفاع في المعاينة هي نفسها نسبة العرض إلى الارتفاع في نشاطك
حتى بعد استدعاء setDisplayOrientation()
.
قد تحتاج إلى ضبط مقاس عريض حسب حجم النافذة ونسبة العرض إلى الارتفاع.
معاينة الكاميرا إلى تنسيق باتجاه عمودي، أو العكس، باستخدام
تخطيطًا للعرض على شاشة عريضة أفقيًا.
وضع المعاينة في تنسيق
يجب وضع فئة معاينة الكاميرا، مثل المثال الذي يظهر في القسم السابق، في تنسيق النشاط مع عناصر التحكّم الأخرى في واجهة المستخدم لالتقاط صورة أو فيديو. يوضّح لك هذا القسم كيفية إنشاء تنسيق ونشاط أساسيَين للمعاينة.
يوفّر رمز التنسيق التالي عرضًا أساسيًا جدًا يمكن استخدامه لعرض ملف شخصي كاميرا
. في هذا المثال، يُفترض أن يكون العنصر FrameLayout
هو
الحاوية لفئة معاينة الكاميرا. يُستخدَم هذا النوع من التنسيقات لكي تتمكّن من إضافة معلومات أو عناصر تحكّم إضافية على صور معاينة الكاميرا المباشرة.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" > <FrameLayout android:id="@+id/camera_preview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" /> <Button android:id="@+id/button_capture" android:text="Capture" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" /> </LinearLayout>
في معظم الأجهزة، يكون الوضع التلقائي لمعاينة الكاميرا هو الوضع الأفقي. يحدِّد مثال التنسيق هذا تنسيقًا أفقيًا (عموديًا) ويضبط الرمز البرمجي أدناه اتجاه التطبيق على الوضع الأفقي. لتبسيط عرض معاينة الكاميرا، عليك تغيير اتجاه نشاط معاينة التطبيق إلى الوضع الأفقي من خلال إضافة ما يلي إلىملف بيان التطبيق.
<activity android:name=".CameraActivity" android:label="@string/app_name" android:screenOrientation="landscape"> <!-- configure this activity to use landscape orientation --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
ملاحظة: ليس من الضروري أن تكون معاينة الكاميرا في الوضع الأفقي.
بدءًا من الإصدار 2.2 من Android (المستوى 8 من واجهة برمجة التطبيقات)، يمكنك استخدام طريقة setDisplayOrientation()
لضبط
تدوير صورة المعاينة. من أجل تغيير اتجاه المعاينة عندما يعيد المستخدم توجيه
في الهاتف، ضمن طريقة surfaceChanged()
في صف المعاينة، أوقِف أولاً المعاينة مع تغيير الاتجاه باستخدام Camera.stopPreview()
، ثم
بدء المعاينة مرة أخرى باستخدام Camera.startPreview()
.
في نشاط عرض الكاميرا، أضِف فئة المعاينة إلى عنصر FrameLayout
المعروض في المثال أعلاه. يجب أن يضمن نشاط الكاميرا أيضًا
إلغاء إذن الوصول إلى الكاميرا عند إيقافها مؤقتًا أو إغلاقها. يوضح المثال التالي كيف
تعديل نشاط الكاميرا لإرفاق فئة المعاينة المعروضة في قسم إنشاء
صف معاينة.
Kotlin
class CameraActivity : Activity() { private var mCamera: Camera? = null private var mPreview: CameraPreview? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Create an instance of Camera mCamera = getCameraInstance() mPreview = mCamera?.let { // Create our Preview view CameraPreview(this, it) } // Set the Preview view as the content of our activity. mPreview?.also { val preview: FrameLayout = findViewById(R.id.camera_preview) preview.addView(it) } } }
Java
public class CameraActivity extends Activity { private Camera mCamera; private CameraPreview mPreview; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Create an instance of Camera mCamera = getCameraInstance(); // Create our Preview view and set it as the content of our activity. mPreview = new CameraPreview(this, mCamera); FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); preview.addView(mPreview); } }
ملاحظة: طريقة getCameraInstance()
في المثال أعلاه
إلى مثال الطريقة الموضحة في الوصول إلى الكاميرات.
جارٍ التقاط الصور
بعد إنشاء فئة معاينة وتنسيق عرض لعرضها، ستكون مستعدًا لبدء التقاط الصور باستخدام تطبيقك. في رمز التطبيق، عليك إعداد أدوات معالجة الأحداث لعناصر التحكم في واجهة المستخدم للاستجابة إلى إجراء المستخدم من خلال التقاط صورة.
لاسترداد صورة، استخدِم الطريقة Camera.takePicture()
. تأخذ هذه الطريقة ثلاث مَعلمات تتلقّى البيانات من الكاميرا.
لتلقّي بيانات بتنسيق JPEG، يجب تنفيذ واجهة Camera.PictureCallback
لتلقّي بيانات الصورة
وكتابته إلى ملف. يوضّح الرمز التالي تنفيذًا أساسيًا لواجهة Camera.PictureCallback
لحفظ صورة تم استلامها من الكاميرا.
Kotlin
private val mPicture = Camera.PictureCallback { data, _ -> val pictureFile: File = getOutputMediaFile(MEDIA_TYPE_IMAGE) ?: run { Log.d(TAG, ("Error creating media file, check storage permissions")) return@PictureCallback } try { val fos = FileOutputStream(pictureFile) fos.write(data) fos.close() } catch (e: FileNotFoundException) { Log.d(TAG, "File not found: ${e.message}") } catch (e: IOException) { Log.d(TAG, "Error accessing file: ${e.message}") } }
Java
private PictureCallback mPicture = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE); if (pictureFile == null){ Log.d(TAG, "Error creating media file, check storage permissions"); return; } try { FileOutputStream fos = new FileOutputStream(pictureFile); fos.write(data); fos.close(); } catch (FileNotFoundException e) { Log.d(TAG, "File not found: " + e.getMessage()); } catch (IOException e) { Log.d(TAG, "Error accessing file: " + e.getMessage()); } } };
يمكنك بدء التقاط صورة من خلال استدعاء طريقة Camera.takePicture()
. يعرض الرمز البرمجي التالي كيفية استدعاء هذه الطريقة من زر
View.OnClickListener
.
Kotlin
val captureButton: Button = findViewById(R.id.button_capture) captureButton.setOnClickListener { // get an image from the camera mCamera?.takePicture(null, null, picture) }
Java
// Add a listener to the Capture button Button captureButton = (Button) findViewById(R.id.button_capture); captureButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { // get an image from the camera mCamera.takePicture(null, null, picture); } } );
ملاحظة: يشير العضو mPicture
في المثال التالي إلى
إلى رمز المثال أعلاه.
تحذير: تذكَّر تحرير Camera
العنصر من خلال استدعاء Camera.release()
عند انتهاء
تطبيقك من استخدامه. للحصول على معلومات حول كيفية رفع إصبعك عن الكاميرا، راجِع تحرير الكاميرا.
تسجيل الفيديوهات
يتطلّب تسجيل الفيديو باستخدام إطار عمل Android إدارةً دقيقةً لعنصر Camera
والتنسيق مع فئة MediaRecorder
. عند تسجيل فيديو باستخدام Camera
، عليك إدارة المكالمتَين Camera.lock()
وCamera.unlock()
للسماح بوصول "MediaRecorder
" إلى جهاز الكاميرا.
بالإضافة إلى مكالمات Camera.open()
وCamera.release()
.
ملاحظة: اعتبارًا من الإصدار 4.0 من Android (المستوى 14 من واجهة برمجة التطبيقات)، تتم إدارة المكالمات الواردة من Camera.lock()
وCamera.unlock()
تلقائيًا.
على عكس التقاط الصور باستخدام كاميرا الجهاز، يتطلب التقاط الفيديو مكالمة خاصة جدًا طلبك. يجب اتّباع ترتيب تنفيذ معيّن للاستعداد لتسجيل الفيديو باستخدام تطبيقك بنجاح، كما هو موضّح أدناه.
- فتح الكاميرا - استخدام
Camera.open()
للحصول على مثيل لكائن الكاميرا. - معاينة الربط - يمكنك إعداد معاينة مباشرة لصورة الكاميرا من خلال توصيل
SurfaceView
بالكاميرا باستخدامCamera.setPreviewDisplay()
. - بدء المعاينة: اتصل برقم
Camera.startPreview()
لبدء عرض صور الكاميرا المباشرة. - بدء تسجيل الفيديو: يجب إكمال الخطوات التالية بترتيبٍ معيّن لتسجيل الفيديو بنجاح:
- فتح قفل الكاميرا - يجب فتح قفل الكاميرا لاستخدامها مع
MediaRecorder
من خلال الاتصال على الرقمCamera.unlock()
. - ضبط MediaRecorder: استخدِم
MediaRecorder
طريقة من الطرق التالية بالترتيب التالي. لمزيد من المعلومات، اطّلِع على مستنداتMediaRecorder
المرجعية.setCamera()
- يمكنك ضبط الكاميرا لاستخدامها في التقاط الفيديو، واستخدام المثيل الحالي لتطبيقك منCamera
.setAudioSource()
- ضبط مصدر الصوت، استخدِمMediaRecorder.AudioSource.CAMCORDER
.setVideoSource()
- تم الضبط مصدر الفيديو، استخدِمMediaRecorder.VideoSource.CAMERA
.- ضبط تنسيق إخراج الفيديو وترميزه لأجهزة Android 2.2 (مستوى واجهة برمجة التطبيقات 8)
الأعلى، استخدم الطريقة
MediaRecorder.setProfile
، واحصل على مثيل للملف الشخصي باستخدامCamcorderProfile.get()
. بالنسبة إلى إصدارات Android الأقدم من 2.2، عليك ضبط تنسيق إخراج الفيديو ومَعلمات التشفير:setOutputFormat()
- اضبط تنسيق الإخراج، أو حدِّد الإعداد التلقائي، أو انقر علىMediaRecorder.OutputFormat.MPEG_4
.setAudioEncoder()
- تم الضبط نوع ترميز الصوت، حدّد الإعداد التلقائي أوMediaRecorder.AudioEncoder.AMR_NB
.setVideoEncoder()
- اضبط نوع ترميز الفيديو، وحدِّد الإعداد التلقائي أوMediaRecorder.VideoEncoder.MPEG_4_SP
.
setOutputFile()
- اضبط ملف الإخراج، واستخدِمgetOutputMediaFile(MEDIA_TYPE_VIDEO).toString()
من المثال في القسم حفظ ملفات الوسائط.setPreviewDisplay()
- حدِّد عنصرSurfaceView
تنسيق المعاينة لتطبيقك. استخدِم العنصر نفسه الذي حدّدته في Connect Preview (معاينة الربط).
ملاحظة: يجب استدعاء طرق ضبط
MediaRecorder
هذه بالترتيب التالي، وإلا سيواجه تطبيقك أخطاء ولن يتم التسجيل. - إعداد MediaRecorder - إعداد
MediaRecorder
مع تقديم إعدادات الضبط من خلال طلبMediaRecorder.prepare()
. - بدء MediaRecorder: لبدء تسجيل الفيديو من خلال الاتصال بالرقم
MediaRecorder.start()
- فتح قفل الكاميرا - يجب فتح قفل الكاميرا لاستخدامها مع
- إيقاف تسجيل الفيديو - يمكنك استدعاء الطرق التالية بالترتيب، من أجل
إكمال تسجيل الفيديو بنجاح:
- إيقاف MediaRecorder: لإيقاف تسجيل الفيديو من خلال الاتصال بـ
MediaRecorder.stop()
- إعادة ضبط MediaRecorder: يمكنك اختياريًا إزالة إعدادات الضبط من
الجهاز المسجِّل من خلال الاتصال بالرقم
MediaRecorder.reset()
. - إصدار MediaRecorder: ارفع إصبعك عن
MediaRecorder
من خلال الاتصال بـMediaRecorder.release()
. - قفل الكاميرا: يمكنك قفل الكاميرا لكي تتمكّن جلسات
MediaRecorder
المستقبلية من استخدامها من خلال الاتصال بالرقمCamera.lock()
. بدءًا من Android 4.0 (المستوى 14 من واجهة برمجة التطبيقات)، لن تكون هذه المكالمة مطلوبة ما لم تعذّر الاتصال بـMediaRecorder.prepare()
.
- إيقاف MediaRecorder: لإيقاف تسجيل الفيديو من خلال الاتصال بـ
- إيقاف المعاينة: عند الانتهاء من استخدام الكاميرا، يمكنك إيقاف
المعاينة باستخدام
Camera.stopPreview()
. - إطلاق الكاميرا - ارفع إصبعك عن الكاميرا حتى تتمكن التطبيقات الأخرى من استخدامها
عن طريق الاتصال بـ
Camera.release()
.
ملاحظة: من الممكن استخدام MediaRecorder
بدون إنشاء معاينة للكاميرا أولاً وتخطّي الخطوات القليلة الأولى من هذه العملية. ومع ذلك،
بما أنّ المستخدمين يفضّلون عادةً الاطّلاع على معاينة قبل بدء التسجيل، لن تتم مناقشة هذه العملية
هنا.
ملاحظة: إذا كان تطبيقك يُستخدَم عادةً لتسجيل الفيديو، اضبط الإعداد
setRecordingHint(boolean)
على true
قبل بدء
المعاينة. يمكن أن يساعد هذا الإعداد في تقليل الوقت المستغرَق لبدء التسجيل.
تكوين MediaRecorder
عند استخدام فئة MediaRecorder
لتسجيل الفيديو، عليك تنفيذ خطوات الإعداد بترتيب معيّن ثم استدعاء طريقة MediaRecorder.prepare()
للتحقّق من الإعداد وتنفيذه. يوضّح مثال الرمز البرمجي التالي كيفية ضبط فئة
MediaRecorder
وإعدادها بشكلٍ سليم لتسجيل الفيديو.
Kotlin
private fun prepareVideoRecorder(): Boolean { mediaRecorder = MediaRecorder() mCamera?.let { camera -> // Step 1: Unlock and set camera to MediaRecorder camera?.unlock() mediaRecorder?.run { setCamera(camera) // Step 2: Set sources setAudioSource(MediaRecorder.AudioSource.CAMCORDER) setVideoSource(MediaRecorder.VideoSource.CAMERA) // Step 3: Set a CamcorderProfile (requires API Level 8 or higher) setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)) // Step 4: Set output file setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()) // Step 5: Set the preview output setPreviewDisplay(mPreview?.holder?.surface) setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT) setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT) // Step 6: Prepare configured MediaRecorder return try { prepare() true } catch (e: IllegalStateException) { Log.d(TAG, "IllegalStateException preparing MediaRecorder: ${e.message}") releaseMediaRecorder() false } catch (e: IOException) { Log.d(TAG, "IOException preparing MediaRecorder: ${e.message}") releaseMediaRecorder() false } } } return false }
Java
private boolean prepareVideoRecorder(){ mCamera = getCameraInstance(); mediaRecorder = new MediaRecorder(); // Step 1: Unlock and set camera to MediaRecorder mCamera.unlock(); mediaRecorder.setCamera(mCamera); // Step 2: Set sources mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // Step 3: Set a CamcorderProfile (requires API Level 8 or higher) mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)); // Step 4: Set output file mediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()); // Step 5: Set the preview output mediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface()); // Step 6: Prepare configured MediaRecorder try { mediaRecorder.prepare(); } catch (IllegalStateException e) { Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage()); releaseMediaRecorder(); return false; } catch (IOException e) { Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage()); releaseMediaRecorder(); return false; } return true; }
قبل الإصدار 2.2 من Android (مستوى واجهة برمجة التطبيقات 8)، عليك ضبط تنسيق الناتج وتنسيقات الترميز.
مباشرة، بدلاً من استخدام CamcorderProfile
. هذا النهج
كما هو موضح في التعليمة البرمجية التالية:
Kotlin
// Step 3: Set output format and encoding (for versions prior to API Level 8) mediaRecorder?.apply { setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT) setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT) }
Java
// Step 3: Set output format and encoding (for versions prior to API Level 8) mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
في ما يلي مَعلمات تسجيل الفيديو التالية لجهاز MediaRecorder
، وهي تمثل الإعدادات default (تلقائية)، ولكن قد تحتاج إلى تعديل هذه الإعدادات لتطبيقك:
setVideoEncodingBitRate()
setVideoSize()
setVideoFrameRate()
setAudioEncodingBitRate()
setAudioChannels()
setAudioSamplingRate()
بدء تشغيل MediaRecorder وإيقافه
عند بدء تسجيل الفيديو وإيقافه باستخدام الصف MediaRecorder
،
يجب اتباع ترتيب معين كما هو موضح أدناه.
- فتح قفل الكاميرا باستخدام
Camera.unlock()
- اضبط
MediaRecorder
كما هو موضّح في مثال الرمز أعلاه. - بدء التسجيل باستخدام "
MediaRecorder.start()
" - تسجيل الفيديو
- إيقاف التسجيل باستخدام "
MediaRecorder.stop()
" - إزالة "مسجّلة الوسائط" باستخدام
MediaRecorder.release()
- قفل الكاميرا باستخدام
Camera.lock()
يوضّح مثال الرمز البرمجي التالي كيفية ربط زر لبدء تسجيل الفيديو وإيقافه بشكلٍ سليم باستخدام الكاميرا وفئته MediaRecorder
.
ملاحظة: عند إكمال تسجيل فيديو، لا ترفع إصبعك عن الكاميرا وإلا سيتم إيقاف المعاينة.
Kotlin
var isRecording = false val captureButton: Button = findViewById(R.id.button_capture) captureButton.setOnClickListener { if (isRecording) { // stop recording and release camera mediaRecorder?.stop() // stop the recording releaseMediaRecorder() // release the MediaRecorder object mCamera?.lock() // take camera access back from MediaRecorder // inform the user that recording has stopped setCaptureButtonText("Capture") isRecording = false } else { // initialize video camera if (prepareVideoRecorder()) { // Camera is available and unlocked, MediaRecorder is prepared, // now you can start recording mediaRecorder?.start() // inform the user that recording has started setCaptureButtonText("Stop") isRecording = true } else { // prepare didn't work, release the camera releaseMediaRecorder() // inform user } } }
Java
private boolean isRecording = false; // Add a listener to the Capture button Button captureButton = (Button) findViewById(id.button_capture); captureButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { if (isRecording) { // stop recording and release camera mediaRecorder.stop(); // stop the recording releaseMediaRecorder(); // release the MediaRecorder object mCamera.lock(); // take camera access back from MediaRecorder // inform the user that recording has stopped setCaptureButtonText("Capture"); isRecording = false; } else { // initialize video camera if (prepareVideoRecorder()) { // Camera is available and unlocked, MediaRecorder is prepared, // now you can start recording mediaRecorder.start(); // inform the user that recording has started setCaptureButtonText("Stop"); isRecording = true; } else { // prepare didn't work, release the camera releaseMediaRecorder(); // inform user } } } } );
ملاحظة: في المثال أعلاه، تشير الطريقة prepareVideoRecorder()
إلى مثال الرمز المعروض في ضبط MediaRecorder. تتولى هذه الطريقة قفل
الكاميرا وضبط مثيل MediaRecorder
وإعداده.
إزالة الكاميرا
الكاميرات هي مورد تشاركه التطبيقات على أحد الأجهزة. يمكن أن يُجري تطبيقك
استخدام الكاميرا بعد الحصول على نسخة افتراضية من "Camera
"، ويجب أن تكون
حرصًا على وجه الخصوص لتحرير كائن الكاميرا عند توقف التطبيق عن استخدامه،
فور إيقاف تطبيقك مؤقتًا (Activity.onPause()
). في حال حذف
عدم رفع التطبيق عن الكاميرا بشكل صحيح أو عدم وصول كل المحاولات اللاحقة إلى الوصول إلى الكاميرا
فإن تضمين تلك السياسات في تطبيقك الخاص سيفشل وقد يتسبب في تعطيل
إيقاف التشغيل.
لإصدار مثيل للكائن Camera
، استخدِم الطريقة Camera.release()
كما هو موضَّح في مثال الرمز أدناه.
Kotlin
class CameraActivity : Activity() { private var mCamera: Camera? private var preview: SurfaceView? private var mediaRecorder: MediaRecorder? override fun onPause() { super.onPause() releaseMediaRecorder() // if you are using MediaRecorder, release it first releaseCamera() // release the camera immediately on pause event } private fun releaseMediaRecorder() { mediaRecorder?.reset() // clear recorder configuration mediaRecorder?.release() // release the recorder object mediaRecorder = null mCamera?.lock() // lock camera for later use } private fun releaseCamera() { mCamera?.release() // release the camera for other applications mCamera = null } }
Java
public class CameraActivity extends Activity { private Camera mCamera; private SurfaceView preview; private MediaRecorder mediaRecorder; ... @Override protected void onPause() { super.onPause(); releaseMediaRecorder(); // if you are using MediaRecorder, release it first releaseCamera(); // release the camera immediately on pause event } private void releaseMediaRecorder(){ if (mediaRecorder != null) { mediaRecorder.reset(); // clear recorder configuration mediaRecorder.release(); // release the recorder object mediaRecorder = null; mCamera.lock(); // lock camera for later use } } private void releaseCamera(){ if (mCamera != null){ mCamera.release(); // release the camera for other applications mCamera = null; } } }
تحذير: إذا لم يُغلق تطبيقك الكاميرا بشكلٍ صحيح، ستتعذّر كل المحاولات اللاحقة للوصول إلى الكاميرا، بما في ذلك المحاولات التي يجريها تطبيقك، وقد يؤدي ذلك إلى إغلاق تطبيقك أو التطبيقات الأخرى.
حفظ ملفات الوسائط
يجب حفظ ملفات الوسائط التي أنشأها المستخدمون مثل الصور والفيديوهات على وحدة خارجية دليل التخزين (بطاقة SD) لتوفير مساحة النظام والسماح للمستخدمين بالوصول إلى هذه الملفات بدون أجهزته. هناك العديد من مواقع الدليل المحتملة لحفظ ملفات الوسائط على الجهاز، مع ذلك، هناك فقط موقعان جغرافيان عاديان عليك اعتبارهما مطوِّرًا:
-
Environment.getExternalStoragePublicDirectory
(Environment.DIRECTORY_PICTURES
): تعرض هذه الطريقة الموقع الجغرافي العادي والمشترَك والمُقترَح لحفظ الصور والفيديوهات. تمت مشاركة هذا الدليل (عام)، لذا فإن التطبيقات الأخرى يمكنه بسهولة اكتشاف الملفات المحفوظة في هذا الموقع وقراءتها وتغييرها وحذفها. إذا أزال المستخدم تطبيقك، لن تتم إزالة ملفات الوسائط المحفوظة في هذا الموقع. لتجنُّب يتداخل مع الصور ومقاطع الفيديو الحالية للمستخدمين، فيجب عليك إنشاء دليل فرعي لملفات وسائط التطبيق داخل هذا الدليل، كما هو موضح في نموذج التعليمات البرمجية أدناه. تتوفّر هذه الطريقة في Android 2.2 (المستوى 8 من واجهة برمجة التطبيقات). للحصول على طلبات البيانات المماثلة في إصدارات واجهة برمجة التطبيقات الأقدم، يُرجى الاطّلاع على مقالة حفظ الملفات المشتركة. Context.getExternalFilesDir
(Environment.DIRECTORY_PICTURES
) - تعرض هذه الطريقة موقعًا عاديًا للحفظ الصور ومقاطع الفيديو المرتبطة بالتطبيق. إذا تم إلغاء تثبيت تطبيقك، أي ملفات محفوظة في هذا الموقع تتم إزالتها. لا يتم فرض الأمان على الملفات في هذا الموقع، وقد تقرأ التطبيقات الأخرى هذه الملفات وتغيرها وتحذفها.
يوضّح مثال الرمز البرمجي التالي كيفية إنشاء موقع File
أو Uri
لملف وسائط يمكن استخدامه عند استدعاء كاميرا الجهاز باستخدام Intent
أو كجزء من إنشاء
تطبيق كاميرا.
Kotlin
val MEDIA_TYPE_IMAGE = 1 val MEDIA_TYPE_VIDEO = 2 /** Create a file Uri for saving an image or video */ private fun getOutputMediaFileUri(type: Int): Uri { return Uri.fromFile(getOutputMediaFile(type)) } /** Create a File for saving an image or video */ private fun getOutputMediaFile(type: Int): File? { // To be safe, you should check that the SDCard is mounted // using Environment.getExternalStorageState() before doing this. val mediaStorageDir = File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyCameraApp" ) // This location works best if you want the created images to be shared // between applications and persist after your app has been uninstalled. // Create the storage directory if it does not exist mediaStorageDir.apply { if (!exists()) { if (!mkdirs()) { Log.d("MyCameraApp", "failed to create directory") return null } } } // Create a media file name val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date()) return when (type) { MEDIA_TYPE_IMAGE -> { File("${mediaStorageDir.path}${File.separator}IMG_$timeStamp.jpg") } MEDIA_TYPE_VIDEO -> { File("${mediaStorageDir.path}${File.separator}VID_$timeStamp.mp4") } else -> null } }
Java
public static final int MEDIA_TYPE_IMAGE = 1; public static final int MEDIA_TYPE_VIDEO = 2; /** Create a file Uri for saving an image or video */ private static Uri getOutputMediaFileUri(int type){ return Uri.fromFile(getOutputMediaFile(type)); } /** Create a File for saving an image or video */ private static File getOutputMediaFile(int type){ // To be safe, you should check that the SDCard is mounted // using Environment.getExternalStorageState() before doing this. File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES), "MyCameraApp"); // This location works best if you want the created images to be shared // between applications and persist after your app has been uninstalled. // Create the storage directory if it does not exist if (! mediaStorageDir.exists()){ if (! mediaStorageDir.mkdirs()){ Log.d("MyCameraApp", "failed to create directory"); return null; } } // Create a media file name String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); File mediaFile; if (type == MEDIA_TYPE_IMAGE){ mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_"+ timeStamp + ".jpg"); } else if(type == MEDIA_TYPE_VIDEO) { mediaFile = new File(mediaStorageDir.getPath() + File.separator + "VID_"+ timeStamp + ".mp4"); } else { return null; } return mediaFile; }
ملاحظة: تتوفّر Environment.getExternalStoragePublicDirectory()
في الإصدار 2.2 من نظام التشغيل Android (المستوى 8 من واجهة برمجة التطبيقات) أو
الإصدارات الأحدث. إذا كنت تستهدف أجهزة تعمل بإصدارات سابقة من Android، استخدِم Environment.getExternalStorageDirectory()
.
بدلاً من ذلك. لمزيد من المعلومات، راجع حفظ الملفات المشتركة.
لجعل معرِّف الموارد المنتظم (URI) متوافقًا مع ملفات العمل، عليك أولاً
تحويل معرّف الموارد المنتظم (URI) الخاص بالملف إلى معرّف موارد منتظم (URI) للمحتوى بعد ذلك، أضِف معرّف الموارد المنتظم للمحتوى إلى EXTRA_OUTPUT
Intent
.
لمزيد من المعلومات حول حفظ الملفات على جهاز Android، يُرجى الاطّلاع على تخزين البيانات.
ميزات الكاميرا
يتيح Android مجموعة كبيرة من ميزات الكاميرا التي يمكنك التحكّم فيها من خلال تطبيق الكاميرا،
مثل تنسيق الصورة ووضع الفلاش وإعدادات التركيز وغير ذلك الكثير. يسرد هذا القسم ميزات الكاميرا
الشائعة، ويناقش بإيجاز كيفية استخدامها. يمكن الوصول إلى معظم ميزات الكاميرا وضبط إعداداتها.
باستخدام الكائن Camera.Parameters
. ومع ذلك، هناك عدة
ميزات مهمة تتطلّب أكثر من إعدادات بسيطة في Camera.Parameters
. يتم تناول هذه الميزات في الأقسام التالية:
للحصول على معلومات عامة عن كيفية استخدام الميزات التي يتم التحكّم فيها من خلال Camera.Parameters
، راجِع مقالة استخدام الكاميرا.
الميزات. للحصول على معلومات أكثر تفصيلاً حول كيفية استخدام الميزات التي يتم التحكّم فيها من خلال ملف تعريف
مَعلمات الكاميرا، اتّبِع الروابط في قائمة الميزات أدناه للوصول إلى مستندات مرجع واجهة برمجة التطبيقات
.
الجدول 1. ميزات الكاميرا الشائعة مُرتَّبة حسب مستوى واجهة برمجة التطبيقات لنظام التشغيل Android الذي تم طرحها فيه
الميزة | مستوى واجهة برمجة التطبيقات | الوصف |
---|---|---|
التعرّف على الوجوه | 14 | التعرّف على وجوه الأشخاص في الصورة واستخدامها لضبط التركيز والقياس والتوازن الأبيض |
مناطق القياس | 14 | تحديد منطقة واحدة أو أكثر ضمن صورة لاحتساب توازن اللون الأبيض |
المجالات التي نركز عليها | 14 | اضبط منطقة واحدة أو أكثر داخل الصورة لاستخدامها للتركيز. |
White Balance Lock |
14 | إيقاف أو بدء التعديلات التلقائية لتوازن اللون الأبيض |
Exposure Lock |
14 | إيقاف التعديلات التلقائية للتعرّض للضوء أو تفعيلها |
Video Snapshot |
14 | التقاط صورة أثناء تصوير فيديو (التقاط اللقطات) |
فيديو في وضع "التسريع الزمني" | 11 | تسجيل اللقطات مع تأخيرات محدّدة لتسجيل فيديو في وضع "التسريع الزمني" |
Multiple Cameras |
9 | دعم أكثر من كاميرا واحدة على الجهاز، بما في ذلك الكاميرات الأمامية والخلفية الكاميرات |
Focus Distance |
9 | يُبلغ هذا الإعداد عن المسافات بين الكاميرا والعناصر التي تبدو كما لو كانت محل التركيز. |
Zoom |
8 | ضبط مستوى تكبير الصورة |
Exposure
Compensation |
8 | زيادة مستوى التعرّض للضوء أو خفضه |
GPS Data |
5 | تضمين بيانات الموقع الجغرافي مع الصورة أو حذفها |
White Balance |
5 | يمكنك ضبط وضع موازنة اللون الأبيض، ما يؤثر في قيم الألوان في الصورة التي تم التقاطها. |
Focus Mode |
5 | ضبط كيفية تركيز الكاميرا على موضوع معيّن، مثل التركيز التلقائي أو الثابت أو الفائق أو التركيز على مسافة غير محدودة |
Scene Mode |
5 | تطبيق وضع مُعدّ مسبقًا لأنواع معيّنة من حالات التصوير، مثل الليل أو الشاطئ أو الثلج أو مشاهد الإضاءة الشمعية |
JPEG Quality |
5 | ضبط مستوى الضغط لصورة JPEG، ما يؤدي إلى زيادة أو خفض جودة ملف ناتج الصورة وحجمه |
Flash Mode |
5 | تفعيل الفلاش أو إيقافه أو استخدام الإعدادات التلقائية |
Color Effects |
5 | يمكنك تطبيق تأثير لون على الصورة التي تم التقاطها، مثل الأبيض والأسود أو اللون البني الداكن أو الصورة السلبية. |
Anti-Banding |
5 | تقليل تأثير التدرّج في الألوان بسبب ضغط JPEG |
Picture Format |
1 | تحديد تنسيق ملف للصورة |
Picture Size |
1 | تحديد أبعاد البكسل للصورة المحفوظة |
ملاحظة: لا تتوفّر هذه الميزات على جميع الأجهزة بسبب اختلافات في الأجهزة وتنفيذ البرامج. للحصول على معلومات عن التحقّق من توفّر الميزات على الجهاز الذي يعمل عليه تطبيقك، يُرجى الاطّلاع على مقالة التحقّق من توفّر الميزات.
التحقّق من توفّر الميزات
عند إعداد ميزات الكاميرا على أجهزة Android، يجب أولاً فهم ما يلي: لا تتوفّر بعض ميزات الكاميرا على جميع الأجهزة. بالإضافة إلى ذلك، قد تتيح الأجهزة التي تتيح استخدام ميزة معيّنة استخدامها بمستويات مختلفة أو مع خيارات مختلفة. لذلك، يُعدّ تحديد ميزات الكاميرا التي تريد إتاحة استخدامها ومستوى توفّرها جزءًا من عملية اتخاذك للقرارات أثناء تطوير تطبيق كاميرا. بعد اتخاذ هذا القرار، يجب أن تخطط لتضمين التعليمة البرمجية في تطبيق للكاميرا يتحقّق لمعرفة ما إذا كانت معدّات الجهاز تتوافق مع هذه الميزات أم لا على نحو جمالي إذا لم تكن الميزة متوفرة.
يمكنك التحقّق من توفّر ميزات الكاميرا من خلال الحصول على مثيل لمَعلمات
كاميرا، والتحقّق من الطرق ذات الصلة. يوضّح لك نموذج الرمز البرمجي التالي كيفية الحصول على كائن
Camera.Parameters
والتحقّق مما إذا كانت الكاميرا تتيح ميزة التركيز التلقائي
:
Kotlin
val params: Camera.Parameters? = camera?.parameters val focusModes: List<String>? = params?.supportedFocusModes if (focusModes?.contains(Camera.Parameters.FOCUS_MODE_AUTO) == true) { // Autofocus mode is supported }
Java
// get Camera parameters Camera.Parameters params = camera.getParameters(); List<String> focusModes = params.getSupportedFocusModes(); if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) { // Autofocus mode is supported }
ويمكنك اتّباع الأسلوب الموضّح أعلاه لمعظم ميزات الكاميرا. يقدّم كائن
Camera.Parameters
طريقة getSupported...()
أو is...Supported()
أو getMax...()
لتحديد ما إذا كانت الميزة متوفرة (وإلى أي مدى).
إذا كان تطبيقك يتطلّب ميزات معيّنة كي يعمل بشكل صحيح، يمكنك طلبها من خلال الإضافات إلى بيان التطبيق. عند الإفصاح عن استخدام ميزات محددة للكاميرا، مثل الفلاش والتركيز التلقائي، يحظِر Google Play تثبيت تطبيقك على الأجهزة التي لا تتيح استخدام هذه الميزات. للحصول على قائمة بميزات الكاميرا التي يمكن الإفصاح عنها في بيان تطبيقك، يُرجى الاطّلاع على مرجع الميزات في البيان.
استخدام ميزات الكاميرا
يتم تفعيل معظم ميزات الكاميرا والتحكّم فيها باستخدام عنصر Camera.Parameters
. يمكنك الحصول على هذا الكائن من خلال الحصول أولاً على مثيل
لعنصر Camera
، واستدعاء الطريقة getParameters()
، وتغيير عنصر المَعلمة المعروض، ثمّ إعادته إلى عنصر الكاميرا، كما هو موضّح في المثال التالي
للرمز البرمجي:
Kotlin
val params: Camera.Parameters? = camera?.parameters params?.focusMode = Camera.Parameters.FOCUS_MODE_AUTO camera?.parameters = params
Java
// get Camera parameters Camera.Parameters params = camera.getParameters(); // set the focus mode params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); // set Camera parameters camera.setParameters(params);
وينطبق هذا الأسلوب على جميع ميزات الكاميرا تقريبًا، ويمكن تغيير معظم المَعلَمات في أي وقت.
الوقت بعد حصولك على مثال لعنصر Camera
. تظهر التغييرات التي تطرأ علىparametres عادةً للمستخدم على الفور في معاينة الكاميرا للتطبيق.
من ناحية البرامج، قد تستغرق تغييرات المَعلمات عدة لقطات لتصبح سارية المفعول، لأنّه يتم معالجة التعليمات الجديدة من خلال مكونات الكاميرا ثم إرسال بيانات الصورة المعدَّلة.
ملاحظة مهمة: لا يمكن تغيير بعض ميزات الكاميرا حسب الطلب. على سبيل المثال، يتطلّب تغيير حجم معاينة الكاميرا أو اتجاهها إيقاف المعاينة أولاً وتغيير حجمها ثم إعادة تشغيلها. بدءًا من Android 4.0 (واجهة برمجة التطبيقات المستوى 14) يمكن تغيير اتجاه المعاينة بدون إعادة تشغيل المعاينة.
يتطلّب تفعيل ميزات الكاميرا الأخرى المزيد من الرموز، بما في ذلك:
- قياس الأداء والمجالات التي يتم التركيز عليها
- التعرّف على الوجوه
- فيديو بوضع التسريع الزمني
في الأقسام التالية، يمكنك الاطّلاع على مخطّط سريع لكيفية تنفيذ هذه الميزات.
قياس الأداء والمجالات التي يتم التركيز عليها
في بعض سيناريوهات التصوير، قد لا تؤدي ميزة التركيز التلقائي وقياس الإضاءة إلى تحقيق النتائج المطلوبة. بدءًا من الإصدار Android 4.0 (مستوى واجهة برمجة التطبيقات 14)، يمكن أن يوفر تطبيق الكاميرا عناصر تحكّم إضافية للسماح لتطبيقك أو المستخدمين بتحديد مناطق في الصورة لاستخدامها في تحديد إعدادات التركيز أو مستوى الضوء وتمرير هذه القيم إلى جهاز الكاميرا لاستخدامها في التقاط الصور أو مقاطع الفيديو.
تعمل مناطق قياس حصة القراءة المجانية وتركيزها بشكل مشابه جدًا لميزات الكاميرا الأخرى، حيث يتحكّم المستخدم في الجهاز.
من خلال الطرق في الكائن Camera.Parameters
. يُنشئ الكود التالي
وضع منطقتين لقياس الضوء على سبيل المثال
Camera
:
Kotlin
// Create an instance of Camera camera = getCameraInstance() // set Camera parameters val params: Camera.Parameters? = camera?.parameters params?.apply { if (maxNumMeteringAreas > 0) { // check that metering areas are supported meteringAreas = ArrayList<Camera.Area>().apply { val areaRect1 = Rect(-100, -100, 100, 100) // specify an area in center of image add(Camera.Area(areaRect1, 600)) // set weight to 60% val areaRect2 = Rect(800, -1000, 1000, -800) // specify an area in upper right of image add(Camera.Area(areaRect2, 400)) // set weight to 40% } } camera?.parameters = this }
Java
// Create an instance of Camera camera = getCameraInstance(); // set Camera parameters Camera.Parameters params = camera.getParameters(); if (params.getMaxNumMeteringAreas() > 0){ // check that metering areas are supported List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>(); Rect areaRect1 = new Rect(-100, -100, 100, 100); // specify an area in center of image meteringAreas.add(new Camera.Area(areaRect1, 600)); // set weight to 60% Rect areaRect2 = new Rect(800, -1000, 1000, -800); // specify an area in upper right of image meteringAreas.add(new Camera.Area(areaRect2, 400)); // set weight to 40% params.setMeteringAreas(meteringAreas); } camera.setParameters(params);
يحتوي العنصر Camera.Area
على مَعلمتَي بيانات: عنصر Rect
لتحديد منطقة داخل مجال رؤية الكاميرا والوزن.
والذي يخبر الكاميرا بمستوى الأهمية الذي يجب منحه لهذه المنطقة في قياس الضوء
أو التركيز على العمليات الحسابية.
الحقل Rect
في كائن Camera.Area
تصف شكلاً مستطيلاً تم تعيينه على شبكة مقاس 2000 × 2000 وحدة. تمثل الإحداثيات -1000، -1000
الزاوية العلوية اليمنى لصورة الكاميرا، بينما تمثل الإحداثيات 1000، 1000
الزاوية السفلية اليمنى لصورة الكاميرا، كما هو موضّح في الرسم التوضيحي أدناه.
الشكل 1: توضح الخطوط الحمراء النظام الإحداثي لتحديد
Camera.Area
ضمن معاينة الكاميرا. يعرض المربع الأزرق الموقع
شكل مساحة كاميرا ذات قيمة Rect
وهي 333,333,667,667.
تتوافق حدود نظام الإحداثيات هذا دائمًا مع الحافة الخارجية للصورة الظاهرة في
معاينة الكاميرا، ولا تتقلّص أو تتوسّع مع مستوى التكبير/التصغير. وبالمثل، لا يؤدي تدوير معاينة
الصورة باستخدام Camera.setDisplayOrientation()
إلى إعادة ربط نظام الإحداثيات.
التعرّف على الوجوه
بالنسبة إلى الصور التي تتضمّن أشخاصًا، تكون الوجوه عادةً الجزء الأكثر أهمية في الصورة، ويجب استخدامها لتحديد كل من التركيز والتوازن الأبيض عند التقاط صورة. يقدّم إطار عمل Android 4.0 (المستوى 14 لواجهة برمجة التطبيقات) واجهات برمجة تطبيقات لتحديد الوجوه وحساب إعدادات الصور باستخدام تكنولوجيا التعرّف على الوجوه.
ملاحظة: أثناء تشغيل ميزة اكتشاف الوجوه،
setWhiteBalance(String)
,
setFocusAreas(List<Camera.Area>)
و
"setMeteringAreas(List<Camera.Area>)
" لن يكون لهما تأثير.
يتطلب استخدام ميزة "التعرّف على الوجوه" في تطبيق الكاميرا بعض الخطوات العامة:
- التحقق من أن ميزة "التعرّف على الوجوه" متوافقة على الجهاز
- إنشاء أداة معالجة ملفات التعرّف على الوجوه
- إضافة أداة معالجة التعرّف على الوجوه إلى عنصر الكاميرا
- بدء اكتشاف الوجوه بعد المعاينة (وبعد إعادة تشغيل كل معاينة)
لا تتوفر ميزة اكتشاف الوجوه في بعض الأجهزة. يمكنك التحقق من توفّر هذه الميزة
من خلال الاتصال بالرقم getMaxNumDetectedFaces()
. يظهر مثال على هذا التحقّق في startFaceDetection()
نموذج الطريقة أدناه.
لتلقّي إشعارات بشأن رصد الوجه والاستجابة له، يجب أن يضبط تطبيق الكاميرا معالجًا لأحداث رصد الوجه. ولإجراء ذلك، عليك إنشاء فئة مستمعين
لتنفيذ الواجهة Camera.FaceDetectionListener
على النحو الموضح في الرسم البياني
مثال التعليمة البرمجية أدناه.
Kotlin
internal class MyFaceDetectionListener : Camera.FaceDetectionListener { override fun onFaceDetection(faces: Array<Camera.Face>, camera: Camera) { if (faces.isNotEmpty()) { Log.d("FaceDetection", ("face detected: ${faces.size}" + " Face 1 Location X: ${faces[0].rect.centerX()}" + "Y: ${faces[0].rect.centerY()}")) } } }
Java
class MyFaceDetectionListener implements Camera.FaceDetectionListener { @Override public void onFaceDetection(Face[] faces, Camera camera) { if (faces.length > 0){ Log.d("FaceDetection", "face detected: "+ faces.length + " Face 1 Location X: " + faces[0].rect.centerX() + "Y: " + faces[0].rect.centerY() ); } } }
بعد إنشاء هذه الفئة، يمكنك ضبطها في عنصر
Camera
الخاص بتطبيقك، كما هو موضّح في مثال التعليمات البرمجية أدناه:
Kotlin
camera?.setFaceDetectionListener(MyFaceDetectionListener())
Java
camera.setFaceDetectionListener(new MyFaceDetectionListener());
يجب أن يبدأ التطبيق وظيفة اكتشاف الوجه في كل مرة تبدأ فيها (أو تعيد تشغيل) معاينة الكاميرا. إنشاء طريقة لبدء ميزة "التعرّف على الوجه" لتتمكن من طلبها حسب الحاجة، كما هو موضَّح في مثال الرمز أدناه.
Kotlin
fun startFaceDetection() { // Try starting Face Detection val params = mCamera?.parameters // start face detection only *after* preview has started params?.apply { if (maxNumDetectedFaces > 0) { // camera supports face detection, so can start it: mCamera?.startFaceDetection() } } }
Java
public void startFaceDetection(){ // Try starting Face Detection Camera.Parameters params = mCamera.getParameters(); // start face detection only *after* preview has started if (params.getMaxNumDetectedFaces() > 0){ // camera supports face detection, so can start it: mCamera.startFaceDetection(); } }
يجب بدء التعرّف على الوجوه في كل مرة تبدأ فيها معاينة الكاميرا (أو تعيد تشغيلها). في حال حذف
استخدام فئة المعاينة المعروضة في إنشاء فئة معاينة، أضف
startFaceDetection()
إلى كل من
surfaceCreated()
وsurfaceChanged()
في فئة المعاينة،
كما هو موضح في نموذج الرمز أدناه.
Kotlin
override fun surfaceCreated(holder: SurfaceHolder) { try { mCamera.setPreviewDisplay(holder) mCamera.startPreview() startFaceDetection() // start face detection feature } catch (e: IOException) { Log.d(TAG, "Error setting camera preview: ${e.message}") } } override fun surfaceChanged(holder: SurfaceHolder, format: Int, w: Int, h: Int) { if (holder.surface == null) { // preview surface does not exist Log.d(TAG, "holder.getSurface() == null") return } try { mCamera.stopPreview() } catch (e: Exception) { // ignore: tried to stop a non-existent preview Log.d(TAG, "Error stopping camera preview: ${e.message}") } try { mCamera.setPreviewDisplay(holder) mCamera.startPreview() startFaceDetection() // re-start face detection feature } catch (e: Exception) { // ignore: tried to stop a non-existent preview Log.d(TAG, "Error starting camera preview: ${e.message}") } }
Java
public void surfaceCreated(SurfaceHolder holder) { try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); startFaceDetection(); // start face detection feature } catch (IOException e) { Log.d(TAG, "Error setting camera preview: " + e.getMessage()); } } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { if (holder.getSurface() == null){ // preview surface does not exist Log.d(TAG, "holder.getSurface() == null"); return; } try { mCamera.stopPreview(); } catch (Exception e){ // ignore: tried to stop a non-existent preview Log.d(TAG, "Error stopping camera preview: " + e.getMessage()); } try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); startFaceDetection(); // re-start face detection feature } catch (Exception e){ // ignore: tried to stop a non-existent preview Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } }
ملاحظة: تذكَّر استدعاء هذه الطريقة بعد استدعاء
startPreview()
. لا تحاول بدء ميزة "اكتشاف الوجه"
في طريقة onCreate()
من النشاط الرئيسي لتطبيق الكاميرا،
لأنّ ميزة المعاينة لا تكون متاحة في هذه المرحلة من تنفيذ تطبيقك.
فيديو التسريع الزمني
يتيح فيديو التسريع الزمني للمستخدمين إنشاء مقاطع فيديو تجمع بين الصور التي تم التقاطها لبضع ثوان أو
دقائق. تستخدِم هذه الميزة MediaRecorder
لتسجيل الصور لإنشاء تسلسل متغيّر ببطء.
لتسجيل فيديو في وضع التسريع الزمني باستخدام MediaRecorder
، عليك ضبط ملف تعريف
المسجّل كما لو كنت تسجّل فيديو عاديًا، وضبط عدد اللقطات التي يتم التقاطها في الثانية على عدد
منخفض واستخدام أحد إعدادات جودة وضع التسريع الزمني، كما هو موضّح في مثال الرمز البرمجي أدناه.
Kotlin
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH)) mediaRecorder.setCaptureRate(0.1) // capture a frame every 10 seconds
Java
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher) mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH)); ... // Step 5.5: Set the video capture rate to a low number mediaRecorder.setCaptureRate(0.1); // capture a frame every 10 seconds
يجب تنفيذ هذه الإعدادات كجزء من إجراء ضبط أكبر لـ MediaRecorder
. للاطلاع على مثال لرمز الضبط الكامل، راجع تهيئة MediaRecorder. بعد اكتمال عملية الضبط،
ابدأ تسجيل الفيديو كما لو كنت تسجل مقطع فيديو عاديًا. لمزيد من المعلومات
حول ضبط إعدادات MediaRecorder
وتشغيله، يُرجى الاطّلاع على مقالة تسجيل الفيديوهات.
يوضّح نموذجا Camera2Video وHdrViewfinder استخدام واجهات برمجة التطبيقات التي تتناولها هذه الصفحة.
حقول الكاميرا التي تتطلّب إذنًا
يجب أن تتضمن التطبيقات التي تعمل بنظام التشغيل Android 10 (المستوى 29 من واجهة برمجة التطبيقات) أو الإصدارات الأحدث
إذن CAMERA
من أجل
للوصول إلى قيم الحقول التالية التي
getCameraCharacteristics()
إرجاع الطريقة:
LENS_POSE_ROTATION
LENS_POSE_TRANSLATION
LENS_INTRINSIC_CALIBRATION
LENS_RADIAL_DISTORTION
LENS_POSE_REFERENCE
LENS_DISTORTION
LENS_INFO_HYPERFOCAL_DISTANCE
LENS_INFO_MINIMUM_FOCUS_DISTANCE
SENSOR_REFERENCE_ILLUMINANT1
SENSOR_REFERENCE_ILLUMINANT2
SENSOR_CALIBRATION_TRANSFORM1
SENSOR_CALIBRATION_TRANSFORM2
SENSOR_COLOR_TRANSFORM1
SENSOR_COLOR_TRANSFORM2
SENSOR_FORWARD_MATRIX1
SENSOR_FORWARD_MATRIX2
نموذج رمز إضافي
لتنزيل نماذج تطبيقات، يُرجى الاطّلاع على مثال على Camera2Basic أو نموذج تطبيق CameraX الرسمي