Android Webview - повністю очистіть кеш


111

У мене є WebView в одному з моїх заходів, і коли він завантажує веб-сторінку, сторінка збирає деякі основні дані з Facebook.

Що я бачу, це те, що сторінка, що відображається в додатку, однакова під час кожного відкриття та оновлення програми.

Я намагався налаштувати WebView не використовувати кеш і очистити кеш і історію WebView.

Я також дотримувався тут пропозиції: Як спорожнити кеш для WebView?

Але нічого з цього не працює, чи має хтось уявлення про те, що я можу подолати цю проблему, тому що це важлива частина моєї заяви.

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

Тому я реалізував першу пропозицію (Хоча змінив код на рекурсивний)

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

Однак це все ще не змінило те, що відображається на сторінці. У своєму браузері на робочому столі я отримую різний HTML-код на веб-сторінці, створеній у WebView, тому я знаю, що WebView десь повинен кешувати.

На каналі IRC мені вказували виправлення для видалення кешування із URL-з'єднання, але я не бачу, як застосувати його до WebView.

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

Якщо я видалю свою програму і повторно встановлю її, я можу відновити веб-сторінку актуальною, тобто не кешованою версією. Основна проблема полягає в змінах в посиланнях на веб-сторінці, тому передній кінець веб-сторінки повністю не змінюється.


1
mWebView.getSettings().setAppCacheEnabled(false);не працював?
Пол

Відповіді:


45

Відредагований фрагмент коду, розміщений вище, розміщений Gaunt Face, містить помилку в тому, що якщо каталог не вдасться видалити, оскільки один з його файлів неможливо видалити, код буде продовжуватися повтором у нескінченному циклі. Я переписав це на справді рекурсивний і додав параметр numDays, щоб ви могли контролювати, скільки років мають бути файли, які обрізаються:

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

Сподіваємось на користь іншим людям :)


Дуже дякую! Ви врятували мені день :)
Kris

Чудова рутина, врятувала нам багато агонії.
Містер Ед

Чи можу я використовувати цей код у програмі для очищення кешу для певного додатка, встановленого на моєму телефоні?
Si8

Якщо весь каталог потрібно видалити, Runtime.getRuntime (). Exec ("rm -rf" + dirName + "\ n") не буде видалений; бути легше?
source.rar

@ source.rar Так, але тоді ви не маєте можливості зберігати файли молодші x днів, що зазвичай потрібно для папки кешу.
markjan

205

Я знайшов навіть елегантне і просте рішення для очищення кешу

WebView obj;
obj.clearCache(true);

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

Я намагався розібратися з способом очищення кешу, але все, що ми могли зробити з вищезгаданих методів, - це видалити локальні файли, але це ніколи не очищає оперативну пам’ять.

API clearCache, звільняє оперативну пам’ять, яку використовує веб-перегляд, і, отже, вимагає завантаження веб-сторінки знову.


11
Тут найкраща відповідь.
user486134

Найкраща відповідь, і мені цікаво, чому його не прийняли..Кудос Акшат :)
Karthik

1
Не пощастило мені. Цікаво, чи щось змінилося? Я можу завантажити WebView за допомогою google.com, і WebView все ще думає, що я ввійшов у систему, навіть після clearCache (правда);
програв переклад

2
@lostintranslation Для цього ви, ймовірно, хочете видалити файли cookie. Хоча я впевнений, що ви це вже дізналися.
NineToeNerd

Потрібно виділити об’єкт? WebView obj = новий WebView (це); obj.clearCache (вірно); У будь-якому випадку, дуже добре для мене, прихильне!
Джорджіо Барчізі

45

Я знайшов виправлення, яке ви шукали:

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

Чомусь Android робить поганий кеш URL-адреси, який він повертається випадково замість нових даних, які вам потрібні. Звичайно, ви можете просто видалити записи з БД, але в моєму випадку я намагаюся отримати доступ лише до однієї URL-адреси, так що видування всього БД простіше.

І не хвилюйтеся, ці БД просто пов'язані з вашим додатком, тому ви не очищаєте кеш всього телефону.


Дякую, це неймовірно акуратний трюк. Він заслуговує на те, щоб бути більш відомим.
Філіп Шерд

2
Це кидає неприємний виняток у соті: 06-14 22: 33: 34.349: ПОМИЛКА / SQLiteDatabase (20382): не вдалося відкрити базу даних. закривши його. 06-14 22: 33: 34,349: ERROR / SQLiteDatabase (20382): android.database.sqlite.SQLiteDiskIOException: помилка вводу / виводу диска 06-14 22: 33: 34.349: ERROR / SQLiteDatabase (20382): на базі даних android.database. sqlite.SQLiteDatabase.native_setLocale (Native Method)
Рафаель Санчес

Ура, Рафаель, я хотів би подумати, що це тому, що оригінальне питання було вирішено в стільнику. Хтось знає, чи це так?
Скотт

просто покладіть 2 рядки в onBackpress () або кнопку назад, жодна історія не залишається в задній стек, завдяки збереженому багато часу.
CrazyMind

36

Щоб очистити всі кеші веб-перегляду під час виходу із форми на додаток:

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

Для льодяника і вище:

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

1
врятуй мені життя і день.
Удай Наяк

2
Відмінно працює, якщо у вас немає доступу до веб-перегляду. Також зауважте, що цей API застарілий, тому використовуйте API "RemoveAllCookies (ValueCallback)" замість цього на пристроях L +.
Акшат

що я повинен замінити ValueCallBack?
Кайсар Хан Бангаш

@QaisarKhanBangash new ValueCallback <Boolean> () {atOverride public void onReceiveValue (булеве значення) {}}
amalBit

3

Це має очистити кеш ваших програм, який повинен бути там, де знаходиться ваш кеш веб-перегляду

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

Спробував це (трохи змінив код) і все-таки отримав ті самі результати -> Пояснив вище
Метт Гонт

3

Єдине рішення, яке працює для мене

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

2

Просто використання коду нижче в Котліні працює для мене

WebView(applicationContext).clearCache(true)

2

Щоб очистити файли cookie та кеш із веб-перегляду,

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

Переконайтеся, що ви використовуєте метод нижче, щоб дані форми не відображалися як автопоп при натисканні на поля введення.

getSettings().setSaveFormData(false);

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

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

Він може очистити обліковий запис google у моєму перегляді веб-сторінок


2
CookieSyncManager вимкнено
розробник

-1

регістр використання: список елементів відображається у вікні переробки рециркулятора кожного разу, коли будь-який клацання на ньому приховує перегляд рециркулятора та показує веб-перегляд із URL-адресою елемента.

Проблема: у мене є аналогічна проблема, коли я відкриваю url_oneвеб-перегляд, а потім намагаюся відкрити інший url_twoу веб-перегляді, він відображається url_oneу фоновому режимі до url_twoзавантаження.

рішення: тому для вирішення того, що я зробив, це завантаження порожнього рядка ""як urlбезпосередньо перед приховуванням url_oneта завантаженням url_two.

вихід: коли я завантажую будь-яку нову URL-адресу у веб-перегляді, вона не відображає жодної іншої веб-сторінки у фоновому режимі.

код

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

Як це пов’язано з питанням?
Зун

@Zun дякую за те, що голосували за недію, і я дуже вдячний за відгуки, і моя відповідь на ваше запитання полягає в тому, що я застряг у подібному сценарії, але я трохи інший, але вихід обох однаковий, тому перед тим, як написати свою відповідь Я також написав випадок користувача, це дозволить досягти подібного ефекту, як про це йдеться, без необхідності обробляти файли cookie.
Абхішек
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.