I'm trying to interact with a Website "synchronously" (javascript events when submit buttons are clicked) in order to get a textField value. This textField doesn't exist in the first place. It is generated when the user clicks on a submit button from a HTML form (2 buttons actually : first one : Id = "ColumnLeft_ADD_BTN_ID", second one : Id = "ColumnLeft_GET_BTN_ID").
When I simulate a click with Javascript, the textField doesn't appear. I get this error "Uncaught TypeError: Cannot read property 'value' of null" because the textField doesn't exist.
I've tried HTMLUnit but I couldn't make it work with Android. I turned to Android WebView.
Here's my code :
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.loadUrl(url);
final String js = "(function() { " +
"document.getElementById('ColumnLeft_RES_TB_ID').value='" + group + "';" +
"document.getElementById('ColumnLeft_ADD_BTN_ID').click();" +
"document.getElementById('ColumnLeft_GET_BTN_ID').click();" +
"return document.getElementById('ColumnLeft_FEED_URL_TB_ID').value; " +
"})();";
mWebView.setWebViewClient(new WebViewClient(){
public void onPageFinished(WebView view, String url){
if(Build.VERSION.SDK_INT >= 19){
view.evaluateJavascript(js, new ValueCallback<String>() {
#Override
public void onReceiveValue(String s) {
JsonReader reader = new JsonReader(new StringReader(s));
// Must set lenient to parse single values
reader.setLenient(true);
try {
if(reader.peek() != JsonToken.NULL) {
if(reader.peek() == JsonToken.STRING) {
String msg = reader.nextString();
Log.d("DEBUG", "msg : " + msg);
}
}
} catch (IOException e) {
Log.e("TAG", "MainActivity: IOException", e);
} finally {
try {
reader.close();
} catch (IOException e) {
// NOOP
}
}
}
});
}
}
});
Related
I am using a WebView to display a website into my application.
When I'm loading my WebView, I first need to fill the authentification form and then redirect to the original URL.
My WebView keep reloading again and again.
Could anyone explain to me how to use a WebView with "automatic" filling please?
final WebView mWebView;
//Show webview into the app via a popup
AlertDialog.Builder mAlertDialog = new AlertDialog.Builder(context);
mAlertDialog.setTitle(R.string.menuBuyCredit);
mWebView = new WebView(context);
mWebView.getSettings().setDomStorageEnabled(true);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.loadUrl(ConstantsClass.URL_BUY_CREDIT);
mWebView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
//In order to automatically fill the form
final String mJavaScript = "javascript:" +
"document.getElementById('Login').value = '" + ClientSingleton.getInstance().getmLogin() + "';" +
"document.getElementById('Password').value = '" + ClientSingleton.getInstance().getmPassword() + "';" +
"document.getElementById('Btn_Envoyer').click()";
view.loadUrl(mJavaScript);
view.loadUrl(ConstantsClass.URL_BUY_CREDIT);
view.pageDown(true);
}
});
mAlertDialog.setView(mWebView);
mAlertDialog.setNegativeButton(R.string.closeDrawer, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
mAlertDialog.show();
} ```
You should use something like
Put this in global
boolean loadedAlready = false;
inside onPageFinished method
if (view.getUrl().equals(ConstantsClass. URL_BUY_CREDIT) && !loadedAlready) {
loadedAlready= true;
view.load(ConstantsClass.URL_BUY_CREDIT);
}
This is my code for handling login:
wblogin.getSettings().setJavaScriptEnabled(true);
wblogin.loadUrl("http://mywebsite.com/login.php");
wblogin.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
wblogin.loadUrl("javascript: {" +
"document.getElementById('email').value = '" + user_name + "';" +
"document.getElementById('password').value = '" + pass_name + "';" +
"document.getElementById('xyz').click();" +
"};");
}
});
When I logout from the website running in Webview it starts to login automatically
Have you turned on a setting like "Remember my login" for the login page? Maybe it is a default checkbox set?
Second idea: Maybe the auto login after logout happens because of cookies set. Find information how to disable cookies in a webview here and here
There is no really pretty and short way in doing so.
The problem is that everytime you load a new page you run the code for logging in on every single page.
To work around that problem you should save wether you already logged into the application, simplest approach is as follows:
wblogin.setWebViewClient(new WebViewClient() {
private boolean shallLogin = true;
#Override
public void onPageFinished(WebView view, String url) {
if (shallLogin == true) {
wblogin.loadUrl("javascript: {" +
"document.getElementById('email').value = '" + user_name + "';" +
"document.getElementById('password').value = '" + pass_name + "';" +
"document.getElementById('xyz').click();" +
"};");
shallLogin = false;
}
}
});
As the login might fail or the user might move around without being logged in a more proper way would be to register a JS Callback and on page reload check if the login were successful by finding an element by ID which is only visible when logged in like the userimage or something.
...
#Override
public void onPageFinished(WebView view, String url) {
wblogin.loadUrl("javascript: {" +
"window.ANDROID_CALLBACK.login(document.getElementsByClassName('.my-user-img').length > 0);"
"};");
}
...
class LoadListener {
public LoadListener (MyWebViewClient myWebViewClient) {
}
public void login(boolean loginWorked) {
wblogin.shallLogin = !loginWorked;
}
}
...
wblogin.addJavascriptInterface(new LoadListener(wblogin), "ANDROID_CALLBACK")
How to scrape 'handlerbars.js' javascript template in htmlunit 2.21? I try to execute this, but this message shown:
'text/x-javascript-template' is not javascript.
and script does not execute. I execute command page.asXml().
Output text is nothing. Do you know dependency for execute javascript template in Htmlunit? Please help.
This Code
HtmlUnit Config
webClient = new WebClient(BrowserVersion.CHROME);
webClient.getBrowserVersion().setBrowserLanguage("ko-kr");
ConfirmHandler okHandler = new ConfirmHandler() {
#Override
public boolean handleConfirm(Page page, String message) {
logger.info("[Confirm] " + message);
return true;
}
};
AlertHandler alertHandler = new AlertHandler() {
#Override
public void handleAlert(Page page, String message) {
logger.info("[Alert] " + message);
}
};
webClient.setRefreshHandler(new ImmediateRefreshHandler());
webClient.getOptions().setGeolocationEnabled(true);
webClient.getOptions().setRedirectEnabled(true);
webClient.getOptions().setUseInsecureSSL(true);
webClient.getOptions().setCssEnabled(false);
webClient.getOptions().setJavaScriptEnabled(script);
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setTimeout(0);
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
webClient.setConfirmHandler(okHandler);
webClient.setAlertHandler(alertHandler);
page move code
page = webClient.getPage("https://promotions.expediapartnercentral.com/promotions/manageroomandrate.html?htid=" + siteIdx);
webClient.waitForBackgroundJavaScript(1000);
page.asXml() repsonse is empty(script is not execute)
I have a webview with following settings :
mView.getSettings().setLoadWithOverviewMode(true);
mView.getSettings().setUseWideViewPort(false);
mView.getSettings().setJavaScriptEnabled(true);
mView.getSettings().setAllowContentAccess(true);
mView.getSettings().setDomStorageEnabled(true);
After loading a webpage, when I try to execute Javascript:
mView.loadUrl("javascript:document.querySelector('input[type=password]').value ='" + password + "'");
It opens a new tab or window instead of setting the value of password field.
Output of document.querySelector('input[type=password]') (from console) :
<input type="password" name="userpassword" id="userpassword" maxlength="6" style="width: 128px; height: 18px">
I tried executing the same javascript from console. It works!
I have also configured webviewclient:
mView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.d(TAG, " shouldOverrideUrlLoading :" + url);
view.loadUrl(url);
return true;
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
Log.d(TAG, "onPageStarted " + url);
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
Log.e(TAG, "Error: " + description);
}
});
loadUrl method, loads the provided URL in the WebView. What you have to do is execute the evaluateJavascript method.
webView.evaluateJavascript("document.querySelector('input[type=password]').value ='" + password + "'", new ValueCallback<String>() {
#Override
public void onReceiveValue(String value) {
/// This callback is called after a result is returned by the script.
}
});
As of Android Kitkat (4.4, API level 19), you can use evaluateJavascript.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webView.evaluateJavascript("js_code", null);
} else {
webView.loadUrl("javascript:js_code");
}
You are forgetting quotes on your CSS selector.
It should be:
document.querySelector('input[type="password"]');
See jsfiddle
I am trying to load data into android webview using
webview.loadDataWithBaseURL("", htmlcontent, "text/html", null, "");
a method returns htmlContent from a StringBuilder which populates html data.
I have enabled javascript and set webChromeClient as follows
webview.getSettings().setJavaScriptEnabled(true);
webview.setWebChromeClient(new WebChromeClient());
webview.addJavascriptInterface(new JSClass(), "Android");
my interface to javascript:
class JSClass {
public void getHTMLContent(String html)
{
Log.i(Global.TAG, "HTMLContentReceived: "+html);
}
}
and my javascript in html page:
<script type="text/javascript">
var ele = document.getElementsByClassName('test');
for(var i=0;i<ele.length;i++){
ele[i].onclick = function(){
window.Android.getHTMLContent(this.innerHTML);
}
}
</script>
but somehow the javascript is not returning any value.
It works fine with loadData(url) where url is a simple webpage in assets folder
Please help
Thanks in advance
You don't have any baseURL to use, since you're loading a dynamical generated HTML.
For this reason webview.loadData(htmlcontent, "text/html", null); should be more than enough.
Javascripts don't throw any exceptions in Java code. Remember that JS is not that type-safe/strict as Java code ... My way of doing is to put logs between sensitive Javascript calls to see if that line passes and to check values. Since you didn't provide the HTML, I would setup the WebChomeClient and override the onConsoleMessage:
webview.setWebChromeClient(new MyChromeClient());
private class MyChromeClient extends WebChromeClient {
#Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
String message = consoleMessage.message() + " -- line " + consoleMessage.lineNumber();
switch (consoleMessage.messageLevel()) {
case ERROR:
logErrorMessage(message);
break;
default:
logInfoMessage(message);
break;
}
return true;
}
private void logInfoMessage(String message) {
Log.i("JSTag", message);
}
private void logErrorMessage(String message) {
Log.e("JSTag", message);
}
}
From your JavaScript you would then call for example: console.log('check my value:' + (ele != null)). More info on this here.
Looking at your JavaScript code, I can't understand to what points this.innerHTML.