The Problem of Run-Once Controllers in Ionic

Ionic is based on Angular. Angular has views and controllers. A view’s controller is supposed to execute each time the view is opened or navigated to. In Ionic, that doesn’t happen.

Take for instance this setup: you’re building a social app that has a Login view. You’ve configured the routes such that the Home view is set to open by default. Each time the app is loaded from scratch: (i) Home view opens, (ii) login session check is performed, and (iii) user is redirected to Login view if session has expired.

Now because Home view has loaded once and its controller executed alongside, the following piece of code will NOT execute again once login is successful on Login view and user is redirected back to Home view, perhaps through $state.go.

.controller('HomeController', function ($scope) {
 
    // Read username from local storage
    $scope.userEmail = window.localStorage['app.user.email'];
 
});

So if the value stored in local storage was an empty string when HomeController ran, $scope.userEmail would still be empty string even after LoginController has updated the local storage value.

Until this very moment, I didn’t have a damning clue to this apparently illogical problem. My searches for angular controller runs only once, angular $state.go controller doesn't execute, and so on naturally went fruitless because I wasn’t searching it right! Apparently, people were not facing the same problem.

A developer on stackoverflow reported that an NG controller should actually run each time its view loads. On the same stackoverflow question, I found my answer.

As per Ionic’s official docs on ion-view:

Views are cached to improve performance. Views can be cached, which means controllers normally only load once, which may affect your controller logic. To know when a view has entered or left, events have been added that are emitted from the view’s scope.

So the problem of run-once controllers is very Ionic specific. And so is the solution. The way to go about the problem is to move your code, that’s supposed to be executed each time a view is shown, from the root of your controller to the view’s $ionicView.enter event handler.

.controller('HomeController', function ($scope) {
 
    $scope.$on('$ionicView.enter', function () {
        // All code in this function will execute each time Home view is shown
        $scope.userEmail = window.localStorage['app.user.email'];
    });
 
});

That’s it!

Sencha Touch: Accessing a remote API that is under Basic Authentication

ST makes it pretty straightforward to access webservices or APIs through its various data proxies and Ext.Ajax. But consuming an API protected under basic authentication can be tricky. Both data proxies and Ext.Ajax provide setUsername() and setPassword() methods, and they work fine on most browsers. But in my experience using these methods, I had big time face-palm moments in case of Safari, iOS, and some Android versions. When these methods are used, an ST app sets the Authorization header AND makes all API requests through URLs formed such as this:

http://user:passwd@www.server.com/api/user/2627

I’m not sure why this is such a big deal for some browsers, but they seem to get confused due to the presence of these two things — Authorization header and user:passwd URL.

The trick to solving the issue is to NOT use setUsername() and setPassword(), and instead set the HTTP headers yourself.

Data Proxies have a headers config.

someModel.getProxy().setHeaders({
	'Authorization': 'Basic ' + btoa(username + ':' + password)
});

Ext.Ajax has a defaultHeaders config.

Ext.Ajax.setDefaultHeaders({
	'Authorization': 'Basic ' + btoa(username + ':' + password)
});

Mobile App Development: Lessons Learned

  1. Sencha Touch is a great framework, but requires a LOT getting used to. The officials Docs do not always have the answer you’re looking for. ST forums and stackoverflow are excellent resources to consult when in need.
  2. If you are a web developer, DO NOT waste time learning Objective-C or Java for creating native iOS and Android apps. Instead use something like ST to develop a mobile web app, and then convert it into a native app using Cordova / PhoneGap.
  3. Cordova is the renamed, open-source version of PhoneGap.
  4. If your app is data-centeric, most probably it will depend on a webservice / API. If the API and the app are hosted on the same server, no problemo. In case of native apps, that are basically web apps PhoneGapped into native apps, that’d mean calling a remote API, and that is the problem. See same origin policy.
  5. Most googled solutions will point to making the service JSONP supported; but JSONP works only for GET requests. CORS is a recent W3C standard that supports all HTTP methods, but it still doesn’t work for PhoneGapped apps. ASP.NET Web API provides an easy CORS implementation.
  6. The perfect solution is to keep making Ajax calls normally, but using the full URL of the remote API. That will work because a PhoneGapped app doesn’t render in a browser but in a WebView (through a file:// URL). So it’s not restricted by browser’s same origin policy.
  7. ASP.NET MVC 5 and Web API are awesome!
  8. You may frequently encounter annoying cache issues with PhoneGapped apps. Just place a super.clearCache() in your Android app’s main activity’s onCreate().
  9. A PhoneGapped iOS app will run in fullscreen mode, by default, such that the status bar in iOS 7+ will appear over it. A fix is right here!
  10. One can create an IPA archive for testing on iOS devices via Build > *.app > iTunes > ?*.ipa. Believe me, it’s one of the most stupid things you will ever do. This is the correct way to create IPA archives for ad hoc distribution.
  11. Here’s how to create an animated splash screen in Android (though I have yet to figure out how to correctly use this in a ST-PhoneGapped app).
  12. If your device has Android 4.4+, you can remote debug your WebView-based Android apps using Chrome.
  13. JavaScript is yummy!

Sencha Touch: Third-party plugins and build errors

Nothing beats Sencha Touch when it comes to sheer number of options and versatility in developing for the mobile. ST has truly set the benchmark of mobile development done right with each major release. It has a vibrant user community, and a robust enterprise adoption. But, sadly, although the documentation is good, it sometimes feels a bit incomplete. If it weren’t for stackoverflow and ST’s official forums, it would have been difficult for me to complete some aspects of my recent mobile app project. Coming to the point…

ST recently announced the much awaited grid feature . They call it Touch Grid. On the surface, it looks super-customizable (just like everything else ST) and enterprise-ready. In short, it’s just what everyone was waiting for. Unfortunately, it is not available for free. Touch Grid comes as part of the Sencha Touch Bundle, something only suited to the enterprise due to its staggering $695 cost.

A couple of months ago, I was looking for something like Touch Grid for my app. The exorbitant pricing of ST Bundle compelled me to look for free alternatives. That was when I found Ext.ux.touch.grid. Its last release was well over a year ago now, and was tested with ST 2.2. But it still works with ST 2.3 (the current release). Including its source folder “Ext.ux.touch.grid” in the root of my ST app and adding a reference to it in my app.js was all that was needed to get it to work.

When I built my app for production deployment (sencha app build production), I got this error:

Unknown definition for dependency: Ext.ux.touch.grid

The above error basically pops up because of not adding a dependency (say, a plugin) in your ST app’s classpath. Adding it to the classpath resulted in the yet another error:

com.sencha.exceptions.ExBuild: java.lang.IllegalArgumentException

A small tweak fixed this error: I created a new folder “plugins” in the root of my app and moved the “Ext.ux.touch.grid” folder into it. I edited my app.js to change the plugin’s path, and likewise changed the classpath.

Add this to the top of app.js (before Ext.application declaration):

Ext.Loader.setConfig({
    enabled: true,
    paths: {
        'Ext.ux.touch.grid': './plugins/Ext.ux.touch.grid'
    }
});

And add the “plugins” folder to the app’s classpath (edit .sencha/app/sencha.cfg):

app.classpath=${app.dir}/app.js,${app.dir}/app,${app.dir}/plugins

Now build again, and all should be fine!
Happy coding.

The Making-of an Android App

UnJumble
I have been developing mobile web apps since quite some time now, mostly using popular JavaScript frameworks, like Sencha Touch, which give a native look & feel to the app. Web apps have their merits, but using a platform’s SDK in order to develop a true native app is is inevitable in cases where you exclusively want your app to be available offline and also leverage some OS niceties that are unavailable to plain JS apps.

I recently got into developing a small, simple, but useful app for Android using using their latest API (level 16). The app — UnJumble — takes as input a jumbled English word, searches through a database of 58,000+ words for possible matches, and displays unscrambled word suggestions based on matches. As an added bonus, UnJumble fetches meanings for each unjumbled suggestion from Wordnik. Of course, the user gets to enable or disable the fetching of meanings as querying Wordnik requires an Internet connection, and this process may be a bit slow in some cases.

I’m currently in the process of giving finishing touches to UnJumble to prepare it for publishing on Google Play store. UnJumble is now available on Google Play. Throughout the journey of its development, I learned a lot of cool things about developing Android apps. In this article, I’ll share what all I learned by methodically teaching you how to build your own Android app using the several “components” I used to create UnJumble. But I’ll assume you’ve read at least a couple of tutorials on the Android Developers website, and that you are fairly familiar with a handful of Android SDK’s major terms and components.

Get ready to read about the journey of an Android app from its development to publishing.

Complete source code for UnJumble can be found at its github page.

Continue reading The Making-of an Android App