Android Webview-キャッシュを完全にクリアします


111

アクティビティの1つにWebViewがあり、それがWebページをロードすると、ページは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");
        }
    }
}

ただし、ページの表示内容は変更されていません。デスクトップブラウザーで、WebViewで生成されたWebページに異なるHTMLコードを取得しているので、WebViewがどこかにキャッシュされている必要があります。

IRCチャネルで、URL接続からキャッシュを削除するための修正を指摘されましたが、まだWebViewに適用する方法がわかりません。

http://www.androidsnippets.org/snippets/45/

アプリケーションを削除して再インストールすると、Webページを最新の状態(つまり、キャッシュされていないバージョン)に戻すことができます。主な問題は、ウェブページのリンクに変更が加えられるため、ウェブページのフロントエンドが完全に変更されていないことです。


1
mWebView.getSettings().setAppCacheEnabled(false);うまくいきませんでしたか?
ポール

回答:


45

上記のGaunt Faceによって投稿された編集済みコードスニペットには、ファイルの1つを削除できないためにディレクトリの削除に失敗した場合、コードが無限ループで再試行を続けるというエラーが含まれています。本当に再帰的になるように書き直し、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

アプリ内でこのコードを使用して、電話にインストールされている特定のアプリのキャッシュをクリアできますか?
Si8 2013年

ディレクトリ全体を削除する必要がある場合、Runtime.getRuntime()。exec( "rm -rf" + dirName + "\ n");は実行されません。簡単になりますか?
source.rar 14年

@ source.rarはい。ただし、x日前より古いファイルを保持することはできません。これは通常、キャッシュフォルダーに必要です。
markjan 2014

205

キャッシュをクリアするためのエレガントでシンプルな解決策を見つけました

WebView obj;
obj.clearCache(true);

http://developer.android.com/reference/android/webkit/WebView.html#clearCache%28boolean%29

私はキャッシュをクリアする方法を見つけようとしましたが、上記の方法からできることはローカルファイルを削除することだけでしたが、RAMをクリーンアップすることはありませんでした。

API clearCacheは、Webビューで使用されていたRAMを解放するため、Webページを再度ロードする必要があります。


11
ここで最良の答えです。
user486134 2013

最良の回答であり、なぜ受け入れられないのかと思います。KudosAkshat :)
Karthik

1
私には運がありません。何か変わったのかしら?google.comでWebViewをロードできますが、clearCache(true)の後でも、WebViewはまだログインしていると考えています。
lostintranslation 2015

2
@lostintranslationそのためには、おそらくCookieを削除する必要があります。きっとあなたはそれを今までに見つけたと確信していますが。
NineToeNerd 2016

オブジェクトを割り当てる必要がありますか?WebView obj = new WebView(this); obj.clearCache(true); とにかく、私にとってとても良い、賛成です!
Giorgio Barchiesi

45

あなたが探していた修正を見つけました:

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

なんらかの理由で、Androidは必要な新しいデータの代わりに誤ってURLのキャッシュを返し続けます。確かに、DBからエントリを削除するだけでもかまいませんが、私の場合は1つのURLにアクセスするだけなので、DB全体を吹き飛ばす方が簡単です。

また、心配する必要はありません。これらのDBはアプリに関連付けられているだけなので、電話全体のキャッシュをクリアしていません。


おかげで、これは信じられないほど巧妙なトリックです。もっと広く知られるに値する。
Philip Sheard、

2
これはハニカムで厄介な例外をスローします:06-14 22:33:34.349:ERROR / SQLiteDatabase(20382):データベースを開くことができませんでした。それを閉じます。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(ネイティブメソッド)
Rafael Sanches

乾杯ラファエル、私はこれが最初の問題がハニカムで解決されたためだと思いたいです。これが事実であるかどうか誰かが知っていますか?
スコット

onBackpress()または戻るボタンに2行追加するだけで、多くの時間を節約できたので、履歴がバックスタックに残りません。
CrazyMind 2016

36

APPからサインアウトするときにすべての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 2017

ValueCallBackで何を置き換える必要がありますか?
Qaisar Khan Bangash

@QaisarKhanBangash new ValueCallback <Boolean>(){atOverride public void onReceiveValue(Boolean value){}}
amalBit

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

私のために働く唯一の解決策

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
    CookieManager.getInstance().removeAllCookies(null);
    CookieManager.getInstance().flush();
} 

2

Kotlinで以下のコードを使用するだけでうまくいきます

WebView(applicationContext).clearCache(true)

2

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();


0

入力フィールドをクリックしたときにフォームデータがオートポップとして表示されないようにするには、以下の方法を使用してください。

getSettings().setSaveFormData(false);

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

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

それは私のウェブビューでグーグルアカウントをクリアすることができます


2
CookieSyncManagerの価格は低くなっています
開発者

-1

使用例:アイテムのリストはリサイクラービューに表示されます。アイテムをクリックすると、リサイクラービューが非表示になり、アイテムのURLを含むWebビューが表示されます。

問題: 私は開いたら、私は同様の問題を抱えているurl_oneのWebViewで、その後別のものを開こうとすると、url_twoそれが示し、WebViewの中url_one背景までurl_twoロードされます。

解決策: 私は何をしたか解決するためには、負荷空白の文字列である""としてurlちょうど隠れる前url_oneとロードurl_two

出力: webviewに新しいURLをロードするたびに、他のWebページがバックグラウンドで表示されません。

コード

public void showWebView(String url){
        webView.loadUrl(url);
        recyclerView.setVisibility(View.GONE);
        webView.setVisibility(View.VISIBLE);
    }

public void onListItemClick(String url){
   showWebView(url);
}

public void hideWebView(){
        // loading blank url so it overrides last open url
        webView.loadUrl("");
        webView.setVisibility(View.GONE);
        recyclerView.setVisibility(View.GONE);
   }


 @Override
public void onBackPressed() {
    if(webView.getVisibility() == View.VISIBLE){
        hideWebView();
    }else{
        super.onBackPressed();
    }
}

これは質問とどのように関連していますか?
Zun

@Zun投票に感謝します。フィードバックに本当に感謝しています。質問に対する私の答えは、同様のシナリオで行き詰まっているということですが、少し異なっていますが、両方の出力は同じなので、私の答えを書く前に私はユーザーケースも作成しました。Cookieを処理する必要なく、問題の質問と同様の効果が得られます。
Abhishek Garg
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.