Android webView 緩存 Cache + HTML5離線功能解決(轉)

原:http://blog.csdn.net/lxy_tap/article/details/52583810

WebView的緩存可以分為頁面緩存和數據緩存。
頁面緩存是指加載一個網頁時的html、JS、CSS等頁面或者資源數據。這些緩存資源是由于瀏覽器的行為而產生,開發者只能通過配置HTTP響應頭影響瀏覽器的行為才能間接地影響到這些緩存數據。

     他們的索引存放在/data/data/package_name/databases下。他們的文件存放在/data/data/package_name/cache/xxxwebviewcachexxx下。文件夾的名字在2.x和4.x上有所不同,但都文件夾名字中都包含webviewcache。

        數據緩存分為兩種:AppCache和DOM Storage(Web Storage)。他們是因為頁面開發者的直接行為而產生。所有的緩存數據都由開發者直接完全地掌控。

AppCache使我們能夠有選擇的緩沖web瀏覽器中所有的東西,從頁面、圖片到腳本、css等等。尤其在涉及到應用于網站的多個頁面上的CSS和JavaScript文件的時候非常有用。其大小目前通常是5M。
在Android上需要手動開啟(setAppCacheEnabled),并設置路徑(setAppCachePath)和容量(setAppCacheMaxSize)
Android中Webkit使用一個db文件來保存AppCache數據(my_path/ApplicationCache.db)

      如果需要存儲一些簡單的用key/value對即可解決的數據,DOM Storage是非常完美的方案。根據作用范圍的不同,有Session Storage和Local Storage兩種,分別用于會話級別的存儲(頁面關閉即消失)和本地化存儲(除非主動刪除,否則數據永遠不會過期)。

在Android中可以手動開啟DOM Storage(setDomStorageEnabled),設置存儲路徑(setDatabasePath)
Android中Webkit會為DOM Storage產生兩個文件(my_path/localstorage/http_h5.m.taobao.com_0.localstorage和my_path/localstorage/Databases.db)

       另外,在Android中清除緩存時,如果需要清除Local Storage的話,僅僅刪除Local Storage的本地存儲文件是不夠的,內存里面有緩存數據。如果再次進入頁面,Local Storage中的緩存數據同樣存在。需要殺死程序運行的當前進程再重新啟動才可以。

HTML5的離線應用功能可以使得WebApp即使在網絡斷開的情況下仍能正常使用,這是個非常有用的功能。近來工作中也要用到HTML5離線應用功能,由于是在Android平臺上做,所以自然而然的選擇Webview來解析網頁。但如何使Webivew支持HTML5離線應用功能呢,經過反復摸索和上網查找資料,反復做試驗終于成功了。

首先需配置webview的的一些屬性,假設activity中已經有了一個Webview的實例對象,名為m_webview,然后增加以下代碼:

WebSettings webseting = m_webview.getSettings();  
    webseting.setDomStorageEnabled(true);             
        webseting.setAppCacheMaxSize(1024*1024*8);//設置緩沖大小,我設的是8M  
    String appCacheDir = this.getApplicationContext().getDir("cache", Context.MODE_PRIVATE).getPath();      
        webseting.setAppCachePath(appCacheDir);  
        webseting.setAllowFileAccess(true);  
        webseting.setAppCacheEnabled(true);  
        webseting.setCacheMode(WebSettings.LOAD_DEFAULT);  

webview可以設置一個WebChromeClient對象,在其onReachedMaxAppCacheSize函數對擴充緩沖做出響應。代碼如下:

m_webview.setWebChromeClient(m_chromeClient);  
    private WebChromeClient m_chromeClient = new WebChromeClient(){  
        //擴充緩存的容量    
    @Override  
    public void onReachedMaxAppCacheSize(long spaceNeeded,    
                long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {    
            quotaUpdater.updateQuota(spaceNeeded * 2);    
        }         
    };  

其次要修改http服務器中的配置,使其支持text/cache-manifest,我使用的是apache服務器,是windows版本的,在apache的conf文件夾中找到mime.types文件,打開后在文件的最后加上
“text/cache-manifest

mf manifest”,重啟服務器即可。這一步很重要,我就是因為服務器端沒有配置這個,所以失敗了好多次,最后是在附錄鏈接1的回復中找到的線索。

經過以上設置Webview就可以支持HTML5的離線應用了。

附錄鏈接1中說緩沖目錄應該是getApplicationContext().getCacheDir().getAbsolutePath();但我經過試驗后發現設置那個目錄不起作用,可能是Android版本不同吧,我的是Android4.0.3,而他的可能是以前的Android版本吧。

緩沖目錄使用

getApplicationContext().getDir("cache", Context.MODE_PRIVATE).getPath()是從附錄鏈接2中找到的線索。

附錄鏈接:
1.http://alex.tapmania.org/2010/11/html5-cache-android-webview.html
2.http://johncookie.iteye.com/blog/1182459
3.HTML5 Offline官方文檔:http://www.w3.org/TR/html5/offline.html#manifests

原因:

webview加載 服務端的網頁,為了減少訪問壓力,用html5緩存技術,本地建了數據庫,在手機瀏覽器里 可以顯示頁面,換成webView就不行了。

public class efan_NewsReader extendsActivity {
        /** Called when the activity is first created. */
        @Override
        publicvoidonCreate(Bundle savedInstanceState)
        {   
                super.onCreate(savedInstanceState);   
                setContentView(R.layout.main);            
                WebView myWebView=(WebView)findViewById(R.id.my_webview);   
                myWebView.setWebViewClient(newWebViewClient());   
                WebSettings settings = myWebView.getSettings();
               // 開啟javascript設置
               settings.setJavaScriptEnabled(true);  
               // 設置可以使用localStorage
               settings.setDomStorageEnabled(true);
               // 應用可以有數據庫
               settings.setDatabaseEnabled(true);   
               String dbPath =this.getApplicationContest().getDir("database", Context.MODE_PRIVATE).getPath();
               settings.setDatabasePath(dbPath);
               // 應用可以有緩存
               settings.setAppCacheEnabled(true);            
               String appCaceDir =this.getApplicationContext().getDir("cache", Context.MODE_PRIVATE).getPath();
               settings.setAppCachePath(appCaceDir);
                
               myWebView.loadUrl("http://10.10.35.47:8080/html5test/test.htm");
        }
}

HTML5 page source code:

 <htmlmanifest="mymanifest.manifest">
    <head>
<metahttp-equiv="Content-Type"content="text/html; content="no-cache"charset=utf-8" />
<scripttype="text/javascript"src="js/jquery-1.6.1.min.js"></script>
 
<script>
$(document).ready(function(){      
 
    databaseTest();
});
 
function databaseTest(){
 
 
    //open database
     var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);  
 
      db.transaction(function (tx) {            
      tx.executeSql('CREATE TABLE IF NOT EXISTS testHtml (id unique, contentText)');
      tx.executeSql('INSERT INTO testHtml (contentText) VALUES ("insert data test!")');  
       });  
 
     db.transaction(function(tx){           
     tx.executeSql('SELECT * FROM testHtml',[],function(tx,result){
            var len=result.rows.length;
            var msg = "<p>Found rows: " + len + "</p>";  
             $("#testinfo").append(msg);
        },null);
     });   
 
 
}
 
</script>
 
 
</head>
<body>
    <div>here is test info:</div>
    <divid="testinfo"></div>
</body>

其他設置還有:
settings.setCacheMode(WebSettings.LOAD_DEFAULT); // 默認使用緩存
settings.setAppCacheMaxSize(810241024); //緩存最多可以有8M
settings.setAllowFileAccess(true); // 可以讀取文件緩存(manifest生效)

in WebChromeClient :

myWebView.setWebChromeClient(newWebChromeClient()
{   
        @Override   
        publicvoidonExceededDatabaseQuota(String url, String databaseIdentifier,
                       longcurrentQuota,longestimatedSize,longtotalUsedQuota,
                       WebStorage.QuotaUpdater quotaUpdater)   
        {        
                quotaUpdater.updateQuota(estimatedSize * 2);   
        }
}
myWebView.setWebChromeClient(newWebChromeClient()
{
    // 擴充緩存的容量   
        @Override   
        publicvoidonReachedMaxAppCacheSize(longspaceNeeded,longtotalUsedQuota,
                       WebStorage.QuotaUpdater quotaUpdater)   
        {        
                quotaUpdater.updateQuota(spaceNeeded * 2);
    }
}

按照范例,我成功的解決了我的問題,而且之前彈出框所出現的找不到數據(提示:underfine)也解決了,這個應該是當初數據庫沒設所引起的。

WebView中存在著兩種緩存:網頁數據緩存(存儲打開過的頁面及資源)、H5緩存(即appcache)。

一、網頁緩存

1、緩存構成
/data/data/package_name/cache/
/data/data/package_name/database/webview.db
/data/data/package_name/database/webviewCache.db

2、緩存模式
較難理解的是以下兩個模式:
LOAD_DEFAULT,根據cache-control決定是否從網絡上取數據。
LOAD_CACHE_ELSE_NETWORK,只要本地有,無論是否過期,或者no-cache,都使用緩存中的數據。
如:m.taobao.com的cache-control為no-cache,在模式LOAD_DEFAULT下,無論如何都會從網絡上取數據,如果沒有網絡,就會出現錯誤頁面;在LOAD_CACHE_ELSE_NETWORK模式下,無論是否有網絡,只要本地有緩存,都使用緩存。本地沒有緩存時才從網絡上獲取。
m.sina.com.cn的cache-control為max-age=60,在兩種模式下都使用本地緩存數據。

總結:根據以上兩種模式,建議緩存策略為,判斷是否有網絡,有的話,使用LOAD_DEFAULT,無網絡時,使用LOAD_CACHE_ELSE_NETWORK。

3、清除緩存
clearCache(boolean)。
CacheManager.clear。高版本中需要調用隱藏API。

4、控制大小
無系統API支持。
可選方式:定時統計緩存大小、按時間順序刪除緩存。

二、H5緩存

1、緩存構成
根據setAppCachePath(String appCachePath)提供的路徑,在H5使用緩存過程中生成的緩存文件。

2、緩存模式
無模式選擇,通過setAppCacheEnabled(boolean flag)設置是否打開。默認關閉,即,H5的緩存無法使用。

3、清除緩存
找到調用setAppCachePath(String appCachePath)設置緩存的路徑,把它下面的文件全部刪除就OK了。

4、控制大小
通過setAppCacheMaxSize(long appCacheMaxSize)設置緩存最大容量,默認為Max Integer。
同時,可能通過覆蓋WebChromeClient.onReachedMaxAppCacheSize(long requiredStorage, long quota, WebStorage.QuotaUpdater quotaUpdater)來設置緩存超過先前設置的最大容量時的策略。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,606評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,582評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,540評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,028評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,801評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,223評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,294評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,442評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,976評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,800評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,996評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,543評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,233評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,926評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,702評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,662評論 25 708
  • 0. 前言 前面有被用戶投訴 APP 流量消耗厲害: 于是乎考慮了流量方面的問題。暫時 APP 中涉及流量的幾個方...
    zyl06閱讀 24,126評論 5 62
  • WebView·開車指南 目錄 WebView簡介 WebView基本使用 WebView常用方法 WebSett...
    小莊bb閱讀 3,533評論 3 25
  • WebView·開車指南 目錄 WebView簡介 WebView基本使用 WebView常用方法 WebSett...
    南城的人閱讀 4,771評論 0 19
  • 2017-7-24(九十四) 感恩 —— 愛人一大早給爸爸轉了四萬,讓爸爸的店鋪可以很好的開始運營。祈愿愛人財富的...
    慢慢花開閱讀 173評論 0 0