Android - 如何在没有网络连接时防止WebView加载

29
我有一个安卓应用程序,其中包含一个Webview。当没有网络连接时,Webview将显示页面不可用。我希望尽可能使其看起来像应用程序,因此不想显示此页面。我在网上找到了一些有用的信息,教你如何隐藏或加载其他东西来覆盖它,但我真正想要的是停留在当前页面,有一个小的弹出对话框提示无连接。基本上,当用户在Webview内点击任何内容时,首先检查连接。如果没有连接,请停留在原地并弹出一个对话框。

感谢您的帮助!!

编辑:

就像我说的,我已经知道如何从网上示例中检查互联网连接。我的问题是我不知道如何停止加载下一页。明确一点,当用户尝试转到下一页时,请检查互联网连接。如果没有连接,则页面将停留在原处,不会转到下一页。我希望用户能够看到他们最后加载的页面,并在网页内容仍然存在的同时得到通知。谢谢!

5个回答

48

我在我的项目中使用了以下内容:

DetectConnection.Java

import android.content.Context;
import android.net.ConnectivityManager;


public class DetectConnection {             
  public static boolean checkInternetConnection(Context context) {   

    ConnectivityManager con_manager = (ConnectivityManager) 
      context.getSystemService(Context.CONNECTIVITY_SERVICE);

    return (con_manager.getActiveNetworkInfo() != null
        && con_manager.getActiveNetworkInfo().isAvailable()
        && con_manager.getActiveNetworkInfo().isConnected());
  }
}

主要代码:

if (!DetectConnection.checkInternetConnection(this)) {
  Toast.makeText(getApplicationContext(), "No Internet!", Toast.LENGTH_SHORT).show();
} else {      
  wv = (WebView) findViewById(R.id.donate_webView1);
  c = new CustomWebViewClient();
  wv.setWebViewClient(c);
  wv.clearCache(true);
  wv.clearHistory();
  wv.getSettings().setJavaScriptEnabled(true);
  wv.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
  wv.getSettings().setBuiltInZoomControls(true);
  wv.loadUrl("http://www.google.com");
}


// Function to load all URLs in same webview
private class CustomWebViewClient extends WebViewClient {
  public boolean shouldOverrideUrlLoading(WebView view, String url) {
    if (!DetectConnection.checkInternetConnection(this)) {
      Toast.makeText(getApplicationContext(), "No Internet!", Toast.LENGTH_SHORT).show();
    } else {
      view.loadUrl(url);
    }     
    return true;
  }
}

更新清单:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

6
谢谢!这对我有用! 您需要网络访问权限,请在AndroidManifest中添加以下内容:<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> - fermin
另外,还有isConnectedOrConnecting,它表示网络连接是否存在或正在建立过程中。 - Ivan Black
关于POST请求怎么办?如果是从WebView发起的POST请求,那么“shouldOverrideUrlLoading”方法将不会被调用。参考:链接 - Prakhar Asthana

8
你可以使用我的CustomWebViewClient类来实现以下功能 -

  • 在网页加载时显示加载对话框
  • 在加载页面失败时显示错误信息
  • 如果没有网络连接,它会给用户提供一个选项去设置并启用移动数据。
  • 在其他类型的错误情况下,它允许用户重新载入网页。

你只需要将它附加到你的webView上即可:

webView.setWebViewClient(new CustomWebViewClient());

CustomWebViewClient

    /**
     * WebViewClient subclass loads all hyperlinks in the existing WebView
     */
    public class CustomWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            // When user clicks a hyperlink, load in the existing WebView
            view.loadUrl(url);
            return true;
        }

        Dialog loadingDialog = new Dialog(WebViewActivity.this);

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            webViewPreviousState = PAGE_STARTED;

            if (loadingDialog == null || !loadingDialog.isShowing())
                loadingDialog = ProgressDialog.show(WebViewActivity.this, "",
                        "Loading Please Wait", true, true,
                        new DialogInterface.OnCancelListener() {

                            @Override
                            public void onCancel(DialogInterface dialog) {
                                // do something
                            }
                        });

            loadingDialog.setCancelable(false);
        }


        @RequiresApi(api = Build.VERSION_CODES.M)
        @Override
        public void onReceivedError(WebView view, WebResourceRequest request,
                                    WebResourceError error) {


            if (isConnected()) {
                final Snackbar snackBar = Snackbar.make(rootView, "onReceivedError : " + error.getDescription(), Snackbar.LENGTH_INDEFINITE);
                snackBar.setAction("Reload", new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        webView.loadUrl("javascript:window.location.reload( true )");
                    }
                });
                snackBar.show();
            } else {
                final Snackbar snackBar = Snackbar.make(rootView, "No Internet Connection ", Snackbar.LENGTH_INDEFINITE);
                snackBar.setAction("Enable Data", new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        startActivityForResult(new Intent(Settings.ACTION_WIRELESS_SETTINGS), 0);
                        webView.loadUrl("javascript:window.location.reload( true )");
                        snackBar.dismiss();
                    }
                });
                snackBar.show();
            }

            super.onReceivedError(view, request, error);

        }

        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        @Override
        public void onReceivedHttpError(WebView view,
                                        WebResourceRequest request, WebResourceResponse errorResponse) {

            if (isConnected()) {
                final Snackbar snackBar = Snackbar.make(rootView, "HttpError : " + errorResponse.getReasonPhrase(), Snackbar.LENGTH_INDEFINITE);

                snackBar.setAction("Reload", new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        webView.loadUrl("javascript:window.location.reload( true )");
                    }
                });
                snackBar.show();
            } else {
                final Snackbar snackBar = Snackbar.make(rootView, "No Internet Connection ", Snackbar.LENGTH_INDEFINITE);
                snackBar.setAction("Enable Data", new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        startActivityForResult(new Intent(Settings.ACTION_WIRELESS_SETTINGS), 0);
                        webView.loadUrl("javascript:window.location.reload( true )");
                        snackBar.dismiss();
                    }
                });
                snackBar.show();
            }
            super.onReceivedHttpError(view, request, errorResponse);
        }

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

            if (webViewPreviousState == PAGE_STARTED) {

                if (null != loadingDialog) {
                    loadingDialog.dismiss();
                    loadingDialog = null;
                }
            }
        }
    }

检查连接方式
    /**
     * Check if there is any connectivity
     *
     * @return is Device Connected
     */
    public boolean isConnected() {

        ConnectivityManager cm = (ConnectivityManager)
                this.getSystemService(Context.CONNECTIVITY_SERVICE);

        if (null != cm) {
            NetworkInfo info = cm.getActiveNetworkInfo();
            return (info != null && info.isConnected());
        }

        return false;

    }

4
感谢您的解决方案,但是有很多定义缺失。如果我将您的代码放入我的项目中,什么也不起作用,许多变量也未知。 - Yvonne Marggraf

2
        webView.setWebViewClient(new WebViewClient() {
        int errorCode = 0;
        @SuppressWarnings("deprecation")
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            return handleUri(view, url);
        }

        @TargetApi(Build.VERSION_CODES.N)
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
            return handleUri(view, request.getUrl().toString());
        }

        private boolean handleUri(WebView view, final String url) {
            view.loadUrl(url);
            return true;
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            if(errorCode == 0) {
               //CHECK IS PAGE I NEED AND DO STUFF
            } else {
               errorCode = 0;
               //delay and try again
            }
        }

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

        @TargetApi(Build.VERSION_CODES.N)
        @Override
        public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
            handleError(error.getErrorCode());
        }

        private void handleError(int errorCode) {
            this.errorCode = errorCode;
        }
    });

1
您可以通过以下代码检查设备是否连接到互联网,无论是通过数据连接还是WiFi连接。
ConnectivityManager manager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo i = manager.getActiveNetworkInfo();
boolean hasConnect = (i!= null && i.isConnected() && i.isAvailable());

if(hasConnect)
                    {
                       // show the webview
                    }
else
 {
    // do what ever you need when when no internet connection
 }

用户进入Webview后,如果连接中断,您可以从以下代码中捕获该事件。
 webView.setWebViewClient(new Callback());

 public class Callback extends WebViewClient{
    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl){
        Toast.makeText(getApplicationContext(), "Failed loading app!, No Internet Connection found.", Toast.LENGTH_SHORT).show();


    }
}  

以下是需要授予的权限: <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

0

您需要重写WebViewClientshouldOverrideUrlLoading方法来捕获URL点击。

要检查Wifi状态,您需要使用ConnectivityManager

请尝试以下操作:

WebView mWebView;
NetworkInfo networkInfoWifi = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE).getNetworkInfo(ConnectivityManager.TYPE_WIFI);

mWebView.setWebViewClient(mWebClient);

WebViewClient mWebClient = new WebViewClient(){

    @Override
    public boolean shouldOverrideUrlLoading(WebView  view, String  url){
        return true;
    }

    @Override
    public void onLoadResource(WebView  view, String  url){
        if (networkInfoWifi.isConnected()) {
            //Take action
        }
    }

}

我建议将您的问题分解为两个较小的步骤——单击拦截和连接状态检查,并进行搜索。这会产生大量结果,我能够利用这两个现有答案来编写代码:

拦截Webview点击

检查Wifi连接


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接