Android webView 快取 Cache + HTML5離線功能解決
頁面快取是指載入一個網頁時的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);
- 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版本吧。
原因:
webview載入 服務端的網頁,為了減少訪問壓力,用html5快取技術,本地建了資料庫,在手機瀏覽器裡 可以顯示頁面,換成webView就不行了。
解決範例:
Activity code:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public class efan_NewsReader extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super .onCreate(savedInstanceState);
setContentView(R.layout.main);
WebView myWebView=(WebView)findViewById(R.id.my_webview);
myWebView.setWebViewClient( new WebViewClient());
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:
?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
< html manifest = "mymanifest.manifest" >
< head >
< meta http-equiv = "Content-Type" content = "text/html;
content=" no-cache" charset = utf -8" />
< script type = "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 >
< div id = "testinfo" ></ div >
</ body >
|
其他設定還有:
settings.setCacheMode(WebSettings.LOAD_DEFAULT); // 預設使用快取
settings.setAppCacheMaxSize(8*1024*1024); //快取最多可以有8M
settings.setAllowFileAccess(true); // 可以讀取檔案快取(manifest生效)
in WebChromeClient :
?
01 02 03 04 05 06 07 08 09 10 |
myWebView.setWebChromeClient( new WebChromeClient()
{
@Override
public void onExceededDatabaseQuota(String url, String databaseIdentifier,
long currentQuota, long estimatedSize, long totalUsedQuota,
WebStorage.QuotaUpdater quotaUpdater)
{
quotaUpdater.updateQuota(estimatedSize * 2 );
}
}
|
or:
?
01 02 03 04 05 06 07 08 09 10 |
myWebView.setWebChromeClient( new WebChromeClient()
{
// 擴充快取的容量
@Override
public void onReachedMaxAppCacheSize( long spaceNeeded, long totalUsedQuota,
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)來設定快取超過先前設定的最大容量時的策略。
三、參考網址
以下地址有關於H5快取的一些內幕,如每個Application只調用一次WebSettings.setAppCachePath(),WebSettings.setAppCacheMaxSize()被忽略等一系列問題,需要仔細閱讀和實驗。
http://code.google.com/p/android/issues/detail?id=24180