16

I use the following code to create some temp files, and wrapped tem as inputsteam to send to client side.

I understand that the temp files can be deleted automatically by android system when disk space low.

But I hope to I can delete the temp files by myself when I exit the App, how can I do? Thanks!

Code

File outputDir = context.getCacheDir(); // context being the Activity pointer
File outputFile = File.createTempFile("prefix", "extension", outputDir);
Atef Hares
  • 4,715
  • 3
  • 29
  • 61
HelloCW
  • 843
  • 22
  • 125
  • 310

7 Answers7

17

Delete the files in onDestroy if isChangingConfigurations() is false or isFinishing is true. Example:

@Override protected void onDestroy() {
  super.onDestroy();
  if(!isChangingConfigurations()) {
    deleteTempFiles(getCacheDir());
  }
}

private boolean deleteTempFiles(File file) {
  if (file.isDirectory()) {
    File[] files = file.listFiles();
    if (files != null) {
      for (File f : files) {
        if (f.isDirectory()) {
          deleteTempFiles(f);
        } else {
          f.delete();
        }
      }
    }
  }
  return file.delete();
}
Onur
  • 5,617
  • 3
  • 26
  • 35
Jared Rummler
  • 37,824
  • 19
  • 133
  • 148
9

call the deleteOnExit() method!

Or

call the delete() method in the onStop() of your activity.

Edit:

It might be better if you called delete() in onDestroy() to insure that your code works even if app is destroyed by system.

Atef Hares
  • 4,715
  • 3
  • 29
  • 61
  • 4
    Thanks! but deleteOnExit() "Note that on Android, the application lifecycle does not include VM termination, so calling this method will not ensure that files are deleted. Instead, you should use the most appropriate out of: " – HelloCW Feb 26 '17 at 03:55
  • If I use delete(), I have to add these file name to a static array, then delete them one by one – HelloCW Feb 26 '17 at 03:57
  • Okay, then call the delete at the `onStop()` – Atef Hares Feb 26 '17 at 03:57
  • I don't think you have another way – Atef Hares Feb 26 '17 at 03:58
  • Thanks! Can I use org.apache.commons.io.FileUtils.forceDelete(getCacheDir()) to delete whole cache folder and all included temp files and sub-folder? – HelloCW Feb 26 '17 at 08:25
  • Note that onStop is *not* the same as actually quitting your app - you don't know exactly when the OS will remove it from memory. http://android.nextapp.com/site/fx/doc/exit – EJoshuaS - Stand with Ukraine Feb 28 '17 at 06:58
  • when the activity is destroyed in memeory by force or by system the [onDestroy()](https://developer.android.com/reference/android/app/Activity.html#onDestroy()) will be called – Atef Hares Feb 28 '17 at 07:13
  • deleteOnExit() called when android device has rebooted,the good way is call delete when your app goes to background – Amin Bahiraee Feb 28 '17 at 07:25
  • @HelloCW If you delete the whole directory, it may even delete files not created by you. – Sridhar Mar 01 '17 at 14:48
  • This still does not get called if the application is terminated while in the background with a "Close All" correct? – justdan0227 Jan 04 '18 at 17:59
  • @HelloCW Thanks. Was wondering why deleteOnExit() wasn't working in android – DIRTY DAVE Nov 08 '21 at 01:22
1

Try Using WorkManager to make sure it cleans up the temp files even after the app is closed.

    override fun doWork(): Result {

            return try {
                applicationContext.cacheDir?.let {
                    if(it.exists()){
                        val entries = it.listFiles()
                        if (entries != null){
                            for (entry in entries) {
                                Timber.i("My file: ${entry.name}")
                                entry.delete()
                            }
                        }
                    }
                }
                Result.success()
            } catch (e: Exception) {
                Timber.e(e)
                Result.failure()
            }

        }
Doilio Matsinhe
  • 2,131
  • 16
  • 29
1

I ended up here looking for a way to remove temp files that I was creating for camera intents, I actually used a combination of Sridhar's answer and the cleanOldFiles function from this answer

I was creating a new image file using createTempFile and then adding that to

public static final HashSet<File> TEMP_FILES = new HashSet<>();

To iterate and remove from the set using the normal foreach loop was throwing a java.util.ConcurrentModificationException so I updated the loop using an Iterator

more on iterators

Thought I'd post in case it helps someone else, thanks to Sridhar and ggrandes from the other post for the help.

public synchronized void cleanTempFiles(final int secondsOld) {
    long now = (System.currentTimeMillis() / 1000);
    for (Iterator<File> iterator = TEMP_FILES.iterator(); iterator.hasNext(); ) {
        File f = iterator.next();
        long expired = (f.lastModified() / 1000) + secondsOld;
        if (now >= expired) {
            Log.d(TAG, "Deleted file - \"" + f.getAbsolutePath() +"\"");
            f.delete();
            iterator.remove();
        }
    }
}

The function removes files older than a given time value in seconds and is called like

cleanTempFiles(3); // or however long
HazeyAce
  • 361
  • 3
  • 12
0

First, keep in mind that "exit" for an Android app means something very different than it does for a desktop application. See this article for details, but the short answer is that, in general, you have no idea when the OS is actually going to close your app (even if it's not visible). In fact, there isn't an explicit guarantee that the OS will close it at all.

A few ideas can be found here (it's C#/Xamarin.Android but same exact idea for Java): How to detect application exit on android?

In addition to the stuff listed there, you could also try registering broadcast receivers for when the phone's shutting down.

Another (worse, in my opinion) way is to simply do this when the app becomes no longer visible (in onStop). As noted above, however, this isn't the same thing as the program actually closing (because you don't know when - or even if - the OS will actually close the app).

Community
  • 1
  • 1
0

It would be better if you can maintain a Set (Avoid Duplicates) for all files you create.

And iterate the file list and delete every file one by one.

 public static final Set<String> TMP_FILES = new HashSet<>();

And delete all by iterating.

public void deleteTempFiles() {
  for(String myTempFile: TMP_FILES) {
    try {
      new File(myTempFile).delete();
    } catch (Exception e) {
      // Handle if needed.
    }
  }
}
Sridhar
  • 1,518
  • 14
  • 27
  • This wouldn't work if one of the temp files in the set was a non-empty directory. – Jared Rummler Mar 02 '17 at 21:30
  • @JaredRummler Its just a sample. If a directory is involved, its should be handled. Also, the question said he's creating temp files using createTempFile(PREFIX, SUFFIX), which will create a file not a directory. – Sridhar Mar 03 '17 at 07:19
  • In the other answer's comments, he posted about deleting the entire cache directory. I just wanted to be clear that this wouldn't work in that scenario. – Jared Rummler Mar 03 '17 at 07:53
0

Unfortunately it appears you have to delete these files one by one, by previously saving them in an array.

That being said, if you check Android Developers page on this issue it makes it as if you could delete the cached files "on a regular basis and also regularly delete other files you no longer need". However I don't think there is an explanation on how to do it.

Luís Gonçalves
  • 338
  • 5
  • 17