问题很简单。
在应用程序中,我们希望跟踪显示的当前URL。为此,我们使用来自shouldOverrideUrlLoading
的{{1}}回调,将url保存到每个更新的类字段中。以下是相关代码:
WebViewClient
但是,至少有一种情况,即回调永远不会被触发,并且mCurrentUrl字段不会更新。
网址:https://m.pandora.net/es-es/products/bracelets/556000
上次更新的网址(点击产品后永远不会调用shouldOverrideUrlLoading):https://m.pandora.net/es-es/products/bracelets
我尝试过像onPageStarted()这样的回调,但是url也被过滤了,因为受保护的代码,它似乎不是上游可访问的。
阅读有关WebView的android文档我发现了这个:
https://developer.android.com/guide/webapps/migrating.html#URLs
在请求资源和解析使用自定义URL方案的链接时,新WebView会应用其他限制。例如,如果实现了诸如shouldOverrideUrlLoading()或shouldInterceptRequest()之类的回调,则WebView仅针对有效URL调用它们。
但仍然没有意义,因为上面的网址是通用的,应该符合标准。
任何替代或解决方案?
答案 0 :(得分:14)
当您点击该网页上的某个产品时,它会使用JavaScript加载新内容,并使用HTML5 History APIs更新地址栏中的可见网址。
从上面的MDN文章:
这会导致网址栏显示http://mozilla.org/bar.html,但不会导致浏览器加载bar.html甚至检查bar.html是否存在。
这些有时被称为single-page applications。由于实际加载的页面没有更改,因此不会调用页面加载的WebView回调。
如果您确切地知道要拦截哪种HTTP请求,可以使用为每个请求调用的shouldInterceptRequest
回调。 Web应用程序可能会从API加载一些数据,例如,当显示产品时,您可以检测到该数据。
如果无法检测到这一点,但您可以控制Web应用程序,则可以使用Android JavaScript interface直接从网页调用Android应用程序中的方法。
如果您无法控制加载的页面,您仍然可以尝试inject a local JavaScript file进入网页observe when the history APIs are used,然后通过JS界面调用Android应用程序中的方法。我尝试使用上一个链接中描述的方法在Chrome中观察这些事件,它似乎工作正常。
答案 1 :(得分:6)
请忽略mWebView.getSettings().setDomStorageEnabled(true);
然后再试一次,如果找到新的网址,则会调用shouldOverrideUrl()
答案 2 :(得分:5)
我遇到了和你一样的问题,我已经完成了扩展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
}
}
};
答案 3 :(得分:5)
也许这对某人有帮助,尽管问题中的签名是正确的,但是Android Studio建议使用以下方法签名:
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
然后从未调用。我花了一段时间才注意到正确的签名是:
public boolean shouldOverrideUrlLoading(WebView view, String url) {
很抱歉,如果这不是100%适合的问题,但我相信这可能会帮助处于相同情况的某人。并非总是很容易注意到第二个参数不同。
答案 4 :(得分:2)
您可以尝试另一种方法:通过javascript端抓取网址。使用以下命令初始化您的webView:
"prepublish": "(in-publish && npm run clean && flow check && npm run test && npm run build) || not-in-publish"
页面完全加载后(您可以使用算法来检查此https://stackoverflow.com/a/6199854/4198633),然后:
webView.addJavascriptInterface(new WebAppInterface(getActivity()), "Android");
并声明您的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);");
}
:
WebAppInterface
你可以做类似的事情来获取网页内的网址或其他内容。
答案 5 :(得分:1)
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;
}
}
}
尝试这个...
答案 6 :(得分:1)
对我来说,问题出在线下-
mWebView.getSettings().setSupportMultipleWindows(true);
删除它后,应该调用了OverrideUrlLoading。
答案 7 :(得分:0)
添加
webView.getSetting().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
那么shouldOverrideUrl
将被触发。
答案 8 :(得分:0)
在解决了这个问题并寻找解决方案之后,我找到了最适合我的解决方案
https://stackoverflow.com/a/56395424/10506087
override fun doUpdateVisitedHistory(view: WebView?, url: String?, isReload: Boolean) {
// your code here
super.doUpdateVisitedHistory(view, url, isReload)
}
答案 9 :(得分:0)
onProgressChanged
总是在重新加载时触发,使用userclick或XmlHttpRequest加载新页面。
比较先前加载的URL和当前加载的URL,您将知道它正在重新加载或加载新页面。在我的单页Web应用程序中,这很完美。
首先声明一个全局变量以存储最后一个URL。
String strLastUrl = null;
然后重写onProgressChanged(WebView视图,int进度)
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);
}
});
我也尝试了上述解决方案,但就我而言,大多数解决方案都存在问题:
doUpdateVisitedHistory
有时XmlHttpRequest生成的“#”后不能返回正确的url。
doUpdateVisitedHistory
返回
http://example.com/myapp//myapp/ onReceivedTitle
在我的情况下不起作用,因为XMLHttpRequest检索的响应没有<title></title>
标记。