
CameraX를 사용해 사진 또는 비디오를 촬영하고, 그 결과를 서버에 업로드한 후 성공 여부를 이전 화면으로 전달하는 과정에서 카메라 화면으로 넘어가지 못하고 Use case binding failed 오류가 발생 했습니다.
이 오류는 설정된 mediaFormat에 따라 하나의 촬영 모드만 활성화해야 하는 상황에서, 사진(ImageCapture)과 비디오(VideoCapture) UseCase를 동시에 바인딩하고 있었기 때문에 발생했습니다.
이번 글에서는 mediaFormat 값에 따라 필요한 UseCase만 바인딩하도록 수정하여 문제를 해결한 과정을 공유합니다.
문제 상황: Use case binding failed 오류
CameraX는 기기 하드웨어가 허용하는 범위 내에서만 여러 UseCase를 동시 바인딩할 수 있습니다. 그러나 사진 촬영과 비디오 촬영 UseCase를 동시에 바인딩하려 할 때 아래와 같은 오류가 발생할 수 있었습니다.
java.lang.IllegalArgumentException: No supported surface combination is found for camera device - Id : 0. May be attempting to bind too many use cases.
이 오류는 CameraX가 해당 기기에서 지원하는 서피스 구성을 찾지 못해 발생했으며, 시스템 리소스가 부족할 때 특히 문제가 됐습니다.
Android 버전에 따른 UseCase 바인딩 문제
이 문제가 Android 7에서는 발생하지 않고, Android 10에서 발생한 이유는 버전별로 CameraX의 하드웨어 리소스 관리 방식과 서피스 제한이 다르기 때문이었습니다. 주요 원인은 다음과 같았습니다.
- 하드웨어 지원 차이: Android 10부터 멀티플 카메라 API 등 고성능 기능이 추가되며, UseCase 동시 사용에 기기 자원 부담이 증가했습니다.
- 엄격한 리소스 관리: Android 10부터 CameraX는 기기별 허용 한도를 더욱 엄격히 확인하여 다중 UseCase 바인딩 시 오류 발생 가능성이 높아졌습니다.
해결 방법: mediaFormat 값에 따른 조건부 바인딩
이 문제를 해결하기 위해 mediaFormat 값에 따라 필요한 UseCase만 선택적으로 바인딩하도록 startCamera() 메서드를 수정했습니다. 사진 모드에서는 ImageCapture만, 비디오 모드에서는 VideoCapture만 바인딩해 자원 부족 문제를 해결할 수 있었습니다.
코드 구현
아래 코드는 mediaFormat 값에 따라 ImageCapture와 VideoCapture를 선택적으로 바인딩한 후, 각각 takePhoto() 또는 captureVideo() 메서드를 호출해 촬영을 시작합니다.
private fun startCamera() {
Log.d("MediaCaptureActivity", "startCamera")
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
val preview = Preview.Builder().build().also {
it.setSurfaceProvider(binding.viewFinder.surfaceProvider)
}
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try {
cameraProvider.unbindAll()
when (mediaFormat) {
UserSettingsManager.EmergencyFormatType.PHOTO.value -> {
imageCapture = ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
.build()
cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture)
takePhoto()
}
UserSettingsManager.EmergencyFormatType.VIDEO.value -> {
val recorder = Recorder.Builder()
.setQualitySelector(QualitySelector.from(Quality.HIGHEST))
.build()
videoCapture = VideoCapture.withOutput(recorder)
cameraProvider.bindToLifecycle(this, cameraSelector, preview, videoCapture)
captureVideo()
}
else -> Log.d("MediaCaptureActivity", "No valid capture format")
}
} catch (exc: Exception) {
Log.e("CameraXApp", "Use case binding failed", exc)
}
}, ContextCompat.getMainExecutor(this))
}
코드 설명
- Preview 설정: Preview는 사진과 비디오 모드에서 공통으로 사용되므로, 모든 모드에서 바인딩할 수 있도록 준비했습니다.
- 조건부 UseCase 바인딩: mediaFormat 값에 따라 필요한 UseCase만 선택해 바인딩했습니다.
- 사진 모드일 경우 ImageCapture만 바인딩하고 takePhoto()를 호출하여 사진 촬영을 시작합니다.
- 비디오 모드일 경우 VideoCapture만 바인딩하고 captureVideo()를 호출하여 비디오 촬영을 시작합니다.
요약
위 코드에서는 mediaFormat 값에 따라 필요한 UseCase만 바인딩해 시스템 자원을 효과적으로 관리할 수 있었습니다. 이를 통해 Android 10과 최신 버전에서 발생할 수 있는 Use case binding failed 오류를 해결할 수 있었습니다.
'Android > Android Core' 카테고리의 다른 글
[Android/Kotlin] 안드로이드 앱에서 카카오 SDK를 사용해 OAuth 로그인을 구현하는 방법 (2) | 2024.11.09 |
---|---|
[Android/Kotlin] EncryptedSharedPreferences 사용하기: 보안 강화된 데이터 저장 방법 (0) | 2024.11.08 |
[Android/Kotlin] activityResultLauncher로 비동기 데이터 교환 및 파일 업로드 결과 처리하기 (2) | 2024.11.01 |
[Android/Kotlin] 기본 카메라 기능을 사용한 사진 및 비디오 자동 촬영 시도 기록 (0) | 2024.10.25 |
[Android/Kotlin] CameraX로 자동 사진 및 비디오 촬영 기능 구현하기 (1) | 2024.10.25 |