이번 글에서는 Android에서 기본 카메라 기능을 활용하여 자동으로 사진과 비디오를 촬영하려고 시도한 과정을 기록합니다. CameraX 대신 기본 카메라 기능을 통해 구현했으나, 자동 촬영이 원활하게 되지 않아 최종적으로 CameraX로 전환하게 된 이유와 관련한 경험을 공유합니다. 이 기록은 나중에 다시 기본 카메라를 활용할 가능성을 염두에 두고 작성되었습니다.
1. 기본 카메라를 이용한 촬영 시도
Android의 기본 카메라 앱을 호출하여 사진과 비디오를 촬영하려고 했습니다. 이때 Intent와 ActivityResultLauncher를 사용해 시스템 카메라 앱을 호출하여 촬영 작업을 수행하고, 촬영된 미디어 파일을 앱의 지정된 위치에 저장하도록 했습니다.
2. 구현 코드 개요
2.1. ActivityResultLauncher를 통한 카메라 및 비디오 인텐트 설정
ActivityResultLauncher를 이용하여 카메라와 비디오 촬영 인텐트를 각각 등록하고, 촬영 결과를 처리했습니다. 촬영이 완료되면 다시 자동으로 촬영을 실행하려고 시도했습니다.
// cameraLauncher 초기화
cameraLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == RESULT_OK) {
Log.d("MediaCaptureActivity", "CameraLauncher RESULT_OK")
// 자동으로 다시 촬영
launchCamera()
}
}
// videoLauncher 초기화
videoLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == RESULT_OK) {
Log.d("MediaCaptureActivity", "VideoLauncher RESULT_OK")
// 자동으로 다시 촬영
launchVideo()
}
}
2.2. 카메라 및 비디오 촬영 인텐트 실행
사진과 비디오 촬영 인텐트를 실행할 때 FileProvider를 사용해 파일의 Uri를 생성하여 MediaStore.EXTRA_OUTPUT을 통해 저장 위치를 지정했습니다.
private fun launchCamera() {
val imageFile = createMediaFile(isImage = true)
contentUri = FileProvider.getUriForFile(
this,
"${packageName}.provider",
imageFile
)
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri)
cameraLauncher.launch(cameraIntent)
}
private fun launchVideo() {
val videoFile = createMediaFile(isImage = false)
contentUri = FileProvider.getUriForFile(
this,
"${packageName}.provider",
videoFile
)
val videoIntent = Intent(MediaStore.ACTION_VIDEO_CAPTURE)
videoIntent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri)
videoLauncher.launch(videoIntent)
}
2.3. 미디어 파일 생성
촬영된 사진이나 비디오를 저장할 파일을 생성하는 메서드입니다. 파일명은 날짜와 시간 정보를 포함해 고유하게 생성되며, 앱의 내부 저장소에 저장됩니다.
private fun createMediaFile(isImage: Boolean): File {
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
val storageDir: File? = if (isImage) {
getExternalFilesDir(Environment.DIRECTORY_PICTURES)
} else {
getExternalFilesDir(Environment.DIRECTORY_MOVIES)
}
val fileExtension = if (isImage) ".jpg" else ".mp4"
val prefix = if (isImage) "JPEG_" else "MP4_"
val mediaFile = File.createTempFile("$prefix${timeStamp}_", fileExtension, storageDir)
filePath = mediaFile.absolutePath
return mediaFile
}
3. 문제점: 자동 촬영의 어려움
위의 접근 방식으로 자동 촬영을 구현하려고 했으나 몇 가지 문제가 있었습니다.
- 자동화의 어려움: 기본 카메라 앱을 호출하면 시스템에 내장된 앱이 실행되므로, 촬영 동작을 앱에서 직접 제어하기 어렵습니다. 촬영 후 자동으로 재촬영을 시작하는 기능을 구현하기 힘들고, 제조사마다 기본 카메라 앱의 동작이 달라 일관된 경험을 제공하기 어렵습니다.
- 제어권 부족: 기본 카메라를 사용할 경우, 촬영 중 다양한 동작을 직접 조정하거나 사용자 인터페이스를 변경하기가 어렵습니다. 촬영 후 자동 재시작 같은 기능은 앱에서 세밀하게 제어할 수 없어 원하는 대로 조정하는 데 한계가 있습니다.
4. CameraX로의 전환
위의 문제점으로 인해 최종적으로 CameraX로 전환하여 사진과 비디오 촬영을 구현했습니다. CameraX는 앱 내에서 카메라 인터페이스를 직접 제어할 수 있으며, 자동 촬영과 같은 기능을 쉽게 구현할 수 있는 장점이 있습니다.
5. 기본 카메라 vs CameraX
장점 | - 간단한 구현 - 다양한 기기에서의 호환성 제공 |
- 유연한 제어 가능 - 다양한 커스터마이징 옵션 제공 |
커스터마이징 및 제어 | - 제한적임 - 시스템 카메라 앱에 의존 |
- 촬영 프로세스와 사용자 경험을 앱 내에서 원하는 대로 조정 가능 |
사용 사례 | - 간단한 촬영 기능 구현 - 빠른 개발이 필요한 경우 |
- 고급 기능 구현 - 사용자 경험을 세밀하게 제어할 때 유리 |
설정 복잡도 | - 비교적 간단함 | - 초기 설정이 복잡하고 유지보수 필요 |
성능 | - 성능에 큰 영향을 미치지 않음 | - 저사양 기기에서 성능에 영향을 줄 수 있음 |
결론적으로, 기본 카메라는 간단한 촬영 기능이나 빠른 개발을 원할 때 적합하고, CameraX는 고급 기능과 사용자 경험의 세밀한 제어가 필요할 때 더 나은 선택이라는 생각이 들었습니다.
6. 결론
기본 카메라 앱을 활용한 접근은 간단한 촬영을 구현할 때 유용하지만, 자동 촬영이나 고급 기능을 요구하는 경우에는 한계가 있었습니다. CameraX는 이러한 요구를 충족시키기 위한 유연성을 제공하므로, 자동화와 사용자 경험을 제어할 수 있는 카메라 기능을 구현할 때는 더 적합한 선택입니다.
이 기록은 기본 카메라 기능을 활용하려는 시도와, 그 한계를 인식하고 CameraX로 전환하게 된 과정을 정리한 것입니다. 나중에 간단한 촬영 기능을 구현하거나 CameraX와의 비교가 필요할 때 참고할 수 있을 것입니다.
+ 자동 촬영 기능을 CameraX로 구현한 내용에 대해 더 자세히 알고 싶다면, 아래 링크를 통해 관련 글을 확인할 수 있습니다. 이 글에서는 CameraX를 사용해 사진과 비디오를 자동으로 촬영하는 방법을 단계별로 설명하고, 구현 코드와 함께 필요한 설정을 소개합니다.
[Android/Kotlin] CameraX로 자동 사진 및 비디오 촬영 기능 구현하기
이번 글에서는 Android의 CameraX 라이브러리를 활용하여 자동으로 사진 및 비디오를 촬영하는 기능을 구현하는 방법을 소개합니다. 권한 설정부터 CameraX 의존성 추가, 미리보기 화면 구성, 자동 촬
quessr.tistory.com
'Android > Android Core' 카테고리의 다른 글
[Android/Kotlin] CameraX에서 발생한 'Use case binding failed' 오류를 조건부 바인딩으로 해결하기 (1) | 2024.11.01 |
---|---|
[Android/Kotlin] activityResultLauncher로 비동기 데이터 교환 및 파일 업로드 결과 처리하기 (2) | 2024.11.01 |
[Android/Kotlin] CameraX로 자동 사진 및 비디오 촬영 기능 구현하기 (1) | 2024.10.25 |
[Android/Kotlin] Bluetooth Notify 기능 구현: CCCD 설정과 알림 활성화 방법 (0) | 2024.10.25 |
[Android/Kotlin] Kotlin에서 abstract class와 open class의 차이점 (0) | 2024.10.04 |