Kotlin File.deleteRecursively() doesn't work on cacheDir

Viewed 377

I'm trying to delete the app's cache subfolder (or even the cache folder itself), but nothing happens.

cacheFolder = File(this.cacheDir, "/download")
deleteFolder(cacheFolder)

private fun deleteFolder(fileOrDirectory : File){
    fileOrDirectory.deleteRecursively()
}

The one-liner doesn't work too

this.cacheDir.deleteRecursively()

Any ideas?

3 Answers

It will be better if you use a service to delete the cacheFiles

This is how I did

class DeleteCache(context: Context, workerParams: WorkerParameters) :
    Worker(context, workerParams) {
    override fun doWork(): Result {
        return try {
            applicationContext.cacheDir?.let {
                if (it.exists()) {
                    val entries = it.listFiles()
                    if (entries != null) {
                        for (entry in entries) {
                            entry.delete()
                        }
                    }
                }
            }
            Result.success()
        } catch (e: Exception) {
            Result.failure()
        }
    }
}

The File.deleteRecursively() function unfortunately doesn't tell you the reason for failure to delete. It just returns true or false to show whether the deletion was successful. If it returns false, the directory tree may have been partly deleted.

Instead of using the old java.io.File class, which this function is a Kotlin extension of, it is preferable to use the "newer" java.nio utility classes because these will throw an IOException that describes the reason for failure to delete. Unfortunately, Kotlin does not currently provide a deleteRecursively() function that uses java.nio. It only provides a non-recursive deleteExisting() function on the Path class. So, you could instead write your own Path.deleteRecursively() extension function to live alongside Path.deleteExisting():

import java.io.IOException
import java.nio.file.FileVisitResult
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.SimpleFileVisitor
import java.nio.file.attribute.BasicFileAttributes
import kotlin.io.path.deleteExisting

fun Path.deleteRecursively() {
    Files.walkFileTree(
        this,
        object : SimpleFileVisitor<Path>() {
            override fun visitFile(file: Path, attrs: BasicFileAttributes?): FileVisitResult {
                file.deleteExisting()
                return FileVisitResult.CONTINUE
            }

            override fun postVisitDirectory(dir: Path, exc: IOException?): FileVisitResult {
                if (exc != null)
                    throw exc
                dir.deleteExisting()
                return FileVisitResult.CONTINUE
            }
        }
    )
}

You can then use it like this:

import kotlin.io.path.Path
...
   Path(cacheDir).deleteRecursively()

and if it fails to delete the whole tree, you'll see a stack trace with an exception and a descriptive message.

Thanks for support. Now I got it working. The problem was the DownloadManager

    val url = "$targetUrlFTP/$appName/$downloadingObject/$onlineVer.zip"
    val request = DownloadManager.Request(Uri.parse(url))
    request.setAllowedNetworkTypes((DownloadManager.Request.NETWORK_MOBILE or 
           DownloadManager.Request.NETWORK_WIFI))

    request.setDestinationInExternalFilesDir(this, cacheFolder.toString(), 
           zipFileName)

    val manager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
    downloadID = manager.enqueue(request)

the line request.setDestinationInExternalFilesDir(this, cacheFolder.toString(), zipFileName)completely messed up the path.

Now I have

cacheFolder = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)!!
zipFile = File(cacheFolder, zipFileName)
...
request.setDestinationUri(Uri.fromFile(zipFile))

and everything works. Even

private fun deleteFolder(fileOrDirectory : File){
    fileOrDirectory.deleteRecursively()
}

does.

Next step is to implement java.nio. Thank you Klitos for updating your post. I had no idea how to use it.

Related