這份開發人員指南將逐步說明讓您的應用程式進行切換的步驟 透過 YAML 檔案 Android Camera2 API 並與 ARCore 分享相機存取權
本主題假設您:
已完成 ARCore 快速入門導覽課程
熟悉 Android Camera2 API (請參閱 Android 專用 Camera2 範例) )
建構並執行範例應用程式
建構及執行共用 Camera Java 範例應用程式時,該應用程式會建立 支援共用相機存取權的 ARCore 工作階段。應用程式以非 AR 模式啟動 啟動 ARCore。
當應用程式在非 AR 模式下運作時,相機檢視器會顯示深褐色 效果。切換至 AR 模式時,背景特效會隨著應用程式關閉 繼續暫停的工作階段,將相機控制恢復給 ARCore。
您可以使用應用程式中的 AR 開關變更模式。預覽期間,兩種模式 顯示 Camera2 擷取的連續影格數量。
如要建構及執行共用相機 Java 範例應用程式:
下載並解壓縮 Android 專用 Google ARCore SDK。
開啟
samples/shared_camera_java
專案。確認 Android 裝置已連線至開發機器 透過 USB 存取。請參閱 ARCore 支援的裝置 ,瞭解詳細資訊。
在 Android Studio 中,按一下 Run 。
選擇裝置做為部署目標,然後按一下 OK 來啟動 在裝置上使用範例應用程式
在裝置上,確認要允許應用程式拍照及 錄製影片
如果出現相關提示,請更新或安裝最新版的 ARCore。
使用 AR 切換功能即可在非 AR 和 AR 模式之間切換。
概略說明如何讓應用程式透過 ARCore 分享相機存取權
請按照下列步驟,在應用程式中實作與 ARCore 共用的相機存取權。
您可以在
SharedCameraActivity.java
敬上
shared_camera_java
內
樣本。
要求 CAMERA
權限
為了使用裝置的相機,使用者
必須授予應用程式 CAMERA
權限。
ARCore 範例包含 CameraPermissionHelper
、
提供公用程式,為您的應用程式要求適當權限。
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 已安裝且為最新版本
必須安裝最新版本的 ARCore,才能使用 ARCore。 下列程式碼片段說明如何要求安裝尚未安裝的 ARCore。
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 工作階段
包括建立工作階段並儲存 ARCore 的參照與 ID。 共用攝影機:
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
(選用) 向任何自訂途徑通知 ARCore
要求更多自訂平台,因而導致效能需求增加 裝置。為確保效能良好,請在執行應用程式時使用 使用者將使用的應用程式。
根據預設,ARCore 會要求兩個串流:
- 1x YUV CPU 串流,目前一律為
640x480
。
ARCore 會使用這個串流進行動作追蹤。 - 1 個 GPU 串流,通常為
1920x1080
使用Session#getCameraConfig()
來判斷目前的 GPU 串流解析度。
您可以使用
getSupportedCameraConfigs()
敬上
和
setCameraConfig()
。
如同粗略指標,您應該會看到:
裝置類型 | 支援同時串流 |
---|---|
高階手機 |
|
中階手機 |
|
如要使用自訂介面 (例如 CPU 圖片讀取器介面),請務必新增介面
系統就會列出需要更新的平台
(例如 ImageReader
)。
Java
sharedCamera.setAppSurfaces(this.cameraId, Arrays.asList(imageReader.getSurface()));
Kotlin
sharedCamera.setAppSurfaces(this.cameraId, listOf(imageReader.surface))
開啟相機
使用已包裝 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)
使用相機裝置狀態回呼
在相機裝置狀態回呼中,會儲存相機裝置的參照。 系統就會啟動新的擷取工作階段
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()
}
建立新的擷取工作階段
建立新的擷取要求。使用 TEMPLATE_RECORD
,以確保擷取要求與 ARCore 相容,並且
在執行階段切換非 AR 和 AR 模式。
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)
}
}
以非 AR 或 AR 模式啟動
如要開始擷取影格,請呼叫 captureSession.setRepeatingRequest()
擷取自相機擷取工作階段 onConfigured()
狀態回呼的做法。
在 onActive()
回呼中繼續執行 ARCore 工作階段,以 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)
}
在執行階段流暢切換非 AR 或 AR 模式
如何從非 AR 模式切換至 AR 模式,並恢復已暫停的 ARCore 工作階段:
Java
// Resume the ARCore session.
resumeARCore();
Kotlin
// Resume the ARCore session.
resumeARCore()
如何從 AR 模式切換為非 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()