Questa guida per gli sviluppatori illustra i passaggi per attivare il passaggio a un'app perfettamente tra il controllo esclusivo della videocamera, tramite API Android Camera2 e condividere l'accesso alla fotocamera con ARCore.
Questo argomento presuppone che tu:
Aver completato la guida rapida di ARCore.
Avete familiarità con API Android Camera2 (esamina l'esempio di fotocamera 2 specifico per Android per scoprire di più)
Crea ed esegui l'app di esempio
Quando crei ed esegui l'app di esempio Shared Camera Java, viene creata una Sessione ARCore che supporta l'accesso alla fotocamera condivisa. L'app si avvia in modalità non AR con ARCore in pausa.
Quando l'app funziona in modalità non AR, il visualizzatore della fotocamera mostra un colore seppia effetto. Quando passi alla modalità AR, l'effetto seppia viene disattivato nell'app restituisce il controllo della fotocamera ad ARCore ripristinando la sessione in pausa.
Per cambiare modalità, puoi utilizzare l'opzione AR nell'app. Durante l'anteprima, entrambe le modalità mostra il numero di fotogrammi continui acquisiti dalla fotocamera 2.
Per creare ed eseguire l'app di esempio Java della fotocamera condivisa:
Scarica ed estrai SDK Google ARCore per Android.
Apri l'app Progetto
samples/shared_camera_java
.Assicurati che il tuo dispositivo Android sia connesso al computer di sviluppo tramite USB. Vedi Dispositivi supportati di ARCore per informazioni dettagliate.
In Android Studio, fai clic su Run .
Scegli il tuo dispositivo come destinazione dell'implementazione e fai clic su OK per avviare di esempio sul tuo dispositivo.
Sul dispositivo, conferma che vuoi consentire all'app di scattare foto e registrare un video.
Se richiesto, aggiorna o installa l'ultima versione di ARCore.
Utilizza l'opzione AR per passare dalla modalità non AR a quella AR e viceversa.
Panoramica dell'abilitazione di un'app per la condivisione dell'accesso alla fotocamera con ARCore
Segui questi passaggi per implementare l'accesso alla fotocamera condivisa con ARCore nella tua app.
Tutti gli snippet di codice sono disponibili in
SharedCameraActivity.java
nel shared_camera_java
campione.
Richiedi l'autorizzazione CAMERA
Per poter utilizzare la fotocamera del dispositivo, l'utente
deve concedere alla tua app l'autorizzazione CAMERA
.
Gli esempi di ARCore includono CameraPermissionHelper
,
che fornisce le utilità per richiedere l'autorizzazione corretta per la tua app.
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)
}
}
Assicurati che ARCore sia installato e aggiornato
ARCore deve essere installato e aggiornato prima di poter essere utilizzato. Il seguente snippet mostra come richiedere un'installazione di ARCore se non è già installato sul dispositivo.
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
}
}
}
Creare una sessione ARCore che supporti la condivisione della fotocamera
Ciò comporta la creazione della sessione e l'archiviazione del riferimento e dell'ID di ARCore Videocamera condivisa:
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
(Facoltativo) Informa ARCore di eventuali piattaforme personalizzate
La richiesta di altre piattaforme personalizzate aumenta le esigenze di rendimento delle dispositivo. Per assicurarti che funzioni correttamente, testa l'app sui dispositivi su cui che gli utenti utilizzeranno.
Per impostazione predefinita, ARCore richiede due flussi:
- 1 stream con CPU YUV, attualmente sempre
640x480
.
ARCore utilizza questo stream per il monitoraggio del movimento. - Uno stream GPU 1x, in genere
1920x1080
UsaSession#getCameraConfig()
per determinare l'attuale risoluzione dello stream GPU.
Puoi modificare la risoluzione dello stream GPU sui dispositivi supportati utilizzando
getSupportedCameraConfigs()
e
setCameraConfig()
.
Come indicatore indicativo, sono previsti i seguenti aspetti:
Tipo di dispositivo | Stream simultanei supportati |
---|---|
Smartphone di fascia alta |
|
Smartphone di fascia media |
|
Per utilizzare piattaforme personalizzate, ad esempio un lettore di immagini CPU, assicurati di aggiungerlo
all'elenco delle piattaforme che devono essere aggiornate
(ad esempio, ImageReader
).
Java
sharedCamera.setAppSurfaces(this.cameraId, Arrays.asList(imageReader.getSurface()));
Kotlin
sharedCamera.setAppSurfaces(this.cameraId, listOf(imageReader.surface))
Apri la fotocamera
Apri la fotocamera utilizzando un callback con wrapping 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)
Usa il callback dello stato del dispositivo della videocamera
Nel callback dello stato del dispositivo della videocamera, memorizza un riferimento al dispositivo della videocamera. avvia una nuova sessione di acquisizione.
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()
}
Crea una nuova sessione di acquisizione
Crea una nuova richiesta di acquisizione. Utilizza TEMPLATE_RECORD
per assicurare che la richiesta di acquisizione sia compatibile con ARCore e per consentire
passando dalla modalità non AR a quella AR in fase di 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)
}
}
Avvia in modalità non AR o AR
Per iniziare ad acquisire frame, chiama captureSession.setRepeatingRequest()
dal callback di stato della sessione di acquisizione della videocamera onConfigured()
.
Riprendi la sessione ARCore all'interno del callback onActive()
per avviare la modalità 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)
}
Passa senza problemi tra le modalità non AR e AR in fase di runtime
Per passare dalla modalità non AR ad AR e riprendere una sessione ARCore messa in pausa:
Java
// Resume the ARCore session.
resumeARCore();
Kotlin
// Resume the ARCore session.
resumeARCore()
Per passare dalla modalità AR a quella 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()