تمت مشاركة إذن الوصول إلى الكاميرا مع ARCore.

يرشدك دليل المطوِّر هذا إلى خطوات تفعيل التبديل بين التطبيقات. بسلاسة بين التحكّم الحصري في الكاميرا من خلال واجهة برمجة تطبيقات Android Camera2 ومشاركة الوصول إلى الكاميرا مع ARCore.

يفترض هذا الموضوع أنك:

إنشاء نموذج التطبيق وتشغيله

عند إنشاء نموذج تطبيق Java المشترك للكاميرا وتشغيله، يؤدي ذلك إلى إنشاء جلسة ARCore تتيح الوصول المشترك إلى الكاميرا. يبدأ التطبيق بتقنية غير الواقع المعزّز مع إيقاف ARCore مؤقتًا.

عندما يعمل التطبيق في وضع غير الواقع المعزّز، يعرض عارض الكاميرا لونًا بني داكن التأثير. عند التبديل إلى وضع "الواقع المعزّز"، يتم إيقاف تأثير البني الداكن داخل التطبيق. إعادة التحكم في الكاميرا إلى ARCore من خلال استئناف الجلسة المتوقفة مؤقتًا.

يمكنك استخدام مفتاح تبديل الواقع المعزّز في التطبيق لتغيير الأوضاع. أثناء المعاينة، يتخطى كلا الوضعين لعرض عدد اللقطات المستمرة التي التقطها تطبيق Camera2.

لإنشاء نموذج تطبيق Java للكاميرا المشتركة وتشغيله:

  1. قم بتنزيل ملف تعريف الارتباط واستخراجه حزمة SDK الخاصة بحزمة تطوير البرامج (SDK) من Google ARCore لنظام التشغيل Android

  2. افتح مشروع samples/shared_camera_java.

  3. التأكّد من أنّ جهاز Android متصل بجهاز التطوير عبر USB. يمكنك الاطّلاع على الأجهزة المتوافقة مع ARCore. للحصول على معلومات مفصلة.

  4. في "استوديو Android"، انقر على Run .

  5. اختَر جهازك كهدف للنشر، وانقر على OK لتشغيل نموذج تطبيق على جهازك.

  6. أكِّد أنّك تريد السماح للتطبيق بالتقاط الصور على الجهاز تسجيل الفيديو.

  7. يُرجى تحديث ARCore أو تثبيته إذا طُلب منك ذلك.

  8. استخدِم مفتاح التبديل "AR" للتبديل بين الوضعَين غير الواقع المعزّز والواقع المعزّز.

نظرة عامة حول تفعيل أحد التطبيقات لمشاركة الوصول إلى الكاميرا مع ARCore

اتّبِع الخطوات التالية لإتاحة الوصول المشترَك إلى الكاميرا من خلال ARCore في تطبيقك. تتوفّر جميع مقتطفات الرمز في SharedCameraActivity.java ضمن shared_camera_java كعينة.

طلب إذن CAMERA

ولكي يتمكن المستخدم من استخدام كاميرا الجهاز، يجب منح تطبيقك إذن CAMERA. تشمل عيّنات ARCore العنصر CameraPermissionHelper، التي توفِّر برامج خدمات لطلب الإذن الصحيح لتطبيقك.

Java

protected void onResume() {
  // Request the camera permission, if necessary.
  if (!CameraPermissionHelper.hasCameraPermission(this)) {
      CameraPermissionHelper.requestCameraPermission(this);
  }
}

Kotlin

override fun onResume() {
  // Request the camera permission, if necessary.
  if (!CameraPermissionHelper.hasCameraPermission(this)) {
    CameraPermissionHelper.requestCameraPermission(this)
  }
}

التأكّد من أنّ حزمة ARCore مثبّتة ومحدَّثة

يجب تثبيت برنامج ARCore وتحديثه قبل التمكّن من استخدامه. يوضح المقتطف التالي كيفية طلب تثبيت ARCore إذا لم يكن مثبّتًا على الجهاز.

Java

boolean isARCoreSupportedAndUpToDate() {
  // Make sure that ARCore is installed and supported on this device.
  ArCoreApk.Availability availability = ArCoreApk.getInstance().checkAvailability(this);
  switch (availability) {
    case SUPPORTED_INSTALLED:
      return true;

    case SUPPORTED_APK_TOO_OLD:
    case SUPPORTED_NOT_INSTALLED:
        // Requests an ARCore installation or updates ARCore if needed.
        ArCoreApk.InstallStatus installStatus = ArCoreApk.getInstance().requestInstall(this, userRequestedInstall);
        switch (installStatus) {
          case INSTALL_REQUESTED:
            return false;
          case INSTALLED:
            return true;
        }
      return false;

    default:
      // Handle the error. For example, show the user a snackbar that tells them
      // ARCore is not supported on their device.
      return false;
  }
}

Kotlin

// Determine ARCore installation status.
// Requests an ARCore installation or updates ARCore if needed.
fun isARCoreSupportedAndUpToDate(): Boolean {
  when (ArCoreApk.getInstance().checkAvailability(this)) {
    Availability.SUPPORTED_INSTALLED -> return true

    Availability.SUPPORTED_APK_TOO_OLD,
    Availability.SUPPORTED_NOT_INSTALLED -> {
      when(ArCoreApk.getInstance().requestInstall(this, userRequestedInstall)) {
        InstallStatus.INSTALLED -> return true
        else -> return false
      }
    }

    else -> {
      // Handle the error. For example, show the user a snackbar that tells them
      // ARCore is not supported on their device.
      return false
    }
  }
}

إنشاء جلسة ARCore تتيح مشاركة الكاميرا

يشمل ذلك إنشاء الجلسة وتخزين مرجع ARCore ومعرّفه. الكاميرا المشتركة:

Java

// Create an ARCore session that supports camera sharing.
sharedSession = new Session(this, EnumSet.of(Session.Feature.SHARED_CAMERA))

// Store the ARCore shared camera reference.
sharedCamera = sharedSession.getSharedCamera();

// Store the ID of the camera that ARCore uses.
cameraId = sharedSession.getCameraConfig().getCameraId();

Kotlin

// Create an ARCore session that supports camera sharing.
sharedSession = Session(this, EnumSet.of(Session.Feature.SHARED_CAMERA))

// Store the ARCore shared camera reference.
sharedCamera = sharedSession.sharedCamera

// Store the ID of the camera that ARCore uses.
cameraId = sharedSession.cameraConfig.cameraId

(اختياري) إبلاغ ARCore بأي مساحات عرض مخصّصة

يؤدي طلب مساحات عرض مخصّصة إضافية إلى زيادة متطلبات الأداء الخاص بك. ولضمان أدائه الجيد، اختبِر تطبيقك على الأجهزة التي سيستخدمه المستخدمون.

ستطلب ARCore تلقائيًا بثَي محتوى:

  1. بث 1x وحدة المعالجة المركزية YUV، حاليًا ودائمًا 640x480
    تستخدم ARCore مصدر البيانات هذا لميزة تتبُّع الحركة.
  2. بثّ وحدة معالجة رسومات بمقدار مرة واحدة، عادةً 1920x1080
    استخدام Session#getCameraConfig() لتحديد دقّة بث وحدة معالجة الرسومات الحالية.

يمكنك تغيير درجة دقة البث عبر وحدة معالجة الرسومات على الأجهزة المتوافقة باستخدام getSupportedCameraConfigs() أو setCameraConfig()

كمؤشر تقريبي، يمكنك أن تتوقع ما يلي:

نوع الجهاز إمكانية بث المحتوى المتزامن
الهواتف المتطورة
  • وحدة معالجة مركزية بها 2x YUV، على سبيل المثال 640x480 و1920x1080
  • 1x بث وحدة معالجة الرسومات، على سبيل المثال 1920x1080
  • صورة ثابتة ذات دقة عالية 1x في بعض الأحيان (JPEG)، على سبيل المثال 12MP
الهواتف المتوسطة المستوى
  • وحدة معالجة مركزية بها 2x YUV، على سبيل المثال 640x480 و1920x1080
  • 1x بث وحدة معالجة الرسومات، على سبيل المثال 1920x1080
–أو–
  • عمليات بث وحدة المعالجة المركزية YUV 1x، على سبيل المثال 640x480 –أو– 1920x1080
  • 1x بث وحدة معالجة الرسومات، على سبيل المثال 1920x1080
  • صورة ثابتة ذات دقة عالية 1x في بعض الأحيان (JPEG)، على سبيل المثال 12MP

لاستخدام مساحات عرض مخصّصة، مثل سطح قارئ صور وحدة المعالجة المركزية (CPU)، احرص على إضافته إلى قائمة مساحات العرض التي يجب تعديلها (على سبيل المثال، ImageReader).

Java

sharedCamera.">setAppSurfaces(this.cameraId, Arrays.asList(imageReader.getSurface()));

Kotlin

sharedCamera.">setAppSurfaces(this.cameraId, listOf(imageReader.surface))

فتح الكاميرا

فتح الكاميرا باستخدام معاودة الاتصال من خلال ARCore:

Java

// Wrap the callback in a shared camera callback.
CameraDevice.StateCallback wrappedCallback =
    sharedCamera.createARDeviceStateCallback(cameraDeviceCallback, backgroundHandler);

// Store a reference to the camera system service.
cameraManager = (CameraManager) this.getSystemService(Context.CAMERA_SERVICE);

// Open the camera device using the ARCore wrapped callback.
cameraManager.openCamera(cameraId, wrappedCallback, backgroundHandler);

Kotlin

// Wrap the callback in a shared camera callback.
val wrappedCallback = sharedCamera.createARDeviceStateCallback(cameraDeviceCallback, backgroundHandler)

// Store a reference to the camera system service.
val cameraManager = this.getSystemService(Context.CAMERA_SERVICE) as CameraManager

// Open the camera device using the ARCore wrapped callback.
cameraManager.openCamera(cameraId, wrappedCallback, backgroundHandler)

استخدام ميزة معاودة الاتصال بحالة جهاز الكاميرا

تخزين إشارة إلى جهاز الكاميرا في استدعاء حالة جهاز الكاميرا لبدء جلسة تسجيل جديدة.

Java

public void onOpened(@NonNull CameraDevice cameraDevice) {
    Log.d(TAG, "Camera device ID " + cameraDevice.getId() + " opened.");
    SharedCameraActivity.this.cameraDevice = cameraDevice;
    createCameraPreviewSession();
}

Kotlin

fun onOpened(cameraDevice: CameraDevice) {
  Log.d(TAG, "Camera device ID " + cameraDevice.id + " opened.")
  this.cameraDevice = cameraDevice
  createCameraPreviewSession()
}

إنشاء جلسة تسجيل جديدة

يمكنك إنشاء طلب تسجيل جديد. استخدام TEMPLATE_RECORD للتأكد من توافق طلب الالتقاط مع ARCore، وإتاحة تجربة التبديل بين وضعَي "الواقع المعزّز" و"الواقع المعزّز" في وقت التشغيل

Java

void createCameraPreviewSession() {
  try {
    // Create an ARCore-compatible capture request using `TEMPLATE_RECORD`.
    previewCaptureRequestBuilder =
        cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);

    // Build a list of surfaces, starting with ARCore provided surfaces.
    List<Surface> surfaceList = sharedCamera.getArCoreSurfaces();

    // (Optional) Add a CPU image reader surface.
    surfaceList.add(cpuImageReader.getSurface());

    // The list should now contain three surfaces:
    // 0. sharedCamera.getSurfaceTexture()
    // 1. …
    // 2. cpuImageReader.getSurface()

    // Add ARCore surfaces and CPU image surface targets.
    for (Surface surface : surfaceList) {
      previewCaptureRequestBuilder.addTarget(surface);
    }

    // Wrap our callback in a shared camera callback.
    CameraCaptureSession.StateCallback wrappedCallback =
        sharedCamera.createARSessionStateCallback(cameraSessionStateCallback, backgroundHandler);

    // Create a camera capture session for camera preview using an ARCore wrapped callback.
    cameraDevice.createCaptureSession(surfaceList, wrappedCallback, backgroundHandler);
  } catch (CameraAccessException e) {
    Log.e(TAG, "CameraAccessException", e);
  }
}

Kotlin

fun createCameraPreviewSession() {
  try {
    // Create an ARCore-compatible capture request using `TEMPLATE_RECORD`.
    previewCaptureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD)

    // Build a list of surfaces, starting with ARCore provided surfaces.
    val surfaceList: MutableList<Surface> = sharedCamera.arCoreSurfaces

    // (Optional) Add a CPU image reader surface.
    surfaceList.add(cpuImageReader.getSurface())

    // The list should now contain three surfaces:
    // 0. sharedCamera.getSurfaceTexture()
    // 1. …
    // 2. cpuImageReader.getSurface()

    // Add ARCore surfaces and CPU image surface targets.
    for (surface in surfaceList) {
      previewCaptureRequestBuilder.addTarget(surface)
    }

    // Wrap the callback in a shared camera callback.
    val wrappedCallback = sharedCamera.createARSessionStateCallback(cameraSessionStateCallback, backgroundHandler)

    // Create a camera capture session for camera preview using an ARCore wrapped callback.
    cameraDevice.createCaptureSession(surfaceList, wrappedCallback, backgroundHandler)
  } catch (e: CameraAccessException) {
    Log.e(TAG, "CameraAccessException", e)
  }
}

البدء في وضع غير الواقع المعزّز أو الواقع المعزّز

لبدء التقاط الإطارات، يمكنك استدعاء captureSession.setRepeatingRequest(). من جلسة تصوير الكاميرا onConfigured() حالة معاودة الاتصال. يمكنك استئناف جلسة ARCore ضِمن معاودة الاتصال على onActive() للبدء في وضع الواقع المعزّز.

Java

// Repeating camera capture session state callback.
CameraCaptureSession.StateCallback cameraSessionStateCallback =
    new CameraCaptureSession.StateCallback() {

      // Called when ARCore first configures the camera capture session after
      // initializing the app, and again each time the activity resumes.
      @Override
      public void onConfigured(@NonNull CameraCaptureSession session) {
        captureSession = session;
        setRepeatingCaptureRequest();
      }

      @Override
      public void onActive(@NonNull CameraCaptureSession session) {
        if (arMode && !arcoreActive) {
          resumeARCore();
        }
      }
    };

// A repeating camera capture session capture callback.
CameraCaptureSession.CaptureCallback cameraCaptureCallback =
    new CameraCaptureSession.CaptureCallback() {
      @Override
      public void onCaptureCompleted() {
        shouldUpdateSurfaceTexture.set(true);
      }
    };

void setRepeatingCaptureRequest() {
    captureSession.setRepeatingRequest(
        previewCaptureRequestBuilder.build(), cameraCaptureCallback, backgroundHandler);
}

void resumeARCore() {
    // Resume ARCore.
    sharedSession.resume();
    arcoreActive = true;

    // Set the capture session callback while in AR mode.
    sharedCamera.setCaptureCallback(cameraCaptureCallback, backgroundHandler);
}

Kotlin

val cameraSessionStateCallback = object : CameraCaptureSession.StateCallback() {
      // Called when ARCore first configures the camera capture session after
      // initializing the app, and again each time the activity resumes.
  override fun onConfigured(session: CameraCaptureSession) {
    captureSession = session
    setRepeatingCaptureRequest()
  }

  override fun onActive(session: CameraCaptureSession) {
    if (arMode && !arcoreActive) {
      resumeARCore()
    }
  }
}

val cameraCaptureCallback = object : CameraCaptureSession.CaptureCallback() {
  override fun onCaptureCompleted(
    session: CameraCaptureSession,
    request: CaptureRequest,
    result: TotalCaptureResult
  ) {
    shouldUpdateSurfaceTexture.set(true);
  }
}

fun setRepeatingCaptureRequest() {
  captureSession.setRepeatingRequest(
    previewCaptureRequestBuilder.build(), cameraCaptureCallback, backgroundHandler
  )
}

fun resumeARCore() {
    // Resume ARCore.
    sharedSession.resume()
    arcoreActive = true

    // Set the capture session callback while in AR mode.
    sharedCamera.setCaptureCallback(cameraCaptureCallback, backgroundHandler)
}

التبديل بسلاسة بين الوضعَين غير الواقع المعزّز أو الواقع المعزّز في وقت التشغيل

للتبديل من وضع الواقع المعزّز إلى وضع الواقع المعزّز واستئناف جلسة ARCore المتوقفة مؤقتًا، اتّبِع الخطوات التالية:

Java

// Resume the ARCore session.
resumeARCore();

Kotlin

// Resume the ARCore session.
resumeARCore()

للتبديل من وضع "الواقع المعزّز" إلى وضع "الواقع المعزّز":

Java

// Pause ARCore.
sharedSession.pause();

// Create the Camera2 repeating capture request.
setRepeatingCaptureRequest();

Kotlin

// Pause ARCore.
sharedSession.pause()

// Create the Camera2 repeating capture request.
setRepeatingCaptureRequest()