If your Android app needs to keep some file cache, it is recommended to store that cache in a known location. Since API level 8 you should use Context.getExternalCacheDir(). Since API level 19 there is also Context.getExternalCacheDirs() in case the device supports multiple external storages.

In any case you end up with this path:

/storage/emulated/0/Android/data/com.example.app.package/cache

When the user uninstalls your app, the whole directory /storage/emulated/0/Android/data/com.example.app.package is gone. That’s correct and desired, especially for cache files. This /cache subdirectory has an additional behaviour. The system knows it’s cache and can purge it in low free storage situation which is not so uncommon on devices with only 16 GB storage and no SD card slot. The user can also manually force clear the cache, either for one individual app or globally for the whole device.

screenshot screenshot

This is when the troubles begin.

When clearing the cache, Android does not kill the running app process and restart it afterward. The process holds on a file inside the cache directory. After Clear Cache, the cache directory is a zombie. It’s still there because the process was holding on a file handle, but it’s not there because the user did Clear Cache. The /cache entry still there, but it’s not a file, nor a directory. It’s not writeable, nor deleteable. Nothing. It’s a zombie, waiting to be buried. The burial happens when the app process stops holding on the cache file handle, e.g. when it quits.

This is deadly for apps with long running background services. That’s all my sync apps. For the users the only practical way to recover is to reboot their devices. That’s not really practical. Some users like to use apps which supposedly keep Android devices fast by purging all the cache, for example shortly after boot time, but still many milliseconds after my sync apps have been started and now running and monitoring file system for changes.

The workaround?

Don’t use /cache. My apps now use /tmp instead. For Android system anything other than /cache is not a cache and therefore is not deleted on Clear Cache. /tmp would never be deleted even at low storage situation. Luckily in my case the cache size is quite small, usually a few MBs, it rarely crosses 10MB mark.

I want my apps to be good Android citizens. But their users certainly don’t appreciate them as good dead citizens. They want them to be alive and working.