[2022.11.12] sample.camera.android-master.7z

 

캡처.JPG

 

 

 

※ 카메라앱을 만드는 방법

  (1) Camera API를 사용하는 방법 (강의에서 설명한 방법)

      - 장점: 카메라 화면의 레이아웃을 마음대로 만들 수 있다

      - 단점: 핸드폰마다 카메라의 개수, 성능, 기능이 다양하기 때문에 이를 모두 지원하도록 앱 개발하는 것이 어렵다

  (2) 내장된 카메라 어플을 사용하는 방법

      - 단점: 카메라 어플의 UI를 사용해야 함 (하지만 카메라 어플에 이미 구현된 다양한 방법으로 촬영할 수 있음)

      - 장점: 구현이 쉬움

 

※ 테스트 환경 정보

  Android Studio Dolphin | 2021.3.1 Patch 1

  Build #AI-213.7172.25.2113.9123335, built on September 30, 2022

  Runtime version: 11.0.13+0-b1751.21-8125866 amd64

  VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.

  Windows 10 10.0

  GC: G1 Young Generation, G1 Old Generation

  Memory: 2048M

  Cores: 4

  Registry:

      external.system.auto.import.disabled=true

      ide.text.editor.with.preview.show.floating.toolbar=false

 

  Current Kotlin plugin version : 213-1.7.20-release-for-android-studio-AS6777.52

 

 

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <uses-feature android:name="android.hardware.camera2" android:required="true"/> //--카메라가 있는 안드로이드 기기의 앱이다

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Camera">

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <provider
            android:name="androidx.core.content.FileProvider" //--내부 저장소의 파일을 다른 어플리케이션에서 저장할 수 있게 해준다 (임시 권한 부여)
            android:authorities="${applicationId}.provider" //--관용적으로 패킷의 이름.provider 로 명명한다
            android:exported="false"
            android:grantUriPermissions="true">

            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths" /> //--리소스에 정의된 provider_paths 라는 이름의 변수값을 이용한다
        </provider>
    </application>
</manifest>

 

 

provider_path.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-files-path name="external_files" path="." /> <!-- /storage/emulated/0/Android/data/com.sample.camera/files -->
    <external-cache-path name="external_cache" path="." /> <!-- /storage/emulated/0/Android/data/com.sample.camera/cache -->
</paths>

 

 

MainActivity.kt

package com.sample.camera

import android.content.Intent
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider
import androidx.core.net.toFile
import com.bumptech.glide.Glide
import com.sample.camera.databinding.ActivityMainBinding
import java.io.File

private const val REQUEST_CODE_FOR_IMAGE_CAPTURE = 100
private const val TAG = "MainActivity"

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private lateinit var photoFile: File

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.camera.setOnClickListener { //--카메라 버튼을 클릭했을때 카메라 어플을 실행하기 위한 클릭 리스너 정의            
        val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) //-인텐트 필터를 걸어 카메라 인텐트를 생성
            if (intent.resolveActivity(packageManager) != null) {
                //val dir = getExternalFilesDir(Environment.DIRECTORY_PICTURES) // photos will be deleted when the app is uninstalled
                val dir = externalCacheDir // photo can be deleted when the app is terminated
                val file = File.createTempFile("photo_", ".jpg", dir)
                val uri = FileProvider.getUriForFile(this, "$packageName.provider", file) //--packageName에 따라 'com.sample.camera.provider' 가 파일명이 된다
                intent.putExtra(MediaStore.EXTRA_OUTPUT, uri) //--위에 정의한 uri 경로에 접근할 수 있게 해준다
                startActivityForResult(intent, REQUEST_CODE_FOR_IMAGE_CAPTURE)
                photoFile = file
            }
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        when (requestCode) {
            REQUEST_CODE_FOR_IMAGE_CAPTURE -> {
                if (resultCode == RESULT_OK) {
//                    BitmapFactory.decodeFile(photoFile.absolutePath)?.let {
//                        binding.image.setImageBitmap(it) 
//--찍은 사진을 ImageView에 표시할 수 있다, 그런데 그냥 실행하면 사진이 원하는대로 출력되지 않을 수 있다
//                    }
                    Glide.with(this).load(photoFile).into(binding.image) // call .centerCrop() .circleCrop() before .into() 
//--Glide 는 이미지의 사진을 찍는 상태를 자동으로 인식하여 출력해줄 수 있는 오픈 소스이다(그외 다른 옵션들도 제공해 준다)
                } else {
                    Toast.makeText(this, "취소 되었습니다", Toast.LENGTH_LONG).show()
                }
            }
        }
    }
}