Comparing React Native to Axway Titanium

Comparing React Native to Axway Titanium

Here at Shockoe we often use cross-platform tools to build our apps. Using a cross-platform tool allows us to have one code base for apps that run on multiple platforms. There will be some platform specific code, but most things can be shared. Our cross-platform tool of choice is Axway Titanium. It used to be that cross-platform tools heavily leveraged WebViews. Tools like Cordova (ex PhoneGap) allow the developer to write a mobile website using HTML, CSS, and JavaScript. Then PhoneGap handles showing this content to the user inside of a native WebView. Instead of the WebView approach, Titanium gives you a JavaScript context and provides a bridge that handles interactions between the JavaScript environment and native components. Titanium stood out because it actually interacted with native components. But now Titanium is not the only framework out there that takes this approach. A couple years ago Kyle took an early look at React Native. Let’s take another look and see how React Native has come along.

Getting Started

Start off by heading over to the React Native Getting Started page. They offer two options: Quick Start and Building Projects with Native Code. I have not tried the, now default, Quick Start option. Several documentation pages refer to needing to “eject” your application if it was created from the Quick Start. For that reason alone I have only used the Building Projects with Native Code option.

There are a few dependencies to install, but the guide walks you through what you need. You will need NodeJS and the watchman package for observing changes. You will also need to install the react native cli. Additionally, you will need Xcode if building for iOS and Android Studio if building for Android.

Once you’ve got the dependencies installed you create a new project with the CLI:
react-native init AwesomeProject

Running the App

With no changes to the code base, you can immediately build the app you just created. In a Titanium project, all builds are handled through the Axway Appcelerator CLI or Axway Appcelerator Studio. This is not the case with React. It seems you can only build to an iOS simulator, Android emulator, or Android device with the React Native CLI. To do this you use either:
react-native run-ios
To target iOS simulator. Or:
react-native run-android
To target an Android device or emulator.

The options provided with these commands are a little lacking compared to the options with the Axway Appcelerator CLI. In my time with React Native, every simulator build chose the iPhone 6 simulator. I could not find an option to specify a different simulator with the CLI. Additionally, the CLI does not handle multiple connected Android devices well. You need to only have a single connected Android device or running emulator.

So how do you target other iOS simulators or build to an iOS device? Open Xcode! From there you use the same build options that a native developer would use. This is a huge difference from Titanium that basically discourages the use of Xcode for anything but building native modules. If you’ve never done native iOS development this can be a little daunting at first. It’s simple enough to find the play button and drop-down to select your build target. But what if you want to do an adhoc distribution build? Fortunately, there are plenty of resources out there for learning Xcode.

How about Android builds? This is an area that I am not as familiar with. Because the React Native CLI is capable of building to a device, I haven’t tried to build the project with Android Studio. I have generated a signed APK. The React Native documentation has a guide, but it comes down to using gradle.

Editing the App

React Native does not provide an IDE like Axway Appcelerator Studio. The documentation does suggest taking a look at Nuclide. Nuclide is a package for Atom that claims to setup an environment for developing React Native. I found I wasn’t taking advantage of its features, so I uninstalled it after a couple days in favor of just Atom.

So you can open the code in a text editor, where do you go from there? With a Titanium project, at least an alloy one, the entry point is alloy.js. From there the index controller has loaded first automatically. React Native provides entry points at index.android.js and index.ios.js. From there you can load whatever components you wish. The simplest thing to do is to edit some of the text provided with the sample project. Once you’ve made an update you can easily see your changes without rebuilding your app!

Axway Titanium provides a live view feature to see your app update as code changes. React Native offers a similar feature. On simulator you can press command + R to reload the code from the React Native packager. On an android emulator you can achieve the same thing by tapping R twice. Reloading can also be accessed from a built-in developer menu! To access the developer menu simply shake your device. You will see options to reload, enable remote JS debugging, enable live reload, and more.

Debugging Your Code

Axway Titanium attaches a console to builds made directly to a device, emulator, or simulator. The React Native process ends as soon as a build is installed and does not attach a console. Instead, you can enable remote debugging through the developer menu and debug your app in Google Chrome. You do not see a DOM representation of the app, but you do get access do the console and debugging tools! The debugging is done over TCP, so you don’t need to have built on a device connected to your computer. Inside the developer menu, you can change the URL used for remote debugging so you can debug as long as the device and machine running Google Chrome are on the same network.

Moving Forward

This has only been a brief look at getting started with React Native. In the future, I would like to revisit this topic to discuss more configuration, component driven design, and interacting with native code. React Native is very young, but it has come a long way in a short period of time. I am very excited to see how it matures as a cross-platform framework.

Want to stay connected on all things mobile?

Sign up for the Shockoe newsletter and we'll keep you updated with the latest blogs, podcasts, and events focused on emerging mobile trends.

Debugging Titanium Applications using Safari Web Inspector

Debugging Titanium Applications using Safari Web Inspector

Debugging is one of the most frustrating aspects of software development of any kind – it is also one of the most essential. Finding a malfunction can be time-consuming; therefore, it is important to have effective tools that can decrease your debugging time. For Titanium, most of my debugging consisted of log statements and alerts. While this method can be useful, it can also be a little time consuming to rebuild and to log a different variable, collection or model.

One of my coworkers saw me using this log for debugging and suggested an alternative: using Safari Web Inspector. I was very surprised at how easy it was to set up and how effective it can be throughout the process. This one line is all you need to add to your “tiapp.xml” file in your project:

`<use-jscore-framework>true</use-jscore-framework>`

under the <iOS> flag. Unfortunately, this method only works on an iOS simulator. Once you have updated your tiapp.xml, build your project and navigate to the page you would like to inspect. Next, you will need to open Safari; if the develop tab isn’t visible you will need to follow a couple extra steps:

Select the Safari tab from that dropdown to navigate to preferences then check “Show develop menu in the bar.” After the Develop tab is visible you will open the Simulator option and then select JSContext.

This is where all the magic happens. The files where breakpoints can be inserted will be visible on the left panel of the screen. Breakpoints are very convenient for stepping through your code and seeing exactly what is happening. I suggest opening the right panel when the breakpoints are hit. This is where you will find local variables and can also add Watch Expressions. Watch Expressions is the place where you can add the variables that you would like to keep an eye on. You will be able to see and follow each variable through every step of your code.

The bottom console is also a very helpful aspect of this debugger. I use this for taking a look at any model or collection to inspect in detail what they contain. This has been a lifesaver for me. It makes it easy to investigate exactly what is going on with any unexpected behavior with your models or collections.

The safari web inspector has its problems and will, from time to time, crash the app – but overall this tool has helped me immensely debugging my titanium apps. It makes it so effortless to nail down exactly where the problem lies. As much as we all want to have flawless code without bugs, they will appear every once in a while. However, this tool can save you from the frustration those bugs can cause. As I stated before, it is very easy to set up, so jump in and play around with it a bit. Have any questions or comments? Feel free to share your tricks for debugging. Also, you can find our latest apps and check out our work here.

Editor: In case you need to know other ways we used to debug Titanium Apps, please also check Appcelerator Titanium iOS Debugging with XCode or Rapid Titanium WebView debugging with Chrome Developer Tools

 

Want to stay connected on all things mobile?

Sign up for the Shockoe newsletter and we'll keep you updated with the latest blogs, podcasts, and events focused on emerging mobile trends.

I Got 99 Problems and a Grid ain’t 1

I Got 99 Problems and a Grid ain’t 1

A Grid View is pretty common in many applications nowadays, displaying images or a variety of image and text content to the user in a repeated pattern cells in a vertical and horizontal layout. This component is highly favored over List Views and Table Views when wanting to compare similar data types as well having a better visual comprehension that helps to distinguish the subsets of items.

However, when it comes to Titanium, they don’t have any reference to a Grid View. So what does that mean for our image heavy applications that would like to display a list of images? You could use a list view if you are able to supply enough information that would allow the user to easily read and comprehend the list. But, if you have limited data or none at all it would be more visually appealing to display a Grid View. Which brings us back to the problem at hand, Titanium does not have any reference to a Grid View.

Let us explore our options:

Option 1:

If you know that your data won’t change you could just do some calculations to disperse your views across the screen in the xml. This would be good for navigation where each button would have separate functionality when clicked.

<Alloy>
    <Window layout="horizontal" horizontalWrap="true" backgroundColor="white">
        <Button width="50%" height="50%" title="TopLeft"/>
        <Button width="50%" height="50%" title="TopRight"/>
        <Button width="50%" height="50%" title="BottomLeft"/>
        <Button width="50%" height="50%" title="BottomRight"/>
    </Window>
</Alloy>

 

However this may get a bit messy and annoying when you have to calculate for up to 20 or more views. Which brings us to

Option 2:

Let’s create a Grid View that has three columns and four rows.

// to fit in a 320-wide space 
var cellWidth = 92;
var cellHeight = 92;
var padding = 5; // padding between cells
var xGrid = 3; // how many cells wide
var yGrid = 4; // how many cells tall

/**
 * This will create a 3 x 4 gridview of 12 images
 * you can do some math to determine how many rows will be needed for your data set
 */

var tableData = [];

// array of team objects
var teams = [
    {name : 'Dragons', logo : '/images/dragon.png'}
    {name : 'Tigers', logo : '/images/tiger.png'},
    {name : 'Foxes', logo : '/images/fox.png'},
    {name : 'Dare Devils', logo : '/images/dare_devil.png'},
    {name : 'Cyclones', logo : '/images/cyclone.png'},
    {name : 'Majors', logo : '/images/major.png'},
    {name : 'Hawks', logo : '/images/hawk.png'},
    {name : 'Stallions', logo : '/images/stallion.png'}.
    {name : 'Knights', logo : '/images/knight.png'},
    {name : 'Pirates', logo : '/images/pirate.png'},
    {name : 'Crusaders', logo : '/images/crusader.png'},
    {name : 'Wolves', logo : '/images/wolf.png'},
];

var cellIndex = 0;

//

for (var y=0; y < yGrid; y++){

    var row = Ti.UI.createTableViewRow({
        className : "grid",
        layout : "horizontal",
        height : cellHeight + padding,
        selectedBackgroundColor : 'white'
    });

    for (var x=0; x < xGrid; x++){
        // the cell that will hold the logo and the team name
        var view = Ti.UI.createView({
            teamID : teams[cellIndex].name + cellIndex.toString()
            left : padding,
            right : padding,
            height : cellHeight,
            width : cellWidth
        });
        // image of the logo of the team
        var teamLogo = Ti.createImageView({
            image : teams[cellIndex].logo,
            teamID : teams[cellIndex].name + cellIndex.toString()
        })
        // label of the team's name
        var teamName = Ti.UI.createLabel({
            font : {
                fontSize:14,
                fontWeight:'bold'
            },
            text : teams[cellIndex].name,
            touchEnabled : false,
            teamID : teams[cellIndex].name + cellIndex.toString()
        });

        view.add(teamLogo);
        view.add(teamName);
        row.add(view);

        cellIndex++;
    }

    tableData.push(row);
}

var tableview = Ti.UI.createTableView({
    data : tableData
});


tableview.addEventListener("click", function(e){
    //teamId property set for each view will determine what view was clicked in the table
    if(e.source.teamID){
        Ti.API.info('Clicked: ' + e.source.teamID);
    }
});

This option gives us a very faux Grid View by using the Table View as a crutch by populating each row with several cells. This is a good option and simply by doing some math to determine the amount of rows you’d need for your data set you can make this very flexible to allow for an undetermined data length. However, a problem with this approach is that a user may notice that the entire row shows feedback for being selected. This can be avoided by substituting the Table view for a Scroll View and instead of using Table Rows, just use a View that spans the entire width and add the cell View accordingly.

Option 3:

Simply use a module. There are several good modules out there that not only make it very easy to add a grid to your project but they also add a lot of extra cool features to the Grid View like TiCollectionView and TiFlexiGrid

There are plenty of other ways to create a Grid View that aren’t mentioned above. Titanium allows for a immense of other possibilities to creating a Grid View and the only thing that you need is imagination and some problem solving skills. So even though Titanium lacks a simple way to incorporate a Grid View within your app, that does not mean you can’t Jimmy Rig your own.

Could Hyperloop be the best Appcelerator feature yet?

Could Hyperloop be the best Appcelerator feature yet?

I recently took the time to checkout out Appcelerator’s Labs page where they allow users try out pre-release software. There are some interesting projects here, but I spent most of my time experimenting with Hyperloop, which could be the best new feature in Titanium.

The Hyperloop module will allow developers to interact with native API’s directly from their JavaScript code! Titanium already covers the majority of native API’s, but some more complicated projects need API’s that are not covered. Hyperloop will make interacting with the API’s not directly covered by Titanium much easier than it has been in the past.

Hyperloop will also make it easier to use third party Android libraries or iOS cocoapods. These can be added to a Titanium project, and Hyperloop will make the library available inside the JavaScript code without having to write a native module.

There is a lot of work that goes into developing and maintaining a native module because there are two different code bases. Debugging native modules can be more time consuming when going back and forth between the native module and the Titanium project. Since Hyperloop will put the native API interaction alongside the rest of the Titanium JavaScript code, maintaining the project should be much easier.

I think Hyperloop will be one of the best additions to Appcelerator’s arsenal, but there are some improvements I would like to see before its final release.

In a typical project using Hyperloop, I might write something like this if I needed to require some native Android API’s:

var View = require('android.view.View'),
  Color = require('android.graphics.Color'),
  LayoutParams = require('android.widget.FrameLayout.LayoutParams');

A more complicated example that uses a lot of native API’s could look like this:

var FrameLayout = require('android.widget.FrameLayout'),
  ViewGroupLayoutParams = require('android.view.ViewGroup.LayoutParams'),
  Color = require('android.graphics.Color'),
  Gravity = require('android.view.Gravity'),
  View = require('android.view.View'),
  Activity = require('android.app.Activity'),
  LayoutParams = require('android.widget.FrameLayout.LayoutParams');

This looks a little messy. I would like to see ES6 style destructuring and object matching. That could make the code above look something like this:

var {
  widget : {
    FrameLayout,
  },
  view : {
    ViewGroup,
    Gravity,
    View
  },
  graphics : {
    Color
  },
  app : {
    Activity
  }
} = require(‘Android');

This could make the code much more readable as classes from the same package will be grouped together, and var’s with matching names will be created automatically.

Class inheritance is another ES6 feature that would be a good addition for Hyperloop. Inheritance is a big part of the Objective-C and Java programming languages. This allows the developer to modify the class’s function’s, but the original function definition is still available by calling the super() function. I think Hyperloop can work without class inheritance, but being able to extend the native classes from within the JavaScript code would be a huge advantage.

I, personally, cannot wait to start using Hyperloop in my daily development here at Shockoe. I think it will not only let me make more powerful applications that harness more native API’s, but it will also save me time when using third party libraries. Fewer native modules means less code to maintain down the line when operating systems and SDK’s are updated.

I think Appcelerator has a great product in development, and with a few improvements, it will be invaluable to the Appcelerator developer community.

Metalling with Titanium: Building my first Alloy application

Metalling with Titanium: Building my first Alloy application

 

Event listeners. Callback functions. Asynchronous programming? These words were foreign to me when I first started working at Shockoe LLC the first week of October 2015. But somehow, I needed to use these things to create a mobile application in the next two months.

I wasn’t completely new to programming. I had recently taking Java programming courses and was learning other languages like C++ and C# by watching online tutorials. Before I started working at Shockoe, I was told to learn JavaScript as that was predominately what I would be using to create Titanium Alloy applications. Going through the tutorial on CodeAcademy taught me little about the language. It seemed to be mostly a tutorial on what programming was. But I figured that since I had the gist of programming, I wouldn’t have much of an issue as anything could be solved with a simple Google query.

Showing up to work on the first day taught me that that wasn’t the case. Edwin, the CEO at Shockoe, assigned me to work on Fighting Mongooses, a name with which I’m now beginning to understand the logic behind.

The concept behind the app sounded pretty simple but integrating various devices, a server, a database, and mobile OS’s turned out to be far more complex than I had anticipated.

The first week or two was spent just trying to figure out what was actually happening in this partially built application.  I slowly started to figure out what the different pieces of code were doing to understand the logic. I used what was already available to piece together a rudimentary working application to fulfill the initial requirements and to prove I could fit in at Shockoe.

From there, I slowly expanded the capabilities of the application and learned more about Appcelerator, Titanium, and JavaScript along the way. After a month and a half of working on Fighting Mongoose, it has taken on a bit of my own personality. It is no longer another developer’s application that I was given to complete and that is a great feeling.

There is still a lot that I need to learn to get near the level of the other developers here, but I have had some great guidance and help while working on the Fighting Mongooses project.

I still have much that I wish to accomplish with the application and feel more comfortable and confident each day with what I’m doing.

I recently found an old version of the app on a device I used for testing about a month ago and it’s amazing to see for myself the progress that I have made since.

I look forward to see the kind of progress I can make in the next month on onward here at Shockoe.

 

 

Appcelerator Titanium iOS Debugging with XCode

Appcelerator Titanium iOS Debugging with XCode

Earlier this week, I was debugging and I was reminded of the sheer power of the XCode developer tools, even in the context of a not-quite-native application like a titanium application.

The Problem

Andrew was working on an application that will load in a large number of images and PDFs from a remote server and display them to the user, in-app. However, when we got to the point that we would be displaying a certain one of our images, we saw this in the Titanium console:

[ERROR] invalid image type. expected TiBlob, String, TiFile, was: TiBlob -[TiUIImageView setImage_:](TiUIImageView.m:687)

Sorry, what? It seems like something odd is happening at a native level, and Titanium is getting too confused to return a sensible error message. Well, guess it’s time to open a support ticket with Appcelerator and wait for them to figure out what the issue could be, right?

Wrong. One of my favorite things about Appcelerator Titanium is its open-source nature. What we can do from here, is open up the native project generated by Titanium and debug it with the normal native debugging tools. When you build a Titanium application for iOS, a (pretty much) normal XCode project is generated from your project, compiled, and run on whatever test device you have selected. In situations like this, we can take that project and manually re-build it in XCode for debugging purposes.

Opening your project in XCode

To open your project in XCode, first run

ti build -p ios --build-only

in your project’s directory. This will ensure you have a native project generated for your Titanium project. From here, all you need to do is open XCode, and open up the XCode project in the build/iphone folder.

Path to a Titanium project's compiled XCode Project

Setting Native Breakpoints

Now that we’ve got the project in XCode, we need to set up a native breakpoint so that we can see what the issue is with the Objective-C code that Titanium is executing on our behalf. Fortunately, the message that Titanium printed out gave us a selector name:

-[TiUIImageView setImage_:]

. Let’s go ahead and set up a symbolic breakpoint for that selector:

Add a breakpoint in XCode by clicking the second icon from the right in the side bar, and then clicking the plus in the bottom right

Add the symbol from the error as the symbol name

Enter the XCode debugger

Now that we’ve got our breakpoints set up, we can run the project in XCode, and execution will stop when our breakpoint is hit in the Titanium SDK code.

The debugger will automatically pause execution when you hit a breakpoint.

Let’s go ahead and step over a few commands and see if we can figure out exactly what’s going wrong.

Step Over

Huh, it looks like we’re having some issue turning our Titanium file into a UIImage that we can apply to the native UIImageView. Let’s use the variable inspector to figure out exactly why we’re failing to convert this into an iOS image.

XCode variable inspection

Well, one look at the MIME type is enough to see exactly what’s wrong. Our file isn’t an image! Even though this didn’t tell us exactly where the issue was, it was enough to direct our debugging (we eventually figured out that we were accidentally saving a PDF file as an image – oops!). Issues like this are why I’m very quick to reach for XCode when I see a native iOS issue – it makes it much easier to figure out what parts of your code might be incorrect when you can easily trace through Appcelerator’s code!

Building a better Titanium app with Backbone Events

Building a better Titanium app with Backbone Events

Building an app with Titanium gives you access to all of the speed of a native framework while giving you the flexibility that you know and love from Javascript, but exposes you to all manner of potential memory issues that traditional native developers are not familiar with. Enter Backbone.js, a not-so-well-kept secret to creating a well structured app dizzyingly quickly. Backbone allows you to define events on most any javascript object, giving you flexibility and control over how your components interact with each other.

Dependencies and upgrading

If your project is built with Alloy, good news!  An older version of Backbone ships with Alloy by default, as well as its underscore dependency.  If you’re maintaining a classic Titanium project, you can download the most recent version of Backbone and underscore from here and use them like normal commonjs libraries.  Additionally, we have provided an updated version of Backbone that has been modified to work with the current version of Alloy.  To use it in an Alloy project, just place the minified version in your lib folder and add


Backbone = require('backbone.min.js');

to alloy.js.

An aside on the topic of mixins

Backbone is an example of an awesome design pattern that Javascript encourages, namely mixins.  The way mixins work is that they define a set of functions that can work if assigned to any Javascript Object.  This allows you to eschew classical inheritance structures in favor of defining small, self-contained pieces of functionality that can be harmoniously applied to a single Object (which can have a prototype, other mixins, or both!).  They’re also a great way to achieve an effect similar to classical inheritance in cases where you can’t use normal prototype chains, like Alloy controllers.  Mixins can be defined in a number of ways, be it by creating a normal Javascript object containing a set of functions that can be copied to another object, or by declaring a function that applies all of the functions in the mixin to a parameter object.  Backbone.Events is an example of a mixin declared as a normal Javascript object.

On to the main Backbone.Event

The core advantage of building a Titanium app with Backbone is its powerful event system, and it couldn’t be easier to use.  To mix in Backbone Events to an alloy controller, just add

_.extend($, Backbone.Events);

to the beginning of your controller (note that you can substitute any javascript object for the first argument).

Now that you have backbone events mixed in to your controller, you can start listing to and triggering them.  First, let’s set up an event listener.


var eventedController = Alloy.createController("controllerWithEvents");

eventedController.on('aCoolEvent', function(){
  alert('Something neat just happened!');
});

To break down that code snippet, using the ‘on’ function from underscore you can subscribe a function to be executed every time that some event is fired.  Then, from whithin the other controller, you can use the ‘trigger’ function to notify listeners of some action.  For example, if you had some picker controller, you could trigger a ‘change’ event whenever the user makes a new selection, and then listen for that event from the parent controller.

So why not normal callbacks?

The advantage of using Backbone events over just using normal Javascript callbacks is twofold.  For one, you can easily register multiple event listeners to a single event.  Since the event is just a simple ‘broadcast’, you can hook up multiple listeners for the same event without the triggering controller having to have any awareness of its listeners.  For example, you could set up a UI controller to listen to cache update events. You could then set up your network library to just broadcast update events.  Then, if you later need to hook something in to automatically update on cache update, you can easily listen to the same event.

Secondly, Backbone exposes a handful of functions that makes it very easy to clean up event listeners en masse.  You can use ‘off’ to dismiss event listeners individually, dismiss listeners for an individual event, or tear down every event listener associated with a given object.


//make an evented object
var eventObject = _.extend({}, Backbone.Events);
//register a few listeners
function listenerOne(evt){
  // ...
};
//register a named function as a listener
eventObject.on('someEvent', listenerOne);
//register a bunch of anonymous listeners
for(var ii = 0; ii < 10000; ii++){
  eventObject.on('someOtherEvent', function(){
    // ...
  });
}

//now let's get weird.

//register a bunch of events with random names
for(var jj = 0; jj < 10000; jj++){
  //use the built in sha1 function to generate a event name from the current time 
  //(realistically, you would generate events like this based on some data object,
  //sensible example omitted for brevity) 
  var eventName = 'dynamicEvent' + require('alloy/sha1').hex_sha1(new Date());

  //now register an event listener with the dynamic event
  eventObject.on(eventName, function(){
    // ...
  });
}

//dispose of just on listener on the object, providing event name and function reference
eventObject.off('someEvent', listenerOne);

//uh oh, how are we going to get rid of those anonymous listeners?

//just don't provide the function reference to off!
eventObject.off('someOtherEvent');
//This will tear down every listener for the provided event.

//and now to tear down the random, misc events.
//we don't know the event name, so just call off to tear down everything
eventObject.off();

In addition to this system for managing events, the most recent version of Backbone provides a number of functions to allow objects to better manage their event listeners.


//index.js

//create some evented object
var eventObject = _.extend({}, Backbone.Events);

//also event the controller
_.extend($, Backbone.Events);

//set up to listen to some event exactly once
eventObject.once('someEvent', function(){
  // ...
});

//set up the controller to listen for events on the object
$.listenTo(eventObject, 'someEvent', function(){
  // ...
});
//set up the object to listen for some controller event once
eventObject.listenToOnce($, 'someControllerEvent', function(){
  // ...
});
//tear down the listener from the controller
$.stopListening(eventObject, 'someEvent');
//you have the same argument flexibility as off with stopListening
//stop listening to an entire object
$.stopListening(eventObject);
//stop listening to anything
$.stopListening();

The advantage of using the listenTo pattern is that either object can tear down an event listener shared by them. This has important implications for Alloy controllers: as long as you manage most of your cross-controller interactions through Backbone.Events, you can tear down every event listener originating from a controller with a single call. We can use this feature to set up intelligent disposal functions that let us tear down most references to a controller quickly and prevent memory issues.


//index.js

//declare a disposal function
$.dispose = function(){
  //first, trigger an event to notify other controllers that this one is being torn down.
  $.trigger('dispose');
  //then, use Underscore.defer to set up a function to be executed after the dispose event
  //has been handled.
  _.defer(function(){
    //tear down all listeners on this controller
    $.off();
    //and tear down all of the event listeners originating from this controller
    $.stopListening();
  });
};

And that’s it. From here, you can set up other controllers to listen to the dispose event and do things like remove the controller when its disposed or build out new UI on controller disposal. Then, after all of the dispose listeners have been handled, all event relationships are automatically disposed of. Assuming you clean up all of your references in dispose events, there’s nothing else you need to do for the average controller to keep memory in check. Bear in mind that things like app-wide events (such as events on Titanium.App, Titanium.Geolocation, Titanium.Gesture, etc.) can still lead to memory leaks and should be handled in your disposal listeners.

You can read more about Backbone.js at the project’s website.
For more information about Backbone’s dependency Underscore and how you can use it to code better and faster, check out our blog post!

Enabling Push Notifications Part 2 of 3

Enabling Push Notifications Part 2 of 3

This document is intended for the average Titanium Developer to enable push notifications.  It is assumed that the reader already has a basic knowledge of Titanium and the APIs.

Today we will talk about Part 2 of 3 of Push Notifications, which begins with Google App Registration.

Register your application with Google

Android Setup

  1. Create a Google API Project

  2. Register with Appcelerator Cloud Services

Step 1: Create a Google API Project

 

You will need to open the Google Developers Console by visiting https://cloud.google.com/console. From there you will need to sign in with your Google ID that you want to be associated with this project.  Once signed in you will see a basic screen and a big red button that says ‘CREATE PROJECT’.

Enter a Project Name, and ignore Project ID.  Project ID is randomly generated by Google to avoid duplication of IDs.  Click the ‘Create’ button and the Google Developer.

The console should refresh.  Now you should be on the projects Overview page.  At the top of this page, you will see Project ID and Project Number.

 

Copy the Project Number, since this will be used at a later point as the GCM Sender ID.  On the left corner of the page, there is an APIs & Auth section.  Go to that page and a list of API items will populate.  Turn On the Google Cloud Messaging for Android.

Again under APIs & Auth you will see ‘Credentials’, click here.  Now you will see a section called ‘Public API Access’.  Click the ‘CREATE NEW KEY’ button to generate an API Access Key.

A popup will appear, on that select ‘Server Key’.  Another popup will appear asking you to enter IP Addresses in the text field, just click ‘Create’.

DO NOT ENTER ANY IP ADDRESSES

Now under the Public API access section, there is a section for API key with a rather strange combination of letters & numbers.  Copy that text and hang onto it.  Now go to the Appcelerator Dashboard https://dashboard.appcelerator.com/.

As before select the app you are working with and click the ‘Cloud’ tab.  On the left menu click ‘Settings & Configurations’.  Then on the tabbed menu click ‘Android Push’.  It will ask you for the GCM API Key and GCM Sender ID, which you should have saved.  Enter those values in and click ‘Save Changes’.

Implement the code into a Common JS library

Ensure that you are using a Common JS library for notifications.  Create a ‘notifications.js’ file inside the ‘lib’ folder.  If the folder does not exists then create it.

iOS Code Setup

With iOS, you must use Ti.Network.registerForPushNotifications the first time the user enters the application.  After registering with the server, the function should return a device token.  Save this device token in-app properties.

Example: Ti.App.Properties.setString(‘deviceToken’, e.deviceToken);

However, make sure you set the application properties on the callback and not inside the common JS library.  These lib files can sometimes act strangely when it comes to saving app properties.

index.js

//require the notifications common js lib file
var notifications = require('notifications');
//check for a device token
var deviceToken = Ti.App.Properties.getString('deviceToken');

//check to see if deviceToken exists
if(deviceToken === '') {
	//create a device token by registering for notifications
	deviceToken = notifications.register();
	//set the deviceToken app property
	Ti.App.Properties.setString('deviceToken', deviceToken);
}
//open the index window
$.index.open();

//controller
var mainWindow = Alloy.createController('Main').getView();
//open the mainWindow
mainWindow.open();

notifications.js

//require ti.cloud for iOS Notifications
var Cloud = require('ti.cloud');

//register the device and receive a token
exports.register = function() {
    Ti.Network.registerForPushNotifications({
        // Specifies which notifications to receive
        types: [
            Ti.Network.NOTIFICATION_TYPE_BADGE,
            Ti.Network.NOTIFICATION_TYPE_ALERT,
            Ti.Network.NOTIFICATION_TYPE_SOUND
        ],
        success: deviceTokenSuccess,
        error: deviceTokenError,
        callback: receivePush
    });
    // Process incoming push notifications
    function receivePush(e) {
        alert('Received push: ' + JSON.stringify(e));
    }
    // Save the device token for subsequent API calls
    function deviceTokenSuccess(e) {
        return e.deviceToken;
    }
    // Display an error upon failure to register
    function deviceTokenError(e) {
        alert('Failed to register for push notifications! ' + e.error);
    }
};

The device token that is generated will allow the application to receive notifications.  You will be able to register the device with ‘Channels’.   The server can push information to certain Channels.  Say you want sports news updates.  Then a Channel called ‘sports_updates’ could be created.  Channels are not done on the server side.  Creation is done on the user side.  There is not a way to manually add a channel on the ACS Dashboard.  Once a user subscribes to a channel for the first time then it is created.


//subscribe to a specific channel
exports.subscribe = function(channel, token) {
    Cloud.PushNotifications.subscribeToken({
        device_token: token,
        channel: channel
    }, function (e) {
        if (e.success) {
            alert('Subscribed');
        } else {
            alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
        }
    });
};

Subscribing a device token to a channel is a function in the common JS library you created for Push Notifications.  In this function, we pass two variables. One is the channel and the other being the device token that was generated earlier.  Each one is needed for the subscription.


//unsubsribe from a specific channel
exports.unsubscribe = function(channel, token) {
    Cloud.PushNotifications.unsubscribeToken({
        device_token: token,
        channel: channel,
    }, function (e) {
        if (e.success) {
            alert('Unsubscribed');
        } else {
            alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
        }
    });
};

You will also need to allow the user to unsubscribe from Channel based Pushed Notifications, which can be done using the unsubscribe function.

Main.js

//device token
var deviceToken = Ti.App.Properties.getString('deviceToken');
//require notificiations lib file
var notifications = require('notifications');
//create view to house label and buttons
var container = Ti.UI.createView({
	width           : Ti.UI.FILL,
	height          : Ti.UI.FILL,
	top             : 30,
	layout          : 'vertical',
	backgroundColor : '#FFFFFF'
});
//create label for title
var channelLabel = Ti.UI.createLabel({
	width     : Ti.UI.FILL,
	height    : Ti.UI.SIZE,
	text      : 'Select a Channel',
	textAlign : 'center'
});
//create sports channel button
var sportsButton = Ti.UI.createButton({
	width     : Ti.UI.FILL,
	height    : Ti.UI.SIZE,
	top       : 10,
	title     : 'Sports'
});
//sports button event listener
sportsButton.addEventListener('click', function(e){
	if(deviceToken !== '') {
		notifications.subscribe('sports_updates', deviceToken);
	} else {
		alert('Error, device not registered for Push Notifications');
	}
});
//add elements together
container.add(channelLabel);
container.add(sportsButton);
$.win.add(container);

Now we need to create a sample page to test this all out with.  It will have a view, label, and button.  Clicking this button will subscribe the user to sports updates from the ACS server.

This will create a basic view with a label and button on top of the window.  It will say ‘Sports’ and upon click will call the register function from the notifications lib file.

notifications.js Again


exports.userLogin = function() {
    // Log in to ACS
    Cloud.Users.login({
        login: 'push_notifications',
        password: 'pushy'
    }, function (e) {
        if (e.success) {
            alert('Login successful');
        } else {
            alert('Error:\n' +
                ((e.error && e.message) || JSON.stringify(e)));
        }
    });
};

You can also have users set up on the ACS server and log them in and subscribe to channels.  However, the user account must exist.  Generally, one user is created for the public, such as the ‘push_notifications’ user we see in the code.   This is perfect for just a basic app with notifications.  If you want user sessions and give the ability for people to create their own accounts you will have to look into Titanium.Cloud.Users on the documentation.

 

Try it and leave a comment below to let us know if you had any problems following these steps.

We will continue next week with part 3.

Underscore.js – Everything you didn’t know you needed

Underscore.js – Everything you didn’t know you needed

Underscore.js (_.js for short) is a phenomenal javascript library that most web and Titanium developers are likely familiar with at this point.  What you may not know is that _.js is bundled with Alloy, letting you use the awesome collection of commonly used functions with little effort on your part.  I’ve compiled a few of my favorites here:

_.each

Underscore’s each function is a great alternate to Javascript’s built in for function, with the key difference that it allows you to have a local scope to work in (as opposed to Javascript’s built in for, which inherits the parent scope).


var people = [{name : "john"}, {name : "amy"}, {name : "bill"}];
//traditional for loop
for (var i = 0; i < people.length; i++){
  var person = people[i];
  Ti.API.info(person.name);
}
//this will print out 'bill' again, since the for uses the parent's scope
Ti.API.info(person.name);

//with _.each
_.each(people,function(person2){
  Ti.API.info(person2.name);
}
//but this won't work, since person2 is out of scope!
Ti.API.info(person2.name);

_.memoize

Memoize does exactly what the name says!  It takes a function, and returns a version of it that will only calculate its return value once for a given set of inputs, and then cache this value and return it on subsequent calls.  It’s absolutely great for functions that always give the same result but can take a long time to compute (the Fibonacci sequence is an oft-used example).  For more information, Wikipedia has a great page on memoization.

Another great use would be for hash functions (e.g. the also-bundled-with-alloy sha1)


var sha1 = require('alloy/sha1');
//memoize the hash function
var cachedSha = _.memoize(sha1.hex_sha1);
//now you can use the memoized version like any other js function!
var hash = cachedSha("hash me!");

_.isWhatever

Underscore provides a awesome set of isSomething functions that can tell you all kinds of things about a given variable, ranging from its type to whether it is finite. Examples include isEmpty, isArguments, and isDate.


_.isEmpty({});//true
_.isArray([]);//true
var notArguments = [1,2,3];
_.isArguments(arguments);//true
_.isArguments(notArguments);//false
_.isString(NaN);//false
//etc. etc.

_.once, _.throttle, and other function modifiers

_.once and _.throttle are great for controlling frequency of execution of functions. Simply put, _.once makes it so a function can only be executed once, and _.throttle rate limits a function so that it can only be executed once every so often (e.g. at most once every 200 ms).  Both are extraordinarily useful in the context of Titanium for dealing with issues associated with events getting created too quickly to be handled in a sensical fashion, such as a user tapping a button too quickly or scrolling too fast. Other awesome function processing functions include _.after (provided function is executed after being called a certain number of times), and _.debounce (function is only executed after it hasn’t been called for some period of time).


//only initialize the app once
var init = _.once(function(){
  //stuff here
});
init();
init();
//was only executed once

And more!

Underscore.js contains roughly 80 different commonly used functions for different purposes, too many for me to possibly go over here.  Take a look at their docs, and feel free to leave comments about your favorites below!