webview don't display javascript windows.open() - javascript

I have a WebView in which i display web content which i have no control over. The content displays fine, but have links which spawn a popup window. The javascript function that does that looks like this:
function getEntry(id) {
var win = window.open('', 'Booking',
'resizable=yes,scrollbars=yes,status=no,width=500,height=400');
win.document.location = '/some/url/1-' + id ;
}
I can't easily change this, and if the people responsible for the page i download would change it, i guess my app would fail miserably...
My WebView setup in the activity looks like this:
_webview = new WebView(this);
setContentView(_webview);
final Activity activity = this;
_chromeClient = new MyChromeClient();
_webview.setWebChromeClient(_chromeClient);
//I experimented with changing user agent, in case that would have any effect, it didn't...
_webview.getSettings().setUserAgentString("Mozilla/5.0 (Windows NT 5.1; rv:9.0.1) Gecko/20100101 Firefox/9.0.1");
_webview.setWebViewClient(new MyWebViewClient());
_webview.getSettings().setJavaScriptEnabled(true);
_webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
_webview.getSettings().setSupportZoom(true);
_webview.getSettings().setBuiltInZoomControls(true);
_webview.getSettings().setDomStorageEnabled(true);
//Cache settings...
_webview.getSettings().setAppCacheMaxSize(1024*1024*8);
_webview.getSettings().setAppCachePath("/data/data/com.your.package.appname/cache");
_webview.getSettings().setAllowFileAccess(true);
_webview.getSettings().setAppCacheEnabled(true);
MyWebClient:
private class MyWebViewClient extends WebViewClient {
#Override
public void onLoadResource(WebView view, String url) {
Log.d("MyWebViewClient",url);
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
showProgressDiag();
Log.d("MyWebViewClient","shouldOverride... : " + url);
view.loadUrl(url);
return true;
}
#Override
public void onPageFinished(WebView view, String url){
hideProgressDiag();
}
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
if(failingUrl.equals("file:///android_asset/html/error.html")){
hideProgressDiag();
Toast.makeText(_context, "Error! Check internet connection, or try again later...", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(_context, failingUrl, Toast.LENGTH_SHORT).show();
view.loadUrl("file:///android_asset/html/error.html");
}
}
}
MyChromeClient:
private class MyChromeClient extends WebChromeClient{
#Override
public void onProgressChanged(WebView view, int progress) {
Pdiag.setProgress(progress * 100);
}
}
When clicking one of the links that points to the javascript function all that happens is that the WebView turns grey, without going through shouldOverrideUrlLoading(). When i hit the back key the app exits, meaning that nothing was placed in the nav history of the WebView. Sometimes nothing happens, but then the shouldOverrideUrlLoading() do run and from a Log.d() i can see that the correct URL for the popup has been given to the WebView.
The thing is, on very rare occasions it shows up fine, but i have no clue how to reproduce it, and wether it actually shows in a popup.
I'm lost... And quite frustrated... Thinking of watching a bad sitcom instead :(
EDIT:
Actually, maybe the URL wasn't all that correct after all... In Firefox the URL ends with "X<<<<" but in my Log.d() output it ends with "X%3C%3C%3C%3C"... I'll investigate if i could change that...
EDIT 2:
Nope, didn't do anything... The URL is identical to the one in Firefox...

First of all, you need to set the following settings on your WebView:
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
webSettings.setSupportMultipleWindows(true);
Then you need to attach a WebChromeClient that overrides onCreateWindow. Your implementation of this method can create a new web view, and display it inside a dialog:
webView.setWebChromeClient(new WebChromeClient() {
#Override
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
WebView newWebView = new WebView(MyActivity.this);
WebSettings webSettings = newWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
// Other configuration comes here, such as setting the WebViewClient
final Dialog dialog = new Dialog(MyActivity.this);
dialog.setContentView(newWebView);
dialog.show();
newWebView.setWebChromeClient(new WebChromeClient() {
#Override
public void onCloseWindow(WebView window) {
dialog.dismiss();
}
});
((WebView.WebViewTransport)resultMsg.obj).setWebView(newWebView);
resultMsg.sendToTarget();
return true;
}
});
Don't forget to set the new web view to the resultMsg, send it to its target and return true, as mentioned in the API documentation.

Please check with adding this -
getSettings().setSupportMultipleWindows(true);

Related

Calling Java method in Android from JavaScript using webview

I'm trying to access my Java method helloWorld(); using JavaScriptInterface in Android, from the page I'm viewing using WebView
I'm a little new to this, and I don't know why I'm not getting the value to my html page
This is the Android code I'm using:
WebView web;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
web = (WebView) findViewById(R.id.webview01);
JavaScriptInterface jsInterface = new JavaScriptInterface(this);
web.getSettings().setJavaScriptEnabled(true);
web.addJavascriptInterface(jsInterface, "JSInterface");
web.getSettings().setUseWideViewPort(true);
web.getSettings().setLoadWithOverviewMode(true);
web.setWebViewClient(new myWebClient());
web.getSettings().setJavaScriptEnabled(true);
web.loadUrl("http://exampleweb:10110/exWeb/deposits.jsp");
}
public class myWebClient extends WebViewClient
{
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
super.onPageStarted(view, url, favicon);
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// TODO Auto-generated method stub
view.loadUrl(url);
return true;
}
}
public class JavaScriptInterface {
private Activity activity;
public JavaScriptInterface(Activity activity) {
this.activity = activity;
}
#JavascriptInterface
public String helloWorld(){
return("hello world");
}
}
}
This is the JavaScript code I've been using (on the page I'm viewing with WebView)
HTML button
<td> <button type="button" class="btn btn-xs btn-primary connectToAndroid">Test android</button></td>
JavaScript
$(".connectToAndroid").on('click', function () {
var val = window.JSInterface.helloWorld();
alert(val);
});
Does anyone know what I'm doing wrong here? I just want to alert an "Hello World" from android in my HTML page.
Any pointers are greatly appreciated!
Try by adding this line of code before loading the url and make sure you reference your jQuery library in the html.
web.setWebChromeClient(new WebChromeClient(this));
This is very weird, I tried using this a couple of hours ago:
$(".connectToAndroid").on('click', function () {
var val = Android.helloWorld();
alert(val);
});
Then I changed it, it didn't say Android anymore,
yet I kept getting an error saying:
Uncaught ReferenceError: Android is not defined
And after a while I figured, Android.helloWorld(); must be cached somehow in my webview app or something.
So, I changed back to this:
$(".connectToAndroid").on('click', function () {
var val = Android.helloWorld();
alert(val);
});
And added this:
web.addJavascriptInterface(jsInterface, "Android");
And now it works like a charm, as it should have from the beginning if it wasn't for some cache somewhere,
Can anyone explain why this happens? Does android webview actually cache javascript code? And can I prevent this behaviour in the future somehow? Cache bothers a lot when coding/testing new stuff.

Android, calling the browser from javascript inside a WebView

I try to call the browser of my device loading a page inside a WebView that contains:
window.open(
'http://www.stackoverflow',
'_blank'.
);
I need to do this from the html that is loaded into the WebView
but i have no success, any idea!?
There are several things you need to do in your app:
Use setJavaScriptCanOpenWindowsAutomatically as #ajpolt says. This will allow window.open to not fail.
Enable setSupportMultipleWindows. This makes WebView to actually attempt opening a new window. Otherwise, it will be opening the URL in the same WebView.
Hook up to WebChromeClient.onCreateWindow callback and create a new WebView instance there. For this new instance, you need to set WebViewClient that will launch the intent from shouldOverrideUrlLoading.
Below is sample code:
WebView webView = (WebView)findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
webView.getSettings().setSupportMultipleWindows(true);
webView.setWebChromeClient(new ChromeClient());
And this is the ChromeClient:
class ChromeClient extends WebChromeClient {
#Override
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
WebView tempWebView = new WebView(MainActivity.this);
tempWebView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
browserIntent.addCategory(Intent.CATEGORY_BROWSABLE);
startActivity(browserIntent);
return true;
}
});
WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
transport.setWebView(tempWebView);
resultMsg.sendToTarget();
return true;
}
}
You are probably missing a setting on your webview.
Try using setJavaScriptCanOpenWindowsAutomatically in your settings, like this:
mWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);

Calling JavascriptInterface method through the WebView and JS function after changing config often doesnt work

I have some problem with calling a JavaScript function in a WebView and getting response in the app (on my Galaxy Tab 2 '10). I call the js-function directly after content loading. According this one solution i use a PictureListener
webView.setPictureListener(new PictureListener() {
#Override
public void onNewPicture(WebView view, Picture picture) {
webView.loadUrl("javascript: JsImpl.init('{response}');");
}
});
it works fine: when content is loaded, onNewPicture always is started.
"javascript: JsImpl.init('{response}') loads js that calls:
class JsImpl {
private final static String LOG_TAG = "JsImpl";
#JavascriptInterface
public void init(String json) {
Log.d(LOG_TAG, json);
}
}
In the log i see D/JsImpl(18400): {response}. It seems to be everything okay but...
When I switch my tab on a landscape or portrait mode the WebView is recreated, onNewPicture are started but the method public void init(String json) in the JsImpl is often not called at all!
So if i change orientation, sometimes js works, sometimes doesn't work. No exception, no errors...
Who faced with the same problem?
Below is full code
public class NextActivity extends Activity {
#SuppressLint("SetJavaScriptEnabled")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_next);
final WebView wv = (WebView) findViewById(R.id.WebView);
wv.getSettings().setJavaScriptEnabled(true);
wv.loadUrl("file:///android_asset/index.html");
wv.addJavascriptInterface(new JsImpl(), "JsImpl");
wv.setPictureListener(new PictureListener() {
#Override
public void onNewPicture(WebView view, Picture picture) {
wv.loadUrl("javascript: JsImpl.init('{responce}');");
}
});
}
class JsImpl {
private final static String LOG_TAG = "JsImpl";
#JavascriptInterface
public void init(String json) {
Log.d(LOG_TAG, json);
}
}
}
html code is not needed here, just put on the assets dir an empty html file index.html.
EDIT:
I've found one soution but i dont know exactly is it correct varion. But it works.
I added handler loop
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (isJSSetup) return;
Log.i("handler-loop", "JS didn't handle. Reload page");
wv.loadUrl(CONTENT_PAGE);
handler.postDelayed(this, 1000);
}
}, 1000);
when #JavascriptInterface init(String json) is called, isJSSetup became true. In handler loop i check if JS is setup or no if (isJSSetup) return;. If no - i reload URL again wv.loadUrl(CONTENT_PAGE) and try to call init(String json). So long as it is not going to work. It's hardcode, so i'm still looking for a good solution.
I hope this will help, but I can't say for sure because you are not showing how your WebView is restored after orientation changes.
I was having very hard time making my nested fragments to work properly after orientation changes. I wanted to retain the form values and all functionality during screen rotations. It all worked fine except the JavascriptInterface was NEVER working after orientation changes.
My WebView is restored in the onCreateView. I had to remove the restoreState call for my WebView and it all works now.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.layoutT4, container, false);
webView = (WebView) rootView.findViewById(R.id.webViewT4);
prepareBrowser(); // the browser is initiated here including the JavascriptInterface
if (webView != null) {
String URL = (savedInstanceState == null) ? "" : savedInstanceState.getString("URL");
if (URL.equals("")) {
webView.loadUrl("yourhome.html");
} else {
//webView.restoreState(savedInstanceState.getBundle("webViewBundle")); // this line was preventing the JavascriptInterface to work properly
webView.loadUrl(URL); // this is saved in onSaveInstanceState - I just reopen the URL here, the PHP page will take care of reloading the data
}
}
return rootView;
}

Android webview "location.replace" doesn't work

I have an Android webview with a page that redirects to another page, using location.replace(url).
Lets say that I have page "A" that redirects to page "B" (using location.replace). When pressing "back" button from page "B", the page returns to page "A", which redirects it to page "B" again.
When I debug the history api (history.length), I can clearly see that on page "B" the length has incremented in "1" (only on Android 4.X webview. On iOS / web browser / Android 2.X it remains the same), which is a bug! (location.replace shouldn't change history.lenght!)
I work with Yaniv on this project and we found the cause of the problem, it was introduced when we tried to add mailto: links handling according to this answer.
The answer suggested using the following extending class of WebViewClient:
public class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(MailTo.isMailTo(url)){
MailTo mt = MailTo.parse(url);
// build intent and start new activity
return true;
}
else {
view.loadUrl(url);
return true;
}
}
}
The problem was that explicitly telling the WebViewClient to load the URL and returning true (meaning "we handled this") added the page to the history. WebViews are quite capable of handling regular URLs by themselves, so returning false and not touching the view instance will let the WebView load the page and handle it as it should.
So:
public class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(MailTo.isMailTo(url)){
MailTo mt = MailTo.parse(url);
// build intent and start new activity
return true;
}
else {
return false;
}
}
}
function locationReplace(url){
if(history.replaceState){
history.replaceState(null, document.title, url);
history.go(0);
}else{
location.replace(url);
}
}
Try this way..
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView mainWebView = (WebView) findViewById(R.id.webView1);
WebSettings webSettings = mainWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mainWebView.setWebViewClient(new MyCustomWebViewClient());
mainWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
mainWebView.loadUrl("file:///android_asset/www/A.html");
}
Or get help from this and this link

android javascript won't work after redirect

I'm using mWebView.addJavascriptInterface(this, XXX) to let java
enter code herescript be executed on a webview.
The problem comes when the web page that I'm browsing sends a redirect.
I'm able to capture it an display the new URL in the same webview but javascript will not work.
The only solution that I've found is to create a new intent that load the new page on a new Activity.
public class QBrowser extends Activity {
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.qbrowser_main);
mWebView = (WebView) findViewById(R.id.webview);
webSettings.setJavaScriptEnabled(true);
mWebView.setWebChromeClient(new MyWebChromeClient());
mWebView.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// BEGIN: THE WORK AROUND I DONT LIKE
Intent intent = new Intent("com.bcnquark.client.qbrowser.QBROWSER");
intent.putExtra("URL", url);
startActivity(intent);
finish();
// END:THE WORK AROUND I DONT LIKE
return true;
}});
Intent intent = getIntent();
String url = intent.getStringExtra("URL");
mWebView.addJavascriptInterface(this, "XXXX");
}
mWebView.loadUrl(url);
}
}

Categories

Resources