Android Webview - Svuota completamente la cache


111

Ho una visualizzazione Web in una delle mie attività e quando carica una pagina Web, la pagina raccoglie alcuni dati in background da Facebook.

Quello che vedo però, è che la pagina visualizzata nell'applicazione è la stessa ogni volta che l'app viene aperta e aggiornata.

Ho provato a impostare il WebView per non utilizzare la cache e cancellare la cache e la cronologia del WebView.

Ho anche seguito il suggerimento qui: come svuotare la cache per WebView?

Ma niente di tutto questo funziona, qualcuno ha qualche idea su come posso superare questo problema perché è una parte vitale della mia applicazione.

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

Quindi ho implementato il primo suggerimento (sebbene abbia cambiato il codice per essere ricorsivo)

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

Tuttavia, ciò non ha ancora cambiato ciò che la pagina sta visualizzando. Sul mio browser desktop ricevo codice html diverso dalla pagina web prodotta in WebView, quindi so che WebView deve essere memorizzato nella cache da qualche parte.

Sul canale IRC mi è stato indicato una correzione per rimuovere il caching da una connessione URL ma non riesco ancora a vedere come applicarlo a un WebView.

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

Se elimino la mia applicazione e la reinstallo, posso aggiornare la pagina web, ovvero una versione non memorizzata nella cache. Il problema principale è che le modifiche vengono apportate ai collegamenti nella pagina Web, quindi il front-end della pagina Web è completamente invariato.


1
mWebView.getSettings().setAppCacheEnabled(false);non ha funzionato?
Paul

Risposte:


45

Lo snippet di codice modificato sopra pubblicato da Gaunt Face contiene un errore in quanto se una directory non viene eliminata perché uno dei suoi file non può essere eliminato, il codice continuerà a riprovare in un ciclo infinito. L'ho riscritto per essere veramente ricorsivo e ho aggiunto un parametro numDays in modo da poter controllare quanti anni devono essere i file che vengono eliminati:

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

Si spera utile ad altre persone :)


Molte grazie! voi ragazzi mi avete salvato la giornata :)
Kris

Grande routine, ci ha risparmiato molta agonia.
Mr Ed,

Posso utilizzare questo codice all'interno di un'app per svuotare la cache per determinate app installate sul mio telefono?
Si8

Se l'intera directory deve essere cancellata, non Runtime.getRuntime (). Exec ("rm -rf" + dirName + "\ n"); essere più facile?
source.rar

@ source.rar Sì, ma in questo caso non hai la possibilità di mantenere file più vecchi di x giorni, cosa che in genere desideri per una cartella cache.
Markjan

205

Ho trovato una soluzione ancora elegante e semplice per svuotare la cache

WebView obj;
obj.clearCache(true);

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

Ho cercato di capire come svuotare la cache, ma tutto ciò che potevamo fare dai metodi sopra menzionati era rimuovere i file locali, ma non puliva mai la RAM.

L'API clearCache, libera la RAM utilizzata dalla webview e quindi impone che la pagina web venga caricata di nuovo.


11
La migliore risposta qui.
user486134

La migliore risposta e mi chiedo perché non sia accettata .. Complimenti Akshat :)
Karthik

1
Nessuna fortuna per me. Chissà se qualcosa è cambiato? Posso caricare un WebView con google.com e il WebView pensa ancora che io sia loggato, anche dopo clearCache (true);
lostintranslation

2
@lostintranslation Per questo probabilmente vorrai eliminare i cookie. Anche se sono sicuro che ormai l'hai scoperto.
NineToeNerd

Hai bisogno di allocare l'oggetto? WebView obj = nuovo WebView (questo); obj.clearCache (true); Comunque, molto buono per me, voto positivo!
Giorgio Barchiesi

45

Ho trovato la soluzione che stavi cercando:

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

Per qualche motivo Android crea una cache errata dell'URL che continua a restituire per sbaglio invece dei nuovi dati di cui hai bisogno. Certo, potresti semplicemente eliminare le voci dal DB, ma nel mio caso sto solo cercando di accedere a un URL, quindi spazzare via l'intero DB è più facile.

E non preoccuparti, questi DB sono semplicemente associati alla tua app, quindi non svuoti la cache dell'intero telefono.


Grazie, questo è un trucco incredibilmente accurato. Merita di essere più ampiamente conosciuto.
Philip Sheard

2
Questo genera una brutta eccezione in honeycomb: 06-14 22: 33: 34.349: ERROR / SQLiteDatabase (20382): impossibile aprire il database. chiudendolo. 06-14 22: 33: 34.349: ERROR / SQLiteDatabase (20382): android.database.sqlite.SQLiteDiskIOException: errore I / O del disco 06-14 22: 33: 34.349: ERROR / SQLiteDatabase (20382): su android.database. sqlite.SQLiteDatabase.native_setLocale (Native Method)
Rafael Sanches

Saluti Rafael, mi piacerebbe pensare che ciò sia dovuto al fatto che il problema originale è stato risolto in Honeycomb. Qualcuno sà se questo è il caso?
Scott

basta inserire 2 righe in onBackpress () o nel pulsante Indietro nessuna cronologia rimane nello stack precedente grazie al risparmio di tempo.
CrazyMind

36

Per cancellare tutte le cache webview mentre ti disconnetti dalla tua APP:

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

Per Lollipop e superiori:

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

1
salvami la vita e il giorno
Uday Nayak

2
Funziona bene se non hai accesso alla visualizzazione web nella tua attività. Tieni inoltre presente che questa API è stata ritirata, quindi utilizza l'API "removeAllCookies (ValueCallback)" invece sui dispositivi L +.
Akshat

cosa devo sostituire con ValueCallBack?
Qaisar Khan Bangash

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

3

Questo dovrebbe svuotare la cache delle applicazioni che dovrebbe essere dove si trova la cache della visualizzazione web

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

Ho provato questo (codice leggermente modificato) e ho comunque ottenuto gli stessi risultati -> Spiegato sopra
Matt Gaunt

3

L'unica soluzione che funziona per me

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

2

Il semplice utilizzo del codice sottostante in Kotlin funziona per me

WebView(applicationContext).clearCache(true)

2

Per cancellare cookie e cache da Webview,

    // 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

Assicurati di utilizzare il metodo seguente per i dati del modulo non essere visualizzati come apertura automatica quando si fa clic sui campi di input.

getSettings().setSaveFormData(false);

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

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

Può cancellare l'account Google nella mia visualizzazione web


2
CookieSyncManager è obsoleto
Sviluppatore

-1

caso d'uso: l' elenco degli articoli viene visualizzato nella visualizzazione riciclatore, ogni volta che un elemento fa clic su di esso nasconde la visualizzazione riciclatore e mostra la visualizzazione Web con l'URL dell'articolo.

problema: ho un problema simile in cui una volta aperto un url_onein webview, quindi provo ad aprirne un altro url_twoin webview, viene visualizzato url_onein background fino a quando non url_twoviene caricato.

soluzione: quindi per risolvere quello che ho fatto è caricare una stringa vuota ""come urlappena prima di nasconderla url_onee caricarla url_two.

output: ogni volta che carico un nuovo URL in webview non mostra altre pagine web in background.

codice

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

In che modo questo è collegato alla domanda?
Zun

@Zun grazie per aver votato verso il basso, e apprezzo molto il feedback, e la mia risposta alla tua domanda è che sono bloccato in uno scenario simile, ma sono leggermente diverso, ma l'output di entrambi è lo stesso, quindi prima di scrivere la mia risposta Ho anche scritto un caso utente, otterrà un effetto simile a quello richiesto in questione, senza bisogno di gestire i cookie.
Abhishek Garg
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.