Hướng dẫn dành cho nhà phát triển này sẽ chỉ cho bạn các bước để bật ứng dụng chuyển đổi một cách liền mạch giữa khả năng kiểm soát độc quyền máy ảnh thông qua API Android Camera2 và chia sẻ quyền truy cập máy ảnh với ARCore.
Chủ đề này giả định bạn:
Đã hoàn thành phần Bắt đầu nhanh về ARCore
Làm quen với API Android Camera2 (xem mẫu Camera2 dành riêng cho Android để tìm hiểu thêm)
Xây dựng và chạy ứng dụng mẫu
Khi tạo và chạy ứng dụng mẫu Shared Camera Java (Máy ảnh dùng chung), ứng dụng này sẽ tạo một Phiên ARCore hỗ trợ quyền truy cập vào máy ảnh dùng chung. Ứng dụng khởi động ở chế độ không phải AR trong đó ARCore bị tạm dừng.
Khi ứng dụng hoạt động ở chế độ không phải chế độ thực tế tăng cường, trình xem camera sẽ cho thấy màu nâu đỏ hiệu ứng. Khi chuyển sang chế độ AR, hiệu ứng màu nâu đỏ sẽ tắt khi ứng dụng trả về quyền điều khiển máy ảnh cho ARCore bằng cách tiếp tục phiên bị tạm dừng.
Bạn có thể dùng nút chuyển AR trong ứng dụng để thay đổi chế độ. Trong khi dùng thử, cả hai chế độ hiển thị số khung hình liên tục do Camera2 chụp.
Cách tạo và chạy ứng dụng mẫu Java cho Máy ảnh dùng chung:
Tải xuống và giải nén SDK ARCore của Google dành cho Android.
Mở Dự án
samples/shared_camera_java
.Đảm bảo rằng thiết bị Android đã kết nối với máy phát triển qua USB. Xem Thiết bị được hỗ trợ của ARCore để biết thông tin chi tiết.
Trong Android Studio, hãy nhấp vào Run .
Chọn thiết bị của bạn làm mục tiêu triển khai rồi nhấp vào OK để chạy ứng dụng mẫu trên thiết bị của bạn.
Trên thiết bị, hãy xác nhận rằng bạn muốn cho phép ứng dụng chụp ảnh và quay video.
Nếu thấy lời nhắc, hãy cập nhật hoặc cài đặt phiên bản ARCore mới nhất.
Dùng nút chuyển AR để thay đổi giữa chế độ không sử dụng công nghệ thực tế tăng cường (AR) và chế độ thực tế tăng cường (AR).
Tổng quan về việc bật ứng dụng để chia sẻ quyền truy cập máy ảnh với ARCore
Hãy làm theo các bước sau để triển khai quyền truy cập máy ảnh dùng chung với ARCore trong ứng dụng của bạn.
Tất cả các đoạn mã đều có trong
SharedCameraActivity.java
trong shared_camera_java
mẫu.
Yêu cầu quyền CAMERA
Để có thể sử dụng máy ảnh của thiết bị, người dùng
phải cấp cho ứng dụng quyền CAMERA
.
Các mẫu ARCore bao gồm CameraPermissionHelper
,
cung cấp các tiện ích để yêu cầu quyền chính xác cho ứng dụng.
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)
}
}
Đảm bảo ARCore đã được cài đặt và cập nhật
Bạn phải cài đặt và cập nhật ARCore trước khi có thể sử dụng. Đoạn mã sau đây cho biết cách yêu cầu cài đặt ARCore nếu ARCore chưa được cài đặt trên thiết bị.
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
}
}
}
Tạo một phiên ARCore có hỗ trợ tính năng chia sẻ máy ảnh
Việc này bao gồm việc tạo phiên và lưu trữ tham chiếu và ID của ARCore camera dùng chung:
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
(Không bắt buộc) Thông báo cho ARCore về mọi nền tảng tuỳ chỉnh
Việc yêu cầu thêm nền tảng tuỳ chỉnh sẽ làm tăng nhu cầu về hiệu suất của thiết bị. Để đảm bảo ứng dụng hoạt động tốt, hãy thử nghiệm ứng dụng của bạn trên các thiết bị mà người dùng sẽ sử dụng.
Theo mặc định, ARCore sẽ yêu cầu hai luồng:
- Luồng CPU YUV 1x, hiện luôn là
640x480
.
ARCore sử dụng luồng này để theo dõi chuyển động. - Luồng GPU 1x, thường là
1920x1080
Sử dụngSession#getCameraConfig()
để xác định độ phân giải luồng GPU hiện tại.
Bạn có thể thay đổi độ phân giải của luồng GPU trên những thiết bị được hỗ trợ bằng cách sử dụng
getSupportedCameraConfigs()
và
setCameraConfig()
.
Như chỉ báo sơ bộ, có thể bạn sẽ thấy:
Loại thiết bị | Hỗ trợ phát trực tuyến đồng thời |
---|---|
Điện thoại cao cấp |
|
Điện thoại cấp trung |
|
Để sử dụng nền tảng tuỳ chỉnh, chẳng hạn như bề mặt trình đọc hình ảnh bằng CPU, hãy nhớ thêm nền tảng đó
vào danh sách nền tảng cần được cập nhật
(ví dụ: ImageReader
).
Java
sharedCamera.setAppSurfaces(this.cameraId, Arrays.asList(imageReader.getSurface()));
Kotlin
sharedCamera.setAppSurfaces(this.cameraId, listOf(imageReader.surface))
Mở máy ảnh
Mở máy ảnh bằng lệnh gọi lại được gói 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)
Sử dụng lệnh gọi lại trạng thái thiết bị máy ảnh
Trong lệnh gọi lại trạng thái thiết bị máy ảnh, lưu trữ tham chiếu đến thiết bị máy ảnh và bắt đầu một phiên chụp mới.
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()
}
Tạo phiên chụp mới
Tạo một yêu cầu chụp mới. Sử dụng TEMPLATE_RECORD
để đảm bảo rằng yêu cầu chụp ảnh tương thích với ARCore và để cho phép liền mạch
chuyển đổi giữa chế độ không sử dụng công nghệ thực tế tăng cường và chế độ thực tế tăng cường trong thời gian chạy.
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)
}
}
Bắt đầu ở chế độ không sử dụng công nghệ thực tế tăng cường hoặc thực tế tăng cường
Để bắt đầu chụp khung hình, hãy gọi captureSession.setRepeatingRequest()
từ lệnh gọi lại trạng thái onConfigured()
trong phiên chụp ảnh.
Tiếp tục phiên ARCore trong lệnh gọi lại onActive()
để bắt đầu ở chế độ thực tế tăng cường.
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)
}
Chuyển đổi liền mạch giữa chế độ không sử dụng công nghệ thực tế tăng cường (AR) hoặc thực tế tăng cường (AR) trong thời gian chạy
Cách chuyển từ chế độ không sử dụng công nghệ thực tế tăng cường sang chế độ thực tế tăng cường và tiếp tục một phiên ARCore đã tạm dừng:
Java
// Resume the ARCore session.
resumeARCore();
Kotlin
// Resume the ARCore session.
resumeARCore()
Cách chuyển từ chế độ AR sang chế độ không phải 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()