Panduan developer ini memandu Anda melakukan langkah-langkah untuk memungkinkan aplikasi beralih dengan lancar antara kontrol eksklusif kamera melalui Android Camera2 API dan berbagi akses kamera dengan ARCore.
Topik ini mengasumsikan bahwa Anda:
Telah menyelesaikan Panduan Memulai ARCore
Memahami Android Camera2 API (tinjau contoh Camera2 khusus Android untuk mempelajari lebih lanjut)
Mem-build dan menjalankan aplikasi contoh
Saat Anda mem-build dan menjalankan aplikasi contoh Shared Camera Java, aplikasi ini akan membuat sesi ARCore yang mendukung akses kamera bersama. Aplikasi dimulai dalam mode non-AR, dengan ARCore dijeda.
Saat aplikasi beroperasi dalam mode non-AR, penampil kamera akan menampilkan efek warna sepia. Saat beralih ke mode AR, efek sepia akan dinonaktifkan saat aplikasi menampilkan kontrol kamera ke ARCore dengan melanjutkan sesi yang dijeda.
Anda dapat menggunakan tombol AR di aplikasi untuk mengubah mode. Selama pratinjau, kedua mode menampilkan jumlah frame berkelanjutan yang diambil oleh Camera2.
Untuk membangun dan menjalankan aplikasi contoh Java Kamera Bersama:
Download dan ekstrak Google ARCore SDK untuk Android.
Buka project
samples/shared_camera_java
.Pastikan perangkat Android Anda terhubung ke mesin pengembangan melalui USB. Lihat Perangkat yang didukung ARCore untuk informasi selengkapnya.
Di Android Studio, klik Run .
Pilih perangkat Anda sebagai target deployment, lalu klik OK untuk meluncurkan aplikasi contoh di perangkat.
Di perangkat, konfirmasi bahwa Anda ingin mengizinkan aplikasi mengambil gambar dan merekam video.
Jika diminta untuk melakukannya, update atau instal versi terbaru ARCore.
Gunakan tombol AR untuk beralih antara mode non-AR dan AR.
Ringkasan cara memungkinkan aplikasi berbagi akses kamera dengan ARCore
Ikuti langkah-langkah berikut untuk menerapkan akses kamera bersama dengan ARCore di aplikasi Anda.
Semua cuplikan kode tersedia di
SharedCameraActivity.java
dalam contoh
shared_camera_java
.
Minta izin CAMERA
Agar dapat menggunakan kamera perangkat, pengguna
harus memberikan izin CAMERA
ke aplikasi Anda.
Contoh ARCore menyertakan CameraPermissionHelper
,
yang menyediakan utilitas untuk meminta izin yang benar untuk aplikasi Anda.
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)
}
}
Pastikan ARCore diinstal dan merupakan versi terbaru
ARCore harus diinstal dan diupdate agar dapat digunakan. Cuplikan berikut menunjukkan cara meminta penginstalan ARCore jika belum diinstal di perangkat.
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
}
}
}
Membuat sesi ARCore yang mendukung berbagi kamera
Hal ini melibatkan pembuatan sesi serta penyimpanan referensi dan ID kamera bersama 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
(Opsional) Beri tahu ARCore tentang platform kustom apa pun
Meminta platform kustom tambahan akan meningkatkan permintaan performa perangkat. Untuk memastikan performanya baik, uji aplikasi Anda di perangkat yang akan digunakan pengguna.
ARCore akan meminta dua streaming secara default:
- 1x streaming CPU YUV, saat ini selalu
640x480
.
ARCore menggunakan aliran ini untuk pelacakan gerakan. - Aliran GPU 1x, biasanya
1920x1080
GunakanSession#getCameraConfig()
untuk menentukan resolusi aliran GPU saat ini.
Anda dapat mengubah resolusi aliran GPU pada perangkat yang didukung menggunakan
getSupportedCameraConfigs()
dan
setCameraConfig()
.
Sebagai indikator kasar, Anda bisa mendapatkan:
Jenis perangkat | Mendukung streaming serentak |
---|---|
Ponsel kelas atas |
|
Ponsel kelas menengah |
|
Untuk menggunakan platform kustom, seperti platform pembaca image CPU, pastikan untuk menambahkannya
ke daftar platform yang perlu diupdate
(misalnya, ImageReader
).
Java
sharedCamera.setAppSurfaces(this.cameraId, Arrays.asList(imageReader.getSurface()));
Kotlin
sharedCamera.setAppSurfaces(this.cameraId, listOf(imageReader.surface))
Membuka kamera
Buka kamera menggunakan callback yang digabungkan dengan 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)
Menggunakan callback status perangkat kamera
Di callback status perangkat kamera, simpan referensi ke perangkat kamera, dan memulai sesi pengambilan gambar baru.
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()
}
Membuat sesi pengambilan gambar baru
Buat permintaan pengambilan gambar baru. Gunakan TEMPLATE_RECORD
untuk memastikan bahwa permintaan pengambilan gambar kompatibel dengan ARCore, dan untuk memungkinkan peralihan
yang lancar antara mode non-AR dan AR saat runtime.
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)
}
}
Mulai dalam mode non-AR atau AR
Untuk mulai mengambil frame, panggil captureSession.setRepeatingRequest()
dari callback status onConfigured()
sesi pengambilan gambar kamera.
Lanjutkan sesi ARCore dalam callback onActive()
untuk memulai dalam mode AR.
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)
}
Beralih dengan lancar antara mode non-AR atau AR saat runtime
Untuk beralih dari mode non-AR ke AR dan melanjutkan sesi ARCore yang dijeda:
Java
// Resume the ARCore session.
resumeARCore();
Kotlin
// Resume the ARCore session.
resumeARCore()
Untuk beralih dari mode AR ke mode non-AR:
Java
// Pause ARCore.
sharedSession.pause();
// Create the Camera2 repeating capture request.
setRepeatingCaptureRequest();
Kotlin
// Pause ARCore.
sharedSession.pause()
// Create the Camera2 repeating capture request.
setRepeatingCaptureRequest()