Android Webview - całkowicie wyczyść pamięć podręczną

111

Mam WebView w jednym z moich działań i kiedy ładuje stronę internetową, strona zbiera pewne dane tła z Facebooka.

Widzę jednak, że strona wyświetlana w aplikacji jest taka sama za każdym razem, gdy aplikacja jest otwierana i odświeżana.

Próbowałem ustawić WebView, aby nie używał pamięci podręcznej i wyczyścił pamięć podręczną i historię WebView.

Ja też postąpiłem zgodnie z sugestią: Jak opróżnić pamięć podręczną dla WebView?

Ale nic z tego nie działa, czy nikt nie ma pomysłów na to, że mogę rozwiązać ten problem, ponieważ jest to istotna część mojej aplikacji.

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

Więc zaimplementowałem pierwszą sugestię (chociaż zmieniłem kod na rekurencyjny)

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

Jednak to nadal nie zmieniło tego, co wyświetla strona. W mojej przeglądarce komputerowej otrzymuję inny kod HTML niż strona internetowa utworzona w WebView, więc wiem, że WebView musi gdzieś buforować.

Na kanale IRC wskazano mi poprawkę, aby usunąć buforowanie z połączenia URL, ale nie widzę jeszcze, jak zastosować to do WebView.

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

Jeśli usunę aplikację i ponownie ją zainstaluję, mogę przywrócić aktualną wersję strony internetowej, tj. Wersję niebuforowaną. Główny problem polega na tym, że zmiany są dokonywane w linkach na stronie internetowej, więc front-end strony pozostaje całkowicie niezmieniony.

Matt Gaunt
źródło
1
mWebView.getSettings().setAppCacheEnabled(false);nie zadziałało?
Paul

Odpowiedzi:

45

Edytowany fragment kodu opublikowany powyżej przez Gaunt Face zawiera błąd polegający na tym, że jeśli katalog nie zostanie usunięty, ponieważ nie można usunąć jednego z jego plików, kod będzie ponawiał w nieskończonej pętli. Przepisałem go tak, aby był prawdziwie rekurencyjny i dodałem parametr numDays, abyś mógł kontrolować, ile lat muszą mieć pliki, które są przycinane:

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

Mam nadzieję, że przydadzą się innym ludziom :)

markjan
źródło
Wielkie dzięki! uratowaliście mi dzień :)
Kris
Świetna rutyna, zaoszczędziła nam wielu cierpień.
Pan Ed,
Czy mogę użyć tego kodu w aplikacji, aby wyczyścić pamięć podręczną niektórych aplikacji zainstalowanych na moim telefonie?
Si8
Jeśli cały katalog ma zostać usunięty, nie byłoby Runtime.getRuntime (). Exec ("rm -rf" + nazwaKatalogu + "\ n"); będzie łatwiejsze?
source.rar
@ source.rar Tak, ale wtedy nie masz możliwości przechowywania plików młodszych niż x dni, co zwykle jest potrzebne w folderze pamięci podręcznej.
markjan
205

Znalazłem nawet eleganckie i proste rozwiązanie do czyszczenia pamięci podręcznej

WebView obj;
obj.clearCache(true);

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

Próbowałem znaleźć sposób na wyczyszczenie pamięci podręcznej, ale wszystko, co mogliśmy zrobić za pomocą wyżej wymienionych metod, to usunięcie plików lokalnych, ale nigdy nie wyczyściło to pamięci RAM.

API clearCache zwalnia pamięć RAM używaną przez przeglądarkę internetową, a tym samym nakazuje ponowne załadowanie strony internetowej.

Akszat
źródło
11
Najlepsza odpowiedź tutaj.
user486134
Najlepsza odpowiedź i zastanawiam się, dlaczego nie została przyjęta..Kudos Akshat :)
Karthik
1
Nie mam szczęścia. Ciekawe, czy coś się zmieniło? Mogę załadować WebView za pomocą google.com, a WebView nadal uważa, że ​​jestem zalogowany, nawet po wyczyszczeniu ClearCache (prawda);
Lostintranslation
2
@lostintranslation W tym celu prawdopodobnie chcesz usunąć pliki cookie. Chociaż jestem pewien, że już się o tym dowiedziałeś.
NineToeNerd
Chcesz przydzielić obiekt? WebView obj = new WebView (this); obj.clearCache (true); Zresztą, bardzo dobrze dla mnie, za!
Giorgio Barchiesi
45

Znalazłem poprawkę, której szukałeś:

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

Z jakiegoś powodu Android tworzy złą pamięć podręczną adresu URL, który przez przypadek zwraca zamiast nowych potrzebnych danych. Jasne, możesz po prostu usunąć wpisy z bazy danych, ale w moim przypadku próbuję uzyskać dostęp tylko do jednego adresu URL, więc usunięcie całej bazy danych jest łatwiejsze.

I nie martw się, te bazy danych są po prostu powiązane z twoją aplikacją, więc nie czyścisz pamięci podręcznej całego telefonu.

Scott
źródło
Dzięki, to niesamowicie zgrabna sztuczka. Zasługuje na to, by być szerzej znane.
Philip Sheard
2
Powoduje to nieprzyjemny wyjątek w strukturze plastra miodu: 06-14 22: 33: 34.349: ERROR / SQLiteDatabase (20382): nie można otworzyć bazy danych. zamknięcie go. 06-14 22: 33: 34.349: ERROR / SQLiteDatabase (20382): android.database.sqlite.SQLiteDiskIOException: błąd we / wy dysku 06-14 22: 33: 34.349: ERROR / SQLiteDatabase (20382): w android.database. sqlite.SQLiteDatabase.native_setLocale (metoda macierzysta)
Rafael Sanches,
Pozdrawiam Rafael, chciałbym pomyśleć, że dzieje się tak dlatego, że pierwotny problem został rozwiązany w Honeycomb. Czy ktoś wie, czy tak jest?
Scott
wystarczy umieścić 2 linie w przycisku onBackpress () lub wstecz, żadna historia nie pozostaje na stosie wstecznym dzięki zaoszczędzeniu dużej ilości czasu.
CrazyMind
36

Aby wyczyścić wszystkie pamięci podręczne widoku internetowego podczas wylogowywania się z aplikacji:

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

Dla Lollipopa i nowszych:

CookieSyncManager.createInstance(this);         
CookieManager cookieManager = CookieManager.getInstance();        
cookieManager.removeAllCookies(ValueCallback);
amalBit
źródło
1
uratuj moje życie i dzień.
Uday Nayak
2
Działa dobrze, jeśli nie masz dostępu do widoku internetowego w swojej aktywności. Należy również pamiętać, że ten interfejs API został wycofany, więc zamiast niego na urządzeniach L + należy używać interfejsu API „removeAllCookies (ValueCallback)”.
Akshat
co powinienem zamienić na ValueCallBack?
Qaisar Khan Bangash
@QaisarKhanBangash new ValueCallback <Boolean> () {atOverride public void onReceiveValue (wartość logiczna) {}}
amalBit
3

Powinno to wyczyścić pamięć podręczną aplikacji, która powinna znajdować się w miejscu, w którym znajduje się pamięć podręczna widoku internetowego

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
źródło
Próbowałem tego (nieznacznie zmieniłem kod) i nadal otrzymałem te same wyniki -> Wyjaśniono powyżej
Matt Gaunt
3

Jedyne rozwiązanie, które na mnie działa

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
    CookieManager.getInstance().removeAllCookies(null);
    CookieManager.getInstance().flush();
} 
Ketan Ramani
źródło
2

U mnie działa po prostu poniższy kod w Kotlinie

WebView(applicationContext).clearCache(true)
Ercan
źródło
2

Aby wyczyścić plik cookie i pamięć podręczną z 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
źródło
0

Upewnij się, że używasz poniższej metody, aby dane formularza nie były wyświetlane jako autopop po kliknięciu pól wejściowych.

getSettings().setSaveFormData(false);
Raghu
źródło
0
CookieSyncManager.createInstance(this);         
CookieManager cookieManager = CookieManager.getInstance();        
cookieManager.removeAllCookie();
WaqasArshad
źródło
0
CookieSyncManager.createInstance(this);    
CookieManager cookieManager = CookieManager.getInstance(); 
cookieManager.removeAllCookie();

Może wyczyścić konto Google w moim widoku internetowym

Dũng Phạm Tiến
źródło
2
CookieSyncManager jest pozbawiony funkcjonalności
programista
-1

przypadek użycia: lista elementów jest wyświetlana w widoku recyklera, po każdym kliknięciu elementu ukrywa widok recyklera i wyświetla widok sieciowy z adresem URL elementu.

problem: mam podobny problem, w którym po otwarciu url_onewidoku w przeglądarce internetowej, a następnie próbie otwarcia innego url_twow widoku sieciowym, wyświetla się on url_onew tle do momentu url_twozaładowania.

rozwiązanie: aby rozwiązać to, co zrobiłem, załaduj pusty ciąg, ""tak jak urltuż przed ukryciem url_onei załadowaniem url_two.

dane wyjściowe: za każdym razem, gdy ładuję nowy adres URL w widoku sieci Web, w tle nie wyświetla się żadna inna strona internetowa.

kod

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
źródło
Jak to się ma do pytania?
Zun
@Zun dziękuję za głosowanie w dół i naprawdę doceniam opinie, a moja odpowiedź na twoje pytanie brzmi, że utknąłem w podobnym scenariuszu, ale mam trochę inny, ale wyniki obu są takie same, więc zanim napiszę moją odpowiedź napisałem również przypadek użytkownika, osiągnie podobny efekt jak zadany w pytaniu, bez konieczności obsługi plików cookie.
Abhishek Garg