Android Q를 타겟으로 할 때 카메라로 찍은 사진 처리

ChodingSense·2021년 4월 21일
0

Android

목록 보기
1/3

새벽에 받은 메시지 하나

나는 Android 10을 대상으로 하니까 크게 상관없을거야.

어? 그런데 얼마전에 신경 쓰이는 메시지를 하나 받았었는데......

11월이라면, 아직 많이 남았지만,

그래 Target Sdk 버전도 30으로 올리고, 미루고 미루던 Scoped Storage를 사용하자.

var cameraUri: Uri

카메라 실행

// Android Q 이상일 경우
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) 
{
	cameraUri = getUriForAndroidQ(contentResolver)
    
    	try 
    	{
    		Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { intent -> 
    			intent.putExtra(MediaStore.EXTRA_OUTPUT, cameraImgUri)
        		startActivityForResult(intent, Constants.TAKE_IMAGE)
            	}
                catch (e: ActivityNotFoundException) 
                {
                
                } 
                catch (e: Exception) 
                {
                
                }
   	}
} 
else 
{
	.......
}

/** 
* uri 가져오자
* Picture 폴더 아래 Choding 폴더에 저장하고 싶다.
**/
fun getUriForAndroidQ(contentResolver: ContentResolver): Uri? 
{
	val folderName = "Choding"
	val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
    	val picturePath = "${Environment.DIRECTORY_PICTURES}${File.separator}$folderName"
        val contentValues = ContentValues()
        contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "$timeStamp.jpg")
        contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg")
        contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, picturePath)

        return contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
}

onActivityResult

if (requestCode == Constants.TAKE_IMAGE && resultCode == Activity.RESULT_OK) 
{
	if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) 
    	{
    		processResult()
    	} 
        else 
        {
            ......
        }
} 
else 
{
	/**
    	* 카메라로 찍은 뒤 취소/뒤로가기를 하면 빈파일(회색)이 갤러리에 남는다.
        * 따라서 지워줘야 함.
        */
	if (requestCode == Constants.TAKE_IMAGE
       		&& resultCode != Activity.RESULT_OK
            	&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) 
        {
        	
                contentResolver.delete(cameraUri, null, null)
      	}
}

이미지 처리

카메라로 찍은 이미지를 회전 처리, 리사이즈를 하여 서버로 업로드하기 위해, 캐시 이미지를 만든다.
후에 캐시 이미지를 지우는걸 잊지 말자!!

private fun processResult() 
{
	/**
    	* 갤러리 새로고침
    	* 여기서 새로고침을 해줘야 카메라 회전 처리를 제대로 할 수 있다.
    	*/
        refreshGallery(this, contentResolver, cameraUri)
        

        /**
         * 화면 회전 처리
         * cursor 방식으로 처리하면 0만 리턴되어 Exif 정보를 이용.
         */
        var degree = 0F
        contentResolver.openInputStream(uri).use { inputStream ->

            val ei = ExifInterface(inputStream)

            val orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)

            degree = when (orientation) 
            {
                ExifInterface.ORIENTATION_ROTATE_90 -> 90.0F
                ExifInterface.ORIENTATION_ROTATE_180 -> 180.0F
                ExifInterface.ORIENTATION_ROTATE_270 -> 270.0F
                else -> 0F
            }

            inputStream?.close()
        }

        /**
         * Uri 로 부터 캐시 이미지를 생성
         * 화면 회전 처리
         */
        contentResolver.openInputStream(uri).use { inputStream ->
            var bitmap = BitmapFactory.decodeStream(inputStream)
            val matrix = Matrix()
            matrix.postRotate(degree)
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)

            /**
             * 리사이즈 처리
             */
            bitmap = resizeBitmapToBase(bitmap, resize)

            bitMapSaveToFileCached(bitmap)

            bitmap.recycle()

            inputStream?.close()
        }
        
 }
 
 
  fun refreshGallery(context: Context, contentResolver: ContentResolver, uri: Uri)
  {
        val pathCursor = contentResolver.query(uri, null, null, null, null)
        pathCursor!!.moveToNext()
        val path = pathCursor.getString(pathCursor.getColumnIndex("_data"))
        pathCursor.close()
        MediaScannerConnection.scanFile(context, arrayOf(path), null, null)
   }
   
   
   fun bitMapSaveToFileCached(bitmap: Bitmap) 
   {
        val file = File.createTempFile(System.currentTimeMillis().toString(), ".jpg" , cacheDir )
        
        try {
            val fos = FileOutputStream(file)
            bitmap.compress(Bitmap.CompressFormat.JPEG , 100 , fos)
            fos.flush()
            fos.close()
        }catch (e : FileNotFoundException) {
            e.printStackTrace()
        } catch (e : IOException) {
            e.printStackTrace()
        } catch (e : Exception) {
            e.printStackTrace()
        }
    }
profile
물고기를 좋아합니다.

0개의 댓글