Java 防止 WebView 显示“网页不可用”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6552160/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Prevent WebView from displaying "web page not available"
提问by JoJo
I have an app that makes extensive use of a WebView. When the user of this app does not have Internet connection, a page saying "web page not available" and various other text appears. Is there a way to not show this generic text in my WebView? I would like to provide my own error handling.
我有一个广泛使用 WebView 的应用程序。当这个应用程序的用户没有互联网连接时,会出现一个页面,上面写着“网页不可用”和其他各种文字。有没有办法不在我的 WebView 中显示这个通用文本?我想提供我自己的错误处理。
private final Activity activity = this;
private class MyWebViewClient extends WebViewClient
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
// I need to do something like this:
activity.webView.wipeOutThePage();
activity.myCustomErrorHandling();
Toast.makeText(activity, description, Toast.LENGTH_LONG).show();
}
}
I found out WebView->clearViewdoesn't actually clear the view.
我发现WebView->clearView实际上并没有清除视图。
采纳答案by SnowboardBruin
First create your own error page in HTML and put it in your assets folder, Let's call it myerrorpage.html Then with onReceivedError:
首先在 HTML 中创建您自己的错误页面并将其放在您的资产文件夹中,我们将其命名为 myerrorpage.html 然后使用 onReceivedError:
mWebView.setWebViewClient(new WebViewClient() {
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
mWebView.loadUrl("file:///android_asset/myerrorpage.html");
}
});
回答by Torid
Check out the discussion at Android WebView onReceivedError(). It's quite long, but the consensus seems to be that a) you can't stop the "web page not available" page appearing, but b) you could always load an empty page after you get an onReceivedError
查看Android WebView onReceivedError() 上的讨论。它很长,但共识似乎是 a) 您无法阻止“网页不可用”页面的出现,但是 b) 在收到 onReceivedError 后,您始终可以加载一个空页面
回答by Sherif elKhatib
I suppose that if you insist on doing this, you could just check if the resource is there before calling the loadURL function. Just simply override the functions and do the check before calling the super()
我想如果你坚持这样做,你可以在调用 loadURL 函数之前检查资源是否存在。只需简单地覆盖函数并在调用 super() 之前进行检查
REMARK (maybe off-topic): In http, there is a method called HEAD which is described as follow:
备注(可能偏离主题):在 http 中,有一种称为 HEAD 的方法,其描述如下:
The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response
HEAD 方法与 GET 相同,除了服务器不得在响应中返回消息正文
This method might be handy. Anyway how ever you implement it ... check this code:
这种方法可能很方便。无论如何你如何实现它......检查这个代码:
import java.util.Map;
import android.content.Context;
import android.webkit.WebView;
public class WebViewPreLoad extends WebView{
public WebViewPreLoad(Context context) {
super(context);
}
public void loadUrl(String str){
if(//Check if exists)
super.loadUrl(str);
else
//handle error
}
public void loadUrl(String url, Map<String,String> extraHeaders){
if(//Check if exists)
super.loadUrl(url, extraHeaders);
else
//handle error
}
}
You could try this check using
您可以尝试使用此检查
if(url.openConnection().getContentLength() > 0)
回答by Ravi Vyas
You could use a GET
request to get the page content and then display that data using the Webview
, this way you are not using multiple server calls. Alternative you can use Javascript
to check the DOM
object for validity.
您可以使用GET
请求来获取页面内容,然后使用 显示该数据Webview
,这样您就不会使用多个服务器调用。您可以使用替代方法Javascript
来检查DOM
对象的有效性。
回答by Bipin Vayalu
try this shouldOverrideUrlLoading, before redirect to another url check for internet conncetion based on that page should be loaded or not.
试试这个shouldOverrideUrlLoading,在重定向到另一个 url 检查基于该页面的互联网连接之前,应该加载或不加载。
回答by Matthew Horst
Perhaps I misunderstand the question, but it sounds like you're saying you get the error received callback, and you just are asking what is the best way to not show the error? Why don't you just either remove the web view from the screen and/or show another view on top of it?
也许我误解了这个问题,但听起来您是说您收到错误接收回调,而您只是在问不显示错误的最佳方法是什么?为什么不直接从屏幕上删除 web 视图和/或在它上面显示另一个视图?
回答by Ephraim
I would just change the webpage to whatever you are using for error handling:
我只是将网页更改为您用于错误处理的任何内容:
getWindow().requestFeature(Window.FEATURE_PROGRESS);
webview.getSettings().setJavaScriptEnabled(true);
final Activity activity = this;
webview.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress) {
// Activities and WebViews measure progress with different scales.
// The progress meter will automatically disappear when we reach 100%
activity.setProgress(progress * 1000);
}
});
webview.setWebViewClient(new WebViewClient() {
public void onReceivedError(WebView view, int errorCode, String description, String
failingUrl) {
Toast.makeText(activity, "Oh no! " + description, Toast.LENGTH_SHORT).show();
}
});
webview.loadUrl("http://slashdot.org/");
this can all be found on http://developer.android.com/reference/android/webkit/WebView.html
这都可以在http://developer.android.com/reference/android/webkit/WebView.html上找到
回答by R Earle Harris
I've been working on this problem of ditching those irritable Google error pages today. It is possible with the Android example code seen above and in plenty of other forums (ask how I know):
今天我一直在解决这个问题,即抛弃那些烦躁的谷歌错误页面。上面和许多其他论坛中看到的 Android 示例代码是可能的(问我是怎么知道的):
wv.setWebViewClient(new WebViewClient() {
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
if (view.canGoBack()) {
view.goBack();
}
Toast.makeText(getBaseContext(), description, Toast.LENGTH_LONG).show();
}
}
});
IF you put it in shouldOverrideUrlLoading() as one more webclient. At least, this is working for me on my 2.3.6 device. We'll see where else it works later. That would only depress me now, I'm sure. The goBack bit is mine. You may not want it.
如果你把它放在 shouldOverrideUrlLoading() 中作为另一个网络客户端。至少,这在我的 2.3.6 设备上对我有用。稍后我们将看到它的其他地方。我敢肯定,那现在只会让我沮丧。goBack 位是我的。你可能不想要它。
回答by Jeevan
When webview is embedded in some custom view such that user almost believes that he is seeing a native view and not a webview, in such scenario showing the "page could not be loaded" error is preposterous. What I usually do in such situation is I load blank page and show a toast message as below
当 webview 嵌入到一些自定义视图中时,用户几乎相信他看到的是原生视图而不是 webview,在这种情况下,显示“页面无法加载”错误是荒谬的。在这种情况下,我通常做的是加载空白页面并显示如下吐司消息
webView.setWebViewClient(new WebViewClient() {
@Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
Log.e(TAG," Error occured while loading the web page at Url"+ failingUrl+"." +description);
view.loadUrl("about:blank");
Toast.makeText(App.getContext(), "Error occured, please check newtwork connectivity", Toast.LENGTH_SHORT).show();
super.onReceivedError(view, errorCode, description, failingUrl);
}
});
回答by cmcromance
Finally, I solved this. (It works till now..)
最后,我解决了这个问题。(它工作到现在..)
My solution is like this...
我的解决方法是这样的...
Prepare the layout to show when an error occurred instead of Web Page (a dirty 'page not found message') The layout has one button, "RELOAD" with some guide messages.
If an error occurred, Remember using boolean and show the layout we prepare.
- If user click "RELOAD" button, set mbErrorOccured to false. And Set mbReloadPressed to true.
- if mbErrorOccured is false and mbReloadPressed is true, it means webview loaded page successfully. 'Cause if error occurred again, mbErrorOccured will be set true on onReceivedError(...)
准备布局以在发生错误时显示而不是网页(脏的“页面未找到消息”) 布局有一个按钮,“重新加载”和一些指导消息。
如果发生错误,请记住使用布尔值并显示我们准备的布局。
- 如果用户单击“重新加载”按钮,请将 mbErrorOccured 设置为 false。并将 mbReloadPressed 设置为 true。
- 如果 mbErrorOccured 为 false 且 mbReloadPressed 为 true,则表示 webview 加载页面成功。因为如果错误再次发生,mbErrorOccured 将在 onReceivedError(...)
Here is my full source. Check this out.
这是我的完整来源。看一下这个。
public class MyWebViewActivity extends ActionBarActivity implements OnClickListener {
private final String TAG = MyWebViewActivity.class.getSimpleName();
private WebView mWebView = null;
private final String URL = "http://www.google.com";
private LinearLayout mlLayoutRequestError = null;
private Handler mhErrorLayoutHide = null;
private boolean mbErrorOccured = false;
private boolean mbReloadPressed = false;
@SuppressLint("SetJavaScriptEnabled")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_webview);
((Button) findViewById(R.id.btnRetry)).setOnClickListener(this);
mlLayoutRequestError = (LinearLayout) findViewById(R.id.lLayoutRequestError);
mhErrorLayoutHide = getErrorLayoutHideHandler();
mWebView = (WebView) findViewById(R.id.webviewMain);
mWebView.setWebViewClient(new MyWebViewClient());
WebSettings settings = mWebView.getSettings();
settings.setJavaScriptEnabled(true);
mWebView.setWebChromeClient(getChromeClient());
mWebView.loadUrl(URL);
}
@Override
public boolean onSupportNavigateUp() {
return super.onSupportNavigateUp();
}
@Override
public void onClick(View v) {
int id = v.getId();
if (id == R.id.btnRetry) {
if (!mbErrorOccured) {
return;
}
mbReloadPressed = true;
mWebView.reload();
mbErrorOccured = false;
}
}
@Override
public void onBackPressed() {
if (mWebView.canGoBack()) {
mWebView.goBack();
return;
}
else {
finish();
}
super.onBackPressed();
}
class MyWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return super.shouldOverrideUrlLoading(view, url);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
@Override
public void onLoadResource(WebView view, String url) {
super.onLoadResource(view, url);
}
@Override
public void onPageFinished(WebView view, String url) {
if (mbErrorOccured == false && mbReloadPressed) {
hideErrorLayout();
mbReloadPressed = false;
}
super.onPageFinished(view, url);
}
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
mbErrorOccured = true;
showErrorLayout();
super.onReceivedError(view, errorCode, description, failingUrl);
}
}
private WebChromeClient getChromeClient() {
final ProgressDialog progressDialog = new ProgressDialog(MyWebViewActivity.this);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setCancelable(false);
return new WebChromeClient() {
@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
}
};
}
private void showErrorLayout() {
mlLayoutRequestError.setVisibility(View.VISIBLE);
}
private void hideErrorLayout() {
mhErrorLayoutHide.sendEmptyMessageDelayed(10000, 200);
}
private Handler getErrorLayoutHideHandler() {
return new Handler() {
@Override
public void handleMessage(Message msg) {
mlLayoutRequestError.setVisibility(View.GONE);
super.handleMessage(msg);
}
};
}
}
Addition:Here is layout....
补充:这里是布局....
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rLayoutWithWebView"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<WebView
android:id="@+id/webviewMain"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@+id/lLayoutRequestError"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:background="@color/white"
android:gravity="center"
android:orientation="vertical"
android:visibility="gone" >
<Button
android:id="@+id/btnRetry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:minWidth="120dp"
android:text="RELOAD"
android:textSize="20dp"
android:textStyle="bold" />
</LinearLayout>