Extend Android class with generic parameters in NativeScript - javascript

I am using NativeScript 2.0 and I would like to create an extension of an Android class like AsyncTask which contains generic parameters.
I know that I can use the extend() method to create an own implementation of a class or interface:
var myRunnable = java.lang.Runnable.extend({
action: null,
run: function() {
this.action();
}
});
But how can I do this for generic classes / interfaces in "pure" JavaScript?

You should be able to extend any interface/class using the same technique. At worst case you can extend Object. To my knowledge at this moment you can't create a interface/class from straight JS as the Java side needs something to base it off of so that the signatures are correct.
However, based on your example; if you are attempting to create a thread or runable in JavaScript; the result will currently fail horribly. NativeScript is currently a single thread, and if you attempt to cause android to attempt to jump back into JS while it is running JS, well lets just say it won't be your friend. :-)
There is a feature request and apparently this is the next big project now that 2.00 has been released. So we should see threads in the near future. There is also a plugin (disclaimer, I'm the author) called NativeScript-webworkers which can give you access to additional JS threads, but the JS threads DO NOT have the ability to interact with the OS like NS does, they are pure JS threads.

Related

Calling swift Code From Javascript

Is it possible to call Swift functions/callbacks from Javascript ?
In Android it is possible to use JavaVoidCallbacks, is there anything similar in Swift? Right now Im using JavaScriptCore,where i can call javascript functions from Swift.
Yes you can.
Please refer to this Tutorial: https://www.raywenderlich.com/124075/javascriptcore-tutorial
You are interested in the paragraph "Exposing Native Code"
In obj-c is very simple. You can do it just by using your jsContext as a normal dictionary.
context[#"functionName"] = ^ <#returnType#> (<#parameters#>) {
<#Your code#>
}
Hope it helped.
In Swift, the easiest way I found was to create a gateway object in Javascript, using e.g. evaluateScript(), and then adding functions to that object:
// x is JSContext
let gateway = x.objectForKeyedSubscript("gateway" as NSString)
let p: #convention(block) (Int, Double) -> () = { h, ms in
return self.swift_method(h, ms)
}
gateway!.setObject(p, forKeyedSubscript: "swift_method" as NSString)
After that you can call gateway.swift_method() in Javascript.
Most type conversions are automatic. I have used types Int, Double, String and [Int] as parameter and/or return types in the lambda.
I have the same question. When I saw the answers to this Q. I tried to use JavaScriptCore to call Swift methods from the JS side. I could inject Swift or JS methods into JSContext. However, the methods injected into JSContext are not accessible in my case.
I use WKWebView as an HTML viewer in the ViewController in my iOS native app. I use this kind of view controller to present some help information in my app. After several days of struggling, I finally found an alternative way to make Swift and JS interaction happen. The strategy is to use WKScriptMessageHandler as a gateway between Swift and JS. Refer to this good blog on how to do it in detail. Another blog, Using WebKit to call WKWebView JavaScript from Swift and Swift from JavaScript, provides another example case, which is very useful.
From my experience, WKScriptMessageHandler is based on a very elegant structure. Through WKUserContentController, you set up a message gateway between JS and Swift. There is This will allow a JS callback to Swift with messages. A delegate of WKWebViewConfiguration has to be implemented, my view controller with web view, or my custom class, to receive JS message calls with data. The message can take a JSON string as a parameter to pass data. On the Swift side, by using a similar JSContext syntax like evaluateJavaScript to specify JS a function with data.
By the way, I was told that in my case, JavaScriptCore is based on Java virtue machine. There may be performance issue and may pose a security risk. Apple has disabled the feature of JavaScriptCore in WKWebView.
The Xcode in my case is Version 13.4, and Swift is 5.
I have written a blog on this: Build a Bridge between Swift and JS

How to use C libraries to create GNOME app in JavaScript

I am a beginner in GNOME desktop application development so I am trying to learn about it as much as possible. I have read various tutorials present on developer.gnome.org written for JavaScript. I know that through GObject Introspection I can access C libraries in JavaScript.
As use of JavaScript for desktop applications is new so not many documentations are present. I was wondering if there is any way I can know which functions I can use with what parameters to access some libraries.
For example I can create a button using GTK in JavaScript by:
this.mybutton = new GTK.Button({some code here});
How can I come to know about the name of the functions I can use? Is there any way I can make out the name of the function for JavaScript seeing the documentation written for C?
For some of the libraries I have seen this documentation written for JavaScript. Any help will be appreciated to understand more about GNOME application development.
I agree with you: the documentation is pretty low on the subject.
Most of the time I try to find already written code from other developers and change it to have what I want.
The C documentation is pretty complete on http://developer.gnome.org and most of the time you can use nearly the same methods.
I suggest you to take a look at this web site: http://www.roojs.org/seed/gir-1.2-gtk-3.0/seed/
And also to this one: http://zetcode.com/gui/javascriptgtktutorial/
Good luck with your javascript development !!!
There is new host for Gnome GJS documentation:
https://gjs.guide/
https://gjs-docs.gnome.org/ for API's
You still can get Javascript function mapped to the that C library function by searching though GIR files. Each library should have an XML file containing introspection information.
Example from one question I asked before.
grep -rn gdk_keymap_get_default /usr/share/gir-1.0/
/usr/share/gir-1.0/Gdk-2.0.gir:16781: c:identifier="gdk_keymap_get_default"
/usr/share/gir-1.0/Gdk-3.0.gir:15776: <function name="get_default" c:identifier="gdk_keymap_get_default">
vim /usr/share/gir-1.0/Gdk-3.0.gir +15776
<class name="Keymap"
c:symbol-prefix="keymap"
c:type="GdkKeymap"
parent="GObject.Object"
glib:type-name="GdkKeymap"
glib:get-type="gdk_keymap_get_type">
<doc xml:space="preserve">A #GdkKeymap defines the translation from keyboard state
(including a hardware key, a modifier mask, and active keyboard group)
to a keyval. This translation has two phases. The first phase is
to determine the effective keyboard group and level for the keyboard
state; the second phase is to look up the keycode/group/level triplet
in the keymap and see what keyval it corresponds to.</doc>
<function name="get_default" c:identifier="gdk_keymap_get_default">
<doc xml:space="preserve">Returns the #GdkKeymap attached to the default display.</doc>
<return-value transfer-ownership="none">
<doc xml:space="preserve">the #GdkKeymap attached to the default display.</doc>
<type name="Keymap" c:type="GdkKeymap*"/>
</return-value>
</function>

Code sharing between browser and server (inheritance)

I am writing a real-time multiplayer browser game in JavaScript. So I'm running JS on the server (Node.js) and in the browser. Because of that I would like to share code between those two contexts.
I decided to devide the code into three parts: Core, Client and Server. As you may have suspected I use Core for code we need on both sides, the Client and the Server.
Until now I have just been extending the corresponding core class, e.g. Client/Player extends Core/Player, which works just fine.
Now I see that for example a Client/Player needs to extend the Core/Player to get the name attribute and at the same time it needs to extend Client/GameObject to get the render() method and the physics attribute.
If it was written in C++, I could try to use multiple inheritance with all its drawbacks. But since it is written in JavaScript, I'm not sure how to solve this. Any ideas?
What I finally did was a hack with kind of a preprocessor. Before start I replace the require("Core/GameObject") in Core/Player with require(context + "/GameObject"). This way I create kind of a "z" which allows me to inherit from both.

Use V8 JavaScript engine to execute JS lib without web view

I am developing a JavaScript component which is responsible for making requests to the server and dispatching results to the UI. By doing this in JavaScript, I am able to use my component in several types of UI: Android app, iOS app, desktop app (QT), web app...
All these UI have instantiated a web view, so my component is started when the UI loads the dedicated URL (webview.load("file://myfirstWebPage.html")).
This first web page loads all the JavaScript components, and when it's done, the UI is able to make some requests to the JavaScript component, which makes a request to the server and when it has the response, it dispatches it back to the client (UI Android, UI iOS ...)
This architecture works fine, but I would like to know if there is another way to load the JavaScript component without using a web view on each client?
Can the V8 engine help me?
If I'm understanding your question, you're looking for a way to execute JavaScript across many platforms (iOS, Android, etc.) without the use of a WebView. The solution will be platform-specific, since even the underlying WebView implementations are different for each platform.
For Android, so long as the device ships with V8, you can create a new V8 Context via its API and use that to execute your JavaScript. The device must actually ship with V8. This answer may help you further.
For iOS, which uses JavaScriptCore, recent developments in iOS7 have been made to allow you load and run arbitrary JavaScript code. Read more here.
For the Android part. I used J2V8 JavaScript library. It is a Java wrapper of Google's V8 JavaScript engine. See here for more details.
I don't know how to use V8, but you can use Rhino library instead. There is no WebView involved too.
Download Rhino first, unzip it, put the js.jar file under libs folder. It is very small, so you don't need to worry your apk file will be ridiculously large because of this one external jar.
Here is some simple code to execute JavaScript code.
Object[] params = new Object[] { "javaScriptParam" };
// Every Rhino VM begins with the enter()
// This Context is not Android's Context
Context rhino = Context.enter();
// Turn off optimization to make Rhino Android compatible
rhino.setOptimizationLevel(-1);
try {
Scriptable scope = rhino.initStandardObjects();
// Note the forth argument is 1, which means the JavaScript source has
// been compressed to only one line using something like YUI
rhino.evaluateString(scope, javaScriptCode, "JavaScript", 1, null);
// Get the functionName defined in JavaScriptCode
Object obj = scope.get(functionNameInJavaScriptCode, scope);
if (obj instanceof Function) {
Function jsFunction = (Function) obj;
// Call the function with params
Object jsResult = jsFunction.call(rhino, scope, scope, params);
// Parse the jsResult object to a String
String result = Context.toString(jsResult);
}
} finally {
Context.exit();
}
You can see more details at my post.
I found this really nifty open source ECMAScript compliant JS Engine completely written in C called duktape
Duktape is an embeddable Javascript engine, with a focus on portability and compact footprint.
You'd still have to go through the ndk-jni business, but it's pretty straight forward. Just include the duktape.c and duktape.h from the distributable source here(If you don't want to go through the build process yourself) into the jni folder, update the Android.mk and all that stuff.
Here's a sample C snippet to get you started.
#include "duktape.h"
JNIEXPORT jstring JNICALL
Java_com_ndktest_MainActivity_evalJS
(JNIEnv * env, jobject obj, jstring input){
duk_context *ctx = duk_create_heap_default();
const char *nativeString = (*env)->GetStringUTFChars(env, input, 0);
duk_push_string(ctx, nativeString);
duk_eval(ctx);
(*env)->ReleaseStringUTFChars(env, input, nativeString);
jstring result = (*env)->NewStringUTF(env, duk_to_string(ctx, -1));
duk_destroy_heap(ctx);
return result;
}
Good luck!

Get output from JavaScript function in C++

Hy,
I'm working at a project that must call from C++ a custom function made in JavaScript. I'm able to run the function
The project should work only on Windows (actually it's a Windows service), so it's ok to use interfaces IWebBrowser2 and IHtmlDocument2
The function's signature is string function(string). I'm able to run the function in C++, based on this tutorial (I'm using IWebBrowser2 and IHtmlDocument2 interface), but I'm not able to get the output from that JS function back in C++.
Is there any method to retrieve the output from that JS function back in C++, using those interfaces? ( or maybe other)
Thank you,
I'll answer to my own question, if someone will have the same question:
Short answer is you can't obtain the output of javascript script using these interfaces. The IWebBrowser2 and IHtmlDocument are running in a context based on IE, so you can't obtain the output of running scripts.
The solutions for this problem are:
V8 or SpiderMonkey
Active Script Interfaces
If you plan to use V8 in your application, the basic example for calling a function is provided at Calling a v8 javascript function from c++ with an argument (But, be aware of the Dispose() function, which is wrongly placed)
If you plan to use Active Script Interfaces, the basic example is provided at Run JavaScript function from C++ without MFC . It's a useful example that shows how to run a JavaScript function.

Categories

Resources