본문 바로가기

안드로이드/팁

[AOS] 카메라로 촬영한 이미지 경로 가져오기 ( targetSdk 30 대응 )

반응형

많은 수의 앱에서 갤러리에서 사진을 업로드하고 카메라로 사진을 찍어서 올리는 행위를 합니다.

인스타그램이나 페이스북처럼 sns을 통해서 자신의 일상을 사진의 형태로 공유하기 때문인데요. 그러다보니 저도 앱들을 개발하면서 이미지 관련 포스팅을 여러개 남겼습니다.

웹뷰에서 이미지 업로드 , 카메라 갤러리에서 이미지 가져오기 (코틀린),   카메라 갤러리에서 이미지 가져오기 (자바)

 

Webview 이미지 업로드 구현하기 ( 카메라, 갤러리 )

웹뷰가 아닌 네이티브만 작업하시는 분들은 제 블로그에 다른 포스팅을 참고해주세요 ! ( 그리고 해당 포스팅은 minsdk 21, Kotlin 기준으로 작업됐습니다. ) [안드로이드/코틀린] 카메라와 갤러리에

superwony.tistory.com

그런데 또 같은 주제로 포스팅을 하는 이유는 'targetSdk 30' 강제 적용 때문입니다. ( 공식문서 )

간략하게 설명드리자면 외부 저장소를 모든 앱들과 공용으로 사용했었는데 앱별 외부 저장소를 제공하도록 변경됐습니다. 자세한 사항은 구글링이나 제가 참고한  블로그 포스팅을 참고해주세요.  

 

구현 코드는 마이그레이션 하는 분들을 위해 간략하게 설명드리고 전체 소스는 뒤에 붙이도록 하겠습니다.

 

| 기본 원리

기본 카메라 앱을 실행시켜서 찍은 사진을 onActivityResult로 결과 값을 받아서 미리 지정된 경로에 이미지 파일을 코드로 저장하는 방식으로 코드 구현 합니다. 

targetSdk30으로 마이그레이션 하는 경우  이미지 파일 저장시 사용된 경로만 변경해주면 됩니다.

기존에 구현된 버전을 마이그레이션 하는 경우 

    private fun createImageFile(): File { // 사진이 저장될 폴더 있는지 체크

        var imageName = "plantdiary_${System.currentTimeMillis()}"

        var file: File? = getExternalFilesDir(Environment.DIRECTORY_PICTURES)

        return File.createTempFile(imageName,".jpg", file).apply {
            cameraImagePath = absolutePath
        }
    }

'getExternalFilesDir' 경로에 파일을 생성해 리턴하고 그 경로를 'cameraImagePath' 변수에 담아서 이미지를 헨들링합니다.

 

처음 구현하시는 경우 ( createImageFile 메소드 외 전체 코드 ) 

카메라 권한 체크 

    <uses-permission android:name="android.permission.CAMERA" />
    private fun showCamera() {
        var cameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
        var storagePermission =
            ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)


        if (cameraPermission == PackageManager.PERMISSION_DENIED || storagePermission == PackageManager.PERMISSION_DENIED
        ) {
            ActivityCompat.requestPermissions(
                this,
                arrayOf(
                    Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE
                ),
                REQ_PERMISSION_CAMERA
            )
        } else {

            var state = Environment.getExternalStorageState()
            if (TextUtils.equals(state, Environment.MEDIA_MOUNTED)) {
                var intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
                intent.resolveActivity(packageManager)?.let {
                    createImageFile().let {
                        var photoUri = FileProvider.getUriForFile(
                            this,
                            BuildConfig.APPLICATION_ID + ".provider",
                            it
                        )
                        intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri)
                        startActivityForResult(intent, REQ_CAMERA)
                    }
                }
            }
        }
    }

카메라로 찍은 사진 처리

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (resultCode == Activity.RESULT_OK) {
            when (requestCode) {
            	REQ_CAMERA -> {
                	// cameraImagePath 변수 사용 하여 처리 
                    ....
                
                }
            }    
        }

provider 설정 ( os 7.0 이상 부터 적용 해야하는 부분 ) 

androidManifest.xml

        <provider
                android:name="androidx.core.content.FileProvider"
                android:authorities="${applicationId}.provider"
                android:exported="false"
                android:grantUriPermissions="true">
            <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/provider_paths" />
        </provider>

res > xml 폴더 생성 및 파일 생성 ( 파일명 : provider_paths, 소스상 네이밍으로 변경 가능 ) 

<?xml version="1.0" encoding="utf-8"?> 
<paths xmlns:android="http://schemas.android.com/apk/res/android"> 
	<external-path name="hidden" path="path"/> 
    <external-path name="external_files" path="."/>
</paths>

 

매번 바뀌는 정책들로 고생하시는 개발자분들 힘내세욥 화이팅 

 

 

 

 

 

 

 

 

반응형