阻止WebView显示“网页不可用”

时间:2011-07-01 18:58:51

标签: java android

我有一个广泛使用WebView的应用程序。当此应用程序的用户没有Internet连接时,会出现“网页不可用”和其他各种文本的页面。有没有办法在我的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();
 }
}

我发现WebView->clearView实际上并没有清除视图。

16 个答案:

答案 0 :(得分:90)

首先在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");

    }
});

答案 1 :(得分:28)

我找到的最佳解决方案是在OnReceivedError事件中加载一个空页面,如下所示:

@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
    super.onReceivedError(view, errorCode, description, failingUrl);

    view.loadUrl("about:blank");
}

答案 2 :(得分:9)

最后,我解决了这个问题。 (它一直工作到现在..)

我的解决方案是这样的......

  1. 准备布局以显示错误发生的时间而不是网页(一个脏的'页面未找到的消息')布局有一个按钮," RELOAD"一些指导信息。

  2. 如果发生错误,请记住使用布尔值并显示我们准备的布局。

  3. 如果用户点击" RELOAD"按钮,将mbErrorOccured设置为false。并将mbReloadPressed设置为true。
  4. 如果mbErrorOccured为false且mbReloadPressed为true,则表示webview加载页面成功。 '如果再次发生错误,mbErrorOccured将在onReceivedError(...)上设置为true
  5. 这是我的完整资料来源。看看这个。

    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);
                }
            };
        }
    }
    

    另外:这是布局......

    <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>
    

答案 3 :(得分:6)

查看Android WebView onReceivedError()处的讨论。这很长,但共识似乎是a)你无法阻止“网页不可用”页面出现,但b)你总是在得到onReceivedError之后加载一个空页

答案 4 :(得分:5)

当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);
            }
        });

答案 5 :(得分:2)

您可以使用GET请求获取页面内容,然后使用Webview显示该数据,这样您就不会使用多个服务器调用。或者,您可以使用Javascript检查DOM对象的有效性。

答案 6 :(得分:2)

也许我误解了这个问题,但听起来你说你得到了错误收到回调,而你只是在问什么是不显示错误的最佳方法?为什么不从屏幕上删除网页视图和/或在其上显示另一个视图?

答案 7 :(得分:1)

我想如果你坚持这样做,你可以在调用loadURL函数之前检查资源是否存在。 只需简单地覆盖函数并在调用super()

之前进行检查

备注(可能是偏离主题的):在http中,有一个名为HEAD的方法,描述如下:

  

HEAD方法与GET相同,只是服务器不能在响应中返回消息正文

这种方法可能很方便。 无论如何你实现它...检查这段代码:

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
}
}

你可以尝试使用

进行检查
if(url.openConnection().getContentLength() > 0)

答案 8 :(得分:1)

在这里,我找到了最简单的解决方案。看看这个..

   @Override
        public void onReceivedError(WebView view, int errorCode,
                                    String description, String failingUrl) {
//                view.loadUrl("about:blank");
            mWebView.stopLoading();
            if (!mUtils.isInterentConnection()) {
                Toast.makeText(ReportingActivity.this, "Please Check Internet Connection!", Toast.LENGTH_SHORT).show();
            }
            super.onReceivedError(view, errorCode, description, failingUrl);
        }

这是isInterentConnection()方法......

public boolean isInterentConnection() {
    ConnectivityManager manager = (ConnectivityManager) mContext
            .getSystemService(Context.CONNECTIVITY_SERVICE);
    if (manager != null) {
        NetworkInfo info[] = manager.getAllNetworkInfo();
        if (info != null) {
            for (int i = 0; i < info.length; i++) {
                if (info[i].getState() == NetworkInfo.State.CONNECTED) {
                    return true;
                }
            }
        }
    }
    return false;
}

答案 9 :(得分:0)

我只是将网页更改为您用于错误处理的任何内容:

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/");

这可以在http://developer.android.com/reference/android/webkit/WebView.html

上找到

答案 10 :(得分:0)

我一直在努力解决今天放弃那些烦躁的Google错误页面的问题。可以使用上面的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();
       }
    }
});

如果你将shouldOverrideUrlLoading()作为另一个webclient放入。至少,这对我的2.3.6设备有用。我们稍后会看到它的工作原理。那我现在只会压抑我,我敢肯定。 goBack位是我的。你可能不想要它。

答案 11 :(得分:0)

试试这个

 @SuppressWarnings("deprecation")
 @Override
 public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
      // Your handling
 }

 @Override
 public void onReceivedError(WebView view, WebResourceRequest req, WebResourceError rerr) {
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
          onReceivedError(view, rerr.getErrorCode(), rerr.getDescription().toString(), req.getUrl().toString());
      }
 }

答案 12 :(得分:0)

我们可以将webView的可见性设置为0(view.INVISIBLE)并显示一些消息。 此代码适用于在lolipop上运行的应用程序。

@SuppressWarnings("deprecation")
    @Override
    public void onReceivedError(WebView webView, int errorCode, String description, String failingUrl) {
        // hide webView content and show custom msg
        webView.setVisibility(View.INVISIBLE);
        Toast.makeText(NrumWebViewActivity.this,getString(R.string.server_not_responding), Toast.LENGTH_SHORT).show();
    }

    @TargetApi(android.os.Build.VERSION_CODES.M)
    @Override
    public void onReceivedError(WebView view, WebResourceRequest req, WebResourceError rerr) {
        // Redirect to deprecated method, so you can use it in all SDK versions
        onReceivedError(view, rerr.getErrorCode(), rerr.getDescription().toString(), req.getUrl().toString());
    }

答案 13 :(得分:0)

我不得不面对这个问题,并试图从不同的角度来解决它。最后,我通过使用单个标志来检查是否发生了错误,从而找到了解决方案。

... extends WebViewClient {

    boolean error;

    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {

        showLoading(true);
        super.onPageStarted(view, url, favicon);

        error  = false; // IMPORTANT
    }

    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);

        if(!error) {
            Observable.timer(100, TimeUnit.MICROSECONDS, AndroidSchedulers.mainThread())
                    .subscribe((data) -> view.setVisibility(View.VISIBLE) );
        }

        showLoading(false);
    }


    @Override
    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {

        view.stopLoading();

        view.setVisibility(View.INVISIBLE) 
        error  = true;  

        // Handle the error
    }


     @Override
    @TargetApi(android.os.Build.VERSION_CODES.M)
    public void onReceivedError(WebView view,
                                WebResourceRequest request,
                                WebResourceError error) {

        this.onReceivedError(view, error.getErrorCode(),
                error.getDescription().toString(),
                request.getUrl().toString());
    }
 }

这样我每次出现错误时都会隐藏页面,并在页面再次正确加载时显示。

还增加了一点延迟。

我避免了加载空白页面的解决方案,因为它不允许您稍后执行webview.reload(),因为它在导航历史记录中添加了新页面。

答案 14 :(得分:-1)

尝试此shouldOverrideUrlLoading,然后重定向到另一个网址,检查是否应该加载基于该网页的互联网连接。

答案 15 :(得分:-1)

覆盖您的WebViewClient方法

@Override
public void onReceivedError(WebView view, int errorCode,
    String description, String failingUrl) {
    view.clearView();
}

view.loadUrl('about:blank')有副作用,因为它会取消原始网址加载。