【问题标题】:Webview failure when internet is off网络关闭时 Webview 失败
【发布时间】:2020-01-28 05:44:42
【问题描述】:

我有一个基于 Web 的应用程序,该应用程序启动时会加载 URL。 我正在尝试处理一个问题

加载资源时关闭WiFi互联网(资源以异步格式加载)。

我正在使用 onReceivedError(WebView view, int errorCode, String description, String failingUrl)WebViewClient 来检查 url 失败。我也试过onReceivedError(WebView view, WebResourceRequest request, WebResourceError error)

但在加载资源期间关闭 WiFi 互联网时,我没有收到任何失败回调。

【问题讨论】:

  • 更好的方法来检测网络连接,使用广播接收器和你的应用程序的上下文,它会在没有网络可用的地方通知你。像 YouTube 做的事情
  • WiFi 网络关闭和打开时会通知吗?因为我尝试了ConnectivityManager.NetworkCallback,因为在关闭互联网时会调用onLost(),但随后会在1-2 秒内调用onAvailable()。我也尝试过使用WifiManager.NETWORK_STATE_CHANGED_ACTIONConnectivityManager.CONNECTIVITY_ACTION 的广播接收器,在关闭和打开WiFi 互联网时仍然无法正常通话。
  • @Shahal 检查我的答案,你无法在没有互联网的情况下加载你的 webview,所以你可以像这样检查互联网连接。
  • 嘿@Shahal 问题解决了吗?

标签: android webview


【解决方案1】:

这可能不是最有效的方法,但在这种情况下它符合我的目的。我正在使用 ping 服务(目前为 8.8.8.8)、JS 回调和 ConnectivityManager NetworkCallback 来实现这一点。

我们正在使用 JS 来检查是否所有资源都加载了,它会给出错误,'no' 或'yes'。 Error & 'no' 表示 html 没有完全加载。

ConnectivityManager NetworkCallback 用于在用户处于设置屏幕时了解同一 WiFi 的互联网何时恢复,因为如果互联网恢复,我们需要将用户重定向回应用程序。在这种情况下会调用onLinkPropertiesChanged,我们会使用 Ping 服务检查互联网是否可用。

注册 NetworkCallback

connectivityManager =
                    (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

            NetworkRequest.Builder builder = new NetworkRequest.Builder();
            builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
            builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
            builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
            builder.addTransportType(NetworkCapabilities.TRANSPORT_VPN);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                connectivityManager.registerNetworkCallback(builder.build(), networkCallback);
            }

networkCallback

ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {

        @RequiresApi(api = Build.VERSION_CODES.M)
        @Override
        public void onAvailable(Network network) {
            // network available
            networkCheck(network);
        }

        @Override
        public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
            super.onLinkPropertiesChanged(network, linkProperties);
            networkCheck(network);
        }

        @Override
        public void onLost(Network network) {
            // network unavailable
            onDisconnected();
        }
    };

networkCheck 检查互联网是否可用。也许这一步可以忽略,虽然写我 NET_CAPABILITY_VALIDATED 会检查互联网。但在某些情况下它会失败。

private void networkCheck(Network network) {
        ConnectivityManager cm = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = cm.getNetworkInfo(network);
        boolean isConnected = (info != null && info.isConnectedOrConnecting());

        if (!isConnected) {
            onDisconnected();
            return;
        }
        NetworkCapabilities nc = cm.getNetworkCapabilities(network);
        if (nc == null || !nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) || !checkPingService()) {
            onDisconnected();
            return;
        }
        onConnected();
    }

checkPingService 检查互联网是否可用

private boolean checkPingService() {
        try {
            Process p1 = java.lang.Runtime.getRuntime().exec("ping -c 1 8.8.8.8");
            int returnVal = p1.waitFor();
            return (returnVal == 0);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

这在我们迄今为止测试的所有场景中都有效。因此,如有任何疑问,请随时发表评论。

【讨论】:

    【解决方案2】:

    试试这个:

    您可以设置网络检查的条件,然后根据需要构建逻辑

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

    希望这会奏效!

    【讨论】:

    • networkInfoWifi.isConnected() 只会告诉 WiFi 是否已连接而不是互联网可用性。当资源以异步格式加载时,onLoadResource() 也不能正常工作(这就是我提到它的原因)。
    【解决方案3】:

    为网络更改创建接收器,您可以检测网络是否关闭,如下所示,您可以将本地广播发送到您的活动 -

    public class NetworkChangeReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(final Context context, final Intent intent) {
    
        ConnectivityManager connectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE );
          NetworkInfo activeNetInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
          boolean isConnected = activeNetInfo != null && activeNetInfo.isConnectedOrConnecting();   
          if (isConnected)       
              Log.i("NET", "Connected" + isConnected);   
          else 
              Log.i("NET", "Not Connected" + isConnected);
        }
    }
    

    menifest.xml 文件中添加以下行

     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.INTERNET" />
     <receiver
            android:name="NetworkChangeReceiver"
            android:label="NetworkChangeReceiver" >
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
                <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
            </intent-filter>
        </receiver>
    

    【讨论】:

    • 试试这个场景,连接到 WiFi(最好是热点)打开和关闭互联网连接。当您关闭互联网时,您会收到“未连接 - 更新变量”,并在 1-2 秒后调用“已连接 - 更新变量”。
    • yeh 在网络连接上向您的活动发送广播并显示网络视图以及未连接时的错误对话框。
    • 当互联网关闭时,“未连接 - 更新变量”和“已连接 - 更新变量”都被调用。
    猜你喜欢
    • 2022-12-11
    • 1970-01-01
    • 1970-01-01
    • 2022-08-02
    • 1970-01-01
    • 2013-12-08
    • 2011-03-27
    • 2016-01-03
    • 1970-01-01
    相关资源
    最近更新 更多