Webview redirection and net::ERR_UNKNOWN_URL_SCHEME analysis and solution

cause

       First, let’s talk about webview redirection . There is no clear official explanation for its definition. The reason is that the requested link (url) changes after the loading is completed (eg. For example, in your code, webview is set to load webpage A, open Later, it was found that the loaded web page B); About net::ERR_UNKNOWN_URL_SCHEME (as shown in the figure below), because webview can only recognize http and https protocols, when encountering a custom protocol starting with "wvhzpj://" in the figure, it will If it cannot be recognized, an error like ERR_UNKNOWN_URL_SCHEME will be prompted.

 
How to solve

       You need to override the shouldOverriderUrlLoading method in the WebviewClient class (select the one whose method parameters are (Webview view, String url), as shown below). This method can process the url that the webview will load. Here we will redirect URLs and custom protocols that do not start with "http://" or "https//" are intercepted . The return value of this method is of boolean type, indicating whether to prevent the webview from continuing to load the URL. The default value is false. When false is returned, it means that no blocking will be performed. Webview believes that the current URL needs to be processed and will continue to load; returning true means that webview is prevented from continuing to load the URL and waits for us to process it .

       So how to determine whether the URL to be loaded by the webview will be redirected? There is a static class HitTestResult in WebView . There are some int variables modified by final in this class. These variables represent the type of web page to which the URL loaded by webview belongs. There are also two get methods , getType() and getExtra() . getType() means to get the type of web page that loads the url; getExtra() means to return an extra information according to the type of web page opened by the url. If the opening type is UNKNOWN_TYPE (open content unknown), at this time the url will be redirected asynchronously through the requestFocusNodeHref(Message) method, then extra will have no return value and will be null . After the above analysis, we can judge the return values ​​obtained by getType() and getExtra(). When getType()==0 (open content is unknown) or getExtra() is null, it is considered that the url loaded by the webview will occur. Redirect, we will handle it in the shouldOverriderUrlLoading method at this time.

The following table shows the types of web pages opened corresponding to the variable values ​​in the HitTestResult class shown above.

Okay, let's take a look at how to determine whether the loaded URL is a non-http/https custom protocol. It's very simple. Judge the parameter String url in the shouldOverriderUrlLoading method. url.startsWith("http://")||url.startsWith("https://") means that the loaded url is http/https protocol, which is incorrect. It performs interception processing, and vice versa. (See below)

solution
 

       Posted below are my solutions to webpage redirection and loading custom protocol links in the code. I intercept the URLs where redirection and custom protocols will occur, and call the mobile phone system browser to open the webpage (I do not get the redirection) The final loading address of the url is quite troublesome. Friends who have a convenient method can leave a message and point it out). The blogger integrates Tencent X5webview, which is used the same as webview. I have marked the description of this comment as much as possible. It is for reference only. If you copy and paste directly, you need to replace the webview control and Content. Please handle it yourself.

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

}

In addition, webview needs to do further processing when the loaded url is a download link. It needs to use the setDownloadListener() method. In the callback listener, it is set to call the mobile browser to open the download link when the opened url is a download link.

/**
 * setDownloadListener()是对加载的url是下载地址时的回调
 */
tencentWeb.setDownloadListener(new DownloadListener() {
    @Override
    public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
 
        // 上面的参数中,url对应文件下载地址,mimetype对应下载文件的MIME类型
        Intent intent = new Intent(Intent.ACTION_VIEW);
        Uri uri = Uri.parse(url);
        intent.addCategory(Intent.CATEGORY_BROWSABLE);
        intent.setData(uri);
        context.startActivity(intent);
    }
});

Bloggers are still exploring more about webview. If there is something wrong in this article, please point it out.

————————————————
Reprinted at: https://blog.csdn.net/qq_41188773/article/details/89669354

Guess you like

Origin blog.csdn.net/weixin_42602900/article/details/132871142