WebViewClient shows white screen - android

I'm new to Android app development.
I'm managing to show a WebView and load a given URL. When I click on a link in the WebView, I get a blank white screen.
When I use the Chrome browser on the device (Galaxy TAB), it's working. Actually i'm trying to imitate Chrome in my WebView.
Does anyone know what's the problem?
This is the WebViewClient I use in my WebView:
siteView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String urlNewString) {
siteView.loadUrl(urlNewString);
return true;
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
if (dialog == null || !dialog.isShowing()) {
if(isFirstTime) {
dialog = ProgressDialog.show(MyActivity.this, "", getString(R.string.loadingMessage), true, false);
MyActivity.isFirstTime = false;
}
}
}
#Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
Toast.makeText(activity, "Oh no! " + description, Toast.LENGTH_SHORT).show();
}
});

try siteView.invalidate()
before loading anything to webview

The problem may lie in your shouldOverrideUrlLoading function. Your are receiving "view" as a parameter and you using "siteView" to load url. Your function should look like:
public boolean shouldOverrideUrlLoading(WebView view, String urlNewString) {
view.loadUrl(urlNewString); // you are using siteView here instead of view
return true;
}
Hope this works for you.

Make sure the url starts with http://. Without http it will just show white screen. Because mostly you will copy url and it will start with www.something.com/asdf. That will not work. change it to http://www.something.com/asdf.

Related

Android Webview: Disable confirm navigation

Is it possible to disable a confirm navigation pop up in android webview from a website that I am viewing?
I tried this one and I what I did is just return 'true' without showing any pop-up, but the navigation pop up still shows up. I want to disable it and I would like to just automatically navigate without any warning.
Here's the CustomWebChromeClient for my webview
public class CustomWebChromeClient extends WebChromeClient {
#Override
public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
return true;
}
}
You can override onJsBeforeUnload to always return true.
onJsBeforeUnload is the callback that gets invoked before the confirm navigation dialog pops up.
https://developer.android.com/reference/android/webkit/WebChromeClient.html#onJsBeforeUnload(android.webkit.WebView, java.lang.String, java.lang.String, android.webkit.JsResult)
Edit: As mentioned by AndyW, confirm or cancel methods should be invoked on jsResult argument otherwise the app might freeze because of the pending javascript dialog.
For me overriding onJsConfirm as followed did it:
#Override
public boolean onJsBeforeUnload(WebView view, String url, String message, JsResult result) {
result.confirm();
return true;
}
Why don't you create a webView in xml and use that webview in activity instead of using a class with webChromeClient, the below steps may help you.
step 1:
Create a webview in your xml file and call this view in Java
webView = (WebView) findViewById(R.id.exampleWebView);
step 2:
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
step 3:
webView.loadUrl(getResources().getString(R.string.olo_non_loggedin_url));
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageStarted(WebView view, String url,
Bitmap favicon) {
super.onPageStarted(view, url, favicon);
pBar.setVisibility(View.VISIBLE);
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
pBar.setVisibility(View.GONE);
}
});

Android: How to check for successful load of url when using webview.loadUrl

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

WebView loads url more than a time in android

webview in android loads more than once while loading the url.
Below is the code.
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
if (url.contains(".pdf")) {
String[] spliturl = url.split("http://someurl/");
String googleurl = "http://docs.google.com/viewer?embedded=true&url=";
System.out.println("Google Url"+googleurl);
System.out.println("spliturl"+spliturl[1]);
view.loadUrl(googleurl+spliturl[1]);
}
else
view.loadUrl(url);
return true;
}
});
I am splitting the url as it contains more than one url to be passed on google document viewer for rendering the pdf document.
First time the url is correctly split and the url is concatenated to open in google docs but the webview executes again there by giving an ArrayIndexOutOfBoundsException at spliturl[1].
Could anybody let me know why is this executing again.
thanks.
I don't know why it gets called multiple times, but the solution is to handle it in onPageStarted rather than in shouldOverrideUrlLoading
boolean calledOnce=false;
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
public void onPageStarted(WebView view, String url, Bitmap favicon) {
if (url.contains(".pdf") && !calledOnce) {
String[] spliturl = url.split("http://someurl/");
String googleurl = "http://docs.google.com/viewer?embedded=true&url=";
System.out.println("Google Url"+googleurl);
System.out.println("spliturl"+spliturl[1]);
url = googleurl+spliturl[1];
calledOnce = true;
}
super.onPageStarted(view, url, favicon);
}
You should always check if an array has a size more than the index requested:
if (url.contains(".pdf") && url.split("http://someurl/").size()>2){
// your code
}
Don't know why it gets called though - probably multiple redirections.

How to block a particular resource from loading in webview

I've searched a lot for this but did not find any answers. I am developing an android app in which at some point, a webview is displayed which shows you a webpage. But I am really worried about a small advertisement on the web view which shows porn content. Is there any way I can block that from loading on the webpage? Every resource passes the onLoadingRecource() method...Is this the place where i can find a solution? I really need help. Thank you.
Since API 11, there's WebViewClient.shouldInterceptRequest, here you can catch loading of embedded objects (images, etc) and replace it with your own image.
For example:
WebResourceResponse wr = new WebResourceResponse("", "", new FileInputStream("/sdcard/aaa.jpg"));
return wr;
You must detect yourself what you want replace by what.
On API<11 it may be more complicated to achieve this (I don't know yet how).
You can remove any Element from the page by injecting JavaScript into a WebView. Below is an example of how to inject JavaScrpt into a WebView to remove an element having its id:
public void onLoadResource(WebView view, String url) {
super.onLoadResource(view, url);
// Removes element which id = 'mastHead'
view.loadUrl("javascript:(function() { " +
"(elem = document.getElementById('mastHead')).parentNode.removeChild(elem); " +
"})()");
}
You can use the below code to check whether to load it on not. Where webview is the object for WebView.
webview.setWebViewClient(new WebViewClient() {
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
super.onPageStarted(view, url, favicon);
Toast.makeText(activity,"onPageStarted url :"+url, Toast.LENGTH_LONG).show();
}
#Override
public void onLoadResource(WebView view, String url) {
// TODO Auto-generated method stub
super.onLoadResource(view, url);
Toast.makeText(activity,"Connecting url :"+url, Toast.LENGTH_LONG).show();
}
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Toast.makeText(activity, "Oh no! " + description, Toast.LENGTH_SHORT).show();
}
});
I think this will help you.
The method has 2 params, override it in your webview and discard urls starting with the domain you want to avoid.

Android detect webview URL change

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();
}

Categories

Resources