I have a webview in my android app and would like to detect when the url changes.
I want to use this to hide the info button in the top bar when the user is on the info.php page and show it again when he is not on the info.php page.
I googled but can't find any working code, can anybody help me?
I know I'm late to the game but I ran into this issue over and over ... I finally found a sloution which is pretty straight forward. Just override WebViewClient.doUpdateVisitedHistory
override fun doUpdateVisitedHistory(view: WebView?, url: String?, isReload: Boolean) {
// your code here
super.doUpdateVisitedHistory(view, url, isReload)
}
It works with all url changes even the javascript ones!
If this does not make you happy then I don't know what will :)
You can use WebViewClient.shouldOverrideUrlLoading to detect every URL changes on your WebViewClient
For those load url by javascript. There is a way to detect the url change by JavascriptInterface. Here I use youtube for example. Use JavaScriptInteface has async issue, luckily its just a callback here so that would be less issue. Notice that #javascriptinterface annotation must be existed.
{
youtubeView.getSettings().setJavaScriptEnabled(true);
youtubeView.setWebViewClient(mWebViewClient);
youtubeView.addJavascriptInterface(new MyJavaScriptInterface(),
"android");
youtubeView.loadUrl("http://www.youtube.com");
}
WebViewClient mWebViewClient = new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
view.loadUrl("javascript:window.android.onUrlChange(window.location.href);");
};
};
class MyJavaScriptInterface {
#JavascriptInterface
public void onUrlChange(String url) {
Log.d("hydrated", "onUrlChange" + url);
}
}
if you override this method of WebViewClient you will be able to handle url changes, and javascript url changes:
public class YXWebViewClient extends WebViewClient {
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
Log.i("Listener", "Start");
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
Log.i("Listener", "Finish");
}
}
and then in your WebView set the WebViewClient
yxWebViewClient = new YXWebViewClient();
webview.setWebViewClient(yxWebViewClient);
I used this method:
webView.setWebChromeClient(new WebChromeClient()
{
#Override public void onProgressChanged(WebView view, int newProgress) {
if (view.getUrl().equals(mUrl))
{
}
else
{
mUrl = view.getUrl();
// onUrlChanged(mUrl) // url changed
}
super.onProgressChanged(view, newProgress);
}
};
);
mUrl is a fields as String...
Try to use onLoadResource. It will be called at least 1 time even if you are using
JS to change your url. But it may be called more than one time, so be careful.
Method onPageFinished seems to work at least in modern WebViews.
An implementation of rinkal-bhanderi's answer would look like this:
class MyWebClient(
private val myCustomMethod: () -> Unit) : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView?,
url: String?): Boolean {
myCustomMethod()
return true
}
}
}
And you would use it like:
webview.webViewClient = MyWebClient(::hideButton)
Where webview is the actual webview you get from calling FindViewById or the object reference you get from binding. And hideButton is a method accessible in the same scope last expression is evaluated.
I had an interesting problem that brought me to this question and happy to provide a solution that may help someone else if they come this way due to a googlebingyahoo search.
mwebVew.reload() would not pick up the new URL I wanted to load once I returned from a preference screen where I either logged on the user or logged off the user. It would update the shared preferences well enough but not update and replace the url web page. So after a few hours of not seeing an answer I tried the following and it worked a real treat.
mWebView.resumeTimers();
Here is the link to the doco if you want more info.
Hope it saves someone else the pain I went through, and happy to have someone tell me I should of implemented it another way.
I had the same problem. So i've solved this problem by overriding public void onPageStarted(WebView view, String url, Bitmap favicon) method as follows:
webView.setWebViewClient(new WebViewClient(){
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon)
{
// Here you can check your new URL.
Log.e("URL", url);
super.onPageStarted(view, url, favicon);
}
});
Also you can overridepublic void onPageFinished(WebView view, String url) method to get a new URL at the end of page load process.
My requirement was to handle the visibility of a floating button in my page based on the url change.
if url is changing from https/ooooo//login to https/ooooo//homepage
it may not be registered in onPageFinished or shouldOverrideUrlLoading.
This was the issue I was facing.
I fixed that issue by following method:
#Override
public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) {
super.doUpdateVisitedHistory(view, url, isReload);
String currentUrl = view.getUrl();
}
*please don't use url which we are getting with doUpdateVisitedHistory method.That will be the basic url.so go with view.getUrl().
:)
Use WebViewClient.shouldOverrideUrlLoading() when the base/host url changes. Use Use WebViewClient.doUpdateVisitedHistory() method of webview if the base url doesnt change like it happens in single page applications and it detects URL change by javascript which does not lead to a web page reload. #Helin Wang
This will help to detect redirect caused by javascript.
WebViewClient mWebViewClient = new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
view.loadUrl("javascript:window.android.onUrlChange(window.location.href);"); }
};
myWebView.setWebViewClient(mWebViewClient);
}
#JavascriptInterface
public void onUrlChange(String url) {
Toast.makeText(mContext, "Url redirected",Toast.LENGTH_SHORT).show();
}
Related
The problem is rather simple.
In the application we want to keep track of the current url being displayed. For that we use shouldOverrideUrlLoading callback from the WebViewClient by saving the url into a class field for every update. 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.
The url: 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
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.
Reading android documentation about WebView I found this:
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. For example, if you implement callbacks such as shouldOverrideUrlLoading() or shouldInterceptRequest(), then WebView invokes them only for valid URLs.
But still doesnt make sense since the above url is generic and should meet the standard.
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.
From the above MDN article:
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.
These are sometimes called single-page applications. Since the actual loaded page doesn’t change, the WebView callback for page loads isn’t called.
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. 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.
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.
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. I tried observing these events in Chrome with the method described in the previous link and it seems to work fine.
Maybe this helps someone, although the signature in the question is correct, but Android Studio suggests the following method signature:
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. It's not always easy to notice that the second parameter is different.
Please omit mWebView.getSettings().setDomStorageEnabled(true);
Then again try, if a new url found then will invoke shouldOverrideUrl()
I had the same problem like you, and I've finished with extending of WebViewChromeClient with listening for callback to
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.
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
override fun doUpdateVisitedHistory(view: WebView?, url: String?, isReload: Boolean) {
// your code here
super.doUpdateVisitedHistory(view, url, isReload)
}
Another approach you can try: Catch the url by javascript side. Initialize your webView with this:
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:
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:
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.
Add
webView.getSetting().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
then shouldOverrideUrl will be triggered.
onProgressChanged is always triggered when reloading, loading new page with userclick or XmlHttpRequest.
Compare the URL of previous load and the current load, you'll know it's reloading or loading a new page. This works perfect in my single page Web App.
First declare a global variable to store last URL.
String strLastUrl = null;
Then override 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:
doUpdateVisitedHistory sometimes can not return correct url after "#" made by XmlHttpRequest.
My case is a single page web App. The web App uses javascript with
xhr to display new page when user click an item. For example, user is
currently at http://example.com/myapp/index.php , after clicking, the
browser url becomes
http://example.com/myapp/index.php#/myapp/query.php?info=1, but in
this case, doUpdateVisitedHistory returns
http://example.com/myapp//myapp/
onReceivedTitle doesn't work in my case because the response retrieved by XMLHttpRequest does not have <title></title> tag.
The JavascriptInterface method also works, but I'm afraid it will cause
security related issues with 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...
In webview android I am trying to load a url and in order to check if the load of this url is done successfully (internet connection was available, the server was up etc) I was under the impression that webview.loadUrl would throw exceptions, but wrong! as it explicitly is stated in here "an exception will NOT be thrown".
So how can I check to see if webview.loadUrl did not fail ?
Unfortunately, currently there is no easy way in WebView to ensure that everything on the page has been loaded successfully. We are hoping for a better API to come up in future version. Let me explain what you can do now.
First of all, in order to detect any problems that prevent WebView from making a connection to the server for loading your main page (e.g. bad domain name, I/O error, etc.), you should use WebViewClient.onReceivedError callback as other people correctly suggest:
public class MyWebViewClient extends WebViewClient {
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
// Make a note about the failed load.
}
}
myWebView.setWebViewClient(new MyWebViewClient());
If the server connection was successful, and the main page was retrieved and parsed, you will receive WebView.onPageFinished callback, so you also need to have this in your WebViewClient subclass:
public class MyWebViewClient extends WebViewClient {
...
#Override
public void onPageFinished(WebView view, String url) {
// Make a note that the page has finished loading.
}
...
}
The caveat here is that if you have received an HTTP error from the server (e.g. a 404 or a 500 error), this callback will be called anyway, it's just the content that you will get in your WebView will be a server error page. People suggest different ways of how to deal with it, see the answers here: How can I check from Android WebView if a page is a "404 page not found"? Basically, it really depends on what you expect to be a "good" page and a "error" page. Unfortunately, there is currently no way for the app to get the HTTP response code from WebView.
The callbacks WebViewClient.onPageStarted and WebViewClient.onProgressChanged are only useful if you want to draw a progress bar as you are loading the page.
Also note that the way of overriding WebViewClient.shouldOverrideUrlLoading that people usually suggest is not correct:
public class MyWebViewClient extends WebViewClient {
...
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// !!! DO NOT DO THIS UNCONDITIONALLY !!!
view.loadUrl(url);
return true;
}
...
}
What few developers realize is that the callback is also called for subframes with non-https schemes. If you'll encounter something like <iframe src='tel:1234'>, you will end up executing view.loadUrl('tel:1234') and your app will show an error page, since WebView doesn't know how to load a tel: URL.
It is recommended to simply return false from the method, if you want WebView to do the loading:
public class MyWebViewClient extends WebViewClient {
...
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// Returning 'false' unconditionally is fine.
return false;
}
...
}
This doesn’t mean you should not call WebView.loadUrl from shouldOverrideUrlLoading at all. The specific pattern to avoid is doing so unconditionally for all URLs.
public class AppWebViewClient extends WebViewClient {
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
super.onPageStarted(view, url, favicon);
setProgressBar(true);
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
#Override
public void onPageFinished(WebView view, String url) {
//Page load finished
super.onPageFinished(view, url);
setProgressBar(false);
}
}
and then you can do
webView.setWebViewClient(new AppWebViewClient());
For the error part you can override the onReceivedError method
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
// TODO Auto-generated method stub
super.onReceivedError(view, errorCode, description, failingUrl);
}
Here is what I came up with, it works like a charm.
Boolean failedLoading = false;
WebView webView = view.findViewById(R.id.webView);
webView.loadUrl("www.example.com");
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (!failedLoading) {
webView.setVisibility(View.VISIBLE);
webView.setAlpha(0f);
ObjectAnimator anim = ObjectAnimator.ofFloat(webView, "alpha",1f);
anim.setDuration(500);
anim.start();
}
}
#Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
super.onReceivedError(view, request, error);
failedLoading = true;
}
});
It will also work great if you add some kind of a refresh button and then you can call the code above inside a function to try again.
You can check if a URL is loaded successfully by using onProgressChanged()
mWebView.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress) {
progressBar.setProgress(progress);
if (progress == 100) {
//your url is loaded successfully
}
}
});
There are two types of links in the HTML file:
(1) A normal link like http://www.bbb.com/q?type=normal
(2) A short link like /q?type=short.
For the first kind, just load the url. For the second kind, I should prepend it with a fixed address like http://www.abc.com before loading the url.
I am trying to do this with overriding the shouldOverrideUrlLoading() function in WebViewClient. However this function doesn't gets called for the second type of link. I tried prepending the "http://www.abc.com" to the second type of links in the HTML file. Then the function does get called when I click the second kind of link.
I think what's happening is WebView will first check if the link is a valid url. Only if it is valid will the function gets called. Am I right? How can I solve this? Thanks in advance.
contentWebView = new WebView(context);
webViewClient = new WebViewClient() {
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// String not in Logger.
Log.d(TAG, "Here!");
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
context.startActivity(intent);
return true;
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (hosted) {
contentWebView.setVisibility(VISIBLE);
} else {
summaryTextView.setVisibility(VISIBLE);
articleLinkButton.setVisibility(VISIBLE);
}
progressBar.setVisibility(View.GONE);
}
};
contentWebView.setWebViewClient(webViewClient);
contentWebView.getSettings().setJavaScriptEnabled(true);
contentWebView.loadData(fullString, "text/html", "utf-8");
contentWebView.setVisibility(GONE);
More on this:
I tried changing
contentWebView.loadData(fullString, "text/html", "utf-8");
to
contentWebView.loadDataWithBaseURL("http://www.abc.com", fullString, "text/html", "utf-8", null);
Then the function gets called.
If I change the short link to a full link in the html string manually. Then the function also gets called.
So I think this is probably what is happening: The WebView checks if the link URL is valid. Only when the URL is valid will the shouldOverrideUrlLoading() be called.
You're probably using the KitKat WebView. This is a known issue (I think it's outlined in the migration guide) where URLs that can't be resolved against the base URL are dropped on the floor (you won't get any callbacks for them, neither shouldOverrideUrlLoading nor onPageStarted).
The problem is that your base URL is a data url, so you're trying to resolve '/q?type=short' against 'data:text/html,...' which doesn't make much sense and so the whole attempt to navigate to the URL gets ignored.
This was different for the pre-KK WebView which used KURL instead of GURL for URL processing. GURL is generally more strict (and more secure) than KURL, which is the cause for some incompatibility between the two WebView versions.
Maybe try using onPageStarted method
solution that worked for me was to use loadDataWithBaseURL with an invalid baseUrl and detect that and remove it and replace with "http://" during setWebViewClient
public class MyActivity
extends Activity
{
private static final String badurl = "http://myappname.invalid/";
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
...
WebView wv = ((WebView)findViewById(R.id.webview));
WebSettings settings = wv.getSettings();
settings.setJavaScriptEnabled(false);
settings.setSupportMultipleWindows(true);
wv.setWebChromeClient(new WebChromeClient() {
#Override
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg)
{
handleUrlview.getHitTestResult().getExtra());
return true;
}
});
wv.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
handleUrl(url);
return true;
}
});
wv.loadDataWithBaseURL(badurl,text,"text/html","utf-8",null);
}
private void handleUrl(String url)
{
if (url.startsWith(badurl))
url = "http://"+url.substring(badurl.length());
try {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
} catch (ActivityNotFoundException e) { }
}
}
i faced this problem too and solved it by replacing my html response. In my html response there is no any host in "href" html tags. Then i replaced it following codes and thats working like a charm now :)
String htmlString = AppCache.homePageResponse.showcaase.replace("href=\"/", "href=\"" + "evidea://" );
I found that if your page runs in an iframe, clicking on external (http://www...) links does NOT trigger shouldOverrideUrlLoading() !
See shouldOverrideUrlLoading() not called for external links from iframe
Try this
private static WebView webView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); //should be activity_main
webView = (WebView) findViewById(R.id.web);
webView.setWebViewClient(new webviewclient());
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl("http://www.yahoo.com");
}
public class webviewclient extends WebViewClient{
#Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
view.loadUrl(request.toString());
return true;
}
In my WebView, I have multiple links in header. In Offline mode, I mustn't allow reload the page and keep that page as is and then, inform users about internet connection. I am able to catch links before it loads using shouldOverrideUrlLoading if I click other links. But if I click the same link, shouldOverrideUrlLoading is not being fired, instead, onLoadResource method is being called first. In that method I tried webView.stopLoading(); but it continues working and fire onReceivedError method and shows error report on the page.
Here is my WebClient:
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(MyApplication.getInstance().isOnline()) {
return false;
}
Toast.makeText(getApplicationContext(), "Please check Internet connection and try again.", Toast.LENGTH_SHORT).show();
return true;
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
Log.i("ON_PAGE_START", "RUNNING ============>" + url);
if (MyApplication.getInstance().isOnline()) {
super.onPageStarted(view, url, favicon);
} else {
webView.stopLoading();
}
}
#Override
public void onLoadResource(WebView view, String url) {
if (MyApplication.getInstance().isOnline()) {
super.onLoadResource(view, url);
} else {
webView.stopLoading();
}
}
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
view.stopLoading();
Toast.makeText(getApplicationContext(), "Please check Internet connection and try again.", Toast.LENGTH_SHORT).show();
super.onReceivedError(view, errorCode, description, failingUrl);
}
});
What I want is to be able to ensure that urls are not being fired if it is offline and inform about that.
Its a known issue and there is a bug reported for it.
http://code.google.com/p/android/issues/detail?id=2887
A number of workarounds have been suggested. e.g.
Override onPageStarted
Add JavascriptInterface by CommonsWare
Disable WebView touch events
Additionally, register a BroadcastReceiver to listen to network state changes and apply the workaround when the connectivity is lost.
Network listener Android
I think in onLoadRessource(..) and onPageStarted() it further should be
view.stopLoading();
in your else{..}
I know its quite an old post but thanks for this post, this helped me solve the issue!!!
I had a similar issue and stopLoading solved my issue :)
shouldOverrideUrlLoading gets called if it goes to a new page or if there is a redirection but not otherwise like for ex clicking on iframe etc. I wanted to achieve the similar behaviour in my app, and i realised that onPageStarted is called but not shouldOverrideUrlLoading.
I didn't override onLoadResource but just onPageStarted since onLoadResource gets called after onPageStarted. OnPageStarted checks if offline and not to load in that case. hope this helps someone.
So right now in my app the URL I'm accessing has a redirect, and when this happens the WebView will open a new browser, instead of staying in my app. Is there a way I can change the settings so the View will redirect to the URL like normal, but stay in my app instead of opening a new browser?
Edit:
I want the redirecting URL, I just don't know how to create it, so the only way to get to that URL is through one that will cause a redirect to the one I want.
For example: When you go here: http://www.amazon.com/gp/aw/s/ref=is_box_/k=9780735622777 notice how it will redirect the URL to the actual product. In my app, if I open it in a new browser, it will do that just fine, however if I keep it in my app with a WebView, it will show up as though it's doing a search for k=9780735622777, like this: http://www.amazon.com/gp/aw/s/ref=is_s_?k=k%3D9780735622777&x=0&y=0 . OR, it will open the view in the browser and show what is appropriate. However, I want to keep everything in my app.
Create a WebViewClient, and override the shouldOverrideUrlLoading method.
webview.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url){
// do your handling codes here, which url is the requested url
// probably you need to open that url rather than redirect:
view.loadUrl(url);
return false; // then it is not handled by default action
}
});
According to the official documentation, a click on any link in WebView launches an application that handles URLs, which by default is a browser. You need to override the default behavior like this
myWebView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return false;
}
});
Just adding a default custom WebViewClient will do. This makes the WebView handle any loaded urls itself.
mWebView.setWebViewClient(new WebViewClient());
You will have to set your custom WebviewClient overriding shouldOverrideUrlLoading method for your webview before loading the url.
mWebView.setWebViewClient(new WebViewClient()
{
#SuppressWarnings("deprecation")
#Override
public boolean shouldOverrideUrlLoading(WebView webView, String url)
{
return shouldOverrideUrlLoading(url);
}
#TargetApi(Build.VERSION_CODES.N)
#Override
public boolean shouldOverrideUrlLoading(WebView webView, WebResourceRequest request)
{
Uri uri = request.getUrl();
return shouldOverrideUrlLoading(uri.toString());
}
private boolean shouldOverrideUrlLoading(final String url)
{
Log.i(TAG, "shouldOverrideUrlLoading() URL : " + url);
// Here put your code
return true; // Returning True means that application wants to leave the current WebView and handle the url itself, otherwise return false.
}
});
Checkout the example code for handling redirect urls and open PDF without download, in webview.
https://gist.github.com/ashishdas09/014a408f9f37504eb2608d98abf49500
Create a class that implements webviewclient and add the following code that allows ovveriding the url string as shown below.
You can see these [example][1]
public class myWebClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
On your constructor, create a webview object as shown below.
web = new WebView(this); web.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
Then add the following code to perform loading of urls inside your app
WebSettings settings=web.getSettings();
settings.setJavaScriptEnabled(true);
web.loadUrl("http://www.facebook.com");
web.setWebViewClient(new myWebClient());
web.setWebChromeClient(new WebChromeClient() {
//
//
}
Please use the below kotlin code
webview.setWebViewClient(object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
view.loadUrl(url)
return false
}
})
For more info click here
In Kotlin, to navigate within same webView we needed to override the shouldOverrideUrlLoading for webview
If return type is true then navigation will be blocked If return
type is false then navigation will happen
object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
return true
}
}.also { webView.webViewClient = it }
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
if (url.equals("your url")) {
Intent intent = new Intent(view.getContext(), TransferAllDoneActivity.class);
startActivity(intent);
}
}