Android WebView call JavaScript function - javascript

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

Related

Android WebView and JavaScript programmtically clicking button not working

I have a very simple use case i.e to programmatically call a button of a web page loaded inside my webview. Below is the code
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setAppCacheEnabled(false);
webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient(){
#Override
public void onPageFinished(WebView view, String url) {
//super.onPageFinished(view, url);
switch (view.getOriginalUrl()){
case Properties.LOGIN_URL:
webView.evaluateJavascript(
"javascript:" +
"var usernameField = document.getElementById('loginUserName');" +
"usernameField.value = '" + Properties.USERNAME + "';" +
"var passwordField = document.getElementById('loginPassword');" +
"passwordField.value = '" + Properties.PASSWORD + "';", null
);
webView.evaluateJavascript(
"javascript:" +
"document.getElementById('loginButton').click();", new ValueCallback<String>() {
#Override
public void onReceiveValue(String s) {
}
}
);
break;
}
}
});
view.loadUrl(Properties.LOGIN_URL);
The username and password field injection is working fine but the code to perform button click isn't working.
I have searched a lot and experimented a lot but no luck, Is this even possible?
EDIT:
The URL I'm accessing is private to our organization, is on http and not secured, not sure if it's relevant.
I have tried another public page with login fields and the same code works and the button gets clicked successfully.
Okay I found the reason. So the onPageFinished was getting called while all the DOM elements are not loaded hence the javascript was failing. For time being it to work I have added a delayed Handler with 5 sec delay and it worked. The right solution should be to check for the page to complete to load (may be use jquery to check when the document is ready).
You can handle the webview button click this way
#JavascriptInterface
public void handleClick(String id) {
startActivity(new Intent(mContext, MainActivity.class));
}
In javascript
Android.handleClick(_id);

Executing JavaScript instructions after loading HTML file in a WebView

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");

Pass variable from plugin back to cordova

The Cordova plugin I'm using plays a VR video file, and is called via GoogleVRPlayer.playVideo(videoUrl, fallbackVideoUrl).
Somewhere in the .java files of the plugin, there's:
#Override
public void onLoadError(String errorMessage) {
// I want to know if this function is executed
Log.e(TAG, "Error loading video: " + errorMessage);
}
Basically, when the video fails to load, I want to set a variable in my javascript in cordova to "error", for example var video_status = "error", so I can use this information later on in my app.
I've found some answers that would possibly solve my problem, but I can't seem to integrate it the right way. I have very little experience with native plugins and Java.
Anyone who can help me with this?
Since the Cordova plugin GoogleVRPlayer launches a new Activity (VrVideoActivity), I would use a Singleton class as an interstitial data bridge between the two Activites to hold the error message.
This is because, on launching the video player activity, your app (the Cordova activity) is paused in the background and will only resume execution once the video player activity is closed.
By using the intermediate class, both the Cordova plugin and the video activity are able to share data.
So I would do something like this:
Create a new file called CordovaBridge.java in cordova-vr-player/src/android/java/neotrino/
package com.neotrino;
public class CordovaBridge {
private String errorMsg = null;
public String getErrorMsg() {return errorMsg;}
public void setErrorMsg(String errorMsg) {this.errorMsg = errorMsg;}
private static final CordovaBridge holder = new CordovaBridge();
public static CordovaBridge getInstance() {return holder;}
}
Modify GoogleVRPlayer.java as follows:
import com.neotrino.CordovaBridge;
#Override
public void onResume(boolean multitasking) {
cordova.getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
String errorMsg = CordovaBridge.getInstance().getErrorMsg();
if(errorMsg != null){
webView.loadUrl("javascript:window.video_status = '"+errorMsg+"'");
}
}
});
}
Modify VrVideoActivity.java as follows:
import com.neotrino.CordovaBridge;
#Override
public void onLoadError(String errorMessage) {
// I want to know if this function is executed
Log.e(TAG, "Error loading video: " + errorMessage);
CordovaBridge.getInstance().setErrorMsg(errorMessage);
}
I haven't tested the above code, but in terms of an approach it should give you an approximation on which to base your solution.

onPageFinished Javascript WebView

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);");

WebView: Wait until input field exists before starting a javascript function

I have a function to load on a website once its two input fields are loaded.
function setCredentials(name, key){
document.getElementById('zoneIdent').value=name;
document.getElementById('zonePwd').value=key;
GInterface.traiterEvenementValidation();
}
It is contained in a auto.html in the *root of project*/assets/www/ folder. (I tried putting it in the /res/assets/www/ folder but I get the following from AndroidStudio : Android Resource Packaging: [QuickPronote] invalid resource directory name: C:\Users\Yann\DEV\workspace\QuickPronote\res/assets
I have to use this function on this type of website : http://81.192.152.242:8001/mobile.eleve.html?FD=1. Note that the website doesn't load quickly.
I'm using the following code :
myWebView.loadUrl(String.valueOf(url));
myWebView.loadUrl("javascript:setCredentials('" + name + "','" + key + "')");
where url, name and key are strings that user has defined.
I tried it, even with dummy text, the two fields are completed and the validation action should be launched but it seems that either the function was loaded too quickly, or either it wasn't lauched at all, because once the website is fully loaded, there is neither the values apearing or an error message saying the credentials are wrong.
If your solution includes the use of external plugin-ins/libs like JQuery, tell me so.
PS: Not using PhoneGap or anything.
Here's where I got my code from in the first place.
First, make sure you've set javascript enabled on the webview,
webView.loadUrl(String.valueOf(url));
webView.getSettings().setJavaScriptEnabled(true);
then add a listener to load the name / key once the page has finished.
webView.setWebViewClient(new WebViewClient(){
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
view.loadUrl("javascript:setCredentials('" + name + "','" + key + "')");
}
});
edit:
I think I found your problem. The lack of the javascript "setCredentials" method in the page: http://81.192.152.242:8001/mobile.professeur.html?FD=1... did you forget to add that?
when I change the above onPageFinished method to this:
myWebView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
myWebView.loadUrl("javascript:document.getElementById('zoneIdent').value='test name';");
}
});
the "Identifier" field is populated with "test name" on that page.

Categories

Resources