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);ไม่ได้ผล?
Paul

คำตอบ:


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

กิจวัตรที่ยอดเยี่ยมช่วยให้เราทุกข์ทรมานได้มาก
Mr Ed

ฉันสามารถใช้รหัสนี้ในแอพเพื่อล้างแคชของแอพบางตัวที่ติดตั้งในโทรศัพท์ของฉันได้หรือไม่?
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

ฉันพยายามหาวิธีล้างแคช แต่สิ่งที่เราทำได้จากวิธีการที่กล่าวมาข้างต้นคือลบไฟล์ในเครื่อง แต่ไม่เคยล้าง RAM

API clearCache ช่วยเพิ่ม RAM ที่ใช้โดย webview และด้วยเหตุนี้จึงสั่งให้โหลดหน้าเว็บอีกครั้ง


11
คำตอบที่ดีที่สุดที่นี่
user486134

คำตอบที่ดีที่สุดและฉันสงสัยว่าทำไมถึงไม่ยอมรับ .. Kudos Akshat :)
Karthik

1
ไม่มีโชคสำหรับฉัน สงสัยว่ามีอะไรเปลี่ยนแปลงหรือไม่? ฉันสามารถโหลด WebView ด้วย google.com และ WebView ยังคงคิดว่าฉันเข้าสู่ระบบแม้ว่าจะหลังจาก clearCache (จริง) แล้วก็ตาม
lostintranslation

2
@lostintranslation เพื่อที่คุณอาจต้องการลบคุกกี้ แม้ว่าฉันแน่ใจว่าคุณพบสิ่งนั้นในตอนนี้
NineToeNerd

ต้องจัดสรรวัตถุหรือไม่? WebView obj = WebView ใหม่ (สิ่งนี้); obj.clearCache (จริง); อย่างไรก็ตามดีมากสำหรับฉันโหวต!
Giorgio Barchiesi

45

ฉันพบวิธีแก้ไขที่คุณกำลังมองหา:

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

ด้วยเหตุผลบางประการ Android สร้างแคชที่ไม่ถูกต้องของ URL ซึ่งจะส่งคืนโดยไม่ได้ตั้งใจแทนที่จะเป็นข้อมูลใหม่ที่คุณต้องการ แน่นอนว่าคุณสามารถลบรายการออกจาก DB ได้ แต่ในกรณีของฉันฉันพยายามเข้าถึง URL เดียวเท่านั้นดังนั้นการกำจัด DB ทั้งหมดจึงง่ายกว่า

และไม่ต้องกังวลฐานข้อมูลเหล่านี้เชื่อมโยงกับแอปของคุณเท่านั้นดังนั้นคุณจึงไม่ได้ล้างแคชของโทรศัพท์ทั้งหมด


ขอบคุณนี่เป็นเคล็ดลับที่ประณีตอย่างไม่น่าเชื่อ สมควรเป็นที่รู้จักในวงกว้างมากขึ้น
Philip Sheard

2
สิ่งนี้ทำให้เกิดข้อยกเว้นที่น่ารังเกียจในรังผึ้ง: 06-14 22: 33: 34.349: ERROR / SQLiteDatabase (20382): ไม่สามารถเปิดฐานข้อมูลได้ ปิดมัน 06-14 22: 33: 34.349: ERROR / SQLiteDatabase (20382): android.database.sqlite.SQLiteDiskIOException: ข้อผิดพลาดดิสก์ I / O 06-14 22: 33: 34.349: ERROR / SQLiteDatabase (20382): ที่ android.database sqlite.SQLiteDatabase.native_setLocale (Native Method)
Rafael Sanches

ไชโยราฟาเอลฉันอยากจะคิดว่านี่เป็นเพราะปัญหาเดิมได้รับการแก้ไขแล้วใน Honeycomb มีใครรู้บ้างว่าเป็นแบบนี้?
Scott

เพียงแค่ใส่ 2 บรรทัดใน onBackpress () หรือปุ่มย้อนกลับไม่มีประวัติค้างอยู่ในกองหลังขอบคุณที่ประหยัดเวลาได้มาก
CrazyMind

36

ในการล้างแคช webview ทั้งหมดในขณะที่คุณลงชื่อออกจากแอปของคุณ:

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

สำหรับ Lollipop ขึ้นไป:

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

1
ช่วยชีวิตและวันของฉัน
Uday Nayak

2
ทำงานได้ดีหากคุณไม่สามารถเข้าถึง Webview ในกิจกรรมของคุณ โปรดทราบว่า API นี้เลิกใช้งานแล้วดังนั้นให้ใช้ API "removeAllCookies (ValueCallback)" แทนในอุปกรณ์ L +
Akshat

สิ่งที่ฉันควรแทนที่ด้วย ValueCallBack?
Qaisar Khan Bangash

@QaisarKhanBangash new ValueCallback <Boolean> () {atOverride public void onReceiveValue (ค่าบูลีน) {}}
amalBit

3

สิ่งนี้ควรล้างแคชแอปพลิเคชันของคุณซึ่งควรเป็นที่แคชของ Webview ของคุณ

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

ลองสิ่งนี้ (เปลี่ยนรหัสเล็กน้อย) และยังคงได้ผลลัพธ์เหมือนเดิม -> อธิบายไว้ข้างบน
Matt Gaunt

3

ทางออกเดียวที่เหมาะกับฉัน

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


2

ในการล้างคุกกี้และแคชจาก 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

ตรวจสอบให้แน่ใจว่าคุณใช้วิธีการด้านล่างเพื่อให้ข้อมูลแบบฟอร์มไม่แสดงเป็น autopop เมื่อคลิกที่ช่องป้อนข้อมูล

getSettings().setSaveFormData(false);


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_oneurl_two

เอาต์พุต:เมื่อใดก็ตามที่ฉันโหลด url ใหม่ใน webview จะไม่แสดงหน้าเว็บอื่น ๆ ในพื้นหลัง

รหัส

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

@ ซุนขอบคุณสำหรับการลงคะแนนและฉันขอขอบคุณสำหรับข้อเสนอแนะและคำตอบของฉันสำหรับคำถามของคุณคือฉันติดอยู่ในสถานการณ์ที่คล้ายกัน แต่ฉันมีความแตกต่างกันเล็กน้อย แต่ผลลัพธ์ของทั้งคู่เหมือนกันดังนั้นก่อนที่จะเขียนคำตอบของฉัน ฉันยังได้เขียนกรณีผู้ใช้ซึ่งจะได้ผลเช่นเดียวกับที่ถามในคำถามโดยไม่จำเป็นต้องจัดการกับคุกกี้
Abhishek Garg
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.