ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [안드로이드 kotlin] camera, gallery URI 확인 및 주의할 점
    안드로이드(kotlin)/기능 관련 2022. 4. 12. 17:39

    버전업 되고 나서 stoage 부분은 처음 만져봤는데 좀 많이 헤맸기 때문에 까먹지 않기 위해 남깁니다.

     

     

    URI(Uniform Resource Identifier)란?

     - 특정 리소스를 식별하는 통합 자원 식별자를 의미

     

    웹 뿐만 아니라 안드로이드에서도 URI 를 이용하며 이를 이용해 카메라 또는 갤러리 등 에서 선택한 항목을 다룹니다.

     

    안드로이드 storage 정책 변경으로 인해 10 버전 이상에서는 기존처럼 external 로 접근하는 방식이 아니고 ScopeStorage 정책을 적용해야 합니다.

     

    카메라 촬영

    카메라는 camerax 를 이용했으며 촬영한 이미지의 URI 도 확인할 수 있습니다. 코드는 아래와 같습니다.

    val timeStamp: String = SimpleDateFormat(CommonData.FILENAME_FORMAT, Locale.KOREA).format(System.currentTimeMillis())
    
                    val contentValues = ContentValues()
                    contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, timeStamp)
                    contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
    
                    val outputOptions = ImageCapture.OutputFileOptions.Builder(
                        context.contentResolver,
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        contentValues
                    ).build()
    
                    imageCapture?.takePicture(
                        outputOptions,
                        ContextCompat.getMainExecutor(context),
                        object : ImageCapture.OnImageSavedCallback {
                            override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
                                var name = ""
                                val savedUri = outputFileResults.savedUri
                                val result = outputFileResults.let {
                                        uri ->
                                    context.contentResolver.query(savedUri!!, null, null, null, null)
                                }?.use { cursor ->
                                    val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
                                    cursor.moveToFirst()
                                    name = cursor.getString(nameIndex)
                                }
                                ...

    (카메라 촬영할 때 URI 정보 확인)

    camerax 를 사용하여 촬영하면 아래 코드처럼 결과물에 대한 정보를 받을 수 있습니다.

    override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults)

    변수 savedUri 에 저장된 내용을 확인해보면 content://media/external/images/media/688 이런식으로 나타납니다.

     

    이걸 이용해서 imageview 를 이용하거나 glide를 이용해서 이미지를 보여줄 수 있습니다.

     

    uri 정보를 이용해서 file path 를 보고 싶다면 아래처럼 하면 됩니다.

    private fun getPath(uri: Uri): String {
            val cursor: Cursor? = requireContext().contentResolver.query(uri, null, null, null, null )
    
            cursor?.moveToNext()
    
            val path: String? = cursor?.getString(cursor.getColumnIndex("_data"))
    
            cursor?.close()
    
            return path?:""
        }

    그럼 /storage/emulated/0/Pictures/2022-04-12-11-40-34-593.jpg 같이 보여집니다.

     

    갤러리 사용

    갤러리는 아래처럼 호출합니다.

    val intent = Intent(Intent.ACTION_PICK)
    intent.type = MediaStore.Images.Media.CONTENT_TYPE
    intent.data = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    intent.type = "image/*"
    galleryVariable.launch(intent)

     

    그리고 선택한 항목에 대한 값을 받습니다.

    val galleryVariable: ActivityResultLauncher<Intent> =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
                if (it.resultCode == RESULT_OK && it.data != null) {
                    currentImageUri = it.data?.data!!
    
                    try {
                        currentImageUri?.let {
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                                val source = ImageDecoder.createSource(
                                    context?.contentResolver!!,
                                    currentImageUri
                                )
    
                                val imagePath: String = getPath(currentImageUri)!!
                                val imageFileName = imagePath.split("/").last()
    
                                photoGalleryVisibilityStatus(imageFileName)
                            } else {
                            ...

    선택한 이미지에 대한 정보는 result data 로 담기게 되며 it.data.data 로 URI 정보를 뽑아낼 수 있습니다.

    변수 currentImageUri 에 content://media/external/images/media/637 같은 URI 정보가 담기게 됩니다.

     

     

     

    갤러리 intent 적용시 주의할 점

    갤러리에서 이미지를 선택하면 해당 이미지 경로를 받아서 file path 를 확인해야하는데 content://media/external/images/media/688 이렇게 나오지 않고 content://com.android.providers.media.documents/document/image%3A40 이런식으로만 나오는 문제가 있었습니다.

    content://media/external/images/media/ 형태로 만들고 싶은데 제대로 나오지 않아서 이런 저런 방식으로 하루 반을 헤매다가 근본적으로 처음 읽는 부분에 뭔가 다른 방식을 적용해 보면 되지 않을까 하는 생각을 하게 되어 intent 부분을 변경하였더니 원하는 형태로 나타났습니다.

     

    갤러리 호출 시 처음 적용한 코드(원하지 않는 형태로 나타났음)

    val intent = Intent(Intent.ACTION_GET_CONTENT)
    intent.type = MediaStore.Images.Media.CONTENT_TYPE
    intent.data = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
    intent.type = "image/*"
    galleryVariable.launch(intent)

    (Intent.ACTION_GET_CONTENT 를 적용했었음)

    이렇게 적용하면 content://com.android.providers.media.documents/document/image%3A40 이 나타납니다.

     

    file path 를 확인하기 위해서는 

    Intent.ACTION_PICK 을 적용시켜야 합니다.

    Intent.ACTION_GET_CONTENT 을 사용한 상태로 file path 를 찾는다면 아래와 같은 에러가 나타나게됩니다.

     

     

    이상으로 카메라, 갤러리 URI 사용 간단 정리를 마칩니다. 

    댓글

Designed by Tistory.