How do I detect when a WebView page is trying to close? - android

I have a WebView into which I'm loading the facebook sharer php page. This page doesn't have any form of confirmation, it simply closes the window once the user has either shared or cancelled.
Since it is loaded into a web view there is nothing to "close" perse, so, I need to detect the window trying to close and act on that callback.
From my various searches it appears that the way to handle this is via a WebChromeClient. So, I'm attempting the following, but the callback is never called. I am obviously missing something, but don't know what. It *feels like the onCloseWindow event should be Overriden, but that causes eclipse to complain (reasonably) that I need to super the instance, which the documentation doesn't seem to suggest is possible.
All help appreciated.
[EDIT] oh, and I just tried swapping the order of the actions, setting the WebChromeClient before calling the url, and (as I expected) that didn't alter the behavior in any way.
webview.getSettings().setJavaScriptEnabled(true);
webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
webview.setWebViewClient(new WebViewClient());
webview.loadUrl("http://www.facebook.com/sharer/sharer.php?u=http://EXTRACTED.com?img_id=abc");// + getIntent().getStringExtra("userId"));
WebChromeClient wbc = new WebChromeClient(){
public void onCloseWindow(Window w){
Log.d(TAG, "Window trying to close");
}
};
webview.setWebChromeClient(wbc);

Whats wrong with:
public void onCloseWindow(WebView w){
super.onCloseWindow(w);
Log.d(TAG, "Window trying to close");
}

Related

Is there a way to convert Javascript alerts to show as Toast in Android WebView?

I have a web app thats working with Javascript alerts on most pages. Now I have recently created a WebView application for the same app. The app works fine, the alerts show.
I've seen solutions that suggest binding JavaScript code to Android code and then call these methods for example to show toast.
I have no doubt that this works, but now, for me, this means I'd have to re-write the code(s) that trigger these alerts.
My question is, is there a way to automatically capture all the alerts and display their contents as toasts instead?
You can use a WebChromeClient:
https://developer.android.com/reference/android/webkit/WebChromeClient
Create an instance of it, set it to your webview, and override onJsAlert.
Be sure to read the docs, to return the correct value, so it doesn't show the javascript alert also.
Thanks to Moonbloom's answer and this answer also.I managed to come with a solution that works exactly as I wanted. So for anyone who will stumble upon the same issue in the future, the snippet below is for you:
mWebView.setWebChromeClient(new WebChromeClient() {
#Override
public boolean onJsAlert(WebView view, String url, String message,
final JsResult result) {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
result.confirm();
return true;
}
});
Where mWebView is a WebView instance.

Button in a webview without Javascript

I have an android application that loads a webview from a server. I do not have the server code so I cannot change anything in Javascript. I want to figure out when a button is being clicked in a webview and what is the label in the button. I do not know the Id, I just want to get the label.
I tried searching for this but could not find an answer. I found solutions where you can work in the javascript but in my case I cannot.
This suggestion may help to find useful information that could lead to determination of your button label. Override shouldOverrideUrlLoading(), shouldInterceptRequest() and/or onLoadResource() for the WebViewClient so you can get at the URL of any redirects.
Example:
webview.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// Try to learn something useful from the 'url' here.
// Continue as normal, loading the 'url' within this WebView.
view.loadUrl(url);
return false; // Allow the WebView to handle the request.
}
// Optional: Add similar for "shouldInterceptRequest()" and/or "onLoadResource()".
});
Note: Overriding shouldOverrideUrlLoading() as above is the standard way to keep redirects within the same WebView rather than redirecting to the default browser application.
You might really want to check this page:
Building Web Apps in WebView (Google API Guides)
Specifically, it seems that addJavascriptInterface might be what you are looking for:
addJavascriptInterface(Object object, String name)
It allows you to execute your Java code from javascript and, paired with the ability to insert code in a page, it's an incredibly powerful tool for granting you a high level of coupling between your Activity and your page.
I think that at this point you will already know what to do, but I'll sketch a possible course of action anyway:
create a javascript interface with the callbacks you want executed in your activity when a button is pressed
as soon as your page loads, install the code to call your javascript interface in each button (or link) by injection
Hope this helps

How to know when WebView rendering is finished

I want to display a progress bar while the WebView is loading. I am hiding it on OnPageFinished(), but this is too early. The Webview is still rendering the image.
The WebView documentation states: "When onPageFinished() is called, the rendering picture may not be updated yet. To get the notification for the new Picture, use onNewPicture(WebView, Picture)."
However, OnNewPicture and the PictureListener interface is deprecated and obsolete. Is there another way to know that the rendering is complete?
Unfortunately, I have found that there is no event or mechanism to truly know when the page is completely loaded and finished rendering.
How about creating a custom WebChromeClient and overriding its onReceivedIcon() or onProgressChanged() methods. The onReceivedIcon() will be triggered once the favIcon is loaded and and using the onProgressChanged(), you can enquire the progress of the webview loading. I hope this helps
Please refer to this code snippet
webView.setWebChromeClient(new CustomWebChromeClient());
You can use onProgressChanged or onReceivedIcon whatever that suits your needs.
public class CustomWebChromeClient extends WebChromeClient {
#Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
if (newProgress==100) {
progressBar.setVisibility(View.GONE);
progressBar.setProgress(newProgress);
}
}
#Override
public void onReceivedIcon(WebView view, Bitmap icon) {
// icon received here
super.onReceivedIcon(view, icon);
}
}
I think you can add and execute JavaScript function at the end of body tag of your web page to call your JavaScript interface function to hide the progress bar. But, beware of enabling JavaScript on your WebView.
I'm suffering same problem, but there is no way to know the timing.
The only way I use is to give enough room for the rendering completion by postDelayed().
In my case 200ms is enough if u don't use heavy contents more than 200K in text.

WebView does not display loaded Html on some phones

I have a WebView in one of my Activities where I want to load a Html page. The page contains jquery-mobile and some html. So I do the following in my Activity :
mWebView=(WebView) findViewById(R.id.MyWebView);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new WebViewClient(){
[...]
});
mWebView.loadUrl("http://www.mymobilepage.html");
The problem is that the page gets loaded and displayed on the emulator, and on a HTC Desire, but when I try to load it on a LG Optimus One nothing gets displayed. The events onPageStarted and onPageFinished both get fired in my WebViewClient but just a blank page is displayed, and also I don't have any errors in my LogCat.
Thanks in advance.
When onPageFinished is called, the page may not be completely rendered. The documentation states:
Notify the host application that a page has finished loading. This method is called only for main frame. When onPageFinished() is called, the rendering picture may not be updated yet. To get the notification for the new Picture, use onNewPicture(WebView, Picture).
However, note that onNewPicture is documented as deprecated and obsolete. I ask about a replacement/alternative here.
This should be a comment, but since there is a bit of code on it I've added as response.
Try changing default background to transparent and alerting as soon as the page is loaded, just to be sure that at least the html is being interpreted:
mWebView = (WebView) this.findViewById(R.id.webview);
mWebView.setBackgroundColor(0);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(false);
mWebView.setWebViewClient(new WebViewClient(){
#Override
public void onPageFinished(WebView view, String url)
{
super.onPageFinished(view, url);
view.loadUrl("javascript:(function() { alert('hello'); })()");
} });
and when loading the webpage:
mWebView.clearView();
mWebView.loadUrl("http://yourmobilepage.something/");
and let us know if something happened.
Try this:
webView.post(new Runnable() {
#Override
public void run() {
// Your code here...
}
});
Have you checked your html/js code with different versions on the emulator? Newer Android versions have newer versions of WebKit, that might be the problem.
I would also check if you have LogCat set to show Error messages only, or Debug+Info+Warning+Error messages. According to this, the javascript errors should show up as Debug messages.
I had a similar issue to this, I found that calling clearview and then reload seemed to clear it up -- as in:
mWebView.clearView();
mWebView.loadUrl("http://yourmobilepage.something/");
mWebView.reload();

Limit WebView touch handling to links

Is it possible to capture touch events over a WebView in the activity that contains it, without loosing link functionality?
Consider a WebView showing a webpage with links. If the user taps on a link I would like the WebView to handle the touch event. If the user taps somewhere else I would like the activity to handle the touch event.
How can this be done?
Yes, it is.
(I can't elaborate more on this unless you are more specific on your question.)
If i understand your question correctly it'd seem difficult to interpret whether something is a link or not in the onTouchEvent() since all it knows about is X,Y coordinates (not html). However, off the top of my head it seems you could probably use the javascript binding piece in WebView to have javascript decide if the something is a link or not and act accordingly. Again, I haven't done this before nor tested it...just thinking out loud.
When initializing your WebView, try:
mWebView.setWebViewClient(new WebViewClientOverrider());
Then create a private class:
private class WebViewClientOverrider extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//TODO handle the link
return true;
}
}
Lastly, replace the TODO handle the link line with your own code for handling the link selection.
Or you can monitor the stack trace for:
android.webkit.CallbackProxy.uiOverrideUrlLoading()
See http://www.javapractices.com/topic/TopicAction.do?Id=78 for how to determine your stack trace from a throwable (created in an overriden WebView.loadUrl() method).

Categories

Resources