Ce guide du développeur vous explique comment faire passer votre application entre le contrôle exclusif de la caméra via API Android Camera2 et en partageant l'accès à l'appareil photo avec ARCore.
Dans cet article, nous partons du principe que vous avez:
avoir terminé le guide de démarrage rapide ARCore ;
Vous connaissez API Android Camera2 (consultez l'exemple Camera2 spécifique à Android). pour en savoir plus)
Créer et exécuter l'application exemple
Lorsque vous compilez et exécutez l'application exemple Shared Camera Java, celle-ci crée un Session ARCore compatible avec l'accès à une caméra partagée. Le démarrage de l'application n'est pas effectué en RA et ARCore en pause.
Lorsque l'application fonctionne en mode non-RA, la visionneuse de l'appareil photo affiche une couleur sépia l'effet. Lorsque vous passez en mode RA, l'effet sépia se désactive renvoie le contrôle de l'appareil photo à ARCore en relançant la session suspendue.
Vous pouvez utiliser le bouton de RA dans l'application pour changer de mode. En preview, les deux modes affiche le nombre d'images prises en continu par Camera2.
Pour compiler et exécuter l'exemple d'application Java Shared Camera, procédez comme suit:
Téléchargez et extrayez le fichier SDK Google ARCore pour Android
Ouvrez le Projet
samples/shared_camera_java
.Assurez-vous que votre appareil Android est connecté à l'ordinateur de développement via USB. Voir la page Appareils compatibles avec ARCore pour obtenir des informations détaillées.
Dans Android Studio, cliquez sur Run .
Choisissez votre appareil comme cible de déploiement, puis cliquez sur OK pour lancer la application exemple sur votre appareil.
Sur l'appareil, confirmez que vous souhaitez autoriser l'application à prendre des photos et enregistrer une vidéo.
Si vous y êtes invité, mettez à jour ou installez la dernière version d'ARCore.
Utilisez le bouton bascule AR pour basculer entre les modes non-RA et RA.
Présentation de l'activation d'une application pour partager l'accès à l'appareil photo avec ARCore
Suivez ces étapes pour implémenter l'accès à l'appareil photo partagé avec ARCore dans votre application.
Tous les extraits de code sont disponibles
SharedCameraActivity.java
dans les shared_camera_java
échantillon.
Demander l'autorisation CAMERA
Pour pouvoir utiliser l'appareil photo de l'appareil, l'utilisateur
doit accorder à votre application l'autorisation CAMERA
.
Les exemples ARCore incluent un élément CameraPermissionHelper
,
qui fournit des utilitaires pour demander
l'autorisation correcte pour votre application.
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)
}
}
Assurez-vous qu'ARCore est installé et à jour
Vous devez installer et mettre à jour ARCore pour pouvoir l'utiliser. L'extrait de code suivant montre comment demander l'installation d'ARCore si ce n'est pas déjà fait sur l'appareil.
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
}
}
}
Créer une session ARCore compatible avec le partage de caméra
Pour cela, vous devez créer la session, puis stocker la référence et l'ID ARCore. caméra partagée:
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
(Facultatif) Indiquer à ARCore les surfaces personnalisées
Le fait de demander des surfaces personnalisées supplémentaires augmente les exigences de performances du appareil. Pour vous assurer qu'elle fonctionne correctement, testez-la sur les appareils les utilisateurs se serviront.
ARCore demandera deux flux par défaut:
- Flux de processeur YUV 1x (actuellement
640x480
).
ARCore utilise ce flux pour le suivi du mouvement. - Un flux GPU x1, généralement
1920x1080
UtiliserSession#getCameraConfig()
pour déterminer la résolution actuelle du flux GPU.
Vous pouvez modifier la résolution du flux GPU sur les appareils compatibles en utilisant
getSupportedCameraConfigs()
et
setCameraConfig()
À titre d'indicateur approximatif, voici ce que vous pouvez attendre de cet indicateur:
Type d'appareil | Flux simultanés acceptés |
---|---|
Téléphones haut de gamme |
|
Téléphones de milieu de gamme |
|
Pour utiliser des surfaces personnalisées telles qu'une surface de lecteur d'images pour processeur, veillez à l'ajouter
à la liste des surfaces à mettre à jour
(par exemple, un ImageReader
).
Java
sharedCamera.setAppSurfaces(this.cameraId, Arrays.asList(imageReader.getSurface()));
Kotlin
sharedCamera.setAppSurfaces(this.cameraId, listOf(imageReader.surface))
Ouvrir l'appareil photo
Ouvrez l'appareil photo à l'aide d'un rappel encapsulé dans 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)
Utiliser le rappel d'état de l'appareil photo
Dans le rappel d'état de l'appareil photo, stockez une référence à l'appareil photo. une nouvelle session de capture.
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()
}
Créer une session de capture
Créez une demande de capture. Utiliser TEMPLATE_RECORD
pour garantir la compatibilité de la demande de capture avec ARCore et permettre
entre le mode non-RA et le mode RA au moment de l'exécution.
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)
}
}
Commencer en mode autre que RA ou RA
Pour commencer à capturer des images, appelez captureSession.setRepeatingRequest()
à partir du rappel d'état onConfigured()
de la session de capture de l'appareil photo.
Reprenez la session ARCore dans le rappel onActive()
pour démarrer en mode RA.
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)
}
Basculez facilement entre les modes non-RA et RA au moment de l'exécution
Pour passer du mode non-RA au mode RA et reprendre une session ARCore suspendue:
Java
// Resume the ARCore session.
resumeARCore();
Kotlin
// Resume the ARCore session.
resumeARCore()
Pour passer du mode RA au mode non-RA:
Java
// Pause ARCore.
sharedSession.pause();
// Create the Camera2 repeating capture request.
setRepeatingCaptureRequest();
Kotlin
// Pause ARCore.
sharedSession.pause()
// Create the Camera2 repeating capture request.
setRepeatingCaptureRequest()