The NativeScript Android runtime is a V8 proxy that translates JavaScript into Java calls
NativeScript for Android using v8
At a glance
- What is it?
- NativeScript for Android is the runtime that lets a JavaScript application call the Android framework directly, built as a C++ proxy around V8 with a set of generator projects that produce the type metadata and bindings. Building it needs the NDK, CMake and several specific SDK levels, and the package pins V8 14.9 with Gradle 8.14 and NDK r29.
- Who is it for?
- Adopt the NativeScript Android runtime if you are building a NativeScript application for Android and want the JavaScript to talk to the Android framework without a native bridge you write yourself, since the runtime and its metadata generators do that translation for you. Do not adopt it as a general cross-platform layer, because this repository is the Android half only and it pins V8, Gradle and NDK versions that have to be rebuilt when they move.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 10 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The runtime is the bridge, not the framework
The README makes the architecture argument in a paragraph and it is worth reading closely, because the terminology is confusing if you have not met the project.
NativeScript is described as a framework which enables developers to write truly native mobile applications for Android and iOS using JavaScript and CSS. Each mobile platform has its own ecosystem and offers completely different development tools and languages, Java for Android and Objective C or Swift for iOS. In order to translate JavaScript code to the corresponding native APIs some kind of proxy mechanism is needed, and this is exactly what the Runtime parts of NativeScript are responsible for. The Android Runtime may be thought of as The Bridge between the JavaScript and Android worlds.
So the split is: the framework gives you the cross-platform programming model, the runtime is the platform-specific piece that makes the calls work, and there is one runtime repository per platform. This repository is the Android one.
The delivery model is worth noting because it explains the build complexity. A NativeScript application for Android is a standard native package, an apk, which besides the JavaScript files embeds the runtime as well. The runtime is not a separate service or a sidecar; it is inside the application binary, which is why the runtime has to be compiled for the target ABI and packaged with the app.
The description says the runtime uses V8, and the package.json confirms it with a version_info block naming v8 14.9.207.39. The same block pins gradle 8.14.3 and gradleAndroid 8.12.1, ndk r29, ndkApiLevel 21, minSdk 21, compileSdk 35, buildTools 35.0.0 and kotlin 2.0.0. The repository description says NativeScript for Android using v8.
The primary language is C++, the licence is Apache-2.0, the default branch is main, and the recent releases are v9.1.1 from 2026-09-05, v9.1.0 from 2026-08-27 and v9.1.0-rc.2 from 2026-08-25. The last push was on 2026-10-13.
Four main projects and two helpers, ordered by dependency
The repository is structured into projects, and the README says they are ordered by dependencies, which is the fastest way to understand the build.
The first is android-metadata-generator, which generates metadata necessary for the Android Runtime. The second is android-binding-generator, which enables Java and Android types to be dynamically created at runtime, and it is needed by the extend routine. The third is android-runtime, which contains the core logic behind the Android runtime, and this is the one with native C++ code that needs the Android NDK to build properly. The fourth is android-runtime-testapp, described as a vanilla Android Application which contains the tests for the runtime project.
Two helper projects sit outside that chain. android-static-binding-generator is a build tool that generates bindings based on the user's JavaScript code. project-template is an empty placeholder Android Application project used by the NativeScript CLI when building an Android project, which is how a new NativeScript project gets its Gradle skeleton.
The division of labour between the two binding generators is the interesting part. The dynamic one makes Java and Android types exist at runtime, which is what lets a JavaScript property access reach a Java object without a compile-time binding for every type. The static one generates bindings from your JavaScript source, which is the optimisation path where the runtime knows the concrete types involved and can skip the generic path.
So the metadata generator describes the Android API surface, the dynamic binding generator turns that into runtime-callable types, the runtime itself does the calling, and the test application exercises it all. A reader trying to understand where a given behaviour lives can use that chain, and the top-level entries bear it out: test-app/ holds the runtime, the test application, the build tools and the jsparser, while build-artifacts/ holds the project template and android-static-binding-generator/ sits at the top.
Building it: SDK levels, environment variables and a Gradle invocation
The build prerequisites are listed in detail, and the specific API levels are the first thing to check.
You install the latest Android Studio, then from the SDK Manager, which is Android Studio, Tools, Android, SDK Manager, you install Android API Level 23, 24, 25, 26 and 27, the Android NDK, the Android Support Repository, the Build Tools, CMake and LLDB. You then clone the repository with its submodules:
git clone --recurse-submodules [email protected]:NativeScript/android-runtime.gitThe submodules matter, because the generator projects and the V8 sources are not in the main tree. There is a .gitmodules file at the root, plus a download_v8.sh script and a v8-versions.json file, which together are how the V8 dependency is pinned.
Three environment variables have to be set. JAVA_HOME such that $JAVA_HOME/bin/java points to your Java executable, ANDROID_HOME pointing to where you have installed the Android SDK, and ANDROID_NDK_HOME pointing to the version of the Android NDK needed for this version of NativeScript.
The NPM dependencies of the build tooling are installed first:
cd test-app/build-tools/jsparser
npm installThen the build itself, which differs by platform:
./gradlewon Mac and Linux, and the same without the leading dot on Windows.
The build produces more than the runtime. It includes building of the runtime package, both optimized and with unstripped V8 symbol table, as well as all supplementary tools used for the Android builds: the metadata generator, the binding generator, the metadata generator again, and the static binding generator. The result lands in the dist folder.
There is a documented speed-up. To cut the build time in half and package only the optimized, stripped, version of the runtime package, comment out tasks.generateRuntimeAar.execute() in the build.gradle script. That is a worthwhile edit for anyone iterating on the runtime, because the unstripped variant doubles the packaging work for no benefit outside of debugging.
Running the tests needs an emulator with an sdcard mounted
The test flow is short, and it has one prerequisite that is easy to miss.
After building the runtime, you go to the test-app subfolder, and you start an emulator or connect a device. The note is that the device or emulator needs to have an sdcard mounted. Then you run:
gradlew runtestsThe sdcard requirement is the kind of detail that appears in a note because it is not obvious from the tooling. Modern Android Studio emulator images often do not have an sdcard mounted by default, and the runtime test suite writes to external storage, so a test run on a fresh emulator fails in a way that looks like a runtime bug rather than a setup omission.
The inspector is connected separately, and the mechanism is the Chrome DevTools protocol rather than a bespoke debugging UI. You install the test app dependencies:
cd test-app
npm installThen you run the test app in Android Studio or manually in the emulator, and start the debug session with:
npx ns debug android --startIf you have the nativescript NPM module installed globally you can omit the npm install and the npx prefix. The command prints a URL such as devtools://devtools/bundled/inspector.html?ws=localhost:40000, which you open in Chrome or Chromium.
That detail about the websocket port in the URL is worth pausing on. The inspector is the standard Chrome DevTools frontend talking to the runtime over a websocket on port 40000, which means you get the familiar Elements, Console and Sources panels against your JavaScript running inside a native app. The repository also has a documentation page on implementing additional Chrome DevTools protocol domains, so extending the inspector for a NativeScript-specific feature is a supported exercise rather than a hack.
One practical note for Android Studio users: you might need to run the studio from the command line to preserve the environment variables, in case you get errors like missing npm when starting the studio the usual way.
Where the NativeScript Android runtime is the wrong dependency
Three limits, and the first is about the size of the commitment.
The first is that adopting this runtime means owning a native build with pinned toolchain versions. The package.json version_info block pins V8 14.9.207.39, Gradle 8.14.3 and 8.12.1 for Android, NDK r29, minSdk 21 and compileSdk 35, and the build requires an exact set of installed SDK platform levels, plus CMake and LLDB. That is a normal situation for a native project, but it means the runtime is not something you pick up and consume; you either build it and vendor the artefact, or you wait for the upstream release matching your toolchain. The releases are dated and frequent, v9.1.0 and v9.1.1 within about a week of each other in August and September 2026, so upstream is moving.
The second is that the coverage of the Android API in the metadata generator is a moving target, and it is generated rather than hand-written. When you target a newer Android API level than the one the metadata was generated against, the type information the runtime relies on for dynamic binding is either missing or stale. The repository's own prerequisite list, API levels 23 through 27, is narrower than the compileSdk 35 in the version_info block, which suggests the generator has not been regenerated across that whole range recently.
The third is that this is one half of a pair, and the halves are not interchangeable. An Android-specific runtime is the right choice if your product targets Android and you want the deepest integration with the platform. It is the wrong choice if the goal is a single JavaScript codebase for several platforms, because then the iOS runtime and the JavaScript-side framework become the constraints, and this repository only solves the Android one of them.
The alternative approach is to write the bridge yourself using the official Android JavaScript interfaces, which means embedding a JavaScript engine and exposing a small set of Java objects to it, or to use a hybrid framework that renders most of the interface in a WebView and keeps only the parts that need native behaviour as Java or Kotlin plugins. The difference in approach is that a hand-written bridge gives you exactly the API surface you need and no generator to keep in step with the platform, at the cost of the work in the interop layer and of losing the ability to call any Android API from JavaScript by name. A hybrid approach avoids a JavaScript engine in the app entirely and gives up direct access to the framework. For a project that mostly needs a form, a list and a camera, the hybrid route is a fraction of the work; for a project where the app is mostly a thin shell over platform APIs, the runtime earns its keep.
Editorial conclusion
Adopt the NativeScript Android runtime if you are building a NativeScript application for Android and want the JavaScript to talk to the Android framework without a native bridge you write yourself, since the runtime and its metadata generators do that translation for you. Do not adopt it as a general cross-platform layer, because this repository is the Android half only and it pins V8, Gradle and NDK versions that have to be rebuilt when they move. Verify first that your installed Android SDK, NDK and Gradle versions match the pins in the package.json version_info block, since the runtime is compiled against them, that your device or emulator has an sdcard mounted before you run the test suite, and that the metadata and binding generator outputs are regenerated when you change the Android API level, because that is the step most likely to go stale.
Frequently asked questions
What is the NativeScript Android runtime and what does it do?
It is the platform-specific runtime that lets JavaScript code call Android APIs. Since JavaScript has to be translated to the native APIs, some kind of proxy mechanism is needed, and the runtime is that mechanism, described as The Bridge between the JavaScript and Android worlds, embedded inside the apk alongside the JavaScript files.
How do I build the NativeScript Android runtime from source?
Install the latest Android Studio with API levels 23 to 27, the NDK, the Support Repository, Build Tools, CMake and LLDB, clone the repository with git clone --recurse-submodules, run npm install in test-app/build-tools/jsparser, set JAVA_HOME, ANDROID_HOME and ANDROID_NDK_HOME, then run ./gradlew on Mac and Linux. The output lands in the dist folder.
What are the four main projects in the NativeScript Android repository?
Ordered by dependency they are android-metadata-generator, which generates the metadata the runtime needs, android-binding-generator, which enables Java and Android types to be created dynamically at runtime, android-runtime, which holds the native C++ core logic and needs the NDK, and android-runtime-testapp, the vanilla Android application that holds the runtime tests.
How do I run the NativeScript Android runtime tests?
After building the runtime, go to the test-app subfolder, start an emulator or connect a device with an sdcard mounted, and run gradlew runtests. The sdcard requirement is called out explicitly in the documentation.
How do I attach the Chrome DevTools inspector to the NativeScript Android test app?
Run npm install in the test-app folder, run the test app in Android Studio or the emulator, then run npx ns debug android --start. It prints a devtools:// URL with a websocket on port 40000, which you open in Chrome or Chromium.
Which V8, Gradle and NDK versions does the NativeScript Android runtime use?
The package.json version_info block pins v8 14.9.207.39, gradle 8.14.3 with gradleAndroid 8.12.1, ndk r29, ndkApiLevel 21, minSdk 21, compileSdk 35, buildTools 35.0.0 and kotlin 2.0.0.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/nativescript-android)Was this useful?