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

Надеюсь, будет полезно другим людям :)

markjan
источник
Большое спасибо! вы, ребята, спасли мне день :)
Крис
Отличный распорядок избавил нас от многих мучений.
Мистер Эд
Могу ли я использовать этот код в приложении для очистки кеша определенного приложения, установленного на моем телефоне?
Si8 08
Если необходимо удалить весь каталог, 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 05
Лучший ответ, и мне интересно, почему его не приняли ... Слава Акшату :)
Картик
1
Мне не повезло. Интересно, изменилось ли что-то? Я могу загрузить WebView с помощью google.com, и WebView все еще думает, что я вошел в систему, даже после clearCache (true);
lostintranslation 02
2
@lostintranslation Для этого вы, вероятно, захотите удалить файлы cookie. Хотя я уверен, что вы уже это поняли.
NineToeNerd 03
Нужно выделить объект? WebView obj = новый WebView (это); obj.clearCache (истина); В любом случае, очень хорошо для меня, проголосовали за!
Giorgio Barchiesi
45

Я нашел исправление, которое вы искали:

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

По какой-то причине Android создает плохой кеш URL-адреса, который он продолжает случайно возвращать вместо новых данных, которые вам нужны. Конечно, вы можете просто удалить записи из БД, но в моем случае я пытаюсь получить доступ только к одному URL-адресу, поэтому сдуть всю БД проще.

И не волнуйтесь, эти БД просто связаны с вашим приложением, поэтому вы не очищаете кеш всего телефона.

Скотт
источник
Спасибо, это невероятно ловкий трюк. Он заслуживает более широкой известности.
Филип Шеард
2
Это вызывает неприятное исключение в сотах: 06-14 22: 33: 34.349: ERROR / SQLiteDatabase (20382): не удалось открыть базу данных. закрывая это. 06-14 22: 33: 34.349: ОШИБКА / SQLiteDatabase (20382): android.database.sqlite.SQLiteDiskIOException: ошибка дискового ввода-вывода 06-14 22: 33: 34.349: ОШИБКА / SQLiteDatabase (20382): в android.database. sqlite.SQLiteDatabase.native_setLocale (собственный метод)
Рафаэль Санчес,
Ура, Рафаэль, я хотел бы думать, что это связано с тем, что исходная проблема была решена в Honeycomb. Кто-нибудь знает, так ли это?
Скотт
просто поместите 2 строки в onBackpress () или кнопку «Назад», в обратном стеке не останется истории, благодаря экономии времени.
CrazyMind
36

Чтобы очистить все кеши веб-просмотра при выходе из приложения из приложения:

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

Для Lollipop и выше:

CookieSyncManager.createInstance(this);         
CookieManager cookieManager = CookieManager.getInstance();        
cookieManager.removeAllCookies(ValueCallback);
amalBit
источник
1
спасти мою жизнь и день.
Удай Наяк,
2
Прекрасно работает, если у вас нет доступа к веб-просмотру в вашей деятельности. Также обратите внимание, что этот API устарел, поэтому используйте API removeAllCookies (ValueCallback) вместо на устройствах L +.
Akshat
что мне заменить на ValueCallBack?
Кайсар Хан Бангаш,
@QaisarKhanBangash new ValueCallback <Boolean> () {atOverride public void onReceiveValue (Boolean value) {}}
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");
    }
}
jqpubliq
источник
Пробовал (немного изменил код) и все равно получил те же результаты -> Объяснено выше
Мэтт Гонт
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 и кеш из 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

Убедитесь, что вы используете метод ниже, чтобы данные формы не отображались как автозапуск при нажатии на поля ввода.

getSettings().setSaveFormData(false);
Рагу
источник
0
CookieSyncManager.createInstance(this);         
CookieManager cookieManager = CookieManager.getInstance();        
cookieManager.removeAllCookie();
WaqasArshad
источник
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
@Zun спасибо за отрицательное голосование, и я очень ценю отзывы, и мой ответ на ваш вопрос заключается в том, что я застрял в аналогичном сценарии, но у меня немного другой, но результат обоих из них одинаковый, поэтому, прежде чем писать свой ответ Я также написал пример пользователя, он даст эффект, аналогичный заданному в вопросе, без необходимости обрабатывать файлы cookie.
Abhishek Garg