delete files from cache based on atime
On android-21 and above, it is possible to use Os.lstat()
to get the atime (time of last access) of files. This should be used when cleaning the file cache instead of mtime (time of last modification) so that cached files like icons that are still being used do not get deleted. I tried adding this to !260 (merged) but I was getting this very odd stacktrace which seems like a bug in the Android SDK:
E/AndroidRuntime( 1132): FATAL EXCEPTION: main
E/AndroidRuntime( 1132): java.lang.VerifyError: org/fdroid/fdroid/Utils
E/AndroidRuntime( 1132): at org.fdroid.fdroid.FDroidApp.updateLanguage(FDroidApp.java:154)
E/AndroidRuntime( 1132): at org.fdroid.fdroid.FDroidApp.onCreate(FDroidApp.java:185)
E/AndroidRuntime( 1132): at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1000)
E/AndroidRuntime( 1132): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4391)
E/AndroidRuntime( 1132): at android.app.ActivityThread.access$1300(ActivityThread.java:141)
E/AndroidRuntime( 1132): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1294)
E/AndroidRuntime( 1132): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime( 1132): at android.os.Looper.loop(Looper.java:137)
E/AndroidRuntime( 1132): at android.app.ActivityThread.main(ActivityThread.java:5041)
E/AndroidRuntime( 1132): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 1132): at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime( 1132): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
E/AndroidRuntime( 1132): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
E/AndroidRuntime( 1132): at dalvik.system.NativeStart.main(Native Method)
Here's the code that I used:
/**
* Recursively delete files in {@code dir} that were last used
* {@code secondsAgo} seconds ago. On {@code android-21} and newer, this
* is based on the last access of the file, on older Android versions, it is
* based on the last time the file was modified, e.g. downloaded.
*
* @param dir The directory to recurse in
* @param secondsAgo The number of seconds old that marks a file for deletion.
*/
@TargetApi(21)
public static void clearOldFiles(File dir, long secondsAgo) {
long olderThan = (System.currentTimeMillis() / 1000L) - secondsAgo;
for (File f : dir.listFiles()) {
if (f.isDirectory()) {
clearOldFiles(f, olderThan);
f.delete();
}
if (Build.VERSION.SDK_INT < 21) {
if (FileUtils.isFileOlder(f, olderThan)) {
f.delete();
}
} else {
try {
StructStat stat = Os.lstat(f.getAbsolutePath());
if (stat.st_atime < olderThan) {
f.delete();
}
} catch (ErrnoException e) {
e.printStackTrace();
}
}
}
}