このデベロッパー ガイドでは、アプリの移行を有効にする手順について説明します。 カメラの排他制御をシームレスに切り替えられます Android Camera2 API ARCore によるカメラアクセスの共有などです。
このトピックは、次のことを前提としています。
ARCore クイックスタートを完了している
Google Cloud の Android Camera2 API (Android 固有の Camera2 サンプルを参照) をご覧ください)
サンプルアプリをビルドして実行する
Shared Camera Java サンプルアプリをビルドして実行すると、 共有カメラアクセスをサポートする ARCore セッション。アプリが AR 以外で起動する モードを終了しました。
アプリが非 AR モードで動作する場合、カメラビューアがセピアカラーになる できます。AR モードに切り替えると、アプリに応じてセピア効果がオフになり、 一時停止したセッションを再開して、カメラ コントロールを ARCore に返します。
アプリの AR スイッチを使用してモードを変更できます。プレビュー中は Camera2 によってキャプチャされた連続フレームの数を表示します。
Shared Camera Java サンプルアプリをビルドして実行するには:
ファイルをダウンロードして解凍 Android 向け Google ARCore SDK。
アプリ
samples/shared_camera_java
プロジェクト。Android デバイスが開発マシンに接続されていることを確認する 接続します。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 の参照と 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 はデフォルトで 2 つのストリームをリクエストします。
- 1x YUV CPU ストリーム。現在は常に
640x480
です。
ARCore は、このストリームをモーション トラッキングに使用します。 - 1x GPU ストリーム(通常は
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()
状態コールバックから取得されます。
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()