Running Javascript from WebView onPageFinished Not Working - javascript

I am unable to get some javascript to run successfully in the onPageFinished() method of my WebViewClient.
I am porting over an iOS app and they are doing the same thing, waiting for page to load, then using Javascript to hide some of the HTML items.
I don't use Javascript much but am not sure why it keeps failing to work correctly. Right now what happens is the page loads, then onPageFinished is called, and the page reloads and the text 'none' shows up in the top left corner.
I've attached my WebViewClient and then all the WebView setup I am doing in onCreate too. I have also included some commented out code of what I have tried before and that code also did not work.
// Manages the behavior when URLs are loaded
private class Browser extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url, headers);
return true;
}
#JavascriptInterface
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
//view.loadUrl("javascript:document.getElementById('navbar_bg').style.display = 'none';");
//webView.loadUrl("javascript:document.getElementById(\"content\")");
view.loadUrl("javascript:document.getElementById(\"navbar_bg\").style.display=\"none\";");
}
}
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mobile_homework);
ButterKnife.bind(this);
homeworkId = getIntent().getIntExtra(HOMEWORK_ID_EXTRA, 0);
// Configure related browser settings
webView.getSettings().setLoadsImagesAutomatically(true);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
// Enable responsive layout
webView.getSettings().setUseWideViewPort(true);
// Zoom out if the content width is greater than the width of the viewport
webView.getSettings().setLoadWithOverviewMode(true);
//allow manual zoom and get rid of pinch to zoom
webView.getSettings().setSupportZoom(true);
webView.getSettings().setBuiltInZoomControls(true);
webView.getSettings().setDisplayZoomControls(false);
// Configure the client to use when opening URLs
webView.setWebViewClient(new Browser());
}
Edit: The final fix was to set variables to each change because it returns a variable when you change any item.
Final working code looked like:
view.loadUrl("javascript:var header = document.getElementById('header_bg_first').style.display='none'; " +
"var navbar = document.getElementById('navbar_bg').style.display='none'; " +
"var footer = document.getElementById('footer').style.display='none'; " +
"var iframePadding = document.getElementById('flcn_assignment').style.paddingRight='10px';");

Related

WebView loads URL 10 times slower than phone's Chrome browser

I've been trying to figure this one out for quite a while, and yet haven't found a solution.
Inside my app I'm extracting a website's HTML through an invisible WebView component. I do not need to view the website, just get the html it loads. The website uses JavaScript to load all of its content, and therefore I need a full web renderer in order to execute that JavaScript. In its current form, I'm overriding the WebViewClient's onPageFinished method to inject JavaScript that dumps the html into a JavaScriptInterface which then processes it.
My main issue here is that when I load this URL inside my app it would take about 8 seconds, whereas loading the exact same URL in the phone's chrome browser it takes less than a second. Any suggestions as to what might be the problem?
If it could be of any help, the JavaScript that gets executed stores a cookie inside the WebView, and then tries to retrieve it, and only if it finds said cookie (which has a short expiration time) it would load the site's HTML. In this case it actually loads data formatted with JSON (about 370k characters).
Relevant WebView code:
private void initWebView(View view) {
class JSInterface{
#JavascriptInterface
public void processHTML(String scheduleJSONResponse){
if(scheduleJSONResponse.length() > 10000){
Log.d(LOG_TAG, "Finished loading JSON");
}
}
}
webView = (WebView) view.findViewById(R.id.fragment_movies_web_view);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new JSInterface(), "Android");
webView.setWebViewClient(new WebViewClient(){
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
Log.d(LOG_TAG, "Page finished loading");
webView.loadUrl("javascript:window.Android.processHTML(document.getElementsByTagName('html')[0].textContent);");
}
});
webView.loadUrl(url);
}
As for why I check that the length is more than 10k characters: Sometimes onPageFinished would get called more than once, with the first call being before the JavaScript is executed, and so I get HTML containing the script to be executed which isn't what I need.
Thanks in advance for any help!
A logcat to demonstrate the issue:
08-18 22:32:23.623 26238-26238/com.michaelsvit.kolnoa I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy#1e4dc08f time:502735009
08-18 22:32:23.638 26238-26238/com.michaelsvit.kolnoa W/cr_BindingManager: Cannot call determinedVisibility() - never saw a connection for the pid: 26238
08-18 22:32:31.336 26238-26238/com.michaelsvit.kolnoa D/MovieGridFragment: Page finished loading
Current code after simplifying it:
private void initWebView(View view) {
class JSInterface{
#JavascriptInterface
public void processHTML(String scheduleJSONResponse){
if(scheduleJSONResponse.length() > 10000){
Log.d(LOG_TAG, "Finished loading JSON");
}
}
}
webView = (WebView) view.findViewById(R.id.fragment_movies_web_view);
webView.getSettings().setJavaScriptEnabled(true);
//webView.addJavascriptInterface(new JSInterface(), "Android");
webView.setWebViewClient(new WebViewClient(){
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
Log.d(LOG_TAG, "Page finished loading");
//webView.loadUrl("javascript:window.Android.processHTML(document.getElementsByTagName('html')[0].textContent);");
}
});
}
through an invisible WebView component..
What when it is visible?
Try it!

Set TextBox value with js injection in a WebView

Using Android Studio I am trying to set the value of a textbox in a login form of a web page which is not mine.
Here's the webView i use to work on the page:
final WebView webView = (WebView) findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebChromeClient(new WebChromeClient());
webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
webView.setWebViewClient(new WebViewClient()
{
#Override
public void onPageFinished(WebView view, String url)
{
webView.loadUrl("javascript: document.getElementById('j_password').value = 'something'");
}
});
webView.loadUrl("http://sg18224.scuolanext.info/");
the problem is that when the page has finished loading instead of setting the textbox value, the whole page becomes white and it only displays the string i was trying to set as value (in this case "something").
If i include the js line in an alert like this:
webView.loadUrl("javascript: alert(document.getElementById('j_password').value = 'something')");
it works! But also displays an alert i don't want to display.
This should help you:
final String js = "javascript:document.getElementById('j_password').value='something';";
webView.setWebViewClient(new WebViewClient() {
#Override
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) { }
});
} else {
view.loadUrl(js);
}
}
});
I am not sure with this answer but you may try it. typically it should be the answer. Long time no interaction with javascript though.
you may try
webView.loadUrl("javascript: document.getElementById('j_password').innerHTML = 'something'");
please comment if its not working.

javascript and webview in android

I am a beginner in android platform and making an app with help of webview and javascript.when I run my code on real device it displays nothing.any help would be appreciable.
Here is my code:
public class MainActivity extends AppCompatActivity {
WebView view_1,view_2;
ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().hide();
String url_1="<script type=\"text/javascript” src=\"http://ds.claymcenter.com/embed.js\">\n" +
"requestAd('Rh8uGpcrlYMjXN1s', 'banner', 'ads', '320' , ‘50');\n" +
"</script>\n" +
" \n" +
"<div id='ads'></div>";
String url_2="https://paytm.com/";
view_1 = (WebView) findViewById(R.id.webViewGoogle);
view_2 = (WebView) findViewById(R.id.webViewFacebook);
view_1.getSettings().setJavaScriptEnabled(true);
view_1.loadData(url_1, "text/html", null);
view_2.getSettings().setJavaScriptEnabled(true);
view_2.loadUrl(url_2);
imageView = (ImageView) findViewById(R.id.imageView);
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
view_1.reload();
view_2.reload();
}
});
} }
I always have a hell of a time trying to get things like this to work, and I don't remember exactly how I did some of this stuff, but here are some ideas:
First thing to try: Wrap that string in url_1 in <html><body>...</body></html> tags.
Second thing to try: You might have to use some kind of "onDocumentReady" event to call your javascript when the js file is completely loaded.
Third thing thing to try: Split out the function call like so:
String url_1="<script type=\"text/javascript\” src=\"http://ds.claymcenter.com/embed.js\">\n" +
"</script>\n" +
"<div id='ads'></div>";
String call = "javascript:requestAd('Rh8uGpcrlYMjXN1s', 'banner', 'ads', '320' , ‘50');\n"
Load the html with the js file then use WebViewClient.onPageFinished() to see when to load the javascript call (don't cut & paste this code, this is just a template):
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
// TODO: need to find out what is in url when html with js file loads
if (urlMatches()) {
view.loadData(call, "application/javascript", null); // not sure about the mime type
}
}
});
This is like "onDocumentReady" but doing it in the Java code.
You might be getting stuck because of this statement from the loadData docs:
Note that JavaScript's same origin policy means that script running in a page loaded using this method will be unable to access content loaded using any scheme other than 'data', including 'http(s)'. To avoid this restriction, use loadDataWithBaseURL() with an appropriate base URL.
So the last thing to try would be using loadDataWithBaseURL.

Unable to execute Js code in WebView in Cordova Project

I have two activity, one main activity(A) is an CordovaActivity, then I use intent to start another activity(B), in B i have an WebView(not CordovaActivity), and after I use this webview to load a simple webpage (alert something), I found the js code is not executed at all, even if I enable javascript by calling setttings.setJsenabel(true);
I start activity B from A
Load Url from webview in Activity B
simple web page
in the device, it does not alert anything
However, if I change the webview to CordovaWebView instead of the original Android native one, it works.....
That's because plain WebView doesn't support showing alerts by itself. You need to provide a WebChromeClient to it that implements WebChromeClient.onJsAlert method. For example:
mywebView.setWebChromeClient(new WebChromeClient() {
#Override
public boolean onJsAlert(
WebView view, String url, String message, final JsResult result) {
new AlertDialog.Builder(view.getContext())
.setTitle("Alert")
.setMessage(message)
.setPositiveButton("Ok",
new AlertDialog.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
result.confirm();
}
}).setCancelable(false).create().show();
return true;
}
});

Using Javascript in webview

So, reading around i read that i could "inject" javascript into a loaded webpage to programatically fill a website's form, so i tried the following:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
WebView WebView;
WebView = (WebView) findViewById(R.id.webview);
WebView.setWebViewClient(new HelloWebViewClient());
WebView.getSettings().setJavaScriptEnabled(true);
WebView.getSettings().setBlockNetworkImage(false);
WebView.loadUrl("http://www.kingsage.es");
String username = "XXX";
String Password = "YYY";
WebView.loadUrl("javascript:document.getElementById('login_player').value='"+username+"';javascript:document.getElementById('login_passwd').value = '"+Password+"';");
}
However, when i run this on the emulator i get an error as if the website could not be found. if i turn off the second loadUrl method i load the website, but i need to fill the login form programatically!, i figure i am doing something wrong but i haven't found and answer reading around. Any help would be appreciated!!
you need to wait until the webpage is loaded (use WebViewClient) then execute your javascript
webView.setWebViewClient(new WebViewClient(){
#Override
public void onPageFinished (WebView webView, String url)
{
webView.loadUrl("javascript:document.getElementById('login_player').value='"+username+"';javascript:document.getElementById('login_passwd').value = '"+Password+"';");
}
});
make also sure that you execute only once, not on every onPageFinished Event
I like JeanLuc's suggestion and it worked for me 98% of the way. I still needed to automatically log the user into the web page once their username and password had been entered so I did the following and its worked well, except for trying to remove the "do you want to remember the password' message.
#Override
public void onPageFinished (WebView webView, String url)
{
webView.loadUrl("javascript:document.getElementById('Login1_UserName').value='"+userName+"';javascript:document.getElementById('Login1_Password').value = '"+password+"';");
webView.loadUrl("javascript:document.getElementById('Login1_LoginButton').click();");
}
The second line selected the 'login' button and logged them in automatically. Hope it helps someone else.
Here is how I acheived it in my scenario where I had to browse a page, fill text boxes and submit.
WebView webView = FindViewById<WebView>(Resource.Id.webEspView);
webView.SetWebViewClient(new Client());
webView.Settings.JavaScriptEnabled = true;
webView.LoadUrl("http://192.168.4.1")
Then added the Client class and overloaded onPageFinished() method.
public class Client : WebViewClient
{
public override void OnPageFinished(WebView view, string url)
{
base.OnPageFinished(view, url);
string ssid = Variables.GetInitialUsername();
ssid = ssid.Trim(new char[] {'\"'});
string pass = Variables.GetInitialPassword();
var script = $"document.getElementById(\"clientId\").value = \"{ssid}\";" +
$"document.getElementById(\"branchId\").value = \"{pass}\";" +
"document.querySelector('button[type=\"submit\"]').click()";
view.LoadUrl($"javascript: {script}");
}
}
Hope it helps.

Categories