Panduan developer ini memandu Anda melalui langkah-langkah untuk mengaktifkan peralihan aplikasi tanpa hambatan di antara kontrol eksklusif kamera melalui API Camera2 Android dan berbagi akses kamera dengan ARCore.
Topik ini mengasumsikan bahwa Anda:
Telah menyelesaikan Panduan Memulai ARCore
Sudah familier dengan API Camera2 Android (tinjau contoh Camera2 khusus Android untuk mempelajari lebih lanjut)
Mem-build dan menjalankan aplikasi contoh
Saat Anda membuat dan menjalankan aplikasi contoh Shared Camera Java, aplikasi contoh akan membuat Sesi ARCore yang mendukung akses kamera bersama. Aplikasi dimulai dalam mode non-AR mode, dengan ARCore dijeda.
Saat aplikasi beroperasi dalam mode non-AR, penampil kamera akan menampilkan warna sepia pengaruh tersebut. Saat beralih ke mode AR, efek sepia akan nonaktif saat aplikasi mengembalikan 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 membuat 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 ARCore Perangkat yang didukung untuk informasi lebih lanjut.
Di Android Studio, klik Run .
Pilih perangkat Anda sebagai target deployment, lalu klik OK untuk meluncurkan aplikasi contoh di perangkat Anda.
Pada perangkat, konfirmasi bahwa Anda ingin mengizinkan aplikasi ini untuk 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 pengaktifan aplikasi untuk 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 shared_camera_java
contoh.
Meminta izin CAMERA
Agar dapat menggunakan kamera perangkat, pengguna
harus memberi aplikasi Anda izin CAMERA
.
Contoh ARCore mencakup 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 sudah diinstal dan sudah diupdate
ARCore harus diinstal dan diupdate sebelum 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 dan penyimpanan referensi dan ID ARCore kamera bersama:
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) Memberi tahu ARCore tentang platform kustom apa pun
Meminta platform kustom tambahan akan meningkatkan tuntutan performa perangkat seluler. Untuk memastikannya berperforma baik, uji aplikasi Anda pada perangkat yang digunakan pengguna.
ARCore akan meminta dua streaming secara default:
- 1x aliran CPU YUV, saat ini selalu
640x480
.
ARCore menggunakan aliran data ini untuk pelacakan gerakan. - 1x aliran GPU, biasanya
1920x1080
GunakanSession#getCameraConfig()
untuk menentukan resolusi streaming GPU saat ini.
Anda dapat mengubah resolusi streaming GPU pada perangkat yang didukung menggunakan
getSupportedCameraConfigs()
dan
setCameraConfig()
.
Sebagai indikator kasar, Anda dapat memperkirakan:
Jenis perangkat | Mendukung streaming secara bersamaan |
---|---|
Ponsel kelas atas |
|
Ponsel kelas menengah |
|
Untuk menggunakan platform kustom, seperti platform pembaca gambar CPU, pastikan untuk menambahkannya
ke daftar platform yang perlu diperbarui
(misalnya, ImageReader
).
Java
sharedCamera.setAppSurfaces(this.cameraId, Arrays.asList(imageReader.getSurface()));
Kotlin
sharedCamera.setAppSurfaces(this.cameraId, listOf(imageReader.surface))
Buka kamera
Buka kamera menggunakan callback yang digabungkan 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
Dalam callback status perangkat kamera, simpan referensi ke perangkat kamera, dan memulai sesi pengambilan gambar yang 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()
}
Buat sesi pengambilan gambar baru
Buat permintaan perekaman baru. Gunakan TEMPLATE_RECORD
untuk memastikan permintaan pengambilan gambar kompatibel dengan ARCore, dan untuk memungkinkan
beralih 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)
}
}
Memulai 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()