安卓Webview - 完全清除缓存

141

我在一个Activity中有一个WebView,当它加载网页时,该页面从Facebook收集一些背景数据。

但我看到的是,每次打开并刷新应用程序时,显示在应用程序中的页面都是相同的。

我尝试设置WebView不使用缓存并清除WebView的缓存和历史记录。

我还遵循了这里的建议:如何清空WebView的缓存?

但是这些都无法解决问题,有人有任何想法吗?因为这是我的应用程序的重要部分。

    mWebView.setWebChromeClient(new WebChromeClient()
    {
           public void onProgressChanged(WebView view, int progress)
           {
               if(progress >= 100)
               {
                   mProgressBar.setVisibility(ProgressBar.INVISIBLE);
               }
               else
               {
                   mProgressBar.setVisibility(ProgressBar.VISIBLE);
               }
           }
    });
    mWebView.setWebViewClient(new SignInFBWebViewClient(mUIHandler));
    mWebView.getSettings().setJavaScriptEnabled(true);
    mWebView.clearHistory();
    mWebView.clearFormData();
    mWebView.clearCache(true);

    WebSettings webSettings = mWebView.getSettings();
    webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);

    Time time = new Time();
    time.setToNow();

    mWebView.loadUrl(mSocialProxy.getSignInURL()+"?time="+time.format("%Y%m%d%H%M%S"));

所以我实现了第一个建议(但将代码更改为递归)

private void clearApplicationCache() {
    File dir = getCacheDir();

    if (dir != null && dir.isDirectory()) {
        try {
            ArrayList<File> stack = new ArrayList<File>();

            // Initialise the list
            File[] children = dir.listFiles();
            for (File child : children) {
                stack.add(child);
            }

            while (stack.size() > 0) {
                Log.v(TAG, LOG_START + "Clearing the stack - " + stack.size());
                File f = stack.get(stack.size() - 1);
                if (f.isDirectory() == true) {
                    boolean empty = f.delete();

                    if (empty == false) {
                        File[] files = f.listFiles();
                        if (files.length != 0) {
                            for (File tmp : files) {
                                stack.add(tmp);
                            }
                        }
                    } else {
                        stack.remove(stack.size() - 1);
                    }
                } else {
                    f.delete();
                    stack.remove(stack.size() - 1);
                }
            }
        } catch (Exception e) {
            Log.e(TAG, LOG_START + "Failed to clean the cache");
        }
    }
}
然而,这仍然没有改变页面显示的内容。在我的桌面浏览器中,我得到的HTML代码与WebView生成的网页不同,因此我知道WebView一定在某个地方进行缓存。
在IRC频道上,有人指出可以通过删除URL连接的缓存来解决问题,但我还不知道如何将其应用于WebView。 http://www.androidsnippets.org/snippets/45/ 如果我删除我的应用程序并重新安装它,我就可以获得最新的网页版本,即非缓存版本。主要问题是链接在网页上进行更改,所以网页的前端完全没有改变。

1
mWebView.getSettings().setAppCacheEnabled(false); 没有起作用吗? - Paul
16个回答

236

最佳答案,我想知道为什么它没有被接受..赞 Akshat :) - Karthik
3
对我来说没什么运气。不知道是否有什么变化?我可以通过载入google.com的WebView,即使使用了clearCache(true)后,该WebView仍然认为我已登录。 - lostintranslation
2
@lostintranslation 你可能想要删除cookies。虽然我相信你现在已经知道了。 - NineToeNerd
需要分配对象吗? WebView obj = new WebView(this); obj.clearCache(true); 总之,对我来说非常好,已点赞! - Giorgio Barchiesi

50

上面由Gaunt Face发布的编辑后的代码片段存在一个错误,即如果一个目录因为其中一个文件无法删除而删除失败,代码会在无限循环中继续重试。我改写了它使其真正递归,并添加了一个numDays参数,这样你就可以控制要修剪的文件必须有多旧:

//helper method for clearCache() , recursive
//returns number of deleted files
static int clearCacheFolder(final File dir, final int numDays) {

    int deletedFiles = 0;
    if (dir!= null && dir.isDirectory()) {
        try {
            for (File child:dir.listFiles()) {

                //first delete subdirectories recursively
                if (child.isDirectory()) {
                    deletedFiles += clearCacheFolder(child, numDays);
                }

                //then delete the files and subdirectories in this dir
                //only empty directories can be deleted, so subdirs have been done first
                if (child.lastModified() < new Date().getTime() - numDays * DateUtils.DAY_IN_MILLIS) {
                    if (child.delete()) {
                        deletedFiles++;
                    }
                }
            }
        }
        catch(Exception e) {
            Log.e(TAG, String.format("Failed to clean the cache, error %s", e.getMessage()));
        }
    }
    return deletedFiles;
}

/*
 * Delete the files older than numDays days from the application cache
 * 0 means all files.
 */
public static void clearCache(final Context context, final int numDays) {
    Log.i(TAG, String.format("Starting cache prune, deleting files older than %d days", numDays));
    int numDeletedFiles = clearCacheFolder(context.getCacheDir(), numDays);
    Log.i(TAG, String.format("Cache pruning completed, %d files deleted", numDeletedFiles));
}

希望对其他人有用 :)


很棒的例程,为我们节省了很多痛苦。 - Mr Ed
我可以在应用程序中使用这段代码来清除我手机上安装的某些应用程序的缓存吗? - Si8
如果需要删除整个目录,使用Runtime.getRuntime().exec("rm -rf "+dirName+"\n");不是更简单吗? - source.rar
@source.rar 是的,但是这样你就无法保留比 x 天更年轻的文件了,而通常你会希望有一个缓存文件夹。 - markjan
你可能想把 getTime() 放到循环外的变量中,这样你就不需要每次都调用它了。 - Fred
这段代码能否仅删除缓存中的HTML文件? - user4951834

49

我找到了你需要的解决方法:

context.deleteDatabase("webview.db");
context.deleteDatabase("webviewCache.db");

由于某些原因,Android会对URL进行错误的缓存,导致它会意外地返回旧数据而非你需要的新数据。当然,你可以从数据库中删除这些条目,但在我的情况下,我只想访问一个URL,因此清空整个数据库更容易。

不要担心,这些数据库只与您的应用程序相关,因此您不会清除整个手机的缓存。


谢谢,这是一个非常巧妙的技巧。它值得更广泛地被知晓。 - Philip Sheard
2
这在蜂巢中会抛出一个令人不满的异常:06-14 22:33:34.349: ERROR/SQLiteDatabase(20382): Failed to open the database. closing it. 06-14 22:33:34.349: ERROR/SQLiteDatabase(20382): android.database.sqlite.SQLiteDiskIOException: disk I/O error 06-14 22:33:34.349: ERROR/SQLiteDatabase(20382): at android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method) - Rafael Sanches
谢谢 Rafael,我想这是因为在Honeycomb中已经解决了原始问题。有人知道是否是这种情况吗? - Scott
只需在onBackPressed()或返回按钮中加入两行代码即可使返回栈中不保留历史记录,谢谢,这样节省了很多时间。 - CrazyMind
这似乎并没有清除JS缓存,只有HTML..是这样吗? - Immanuel

42

在您退出应用程序时清除所有Webview缓存:

CookieSyncManager.createInstance(this);         
CookieManager cookieManager = CookieManager.getInstance();        
cookieManager.removeAllCookie();

对于Lollipop及以上版本:

CookieSyncManager.createInstance(this);         
CookieManager cookieManager = CookieManager.getInstance();        
cookieManager.removeAllCookies(ValueCallback);

1
拯救了我的生命和一天。 - Uday Nayak
2
如果您的活动中没有访问Webview,则可以正常工作。还请注意,此API已被弃用,因此在L+设备上请改用“removeAllCookies(ValueCallback)”API。 - Akshat
我应该用什么替换ValueCallBack? - Qaiser Hussain
@QaisarKhanBangash 新的 ValueCallback<Boolean>() { @Override public void onReceiveValue(Boolean value) { } } - amalBit

25

清除 Webview 中的 Cookie 和缓存,

    // Clear all the Application Cache, Web SQL Database and the HTML5 Web Storage
    WebStorage.getInstance().deleteAllData();

    // Clear all the cookies
    CookieManager.getInstance().removeAllCookies(null);
    CookieManager.getInstance().flush();

    webView.clearCache(true);
    webView.clearFormData();
    webView.clearHistory();
    webView.clearSslPreferences();

6
唯一适用于我的解决方案
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
    CookieManager.getInstance().removeAllCookies(null);
    CookieManager.getInstance().flush();
} 

3

这应该可以清除您的应用程序缓存,这应该是您的Webview缓存所在的位置

File dir = getActivity().getCacheDir();

if (dir != null && dir.isDirectory()) {
    try {
        File[] children = dir.listFiles();
        if (children.length > 0) {
            for (int i = 0; i < children.length; i++) {
                File[] temp = children[i].listFiles();
                for (int x = 0; x < temp.length; x++) {
                    temp[x].delete();
                }
            }
        }
    } catch (Exception e) {
        Log.e("Cache", "failed cache clean");
    }
}

尝试了这个(稍微改变了代码),但仍然得到相同的结果 -> 如上所述 - Matt Gaunt

3
webView.clearCache(true)
appFormWebView.clearFormData()
appFormWebView.clearHistory()
appFormWebView.clearSslPreferences()
CookieManager.getInstance().removeAllCookies(null)
CookieManager.getInstance().flush()
WebStorage.getInstance().deleteAllData()

2

在Kotlin中,只需使用以下代码即可:

WebView(applicationContext).clearCache(true)

1

之前的代码已经被弃用了。因此,在基于Kotlin的Android项目中,您可以尝试使用这个:

CookieManager.getInstance().removeAllCookies {  
   // Do your work here.
}

1
我使用这种方法来解决我的问题。我看到很多答案都包含“CookieManager.getInstance().flush()”。实际上,这并不是必要的,因为flush()会将cookie写入数据库中。如果你想清除所有的数据库,可以尝试使用WebStorage.getInstance().deleteAllData();但在大多数情况下,这并不是必要的。 - JeckOnly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接