Home > Mobile >  How could I get the real path when selected an image from gallery without using startActivityForResu
How could I get the real path when selected an image from gallery without using startActivityForResu

Time:11-15

As startActivityForResult has been deprecated, I would rather don't use it for getting the absolute path of the selected image from the gallery.

Therefor I have tried without it as the code below, however it doesn't work. What am I doing wrong?

enter image description here

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center_horizontal"
    tools:context=".MainActivity">
    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@ id/img_camera"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_marginTop="30dp"
        android:layout_marginBottom="30dp"
        android:src="@drawable/camera"/>

   
    <TextView
        android:id="@ id/txt_path"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Path"
        android:layout_marginTop="30dp"/>




</LinearLayout>

MainAcitivty.kt

package com.gearsrun.choosephotoapplication

import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.graphics.drawable.toBitmap
import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target
import com.gearsrun.choosephotoapplication.databinding.ActivityMainBinding
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.OutputStream
import java.util.*


class MainActivity : AppCompatActivity() {
    private lateinit var binding : ActivityMainBinding
    private var mImagePath = ""
    private lateinit var activityResultLauncher:ActivityResultLauncher<Intent>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        val getImage = registerForActivityResult(
            ActivityResultContracts.GetContent(),
            ActivityResultCallback {
                Glide.with(this)
                    .load(it)
                    .centerCrop()
                    .diskCacheStrategy(DiskCacheStrategy.ALL)
                    .listener(object : RequestListener<Drawable>{
                        override fun onLoadFailed(
                            e: GlideException?,
                            model: Any?,
                            target: Target<Drawable>?,
                            isFirstResource: Boolean
                        ): Boolean {
                            Log.e("TAG", "Error loading image", e)
                            return false // important to return false so the error placeholder can be placed
                        }

                        override fun onResourceReady(
                            resource: Drawable?,
                            model: Any?,
                            target: Target<Drawable>?,
                            dataSource: DataSource?,
                            isFirstResource: Boolean
                        ): Boolean {

                            val bitmap: Bitmap = (resource?.toBitmap() ?: null) as Bitmap

                            mImagePath = saveImageToInternalStorage(bitmap)
                            binding.txtPath.text = mImagePath
                            return false
                        }
                    })
            }
        )

        binding.imgCamera.setOnClickListener {
            getImage.launch("image/*")
        }
    }


    private fun saveImageToInternalStorage(bitmap: Bitmap): String {
      val wrapper = ContextWrapper(applicationContext)
        var file = wrapper.getDir(IMAGE_DIRECTORY, Context.MODE_PRIVATE)
        file = File(file,"${UUID.randomUUID()}.jpg")
        try{
            val stream :OutputStream = FileOutputStream(file)
            bitmap.compress(Bitmap.CompressFormat.JPEG,100,stream)
            stream.flush()
            stream.close()
        }catch (e:IOException){
          e.printStackTrace()
        }
        return file.absolutePath

    }

    companion object {
        private const val IMAGE_DIRECTORY = "GearsRunImages"
    }
}

CodePudding user response:

I believe the issue occurred in the implementation of Glide.

Glide was used to load an image, Im assuming the imgCamera was used to preview the loaded image. Therefore, need to add into(binding.imgCamera) in your Glide implementation.

So, after the image loaded, the onResourceReady() will triggered and your logic may run there.

I think, update getImage like in the following code may works

val getImage = registerForActivityResult(
            ActivityResultContracts.GetContent(),
            ActivityResultCallback {
                Glide.with(this)
                    .load(it)
                    .centerCrop()
                    .diskCacheStrategy(DiskCacheStrategy.ALL)
                    .listener(object : RequestListener<Drawable>{
                        override fun onLoadFailed(
                            e: GlideException?,
                            model: Any?,
                            target: Target<Drawable>?,
                            isFirstResource: Boolean
                        ): Boolean {
                            Log.e("TAG", "Error loading image", e)
                            return false // important to return false so the error placeholder can be placed
                        }

                        override fun onResourceReady(
                            resource: Drawable?,
                            model: Any?,
                            target: Target<Drawable>?,
                            dataSource: DataSource?,
                            isFirstResource: Boolean
                        ): Boolean {

                            val bitmap: Bitmap = (resource?.toBitmap() ?: null) as Bitmap

                            mImagePath = saveImageToInternalStorage(bitmap)
                            binding.txtPath.text = mImagePath
                            return false
                        }
                    })
                    .into(binding.imgCamera)
            }
        )
  • Related