To provide a quick way for the user to clear out the cache, I am using the following function (based on this and this) attached to a Clear Cache button:
static void clearAppCache(Context context) {
try {
File dir = context.getCacheDir();
deleteDir(dir);
} catch (Exception e) {
// TODO: handle exception
}
}
private static boolean deleteDir(File dir) {
if (dir != null && dir.isDirectory()) {
String[] children = dir.list();
for (String aChildren : children) {
boolean success = deleteDir(new File(dir, aChildren));
if (!success) {
return false;
}
}
return dir.delete();
} else if (dir!= null && dir.isFile()) {
return dir.delete();
} else {
return false;
}
}
I'm also setting up my WebView with the same cache path, as follows:
WebSettings webSettings = mWebView.getSettings();
webSettings.setAppCacheEnabled(true);
String cachePath = getApplicationContext().getCacheDir().getAbsolutePath();
webSettings.setAppCachePath(cachePath);
My theory is that calling clearAppCache() will also clear the WebView's cache because all it's doing is clearing out the same cache folder I've set for the WebView.
But since my WebView is now loading a page that uses a service worker, I'm finding that this doesn't seem to be clearing out the service worker cache. I've had reports from one user that, to really clear out the service worker stuff, they have to manually clear the content of the following folder (on their rooted device):
/data/data/com.example.myapp/app_webview/Cache/
Based on this post I have tried adding the following line to my clearAppCache() function:
WebStorage.getInstance().deleteAllData();
But still this doesn't seem to have the effect of clearing the service worker cache.
Any ideas? Yes I know that the service worker cache can be cleared using javascript (see the above-linked post), but I want a way of doing this directly from Android.
I have now found a way to delete the service worker cache. My data directory is at:
/data/user/0/com.app.package
And then within that is:
/cache
/http
/org.chromium.android_webview
/WebView
/code_cache
/files
/shared_prefs
/app_webview
/webview_data.lock
/Web Data
/Web Data-journal
/metrics_guid
/Cookies
/Cookies-journal
/GPUCache
/Service Worker
/QuotaManager
/QuotaManager-journal
/databases
/app_textures
/app_download_internal
/databases
/shaders
Note the presence of a Service Worker sub-directory within app_webview, which is a bit of a giveaway.
So, to clear the service worker cache, it seems that you just have to delete that sub-directory:
File dataDir = context.getDataDir(); // or see https://stackoverflow.com/a/19630415/4070848 for older Android versions
File serviceWorkerDir = new File(dataDir.getPath() + "/app_webview/Service Worker/");
deleteDir(serviceWorkerDir); // function defined in original post
Or, being more brutal, it seems that you can just delete the whole app_webview sub-folder and everything in it:
File dataDir = context.getDataDir(); // or see https://stackoverflow.com/a/19630415/4070848 for older Android versions
File appWebViewDir = new File(dataDir.getPath() + "/app_webview/");
deleteDir(appWebViewDir); // function defined in original post
What still confuses me is that, despite setting the cache path for the WebView with webSettings.setAppCachePath(cachePath) to be in the cache directory (see my original post), the WebView has chosen to use app_webview for service worker caching. Maybe it uses the cache directory for traditional http caching, and chooses its own location (app_webview) for service worker caching? It still doesn't seem right though. Furthermore, as mentioned, one user has reported the presence of a Cache sub-directory within app_webview, and they are on KitKat (Android 4.4) that doesn't support service workers... not sure why that app_webview/Cache directory is in use rather than (or in addition to) cache. I don't have app_webview/Cache at all on mine.
I'm not familiar with the Android<->WebView interactions. But assuming you could run JavaScript from the context of a page in your local origin, the following code should clear out everything in the Cache Storage API for your origin:
async function clearAllCaches() {
const allCaches = await caches.keys();
for (const cache of allCaches) {
caches.delete(cache);
}
}
Using the Clear-Site-Data header is another option, if you have control over a remote webserver that's serving your HTML, and if you know that your users will have a WebView based on Chrome 61+.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With