-
Android Camera 사용하기회사 생활/여권 NFC (CameraX + OCR + NFC) 2023. 7. 29. 14:39
회사에서 안드로이드 Camera를 이용해서 하는 프로젝트들이 너무 많아져서 공부할 필요성을 느껴 이참에 사용법을 공부해보려고 한다.
카메라를 사용하는 방법은 아주 크게 2가지 정도 있다.
1. Camera 앱을 사용하는 방법
2. Camera api 사용하는 방법 (Camera1 api, Camera2 api, CameraX api)
첫번째 방식은 이미지만 받을 경우 제일 편한 방식이다. 하지만 카메라 화면을 커스텀하게 하거나 카메라의 화면을 실시간(preview callback)으로 화면 정보를 가공해서 사용 못하는 등의 제한이 있다.
1번 방법은 카메라에 guide line을 커스텀하게 만들고 이미지 preview를 실시간으로 서버와 통신해서 사용해야 하는 나에게는 별로 필요는 없지만 공부한다는 마음으로 먼저 복습해봤다.
1. Camera 앱을 사용하는 방법
a) 카메라를 실행한 후 찍은 사진을 저장후 저장된 사진을 불러오는 방법
val getTakePicture = registerForActivityResult(ActivityResultContracts.TakePicture()) { if (it) { pictureUri.let { imageView.setImageURI(pictureUri) } } }
private fun createImageFile(): Uri? { val now = SimpleDateFormat("yyMMdd_HHmmss").format(Date()) val content = ContentValues().apply { put(MediaStore.Images.Media.DISPLAY_NAME, "img_$now.jpg") put(MediaStore.Images.Media.MIME_TYPE, "image/jpg") } return contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, content) }
pictureUri = createImageFile() getTakePicture.launch(pictureUri) // Require Uri
과거에는 Intent로 해서 onActivityResult로 받아왔던 것 같은데 이제는 이런방식으로 불러오는 것 같다.
뭐 어쨋든 일단 저장후 File Uri로 이미지를 불러오는 방식이다.b) 카메라를 실행하며 결과로 비트맵 이미지를 얻는 방법 (저장x)
val getTakePicturePreview = registerForActivityResult(ActivityResultContracts.TakePicturePreview()) { bitmap -> bitmap.let { imageView.setImageBitmap(bitmap) } } button2.setOnClickListener { if (requestPermission()) getTakePicturePreview.launch(null) // Bitmap get }
앞에 (a) 방식은 ActivityResultContracts.TakePicture() 가 Uri를 가져왔던 방식이라면 (b) 방식은 파일을 저장 안하고 bitmap으로 바로 가져오는 방식 같다.
c) 갤러리에서 파일 불러오기
val getContentImage = registerForActivityResult(ActivityResultContracts.GetContent()) { uri -> uri.let { imageView.setImageURI(uri) } } button3.setOnClickListener { if (requestPermission()) getContentImage.launch("image/*") }
그리고 추가로 권한도 허가 해야한다. 권한 허가 코드는 따로 빼내기가 귀찮아서 전체 코드로 gogo
더보기class CameraAppActivity : AppCompatActivity() { val REQUEST_PERMISSION_CODE_1 = 111 private lateinit var imageView: ImageView private lateinit var button1: Button private lateinit var button2: Button private lateinit var button3: Button private var pictureUri: Uri? = null // 요청하고자 하는 권한들 private val permissionList = arrayOf( Manifest.permission.CAMERA, ) @RequiresApi(Build.VERSION_CODES.TIRAMISU) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_camera_app) imageView = findViewById(R.id.imageView) button1 = findViewById(R.id.button1) button2 = findViewById(R.id.button2) button3 = findViewById(R.id.button3) // 1. 카메라를 실행한 후 찍은 사진을 저장후 저장된 사진을 불러오는 방법 val getTakePicture = registerForActivityResult(ActivityResultContracts.TakePicture()) { if (it) { pictureUri.let { imageView.setImageURI(pictureUri) } } } pictureUri = createImageFile() button1.setOnClickListener { if (requestPermission()) getTakePicture.launch(pictureUri) // Require Uri } // 2. 카메라를 실행하며 결과로 비트맵 이미지를 얻음 val getTakePicturePreview = registerForActivityResult(ActivityResultContracts.TakePicturePreview()) { bitmap -> bitmap.let { imageView.setImageBitmap(bitmap) } } button2.setOnClickListener { if (requestPermission()) getTakePicturePreview.launch(null) // Bitmap get } // 3. 파일 불러오기 val getContentImage = registerForActivityResult(ActivityResultContracts.GetContent()) { uri -> uri.let { imageView.setImageURI(uri) } } button3.setOnClickListener { if (requestPermission()) getContentImage.launch("image/*") } } private fun createImageFile(): Uri? { val now = SimpleDateFormat("yyMMdd_HHmmss").format(Date()) val content = ContentValues().apply { put(MediaStore.Images.Media.DISPLAY_NAME, "img_$now.jpg") put(MediaStore.Images.Media.MIME_TYPE, "image/jpg") } return contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, content) } private fun requestPermission(): Boolean { return if (permissionList.all { ContextCompat.checkSelfPermission( this, it ) == PackageManager.PERMISSION_GRANTED }) { true } // 권한 요청 else { requestPermissions(permissionList, REQUEST_PERMISSION_CODE_1) false } } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) when (requestCode) { // 다시 묻지 않음을 생각하고 처리하는 법. REQUEST_PERMISSION_CODE_1 -> { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED && grantResults[2] == PackageManager.PERMISSION_GRANTED ) { Toast.makeText(this, "모든 권한을 허용하였습니다.", Toast.LENGTH_SHORT).show() } else { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "카메라 권한을 허용하였습니다.", Toast.LENGTH_SHORT).show() } else if (shouldShowRequestPermissionRationale(Manifest.permission.BLUETOOTH_ADVERTISE)) { Toast.makeText(this, "카메라 권한을 거절하였습니다.", Toast.LENGTH_SHORT).show() } else { Toast.makeText(this, "카메라 권한을 다시 묻지 않음을 하였습니다.", Toast.LENGTH_SHORT).show() } } } } } }
그리고 당연하게도 Manifest.xml에 카메라 permission도 추가
더보기<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <uses-feature android:name="android.hardware.camera" android:required="false" /> <uses-permission android:name="android.permission.CAMERA" /> ...생략 ... </manifest>
카메라 사용하는 방법이 onActivityResult가 deprecated 되면서 바뀐듯 싶다. 바뀌면서 찾아서 하는데 4시간이나 걸렸다능....
뭐 어쨋든 중요한건 이것 보다는 이제 Camera API를 사용하는 방법을 집중적으로 알아봐야겠다.
내일이나 다음주에....
'회사 생활 > 여권 NFC (CameraX + OCR + NFC)' 카테고리의 다른 글
CameraX api 4편 : Anlysis와 text 분석 라이브러리(OCR) (0) 2023.11.14 CameraX api 3편 : takePicture 메소드 (0) 2023.11.13 CameraX api 2 : CameraX 기본 코드 분석 (0) 2023.11.10 CameraX api 1 : 기초 (0) 2023.11.05 여권 NFC 정보 가져오기 (0) 2023.06.01