คู่มือนักพัฒนาซอฟต์แวร์นี้จะแนะนำคุณตลอดขั้นตอนการเปิดใช้แอปเพื่อเปลี่ยน ระหว่างการควบคุมกล้องพิเศษผ่าน API กล้อง 2 ของ Android และแชร์สิทธิ์เข้าถึงกล้องกับ ARCore
โดยหัวข้อนี้จะถือว่าคุณมีคุณสมบัติดังนี้
ได้ผ่าน ARCore Quickstart เสร็จสมบูรณ์แล้ว
มีความคุ้นเคยกับ API กล้อง 2 ของ Android (ดูตัวอย่าง Camera2 สำหรับ Android โดยเฉพาะ เพื่อดูข้อมูลเพิ่มเติม)
สร้างและเรียกใช้แอปตัวอย่าง
เมื่อคุณสร้างและเรียกใช้แอปตัวอย่าง JavaScript กล้องที่แชร์ แอปจะสร้าง เซสชัน 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))
เปิดกล้องถ่ายรูป
เปิดกล้องโดยใช้ Callback ที่ปกปิดด้วย 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)
ใช้ Callback สถานะของอุปกรณ์กล้อง
ใน Callback สถานะของอุปกรณ์กล้องจะเก็บการอ้างอิงอุปกรณ์กล้อง และ เริ่มเซสชันการจับภาพใหม่
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()
จาก Callback สถานะเซสชันการจับภาพ onConfigured()
กลับไปใช้เซสชัน ARCore ภายใน Callback ของ 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()