In diesem Entwicklerleitfaden erfahren Sie, wie Sie den Wechsel Ihrer App aktivieren. zwischen der exklusiven Steuerung der Kamera über die Android Camera2 API und den Zugriff auf die Kamera mit ARCore.
In diesem Thema wird davon ausgegangen, dass Sie:
Du hast die ARCore-Kurzanleitung abgeschlossen
Sie kennen die Android Camera2 API (Sie können sich das Android-spezifische Beispiel von Camera2 ansehen) .
Beispielanwendung erstellen und ausführen
Wenn Sie die Beispiel-App Shared Camera Java erstellen und ausführen, wird ein ARCore-Sitzung, die den Zugriff auf die gemeinsame Kamera unterstützt. Die App startet nicht im AR-Modus mit pausiertem ARCore-Modus.
Wenn die App im Nicht-AR-Modus betrieben wird, zeigt das Gerät der Kamera eine Sepiafarbe an. Effekts. Wenn du in den AR-Modus wechselst, schaltet sich der Sepia-Effekt aus, da die App gibt die Kamerasteuerung an ARCore zurück, indem die pausierte Sitzung fortgesetzt wird.
Mit dem AR-Schalter in der App kannst du den Modus ändern. Während der Vorschau werden beide Modi die Anzahl der aufeinanderfolgenden Frames, die von Camera2 aufgenommen wurden, anzuzeigen.
So erstellen Sie die Java-Beispiel-App für freigegebene Kamera und führen sie aus:
Laden Sie die Datei Google ARCore SDK for Android
Öffnen Sie das
samples/shared_camera_java
-ProjektAchten Sie darauf, dass Ihr Android-Gerät mit dem Entwicklungscomputer verbunden ist USB-Kabel. Weitere Informationen zu unterstützten Geräten für ARCore .
Klicken Sie in Android Studio auf Run .
Wählen Sie Ihr Gerät als Bereitstellungsziel aus und klicken Sie auf OK, um die Beispiel-App auf Ihrem Gerät.
Bestätigen Sie auf dem Gerät, dass Sie der App erlauben möchten, Fotos und Video aufnehmen.
Wenn du dazu aufgefordert wirst, aktualisiere oder installiere die neueste Version von ARCore.
Mit dem Schalter AR können Sie zwischen dem Nicht-AR- und dem AR-Modus wechseln.
App für die Freigabe des Kamerazugriffs mit ARCore aktivieren
Folge dieser Anleitung, um den Zugriff auf die gemeinsame Kamera mit ARCore in deiner App zu implementieren.
Alle Code-Snippets sind in der
SharedCameraActivity.java
in der shared_camera_java
Stichprobe.
Berechtigung „CAMERA
“ anfordern
Damit Nutzer die Kamera des Geräts verwenden können,
muss deiner App die Berechtigung CAMERA
erteilen.
Zu den ARCore-Beispielen gehören CameraPermissionHelper
,
womit Dienstprogramme die richtige Berechtigung für Ihre App anfordern können.
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 muss installiert und auf dem neuesten Stand sein
ARCore muss installiert und auf dem neuesten Stand sein, damit du es verwenden kannst. Das folgende Snippet zeigt, wie Sie die Installation von ARCore anfordern, wenn ARCore noch nicht auf dem Gerät installiert ist.
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
}
}
}
ARCore-Sitzung erstellen, die die Kamerafreigabe unterstützt
Dazu gehört das Erstellen der Sitzung und das Speichern der Referenz und der ID von ARCore Gemeinsame Kamera:
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
Optional: ARCore über benutzerdefinierte Oberflächen informieren
Wenn zusätzliche benutzerdefinierte Oberflächen angefordert werden, erhöht sich die Leistungsanforderungen der . Testen Sie Ihre App auf den Geräten, die die Nutzenden nutzen.
ARCore fordert standardmäßig zwei Streams an:
- 1x YUV-CPU-Stream, aktuell immer
640x480
.
ARCore verwendet diesen Stream für die Bewegungserkennung. - Ein 1x GPU-Stream, normalerweise
1920x1080
Session#getCameraConfig()
verwenden um die aktuelle Auflösung des GPU-Streams zu ermitteln.
Du kannst die Auflösung des GPU-Streams auf unterstützten Geräten mit dem folgenden Befehl ändern:
getSupportedCameraConfigs()
und
setCameraConfig()
Als grober Indikator können Sie Folgendes erwarten:
Gerätetyp | Gleichzeitige Streams werden unterstützt |
---|---|
High-End-Smartphones |
|
Smartphones der mittleren Preisklasse |
|
Wenn Sie benutzerdefinierte Oberflächen verwenden möchten, z. B. eine CPU-Bildleseoberfläche, müssen Sie diese hinzufügen
in der Liste der zu aktualisierenden Oberflächen.
z. B. ImageReader
.
Java
sharedCamera.setAppSurfaces(this.cameraId, Arrays.asList(imageReader.getSurface()));
Kotlin
sharedCamera.setAppSurfaces(this.cameraId, listOf(imageReader.surface))
Kamera öffnen
Öffne die Kamera mit einem mit ARCore verpackten Callback:
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)
Callback für den Gerätestatus der Kamera verwenden
Im Kameragerätestatus wird ein Verweis auf das Kameragerät gespeichert. eine neue Aufnahme starten.
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()
}
Neue Aufnahmesitzung erstellen
Erstellen Sie eine neue Erfassungsanfrage. TEMPLATE_RECORD
verwenden
um sicherzustellen, dass die Aufnahmeanfrage mit ARCore kompatibel ist und eine nahtlose
während der Laufzeit zwischen Nicht-AR- und AR-Modus wechseln.
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)
}
}
Im Nicht-AR- oder AR-Modus starten
Rufen Sie captureSession.setRepeatingRequest()
auf, um mit der Aufnahme von Frames zu beginnen.
aus dem onConfigured()
-Statusrückruf für Kameraaufnahmesitzungen.
Setze die ARCore-Sitzung innerhalb des onActive()
-Callbacks fort, um im AR-Modus zu starten.
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)
}
Nahtlos zwischen Nicht-AR- und AR-Modus während der Laufzeit wechseln
So wechseln Sie vom Nicht-AR-Modus in den AR-Modus und setzen eine pausierte ARCore-Sitzung fort:
Java
// Resume the ARCore session.
resumeARCore();
Kotlin
// Resume the ARCore session.
resumeARCore()
So wechseln Sie vom AR- in den Nicht-AR-Modus:
Java
// Pause ARCore.
sharedSession.pause();
// Create the Camera2 repeating capture request.
setRepeatingCaptureRequest();
Kotlin
// Pause ARCore.
sharedSession.pause()
// Create the Camera2 repeating capture request.
setRepeatingCaptureRequest()