注: このページでは、Camera2 パッケージについて説明します。アプリで Camera2 の特定の低レベルの機能を必要とする場合を除き、CameraX を使用することをおすすめします。CameraX と Camera2 は、どちらも Android 5.0(API レベル 21)以降に対応しています。
最新の Android デバイスの多くは、前面、背面、または背面に 2 台以上のカメラを搭載しています。 2 つの側面があります。レンズごとに、バースト キャプチャ、 手動制御、モーショントラッキングなどです小切手の預け入れアプリは、 背面カメラですが、ソーシャル メディア アプリでは、 前面カメラですが、ユーザーは利用可能なすべてのカメラを 。また、ユーザーの選択も記憶します。
このページでは、カメラのレンズとその機能をリストアップして、 は、特定の状況でどのレンズを使用するかをアプリ内で決定できます。 次のコード スニペットは、すべてのカメラのリストを取得して、 できます。
try {
val cameraIdList = cameraManager.cameraIdList // may be empty
// iterate over available camera devices
for (cameraId in cameraIdList) {
val characteristics = cameraManager.getCameraCharacteristics(cameraId)
val cameraLensFacing = characteristics.get(CameraCharacteristics.LENS_FACING)
val cameraCapabilities = characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)
// check if the selected camera device supports basic features
// ensures backward compatibility with the original Camera API
val isBackwardCompatible = cameraCapabilities?.contains(
CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) ?: false
...
}
} catch (e: CameraAccessException) {
e.message?.let { Log.e(TAG, it) }
...
}
try {
String[] cameraIdList = cameraManager.getCameraIdList(); // may be empty
// iterate over available camera devices
for (String cameraId : cameraIdList) {
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
int cameraLensFacing = characteristics.get(CameraCharacteristics.LENS_FACING);
int[] cameraCapabilities =
characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
// check if the selected camera device supports basic features
// ensures backward compatibility with the original Camera API
boolean isBackwardCompatible = false;
for (int capability : cameraCapabilities) {
if (capability == CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) {
isBackwardCompatible = true;
break;
}
}
...
}
} catch (CameraAccessException e) {
Log.e(TAG, e.getMessage());
...
}
変数 cameraLensFacing
は、カメラの向きを表します。
デバイス画面を基準に、次のいずれかの値を取ります。
CameraMetadata.LENS_FACING_FRONT
CameraMetadata.LENS_FACING_BACK
CameraMetadata.LENS_FACING_EXTERNAL
レンズを向く構成について詳しくは、以下をご覧ください。
CameraCharacteristics.LENS_FACING
。
上記のコードサンプルの変数 cameraCapabilities
には次のものが含まれます。
その他の機能に関する情報(カメラが
出力として標準フレームを生成できます(たとえば、
深度センサーデータなど)が含まれます。「新規顧客の獲得」目標を
CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE
リストにあるカメラの機能のいずれかであり、
isBackwardCompatible
。
適切なデフォルト値を選択する
アプリでは、特定のカメラをデフォルトで開きたい場合がある (利用可能な場合)。たとえば、自撮りアプリは多くの場合、前面カメラと 拡張現実アプリは背面カメラから始まります。 次の関数は、指定された方向を向く最初のカメラを返します。
fun getFirstCameraIdFacing(cameraManager: CameraManager,
facing: Int = CameraMetadata.LENS_FACING_BACK): String? {
try {
// Get list of all compatible cameras
val cameraIds = cameraManager.cameraIdList.filter {
val characteristics = cameraManager.getCameraCharacteristics(it)
val capabilities = characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)
capabilities?.contains(
CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) ?: false
}
// Iterate over the list of cameras and return the first one matching desired
// lens-facing configuration
cameraIds.forEach {
val characteristics = cameraManager.getCameraCharacteristics(it)
if (characteristics.get(CameraCharacteristics.LENS_FACING) == facing) {
return it
}
}
// If no camera matched desired orientation, return the first one from the list
return cameraIds.firstOrNull()
} catch (e: CameraAccessException) {
e.message?.let { Log.e(TAG, it) }
}
}
public String getFirstCameraIdFacing(CameraManager cameraManager, @Nullable Integer facing) {
if (facing == null) facing = CameraMetadata.LENS_FACING_BACK;
String cameraId = null;
try {
// Get a list of all compatible cameras
String[] cameraIdList = cameraManager.getCameraIdList();
// Iterate over the list of cameras and return the first one matching desired
// lens-facing configuration and backward compatibility
for (String id : cameraIdList) {
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(id);
int[] capabilities = characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
for (int capability : capabilities) {
if (capability == CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE
&& characteristics.get(CameraCharacteristics.LENS_FACING).equals(facing)) {
cameraId = id;
break;
}
}
}
// If no camera matches the desired orientation, return the first one from the list
cameraId = cameraIdList[0];
} catch (CameraAccessException e) {
Log.e(TAG, "getFirstCameraIdFacing: " + e.getMessage());
}
return cameraId;
}
カメラの切り替えを有効にする
多くのカメラアプリでは、カメラを切り替えるオプションが用意されています。

多くのデバイスには、同じ方向を向いた複数のカメラが搭載されています。中には、 外部 USB カメラを使用できます。ユーザーが複数の Google Cloud サービス間を 利用可能なカメラごとに、最初に使用可能なカメラを レンズを向いた構成になっています。
次のカメラを選択するための普遍的なロジックはありませんが、 次のコードは、ほとんどのユースケースで機能します。
fun filterCompatibleCameras(cameraIds: Array<String>,
cameraManager: CameraManager): List<String> {
return cameraIds.filter {
val characteristics = cameraManager.getCameraCharacteristics(it)
characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)?.contains(
CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) ?: false
}
}
fun filterCameraIdsFacing(cameraIds: List<String>, cameraManager: CameraManager,
facing: Int): List<String> {
return cameraIds.filter {
val characteristics = cameraManager.getCameraCharacteristics(it)
characteristics.get(CameraCharacteristics.LENS_FACING) == facing
}
}
fun getNextCameraId(cameraManager: CameraManager, currCameraId: String? = null): String? {
// Get all front, back and external cameras in 3 separate lists
val cameraIds = filterCompatibleCameras(cameraManager.cameraIdList, cameraManager)
val backCameras = filterCameraIdsFacing(
cameraIds, cameraManager, CameraMetadata.LENS_FACING_BACK)
val frontCameras = filterCameraIdsFacing(
cameraIds, cameraManager, CameraMetadata.LENS_FACING_FRONT)
val externalCameras = filterCameraIdsFacing(
cameraIds, cameraManager, CameraMetadata.LENS_FACING_EXTERNAL)
// The recommended order of iteration is: all external, first back, first front
val allCameras = (externalCameras + listOf(
backCameras.firstOrNull(), frontCameras.firstOrNull())).filterNotNull()
// Get the index of the currently selected camera in the list
val cameraIndex = allCameras.indexOf(currCameraId)
// The selected camera may not be in the list, for example it could be an
// external camera that has been removed by the user
return if (cameraIndex == -1) {
// Return the first camera from the list
allCameras.getOrNull(0)
} else {
// Return the next camera from the list, wrap around if necessary
allCameras.getOrNull((cameraIndex + 1) % allCameras.size)
}
}
public List<String> filterCompatibleCameras(CameraManager cameraManager, String[] cameraIds) {
final List<String> compatibleCameras = new ArrayList<>();
try {
for (String id : cameraIds) {
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(id);
int[] capabilities = characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
for (int capability : capabilities) {
if (capability == CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) {
compatibleCameras.add(id);
}
}
}
} catch (CameraAccessException e) {
Log.e(TAG, "filterCompatibleCameras: " + e.getMessage());
}
return compatibleCameras;
}
public List<String> filterCameraIdsFacing(CameraManager cameraManager, List<String> cameraIds, int lensFacing) {
final List<String> compatibleCameras = new ArrayList<>();
try {
for (String id : cameraIds) {
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(id);
if (characteristics.get(CameraCharacteristics.LENS_FACING) == lensFacing) {
compatibleCameras.add(id);
}
}
} catch (CameraAccessException e) {
Log.e(TAG, "filterCameraIdsFacing: " + e.getMessage());
}
return compatibleCameras;
}
public String getNextCameraId(CameraManager cameraManager, @Nullable String currentCameraId) {
String nextCameraId = null;
try {
// Get all front, back, and external cameras in 3 separate lists
List<String> compatibleCameraIds = filterCompatibleCameras(cameraManager, cameraManager.getCameraIdList());
List<String> backCameras = filterCameraIdsFacing(cameraManager, compatibleCameraIds, CameraMetadata.LENS_FACING_BACK);
List<String> frontCameras = filterCameraIdsFacing(cameraManager, compatibleCameraIds, CameraMetadata.LENS_FACING_FRONT);
List<String>externalCameras = filterCameraIdsFacing(cameraManager, compatibleCameraIds, CameraMetadata.LENS_FACING_EXTERNAL);
// The recommended order of iteration is: all external, first back, first front
List<String> allCameras = new ArrayList<>(externalCameras);
if (!backCameras.isEmpty()) allCameras.add(backCameras.get(0));
if (!frontCameras.isEmpty()) allCameras.add(frontCameras.get(0));
// Get the index of the currently selected camera in the list
int cameraIndex = allCameras.indexOf(currentCameraId);
// The selected camera may not be in the list, for example it could be an
// external camera that has been removed by the user
if (cameraIndex == -1) {
// Return the first camera from the list
nextCameraId = !allCameras.isEmpty() ? allCameras.get(0) : null;
else {
if (!allCameras.isEmpty()) {
// Return the next camera from the list, wrap around if necessary
nextCameraId = allCameras.get((cameraIndex + 1) % allCameras.size());
}
}
} catch (CameraAccessException e) {
Log.e(TAG, "getNextCameraId: " + e.getMessage());
}
return nextCameraId;
}
このコードは、さまざまなデバイスを使用する多数のデバイスで
できます。エッジケースの説明について詳しくは、CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA
をご覧ください。
互換性のあるアプリを作成する
サポートが終了した Camera API を使用しているアプリの場合は、
Camera.getNumberOfCameras()
返品は OEM の実装によって異なります。論理マルチカメラがある場合は、
アプリの下位互換性を維持するため、この方法では
すべての論理カメラと基盤となる物理カメラグループの 1 つです
Camera2 API を使用すると、すべてのカメラを確認できます。
カメラの向きの背景について詳しくは、以下をご覧ください。
Camera.CameraInfo.orientation
。
通常は
Camera.getCameraInfo()
すべてのカメラを照会する API
orientation
秒
画面の向きに合わせて 1 台のカメラのみを
カメラの切り替え。
すべてのデバイスタイプに対応する
常に 1 つ以上搭載されているハンドヘルド デバイス上でアプリが実行されるとは想定しないでください。 2 台のカメラが必要ですそのアプリに最も適したカメラを選択してください。もし 特定のカメラが不要な場合は、目的の方向を向いている最初のカメラを選択します。 方向です。外部カメラが接続されている場合、 デフォルトとして優先されます。