일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Rxjava Observable
- 자바 다형성
- rxjava hot observable
- ar vr 차이
- ANR이란
- 스택 자바 코드
- 큐 자바 코드
- 멤버변수
- 객체
- 서비스 쓰레드 차이
- rxjava cold observable
- 안드로이드 라이선스 종류
- 클래스
- 안드로이드 유닛 테스트 예시
- 안드로이드 유닛테스트란
- 스택 큐 차이
- 안드로이드 유닛 테스트
- 서비스 vs 쓰레드
- jvm이란
- 안드로이드 os 구조
- android retrofit login
- 2022 플러터 안드로이드 스튜디오
- 2022 플러터 설치
- 안드로이드 레트로핏 crud
- 안드로이드 레트로핏 사용법
- rxjava disposable
- 플러터 설치 2022
- android ar 개발
- jvm 작동 원리
- 안드로이드 라이선스
- Today
- Total
나만을 위한 블로그
[Android] CameraX 코드랩 뜯어보기 - 2 - 본문
https://onlyfor-me-blog.tistory.com/490
1편에서 뼈대 코드들을 만들었으니 이제 카메라를 쓰기 위해 유저에게 권한을 요청하는 처리를 구현한다. 카메라 기능을 사용하기 위해선 권한이 필요하고 이후 소리를 녹음하는 기능도 구현하기 때문에 여러 권한들을 매니페스트에 지정한다.
<uses-feature android:name="android.hardware.camera.any" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
안드로이드 파이 버전 이하에선 외부 저장소 쓰기 권한이 필요하다. 그래서 외부 저장소 권한을 추가했고 맨 위의 android.hardware.camera.any를 추가하면 이 앱을 실행하는 단말에 카메라가 있는지 여부를 확인할 수 있다. ".any"를 지정하면 전면 또는 후면 카메라 모두를 확인한다. ".any"를 쓰지 않으면 후면 카메라가 없을 경우 앱이 작동하지 않을 수 있다. 이와 관련된 디벨로퍼 링크는 아래에 첨부한다. android.hardware.camera.any의 내용은 밑으로 조금만 스크롤하면 나온다.
https://developer.android.com/guide/topics/manifest/uses-feature-element#features-reference
앱은 장치의 카메라 중 하나 또는 장치에 연결된 외부 카메라를 사용한다. 앱에서 카메라가 각각 후면 또는 전면을 향하도록 요구하지 않는 경우 android.hardware.camera 또는 android.hardware.camera.front 대신 이것을 사용하라. 후면 카메라는 android.hardware.camera가 android.required="false"로 선언되지 않는 한 필수 기능이다.
전면 카메라만 있는 Chromebook 같은 장치는 이 기능을 지원하지 않는다. 앱에서 모든 카메라를 쓸 수 있다면 android.hardware.camera.any를 사용하라
그리고 MainActivity에 이 함수를 재정의한다.
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == REQUEST_CODE_PERMISSIONS) {
if (allPermissionsGranted()) {
startCamera()
} else {
Toast.makeText(this, "권한이 승낙되지 않아서 앱이 종료됨", Toast.LENGTH_SHORT).show()
finish()
}
}
}
이 함수는 현재 deprecated된 함수다. 이것을 쓰는 것보단 TedPermission을 쓰거나 디벨로퍼에서 제시하는 방식을 사용한다. 권한 부분만 바꾸는 것은 어렵지 않으니 생략한다.
https://developer.android.com/training/permissions/requesting?hl=ko#manage-request-code-yourself
다시 코드를 보면 권한이 허용된 경우 startCamera()를 통해 카메라 기능을 시작한다. 앱을 실행해서 권한 요청 팝업이 표시되는지 확인한다. startCamera()는 시그니처만 만들어 둔 상태라 컴파일 에러는 발생하지 않겠지만 아무 기능도 하지 않는다.
뷰파인더는 사용자가 찍을 사진을 미리 볼 수 있게 하기 위해서 사용한다. 여기선 CameraX Preview 클래스를 통해 뷰파인더를 구현한다. 이제 startCamera() 안에 아래 내용을 복붙한다.
private fun startCamera() {
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
// Used to bind the lifecycle of cameras to the lifecycle owner
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
// Preview
val preview = Preview.Builder()
.build()
.also {
it.setSurfaceProvider(viewBinding.viewFinder.surfaceProvider)
}
// Select back camera as a default
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try {
// Unbind use cases before rebinding
cameraProvider.unbindAll()
// Bind use cases to camera
cameraProvider.bindToLifecycle(
this, cameraSelector, preview
)
} catch(exc: Exception) {
Log.e(TAG, "Use case binding failed", exc)
}
}, ContextCompat.getMainExecutor(this))
}
ProcessCameraProvider의 인스턴스를 만드는 것은 카메라의 생명주기를 lifecycleOwner에 바인딩하기 위해서다. CameraX는 앱의 생명주기를 인식할 수 있기 때문에 카메라를 열고 닫는 작업이 필요없다.
그리고 곧바로 ProcessCameraProvider의 인스턴스에 리스너를 추가하고 Runnable을 매개변수로 넘긴다. ContextCompat.getMainExecutor()는 메인 쓰레드에서 실행되는 Executor를 반환하는 역할을 한다. 그리고 Runnable 안에서 ProcessCameraProvider를 만드는데 이것은 앱 프로세스에서 카메라의 생명주기를 lifecycleOwner에 바인딩하기 위해 사용되는 클래스다. 카메라 기능에 대한 접근을 캡슐화, 관리하는 클래스로 카메라 기능 개발을 단순화하기 위해 설계된 Jetpack 구성요소다.
카메라 관련 그 다음 Preview 객체를 초기화한 다음 PreviewView에서 surface provider를 가져와 미리보기에 설정한다. 후면 카메라를 사용하게 설정하고 try 블록에서 cameraProvider에 바인딩된 것들을 해제하고 위에서 설정한 cameraSelector, preview 객체를 cameraProvider에 바인딩한다.
이제 에뮬레이터나 실제 핸드폰에서 앱을 빌드하면 아래와 같이 표시된다.
'Android' 카테고리의 다른 글
[Android] withContext란? (0) | 2023.04.08 |
---|---|
[Android] CameraX 코드랩 뜯어보기 - 3 - (0) | 2023.03.27 |
[Android] dataUrl이란? 웹뷰로 dataUrl 전송하는 법 (0) | 2023.03.25 |
[Android] Coroutine + Retrofit + Hilt + LiveData를 써서 네트워크 상태 별 처리하기 & 리사이클러뷰 페이징 (0) | 2023.03.21 |
[Android] hilt 적용 후 단위 테스트 작성 시 @HiltAndroidTest Not found 에러 해결 (0) | 2023.03.15 |