Webview中如何加载缓存页面
How to Load Cache Page in Webview
我在 HTML 页面上应用了缓存清单。
On Chrome 当互联网连接断开时,浏览器会重定向到缓存模式。
那么,Android-Webview 就不是这样了。它给出以下错误:
Webpage could not be loaded
net:ERR_NAME_NOT_RESOLVED
已查阅各种资源,但 none 似乎有所帮助。
下面是我使用的代码:
package com.example.page;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.view.View;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
import com.google.firebase.iid.FirebaseInstanceId;
public class MainActivity extends Activity {
public static WebView mWebview;
private android.content.Context Context;
private static String getIntentValue = null;
public static SharedPreferences sharedPreferences;
private ProgressDialog mProgressDialog;
private String mCM;
private ValueCallback<Uri> mUM;
private ValueCallback<Uri[]> mUMA;
private final static int FCR=1;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent){
super.onActivityResult(requestCode, resultCode, intent);
mWebview.setWebViewClient(new Callback());
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Context = this;
String regId = FirebaseInstanceId.getInstance().getToken();
getIntentValue = getIntent().getStringExtra("value");
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
if (!DetectConnection.checkInternetConnection(this)) {
Toast.makeText(getApplicationContext(), "No Internet Connection!", Toast.LENGTH_LONG).show();
finish(); //Calling this method to close this activity when internet is not available.
} else {
mWebview = (WebView) findViewById(R.id.webview1);
WebSettings webSettings = mWebview.getSettings();
mWebview.getSettings().setJavaScriptEnabled(true);
mWebview.setWebChromeClient(new WebChromeClient());
mWebview.setWebViewClient(new CustomWebViewClient());
//improve WebView Performance
mWebview.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
mWebview.getSettings().setAppCacheEnabled(false);
mWebview.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
if(Build.VERSION.SDK_INT >=23 && (ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.CAMERA}, 1);
}
mWebview.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
webSettings.setDomStorageEnabled(true);
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
webSettings.setUseWideViewPort(true);
webSettings.setAllowFileAccess(true);
webSettings.setSavePassword(true);
webSettings.setSaveFormData(true);
webSettings.setEnableSmoothTransition(true);
// progress dialog
mProgressDialog = new ProgressDialog(Context);
if (sharedPreferences.getBoolean("isKeyGenerated", true)) {
if (getIntentValue != null) {
mWebview.loadUrl("http://www.example.com/page");
getIntentValue = null;
} else {
mWebview.loadUrl("http://www.example.com/page2");
}
}
}
}
public class Callback extends WebViewClient{
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl){
Toast.makeText(getApplicationContext(), "Failed loading app!", Toast.LENGTH_SHORT).show();
}
}
// Function to load all URLs in same webview
private class CustomWebViewClient extends WebViewClient {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.contains(".pdf")) {
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(i);
} else {
view.loadUrl(url);
}
return true;
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
super.onPageStarted(view, url, favicon);
//on page started, show loading page
mProgressDialog.setCancelable(true);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.show();
}
@Override
public void onPageFinished(WebView view, String url)
{
String currentPage= mWebview.getUrl();
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("currentpage",currentPage);
editor.commit();
//after loading page, remove loading page
// TODO Auto-generated method stub
super.onPageFinished(view, url);
mProgressDialog.dismiss();
}
@Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
view.loadUrl("http://example.com/page");
}
}
@Override
public void onBackPressed() {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
String currenturl = sharedPreferences.getString("currentpage", null);
mWebview.requestFocus();
if (currenturl.contains("http://example.com/page")){
moveTaskToBack(true);
}else{
mWebview.goBack();
}
if (mWebview.canGoBack()) {
if (!DetectConnection.checkInternetConnection(Context)) {
Toast.makeText(Context, "No Internet Connection!", Toast.LENGTH_SHORT).show();
}
}
}
public static void loadUrl(String key) {
if (getIntentValue != null) {
mWebview.loadUrl("http://example.com/page");
getIntentValue = null;
} else {
mWebview.loadUrl("http://example.com/page");
}
}
public static void reLoad() {
mWebview.reload();
}
@Override
public void onConfigurationChanged(Configuration newConfig){
super.onConfigurationChanged(newConfig);
}
}
更改此行:
mWebview.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
收件人:
mWebview.getSettings().setCacheMode( WebSettings.LOAD_CACHE_ELSE_NETWORK)
mWebview.getSettings().setCacheMode( WebSettings.LOAD_CACHE_ELSE_NETWORK)
这将告诉 WebView 从缓存中加载页面,但如果它需要缓存中没有的任何内容,它会查找网络,当您没有连接时,它只会给您 "page could not be loaded error." 这是因为遗憾的是并非所有内容都存储在缓存中,即使使用此设置,您也会注意到浏览器正在使用网络。
使用WebSettings.LOAD_CACHE_ONLY
mWebview.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ONLY);
只需包含 enableHTML5AppCache()
private void enableHTML5AppCache() {
mWebview.getSettings().setDomStorageEnabled(true);
mWebview.getSettings().setAppCachePath("/data/data/" + getPackageName() + "/cache");
mWebview.getSettings().setAppCacheEnabled(true);
mWebview.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
}
2021 更新内容已更改:已弃用
应用程序缓存 API 已弃用,一旦在 Chromium 中删除支持,此方法将成为所有 Android 版本的空操作。考虑改用 Service Worker。有关详细信息,请参阅 https://web.dev/appcache-removal/。
改为阅读服务人员 :) 快乐编码:P
我在 HTML 页面上应用了缓存清单。
On Chrome 当互联网连接断开时,浏览器会重定向到缓存模式。 那么,Android-Webview 就不是这样了。它给出以下错误:
Webpage could not be loaded
net:ERR_NAME_NOT_RESOLVED
已查阅各种资源,但 none 似乎有所帮助。
下面是我使用的代码:
package com.example.page;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.view.View;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
import com.google.firebase.iid.FirebaseInstanceId;
public class MainActivity extends Activity {
public static WebView mWebview;
private android.content.Context Context;
private static String getIntentValue = null;
public static SharedPreferences sharedPreferences;
private ProgressDialog mProgressDialog;
private String mCM;
private ValueCallback<Uri> mUM;
private ValueCallback<Uri[]> mUMA;
private final static int FCR=1;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent){
super.onActivityResult(requestCode, resultCode, intent);
mWebview.setWebViewClient(new Callback());
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Context = this;
String regId = FirebaseInstanceId.getInstance().getToken();
getIntentValue = getIntent().getStringExtra("value");
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
if (!DetectConnection.checkInternetConnection(this)) {
Toast.makeText(getApplicationContext(), "No Internet Connection!", Toast.LENGTH_LONG).show();
finish(); //Calling this method to close this activity when internet is not available.
} else {
mWebview = (WebView) findViewById(R.id.webview1);
WebSettings webSettings = mWebview.getSettings();
mWebview.getSettings().setJavaScriptEnabled(true);
mWebview.setWebChromeClient(new WebChromeClient());
mWebview.setWebViewClient(new CustomWebViewClient());
//improve WebView Performance
mWebview.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
mWebview.getSettings().setAppCacheEnabled(false);
mWebview.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
if(Build.VERSION.SDK_INT >=23 && (ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.CAMERA}, 1);
}
mWebview.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
webSettings.setDomStorageEnabled(true);
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
webSettings.setUseWideViewPort(true);
webSettings.setAllowFileAccess(true);
webSettings.setSavePassword(true);
webSettings.setSaveFormData(true);
webSettings.setEnableSmoothTransition(true);
// progress dialog
mProgressDialog = new ProgressDialog(Context);
if (sharedPreferences.getBoolean("isKeyGenerated", true)) {
if (getIntentValue != null) {
mWebview.loadUrl("http://www.example.com/page");
getIntentValue = null;
} else {
mWebview.loadUrl("http://www.example.com/page2");
}
}
}
}
public class Callback extends WebViewClient{
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl){
Toast.makeText(getApplicationContext(), "Failed loading app!", Toast.LENGTH_SHORT).show();
}
}
// Function to load all URLs in same webview
private class CustomWebViewClient extends WebViewClient {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.contains(".pdf")) {
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(i);
} else {
view.loadUrl(url);
}
return true;
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
super.onPageStarted(view, url, favicon);
//on page started, show loading page
mProgressDialog.setCancelable(true);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.show();
}
@Override
public void onPageFinished(WebView view, String url)
{
String currentPage= mWebview.getUrl();
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("currentpage",currentPage);
editor.commit();
//after loading page, remove loading page
// TODO Auto-generated method stub
super.onPageFinished(view, url);
mProgressDialog.dismiss();
}
@Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
view.loadUrl("http://example.com/page");
}
}
@Override
public void onBackPressed() {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
String currenturl = sharedPreferences.getString("currentpage", null);
mWebview.requestFocus();
if (currenturl.contains("http://example.com/page")){
moveTaskToBack(true);
}else{
mWebview.goBack();
}
if (mWebview.canGoBack()) {
if (!DetectConnection.checkInternetConnection(Context)) {
Toast.makeText(Context, "No Internet Connection!", Toast.LENGTH_SHORT).show();
}
}
}
public static void loadUrl(String key) {
if (getIntentValue != null) {
mWebview.loadUrl("http://example.com/page");
getIntentValue = null;
} else {
mWebview.loadUrl("http://example.com/page");
}
}
public static void reLoad() {
mWebview.reload();
}
@Override
public void onConfigurationChanged(Configuration newConfig){
super.onConfigurationChanged(newConfig);
}
}
更改此行:
mWebview.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
收件人:
mWebview.getSettings().setCacheMode( WebSettings.LOAD_CACHE_ELSE_NETWORK)
mWebview.getSettings().setCacheMode( WebSettings.LOAD_CACHE_ELSE_NETWORK)
这将告诉 WebView 从缓存中加载页面,但如果它需要缓存中没有的任何内容,它会查找网络,当您没有连接时,它只会给您 "page could not be loaded error." 这是因为遗憾的是并非所有内容都存储在缓存中,即使使用此设置,您也会注意到浏览器正在使用网络。
使用WebSettings.LOAD_CACHE_ONLY
mWebview.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ONLY);
只需包含 enableHTML5AppCache()
private void enableHTML5AppCache() {
mWebview.getSettings().setDomStorageEnabled(true);
mWebview.getSettings().setAppCachePath("/data/data/" + getPackageName() + "/cache");
mWebview.getSettings().setAppCacheEnabled(true);
mWebview.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
}
2021 更新内容已更改:已弃用 应用程序缓存 API 已弃用,一旦在 Chromium 中删除支持,此方法将成为所有 Android 版本的空操作。考虑改用 Service Worker。有关详细信息,请参阅 https://web.dev/appcache-removal/。 改为阅读服务人员 :) 快乐编码:P