Ich habe eine Android-App, die einfach eine Website enthält. Ich möchte, dass die App die Seiten der Website für die Offline-Nutzung zwischenspeichert.Android WebView lädt keine zweite Seite aus dem Cache
Ich mache einen einfachen Test, um zu sehen, ob der Cache funktioniert, aber es ist leider nicht möglich, eine Seite zu laden, die ich zuvor im Online-Modus geladen habe, wenn offline. Zur besseren Übersicht lade ich im Online-Modus die folgenden 2 Seiten ein.
webView.loadUrl("http://www.bmimobile.co.uk/why-bmi.php", getHeaders());
webView.loadUrl("http://www.bmimobile.co.uk/", getHeaders());
.
Ich hoffe, dass die "why-bmi.php" Seite in den Cache sowie die folgende Seite http://www.bmimobile.co.uk/ geladen wird. Die letztere Seite hat einen Link darauf, der auf die erste Seite verweist. Wenn ich dann aus der App komme und den Netzwerkadapter ausschalte gehe dann wieder in die App die "http://www.bmimobile.co.uk/" Seite wird angezeigt, aber wenn ich auf den "why-bmi" Link klicke, wird diese Seite NICHT angezeigt. Ich kurze Toast-Nachricht zeigt "Fehler beim Laden der Seite".
Kann mir jemand sagen, warum die Webansicht die geladene Seite nicht für die spätere Offline-Nutzung zwischenspeichert?
Hier ist die Hauptaktivität und ich habe das Anwendungsobjekt, das den appcachepath definiert, erweitert.
Vielen Dank im Voraus
Matt
package uk.bmi.mobile;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import android.app.Activity;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.util.Log;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MainActivity extends Activity {
private WebView webView;
private static final String TAG = MainActivity.class.getSimpleName();
ApplicationExt bmiAppObj;
//instruct server to set it's headers to make resources cachable
private Map<String, String> getHeaders() {
Map<String, String> headers = new HashMap<String, String>();
headers.put("IS_ALEX_APP", "1");
return headers;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e(TAG, "in onCreate in mainactivity");
} //end of oncreate
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null;
}
@Override
protected void onResume() {
super.onResume();
Log.e(TAG, "in onResume in mainactivity");
webView = (WebView)findViewById(R.id.webView1);
bmiAppObj = (ApplicationExt)getApplication();
if(isNetworkAvailable() == true){
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);
webView.getSettings().setAppCacheEnabled(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().setJavaScriptEnabled(true);
// Load the URLs inside the WebView, not in the external web browser
webView.setWebViewClient(new WebViewClient());
webView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
webView.loadUrl("http://www.bmimobile.co.uk/why-bmi.php", getHeaders());
webView.loadUrl("http://www.bmimobile.co.uk/", getHeaders());
}else{
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);
webView.getSettings().setAppCacheEnabled(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().setJavaScriptEnabled(true);
// Load the URLs inside the WebView, not in the external web browser
webView.setWebViewClient(new WebViewClient());
webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ONLY);
webView.loadUrl("http://www.bmimobile.co.uk/", getHeaders());
}
}
@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);
}
}//end of mainActivity
.
package uk.bmi.mobile;
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;
Webservice webservice;
BmiDB bmiDb;
@Override
public void onCreate()
{
super.onCreate();
Log.e(TAG, "inside appext");
webservice = new Webservice(this);
bmiDb = new BmiDB(this);
// 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;
}
}
}
}//end of onCreate
@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();
}
}
}
.Dies ist die Protokollierung, wenn die App zuerst im Online-Modus
02-16 08:38:52.744: I/NONPRIME(8871): <CallBackProxy> Send to WebViewClient.
02-16 08:38:56.314: D/skia(8871): ----- started: [1 325] http://www.bmimobile.co.uk/images/mobile/bg-index.png
02-16 08:38:56.499: D/skia(8871): ----- started: [1 64] http://www.bmimobile.co.uk/CubeCore/modules/cubeMobile/images/bg-black-bar.png
02-16 08:38:56.509: D/skia(8871): ----- started: [26 20] http://www.bmimobile.co.uk/images/mobile/home-icon.png
02-16 08:38:56.529: D/skia(8871): ----- started: [275 189] http://www.bmimobile.co.uk/images/mobile/home-img.png
02-16 08:38:56.549: D/skia(8871): ----- started: [320 450] http://www.bmimobile.co.uk/images/mobile/welcome/bg-welcome.jpg
02-16 08:38:56.554: D/skia(8871): ----- started: [270 38] http://www.bmimobile.co.uk/images/mobile/welcome/next.png
02-16 08:38:56.584: D/skia(8871): ----- started: [16 17] http://www.bmimobile.co.uk/images/mobile/why.png
02-16 08:38:56.584: D/skia(8871): ----- started: [18 17] http://www.bmimobile.co.uk/images/mobile/services.png
02-16 08:38:56.584: D/skia(8871): ----- started: [20 15] http://www.bmimobile.co.uk/images/mobile/visit.png
02-16 08:38:56.589: D/skia(8871): ----- started: [20 15] http://www.bmimobile.co.uk/images/mobile/consultants.png
02-16 08:38:56.589: D/skia(8871): ----- started: [13 19] http://www.bmimobile.co.uk/images/mobile/contact.png
geladen wird.
Dies ist die Protokollierung, wenn ich aus der App aus dem Netzwerk-Adapter ausgeschaltet und dann zurück in die App im Offline-Modus gegangen bin.
02-16 08:41:37.799: E/MainActivity(8871): in onResume in mainactivity
02-16 08:41:37.804: E/ApplicationExt(8871): extStorageAppCachePath = /storage/sdcard0/Android/data/uk.bmi.mobile/cache
02-16 08:41:37.804: E/MainActivity(8871): appCachePath = /storage/sdcard0/Android/data/uk.bmi.mobile/cache
02-16 08:41:37.834: W/dalvikvm(8871): disableGcForExternalAlloc: false
[edit1] Eigentlich bei näherer Betrachtung der Protokollierung, so scheint es geändert zu haben, wenn im Online-Modus geladen. Unten ist der Logcat im Omline-Modus. Es scheint ein Problem mit dem Cache-Speicher zu geben.
02-19 15:16:10.497: E/ApplicationExt(5467): inside appext
02-19 15:16:10.687: E/ApplicationExt(5467): extStorageAppCachePath = /storage/sdcard0/Android/data/uk.bmi.mobile/cache
02-19 15:16:10.722: E/MainActivity(5467): in onCreate in mainactivity
02-19 15:16:10.727: E/MainActivity(5467): in onResume in mainactivity
02-19 15:16:10.737: E/ApplicationExt(5467): extStorageAppCachePath = /storage/sdcard0/Android/data/uk.bmi.mobile/cache
02-19 15:16:10.737: E/MainActivity(5467): appCachePath = /storage/sdcard0/Android/data/uk.bmi.mobile/cache
02-19 15:16:10.792: E/(5467): file /data/data/com.nvidia.NvCPLSvc/files/driverlist.txt: not found!
02-19 15:16:10.792: I/(5467): Attempting to load EGL implementation /system/lib//egl/libEGL_tegra_impl
02-19 15:16:10.807: I/(5467): Loaded EGL implementation /system/lib//egl/libEGL_tegra_impl
02-19 15:16:10.842: I/(5467): Loading GLESv2 implementation /system/lib//egl/libGLESv2_tegra_impl
02-19 15:16:10.882: E/SQLiteLog(5467): (1) no such table: CacheGroups
02-19 15:16:10.882: D/WebKit(5467): ERROR:
02-19 15:16:10.882: D/WebKit(5467): Application Cache Storage: failed to execute statement "DELETE FROM CacheGroups" error "no such table: CacheGroups"
02-19 15:16:10.882: D/WebKit(5467): external/webkit/Source/WebCore/loader/appcache/ApplicationCacheStorage.cpp(558) : bool WebCore::ApplicationCacheStorage::executeSQLCommand(const WTF::String&)
02-19 15:16:10.882: E/SQLiteLog(5467): (1) no such table: Caches
02-19 15:16:10.882: D/WebKit(5467): ERROR:
02-19 15:16:10.882: D/WebKit(5467): Application Cache Storage: failed to execute statement "DELETE FROM Caches" error "no such table: Caches"
02-19 15:16:10.882: D/WebKit(5467): external/webkit/Source/WebCore/loader/appcache/ApplicationCacheStorage.cpp(558) : bool WebCore::ApplicationCacheStorage::executeSQLCommand(const WTF::String&)
02-19 15:16:10.882: E/SQLiteLog(5467): (1) no such table: Origins
02-19 15:16:10.882: D/WebKit(5467): ERROR:
02-19 15:16:10.882: D/WebKit(5467): Application Cache Storage: failed to execute statement "DELETE FROM Origins" error "no such table: Origins"
02-19 15:16:10.882: D/WebKit(5467): external/webkit/Source/WebCore/loader/appcache/ApplicationCacheStorage.cpp(558) : bool WebCore::ApplicationCacheStorage::executeSQLCommand(const WTF::String&)
02-19 15:16:10.882: E/SQLiteLog(5467): (1) no such table: DeletedCacheResources
02-19 15:16:10.992: E/ApplicationExt(5467): extStorageAppCachePath = /storage/sdcard0/Android/data/uk.bmi.mobile/cache
02-19 15:16:11.022: W/dalvikvm(5467): disableGcForExternalAlloc: false
02-19 15:16:13.787: I/NONPRIME(5467): <CallBackProxy> Send to WebViewClient.
02-19 15:16:21.427: D/skia(5467): ----- started: [1 325] http://www.bmimobile.co.uk/images/mobile/bg-index.png
02-19 15:16:21.517: D/skia(5467): ----- started: [1 64] http://www.bmimobile.co.uk/CubeCore/modules/cubeMobile/images/bg-black-bar.png
02-19 15:16:21.542: D/skia(5467): ----- started: [26 20] http://www.bmimobile.co.uk/images/mobile/home-icon.png
02-19 15:16:21.577: D/skia(5467): ----- started: [275 189] http://www.bmimobile.co.uk/images/mobile/home-img.png
02-19 15:16:21.597: D/skia(5467): ----- started: [270 38] http://www.bmimobile.co.uk/images/mobile/welcome/next.png
02-19 15:16:21.677: D/skia(5467): ----- started: [16 17] http://www.bmimobile.co.uk/images/mobile/why.png
02-19 15:16:21.677: D/skia(5467): ----- started: [20 15] http://www.bmimobile.co.uk/images/mobile/visit.png
02-19 15:16:21.677: D/skia(5467): ----- started: [18 17] http://www.bmimobile.co.uk/images/mobile/services.png
02-19 15:16:21.687: D/skia(5467): ----- started: [20 15] http://www.bmimobile.co.uk/images/mobile/consultants.png
02-19 15:16:21.687: D/skia(5467): ----- started: [13 19] http://www.bmimobile.co.uk/images/mobile/contact.png
02-19 15:16:21.692: D/skia(5467): ----- started: [320 450] http://www.bmimobile.co.uk/images/mobile/welcome/bg-welcome.jpg
.
[notes] Wenn ich im Online-Modus auf die Why-Bmi-Taste klicke, dann aus der App, schalte den Adapter aus und klicke erneut auf die Why-Bmi-Taste, dann erscheint die Meldung "Fehler beim Laden der Seite" .
Wenn ich jedoch zu den folgenden URLs wechseln, wird meine SO-Seite angezeigt. Wenn ich auf den Link zu meiner Bounty-Seite (diese Seite) klicke und dann offline gehe, wird die SO-Seite wie erwartet angezeigt. Wenn Sie jedoch im Offline-Modus auf den Bounty-Link klicken, wird dieser angezeigt. Es gibt also Unterschiede zwischen der SO-Site und der bmi-Site.
if(isNetworkAvailable() == true){
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);
webView.getSettings().setAppCacheEnabled(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().setJavaScriptEnabled(true);
// Load the URLs inside the WebView, not in the external web browser
webView.setWebViewClient(new WebViewClient());
webView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
//webView.loadUrl("http://www.bmimobile.co.uk/why-bmi.php", getHeaders());
//webView.loadUrl("http://www.bmimobile.co.uk/", getHeaders());
webView.loadUrl("http://stackoverflow.com/users/532462/turtleboy?tab=bounties");
webView.loadUrl("http://stackoverflow.com/users/532462/turtleboy");
}else{
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);
webView.getSettings().setAppCacheEnabled(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().setJavaScriptEnabled(true);
// Load the URLs inside the WebView, not in the external web browser
webView.setWebViewClient(new WebViewClient());
webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ONLY);
// webView.loadUrl("http://www.bmimobile.co.uk/", getHeaders());
webView.loadUrl("http://stackoverflow.com/users/532462/turtleboy");
}
}
[edit2]
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="uk.bmi.mobile"
android:versionCode="5"
android:versionName="1.0.4" >
<!-- GCM requires Android SDK version 2.2 (API level <img src="http://www.androidhive.info/wp-includes/images/smilies/icon_cool.gif" alt="8)" class="wp-smiley"> or above. -->
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16" />
<!-- GCM connects to Internet Services. -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- GCM requires a Google account. -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- Creates a custom permission so only this app can receive its messages. -->
<permission
android:name="uk.bmi.mobile.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="uk.bmi.mobile.permission.C2D_MESSAGE" />
<!-- This app has permission to register and receive data message. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!-- Network State Permissions to detect Internet status -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Permission to vibrate -->
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permisson.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!-- Main activity. -->
<application
android:icon="@drawable/bmi_icon"
android:label="@string/app_name"
android:name="uk.bmi.mobile.ApplicationExt" >
<!-- Register Activity -->
<activity
android:name=".RegisterActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Main Activity -->
<activity
android:name="uk.bmi.mobile.MainActivity"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name"
android:screenOrientation="portrait" >
</activity>
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<!-- Receives the actual messages. -->
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<!-- Receives the registration id. -->
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="uk.bmi.mobile" />
</intent-filter>
</receiver>
<service android:name="uk.bmi.mobile.GCMIntentService" />
</application>
</manifest>
haben Sie die Berechtigung READ_EXTERNAL_STORAGE gesetzt? –
@Yalla T. Hallo Nein, ich habe nicht, werde ich es aufnehmen müssen? – turtleboy
Nein, habe ich nicht, muss ich es aufnehmen? – turtleboy