Tag Archives: Android

NativeScript application wide runtime settings (updated 5.2)

NativeScript Switch

On thing most people are probably not aware of is that the Android runtimes has a large number of knobs and switches to customize certain behavior of the engine.   I will try and list out all the current switches and knobs that you can use.   iOS now has one switch.

First of all the settings go into the /app/package.json   If you open up the default package json you probably will see:

    "android": {      
        "v8Flags": "--expose_gc"    
   "main": "app.js",
   "name": "tns-template-hello-world",
   "version": "5.2.0"

That "android" key is where everything goes for Android specific settings.   The default setting that comes in the files is "v8Flags": "--expose_gc" this one is rather critical in that this enabled the runtime to call gc from JavaScript.   Now, there is quite a few v8Flags you can use; most the time they aren't needed but if you need to tune the v8 engine; you can add more flags into this string.  I even list a few in this post.   Let me warn you again; DO NOT remove the "--expose_gc".   You will cause your app to crash when something attempts to call the GC from code.

As of version 5.2; there is a "ios" key called "jscFlags" option that is now available. My recommendation while building/testing your app is to add the key "ios": { "jscFlags":"--validateOptions=1" } The jscFlags has items that can be used to tweak the JavaScript core engine. You can find more flags here.

Ok, so here is the complete list of settings you can change in the Android section:

SettingDefaultMin VersionDescription
gcThrottleTime03.xAllows you to throttle
how frequently JS GC
triggers native GC
Memory Management
memoryCheckInterval03.xHow frequently to check
memory usage
Memory Management
freeMemoryRatio0.03.xRation of memory before a GC is ran (works with
Memory Management
markingModefull3.xSwitches which type of GC engine to use.  "none" will enable a different engine which doesn't do
marking.  Typically faster
for Angular apps
handleTimeZoneChangesfalse4.1True will enable the
ability for a time zone
change in the settings to
effect the NS app.
maxLogcatObjectSize10244.0How many lines of text a
console output will log.
forceLogfalse4.0True will enable logging
in release mode
suppressCallJSMethodExceptionfalse5.1True will suppress the
boolean type conversion error from null that could randomly occur and crash the application.
codeCachefalse2.xTrue - Enables code
caching in the v8 engine.
v8Flags--expose_gc1.xTunes the v8 engine
heapSnapshotBlob""2.x(Believe to be unused
heapSnapshotScript""2.x(Believe to be unused
snapshot.blob""2.x(Believe to be unused
profilerOutputDirKey""2.x(Believe to be unused
profiling""2.x(Believe to be unused

IOS Level Flags:

SettingDefaultMin VersionDescription
gcThrottleTime05.2Allows you to throttle
how frequently JS GC
triggers native GC
See: Custom Flags
memoryCheckInterval05.2How frequently to check memory usage
See: Custom Flags
freeMemoryRatio0.05.2Ration of memory before a GC is ran (works with
See: Custom Flags
jscFlags""5.2Tunes the JavaScriptCore engine. Valid Flags

Top Level Global Flags:

SettingDefaultMin VersionDescription
discardUncaughtJsExceptionsfalse4.2True - will disable
crashing on JS errors, will
log any issues to console.

Recommended changes:
discardUncaughtJsExceptions: "true" - This will keep the app from crashing on certain types of errors; this should be enabled for release mode! Some developers might find it more productive to have this enabled while coding to eliminate application crashes. Please note you MUST pay attention to the console if you enable this during development; because most JS errors that would crash out; will now be just logged to the console.

suppressCallJSMethodExceptions: "true" - This will keep the app from crashing on the boolean conversion issue that can occasionally occur.  This is not to say the app might have some other issue later; but this will eliminate a stupid (imho) crash reason.

markingMode: "none" - This will enable the experimental GC engine, this will help incredibly with Angular based apps. Please note it "might" cause more crashing errors if a plugin forgot to hold a reference to something it needed later. However with the above discardUncaughtJsExceptions enabled; those errors won't crash the app.

Late Breaking news; in 4.2 they actually moved "discardUncaughtJsExceptions" to the top level of the package; the reason why is because shortly after they added the support to Android; the support was added to iOS.  So now this flag controls both iOS and Android, so it no longer belongs just in the "android" block.

So in your package json would look like this if you used my recommended settings:

   "android": {
       "v8Flags": "--expose_gc",
       "markingMode": "none",
       "suppressCallKSMethodExceptions": "true"
    "ios": {
        "jscFlags": "--validateOptions=1"
    "discardUncaughtJsExceptions": "true",
    "main": "app.js",
    "name": "tns-template-hello-world",
    "version": "5.2.0"

NativeScript Android Snapshots

For those who haven't deployed any apps in v2.4 of NativeScript; one of the new features that is turned on by default is SnapShots.    Now most the time this is a AWESOME thing, however occasionally this can cause issues.   For example I have one app of mine that this crashes at startup when using SnapShots.

Now the docs do list how to disable snapshots; but it is a lot easier for me to find the notes on my own site than trying to figure out which doc has the info.

The environmental variable you need to adjust is: <strong>TNS_ANDROID_SNAPSHOT</strong>

  • 0 = Force Snapshots off always
  • 1 = Force snapshots on (including in debug mode)
  • Unset = Snapshots only in Release mode

NativeScript: Debugging the Android Build Process

I've seen this error myself a couple times and it appears that several others have ran into it..   You type something like tns run android or tns build android and it gives you an error about some process failing to build -1 error and to try a --stacktrace to see more info...  Not entirely helpful.   How do you do a --stacktrace?

So let me tell you how to actually do a --stacktrace; the magic is simple, but not obvious.

You need to do the following:

cd platforms/android
./gradlew buildapk --stacktrace

Pretty simple once you know it...   This is what TNS uses to actually do the building part of the process; so when it fails; you need to manually run the process with the --stacktrace parameter.  This will NORMALLY give you why it failed; however there are cases where it doesn't.   So in those cases you try this command next:

./gradlew buildapk --stacktrace --info

And if that fails; then you try the really realllllllly reallllllllllly verbose output command:

./gradlew buildapk --stacktrace --debug > somefile.txt

Then open up the text file in some editor that can handle 5 megs of text and search for the first occurrence of "failed" will typically give you why it failed....

One interesting issue that I ran into the other day helping a buddy of mine...   TNS seems to assume that anything not listed as a DevDependancy is a Dependancy; this can cause serious issues sometimes with things that actually should NOT be compiled into the app.   TNS builds a module using gyp; and gyp requires tar and tar-pack.  The authors of tar & tar-pack decided that the npm modules should have tests included in them (what????  Are you crazy?) and these tests have .tgz and .gz files in it.   Unfortunately these .tgz and .gz files will cause the android tools to fail in a lot of cases when it attempts to process them.

So there is two ways to solve this issue:

  1. Add tar & tar-pack to your dev-dependancies.
  2. Manually enter your node_modules folder; and find tar/tar-pack and then delete the test folders.

In my opinion adding those two modules to your dev-dependancies simplifies things and then you don't forget about them at some later point if you have to reinstall your modules...

In addition if you need to determine the Gradle dependency tree you can use:

gradle app:dependencies --configuration debugRuntimeClasspath

NativeScript, TypeScript and accessing native Android runtimes

When you are trying to access any of the native android platform using TypeScript, TS will complain about the root name --
TS2304: Cannot find name 'zzzz' at line yyyy

TypeScript is unaware that those variables exist and are actually global in scope; so to make TypeScript happy; in your code you will want to do something like this:

declare var android: any;
declare var com: any;
declare var java: any;

This will tell TypeScript that these are global, so it will no longer throw an error when you try to access any classes that start with android, java, or com. If you are accessing any other classes that Android publishes, you can also use the same technique: declare var zzzz: any;

Small update; Josh mentioned it via twitter about installing the tns-platform-declarations.  I'm not sure why I didn't post this here also -- so I'm updating the post a tad -- installing the tns-platform-declarations will get you intellisense for the android & ios platforms.  It is well worth the download if you are using native ios or android calls.

NativeScript: Android plugins and Windows path size issues

If your on Linux or OSX you can skip this post; it only applies to us pathetic people that prefer Windows (like me ). I do have Linux and OSX, so maybe I'm not that pathetic; but since I do prefer Windows, maybe I am.

If you don't want to read the reason this occurs but all you want is the fix; then scroll down to the fix!

Well if you see this error: Command [Some Path]\gradlew.bat failed with exit code 1 then you more than likely ran into this error if you see a lot of messages above it with "No Delegate Set" and errors.

Well to understand the issue you need to understand that this is a issue between Windows, Gradle and how NativeScript (A fix might show up by v1.8 of NativeScript) currently does Android plugins. Windows, if it supported larger path sizes; this wouldn't be an issue (which is why it works on Mac/Linux). NativeScript if it handled plugins differently might not run into this issue either. But at the current place we are at; it does so here is the crux of the issue.

1. Windows only supports 255 character path sizes (if they are not UNC or Unicode path's)

2. NativeScript scans all your plugins; any that have a platforms/android folder; it will use the include.gradle file found in that folder.  If there is NOT a include.gradle file; it will create one for you using the plugin name as the information.

3. Gradle combines all the productFlavors (which are inside the include.gradle files) into one long string.

Ok, lets look at a sample include.gradle file (this is also what is also generated for you, if it doesn't exist)

android {
    productFlavors {
        "nativescript-websockets" {
            dimension "nativescript-websockets"

So lets pretend your code exists at: C:\nativescript\AwesomeProject\, so there is (32) characters. Now add platforms\android\ (18). Next add build\intermediates\res\merged\ (31) as this is where Gradle does its resource merging. So lets say you are using the Telerik NativeScript UI plugin; and lets grab one of the image names \debug\drawable-xxhdpi\someimage.png which is of course adds another 49 characters. So this means we are using 130 characters already; leaving us with 122 characters left to play with.

So if you have a plugin installed like nativescript-websockets you get 23 characters used just for a single plugin. I bet you can see where this is going. Add on the cool nativescript-telerik-ui plugin and you have another 23 characters used. Add just a couple more plugins, and yes -- you are now well over 255 character limit!

Guess what happens???    Well if you are following the story so far; you get a nice error that gradle quit with error 1.

The Fix:

Now for the good news; here is how you can continue developing!

  1. Go to your app folder and do a tns platform remove android to safely recover, you need to kill your existing android platforms folder.
  2. Go into you node_modules folder, and then you need to repeat this next set of steps for EACH of the plugins you have installed.
    • Enter that plugins platforms\android folder and edit the include.gradle -- if that folder doesn't exist then you are done and can skip this plugin.  If the folder exists but the include.gradle file doesn't exist you can choose to ignore it or create your own.  DO NOT create a platforms\android folder, if it doesn't exist. Only create a include.gradle if the plugin already has a platforms\android folder and it doesn't have a include.gradle.
    • Edit the include.gradle and make the name shorter; this is the formula that I used.   Replace nativescript with "ns", eliminate any dashes, and then use the first letter for each word in the plugin.   So "nativescript-cardview" becomes "nscv",and "nativescript-telerik-ui" becomes "nstu". So the include.gradle changes from above (nativescript-websockets) to:
      android {
          productFlavors {
              "nsws" {
                  dimension "nsws"

      Pretty simple huh?   By shorting the name, you go from 23 character per plugin to 4 characters per plugin.   So you can now easily fit 5 plugins in the same space it used to take for 1 plugin.  Please make sure the total letters are unique -- don't have two plugins with the same name (i.e. "nsws" for nativescript-websockets and nativescript-webserver)  as the same name, make them distinct.  Having duplicate names will probably break Gradle.
  3. Do a nativescript platform add android to re-install the platform after you are all done, and then you should be good to go.

Please note this potential side effect: I have confirmation below that if you are using a plugin that requires additional permissions; this work around will unfortunately not merge the info from the plugins AndroidManifest.xml file.   With all the plugins I had, I never saw this issue; but depending on what you are doing this is something you may run into.   You have two choices to deal with this:

  1. Don't rename that specific plugin inside the include.gradle file.  This way the AndroidManifest.xml file will get merged properly.   You an afford a couple plugins to still have large names.
  2. Copy the information that you need (like permissions) from the plugins AndroidManifest and manually merge it into your master manifest located at App/App_Resources/Android/AndroidManifest.xml

The bug report so you can track this is Android/369 and based on the conversation with the NativeScript devs this should hopefully be fixed in v1.8 (but no promises).

Introducing NativeScript-Protect

(c) 2014, Yuri Samoilov

(c) 2014, Yuri Samoilov

UPDATE: Works on iOS and Android; see https://AppProtection.net.

Have you spent months working on the perfect application?  Are you now worried someone will just copy your source code right from your NativeScript application?  (This is not a unique issue to NativeScript; ReactNative, Titanium*,Cordova/PhoneGap and any other platforms that are not compiling Java code have this exact same issue. )

Well, I have a solution for you.  After a lot of hard work; I am proud to introduce my first commercial component into the NativeScript eco-system;  NativeScript-Protect.   The NativeScript-Protect plugin is a (very) simple  install and then it will automatically encrypt and/or minimize your source code while you are building your release version of the project.

It automatically ties itself into the NativeScript (tns) command so that you do not have to do anything. When you run anything that does a build; it will automatically encrypt and/or minimize your build copies of the code.

This does NOT touch your original source code; only the BUILD copies that the NativeScript (tns) command copies into the build system.  So it makes itself a seamless part of your standard build process that you can just totally forget it even exists.

The initial release is only for Android; but I expect to have the iOS runtimes done early next year.

If you would like to see it in action; I have a 4 minute video showing it from start to end.

In addition, two demo APK's compiled as a debug app with everything encrypted or just the main app files encrypted, can be downloaded for you to check out and kick the tires.
If you have any questions; please feel free to comment here, or contact me via the contact button on the nativescript.tools website.
* - Titanium has a encryption step; however it is rather simple to decrypt system and so in my book this is actually worse than no encryption since it gives a very false sense of security.
UPDATE: The current version turned into AppProtection.net -- So it fully supports Android & iOS.

NativeScript v1.1.0 - Released

NativeScript v1.1.0 was just released a couple days ago.    Here is what is new and how to get all the cool new features.

Some of the changes are:

  • Exposing Application events as Real Event [example]
  • Parent is now exposed in itemLoading event
  • Repeater Component Added [more]
  • TabView.selectedIndexChanged Event added
  • Hint property for TextView
  • NavigatingTo/From, NavigatedTo/From events added to Page component
  • Search now has Hint Color
  • Dozens of Bug Fixes
  • View and GestureObserver classes has breaking changes [more]

If you are currently running version 0.9.0 or v1.0.0 then here are the steps to upgrade you to the wonderful version 1.1.0


Upgrading the NativeScript Tools:

First thing to do is upgrade your TNS (or NativeScript) command so go to a command prompt (if on windows it will probably need to be an Administrator command prompt) or  bash/terminal prompt.

Type "tns --version" or "nativescript --version", if you already have version 1.1.0 then you can skip this step as you already have the latest nativescript tools.

Windows (from an Administrator prompt):

npm install -g nativescript

sudo npm install -g nativescript

This will update you to the latest version of the command nativescript command line.  And you should type "tns --version" after to verify it has been upgraded to v1.1.0

Upgrading the Platforms:

Next thing you will need to upgrade is your "platforms", so navigate to the root level folder where your project is; and then if you are working on a Android project type:

tns platform update android

and/or (if you are working on a ios version on a Macintosh)
tns platform update ios


Upgrading the Common Library:

Unfortunately The next piece is a lot more tricky as it requires a lot more steps.   Hopefully this will be fixed in v1.2.0.    But right now it is a small bit of a pain.   The easiest method is to create a new project and then copy the tns_modules out of the new project into your existing project and then delete the dummy project.      So at a command line do the following (assuming your still in your main app project folder from the steps above).    Please remember to replace <yourapp> with whatever folder name your app is in.


cd ..
tns create testupgrade
rd /S /Q <strong>&lt;yourapp&gt;</strong>\app\tns_modules
move testupgrade\app\tns_modules &lt;<strong>yourapp</strong>&gt;\app
rd /S /Q testupgrade

cd ..
tns create testupgrade
rm -rf &lt;<strong>yourapp</strong>&gt;/app/tns_modules
mv testupgrade/app/tns_modules &lt;<strong>yourapp</strong>&gt;/app
rm -rf testupgrade


LiveSync Update:

Last piece, If you are using my awesomely cool LiveSync code; you have one more step you need to do; unfortunately Telerik has not yet accepting my patch into the android platform.   So  I have pulled the same 1.1.0 platform source code as they released then added my patch and again compiled it for your usage (if you wish to compile it yourself; the readme file in the LiveSync project explains how.)       The pre-compiled runtimes can be pulled from http://www.master-technology.com/tns-android-1.1.0.tgz

After downloading and moving this file into your main project app directory (i.e. where the watcher.js file lives); The steps are as follows (Oh you will need to make sure to copy your androidmanifest.xml file from the platform/android folder if you have made **any** changes to it that you want to keep as this will install a new copy):


tns platform remove android
tns platform add android --frameworkPath=.\tns-android-1.1.0.tgz
cd app
npm install nativescript-livesync@latest --save
copy /y node_modules\nativescript-livesync\support\watcher.js ..

tns platform remove android
tns platform add android --frameworkPath=./tns-android-1.1.0.tgz
cd app
npm install nativescript-livesync@latest --save
cp node_modules/nativescript-livesync/support/watcher.js ..

And you will be done.  LiveSync will continue to work and you will be fully on the 1.1.0 Release!