واجهة برمجة تطبيقات الكاميرا

يتيح إطار عمل Android استخدام العديد من الكاميرات وميزات الكاميرا المتاحة على الأجهزة، مما يتيح لك التقاط صور ومقاطع فيديو في تطبيقاتك. يناقش هذا المستند وسريعة وبسيطة لالتقاط الصور والفيديوهات وتحديد نهج متقدم لإنشاء تجارب كاميرات مخصَّصة للمستخدمين.

ملاحظة: تصف هذه الصفحة Camera الفئة التي تم إيقافها. ننصح باستخدام مكتبة cameraX في Jetpack، أو في حالات استخدام معيّنة camera2, الصف. يعمل كل من CameraX و Camera2 على نظام التشغيل Android 5.0 (المستوى 21 لواجهة برمجة التطبيقات). أعلى.

يمكنك الاطّلاع على المراجع التالية ذات الصلة:

الاعتبارات

قبل تمكين تطبيقك من استخدام الكاميرات على أجهزة Android، يجب مراعاة بعض أسئلة حول الطريقة التي سيستخدم بها تطبيقك ميزة الأجهزة هذه.

  • متطلبات الكاميرا - هل استخدام كاميرا مهم جدًا بالنسبة إلى تطبيق لا تريده أن يكون تطبيقك مثبّتًا على جهاز لا يحتوي على الكاميرا؟ إذا كان الأمر كذلك، يجب توضيح متطلبات الكاميرا في البيان.
  • صورة سريعة أو كاميرا مخصّصة - كيف سيستخدم تطبيقك الكاميرا؟ هل أنت مهتم فقط بالتقاط صورة سريعة أو مقطع فيديو أم هل تطبيق توفير طريقة جديدة لاستخدام الكاميرات؟ لالتقاط لقطة سريعة أو مقطع، ننصحك استخدام تطبيقات الكاميرا الحالية لتطوير ميزة مخصّصة في الكاميرا، اطّلِع على قسم إنشاء تطبيق كاميرا.
  • متطلبات الخدمات التي تعمل في المقدّمة: متى يتفاعل تطبيقك مع الكاميرا؟ في نظام التشغيل Android 9 (مستوى واجهة برمجة التطبيقات 28) والإصدارات الأحدث، سيتم تشغيل التطبيقات التي تعمل في لا يمكن للخلفية الوصول إلى الكاميرا. لذلك، يجب أن تستخدم الكاميرا إمّا عندما يكون تطبيقك في المقدّمة أو كجزء من التي تعمل في المقدّمة.
  • التخزين - هل الصور أو مقاطع الفيديو التي ينشئها تطبيقك مخصصة لتكون مرئية فقط للتطبيق أو المشاركة حتى تتمكن التطبيقات الأخرى مثل المعرض أو والوسائط والتطبيقات الاجتماعية يمكنها استخدامها؟ هل ترغب في أن تكون الصور ومقاطع الفيديو متاحة حتى إذا كان تم إلغاء تثبيت تطبيقك؟ راجِع القسم حفظ ملفات الوسائط من أجل الاطّلاع على طريقة تطبيق هذه الخيارات

الأساسيات

يدعم إطار عمل Android التقاط الصور والفيديو من خلال android.hardware.camera2 واجهة برمجة التطبيقات أو الكاميرا Intent. إليك الأخبار ذات الصلة الفئات:

android.hardware.camera2
هذه الحزمة هي واجهة برمجة التطبيقات الأساسية للتحكّم في كاميرات الأجهزة. يمكن استخدامها للحصول على الصور أو مقاطع الفيديو عند إنشاء تطبيق كاميرا.
Camera
هذه الفئة هي واجهة برمجة التطبيقات القديمة التي تم إيقافها نهائيًا للتحكّم في كاميرات الأجهزة.
SurfaceView
يُستخدم هذا الصف لتقديم معاينة مباشرة للكاميرا للمستخدم.
MediaRecorder
يُستخدَم هذا الصف لتسجيل الفيديو من الكاميرا.
Intent
يمكن استخدام نوع الإجراء المقصود، أي MediaStore.ACTION_IMAGE_CAPTURE أو MediaStore.ACTION_VIDEO_CAPTURE لالتقاط صور أو فيديوهات بدون الحاجة مباشرةً. باستخدام الكائن Camera.

بيانات البيان

قبل البدء في تطوير تطبيقك باستخدام واجهة برمجة التطبيقات للكاميرا، يجب التأكد يتضمن البيان التعريفات المناسبة للسماح باستخدام أجهزة الكاميرا وغيرها من والميزات ذات الصلة.

  • إذن الكاميرا - يجب أن يطلب التطبيق إذن استخدام أحد الأجهزة والكاميرا.
    <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(). تعذّر التحقّق من الاستثناءات إذا كانت الكاميرا مفعّلة استخدام أو غير موجود إلى إيقاف تشغيل التطبيق بواسطة النظام.

على الأجهزة التي تعمل بنظام التشغيل Android 2.3 (مستوى واجهة برمجة التطبيقات 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() لك تلقائيًا.

على عكس التقاط الصور باستخدام كاميرا الجهاز، يتطلب التقاط الفيديو مكالمة خاصة جدًا طلبك. يجب اتباع ترتيب محدد للتنفيذ للاستعداد بنجاح وتسجيل الفيديو مع طلبك، كما هو موضح أدناه.

  1. فتح الكاميرا - استخدام Camera.open() للحصول على مثيل لكائن الكاميرا.
  2. معاينة الربط - يمكنك إعداد معاينة مباشرة لصورة الكاميرا من خلال توصيل SurfaceView بالكاميرا باستخدام Camera.setPreviewDisplay().
  3. بدء المعاينة - اتصل بالرقم Camera.startPreview() لبدء عرض الصور المباشرة للكاميرا.
  4. بدء تسجيل الفيديو - يجب إكمال الخطوات التالية في الترتيب لتسجيل الفيديو بنجاح:
    1. فتح قفل الكاميرا - يجب فتح قفل الكاميرا لاستخدامها مع MediaRecorder من خلال الاتصال على الرقم Camera.unlock().
    2. إعداد MediaRecorder - الاتصال بطرق MediaRecorder التالية بهذا الترتيب. لمزيد من المعلومات، اطّلِع على مستندات MediaRecorder المرجعية.
      1. setCamera() - يمكنك ضبط الكاميرا لاستخدامها في التقاط الفيديو، واستخدام المثيل الحالي لتطبيقك من Camera.
      2. setAudioSource() - ضبط مصدر الصوت، استخدِم MediaRecorder.AudioSource.CAMCORDER.
      3. setVideoSource() - تم الضبط مصدر الفيديو، استخدِم MediaRecorder.VideoSource.CAMERA.
      4. ضبط تنسيق إخراج الفيديو وترميزه لأجهزة Android 2.2 (مستوى واجهة برمجة التطبيقات 8) الأعلى، استخدم الطريقة MediaRecorder.setProfile، واحصل على مثيل للملف الشخصي باستخدام CamcorderProfile.get(). بالنسبة لإصدارات Android السابقة 2.2، يجب ضبط تنسيق إخراج الفيديو ومَعلمات الترميز:
        1. setOutputFormat() - تم الضبط تنسيق الإخراج، حدّد الإعداد الافتراضي أو MediaRecorder.OutputFormat.MPEG_4.
        2. setAudioEncoder() - تم الضبط نوع ترميز الصوت، حدّد الإعداد التلقائي أو MediaRecorder.AudioEncoder.AMR_NB.
        3. setVideoEncoder() - تم الضبط نوع ترميز الفيديو، حدّد الإعداد التلقائي أو MediaRecorder.VideoEncoder.MPEG_4_SP.
      5. setOutputFile() - اضبط ملف الإخراج، واستخدِم getOutputMediaFile(MEDIA_TYPE_VIDEO).toString() من المثال في القسم حفظ ملفات الوسائط.
      6. setPreviewDisplay() - تحديد عنصر تنسيق المعاينة SurfaceView من أجل تطبيقك. استخدِم العنصر نفسه الذي حدّدته في Connect Preview (معاينة الربط).

      تنبيه: يجب استدعاء طرق الإعداد MediaRecorder هذه بهذا الترتيب، وإلا التطبيق أخطاء وسيفشل التسجيل.

    3. إعداد MediaRecorder - إعداد MediaRecorder مع تقديم إعدادات الضبط من خلال طلب MediaRecorder.prepare().
    4. بدء MediaRecorder: لبدء تسجيل الفيديو من خلال الاتصال بالرقم MediaRecorder.start()
  5. إيقاف تسجيل الفيديو - يمكنك استدعاء الطرق التالية بالترتيب، من أجل إكمال تسجيل الفيديو بنجاح:
    1. إيقاف MediaRecorder: لإيقاف تسجيل الفيديو من خلال الاتصال بـ MediaRecorder.stop()
    2. إعادة ضبط MediaRecorder - بشكل اختياري، يمكنك إزالة إعدادات الضبط من المسجّلة الذكية من خلال الاتصال بـ MediaRecorder.reset().
    3. إصدار MediaRecorder: ارفع إصبعك عن MediaRecorder من خلال الاتصال بـ MediaRecorder.release().
    4. قفل الكاميرا: عليك قفل الكاميرا بحيث يمكن لجلسات MediaRecorder المستقبلية استخدامها عن طريق الاتصال بالرقم Camera.lock(). بدءًا من Android 4.0 (المستوى 14 من واجهة برمجة التطبيقات)، لن تكون هذه المكالمة مطلوبة ما لم تعذّر الاتصال بـ MediaRecorder.prepare().
  6. إيقاف المعاينة - عند انتهاء نشاطك باستخدام الكاميرا، يمكنك إيقاف باستخدام Camera.stopPreview().
  7. إطلاق الكاميرا - ارفع إصبعك عن الكاميرا حتى تتمكن التطبيقات الأخرى من استخدامها عن طريق الاتصال بـ 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. الإعدادات الافتراضية، على الرغم من ذلك، قد تحتاج إلى ضبط هذه الإعدادات في تطبيقك:

بدء تشغيل MediaRecorder وإيقافه

عند بدء تسجيل الفيديو وإيقافه باستخدام الصف MediaRecorder، يجب اتباع ترتيب معين كما هو موضح أدناه.

  1. فتح قفل الكاميرا باستخدام "Camera.unlock()"
  2. اضبط MediaRecorder كما هو موضّح في مثال الرمز أعلاه.
  3. بدء التسجيل باستخدام "MediaRecorder.start()"
  4. تسجيل الفيديو
  5. إيقاف التسجيل باستخدام "MediaRecorder.stop()"
  6. رفع إصبعك عن مسجّل الوسائط باستخدام MediaRecorder.release()
  7. قفل الكاميرا باستخدام "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() في Android 2.2 (المستوى 8 من واجهة برمجة التطبيقات) أو أعلى. إذا كنت تستهدف أجهزة تعمل بإصدارات سابقة من Android، استخدِم Environment.getExternalStorageDirectory(). بدلاً من ذلك. لمزيد من المعلومات، راجع حفظ الملفات المشتركة.

لجعل معرِّف الموارد المنتظم (URI) متوافقًا مع ملفات العمل، عليك أولاً تحويل معرّف الموارد المنتظم (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. التغييرات على تظهر المعلمات عادةً للمستخدم على الفور في معاينة الكاميرا في التطبيق. من جانب البرنامج، قد تستغرق تغييرات المعلمات عدة إطارات لتصبح سارية المفعول يعالج جهاز الكاميرا التعليمات الجديدة، ثم يرسل بيانات مُحدّثة عن الصور.

ملاحظة مهمة: لا يمكن تغيير بعض ميزات الكاميرا حسب الطلب. ضِمن على وجه الخصوص، يتطلب تغيير حجم معاينة الكاميرا أو اتجاهها إيقاف المعاينة وتغيير حجم المعاينة، ثم إعادة بدء المعاينة. بدءًا من 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()" إلى إعادة تعيين نظام الإحداثيات.

التعرّف على الوجه

بالنسبة إلى الصور التي تتضمن أشخاصًا، تكون الوجوه عادةً أهم جزء في الصورة، لتحديد كل من التركيز وتوازن اللون الأبيض عند التقاط صورة. الإصدار 4.0 من نظام التشغيل Android (المستوى 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، يمكنك مراجعة التقاط الفيديوهات.

The 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 الرسمي