'Getting all Images in Android

I am building a photo vault where users can hide their photos. I write the following code which traverses through all the directories (except the hidden one) and creates a report mentioning the number of images with directory name and file(images) path.

It works fine and does its job but the problem here is the amount of time it takes to execute.

I run it on my OnePlus 7T with 128 GB Storage and 52% used it takes almost 30-40 seconds to get all the images. That is an insane amount of time for a user to wait every time they want to add an image to the vault.

I want to know what optimization could be made here so that its speed gets optimized. I have tested other similar applications and they are doing it in a snap.

Please let me know if you can help.

@OptIn(ExperimentalTime::class)
private fun getFiles(): List<MyFileModel> {
    val list = mutableListOf<MyFileModel>()

    val time = measureTime {
        Environment.getExternalStorageDirectory().listFiles()?.forEach {file->
            if (file.isDirectory) {
                openDirectory(file)
            } else if (file.isImage) {
                addImage(file)
                Log.i(
                    TAG,
                    "getFiles: image: ${file.name}\nParent File: ${file.parentFile}\nParent: ${file.parent}"
                )
            }
        }
    }
    Log.i(
        TAG,
        "getFiles: took ${time.inWholeHours}h : ${time.inWholeMinutes}m : ${time.inWholeSeconds}s"
    )
    map.keys.forEach {
        Log.i(TAG, "getFiles: There are ${map[it]?.size} images in $it directory")
    }
    return listOf()


}



private fun addImage(file: File) {
    val parentPath = file.parent ?: throw Exception("Could not add file as image. File: $file")
    var folderName: String? = null
    if (parentPath == FileUtils.ROOT_ADDRESS.path) {
        folderName = "STORAGE"
        //File is in the home directory
    } else {
        folderName = parentPath.substring(parentPath.lastIndexOf("/") + 1)
    }
    val files: MutableList<File>? = map[folderName]
    if (files.isNullOrEmpty()) {
        map[folderName] = mutableListOf(file)
    } else {
        files.addIfNotAlreadyAdded(file)
    }
//        Log.i(TAG, "addImage: map: $map")
}

//
private fun openDirectory(file: File) {
    Log.i(TAG, "getFiles: FILE: ${file.absolutePath}")
    if (file.isHidden) return
    if (file.isImage) {
        addImage(file)
        return
    }
    if (file.isDirectory) {
        file.listFiles()?.forEach {
            Log.i(TAG, "openDirectory: file.listFiles().forEach : file: $it")
            if (it.isImage) {
                addImage(it)
            }
            if (it.isDirectory) {
                openDirectory(it)
            }
        }

    }

}

Here is the extensions function that checks if the file is an image or not.

val File.isImage: Boolean
get() {
    val fileName = this.name
    val lasIndexOfDot = fileName.lastIndexOf(".")
    if (lasIndexOfDot == -1) {
        //This means that the file got no extension
        return false
    }
    val extension = fileName.substring(fileName.lastIndexOf(".") + 1).lowercase()

    return extension.equals("png") ||
            extension.equals("jpeg") ||
            extension.equals("jpg") ||
            extension.equals("gif")
}

Thank you :)



Solution 1:[1]

Finally, I was able to do that by implementing the Content Provider. Going through all files and folders in the storage and then checking each file if it is an image or not and that too by looking at the file extension. It was a set of terrible ideas. But in the end, this is how we learn. :)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Waqas Younis