Android Webview - Leeren Sie den Cache vollständig

111

Ich habe eine WebView in einer meiner Aktivitäten und wenn eine Webseite geladen wird, sammelt die Seite einige Hintergrunddaten von Facebook.

Was ich jedoch sehe, ist, dass die in der Anwendung angezeigte Seite bei jedem Öffnen und Aktualisieren der App gleich ist.

Ich habe versucht, WebView so einzustellen, dass kein Cache verwendet wird, und den Cache und den Verlauf von WebView zu löschen.

Ich bin auch dem Vorschlag hier gefolgt: Wie leere ich den Cache für WebView?

Aber nichts davon funktioniert, hat jemand eine Idee, wie ich dieses Problem überwinden kann, weil es ein wesentlicher Bestandteil meiner Anwendung ist.

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

Also habe ich den ersten Vorschlag implementiert (obwohl der Code so geändert wurde, dass er rekursiv ist)

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");
        }
    }
}

Dies hat jedoch immer noch nichts an der Anzeige der Seite geändert. In meinem Desktop-Browser erhalte ich einen anderen HTML-Code als die in WebView erstellte Webseite, sodass ich weiß, dass WebView irgendwo zwischengespeichert werden muss.

Auf dem IRC-Kanal wurde ich auf ein Update zum Entfernen des Cachings aus einer URL-Verbindung hingewiesen, kann aber noch nicht sehen, wie es auf eine WebView angewendet werden soll.

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

Wenn ich meine Anwendung lösche und erneut installiere, kann ich die Webseite wieder auf den neuesten Stand bringen, dh eine nicht zwischengespeicherte Version. Das Hauptproblem besteht darin, dass Änderungen an Links auf der Webseite vorgenommen werden, sodass das Frontend der Webseite völlig unverändert bleibt.

Matt Gaunt
quelle
1
mWebView.getSettings().setAppCacheEnabled(false);hat nicht funktioniert?
Paul

Antworten:

45

Das oben von Gaunt Face veröffentlichte bearbeitete Code-Snippet enthält den Fehler, dass der Code in einer Endlosschleife wiederholt wird, wenn ein Verzeichnis nicht gelöscht werden kann, weil eine seiner Dateien nicht gelöscht werden kann. Ich habe es so umgeschrieben, dass es wirklich rekursiv ist, und einen numDays-Parameter hinzugefügt, damit Sie steuern können, wie alt die zu bereinigenden Dateien sein müssen:

//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));
}

Hoffentlich von Nutzen für andere Leute :)

Markjan
quelle
Vielen Dank! ihr habt meinen Tag gerettet :)
Kris
Tolle Routine, hat uns viel Qual erspart.
Herr Ed
Kann ich diesen Code in einer App verwenden, um den Cache für bestimmte auf meinem Telefon installierte Apps zu löschen?
Si8
Wenn das gesamte Verzeichnis gelöscht werden muss, würde Runtime.getRuntime (). Exec ("rm -rf" + dirName + "\ n"); sei einfacher?
source.rar
@ source.rar Ja, aber dann können Sie keine Dateien jünger als x Tage halten, was normalerweise für einen Cache-Ordner gewünscht wird.
Markjan
205

Ich habe eine noch elegantere und einfachere Lösung gefunden, um den Cache zu leeren

WebView obj;
obj.clearCache(true);

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

Ich habe versucht, herauszufinden, wie der Cache geleert werden kann, aber mit den oben genannten Methoden konnten wir nur die lokalen Dateien entfernen, aber der RAM wurde nie bereinigt.

Die API clearCache gibt den von der Webansicht verwendeten RAM frei und fordert daher das erneute Laden der Webseite.

Akshat
quelle
11
Die beste Antwort hier.
user486134
Die beste Antwort und ich frage mich, warum es nicht akzeptiert wird. Kudos Akshat :)
Karthik
1
Kein Glück für mich. Frage mich, ob sich etwas geändert hat? Ich kann ein WebView mit google.com laden und das WebView glaubt immer noch, dass ich angemeldet bin, auch nach clearCache (true).
Verlorene Übersetzung
2
@lostintranslation Dafür möchten Sie wahrscheinlich Cookies löschen. Obwohl ich sicher bin, dass Sie das inzwischen herausgefunden haben.
NineToeNerd
Müssen Sie das Objekt zuordnen? WebView obj = new WebView (this); obj.clearCache (true); Wie auch immer, sehr gut für mich, positiv bewertet!
Giorgio Barchiesi
45

Ich habe das Update gefunden, nach dem Sie gesucht haben:

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

Aus irgendeinem Grund erstellt Android einen fehlerhaften Cache der URL, die versehentlich zurückgegeben wird, anstatt der neuen Daten, die Sie benötigen. Sicher, Sie könnten einfach die Einträge aus der Datenbank löschen, aber in meinem Fall versuche ich nur, auf eine URL zuzugreifen, damit das Wegblasen der gesamten Datenbank einfacher ist.

Und keine Sorge, diese DBs sind nur mit Ihrer App verknüpft, sodass Sie nicht den Cache des gesamten Telefons leeren.

Scott
quelle
Danke, das ist ein unglaublich ordentlicher Trick. Es verdient, bekannter zu werden.
Philip Sheard
2
Dies löst eine böse Ausnahme in Honeycomb aus: 06-14 22: 33: 34.349: ERROR / SQLiteDatabase (20382): Fehler beim Öffnen der Datenbank. Schließen Sie es. 06-14 22: 33: 34.349: FEHLER / SQLiteDatabase (20382): android.database.sqlite.SQLiteDiskIOException: Festplatten-E / A-Fehler 06-14 22: 33: 34.349: FEHLER / SQLiteDatabase (20382): at android.database. sqlite.SQLiteDatabase.native_setLocale (native Methode)
Rafael Sanches
Prost Rafael, ich würde gerne glauben, dass dies daran liegt, dass das ursprüngliche Problem in Honeycomb behoben wurde. Weiß jemand, ob dies der Fall ist?
Scott
Fügen Sie einfach 2 Zeilen in onBackpress () oder die Zurück-Schaltfläche ein. Dank der Zeitersparnis verbleibt kein Verlauf im Back-Stack.
CrazyMind
36

So löschen Sie alle Webview-Caches, während Sie sich von Ihrer APP abmelden:

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

Für Lollipop und höher:

CookieSyncManager.createInstance(this);         
CookieManager cookieManager = CookieManager.getInstance();        
cookieManager.removeAllCookies(ValueCallback);
amalBit
quelle
1
rette mein Leben und meinen Tag.
Uday Nayak
2
Funktioniert einwandfrei, wenn Sie in Ihrer Aktivität keinen Zugriff auf die Webansicht haben. Beachten Sie auch, dass diese API veraltet ist. Verwenden Sie daher stattdessen die API "removeAllCookies (ValueCallback)" auf L + -Geräten.
Akshat
Was soll ich durch ValueCallBack ersetzen?
Qaisar Khan Bangash
@QaisarKhanBangash new ValueCallback <Boolean> () {atOverride public void onReceiveValue (Boolean value) {}}
amalBit
3

Dies sollte Ihren Anwendungscache leeren, in dem sich Ihr Webview-Cache befinden sollte

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");
    }
}
jqpubliq
quelle
Versuchte dies (Code leicht geändert) und bekam immer noch die gleichen Ergebnisse -> oben erklärt
Matt Gaunt
3

Die einzige Lösung, die für mich funktioniert

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

Die einfache Verwendung des folgenden Codes in Kotlin funktioniert für mich

WebView(applicationContext).clearCache(true)
Ercan
quelle
2

Um Cookies und Cache aus Webview zu löschen,

    // 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();
Srinivasan
quelle
0

Stellen Sie sicher, dass Sie die folgende Methode verwenden, damit die Formulardaten nicht als Autopop angezeigt werden, wenn Sie auf Eingabefelder klicken.

getSettings().setSaveFormData(false);
Raghu
quelle
0
CookieSyncManager.createInstance(this);         
CookieManager cookieManager = CookieManager.getInstance();        
cookieManager.removeAllCookie();
WaqasArshad
quelle
0
CookieSyncManager.createInstance(this);    
CookieManager cookieManager = CookieManager.getInstance(); 
cookieManager.removeAllCookie();

Es kann Google-Konto in meiner Webansicht löschen

Dũng Phạm Tiến
quelle
2
CookieSyncManager ist beraubt
Entwickler
-1

Anwendungsfall: Die Liste der Artikel wird in der Recycler-Ansicht angezeigt. Immer wenn ein Artikel darauf klickt, wird die Recycler-Ansicht ausgeblendet und die Webansicht mit der Artikel-URL angezeigt.

Problem: Ich habe ein ähnliches Problem:url_one Wenn ich eine in der Webansicht öffne und dann versuche, eine andere url_twoin der Webansicht zu öffnen , wird sie url_oneim Hintergrund angezeigt, bis sie url_twogeladen ist.

Lösung: Um zu lösen, was ich getan habe, muss eine leere Zeichenfolge ""wie urlkurz vor dem Ausblenden url_oneund Laden geladen werden url_two.

Ausgabe: Wenn ich eine neue URL in die Webansicht lade, wird keine andere Webseite im Hintergrund angezeigt.

Code

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();
    }
}
Abhishek Garg
quelle
Wie hängt das mit der Frage zusammen?
Zun
@Zun, danke für die Abwertung, und ich freue mich sehr über Feedback. Meine Antwort auf Ihre Frage lautet, dass ich in einem ähnlichen Szenario stecke, aber ein bisschen anders bin, aber die Ausgabe von beiden gleich ist, also bevor ich meine Antwort schreibe Ich habe auch einen User Case geschrieben, der einen ähnlichen Effekt wie die fragliche erzielt, ohne dass Cookies behandelt werden müssen.
Abhishek Garg