简体   繁体   English

WebViewClient 未调用 shouldOverrideUrlLoading

[英]WebViewClient not calling shouldOverrideUrlLoading

The problem is rather simple.问题比较简单。 In the application we want to keep track of the current url being displayed.在应用程序中,我们希望跟踪当前显示的 url。 For that we use shouldOverrideUrlLoading callback from the WebViewClient by saving the url into a class field for every update.为此,我们使用来自WebViewClientshouldOverrideUrlLoading回调,方法是将 url 保存到每次更新的类字段中。 Here is the relevant code:这是相关的代码:

    mWebView.getSettings().setJavaScriptEnabled(true);
    mWebView.getSettings().setDomStorageEnabled(true); 
    mWebView.setWebViewClient(new WebViewClient() {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            mCurrentUrl = url;

            // If we don't return false then any redirect (like redirecting to the mobile
            // version of the page) or any link click will open the web browser (like an
            // implicit intent).
            return false;
        }



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

However, there is at least one scenario, where the callback never gets triggered and the mCurrentUrl field doesnt get updated.但是,至少有一种情况,回调永远不会被触发,并且 mCurrentUrl 字段不会更新。

The url: https://m.pandora.net/es-es/products/bracelets/556000网址: https : //m.pandora.net/es-es/products/bracelets/556000

Last updated url (shouldOverrideUrlLoading never gets called when clicking the product): https://m.pandora.net/es-es/products/bracelets最后更新的 url(shouldOverrideUrlLoading 在点击产品时永远不会被调用): https ://m.pandora.net/es-es/products/bracelets

I have tried with callbacks like onPageStarted(), but the url also gets filtered and there doesn't seem to be an accessible one upstream since its protected code.我尝试过使用 onPageStarted() 之类的回调,但是 url 也被过滤了,并且由于其受保护的代码,上游似乎没有可访问的。

Reading android documentation about WebView I found this:阅读有关 WebView 的 android 文档我发现了这一点:

https://developer.android.com/guide/webapps/migrating.html#URLs https://developer.android.com/guide/webapps/migrating.html#URLs

The new WebView applies additional restrictions when requesting resources and resolving links that use a custom URL scheme.新的 WebView 在请求资源和解析使用自定义 URL 方案的链接时应用了额外的限制。 For example, if you implement callbacks such as shouldOverrideUrlLoading() or shouldInterceptRequest(), then WebView invokes them only for valid URLs.例如,如果您实现了诸如 shouldOverrideUrlLoading() 或 shouldInterceptRequest() 之类的回调,那么 WebView 只会为有效的 URL 调用它们。

But still doesnt make sense since the above url is generic and should meet the standard.但仍然没有意义,因为上面的 url 是通用的,应该符合标准。

Any alternative or solution to this?有什么替代方案或解决方案吗?

When you click a product on that web page, it loads the new content in with JavaScript and updates the visible URL in the address bar using the HTML5 History APIs .当您单击该网页上的产品时,它会使用 JavaScript 加载新内容,并使用HTML5 历史 API更新地址栏中的可见 URL。

From the above MDN article:来自上面的 MDN 文章:

This will cause the URL bar to display http://mozilla.org/bar.html , but won't cause the browser to load bar.html or even check that bar.html exists.这将导致 URL 栏显示http://mozilla.org/bar.html ,但不会导致浏览器加载 bar.html 甚至检查 bar.html 是否存在。

These are sometimes called single-page applications .这些有时称为单页应用程序 Since the actual loaded page doesn't change, the WebView callback for page loads isn't called.由于实际加载的页面不会更改,因此不会调用页面加载的 WebView 回调。

In case you know precisely what kind of HTTP request you want to intercept, you could use the shouldInterceptRequest callback that gets called for each request.如果您确切地知道要拦截哪种 HTTP 请求,则可以使用为每个请求调用的shouldInterceptRequest回调。 It's likely that the web application loads some data from an API, for example when a product is shown, which you could then detect. Web 应用程序很可能从 API 加载了一些数据,例如在展示产品时,您可以检测到这些数据。

If detecting this isn't possible, but you're in control of the web application, you could use the Android JavaScript interface to invoke methods within the Android application directly from the web page.如果无法检测到这种情况,但您可以控制 Web 应用程序,则可以使用Android JavaScript 接口直接从 Web 页面调用 Android 应用程序中的方法。

If you're not in control of the loaded page, you could still try to inject a local JavaScript file into the web page and observe when the history APIs are used , then call methods in your Android application over the JS interface.如果您无法控制加载的页面,您仍然可以尝试将本地 JavaScript 文件注入网页并观察历史 API 何时被使用,然后通过 JS 接口调用 Android 应用程序中的方法。 I tried observing these events in Chrome with the method described in the previous link and it seems to work fine.我尝试使用上一个链接中描述的方法在 Chrome 中观察这些事件,它似乎工作正常。

Maybe this helps someone, although the signature in the question is correct, but Android Studio suggests the following method signature:也许这对某人有所帮助,虽然问题中的签名是正确的,但 Android Studio 建议使用以下方法签名:

public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {

which then never called.然后从未调用过。 It took me a while to notice that the right signature is:我花了一段时间才注意到正确的签名是:

public boolean shouldOverrideUrlLoading(WebView view, String url) {

Sorry if this not 100% fit the question, but I believe this may help someone in the same situation.对不起,如果这不是 100% 适合这个问题,但我相信这可能会帮助处于相同情况的人。 It's not always easy to notice that the second parameter is different.注意到第二个参数不同并不总是那么容易。

Please omit mWebView.getSettings().setDomStorageEnabled(true);请省略mWebView.getSettings().setDomStorageEnabled(true);

Then again try, if a new url found then will invoke shouldOverrideUrl()然后再试一次,如果找到一个新的 url,则将调用shouldOverrideUrl()

I had the same problem like you, and I've finished with extending of WebViewChromeClient with listening for callback to我有和你一样的问题,我已经完成了 WebViewChromeClient 的扩展,并监听了回调

public void onReceivedTitle(WebView view, String title)

mWebView.setWebChromeClient(mSWWebChromeClient);

private WebChromeClient mSWWebChromeClient = new WebChromeClient() {

        @Override
        public void onReceivedTitle(WebView view, String title) {
            super.onReceivedTitle(view, title);
            if (!view.getUrl().equals(mCurrentUrl)) {
                mCurrentUrl = view.getUrl();
                //make something
            }
        }

    }; 

For me the problem was below line -对我来说,问题出在下面——

mWebView.getSettings().setSupportMultipleWindows(true);

After removing it shouldOverrideUrlLoading was being called.删除它后,shouldOverrideUrlLoading 被调用。

Another approach you can try: Catch the url by javascript side .您可以尝试的另一种方法: Catch the url by javascript side Initialize your webView with this:用这个初始化你的 webView:

webView.addJavascriptInterface(new WebAppInterface(getActivity()), "Android");

After page is completely loaded (You can use an algorithm to check this like this https://stackoverflow.com/a/6199854/4198633 ), then:页面完全加载后(您可以使用算法来检查这个https://stackoverflow.com/a/6199854/4198633 ),然后:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    webView.evaluateJavascript("(function() {return window.location.href;})", new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String url) {
            //do your scheme with variable "url"
        }
    });
} else {
    webView.loadUrl("javascript:Android.getURL(window.location.href);");
}

And declare your WebAppInterface :并声明您的WebAppInterface

public class WebAppInterface {
    Activity mContext;

    public WebAppInterface(Activity c) {
        mContext = c;
    }

    @JavascriptInterface
    public void getURL(final String url) {
        mContext.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                //do your scheme with variable "url" in UIThread side. Over here you can call any method inside your activity/fragment
            }
        });

    }

}

You can do something like that to get url, or anything else inside the page.您可以执行类似操作来获取 url 或页面内的任何其他内容。

after stumbling on this problem and searching for solutions, I've found the one that worked perfectly for me在遇到这个问题并寻找解决方案后,我找到了一个对我来说完美的方法

https://stackoverflow.com/a/56395424/10506087 https://stackoverflow.com/a/56395424/10506087

 override fun doUpdateVisitedHistory(view: WebView?, url: String?, isReload: Boolean) {
    // your code here
    super.doUpdateVisitedHistory(view, url, isReload)
}

Add webView.getSetting().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);添加webView.getSetting().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); then shouldOverrideUrl will be triggered.然后shouldOverrideUrl将被触发。

onProgressChanged is always triggered when reloading, loading new page with userclick or XmlHttpRequest. onProgressChanged总是在重新加载时触发,使用 userclick 或 XmlHttpRequest 加载新页面。 Compare the URL of previous load and the current load, you'll know it's reloading or loading a new page.比较之前加载的 URL 和当前加载的 URL,你会知道它正在重新加载或加载一个新页面。 This works perfect in my single page Web App.这在我的单页 Web 应用程序中非常有效。

First declare a global variable to store last URL.首先声明一个全局变量来存储最后一个 URL。

String strLastUrl = null;

Then override onProgressChanged(WebView view, int progress)然后覆盖 onProgressChanged(WebView view, int progress)

mWebView.setWebChromeClient(new MyWebChromeClient(){

   @Override
   public void onProgressChanged(WebView view, int progress) {
            if (progress == 100) {
                //A fully loaded url will come here
                String StrNewUrl = view.getUrl();
                if(TextUtils.equals(StrNewUrl,strLastUrl)){
                   //same page was reloaded, not doing anything
                }else{
                   //a new page was loaded,write this new url to variable
                   strLastUrl = StrNewUrl;
                   //do your work here
                   Log.d("TAG", "A new page or xhr loaded, the new url is : " + strLastUrl);
                }
            }
            super.onProgressChanged(view, progress);
        }
});

I've also tried above solutions, but most of them have issue in my case:我也尝试过上述解决方案,但在我的情况下,其中大多数都有问题:

  1. doUpdateVisitedHistory sometimes can not return correct url after "#" made by XmlHttpRequest. doUpdateVisitedHistory有时无法在 XmlHttpRequest 生成的“#”后返回正确的 url。
  2. onReceivedTitle doesn't work in my case because the response retrieved by XMLHttpRequest does not have <title></title> tag. onReceivedTitle在我的情况下不起作用,因为 XMLHttpRequest 检索到的响应没有<title></title>标记。
  3. The JavascriptInterface method also works, but I'm afraid it will cause security related issues with javascript. JavascriptInterface 方法也有效,但我担心它会导致 javascript 的安全相关问题。
public class AndroidMobileAppSampleActivity extends Activity {
 /** Called when the activity is first created. */
String mCurrentUrl="";
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    WebView mWebView = (WebView) findViewById(R.id.mainWebView);

    WebSettings webSettings = mWebView.getSettings();
    webSettings.setJavaScriptEnabled(true);

    mWebView.setWebViewClient(new MyCustomWebViewClient());
    mWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);

    mWebView.loadUrl("https://m.pandora.net/es-es/products/bracelets/556000");

}

private class MyCustomWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        mCurrentUrl = url;
        Log.i("mCurrentUrl",""+mCurrentUrl);  
        view.loadUrl(url);

        return true;
    }
}
}

try this one...试试这个...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 WebViewClient - onPageStarted()vs shouldOverrideUrlLoading()? - WebViewClient - onPageStarted() vs shouldOverrideUrlLoading()? WebViewClient不会打开在ShouldOverrideUrlLoading()中处理的页面 - WebViewClient will not open page handled in shouldOverrideUrlLoading() android 2.2中的WebViewClient不应该调用OverlyUrlLoading - WebViewClient in android 2.2 shouldOverrideUrlLoading not called Android-具有多个webViewClient的多个webView:在新的webViewClient上未调用shouldOverrideUrlLoading - Android - multiple webViews with multiple webViewClient : shouldOverrideUrlLoading not called on new webViewClient WebViewClient.shouldOverrideUrlLoading中的FragmentTransaction抛出IllegalStateException - FragmentTransaction in WebViewClient.shouldOverrideUrlLoading throws IllegalStateException android webview shouldOverrideUrlLoading没有调用 - android webview shouldOverrideUrlLoading is not calling 使用WebViewClient shouldOverrideUrlLoading时,WebChromeClient中的链接不会打开野生动物园 - Link in WebChromeClient does not open safari when using WebViewClient shouldOverrideUrlLoading window.beforeunload 在 WebViewClient.shouldOverrideUrlLoading 之前调用 - window.beforeunload called before WebViewClient.shouldOverrideUrlLoading phonegap:调用webviewclient时出现超时错误 - phonegap: Timeout error calling webviewclient DroidGap:超时错误! -在android phonegap中调用webViewClient - DroidGap: TIMEOUT ERROR! - calling webViewClient in android phonegap
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM