คู่มือนักพัฒนาซอฟต์แวร์นี้จะอธิบายขั้นตอนการอนุญาตให้แอปสลับไปมาระหว่างการควบคุมกล้องโดยเฉพาะอย่างราบรื่นผ่าน Android Camera2 API และการแชร์การเข้าถึงกล้องด้วย ARCore
หัวข้อนี้จะถือว่าคุณ:
คุ้นเคยกับ Android Camera2 API (ดูข้อมูลเพิ่มเติมได้จากตัวอย่าง Camera2 สำหรับ Android โดยเฉพาะ)
สร้างและเรียกใช้แอปตัวอย่าง
เมื่อคุณสร้างและเรียกใช้แอปตัวอย่างของ Shared Camera Java จะเป็นการสร้างเซสชัน ARCore ที่รองรับการเข้าถึงกล้องที่ใช้ร่วมกัน แอปจะเริ่มต้นในโหมดที่ไม่ใช่ AR และ ARCore หยุดชั่วคราว
เมื่อแอปทำงานในโหมดที่ไม่ใช่ AR โปรแกรมดูภาพของกล้องจะแสดงเอฟเฟกต์สีซีเปีย เมื่อเปลี่ยนเป็นโหมด AR เอฟเฟกต์ซีเปียจะปิดเมื่อแอปคืนการควบคุมกล้องกลับไปเป็น ARCore โดยกลับมาใช้งานเซสชันที่หยุดชั่วคราวต่อ
คุณใช้สวิตช์ AR ในแอปเพื่อเปลี่ยนโหมดได้ ระหว่างการแสดงตัวอย่าง ทั้ง 2 โหมดจะแสดงจำนวนเฟรมที่ต่อเนื่องซึ่งกล้อง Camera2 จับภาพไว้ได้
หากต้องการสร้างและเรียกใช้แอปตัวอย่าง Java สำหรับกล้องที่แชร์ ให้ทำดังนี้
ดาวน์โหลดและแตกไฟล์ Google ARCore SDK สำหรับ Android
เปิดโปรเจ็กต์
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 หากยังไม่ได้ติดตั้งในอุปกรณ์
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
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 จะขอสตรีม 2 รายการโดยค่าเริ่มต้น
- สตรีม CPU YUV 1 รายการ ปัจจุบันใช้
640x480
เสมอ
ARCore ใช้สตรีมนี้สำหรับการติดตามการเคลื่อนไหว - สตรีม GPU 1 เท่า โดยทั่วไปจะอยู่ที่
1920x1080
ใช้Session#getCameraConfig()
เพื่อระบุความละเอียดของสตรีม GPU ปัจจุบัน
คุณเปลี่ยนความละเอียดของสตรีม 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()
โค้ดเรียกกลับ
ดำเนินเซสชัน ARCore ต่อภายในโค้ดเรียกกลับของ onActive()
เพื่อเริ่มในโหมด 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()