Study + Daily = Steadily 자세히보기

Development/Android

[번역] CameraX 기초 예제 - Part2

레카아범 2022. 2. 11. 13:09
반응형

본 포스트는 developer.android.com 에 작성되어 있는  Getting Started with CameraX 문서를 한글로 번역한 문서입니다.
본래 한 포스트로 작성되어 있으나, 티스토리 블로그의 문제인지 자꾸 포스팅이 날아가는 오류가 발생해 부득이 나눠 발행합니다.

[번역] CameraX 기초 예제 - Part1  (이전)
[번역] CameraX 기초 예제 - Part2 (현재)
[번역] CameraX 기초 예제 - Part3 (다음)

 

 

뷰파인더 레이아웃 만들기

기본 레이아웃을 다음 코드로 교체합니다.

1. activity_main레이아웃 파일을 열고 아래 코드로 변경합니다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".MainActivity">

   <Button
       android:id="@+id/camera_capture_button"
       android:layout_width="100dp"
       android:layout_height="100dp"
       android:layout_marginBottom="50dp"
       android:scaleType="fitCenter"
       android:text="Take Photo"
       app:layout_constraintLeft_toLeftOf="parent"
       app:layout_constraintRight_toRightOf="parent"
       app:layout_constraintBottom_toBottomOf="parent"
       android:elevation="2dp" />

   <androidx.camera.view.PreviewView
       android:id="@+id/viewFinder"
       android:layout_width="match_parent"
       android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.kt 를 설정합니다.

  1. MainActivity.kt의 코드를 아래와 같이 변경합니다. 여기에는 import 문, 인스턴스화할 변수, 구현할 함수 및 상수가 포함됩니다.

카메라 권한을 확인하고, 카메라를 시작하고, 카메라 버튼에 대해 onClickListener()를 설정하고, outputDirectory 및 cameraExecutor를 구현할 수 있도록 onCreate()가 이미 구현되었습니다

onCreate()가 구현되어 있더라도, 파일내의 함수들을 구현하기 전까지는 카메라는 동작하지 않습니다.

 

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.Manifest
import android.content.pm.PackageManager
import android.net.Uri
import android.util.Log
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import java.util.concurrent.Executors
import androidx.camera.core.*
import androidx.camera.lifecycle.ProcessCameraProvider
import kotlinx.android.synthetic.main.activity_main.*
import java.io.File
import java.nio.ByteBuffer
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.ExecutorService
typealias LumaListener = (luma: Double) -> Unit

class MainActivity : AppCompatActivity() {
   private var imageCapture: ImageCapture? = null

   private lateinit var outputDirectory: File
   private lateinit var cameraExecutor: ExecutorService

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_main)

       // Request camera permissions
       if (allPermissionsGranted()) {
           startCamera()
       } else {
           ActivityCompat.requestPermissions(
               this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
       }

       // Set up the listener for take photo button
       camera_capture_button.setOnClickListener { takePhoto() }

       outputDirectory = getOutputDirectory()

       cameraExecutor = Executors.newSingleThreadExecutor()
   }

   private fun takePhoto() {}

   private fun startCamera() {}

   private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
       ContextCompat.checkSelfPermission(
           baseContext, it) == PackageManager.PERMISSION_GRANTED
   }

   private fun getOutputDirectory(): File {
       val mediaDir = externalMediaDirs.firstOrNull()?.let {
           File(it, resources.getString(R.string.app_name)).apply { mkdirs() } }
       return if (mediaDir != null && mediaDir.exists())
           mediaDir else filesDir
   }

   override fun onDestroy() {
       super.onDestroy()
       cameraExecutor.shutdown()
   }

   companion object {
       private const val TAG = "CameraXBasic"
       private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"
       private const val REQUEST_CODE_PERMISSIONS = 10
       private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA)
   }
}

 

3. 카메라 권한 요청

앱이 카메라를 열기 전에 사용자의 허가가 필요합니다. 이 단계에서는 카메라 권한을 구현합니다.

 

1. AndroidManifest.xml을 열어  application태그 앞에 다음 코드를 추가합니다

<uses-feature android:name="android.hardware.camera.any" />
<uses-permission android:name="android.permission.CAMERA" />

android.hardware.camera.any를 추가하면 장치에 카메라가 있는지 확인합니다. .any를 지정하는 것은 전면 카메라 또는 후면 카메라일 수 있다는 것을 의미합니다.

 

.any없이 android.hardware.camera를 사용할 경우 대부분의 크롬북처럼 후방 카메라가 없는 기기가 있으면 동작하지 않습니다. 두 번째 줄에는 해당 카메라에 액세스할 수 있는 권한이 추가됩니다.

 

2. 아래 코드를 MainActivity.kt에 복사합니다. 이후 코드를 하나하나 분석해보도록 합시다.

override fun onRequestPermissionsResult(
   requestCode: Int, permissions: Array<String>, grantResults:
   IntArray) {
   if (requestCode == REQUEST_CODE_PERMISSIONS) {
       if (allPermissionsGranted()) {
           startCamera()
       } else {
           Toast.makeText(this,
               "Permissions not granted by the user.",
               Toast.LENGTH_SHORT).show()
           finish()
       }
   }
}
  • 요청 코드가 올바른지 확인하고, 그렇지 않으면 무시합니다.
if (requestCode == REQUEST_CODE_PERMISSIONS) {

}
  • 권한이 부여되면 startCamera()함수를 호출 합니다.
 if (allPermissionsGranted()) {
   startCamera()
}
  • 권한이 부여되지 않은 경우 사용자에게 권한이 부여되지 않았음을 알리는 토스트를 표시합니다.
else {
   Toast.makeText(this,
       "Permissions not granted by the user.",
       Toast.LENGTH_SHORT).show()
   finish()
}

3. 앱을 실행 합니다.

반응형