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

Cautionary Tale for Angular Developers


Okay, now take a moment to watch this video

I’m sure after watching it, you may have realized that I’m not here to talk about why Neo falls into coma by stopping sentinels. Instead I’m going to talk about why my application got crashed the same way in Windows 8 RT webview and what I learned.

The Reality

An Application was built on top of Angular.js and Twitter Bootstrap for Desktop, Android, iOS, and Windows8. For touch devices, we’d created a Native wrapper around which loads the application in a webview. It looked fine in Android and iOS devices but was crashing in Windows8 RT upon opening a Bootstrap Modal popup. And I had no clue why Windows8 RT alone?

This is what I was using to open a modal window. I know its very bad to do the imperative DOM manipulation inside controller but as there were no directives bound to .modal I believed its safe to use it.

<br>
$('.modal').modal({backdrop: 'static'});<br>

But I was wrong. In Windows8 RT, the above line was throwing an error “Object [object Object] has no method ‘modal'”. My guess is that I must be executing bootstrap code in middle of $digest cycle or something.

The Fix

To fix this issue I could either move that code in a custom directive and toggle modal’s state or use Angular UI Bootstrap. I decided to go with the latter. Finally I learned a very hard lesson while fixing the issue that one should spend some time to get it right than just get it done.

Follow the best practices or get ready to be bitten.

So I’ve used AngularUI Bootstrap modal directive to instead of doing DOM manipulation in the controller.

<br>
var App = angular.module('App', ['ui.bootstrap']);<br>
App.run(function($rootScope) {<br>
    $rootScope.opts = {<br>
        backdrop: true,<br>
        backdropClick: false,<br>
    };</p>
<p>    $rootScope.modalOpen = false;<br>
});<br>

Finally updated the DOM as follows:

<br>
  &lt;button class="btn btn-primary btn-large" ng-click="modalOpen = true"&gt;Open Modal&lt;/button&gt;</p>
<p>  &lt;div class="modal hide" options="opts" modal="modalOpen"&gt;<br>
    &lt;div class="modal-header"&gt;<br>
      &lt;h3&gt;Modal Header&lt;/h3&gt;<br>
    &lt;/div&gt;<br>
    &lt;div class="modal-body"&gt;<br>
      Modal Body goes here...<br>
    &lt;/div&gt;<br>
    &lt;div class="modal-footer"&gt;<br>
      &lt;div class="btn" ng-click="modalOpen = false"&gt;Close&lt;/div&gt;<br>
    &lt;/div&gt;<br>
  &lt;/div&gt;<br>

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.

Desire(HTC) is half of life


HTC Desire a8181
HTC Desire a8181

Updates:

Problem:ย Phone Storage space is getting low.
Solution:ย This warning ย appears and annoys once you have less than 17MB free space on internal phone storage. The solution is to move each and every new app installed in your SD card. And do not install the updates for ADOBE flash player (11 MB) at all.