JavaScript uses Nativescript to invoke native APIs to implement Cross-platform (mobile end)

Source: Internet
Author: User
Tags garbage collection local time cpu usage


Nativescript is a running environment that allows you to use generic JavaScript code to create native Ios,android and Windows (upcoming) applications. Nativescript has a number of cool features, such as supporting JavaScript object bidirectional binding to native UI components, and using CSS to write styles for native applications. But my favorite feature is that Nativescript gives you direct access to native APIs on the local platform.

Note * It can be understood that Nativescript is a command forwarding agent for a JavaScript V8 run environment that forwards JavaScript calls to native APIs on different platforms such as Android, IOS, and windows that will be supported.

For example, take a look at the code for the Android application written by Nativescript:

var time = new Android.text.format.Time ();
Time.set (1, 0, 2015);
Console.log (Time.format ("%d"));

You just need two minutes to analyze it. This JavaScript code instantiates a Java Android.text.format.Time () object, calls its set () method, and then prints the return value after the format, which is the string "01/01/15 ”。

I know you're excited, don't panic, let's take a look at the iOS code:

var alert = new Uialertview ();
Alert.message = "Hello world!";
Alert.addbuttonwithtitle ("OK"); ();

This JavaScript code instantiates a objective-c Uialertview class, sets its information properties, and then calls its Addbuttonwithtitle () and Show () methods. When you run this code, you will see the Hello Word warning box.

Nativescript Run Time

The Nativescript operating environment may look like magic, and believe it or not, the architecture is not so complicated. Everything starts with the JavaScript virtual machine, where Nativescript starts to execute JavaScript instructions. Specifically, Nativescript uses V8 on Android and JavaScriptCore on iOS. Because Nativescript uses JavaScript virtual machines, you still need to follow JavaScript syntax structures and specifications to access all JavaScript code for the native API.

In general, Nativescript will use the latest stable version of both V8 and JavaScriptCore, so nativescript support for ECMAScript languages is almost the same on iOS desktop Safari. And Nativescript is almost the same as desktop browsers on Android. Includes some new syntax for ES6.

It's important to understand that Nativescript uses JavaScript virtual machines, but this is just the first step in the implementation, let's look at the first line of code for the example above:

var time = new Android.text.format.Time ();

In the Nativescript Android runtime Environment, the code is compiled (JIT) and executed in V8. This we may easily understand change ... :

var x = 1 + 2;

But the next question is ... How does V8 know what is android.text.format.Time ()?

We will focus on the implementation of V8 and Android, and the basic architecture pattern applies to JavaScriptCore on iOS as well. If there is a significant difference, this article will mention.

The implementation details of Nativescript on Windows will not be discussed here, because the solution may change, but the current implementation of Windows is almost the same as the JavaScriptCore running on iOS.

Nativescript How to manage JavaScript virtual machines

V8 knows what Android is because Nativescript is injected at runtime because V8 has a bunch of APIs that let you configure your JavaScript environment. In JavaScript you can use custom C + + code to analyze CPU usage, manage JavaScript garbage collection, and so on a lot of API

In the face of these APIs are several "context" classes that allow you to manipulate global variables, potentially injecting a global Android object for Nativescript. This actually uses the same operating mechanism as node.js to make the global API available-such as require ()-nativescript use it to inject APIs that allow you to access local code. There are similar mechanisms in JavaScriptCore. Cool, huh?

Let's go back to our code:

var time = new Android.text.format.Time ();

Now that you know that the code is running in V8, and V8 already knows what Android.text.format.Time is (), because Nativescript injected the necessary objects into the global scope. But there are still some big unanswered questions, how to get nativescript to understand what the API is doing, and then call it?

Metadata (meta data)

For Nativescript, reflection is the cornerstone of allowing Nativescript to invoke APIs on each platform. including Android.text.format.Time. Because it is difficult to refactor these APIs from a performance perspective, Nativescript will do this in advance and embed the pre-built metadata in the Android/ios process.

With that in mind, let's go back to our code again:

var time = new Android.text.format.Time ();

Now that you know the V8 code is running like this, Nativescript injects android.text.format.Time JavaScript objects into each individual metadata. Next question: How do I forward the JavaScript call time () in Nativescript to the native Android.text.format.Time ()?

calling local code

The answer to nativescript how to invoke native code lies in the API of the JavaScript virtual machine. Our last API to use V8 was to inject global variables. This time, we will look at invoking the given C + + code in the JavaScript callback.

For example, the code new Android.text.format.Time () of a JavaScript function call, V8 produces a callback. That is, V8 has a callback that lets the Nativescript intercept the function call, then executes some action with the custom C + + code and returns a new result.

In the case of Android, C + + code running Nativescript cannot directly access Java APIs, such as Android.text.format.Time. However, Android's JNI, or Java local interface, provides bridging capabilities between C + + and Java, so Nativescript uses JNI to complete forwarding. This bridge is not necessary in iOS, because C + + code can call the Objective-c API directly.

With this, let's go back to the code:

var time = new Android.text.format.Time ();

We already know that this code runs in V8, because Nativescript injected the object, it knows what Android.text.format.Time is, and there are these metadata-generated APIs in Nativescript. We now know that when the Timer () executes, the following things happen:

1) V8 run the callback function.
2 The Nativescript runtime knows by its metadata that the time () call needs to instantiate a Android.text.format.Time object.
3 Nativescript The runtime uses JNI to instantiate a Android.text.format.Time object and keep a reference to it.
4 The Nativescript runtime converts the proxy's Java time object into a JavaScript object return.
5 Control the returned JavaScript proxy object is the local time variable that is stored.

The proxy object is a manual mapping of JavaScript objects and local platform objects in Nativescript. For example, let's take a look at the next line in the preceding code:

var time = new Android.text.format.Time ();
Time.set (1, 0, 2015);

Based on the generated metadata, Nativescript knows all the methods on the proxy object. In this case, the code invokes the set () method of the Timer object. This method calls the V8 and its function callback again; Nativescript then forwards the corresponding method call on the Java time object via Android JNI.

This is how the Nativescript works in part. Cool, huh?

Now, there are some very complex parts left, because converting Objective-c and Java objects into JavaScript objects can be cumbersome, especially given the different types of inheritance languages.

We're not going to delve into the details of these issues, and another feature of Nativescript is that you don't have to dive into the local code, like the TNS module.

TNS Modules

TNS modules is a shorthand for Telerik nativescript modules. Like the node module, it also uses COMMONJS. So if you've already used require () and exports objects, then you've mastered the TNS module.

The TNS module allows you to api,nativescript a specific local invocation into a platform-independent system that provides dozens of of these modules for your use. For example, suppose you need to create a file in your ios/android application. You might want to write the following code in Android:

New (path);

Also write the following code in iOS:

Nsfilemanager.defaultmanager ();
Filemanager.createfileatpathcontentsattributes (path);

But if you use the TNS File system module, your code will be the same without worrying about the internal implementation details of the ios/android:

var fs = require ("File-system");
var file = new fs. File (path);

What's even cooler is that you can write the TNS module yourself. For example, here is a TNS module that retrieves the operating system version of a device:

Module.exports = {
Version:UIDevice.currentDevice (). systemversion
Module.exports = {

This code retrieves only one version attribute, but how much inspiration does it give you? Using a custom TNS module is trivial, just like using the NPM module in Nodejs:

var device = require ("./device");
Console.log (device.version);

If you are already familiar with NPM, the Nativescript module is very easy to write, distribute, and use. Personally, as a web developer, native iOS and Android code scares me, especially when Java/objective-c's API documents are thrown together, which lowers our barriers to cross-platform development.

Related Article

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.