I have an app that registers with GCM for push notifications. That code works fine and is not the source of my problem. Once registered, the app simply displays a website in a WebView. So far so good all this works if the device's network adapter is switched on.
If the network adapter is switched off then the webview should load from cache. This part is not working. I have followed the tutorial below and taken parts from it in a bit to save the website pages in a cache saved on the sdcard.
If i run the app the web site is displayed. If i then turn off the network adapter and visit the site, it will not display. I check the cache directory on the sdcard and parts of the site have been written to the cache.
Why doesn't the site load from cache when off-line?
Is it possible to keep the webpages it the cache until say the app is uninstalled or android decides otherwise?
tutorial
The tutorial shows you how to create a directory on the sdcard and write to it. The directories do exist but the webview is not restored from this cache in offline mode.
below is how i call the mainactivity that displays the webview.
Intent i = new Intent(getApplicationContext(), MainActivity.class);
//i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.putExtra("name", "hardcoded client name");
i.putExtra("email", "hardcoded email");
startActivity(i);
finish();
.
Here is the full MainActivity. You can ignore the first part as that's the code that handle the GCM push notification stuff, that all works. I need to know why the webview will not load from cache.
import static com.bmi.bmitestapp.CommonUtilities.DISPLAY_MESSAGE_ACTION;
import static com.bmi.bmitestapp.CommonUtilities.EXTRA_MESSAGE;
import static com.bmi.bmitestapp.CommonUtilities.SENDER_ID;
import java.io.File;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;
import android.widget.Toast;
import android.webkit.*;
import com.google.android.gcm.GCMRegistrar;
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
// label to display gcm messages
TextView lblMessage;
WebView webView;
// Asyntask
AsyncTask<Void, Void, Void> mRegisterTask;
// Alert dialog manager
AlertDialogManager alert = new AlertDialogManager();
// Connection detector
ConnectionDetector cd;
public static String name;
public static String email;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e(TAG, "in onCreate in mainactivity");
cd = new ConnectionDetector(getApplicationContext());
// Check if Internet present
// if (!cd.isConnectingToInternet()) {
// // Internet Connection is not present
// alert.showAlertDialog(MainActivity.this,
// "Internet Connection Error",
// "Please connect to working Internet connection", false);
// // stop executing code by return
// return;
// }
// Getting name, email from intent
Intent i = getIntent();
name = i.getStringExtra("name");
email = i.getStringExtra("email");
// Make sure the device has the proper dependencies.
GCMRegistrar.checkDevice(this);
// Make sure the manifest was properly set - comment out this line
// while developing the app, then uncomment it when it's ready.
GCMRegistrar.checkManifest(this);
lblMessage = (TextView) findViewById(R.id.lblMessage);
registerReceiver(mHandleMessageReceiver, new IntentFilter(
DISPLAY_MESSAGE_ACTION));
// Get GCM registration id
final String regId = GCMRegistrar.getRegistrationId(this);
// Check if regid already presents
if (regId.equals("")) {
// Registration is not present, register now with GCM
GCMRegistrar.register(this, SENDER_ID);
} else {
// Device is already registered on GCM
if (GCMRegistrar.isRegisteredOnServer(this)) {
// Skips registration.
Toast.makeText(getApplicationContext(), "Already registered with GCM", Toast.LENGTH_LONG).show();
} else {
// Try to register again, but not in the UI thread.
// It's also necessary to cancel the thread onDestroy(),
// hence the use of AsyncTask instead of a raw thread.
final Context context = this;
mRegisterTask = new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
// Register on our server
// On server creates a new user
ServerUtilities.register(context, name, email, regId);
return null;
}
@Override
protected void onPostExecute(Void result) {
mRegisterTask = null;
}
};
mRegisterTask.execute(null, null, null);
}
}
webView = (WebView)findViewById(R.id.webView1);
// Initialize the WebView
webView.getSettings().setSupportZoom(true);
webView.getSettings().setBuiltInZoomControls(true);
webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
webView.setScrollbarFadingEnabled(true);
webView.getSettings().setLoadsImagesAutomatically(true);
webView.getSettings().setDomStorageEnabled(true);
// Set cache size to 8 mb by default. should be more than enough
webView.getSettings().setAppCacheMaxSize(1024*1024*8);
// This next one is crazy. It's the DEFAULT location for your app's cache
// But it didn't work for me without this line.
// UPDATE: no hardcoded path. Thanks to Kevin Hawkins
String appCachePath = getApplicationContext().getCacheDir().getAbsolutePath();
Log.e(TAG, "appCachePath = " + appCachePath);
webView.getSettings().setAppCachePath(appCachePath);
webView.getSettings().setAllowFileAccess(true);
webView.getSettings().setAppCacheEnabled(true);
// Load the URLs inside the WebView, not in the external web browser
webView.setWebViewClient(new WebViewClient());
if (savedInstanceState == null)
{
if(isNetworkAvailable() == true){
Log.e(TAG, "we have a network connection");
webView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
webView.loadUrl("http://bmi.cubecore.co.uk");
} else {
Log.e(TAG, "we don't have a network connection");
webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ONLY);
webView.loadUrl("http://bmi.cubecore.co.uk");
}
}
} //end of oncreate
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null;
}
/**
* Receiving push messages
* */
private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String newMessage = intent.getExtras().getString(EXTRA_MESSAGE);
// Waking up mobile if it is sleeping
WakeLocker.acquire(getApplicationContext());
/**
* Take appropriate action on this message
* depending upon your app requirement
* For now i am just displaying it on the screen
* */
// Showing received message
lblMessage.append(newMessage + "\n");
Toast.makeText(getApplicationContext(), "New Message: " + newMessage, Toast.LENGTH_LONG).show();
// Releasing wake lock
WakeLocker.release();
}
};
@Override
protected void onDestroy() {
super.onDestroy();
// Clear the cache (this clears the WebViews cache for the entire application)
//webView.clearCache(false);
if (mRegisterTask != null) {
mRegisterTask.cancel(true);
}
try {
unregisterReceiver(mHandleMessageReceiver);
GCMRegistrar.onDestroy(this);
} catch (Exception e) {
Log.e("UnRegister Receiver Error", "> " + e.getMessage());
}
}
@Override
public void onBackPressed() {
super.onBackPressed();
}
@Override
protected void onResume() {
super.onResume();
Log.e(TAG, "in onResume in mainactivity");
}
@Override
public File getCacheDir()
{
// NOTE: this method is used in Android 2.1
Log.e(TAG, "getcachedir");
return getApplicationContext().getCacheDir();
}
@Override
protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
// Save the state of the WebView
webView.saveState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState)
{
super.onRestoreInstanceState(savedInstanceState);
// Restore the state of the WebView
webView.restoreState(savedInstanceState);
}
}
.
Here's the code from the tutorial above that writes to the sdcard.
package com.bmi.bmitestapp;
import java.io.File;
import android.app.Application;
import android.os.Environment;
import android.util.Log;
public class ApplicationExt extends Application
{
private static final String TAG = ApplicationExt.class.getSimpleName();
// NOTE: the content of this path will be deleted
// when the application is uninstalled (Android 2.2 and higher)
protected File extStorageAppBasePath;
protected File extStorageAppCachePath;
@Override
public void onCreate()
{
super.onCreate();
Log.e(TAG, "inside appext");
// Check if the external storage is writeable
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))
{
// Retrieve the base path for the application in the external storage
File externalStorageDir = Environment.getExternalStorageDirectory();
if (externalStorageDir != null)
{
// {SD_PATH}/Android/data/com.devahead.androidwebviewcacheonsd
extStorageAppBasePath = new File(externalStorageDir.getAbsolutePath() +
File.separator + "Android" + File.separator + "data" +
File.separator + getPackageName());
}
if (extStorageAppBasePath != null)
{
// {SD_PATH}/Android/data/com.devahead.androidwebviewcacheonsd/cache
extStorageAppCachePath = new File(extStorageAppBasePath.getAbsolutePath() +
File.separator + "cache");
boolean isCachePathAvailable = true;
if (!extStorageAppCachePath.exists())
{
// Create the cache path on the external storage
isCachePathAvailable = extStorageAppCachePath.mkdirs();
}
if (!isCachePathAvailable)
{
// Unable to create the cache path
extStorageAppCachePath = null;
}
}
}
}
@Override
public File getCacheDir()
{
// NOTE: this method is used in Android 2.2 and higher
if (extStorageAppCachePath != null)
{
// Use the external storage for the cache
Log.e(TAG, "extStorageAppCachePath = " + extStorageAppCachePath);
return extStorageAppCachePath;
}
else
{
// /data/data/com.devahead.androidwebviewcacheonsd/cache
return super.getCacheDir();
}
}
}
I thought i'd include a little logging. This is the logging from a fresh install with the network adapter ON.
01-29 14:13:10.220: D/dalvikvm(16904): Late-enabling CheckJNI
01-29 14:13:10.470: E/ApplicationExt(16904): inside appext
01-29 14:13:10.720: E/RegisterActivity(16904): in onresume in registeractivity
01-29 14:13:10.880: D/libEGL(16904): loaded /system/lib/egl/libEGL_tegra.so
01-29 14:13:11.000: D/libEGL(16904): loaded /system/lib/egl/libGLESv1_CM_tegra.so
01-29 14:13:11.030: D/libEGL(16904): loaded /system/lib/egl/libGLESv2_tegra.so
01-29 14:13:11.070: D/OpenGLRenderer(16904): Enabling debug mode 0
01-29 14:13:18.390: E/ApplicationExt(16904): extStorageAppCachePath = /mnt/sdcard/Android/data/com.bmi.bmitestapp/cache
01-29 14:13:18.390: D/webview(16904): [InitTabEffectPivot] >> nScreenWidth = 720
01-29 14:13:18.390: D/webview(16904): [InitTabEffectPivot] >> nScreenHeight = 1280
01-29 14:13:18.390: D/SqliteDatabaseCpp(16904): Registering sqlite logging func: /data/data/com.bmi.bmitestapp/databases/webview.db
01-29 14:13:18.390: D/SqliteDatabaseCpp(16904): DB info: open db, path = /data/data/com.bmi.bmitestapp/databases , key = sefraes, flag = 6, cannot stat file, errno = 2, message = No such file or directory
01-29 14:13:18.400: E/MainActivity(16904): in onCreate in mainactivity
01-29 14:13:18.400: D/SqliteDatabaseCpp(16904): DB info: path = /data/data/com.bmi.bmitestapp/databases , key = sefraes, handle: 0x1f9a858, type: w, r/w: (0,1), mode: delete, disk free size: 1276 M
01-29 14:13:18.400: D/GCMRegistrar(16904): resetting backoff for com.bmi.bmitestapp
01-29 14:13:18.420: V/GCMRegistrar(16904): Registering app com.bmi.bmitestapp of senders 598080744593
01-29 14:13:18.430: E/ApplicationExt(16904): extStorageAppCachePath = /mnt/sdcard/Android/data/com.bmi.bmitestapp/cache
01-29 14:13:18.430: E/MainActivity(16904): appCachePath = /mnt/sdcard/Android/data/com.bmi.bmitestapp/cache
01-29 14:13:18.430: E/MainActivity(16904): we have a network connection
01-29 14:13:18.430: E/MainActivity(16904): in onResume in mainactivity
01-29 14:13:18.490: W/webcore(16904): java.lang.Throwable: EventHub.removeMessages(int what = 107) is not supported before the WebViewCore is set up.
01-29 14:13:18.490: W/webcore(16904): at android.webkit.WebViewCore$EventHub.removeMessages(WebViewCore.java:1974)
01-29 14:13:18.490: W/webcore(16904): at android.webkit.WebViewCore$EventHub.access$9100(WebViewCore.java:1008)
01-29 14:13:18.490: W/webcore(16904): at android.webkit.WebViewCore.removeMessages(WebViewCore.java:2215)
01-29 14:13:18.490: W/webcore(16904): at android.webkit.WebView.sendOurVisibleRect(WebView.java:3285)
01-29 14:13:18.490: W/webcore(16904): at android.webkit.ZoomManager.setZoomScale(ZoomManager.java:772)
01-29 14:13:18.490: W/webcore(16904): at android.webkit.ZoomManager.access$1900(ZoomManager.java:59)
01-29 14:13:18.490: W/webcore(16904): at android.webkit.ZoomManager$PostScale.run(ZoomManager.java:1345)
01-29 14:13:18.490: W/webcore(16904): at android.os.Handler.handleCallback(Handler.java:608)
01-29 14:13:18.490: W/webcore(16904): at android.os.Handler.dispatchMessage(Handler.java:92)
01-29 14:13:18.490: W/webcore(16904): at android.os.Looper.loop(Looper.java:156)
01-29 14:13:18.490: W/webcore(16904): at android.app.ActivityThread.main(ActivityThread.java:5045)
01-29 14:13:18.490: W/webcore(16904): at java.lang.reflect.Method.invokeNative(Native Method)
01-29 14:13:18.490: W/webcore(16904): at java.lang.reflect.Method.invoke(Method.java:511)
01-29 14:13:18.490: W/webcore(16904): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
01-29 14:13:18.490: W/webcore(16904): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
01-29 14:13:18.490: W/webcore(16904): at dalvik.system.NativeStart.main(Native Method)
01-29 14:13:18.500: W/webcore(16904): java.lang.Throwable: EventHub.removeMessages(int what = 105) is not supported before the WebViewCore is set up.
01-29 14:13:18.500: W/webcore(16904): at android.webkit.WebViewCore$EventHub.removeMessages(WebViewCore.java:1974)
01-29 14:13:18.500: W/webcore(16904): at android.webkit.WebViewCore$EventHub.access$9100(WebViewCore.java:1008)
01-29 14:13:18.500: W/webcore(16904): at android.webkit.WebViewCore.removeMessages(WebViewCore.java:2215)
01-29 14:13:18.500: W/webcore(16904): at android.webkit.WebView.sendViewSizeZoom(WebView.java:3520)
01-29 14:13:18.500: W/webcore(16904): at android.webkit.ZoomManager.setZoomScale(ZoomManager.java:778)
01-29 14:13:18.500: W/webcore(16904): at android.webkit.ZoomManager.access$1900(ZoomManager.java:59)
01-29 14:13:18.500: W/webcore(16904): at android.webkit.ZoomManager$PostScale.run(ZoomManager.java:1345)
01-29 14:13:18.500: W/webcore(16904): at android.os.Handler.handleCallback(Handler.java:608)
01-29 14:13:18.500: W/webcore(16904): at android.os.Handler.dispatchMessage(Handler.java:92)
01-29 14:13:18.500: W/webcore(16904): at android.os.Looper.loop(Looper.java:156)
01-29 14:13:18.500: W/webcore(16904): at android.app.ActivityThread.main(ActivityThread.java:5045)
01-29 14:13:18.500: W/webcore(16904): at java.lang.reflect.Method.invokeNative(Native Method)
01-29 14:13:18.500: W/webcore(16904): at java.lang.reflect.Method.invoke(Method.java:511)
01-29 14:13:18.500: W/webcore(16904): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
01-29 14:13:18.500: W/webcore(16904): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
01-29 14:13:18.500: W/webcore(16904): at dalvik.system.NativeStart.main(Native Method)
01-29 14:13:18.530: D/OpenGLRenderer(16904): Flushing caches (mode 0)
01-29 14:13:18.570: I/SqliteDatabaseCpp(16904): sqlite returned: error code = 1, msg = no such table: CacheGroups
01-29 14:13:18.570: I/SqliteDatabaseCpp(16904): sqlite returned: error code = 1, msg = no such table: Caches
01-29 14:13:18.570: I/SqliteDatabaseCpp(16904): sqlite returned: error code = 1, msg = no such table: Origins
01-29 14:13:18.570: I/SqliteDatabaseCpp(16904): sqlite returned: error code = 1, msg = no such table: DeletedCacheResources
01-29 14:13:18.850: E/ApplicationExt(16904): extStorageAppCachePath = /mnt/sdcard/Android/data/com.bmi.bmitestapp/cache
01-29 14:13:19.330: I/PRIME(16904): <CallBackProxy> Send to WebViewClient.
01-29 14:13:19.370: V/GCMBroadcastReceiver(16904): onReceive: com.google.android.c2dm.intent.REGISTRATION
01-29 14:13:19.370: V/GCMBroadcastReceiver(16904): GCM IntentService class: com.bmi.bmitestapp.GCMIntentService
01-29 14:13:19.370: V/GCMBaseIntentService(16904): Acquiring wakelock
01-29 14:13:19.460: V/GCMBaseIntentService(16904): Intent service name: GCMIntentService-598080744593-1
01-29 14:13:19.470: E/GCMRegistrar(16904): internal error: retry receiver class not set yet
01-29 14:13:19.480: V/GCMRegistrar(16904): Registering receiver
01-29 14:13:19.480: D/GCMBaseIntentService(16904): handleRegistration: registrationId = APA91bFytZvnkmsEVHSnw5VRxIwfPRmPsSRVrgRNRa5ww3oqCfnLEZMaBBNtQtlZoK4RD4VQXfAfKDsQUa53PwQBH_rwuI_gEEdHQhxadpBVmJ7L3Dxy90Bzryg_aCWx20-cdZ32cbiiaGR3zUMjpqZizYQbnARN4w, error = null, unregistered = null
01-29 14:13:19.480: D/GCMRegistrar(16904): resetting backoff for com.bmi.bmitestapp
01-29 14:13:19.480: V/GCMRegistrar(16904): Saving regId on app version 1
01-29 14:13:19.490: I/GCMIntentService(16904): Device registered: regId = APA91bFytZvnkmsEVHSnw5VRxIwfPRmPsSRVrgRNRa5ww3oqCfnLEZMaBBNtQtlZoK4RD4VQXfAfKDsQUa53PwQBH_rwuI_gEEdHQhxadpBVmJ7L3Dxy90Bzryg_aCWx20-cdZ32cbiiaGR3zUMjpqZizYQbnARN4w
01-29 14:13:19.490: D/NAME(16904): hardcoded client name
01-29 14:13:19.490: I/bmi GCM(16904): registering device (regId = APA91bFytZvnkmsEVHSnw5VRxIwfPRmPsSRVrgRNRa5ww3oqCfnLEZMaBBNtQtlZoK4RD4VQXfAfKDsQUa53PwQBH_rwuI_gEEdHQhxadpBVmJ7L3Dxy90Bzryg_aCWx20-cdZ32cbiiaGR3zUMjpqZizYQbnARN4w)
01-29 14:13:19.490: D/bmi GCM(16904): Attempt #1 to register
01-29 14:13:19.500: V/bmi GCM(16904): Posting 'email=hardcoded email®Id=APA91bFytZvnkmsEVHSnw5VRxIwfPRmPsSRVrgRNRa5ww3oqCfnLEZMaBBNtQtlZoK4RD4VQXfAfKDsQUa53PwQBH_rwuI_gEEdHQhxadpBVmJ7L3Dxy90Bzryg_aCWx20-cdZ32cbiiaGR3zUMjpqZizYQbnARN4w&name=hardcoded client name' to http://mobilewebexpert.co.uk/pushtest/register.php
01-29 14:13:19.500: E/URL(16904): > http://mobilewebexpert.co.uk/pushtest/register.php
01-29 14:13:20.610: V/GCMRegistrar(16904): Setting registeredOnServer status as true until 2013-02-05 14:13:20.617
01-29 14:13:20.620: V/GCMBaseIntentService(16904): Releasing wakelock
01-29 14:13:21.470: D/skia(16904): notifyPluginsOnFrameLoad not postponed
01-29 14:13:21.570: D/SQLiteDatabase(16904): Create pool connection
01-29 14:13:21.570: D/SqliteDatabaseCpp(16904): DB info: open db, path = /data/data/com.bmi.bmitestapp/databases , key = sefraes, flag = 1, file size = 12288
01-29 14:13:21.570: D/SqliteDatabaseCpp(16904): DB info: path = /data/data/com.bmi.bmitestapp/databases , key = sefraes, handle: 0x2797350, type: r, r/w: (1,1), mode: wal, disk free size: 1276 M
.
This is the logging after i have turned off the network adapter.
01-29 14:16:57.080: E/RegisterActivity(16904): in onresume in registeractivity
01-29 14:17:03.490: D/webview(16904): [InitTabEffectPivot] >> nScreenWidth = 720
01-29 14:17:03.490: D/webview(16904): [InitTabEffectPivot] >> nScreenHeight = 1280
01-29 14:17:03.490: E/MainActivity(16904): in onCreate in mainactivity
01-29 14:17:03.490: V/GCMRegistrar(16904): Is registered on server: true
01-29 14:17:03.500: E/ApplicationExt(16904): extStorageAppCachePath = /mnt/sdcard/Android/data/com.bmi.bmitestapp/cache
01-29 14:17:03.500: E/MainActivity(16904): appCachePath = /mnt/sdcard/Android/data/com.bmi.bmitestapp/cache
01-29 14:17:03.500: E/MainActivity(16904): we don't have a network connection
01-29 14:17:03.500: E/MainActivity(16904): in onResume in mainactivity
01-29 14:17:03.500: D/chromium(16904): Unknown chromium error: -400
01-29 14:17:03.540: D/skia(16904): notifyPluginsOnFrameLoad not postponed
01-29 14:17:03.580: D/OpenGLRenderer(16904): Flushing caches (mode 0)
One thing i've noticed, it might be nothing, but registeractivity is the activity that calls MainActivity. RegisterActivity just has a button that fires an Intent for MainActivity. After the network adapter is off i have to press the button on registerAcivity, which calls onCreate in MainActivity. It is like it's a new instance of MainActivity?? Could this be effecting the caching of the webview. Effectively the onDestroy of the main activity must have been called along the way.
Also another thing has caught my attention.
01-29 14:17:03.580: D/OpenGLRenderer(16904): Flushing caches (mode 0)
You might often face issues in updating the chrome and Android System Webview. To fix this problem, you can reboot your device, check your internet connection, stop auto-updating all apps, clear Google Playstore cache, and storage, leave the beta testing program, and manually update Android WebView app from Playstore.
Web View is slower on both as compared to native android browser.
This interface was deprecated in API level 12. This interface is now obsolete.
For that particular URL http://bmi.cubecore.co.uk
, your WebView's caching is prohibited by that http server, see the response header Cache-Control:
200 OK
... ...
Pragma: no-cache
Server: Apache/2.2.3 (CentOS)
Content-Type: text/html; charset=utf-8
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Expires: Thu, 19 Nov 1981 08:52:00 GMT
This means the client must always connect and load the URL from http server, never from its local cache. That also explained why Unknown chromium error: -400
occurred when you try to load the page after network adapter is switched off. Unknown chromium error: -400
generally means failed to connect internet for some reason.
There is nothing you can do without login and adjust the http server settings. You can use the following URL exam your cache implementation:
http://stackoverflow.com/questions/14549638/webview-not-displaying-website-when-offline
The response header is:
200 OK
... ...
Last-Modified: Wed, 30 Jan 2013 00:28:59 GMT
Vary: *
Content-Type: text/html; charset=utf-8
Cache-Control: public, max-age=60
Expires: Wed, 30 Jan 2013 00:29:59 GMT
If there is no other issue in your code, your cache implementation should work.
This is not what http cache is intended for. If you want to enable offline access for html pages you should use AppCache. Try these two tutorials:
I would not use AppCache if you are writing a native Android app. Load the documents you want to serve yourself, and load them into the webview with either WebView.loadData(...) or create a ContentProvider and use WebView.loadUrl with a content:// prefix. Using ContentProvider is the best way, but loading a data url should be quick to test.
I hope this will get you started, reply if you need help loading the data from a URL in your app.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With