Is it possible to call JavaFx application from javaScript? Now i'm able to call an html file from javaFX using
webview = new WebView();
webview.setVisible(true);
webengine = webview.getEngine();
webengine.setJavaScriptEnabled(true);
File file = new File("C:\\sample.html");
System.out.println(file.exists() + " file exitence");
webengine.load(file.toURI().toURL().toString());
if possible please help me. i'm new to java and JavaFx.
In JS: alert("HEAD;DATA");
In Java:
WebView webView = new WebView();
final WebEngine engine = webView.getEngine();
engine.setOnAlert(new EventHandler<WebEvent<String>>() {
public void handle(WebEvent<String> e) {
String[] infs = e.getData().split(";");
if(infs[0].equals("HEAD")){
System.out.println(infs[1]);
}
}
});
Related
I can't get the Java / Javascript bridge to work on Java11 and Java13. The bridge seems to work fine i Java8 and Java10.
Here is essentially the same code as https://stackoverflow.com/a/34840552/11329518, which again works for me on Java8 and Java10:
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import javafx.application.Application;
import javafx.concurrent.Worker.State;
import javafx.scene.control.ButtonType;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebEvent;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import netscape.javascript.JSObject;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
JavaBridge bridge;
WebEngine webEngine;
#Override
public void start(Stage primaryStage) throws MalformedURLException {
final URL url = new File("C:/test.html").toURI().toURL();
WebView webView = new javafx.scene.web.WebView();
webEngine = webView.getEngine();
webEngine.load(url.toExternalForm());
webEngine.setJavaScriptEnabled(true);
webEngine.setOnAlert(Main::showAlert);
webEngine.getLoadWorker().stateProperty().addListener((ov, oldState, newState) -> {
if (newState == State.SUCCEEDED) {
System.out.println("READY");
JSObject jsobj = (JSObject) webEngine.executeScript("window");
bridge = new JavaBridge();
jsobj.setMember("bridge", bridge);
}
});
primaryStage.setScene(new javafx.scene.Scene(webView, 300, 300));
primaryStage.show();
}
// Shows the alert, used in JS catch statement
private static void showAlert(WebEvent<String> event) {
javafx.scene.control.Dialog<ButtonType> alert = new javafx.scene.control.Dialog<>();
alert.getDialogPane().setContentText(event.getData());
alert.getDialogPane().getButtonTypes().add(ButtonType.OK);
alert.showAndWait();
}
public class JavaBridge {
public void hello() {
System.out.println("hello");
}
}
}
with test.html containing the Javascript:
<button onclick="try{bridge.hello();}catch(err){alert(err.message);}">call java</button>
What's going on?
I get the following error when clicking the button:
bridge.hello is not a function. (In 'bridge.hello()', 'bridge.hello' is undefined)
I can't reproduce your issue with JavaFX 13 or 14-ea+6, using Java 11 (OpenJDK 11.0.2) or Java 13 (OpenJDK 13).
However I can reproduce the issue, if I remove the strong reference to JavaBridge and I use Java 11.
This:
jsobj.setMember("bridge", new JavaBridge());
fails with the same error you have posted, with Java 11. But when using Java 13 (OpenJDK 13), that works fine (and also with Java 12).
Are you using other Java vendors? Can you try with OpenJDK https://jdk.java.net/13/?
There are two things that resolved this issue with OpenJDK 14 and JavaFx 14
Hard Reference to Bridge Object
bridge = new JavaBridge(); // create Bridge before hand
webEngine.getLoadWorker().stateProperty().addListener((ov, oldState,
newState) -> {
if (newState == State.SUCCEEDED) {
System.out.println("READY");
JSObject jsobj = (JSObject) webEngine.executeScript("window");
jsobj.setMember("bridge", bridge);
}
});
Use Bridge in Javascript/HTML page after the page is loaded
window.onload = function() {
bridge.hello();
}
I'm using a JavaScript interface to communicate with a JavaScript library (running in an Android webview) and the native side. This works great, except when sending over large, stringified JSON objects. It is incredibly slow, taking as long as 20 seconds. Is there a way to remedy this?
Edit: here's the JS Interface on the native side:
public class JSInterface {
private Activity activity;
public JSInterface (Activity act) {
this.activity = act;
}
public void someMethod(String message) {
try {
JSONObject obj = new JSONObject(message);
// Do stuff...
} catch (JSONException ex) {
showError(ex.getMessage());
}
}
}
And here's how the webview uses it:
$(document).ready(function() {
try {
JSInterface.someMethod(JSON.stringify(largeJsonObject));})
} catch(err) {
console.log('error: ' + err.message);
}
});
The Webview is initialized like this:
WebView mainWebView = (WebView) findViewById(R.id.activity_main_webview);
WebSettings webSettings = ProjectData.mainWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
JSInterface mainJSInterface = new JSInterface(this);
mainWebView.addJavascriptInterface(mainJSInterface, "JSInterface");
mainWebView.setWebChromeClient(new WebChromeClient());
mainWebView.setWebViewClient(new WebViewClient());
mainWebView.loadUrl("file:///android_asset/web_view/index.html");
I want to list all the files in a specific folder in my a Javascript that I use to manipulate my HTMLs.
I'm using a java method to list all the files that I to display.
Here's the the class.
public class JavaScriptInterface {
private Context context;
public JavaScriptInterface(Context current){
this.context = current;
}
#JavascriptInterface
public List<String> getFileNames(String path){
String [] files;
try {
files = context.getAssets().list(path);
ArrayList<String> testName = new ArrayList<String>();
for (String file: files) {
Log.d("File name: ", file);
file = file.replace(".js", "");
String[] fileName = file.split("_");
testName.add(fileName[1]);
}
return testName;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
Then I added this in my mainActivity
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
super.init();
setToUnstrictMode();
WebView wV = (WebView)appView.getEngine().getView();
wV.addJavascriptInterface(new JavaScriptInterface(this), "jsInterface");
// Set by <content src="index.html" /> in config.xml
wV.loadUrl(launchUrl);
}
Then I tried accessing it in my JS using this function.
var getTestNames = function(){
return window.jsInterface.getFileNames("www/js/tests");
}
Apparently, It's not working.
EDIT: I noticed that I was able to call the method, the log from the method getFileNames shows up in my logs. However, for some reasons, I could not pass it properly in a variable.
Maybe just write a simple plugin. I wrote some by myself i can approve that they are working. Use tips from official cordova documentation: https://cordova.apache.org/docs/en/latest/guide/platforms/android/plugin.html
I know that it's different approach, but at least it's a working one.
I am calling a native android function via java script loaded in a webview but is not working
Here is what i have done with WebView
paintView = (WebView) findViewById(R.id.webView1);
WebSettings Websettings = paintView.getSettings();
Websettings.setBuiltInZoomControls(true);
Websettings.setSupportZoom(true);
Websettings.setJavaScriptEnabled(true);
Websettings.setBuiltInZoomControls(true);
Websettings.setRenderPriority(RenderPriority.HIGH);
paintView.getSettings().setPluginState(PluginState.ON);
paintView.setWebChromeClient(new WebChromeClient());
final MyJavaScriptInterface myJavaScriptInterface = new MyJavaScriptInterface(this);
paintView.loadUrl("file:///android_asset/index_jQueryMobile.html");
and here is the android method
#JavascriptInterface
public void byteToImage(String base64img, String ImageName) throws IOException
{
byte[] pdfAsBytes = Base64.decode(base64img.toString(), 0);
File file = new File(Environment.getExternalStorageDirectory()+"/AndroPaint");
if(!file.exists()) {
file.mkdirs();
}
File filePath = new File(Environment.getExternalStorageDirectory()+"/AndroPaint/"+ImageName+".png");
FileOutputStream os = new FileOutputStream(filePath, true);
os.write(pdfAsBytes);
os.flush();
os.close();
}
and here is the JS function
function getImageBytes()
{
var canvas = document.getElementById('canvas');
var imageName = document.getElementById('imgName');
var imgData= canvas.toDataURL();
activity.byteToImage(imgData,imageName);
}
here is the exception
01-04 10:48:50.409: E/Web Console(15681): Uncaught ReferenceError: activity is not defined:72
You made a connection interface MyJavaScriptInterface, but you forgot to attach it to the WebView:
paintView.addJavascriptInterface(new MyJavaScriptInterface(this), "activity");
That is why you are getting activity is not defined error. activity object cannot be found by JS engine.
Here is a small tutorial on that
I made a Javascript page to generate a JSON object for read it then from Android device.
I read it with the following code
StringBuilder stringBuilder = new StringBuilder();
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse response = client.execute(httpGet);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode == 200){
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(content));
String line;
while ((line = reader.readLine()) != null){
stringBuilder.append(line);
}
} else {
Log.e("JSON", "Failed to donwload file");
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
The problem is that this code returns the source code of the webpage, and the source code is the script in Javascript, not the JSON string generated after execute it.
I need the JSON string and I need use Javascript to generate the JSON string because I access to an external service.
I haven't find any solution for this. I don't care if the possible solution involves the server or the Android terminal.
Thanks.
String myresponse=Html.escapeHtml(YourStringHere);
Try this.
private class MyJavaScriptInterface {
private MyJavaScriptInterface () {
}
public void setHtml(String contentHtml) {
//here you get the content html
}
}
private WebViewClient webViewClient = new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
view.loadUrl("javascript:window.ResponseChecker.setHtml"
+ "(document.body.innerHTML);");
}
}