ARCore ile paylaşılan kamera erişimi

Bu geliştirici kılavuzunda, uygulamanızda Android Camera2 API aracılığıyla özel kamera kontrolü ve ARCore ile kamera erişimi paylaşımı arasında sorunsuz geçiş yapma olanağı sunma adımları açıklanmaktadır.

Bu konuda aşağıdaki varsayımlarda bulunulmuştur:

Örnek uygulamayı derleyip çalıştırma

Shared Camera Java örnek uygulamasını derleyip çalıştırdığınızda bu uygulama, paylaşılan kamera erişimini destekleyen bir ARCore oturumu oluşturur. Uygulama, ARCore moddayken AR olmayan modda başlatılır.

Uygulama, artırılmış gerçeklik (AR) olmayan modda çalışırken, kamera görüntüleyici bir sepya renk efekti gösterir. AR moduna geçerken, uygulama duraklatılmış oturumu devam ettirerek kamera kontrolünü ARCore'a döndürdüğünde sepya efekti devre dışı kalır.

Modları değiştirmek için uygulamadaki AR anahtarını kullanabilirsiniz. Önizleme sırasında her iki mod da Kamera2 tarafından yakalanan kesintisiz kare sayısını görüntüler.

Shared Camera Java örnek uygulamasını derlemek ve çalıştırmak için:

  1. Android için Google ARCore SDK'sını indirip çıkarın.

  2. samples/shared_camera_java projesini açın.

  3. Android cihazınızın USB aracılığıyla geliştirme makinesine bağlı olduğundan emin olun. Ayrıntılı bilgi için ARCore Desteklenen cihazlar bölümüne bakın.

  4. Android Studio'da Run simgesini tıklayın.

  5. Dağıtım hedefi olarak cihazınızı seçin ve OK düğmesini tıklayarak örnek uygulamayı cihazınızda başlatın.

  6. Cihazda, uygulamanın resim çekmesine ve video kaydetmesine izin vermek istediğinizi onaylayın.

  7. İstenirse ARCore'un en son sürümünü güncelleyin veya yükleyin.

  8. Artırılmış gerçeklik (AR) olmayan ve AR modları arasında geçiş yapmak için AR anahtarını kullanın.

Uygulamaların ARCore ile kamera erişimini paylaşmasını etkinleştirmeye genel bakış

Uygulamanızda ARCore ile paylaşılan kamera erişimi uygulamak için aşağıdaki adımları izleyin. Tüm kod snippet'leri, shared_camera_java örneğindeki SharedCameraActivity.java içinde bulunabilir.

CAMERA izni iste

Kullanıcının, cihazın kamerasını kullanabilmesi için uygulamanıza CAMERA izni vermesi gerekir. ARCore örnekleri, yardımcı programlara uygulamanız için doğru izni isteme olanağı sunan CameraPermissionHelper içerir.

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'un yüklü ve güncel olduğundan emin olun

ARCore'un kullanılabilmesi için yüklü ve güncel olması gerekir. Cihazda yüklü değilse ARCore yükleme isteğinde nasıl bulunulacağını aşağıdaki snippet'te görebilirsiniz.

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
    }
  }
}

Kamera paylaşımını destekleyen bir ARCore oturumu oluşturun

Bu işlem, oturumu oluşturmayı ve ARCore paylaşılan kameranın referansını ve kimliğini depolamayı içerir:

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

(İsteğe bağlı) ARCore'a özel yüzeyler hakkında bilgi verin

Ek özel yüzeylerin istenmesi, cihazın performans taleplerini artırır. İyi performans gösterdiğinden emin olmak için uygulamanızı kullanıcılarınızın kullanacağı cihazlarda test edin.

ARCore, varsayılan olarak iki akış isteğinde bulunur:

  1. 1x YUV CPU akışı, şu anda her zaman 640x480.
    ARCore, hareket izleme için bu akışı kullanır.
  2. 1x GPU akışı, genellikle 1920x1080
    Geçerli GPU akış çözünürlüğünü belirlemek için Session#getCameraConfig() değerini kullanın.

Desteklenen cihazlarda getSupportedCameraConfigs() ve setCameraConfig() kullanarak GPU akışının çözünürlüğünü değiştirebilirsiniz.

Kabaca bir gösterge olarak, şunları bekleyebilirsiniz:

Cihazın türü Eşzamanlı akışlar destekleniyor
İleri teknoloji telefonlar
  • 2x YUV CPU akışı, ör. 640x480 ve 1920x1080
  • 1x GPU akışı, ör. 1920x1080
  • Ara sıra yüksek çözünürlüklü 1x hareketsiz resim (JPEG), ör. 12MP
Orta seviye telefonlar
  • 2x YUV CPU akışı, ör. 640x480 ve 1920x1080
  • 1x GPU akışı, ör. 1920x1080
–veya–
  • 1x YUV CPU akışı, ör. 640x480 –veya- 1920x1080
  • 1x GPU akışı, ör. 1920x1080
  • Ara sıra yüksek çözünürlüklü 1x hareketsiz resim (JPEG), ör. 12MP

CPU görüntü okuyucu yüzeyi gibi özel yüzeyler kullanmak için bu yüzeyleri güncellenmesi gereken yüzeyler listesine eklediğinizden emin olun (ör. ImageReader).

Java

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

Kotlin

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

Kamerayı aç

ARCore ile sarmalanmış geri çağırma kullanarak kamerayı açın:

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)

Kamera cihaz durumu geri aramasını kullan

Kamera cihaz durumu geri çağırma bölümünde kamera cihazı için bir referans depolayın ve yeni bir çekim oturumu başlatın.

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()
}

Yeni yakalama oturumu oluşturma

Yeni bir yakalama isteği oluşturun. Yakalama isteğinin ARCore ile uyumlu olduğundan emin olmak ve çalışma zamanında AR olmayan ve AR modu arasında sorunsuz geçişe olanak tanımak için TEMPLATE_RECORD kullanın.

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)
  }
}

Artırılmış gerçeklik (AR) olmayan modda veya AR modunda başlat

Kare yakalamaya başlamak için kamera yakalama oturumundan onConfigured() durumu geri çağırmasından captureSession.setRepeatingRequest()'i çağırın. AR modunda başlatmak için onActive() geri çağırması içindeki ARCore oturumunu devam ettirin.

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)
}

Çalışma zamanında artırılmış gerçeklik (AR) veya AR olmayan modlar arasında sorunsuz bir şekilde geçiş yapın

AR olmayan moddan AR moduna geçmek ve duraklatılmış bir ARCore oturumunu devam ettirmek için:

Java

// Resume the ARCore session.
resumeARCore();

Kotlin

// Resume the ARCore session.
resumeARCore()

AR modundan AR olmayan moda geçmek için:

Java

// Pause ARCore.
sharedSession.pause();

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

Kotlin

// Pause ARCore.
sharedSession.pause()

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