Vista web de Android: borra completamente la caché

111

Tengo un WebView en una de mis actividades, y cuando carga una página web, la página recopila algunos datos de fondo de Facebook.

Sin embargo, lo que veo es que la página que se muestra en la aplicación es la misma cada vez que se abre y se actualiza la aplicación.

Intenté configurar WebView para que no use la caché y borre la caché y el historial de WebView.

También he seguido la sugerencia aquí: ¿Cómo vaciar el caché para WebView?

Pero nada de esto funciona, ¿alguien tiene alguna idea de que puedo superar este problema porque es una parte vital de mi aplicación?

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

Así que implementé la primera sugerencia (aunque cambié el código para que sea recursivo)

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

Sin embargo, esto todavía no ha cambiado lo que se muestra en la página. En mi navegador de escritorio, obtengo un código html diferente al de la página web producida en WebView, así que sé que WebView debe estar almacenado en caché en algún lugar.

En el canal de IRC, me señalaron una solución para eliminar el almacenamiento en caché de una conexión URL, pero todavía no veo cómo aplicarlo a un WebView.

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

Si elimino mi aplicación y la reinstalo, puedo volver a actualizar la página web, es decir, una versión sin caché. El principal problema es que los cambios se realizan en los enlaces de la página web, por lo que la parte frontal de la página web no se modifica por completo.

Matt Gaunt
fuente
1
mWebView.getSettings().setAppCacheEnabled(false);no funcionó?
Paul

Respuestas:

45

El fragmento de código editado anteriormente publicado por Gaunt Face contiene un error en el sentido de que si un directorio no se elimina porque uno de sus archivos no se puede eliminar, el código seguirá reintentando en un bucle infinito. Lo reescribí para que fuera realmente recursivo y agregué un parámetro numDays para que pueda controlar la antigüedad de los archivos que se eliminan:

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

Con suerte, de utilidad para otras personas :)

Markjan
fuente
¡Muchas gracias! ustedes me salvaron el día :)
Kris
Gran rutina, nos ahorró mucha agonía.
Mr Ed
¿Puedo usar este código dentro de una aplicación para borrar la caché de cierta aplicación instalada en mi teléfono?
Si8
Si es necesario eliminar todo el directorio, no lo haría Runtime.getRuntime (). Exec ("rm -rf" + dirName + "\ n"); ¿ser más fácil?
source.rar
@ source.rar Sí, pero no tiene la capacidad de mantener archivos con menos de x días de antigüedad, lo que normalmente desea para una carpeta de caché.
Markjan
205

Encontré una solución incluso elegante y simple para borrar el caché

WebView obj;
obj.clearCache(true);

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

He estado tratando de encontrar la forma de borrar el caché, pero todo lo que pudimos hacer con los métodos mencionados anteriormente fue eliminar los archivos locales, pero nunca limpiaron la RAM.

La API clearCache libera la RAM utilizada por la vista web y, por lo tanto, exige que la página web se cargue nuevamente.

Akshat
fuente
11
La mejor respuesta aqui.
user486134
La mejor respuesta y me pregunto por qué no se acepta ... Felicitaciones Akshat :)
Karthik
1
No tuve suerte. ¿Me pregunto si algo ha cambiado? Puedo cargar un WebView con google.com y el WebView todavía cree que estoy conectado, incluso después de clearCache (verdadero);
lostintranslation
2
@lostintranslation Para eso, probablemente desee eliminar las cookies. Aunque estoy seguro de que ya lo has descubierto.
NineToeNerd
¿Necesitas asignar el objeto? WebView obj = new WebView (esto); obj.clearCache (verdadero); De todos modos, muy bien para mí, ¡votó a favor!
Giorgio Barchiesi
45

Encontré la solución que estabas buscando:

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

Por alguna razón, Android crea un caché incorrecto de la URL que sigue regresando por accidente en lugar de los nuevos datos que necesita. Claro, podría simplemente eliminar las entradas de la base de datos, pero en mi caso solo estoy tratando de acceder a una URL, por lo que eliminar toda la base de datos es más fácil.

Y no se preocupe, estas bases de datos solo están asociadas con su aplicación, por lo que no está borrando el caché de todo el teléfono.

Scott
fuente
Gracias, este es un truco increíblemente genial. Merece ser más conocido.
Philip Sheard
2
Esto arroja una desagradable excepción en panal: 06-14 22: 33: 34.349: ERROR / SQLiteDatabase (20382): No se pudo abrir la base de datos. cerrándolo. 06-14 22: 33: 34.349: ERROR / SQLiteDatabase (20382): android.database.sqlite.SQLiteDiskIOException: error de E / S de disco 06-14 22: 33: 34.349: ERROR / SQLiteDatabase (20382): en android.database. sqlite.SQLiteDatabase.native_setLocale (Método nativo)
Rafael Sanches
Saludos Rafael, me gustaría pensar que esto se debe a que el problema original se ha resuelto en Honeycomb. ¿Alguien sabe si este es el caso?
Scott
simplemente ponga 2 líneas en onBackpress () o en el botón de retroceso, no queda historial en la pila posterior gracias a que ahorró mucho tiempo.
CrazyMind
36

Para borrar todos los cachés de webview mientras cierra sesión desde su aplicación:

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

Para Lollipop y superior:

CookieSyncManager.createInstance(this);         
CookieManager cookieManager = CookieManager.getInstance();        
cookieManager.removeAllCookies(ValueCallback);
amalBit
fuente
1
salva mi vida y mi día.
Uday Nayak
2
Funciona bien si no tiene acceso a la vista web en su actividad. También tenga en cuenta que esta API ha quedado obsoleta, por lo que debe utilizar la API "removeAllCookies (ValueCallback)" en su lugar en los dispositivos L +.
Akshat
¿Qué debo reemplazar con ValueCallBack?
Qaisar Khan Bangash
@QaisarKhanBangash new ValueCallback <Boolean> () {atOverride public void onReceiveValue (valor booleano) {}}
amalBit
3

Esto debería borrar el caché de sus aplicaciones, que debería estar donde está el caché de su vista 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");
    }
}
jqpubliq
fuente
Intenté esto (código modificado ligeramente) y aún obtuve los mismos resultados -> Explicado anteriormente
Matt Gaunt
3

La única solución que me funciona

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

Simplemente usar el siguiente código en Kotlin funciona para mí

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

Para borrar las cookies y la caché de 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();
Srinivasan
fuente
0

Asegúrese de utilizar el método siguiente para que los datos del formulario no se muestren como autopop al hacer clic en los campos de entrada.

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

Puede borrar la cuenta de Google en mi vista web

Dũng Phạm Tiến
fuente
2
CookieSyncManager es depricado
Desarrollador
-1

caso de uso: la lista de elementos se muestra en la vista del reciclador, cada vez que se hace clic en un elemento, se oculta la vista del reciclador y se muestra la vista web con la URL del elemento.

Problema: tengo un problema similar en el que una vez que abro una vista url_oneweb, luego intento abrir otra vista url_twoweb, se muestra url_oneen segundo plano hasta que url_twose carga.

solución: así que para resolver lo que hice es cargar una cadena en blanco ""como urljusto antes de ocultar url_oney cargar url_two.

salida: cada vez que cargo una nueva URL en webview, no muestra ninguna otra página web en segundo plano.

código

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
fuente
¿Cómo se relaciona esto con la pregunta?
Zun
@Zun, gracias por votar en contra, y realmente aprecio los comentarios, y mi respuesta a su pregunta es que estoy atrapado en un escenario similar, pero tengo un poco diferente, pero el resultado de ambos es el mismo, así que antes de escribir mi respuesta También he escrito un caso de usuario, logrará un efecto similar al solicitado en la pregunta, sin necesidad de manejar cookies.
Abhishek Garg