pick multiple files in android poster

How to pick multiple files from Android

In this tutorial, I am explaining how to pick multiple files in android using the default file chooser. By using this example, you can select images and files. In my previous post, I explained how to capture images using a content provider.

Step to pick multiple files in android

  • Setup file picking intent for multiple files and registerForActivityResult.
  • on activity, result get the select files URI.
  • Store the image in a defined location from the URI.
  • Display the image from the file location.

Setup File Picking Intent

Once we got the permission next step is to set up the intent to pick multiple images from the gallery or from another location.

val selectImagesActivityResult =
                registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
                    if (result.resultCode == Activity.RESULT_OK) {

                    }
                }
    val intent = Intent(ACTION_GET_CONTENT)
                intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
                intent.type = "*/*"
                selectImagesActivityResult.launch(intent)

In the above code,

Intent.EXTRA_ALLOW_MULTIPLE to true set the intent to select multiple files.

intent.type = "*_/*_" to allow intent to accept all kinds of files like images, pdf and etc.

if you want to allow only images, use intent.type = "image_/*_"

Finally, register startActivityResult with the intent we created. This is redirected to the default file chooser to select our needed files.

Get File URI from the result

Once all the files are selected, It will come to the Activity result with the result as a response. The result contains Intent with data.

If user selected multiple images, it will come to the intent clipData and if the user selected only one image then we need to check it in intent data.

 val selectImagesActivityResult =
                registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
                    if (result.resultCode == Activity.RESULT_OK) {
                        val data: Intent? = result.data
                        //If multiple image selected
                        if (data?.clipData != null) {
                            val count = data.clipData?.itemCount ?: 0
                            for (i in 0 until count) {
                                val imageUri: Uri? = data.clipData?.getItemAt(i)?.uri
                            }
                        }
                        //If single image selected
                        else if (data?.data != null) {
                            val imageUri: Uri? = data.data
                        }
                    }
                }

If multiple files are selected, clipData has all the selected file URI. So, loop through the clipdata and get all the file URI.

Get File From URI

Now we are having the URI of the selected files. Let’s get the File from the URI. I have created a method to get the Files from the URI.

private fun getImageFromUri(imageUri: Uri?) : File? {
            imageUri?.let { uri ->
                val mimeType = getMimeType(this@MainActivity, uri)
                mimeType?.let {
                    val file = createTmpFileFromUri(this, imageUri,"temp_image", ".$it")
                    file?.let { Log.d("image Url = ", file.absolutePath) }
                    return file
                }
            }
            return null
        }

        private fun getMimeType(context: Context, uri: Uri): String? {
            //Check uri format to avoid null
            val extension: String? = if (uri.scheme == ContentResolver.SCHEME_CONTENT) {
                //If scheme is a content
                val mime = MimeTypeMap.getSingleton()
                mime.getExtensionFromMimeType(context.contentResolver.getType(uri))
            } else {
                //If scheme is a File
                //This will replace white spaces with %20 and also other special characters. This will avoid returning null values on file name with spaces and special characters.
                MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(File(uri.path)).toString())
            }
            return extension
        }

        private fun createTmpFileFromUri(context: Context, uri: Uri, fileName: String, mimeType: String): File? {
            return try {
                val stream = context.contentResolver.openInputStream(uri)
                val file = File.createTempFile(fileName, mimeType,cacheDir)
                FileUtils.copyInputStreamToFile(stream,file)
                file
            } catch (e: Exception) {
                e.printStackTrace()
                null
            }
        }

in the above code, The createTmpFileFromUri() creates the Temp file in the cache directory and writes the selected file in the cache directory using the given URI. The getMimeType() get the type of the file like pdf or jpg.

Finally, getImageFromUri() will return the file location where the selected images are stored in thecache directory.

Display the selected Files

Now we got the file locations of the selected images. let load the files into recyclerview and display. In this example, I have selected images and displayed images in recyclerview.

lateinit var imageAdapter: ImageAdapter
    var selectedPaths = mutableListOf<String>()
    imageAdapter = ImageAdapter()
    rvImages.adapter = imageAdapter

    val selectImagesActivityResult =
                registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
                    if (result.resultCode == Activity.RESULT_OK) {
                        val data: Intent? = result.data
                        //If multiple image selected
                        if (data?.clipData != null) {
                            val count = data.clipData?.itemCount ?: 0

                            for (i in 0 until count) {
                                val imageUri: Uri? = data.clipData?.getItemAt(i)?.uri
                                val file = getImageFromUri(imageUri)
                                file?.let {
                                    selectedPaths.add(it.absolutePath)
                                }
                            }
                            imageAdapter.addSelectedImages(selectedPaths)
                        }
                        //If single image selected
                        else if (data?.data != null) {
                            val imageUri: Uri? = data.data
                            val file = getImageFromUri(imageUri)
                            file?.let {
                                selectedPaths.add(it.absolutePath)
                            }
                            imageAdapter.addSelectedImages(selectedPaths)
                        }
                    }
                }

Deleting the Cache Directory

Once done with all your file operations, we need to clear the files from the cache directory. you can do this by using the below function.

fun deleteTempFiles(file: File = cacheDir): Boolean {
            if (file.isDirectory) {
                val files = file.listFiles()
                if (files != null) {
                    for (f in files) {
                        if (f.isDirectory) {
                            deleteTempFiles(f)
                        } else {
                            f.delete()
                        }
                    }
                }
            }
            return file.delete()
        }

Screenshots:

select file screenshot
selecting files
after selecting files

Source:

You can download the source on Github.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *


Latest Posts