Android Webview - limpe completamente o cache

111

Eu tenho um WebView em uma de minhas atividades e, quando carrega uma página da web, a página reúne alguns dados de fundo do Facebook.

O que estou vendo, porém, é que a página exibida no aplicativo é a mesma sempre que o aplicativo é aberto e atualizado.

Tentei configurar o WebView para não usar cache e limpar o cache e o histórico do WebView.

Eu também segui a sugestão aqui: Como esvaziar o cache do WebView?

Mas nada disso funciona, alguém tem alguma ideia de como posso superar esse problema porque é uma parte vital da minha aplicação.

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

Então, implementei a primeira sugestão (embora tenha alterado o código para ser 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");
        }
    }
}

No entanto, isso ainda não mudou o que a página está exibindo. No navegador do meu desktop, estou obtendo um código html diferente para a página da web produzida no WebView, então sei que o WebView deve estar em cache em algum lugar.

No canal IRC, fui apontado para uma correção para remover o cache de uma conexão de URL, mas ainda não consigo ver como aplicá-lo a um WebView.

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

Se eu excluir meu aplicativo e reinstalá-lo, posso fazer com que a página da web seja atualizada, ou seja, uma versão não armazenada em cache. O principal problema é que as alterações são feitas nos links da página da web, de modo que o front-end da página fica completamente inalterado.

Matt Gaunt
fonte
1
mWebView.getSettings().setAppCacheEnabled(false);não funcionou?
Paulo

Respostas:

45

O trecho de código editado acima postado por Gaunt Face contém um erro em que se um diretório falhar ao excluir porque um de seus arquivos não pode ser excluído, o código continuará tentando em um loop infinito. Eu o reescrevi para ser verdadeiramente recursivo e adicionei um parâmetro numDays para que você possa controlar a idade dos arquivos que foram removidos:

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

Espero que possa ser usado por outras pessoas :)

Markjan
fonte
Muito obrigado! vocês salvaram meu dia :)
Kris
Ótima rotina, nos salvou de muita agonia.
Sr. Ed,
Posso usar este código em um aplicativo para limpar o cache de determinado aplicativo instalado no meu telefone?
Si8
Se todo o diretório precisa ser excluído, não Runtime.getRuntime (). Exec ("rm -rf" + dirName + "\ n"); ser mais fácil?
source.rar
@ source.rar Sim, mas você não pode manter arquivos com menos de x dias, o que normalmente você deseja para uma pasta de cache.
markjan
205

Eu encontrei uma solução simples e elegante para limpar o cache

WebView obj;
obj.clearCache(true);

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

Tenho tentado descobrir uma maneira de limpar o cache, mas tudo o que pudemos fazer com os métodos mencionados acima foi remover os arquivos locais, mas nunca limpar a RAM.

A API clearCache libera a RAM usada pelo webview e, portanto, exige que a página da web seja carregada novamente.

Akshat
fonte
11
A melhor resposta aqui.
usuário 486134
A melhor resposta e eu me pergunto por que não é aceita ... Kudos Akshat :)
Karthik
1
Sem sorte para mim. Será que algo mudou? Posso carregar um WebView com google.com e o WebView ainda acha que estou conectado, mesmo depois de clearCache (true);
perdeu a tradução de
2
@lostintranslation Para isso, você provavelmente deseja excluir os cookies. Embora eu tenha certeza de que você já descobriu isso.
NineToeNerd,
Precisa alocar o objeto? WebView obj = novo WebView (este); obj.clearCache (true); De qualquer forma, muito bom para mim, voto positivo!
Giorgio Barchiesi
45

Encontrei a solução que você procurava:

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

Por alguma razão, o Android cria um cache ruim da url, que retorna acidentalmente, em vez dos novos dados de que você precisa. Claro, você poderia simplesmente excluir as entradas do banco de dados, mas no meu caso, estou apenas tentando acessar uma URL, de modo que explodir todo o banco de dados é mais fácil.

E não se preocupe, esses bancos de dados estão apenas associados ao seu aplicativo, então você não está limpando o cache de todo o telefone.

Scott
fonte
Obrigado, este é um truque incrivelmente legal. Ele merece ser mais conhecido.
Philip Sheard
2
Isso lança uma exceção desagradável no honeycomb: 06-14 22: 33: 34.349: ERROR / SQLiteDatabase (20382): Falha ao abrir o banco de dados. fechando. 06-14 22: 33: 34.349: ERROR / SQLiteDatabase (20382): android.database.sqlite.SQLiteDiskIOException: erro de E / S de disco 06-14 22: 33: 34.349: ERROR / SQLiteDatabase (20382): em android.database. sqlite.SQLiteDatabase.native_setLocale (Método nativo)
Rafael Sanches
Saúde Rafael, gostaria de pensar que isso ocorre porque o problema original foi resolvido no Honeycomb. Alguém sabe se este é o caso?
Scott
basta colocar 2 linhas no botão onBackpress () ou voltar e nenhum histórico permanece na pilha de retorno graças à economia de muito tempo.
CrazyMind
36

Para limpar todos os caches do webview enquanto você sai do seu APP:

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

Para Lollipop e superior:

CookieSyncManager.createInstance(this);         
CookieManager cookieManager = CookieManager.getInstance();        
cookieManager.removeAllCookies(ValueCallback);
amalBit
fonte
1
salve minha vida e dia.
Uday Nayak
2
Funciona bem se você não tiver acesso ao webview em sua atividade. Observe também que esta API foi descontinuada, então use a API "removeAllCookies (ValueCallback)" em vez de dispositivos L +.
Akshat de
o que devo substituir por ValueCallBack?
Qaisar Khan Bangash
@QaisarKhanBangash new ValueCallback <Boolean> () {atOverride public void onReceiveValue (valor booleano) {}}
amalBit
3

Isso deve limpar o cache de seus aplicativos, que deve estar onde está o cache de sua visualização

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
fonte
Tentei (código alterado ligeiramente) e ainda obteve os mesmos resultados -> Explicado acima
Matt Gaunt
3

A única solução que funciona para mim

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

Simplesmente usar o código abaixo em Kotlin funciona para mim

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

Para limpar o cookie e o cache do 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
fonte
0

Certifique-se de usar o método abaixo para que os dados do formulário não sejam exibidos como autopop quando clicado nos campos de entrada.

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

Ele pode limpar a conta do Google em meu webview

Dũng Phạm Tiến
fonte
2
CookieSyncManager foi descontinuado
Desenvolvedor de
-1

caso de uso: a lista de itens está sendo exibida na visualização do reciclador, sempre que algum item clica, ele oculta a visualização do reciclador e mostra a visualização da web com o URL do item.

Problema: tenho um problema semelhante no qual, uma vez que abro um url_oneno webview e tento abrir outro url_twono webview, ele aparece url_oneem background até url_twoser carregado.

solução: para resolver o que fiz foi carregar a string em branco ""como urlantes de esconder url_onee carregar url_two.

saída: sempre que carrego qualquer novo url no webview, ele não mostra nenhuma outra página da web em 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
fonte
Como isso está relacionado à pergunta?
Zun
@Zun, obrigado por votar e eu realmente aprecio o feedback, e minha resposta à sua pergunta é que estou preso em um cenário semelhante, mas tenho um pouco de diferença, mas o resultado de ambos é o mesmo, então antes de escrever minha resposta Eu também escrevi um caso de usuário, ele terá um efeito semelhante ao da pergunta em questão, sem a necessidade de lidar com cookies.
Abhishek Garg