본문 바로가기
프로그래밍/Android, iOS

[Android] 외부저장소 권한 없이 이미지 파일 exIfInterface 가져오기

by YuminK 2021. 12. 4.

안드로이드 10부터 WRITE_EXTERNAL_STORAGE 권한을 사용하는 것이 제한이 된다.

각 어플마다 가지고 있는 저장소에서는 자유롭게 접근이 가능하지만 다른 어플의 저장소에 접근하는 경우 접근을 제한하고 있다.

private fun createTempFile()
{
    val strTime = CB_AppFunc.getDateStringForSave()
    val storageDir = requireActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES)
    val imageFile = File.createTempFile(
        strTime,      // prefix
        ".jpg",  // suffix
        storageDir    // directory
    ).apply { deleteOnExit() }

    imageBitmap = null
    strFilePath = imageFile.absolutePath
    imageUri =  FileProvider.getUriForFile(requireContext(), getString(R.string.file_provider), imageFile)
}

위의 temp파일을 생성하는 코드를 보면 getExternalFilesDir() 함수를 사용하여 어플 개인 저장소에 접근하여 파일을 생성한다. 그래서 카메라를 통해 Uri를 전달하고 Path에 접근하여 exitifInterface를 가지고 오더라도 문제가 발생하지 않았다. (개인 저장소)

 

fun changeImageOrientation(imageBitmap: Bitmap, exifInterface: ExifInterface): Bitmap?
{
    try
    {
        var bitmap = imageBitmap
        val iOrientation = exifInterface
            .getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED)

        when (iOrientation)
        {
            ExifInterface.ORIENTATION_ROTATE_90 ->
                bitmap = rotateBitmap(imageBitmap, 90f)
            ExifInterface.ORIENTATION_ROTATE_180 ->
                bitmap = rotateBitmap(imageBitmap, 180f)
            ExifInterface.ORIENTATION_ROTATE_270 ->
                bitmap = rotateBitmap(imageBitmap, 270f)
            else -> {}
        }

        return bitmap
    }
    catch (e: Exception)
    {
        e.printStackTrace()
        return null
    }
}
try
{
    val exitIfInterface = ExifInterface(strFilePath!!)
    imageBitmap = CB_AppFunc.changeImageOrientation(imageBitmap!!, exitIfInterface)
}
catch (e: IOException)
{
    e.printStackTrace()
    imageBitmap = null
}

이런 방식으로 코드를 작성해도 카메라는 정상적으로 동작을 하는데... 

이미지 파일을 들고 오는 경우에는 외부 저장소 파일이다 보니까 path를 가지고 접근을 하면 문제가 발생했다. (permission denied)

그래서 결국에는 Uri를 통해서 가져오는 방식으로 변경하니까 정상적으로 exIfInterface정보를 가지고 올 수 있었다.

// N 버전 이상만 화면 회전을 시도한다. (외부 저장소 권한 제거)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{
    try
    {
        val inputStream = CB_AppFunc.application.contentResolver.openInputStream(uri)!!
        val exifInterface = ExifInterface(inputStream)
        imageBitmap = CB_AppFunc.changeImageOrientation(imageBitmap!!, exifInterface)
    }
    catch (e: IOException)
    {
        e.printStackTrace()
        imageBitmap = null
    }

    if(imageBitmap == null)
    {
        Log.e(strTag, "failed to change orientation on image")
        uploadFailed()
        return@launch
    }
}

 

댓글