NativeScript: Edge of Tomorrow


This article is all about my experiences of building a Native Android application using NativeScript. NativeScript a framework for building cross-platform Android & iOS apps using Javascript and XML. For the reference, I am in the middle of migrating the same application to NativeScript + Angular combo (just for fun) as it leverages existing Angular skillset such as data-binding, event handling, routing, AuthGuard, etc, and makes it easy to reason about as well.

In a nutshell, NativeScript is not just a set of Javascript libraries but more of a runtime that enables to call Native Android and iOS apis using Javascript. It uses a Javascript virtual machine – V8 for Android and Webkit Core for iOS – that interprets and executes Javascript code at runtime to their respective native code. Hence, there is no limit in terms of which native API can be called in NativeScript, makes it a super powerful tool – worth adding in your arsenal 🙂

This article does not discuss about building Native apps in NativeScript because their documentation is pretty neat and covers it all.

Android ecosystem

Even though you were convinced to write native apps in pure Javascript, that fact is partially true. Meaning you still need to setup android SDK and tools in order to run your application on Emulator or Device. Oh boy, it was PITA in the beginning, especially when you are used to write for Web only – just Write. Refresh. Repeat!

One of such issues faced even before I could run their Sample Groceries app was the ANDROID_HOME environment variable is not set error, while running tns platform add android command. Although, there were tons of stack-overflow answers about that weirdo behavior but unfortunately all were suggesting to add ANDROID_HOME to the PATH environment variable – been there, done that already. At one point, I had decided to give up on NativeScript as I was this frustrated!

But soon the NativeScript community slack channel came to the rescue which I found on their troubleshooting documentation. That culprit is sudo – was running sudo tns platform add android like a rookie 👊. Nonetheless, I quickly got over it and set up the project with tns create FreshCall command.

NativeScript Plugins

The android application named FreshCall that I was building is a simple phone call management app to keep a tap on number of users being called on a daily/weekly basis, extract call charges for reimbursement purposes, and possibly record a phone conversation (with speakers on) for quality purposes. As you have already guessed that the application supposed to use android native APIs for most of the requirements such as ask permissions, choose or dial contact numbers, record conversation and upload it to Firebase, fetch call charges from USSD dialogs, etc. Luckily, the NativeScript community is flourished enough to have many plugins ready for most of the things I needed 😊

I realized that building traditional apps in NativeScript is far more easier than ones using native APIs. That’s why problems and worries did not stop for me at the rookie mistake made earlier, after all it was just the beginning.

Migrate Android code to NativeScript

Obvious thing for any phone management application is to detect Incoming calls and allow to make Outgoing calls using TelephonyManager. Truck load of articles and stack-overflow questions can be found on the topic, however, using them in NativeScript was a big deal. But Extending native classes section from the NativeScript documentation was quite useful that opened up ways for further exploration.

Below is the incoming call tracking code in Java (android):

private class CallStateListener extends PhoneStateListener {
  @Override
  public void onCallStateChanged(int state, String incomingNumber) {

  }
}
tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
tm.listen(callStateListener, PhoneStateListener.LISTEN_CALL_STATE);

So the above Java code can be ported to NativeScript as follows:

var callStateListener = android.telephony.PhoneStateListener.extend({
onCallStateChanged: function (state, incomingNumber) {

}
var application = require("application");
var tm = application.android.context.getSystemService(android.content.Context.TELEPHONY_SERVICE);
tm.listen(new callStateListener(), android.telephony.PhoneStateListener.LISTEN_CALL_STATE);

How did I manage to port it so flawlessly? Here is a simple trick:

  1. Learn to extend android native classes in NativeScript.
  2. Search android documentation for a native property such as PhoneStateListener and refer the java.lang.Object path for the same i.e. android.telephony.PhoneStateListener.

The similar trick is applicable for application ctx, android Context, and tm.listen event.

Background Services

NativeScript community is so kind to give you all the tools to build a bridge, but the only condition is that you’ve to learn to build it yourself, 😄. I hope one day it will be a piece of cake as NativeScript grows and will be widely adopted as a standard to build native apps.

To track the USSD dialog’s response – the call charge window appears after the call ends – I needed a background service to keep an eye on it and extract the the call charge as soon as it shows up. Somehow I could write a background service myself with the help of the sample provided by NativeScript community and port the USSD parsing using the trick we just learned. However, the onServiceConnected() method – enables accessibility service to read USSD responses – was not getting registered even after enabling it for the application from the android settings.

During the salvation of this problem, I learned two things:

  1. When in doubt, always rebuild using tns build android (remove the existing application from the device before live-syncing again).
  2. Reinstall android packages if updates are available.
    Android SDK and tools
    Android SDK and tools

Wrap up

Experience of building the android application (without having any knowledge of Native Application Development before) was terribly empowering 😉. My advice to fellow developers is to keep Android Documentation open all the time!

Peter Kanev from NativeScript core team had been a great help. Also, special thanks to Brad Martin (who built many plugins I’ve been using) and Marek Maszay for their constant support and cheer on Slack.

Live on the Edge Of Tomorrow today with NativeScript!

If you found this article useful in anyway, feel free to donate me and receive my dilettante painting as a token of appreciation for your donation.
Advertisement