Avoid /Android/data/ (app_package) /cache
August 10, 2014
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.
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.