본문 바로가기

안드로이드

[Android Studio] 사진 가져오기, 사진 찍은 후 Crop 하기 2편 ! (Kotlin)

728x90

 저번에 이어서 사진 찍은 후 crop 바로 하기 포스팅을 하겠습니다. 

 이전 포스팅은 이 곳에서 볼 수 있습니다.

https://jangstory.tistory.com/108

 

[Android Studio] 사진 가져오기, 사진 찍은 후 Crop 하기 1편 ! (Kotlin)

오늘은 Android Studio 사진 가져오기, 사진 찍은 후 Crop 기능을 라이브러리 사용하지 않고 설정하는 법에 대해 포스팅 하겠습니다. 1. Manifests 추가 (Manifests 를 추가했으면 당연히 permission 확인 후 검

jangstory.tistory.com

 

 다음은 안드로이드 공식 문서입니다. 참고해주세요!

https://developer.android.com/training/camera/photobasics?hl=ko 

 

사진 촬영  |  Android 개발자  |  Android Developers

이 과정에서는 기존 카메라 애플리케이션을 사용하여 사진을 캡처하는 방법을 설명합니다. 클라이언트 앱을 실행하는 기기에서 촬영한 하늘 사진을 조합하여 세계 날씨 지도를 만드는 크라우

developer.android.com

 

 

1. manifests 에 Provider 를 추가해 줘야 합니다.! 

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="자신의 앱 패키지명.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
    android:name="android.support.FILE_PROVIDER_PATHS"
    android:resource="@xml/file_paths" />
</provider>

 

2. xml 추가.

위의 meta-data 에 적어놓은 것 처럼 xml 파일에 file_paths 의 이름으로 파일을 추가해줍니다. 이름 바꿔도 상관없습니다.

다만 provider에 적은 이름을 똑같이 사용하여 만들어야합니다. 

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-files-path name="my_images" path="/" />
</paths>

 

설정은 끝났습니다

 

0. File path 변수 , uri 변수 추가 

private lateinit var currentPhotoPath: String
private var getPhotoURI: Uri? = null

 

1. 버튼 리스너 설정 

tvTakePicture.setOnClickListener {
	startCapture()
}

 

2. 사진찍기 함수 설정 

private fun startCapture() {
    Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
        takePictureIntent.resolveActivity(requireActivity().packageManager)?.also {
            val photoFile: File? = try {
                createImageFile()
            } catch (ex: IOException) {
                null
            }
            photoFile?.also {
                val photoURI: Uri = FileProvider.getUriForFile(
                    requireActivity(),
                    Constants.FILE_PROVIDER,
                    it
                )
                getPhotoURI = photoURI

                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
                takePictureLauncher.launch(takePictureIntent)
            }
        }
    }
}

 

3. 설정해둔 File Path 에 공간을 만들고 파일 만드는 함수 추가

@Throws(IOException::class)
private fun createImageFile(): File {
    val timeStamp: String = SimpleDateFormat(DATE_TYPE).format(Date())
    val storageDir: File? =
        requireActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES)
    return File.createTempFile(
        "JPEG_${timeStamp}_",
        ".jpg",
        storageDir
    ).apply {
        currentPhotoPath = absolutePath
    }
}

 

 

4. 사진 가져오는 Launcher 생성 (사진찍고 가져오기만 필요하실 경우 여기서 URI 만 사용해서 끝내면 됩니다.) 

private val takePictureLauncher =
    registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
        if (it.resultCode == Activity.RESULT_OK) {
            getPhotoURI?.let { uri ->
                cropSingleImage(uri)
            }
            return@registerForActivityResult
        }
    }

 

 

 

5. Crop Intent 설정 함수 추가 

private fun cropSingleImage(photoUriPath: Uri) {
    val cropIntent = Intent(CROP_INTENT).apply {
        flags = Intent.FLAG_GRANT_WRITE_URI_PERMISSION
        flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
        setDataAndType(photoUriPath, IMAGE_TYPE)
        putExtra(ASPECT_X, 1)
        putExtra(ASPECT_Y, 1)
        putExtra(SCALE, true)
        putExtra(OUTPUT, photoUriPath)
    }

    val list = requireActivity().packageManager.queryIntentActivities(cropIntent, 0)

    requireActivity().grantUriPermission(
        list[0].activityInfo.packageName,
        photoUriPath,
        Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION
    )

    requireActivity().grantUriPermission(
        list[0].activityInfo.packageName, photoUriPath,
        Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION
    )

    val intent = Intent(cropIntent).apply {
        flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
        flags = Intent.FLAG_GRANT_WRITE_URI_PERMISSION
        component = ComponentName(list[0].activityInfo.packageName, list[0].activityInfo.name)
    }

    cropPictureLauncher.launch(intent)
}

 

6. crop Launcher 생성 

private val cropPictureLauncher =
    registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
        if (it.resultCode == Activity.RESULT_OK) {
            val file = File(currentPhotoPath)// 사용하면 됨
            dismiss()
            return@registerForActivityResult
        }
        dismiss()
    }

 

 

이상입니다. !