解决webview出现错误net::err_unknown_url_scheme 的问题

产生原因webview重定向,其定义没有明确的官方解释,发生的原因是请求的链接(url)在加载完成后发生了变化 (eg.比如你的代码中设置webview加载的是网页A,打开后发现加载的是网页B); 关于 net::ERR_UNKNOWN_URL_SCHEME (如下图所示),因为webview只能识别http和https协议,遇到图中这种"wvhzpj://"开头的自定义协议时就无法识别,便会提示ERR_UNKNOWN_URL_SCHEME这样的错误。

解决方法:重写WebviewClient类中的 shouldOverriderUrlLoading 方法( 选取方法参数为(Webview view , String url )的那种,如下图),该方法可以对webview将要加载的url 进行处理,我们在此处对 会发生重定向的 url 和 不以 "http://"、"https//" 开头的自定义协议 进行拦截处理。该方法的返回值为boolean 类型,表示是否阻止webview继续加载url,默认值为 false。当返回false,表示不进行阻止,webview认为当前的url需要进行处理,会继续加载;返回 true,表示阻止webview继续加载url,等待我们进行处理。

     那么如何判断 webview 将要加载的url会不会发生重定向呢?WebView中有个静态类 HitTestResult,这个类中有一些被 final 修饰的 int 变量,这些变量表示webview加载的url所属的网页类型。还有两个get方法 getType() 和 getExtra() , getType() 表示获取加载url的网页类型; getExtra() 表示根据url打开的网页类型,返回一个extra信息,如果打开类型为 UNKNOWN_TYPE(打开的内容未知) ,此时 url 就会通过requestFocusNodeHref(Message)方法异步重定向,则extra就没有返回值,为null。经过上面分析,我们可以对getType() 和 getExtra() 获取到的返回值进行判断,当 getType()==0 (打开内容未知) 或者 getExtra() 为 null 时,就认为webview加载的url会发生重定向,我们此时就在shouldOverriderUrlLoading方法中对其进行处理。

HitTestResult 类中变量值所对应打开的网页类型

接下来看看如何判定加载的url是非 http/https 的自定义协议。很简单,对shouldOverriderUrlLoading方法中的参数 String url进行判断,url.startsWith("http://")||url.startsWith("https://") 即表示加载的url是 http/https 协议,不对其进行拦截处理,反之则进行拦截处理。

@Override
public boolean shouldOverrideUrlLoading(final WebView view, final String url) {

    WebView.HitTestResult hit = view.getHitTestResult();
    //hit.getExtra()为null或者hit.getType() == 0都表示即将加载的URL会发生重定向,需要做拦截处理
    if (TextUtils.isEmpty(hit.getExtra()) || hit.getType() == 0) {
        //通过判断开头协议就可解决大部分重定向问题了,有另外的需求可以在此判断下操作
        Log.e("重定向", "重定向: " + hit.getType() + " && EXTRA()" + hit.getExtra() + "------");
        Log.e("重定向", "GetURL: " + view.getUrl() + "\n" +"getOriginalUrl()"+ view.getOriginalUrl());
        Log.d("重定向", "URL: " + url);
    }

    if (url.startsWith("http://") || url.startsWith("https://")) { //加载的url是http/https协议地址
        view.loadUrl(url);
        return false; //返回false表示此url默认由系统处理,url未加载完成,会继续往下走

    } else { //加载的url是自定义协议地址
        try {
            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
            context.startActivity(intent);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章