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);");
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");
I using WebView to show this website
http://app.wlojii.com
I want to make control panel in notification bar to play/stop music.
The problem i cant find the function that play/stop the music.
I inspected the button element and tried some variants of functions unsuccessfully (play, play(), player.play()), and i used this method to call the functions:
mWebView.loadUrl("javascript: ...")
I am not so familiar with JavaScript and web, i need some help.
Pavel
I have added a git repo with the working code https://github.com/premithk/webviewclickeventexample
The problem last time was that getElementsByClassName returns an array. So i have changed the code to
mWebview.loadUrl("javascript(function({l=document.getElementsByClassName('mejs-playpause-button');
e=document.createEvent('HTMLEvents');
e.initEvent('click',true,true);
l[0].dispatchEvent(e);})()");
Any ways the code in repo works such that there is a button (native) that will act as play/pause
Register a Javascriptinterface or use this library.
https://github.com/lzyzsd/JsBridge/blob/master/README.md
The library acts as a bridge between webview and the Java part of the app
Yes, The idea is to inject an object to the JS part and use that as a bridge to call a function inside the native part. Have updated the git repo reflecting the change. Only thing is that before we inject the event listener we have to make sure the page is fully loaded, so it might take some time. So first thing is to add the interface mWebview.addJavascriptInterface(new JSInterface(), "jsnativebridge");
Then define the class
private class JSInterface {
#JavascriptInterface
public void playPauseClicked(String string) {
Log.d("console", "" + string);
}
}
Then wait for page load and add the event listener like below
mWebview.setWebViewClient(new WebViewClient() {
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Toast.makeText(activity, description, Toast.LENGTH_SHORT).show();
}
public void onPageFinished(WebView view, String url) {
Log.d("console", "" + "loaded");
mWebview.loadUrl(
"javascript:(function() { " +
"var ch=document.getElementsByClassName('mejs-playpause-button');" +
"ch[0].addEventListener('click', function(){" +
" jsnativebridge.playPauseClicked('Yes');" +
"});"+
"})()"
);
}
});
You can refer the git repo, have added a working demo.
Cheers
I have a WebView in Android. I load page in webview from url and i want to hide some elements that the webpage actually has. I did it after page has loaded. And it give me only 'none' text in the webview nothing more. I tried as follows
#Override
public void onPageFinished(WebView view, String url) {
view.loadUrl("javascript:window.document.getElementsByClassName('cdo-search')[0].style.display='none';");
if (pd.isShowing()) {
pd.dismiss();
}
}
How can we hide element that webpage actually has?
My previous answer was not it. after testing I found out that this solved the problem. The issue is not with android or webview. it's the way url based javascript execution works.
#Override
public void onPageFinished(WebView view, String url) {
view.loadUrl("javascript:function a(){window.document.getElementsByClassName('cdo-search')[0].style.display='none';}; a()");
if (pd.isShowing()) {
pd.dismiss();
}
}
I'm not entirely sure what's the reason but if i had to guess, what ever is returned by the statement you write in this format other than undefined, will be set as the document's html.
in other words, you cannot do any kind of assignment operation in outer scope, while executing JS in this format.
my testing method:
i put these two in the address-bar of this particular Stack overflow page.
javascript:function a(){window.document.getElementsByClassName('question-hyperlink')[0].style.display='none';}; a()
javascript:window.document.getElementsByClassName('question-hyperlink')[0].style.display='none';
in the first attempt the qustion disappeared as expected but in second one, the page turned into "none".
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(); })()");
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");");