I am having a bit of trouble getting my application to correctly run some JS on a page using the onPageFinished method.
The code below is contained within a class I've created that extends AsyncTask to fetch and parse a JSON file held elsewhere.
I am able to fetch the JSON file correctly, parse the data and the url for the WebView is obtained and set. Everything works loads as it should until I attempt to run some JS with the onPageFinished method.
//onPostExecute method runs when the doInBackground method is completed
#SuppressLint("SetJavaScriptEnabled")
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
//Casting as WebView as findViewById doesnt explicity return a value type.
webView = (WebView) findViewById(R.id.webView);
//Obtaining the websettings of the webView
WebSettings webViewSettings = webView.getSettings();
//Setting Javascript enabled
webViewSettings.setJavaScriptEnabled(true);
webView.setWebViewClient(new webViewClient(){
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
webView.loadUrl("document.getElementById('field_133').value = 'Test';");
Log.d("onPageFinished", "The Page has finished loading");
}
});
//Obtaining the first item in the cellRef List Array - From here we will access the Url data for the train operator.
parsedUrl = cellRef.get(0).getUrl();
//load the page we parsed from online file
webView.loadUrl(parsedUrl);
Log.d("loadUrl", "Now load the parsed Url");
}
All I am looking to do at the moment is test that the JS can correctly populate a textbox once the page has loaded with the value of "Test" - However, the WebView appears to be stuck in a loop of loading & refreshing (seeing repeated logcat prints of "The page has finished loading") when trying to run:
webView.loadUrl("document.getElementById('field_133').value = 'Test';");
Is this the correct way of trying to inject some JS into the WebView in Android? Apologies if there is something obvious missing, the majority of my experience lies in Swift.
Any help would be appreciated.
Thanks
Try "javascript:" before the code.
I use this, works perfectly:
loadUrl("javascript:(function() { document.getElementsByTagName('video')[0].play(); })()");
Related
I realized an Android program that loads a HTML file into a WebView, the HTML file loads Leaflet.js that shows different styles of maps based on the provider you gave it.
I load the page in the OnCreate() method with this instruction:
myWebView.loadUrl("file:///android_asset/test.html");
After that, I need to take the list of different maps from a Handler (with class name JavascriptInterface.java) that I added to the WebView like this:
myWebView.addJavascriptInterface(new JavaScriptInterface(this, myWebView), "MyHandler");
The final code needs to look like this:
myWebView.loadUrl("file:///android_asset/test.html");
myWebView.loadUrl("javascript:window.MyHandler.getMaps()");
The problem is that the first loadUrl() isn't fast enough, so the second loadUrl goes before the map is initialized, causing a lot of problems.
The temporary, and also horrible, solution that I found is to hold the second loadUrl for 1 second before executing it, like this:
myWebView.loadUrl("file:///android_asset/test.html");
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
// Actions to do after 1 second
myWebView.loadUrl("javascript:window.MyHandler.getMaps()");
}
}, 1000);
There is a better way of executing an instruction after another one? I already tried using an ASyncTask, but there is the possibility that I didn't implemented it well.
Please call myWebView.loadUrl("javascript:window.MyHandler.getMaps()"); inside Webview onPageFinished event.
myWebView.setWebViewClient(new WebViewClient() {
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
Log.d("WebView", "onPageStarted " + url);
}
#Override
public void onPageFinished(WebView view, String url) {
myWebView.loadUrl("javascript:window.MyHandler.getMaps()");
}
});
myWebView.loadUrl("file:///android_asset/test.html");
Good Day,
I have a webview in Android app which loads a resource that uses html and javascript:
WebView.getSettings().setJavaScriptEnabled(true);
//webView.getSettings().setDomStorageEnabled(true);
//webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
//webView.getSettings().setLoadWithOverviewMode(true);
//webView.getSettings().setUseWideViewPort(true);
//webView.getSettings().setBuiltInZoomControls(true);
webView.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
//webView.loadUrl("file:///android_asset/Index.html");
webView.loadUrl("http://foo.com/newbilltemplate/");
The comments show you what I've tried so far. Also I tried local and online resource and the problem still exist.
The index.html page doesn't use Javascript but when a button is clicked it uses some Javascript calculations to display in the next page.
Thanks,
I feel pretty stupid for having to ask this but I can't for the life of me get it to work.
So I've searched around and found lots of help, guides, and etc for using the onPageFinished function in WebViewClient and my code is largely based on these.
Basically I have a function that is supposed to load a web page and then hides certain elements on that page with the onPageFinished. Instead of actually doing this though it hides the entire page and the webview displays the text "none".
When I comment out the onPageFinished function the webview loads the page just fine which leads me to believe that it has to be the javascript but according to the w3c site my javascript is correct for what I want to do...
So my question is this, Does anyone see the problem with the below code and/or anyone have a suggestion for something else that might accomplish my above stated goals?
Any help in getting this to work would be greatly appreciated.
Code:
public class MainActivity extends AppCompatActivity{
private WebView browser;
private String url = "https://www.google.com";
< onCreate calls cleanPage and other stuff >
public void cleanPage() {
browser = (WebView) findViewById(R.id.webview);
browser.getSettings().setJavaScriptEnabled(true);
browser.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
browser.loadUrl("javascript:document.getElementById('lga').style.display='none';");
}
});
browser.loadUrl(url);
}
}
Notes:
-The above uses google as an example, lga is the id of the google banner div.
-browser and url are global because once I get cleanPage working I will add in other functions that will alter them as needed.
You need to add void(0); at the end of your javascript: URL. Otherwise, WebView replaces your current page with the result of the JS evaluation (in your case, that is the string "none").
So change this:
browser.loadUrl("javascript:document.getElementById('lga').style.display='none';");
to:
browser.loadUrl("javascript:document.getElementById('lga').style.display='none';void(0);");
I have a webview with HTML webpage which is downloaded from server and i populate dynamic data and add rows of information to this webpage. I have used the following code on that webpage to enable javascript:
class JSClass {
Context jsContext;
JSClass(Context c){
jsContext = c;
}
public void getHTMLContent(String info)
{
Log.i(TAG, "Info: "+info);
}
}
WebView webview = (WebView) findViewById(R.id.webView);
webview.loadDataWithBaseURL("", htmlcontent, "text/html", "utf-8", "");
webview.getSettings().setJavaScriptEnabled(true);
webview.setWebChromeClient(new WebChromeClient());
webview.addJavascriptInterface(new JSClass(this), "Android");
webview.loadUrl("javascript:"+
"var rows = document.getElementsByClassName('info');"+
"if(rows !== null){"+
"for(var i=0;i<rows.length;i++){"+
"rows[i].onclick = function(){"+
"var workId = 0;"+
"workId = parseInt(this.cells[0].innerHTML);"+
"window.Android.getHTMLContent(workId);"+
"}}}"
);
when i click on any row, i cal an intent to download images from the server depending on the row data. It works fine on first click, but the second time i click, the application closes without any error. I don't understand the reason. Please help. Thanks in advance
I think you need to use loadDataWithBaseURL again instead of just loadUrl.
See this link. There is a section explaining loadData that says:
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.
FINALLY!! fixed it.. the adapter was holding previously downloaded images as well as the images downloaded during second click and i don't understand why the application was closing without giving any memory leaks as well.. anyways its working fine now after using
adapter.clear();
or re-initializing the adapter to null after all the image thumbs are downloaded(i do not know if this is very efficient). After the adapter is cleared, use
adapter.notifyDataSetChanged();
I have been able to get content out of WebView using javascript and loadUrl() method having specified an interface thats called from javascript string that is injected into WebView.The problem is that this only works for me when the loadUrl() method is present in onPageFinished() method in the WebView client. What I want to do is I want to get the content out of the WebView (with the content already loaded). The WebView is in an activity instrumentation test case and I can for instance use findAll() method and that works fine. For some reason I can not use loadUrl() and get the desired behaviour (which is injecting javascript and getting content out of the WebView with a help of an interface).
PLease help.
Thanks
Pawel
EDIT:
Just adding code to show what I am doing exactly:
Yes I understand that but my problem is that I am trying to do it within a test case this way:
public void testWebView() throws Exception {
solo.sleep(3000); // wait for views to load on the screen
WebView a=null;
ArrayList<View> views = solo.getCurrentViews(); // I am using solo object to get views for the screen currently loaded
for(View s:views)
{
if (s instanceof WebView)
{
a = (WebView)s; // this is where I get my WebView
}
}
Instrumentation inst = getInstrumentation();
inst.runOnMainSync(new Runnable()
{
public void run()
{
int d =a.findAll("something"); // this method runs fine on the object and i get the desired result
WebSettings settings = a.getSettings();
settings.setJavaScriptEnabled(true);
a.loadUrl("javascript:document.location = document.getElementById('google').getAttribute('href')"); // this javascript is never executed and that is my problem
}
});
}
You can inject javascript in a loaded page much the same way you can do it in desktop browsers - via inline javascript entered into navigation bar.
Bind some Java object so that it can be called from Javascript with WebView:
addJavascriptInterface(javaObjectExposed, "JSname")
Force execute javascript within an existing page by
WebView.loadUrl("javascript:window.JSname.passData("some data from page");");