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.

Profiling Titanium: Getting a picture of the Kroll toll

Profiling Titanium: Getting a picture of the Kroll toll

As cross-platform developers, we all know that maintaining speed in a complex codebase is of paramount importance. When you’re adding layers of abstraction to your code in hopes of being able to share large portions of it across disparate platforms, the little steps you have to take to synchronize your common code with the underlying platform-specific code can quickly add up to a massive slowdown that leaves you with an application that performs and feels no better than a mobile web application plopped into a WebView.

The Kroll Bridge

Titanium effectively acts as a three-tier framework. At the lowest level, there is a layer of native code used to implement core application functionality. These are your views, your HTTP clients, and your other pieces of code that reach out and allow you to interact with device features like the camera and geolocation service. On top of these platform-specific native layers lies a platform-specific bridging layer, which allows you to abstract away the complexity of these native objects and translate them into Javascript-land objects (called proxy objects). Finally, on top of this bridging layer lies your application-specific Javascript code, which is where the bulk of your application logic will reside.

 

Titanium’s abstraction and the bridging layer is known as the Kroll Bridge, and it represents the single biggest bottleneck in a Titanium application. The Kroll bridge is exactly what it sounds like, it’s a connection between the native objects in your application provided by the Titanium SDK and the Javascript proxy objects that stand in their place within your Javascript code. Every time you update one of your proxy objects, the Kroll bridge gets to work synchronizing your changes to the native object. Because of this automatic synchronization logic, it’s easy to make a huge number of Kroll calls without really recognizing what you’re doing, which leaves you with an application that has no obvious performance issues (from a code perspective) that has distinct slowdowns when placed on a physical device.

Acknowledging the Kroll cost

Titanium provides various methods of sending data back and forward between your Javascript code and your native code. For the most part, these can be divided into the categories of bulk operations vs sequential operations. Going into this blog post, I had intended to write at length about the virtues of batching your calls and minimizing your Kroll crossings, however, it seems like there may be more nuances to the performance concerns in Titanium than I had thought! For the purposes of this blog post, I’ve taken a look at how long various operations block the Titanium thread.

I’ve prepared a couple of minimal test cases, with built-in timestamping and simple profiling code, so feel free to test these cases on your own devices! For each of these tests, we’ll run some operation 1000 times and take the difference in milliseconds between the start of the operations and the end. Note that this testbed only takes a look at how long different operations tie up the Titanium thread. Many of these tests tie up the UI thread for a substantial amount of time as well and will cause the app to become unresponsive. The UI thread performance of these tests are outside of the scope of this blog post, I’d like to circle back in a few weeks and take a closer look at the UI impact of these tests as well.

I ran all of my tests on a Nexus 5 running Android 6.0 Marshmallow and an iPhone 5 running iOS 9.1. I ran six trials of each of these tests and averaged the results. I’ve published the test code on GitHub. Take a look, give it a clone, and follow along on your own devices.

Creation arguments vs Create then set

Titanium provides factory methods to create proxy objects, which allow you to interact with native objects that you may need multiple instances of. Optionally, these methods accept a creation dictionary describing its initial state. Of course, you can just make the proxy and then configure it later, what’s the difference?

var newView = Ti.UI.createView();
 
newView.top = 5;
newView.height = 40;
newView.width = Ti.UI.FILL;
newView.left = 5;
newView.right = 5;
newView.backgroundColor = 'red';
var newView = Ti.UI.createView({
    top : 5,
    height : 40,
    width : Ti.UI.FILL,
    left : 5,
    right : 5,
    backgroundColor : 'red'
});

 

On iOS, this behaves largely as expected. Creation with arguments returns a little faster than the creation followed by sets. On Android, however, in addition to being substantially slower, the creation dictionary actually slowed the creation process down!

Sequential updates vs applyProperties

Similarly, Titanium provides both individual property set APIs as well as a bulk application API. Take the following examples:

view.height          = 80;
view.backgroundColor = 'blue';
view.left            = 10;
view.right           = 10;
view.applyProperties({
	height          : 80,
	backgroundColor : 'blue',
	left            : 10,
	right           : 10
});

 

Oddly enough, we observe the opposite behavior here from view creation! Android performs as expected, with the bulk API yielding better performance. iOS, on the other hand, runs quite slowly, and the bulk API is slower than the sequential sets.

TableView population

The table structures in Titanium also provide bulk or individual modification APIs. Consider the following examples:

for(var ii = 0; ii < 1000; ++ii){
	var newRow = Ti.UI.createTableViewRow({
		top : 5,
		height : 40,
		width : Ti.UI.FILL,
		left : 5,
		right : 5,
		backgroundColor : 'red'
	});

	theTable.appendRow(newRow);
}
var tableData = [];
for(var ii = 0; ii < 1000; ++ii){
	var newRow = Ti.UI.createTableViewRow({
		top : 5,
		height : 40,
		width : Ti.UI.FILL,
		left : 5,
		right : 5,
		backgroundColor : 'red'
	});

	tableData.push(newRow);
}

theTable.setData(tableData);

 

Finally, an expected result! The bulk population API is massively more performant than the individual population API. Android is still a little slower than iOS, but that is mostly expected.

View Removal

When flushing the views within a hierarchy, you can either loop over the children array or call removeAllChildren.

var children = theWindow.children;

for(var ii = 0, numChildren = children.length; ii < numChildren; ++ii){
	theWindow.remove(children[ii]);
}
theWindow.removeAllChildren();

 

Another API that performs differently on iOS vs Android. On iOS, the call to removeAllChildren is almost immediate, whereas on Android the call takes even longer than looping over the entire child list and removing them individually.

Event Firing

Titanium exposes a built-in eventing API used for communicating between native code and Javascript code. Additionally, Backbone exposes an eventing API for communication between Javascript objects. I frequently see the Titanium eventing API repurposed for use in Javascript-land communication, let’s see what the impact is.

var startTime;

var handledCount = 0;

function testListener(){
	handledCount++;

	if(handledCount === 10000){
		var endTime = new Date();
		var delta = endTime - startTime;

		alert('fired 10000 Ti.APP events in ' + delta + 'ms');

		Ti.App.removeEventListener('testEvent', testListener);
	}
}

Ti.App.addEventListener('testEvent', testListener);

startTime = new Date();

for(var ii = 0; ii < 10000; ++ii){
	Ti.App.fireEvent('testEvent');
}
var startTime;

//since events fire asynchronously, we need to keep track of how many were handled.
var handledCount = 0;
var eventingObj = _.extend({}, Backbone.Events);

eventingObj.on('testEvent', function(){
	handledCount++;

	if(handledCount === 10000){
		var endTime = new Date();
		var delta = endTime - startTime;

		alert('fired 10000 Backbone events in ' + delta + 'ms');
	}
});

startTime = new Date();

for(var ii = 0; ii < 10000; ++ii){
	eventingObj.trigger('testEvent');
}

 

Another substantial difference. Backbone events perform consistently (and impressively well!) on both platforms, whereas Titanium events are much slower on iOS, and are a little slower on Android.

Takeaways

The clearest takeaways from these tests are that one needs to be much more careful while modifying the view hierarchy on android, that Ti.App events are quite slow, and that there isn’t a one-size-fits-all performance solution for Titanium. There’s no magic bullet that you can adopt in your codebase and not have to worry about platform-specific performance issues. Android’s slowness when handing creation dictionaries and iOS’s aversion to applyProperties makes it more difficult to write platform-agnostic performant code. That being said, in the general case, applyProperties is still worth using, because of the small performance hit we took on iOS and the performance bump we get on Android (which is usually the issue from a performance perspective).

At the end of the day, there’s no substitute for profiling your application and making use of the platform-specific Alloy preprocessor directives (OS_ANDROID, OS_IOS) to deal with platform-specific performance issues. And now that we’re armed with concrete data, we’re ever so slightly better equipped to do that!

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.

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!

Digest Authentication with Appcelerator Titanium HTTPClient

Digest Authentication with Appcelerator Titanium HTTPClient

I’ve been working with web technologies for over a decade and never had to touch Digest Access Authentication.  All of the services I had worked with had other solutions for authentication.  A few months back that all changed.  I was finishing up a mobile project, to be used for internal purposes for the client, when suddenly the API requirements changed.  They had implemented Digest Access Authentication with MD5.  Uh-oh.

What is Digest Authentication?

Let’s start small; I certainly had to.  Digest Access Authentication is a method for validating a user and granting them some access over HTTP.  It involves making a request, being presented with a challenge, answering that challenge with another request, and finally getting the resource originally requested.  It works like this:

  1. Client sends request to the server
  2. Server responds with a nonce (number to be used once) with a status of 401
  3. Client makes another request to the server providing identification information
  4. Server evaluates whether the user is valid and if they are who they say are
  5. Server responds with desired resource

How do we do this in Titanium?

The idea is to send out requests like normal, check for a 401 status code, and respond to the presented challenge if applicable.  That is simple enough:


//Create the HTTPClient
xhr = Titanium.Network.createHTTPClient();

xhr.onload = function(){
	//Process the response
}

xhr.onerror = function(){
	//Process an error
	if(this.status == 401){
		//Respond to challenge
	}
}

When I was originally tackling this problem I found a very helpful example on github by rollsroyc3: https://gist.github.com/rollsroyc3/6869880  The majority of the following code is from that example, but I made a few changes.

Before adding any code to actually handle the challenge, let’s take a step back.  Assuming you have multiple HTTPClients, like I did, every HTTPClient would need to be rewritten.  Instead, let’s encourage code reuse and turn this into a commonJS lib that wraps the HTTPClient.  Then we can have one HTTPClient that does Digest Authentication when it encounters a 401 status code and acts normally with all others:

(I use underscore.js a bit here, and you should too)


var timeout = 2000;

 
 /**
  * The authentication magic.
  *
  * Breaks down a 401 request from a digest authentication endpoint and generates a response
  * 
  * @param  {Response Headers} h : The response headers
  * @return {Request Headers} : The request headers to match the response
  */
function parseAuthenticationResponse(h) {
	var auth = {
		headers : {}
	};
	var scre = /^\w+/;
	var scheme = scre.exec(h);
	auth.scheme = scheme[0];
 
	var nvre = /(\w+)=['"]([^'"]+)['"]/g;
	var pairs = h.match(nvre);
 
	var vre = /(\w+)=['"]([^'"]+)['"]/;
	var i = 0;
	for (; i < pairs.length; i++) {
		var v = vre.exec(pairs[i]);
		if (v) {
			auth.headers[v[1]] = v[2];
		}
	}
	return auth;
}

/**
 * Generates a unique token for a CNONCE value using the device ID and current time
 * @return {String} : Unique token for a CNONCE value
 */
function generateUniqueCNONCE(){
	return new Date().getTime() + Ti.Platform.id;
}
 

/**
 * Performs the secondary request with our response to the challenge
 * @param  {String}   requestType : HTTP verb
 * @param  {String}   url         : The location of the desired resource
 * @param  {Object}   postData    : Any data that needs to be sent with the request
 * @param  {String}   header      : The Authorization Header
 * @param  {Function} onload      : Callback if successful
 * @param  {Function} onerror     : Callback if failure
 * @return {void}             
 */
exports.httpClient = function(requestType, url, postData, header, onload, onerror) {
	//Create the client
	var xhr = Titanium.Network.createHTTPClient();

	//We've already tried to authorize at this point, send the appropriate callbacks
	xhr.onload = function() {
		if (_.isFunction(onload)){
			onload((this.responseText ? JSON.parse(this.responseText) : null), xhr);
		}
	};
 
	xhr.onerror = function(e) {
		if(_.isFunction(onerror)){
			onerror(xhr, e);
		}
	};

	xhr.setTimeout(timeout);

	//Perform the request
	xhr.open(requestType, url);
 
 	//Set the header
	header && xhr.setRequestHeader("Authorization", header);
 
	if ((requestType == 'POST' || requestType == 'PUT' || requestType == 'DELETE') && postData) {
		//Set the content type
		xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
		//Stringify the post data, to ensure it's not url encoded
		xhr.send(JSON.stringify(postData));
	} else {
		xhr.send();
	}
};

/**
 * Performs the initial request
 * @param  {String}   requestType : HTTP verb
 * @param  {String}   url         : The location of the desired resource
 * @param  {Object}   postData    : Any data that needs to be sent with the request
 * @param  {Function} onload      : Callback if successful
 * @param  {Function} onerror     : Callback if failure
 * @param  {Object}   user        : Object containing username nad password for auth
 * @return {void}             
 */
exports.httpClientDigest = function(requestType, url, postData, onload, onerror, user) {
	//Create the client
	var xhr = Titanium.Network.createHTTPClient();

	//If all goes well we don't need to do anything!
	xhr.onload = function() {
		if(_.isFunction(onload)){
			onload((this.responseText ? JSON.parse(this.responseText) : null) || this.responseText, xhr);
		}
	};
 
 	//If there's an error, we need to check for an authentication challenge
	xhr.onerror = function(e){
		if (this.status == 401) {
      		//401 error, time to authenticate
			var headers = this.getResponseHeaders();
			var tokensObj = parseAuthenticationResponse(headers['Www-Authenticate']);
 
 			//Build the headers
			tokensObj.headers.cnonce = generateUniqueCNONCE();
			tokensObj.headers.nc = '00000001';
			tokensObj.headers.algorithm = 'MD5';
			tokensObj.headers.method = requestType;
			tokensObj.headers.domain = url;
 
			var HA1 = Ti.Utils.md5HexDigest(user.username + ':' + tokensObj.headers.realm + ':' + user.password);
			var HA2 = Ti.Utils.md5HexDigest(tokensObj.headers.method + ':' + tokensObj.headers.domain);
			var authResponse = Ti.Utils.md5HexDigest(HA1 + ':' + tokensObj.headers.nonce + ':' + tokensObj.headers.nc + ':' + tokensObj.headers.cnonce + ':' + tokensObj.headers.qop + ':' + HA2);
			var responseContentHeader = 'Digest username="' + user.username + '"' + ', realm="' + tokensObj.headers.realm + '"' + ', nonce="' + tokensObj.headers.nonce + '"' + ', uri="' + tokensObj.headers.domain + '"' + ', algorithm="' + tokensObj.headers.algorithm + '"' + ', response="' + authResponse + '"' + ', qop="' + tokensObj.headers.qop + '"' + ', nc=' + tokensObj.headers.nc + ', cnonce="' + tokensObj.headers.cnonce + '"';
      
      		//Respond to the authentication and request the resource again
			exports.httpClient(requestType, url, postData, responseContentHeader, onload, onerror);
		}
		else{
			//Some other error, let the callback handle it
			if(_.isFunction(onerror)){
				onerror(xhr, e);
			}
		}
	};

	xhr.setTimeout = timeout;

	//Perform the request
	xhr.open(requestType, url);
	
 
 	//Evaluate whether there is data to send
	if ((requestType == 'POST' || requestType == 'PUT' || requestType == 'DELETE') && postData) {
		//Set the content type
		xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
		//Stringify the post data, to ensure it's not url encoded
		xhr.send(JSON.stringify(postData));
	}
	else {
		xhr.send();
	}
};

We can then require this in and use it:


var httpDigest = require('httpDigest');

//Data to send
var data = {
	test: 'string'
};

//Connect through HTTP Client with Digest
httpDigest.httpClientDigest('POST', address, data, function(response, client){
	//Do something on success
},function(client, e){
	//Do something on failure
}, {username: 'username', password: 'password'});

Improvements

This is just one example of how it can be accomplished.  Your needs may be different.  There are many more options available to the HTTPClient that are not exposed (like headers).  This was a quick and dirty solution to a last minute problem.

If I needed the library today for a new project I would modify it to make use of Backbone events.  Imagine different components being notified when a new request has been made, when that request has been met with Digest Access Authentication, and when the response is finally successful!  Evented networks are both a blessing and a curse.  Allowing various controllers to listen for updates to data is amazing, but if you’re not careful with cleanup then you’re begging for memory leaks.

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 3 of 3

Enabling Push Notifications Part 3 of 3

Android Code Setup

Android is set up the same way with just a few minor differences.  On Android, we use the ti.cloudpush module and ti.cloud for Push Notifications.  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.

//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 === '') {
	//get the devices token
	deviceToken = notifications.getToken();
	//set the deviceToken app property
	Ti.App.Properties.setString('deviceToken', deviceToken);
}

In the index js file we set up the device to look for a token and if there is not one to register the user for Push Notifications.

//require ti.cloudpush module
var CloudPush = require('ti.cloudpush');
//require ti.cloud module
var Cloud = require('ti.cloud');

//get device token
exports.getToken = function() {
  // Initialize the module
  CloudPush.retrieveDeviceToken({
      success: deviceTokenSuccess,
      error: deviceTokenError
  });
  // Enable push notifications for this device
  function deviceTokenSuccess(e) {
      CloudPush.enabled = true;
      return e.deviceToken;
  }
  function deviceTokenError(e) {
      alert('Failed to register for push notifications! ' + e.error);
  }
  // Process incoming push notifications
  CloudPush.addEventListener('callback', function (evt) {
      alert(evt.payload);
  });
};

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.  Then a Channel called ‘sports_updates’ could be created.  Channels are not done 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.

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 being the channel and the other being the device token that was generated earlier.  Each one is needed for the subscription.  Now the module ti.cloud will be required for this project as well.  The first module, ti.cloudpush, is just for registering a device token, and ti.cloud does the rest.  So we add ti.cloud to the notifications lib file.

//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.

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

//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)));
        }
    });
};

//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

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.

Sending Push Notifications using the Dashboard (http://dashboard.appcelerator.com)

This will cover three different ways for notifications to be sent.

Sending to Specific Channel/Users
Sending to All Channels
Setting up Recurring Notifications

 

Go to the Dashboard, then Cloud, then Push Notifications.  You will see a button that says ‘Send Push Notification’, click on it.

Sending to Specific Channel/Users

  • Channel – Which channel to send the notification to

    • Choose ‘Specific Channel’

  • Choose ‘Specific Channel’

  • Users – You can choose to enter a username if you have created any to notify just users who subscribe to that channel.

  • Alert – The message body you want the user to see

  • Send When – The time you would like to send the notification

    • Choose ‘Send Now’

  • Title – The title of the notification

Let’s say we notify the ‘sports’ channel, then we need to choose ‘Specific Channel’ under the Channel.  Then under ‘Channel Name’ you would put ‘sports’.  The ACS server is Case Sensitive, so stick with lowercase or camel case.  For the ‘Alert’ section just come up with something such as ‘Richmond, Virginia to get a Major NFL Team’.  Under ‘Send When’ choose ‘Send Now’.  Then for ‘Title’ enter ‘WZYB Sports’ or something like that.

 

Click ‘Save Changes’ which will send the notification to the subscriber devices.

Sending to All Channels

  • Channel – Which channel to send the notification to

    • Choose ‘All Channels’

  • Alert – The message body you want the user to see

  • Send When – The time you would like to send the notification

    • Choose ‘Send Now’

  • Title – The title of the notification

Click ‘Save Changes’ which will send the notification to the subscriber devices.

Setting up Recurring Notifications

  • Channel – Which channel to send the notification to

    • Choose ‘All Channels’ or ‘Specific Channel’

  • Alert – The message body you want the user to see

  • Send When – The time you would like to send the notification

    • Choose ‘Recurring’

    • Enter the Start Date, End Date, Cycle and Time of Day

  • Title – The title of the notification

Click ‘Save Changes’ which will send the notification to the subscriber devices.

That concludes this tutorial on Push Notifications.  Please feel free to leave a comment and let us know if this worked for you.

 

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.

Enabling Push Notifications Part 1 of 3

Enabling Push Notifications Part 1 of 3

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

There are several steps that you will need to follow to enable Push Notifications in your applications, they are :

  1. Determine which platform you wish to have notifications on.  Preferably on both iOS and Android.

  2. Set up your application in Appcelerator Studio.

  3. Become familiar with the Cloud section of the Dashboard.

  4. Register your application with Apple and create all necessary Application Identifiers, Certificates and Provisioning Profiles.

  5. Register your application with Google and set up the Google Developer Console for Google Cloud Services

  6. Implement the code into your application inside a Common JS library.

  7. Sending Notifications

Determine which platform you wish you have notifications on

The purpose of Titanium is to write one code base that works with multiple platforms.  This document will teach you how to set up for both of them.  However if you only wish to set up for one platform this document will help you do that as well.  The two platforms that will be discussed are iOS and Android.  First we will cover iOS setup and then Android.

Set up your application in Appcelerator Studio

You may already have your application created, or you may be starting from scratch.  Either way open your project in Appcelerator Studio.  Make sure that your application is set up for Appcelerator Services.  

You can enable this in two places.  First upon creation of the project.  Second is from the tiapp.xml file.  Open the tiapp.xml and you will see a section called ‘Appcelerator Services’.  Click the ‘Enable Appcelerator Services’, then turn on the ‘Cloud’ section.  Enabling cloud services in Studio creates a new Cloud application and adds its URL and credentials to the Titanium project.

Then you will see a section called ‘Modules’, this is where new modules can be added.  We are going to add the Cloud module (iOS) and the Cloud Push module (Android).

Click the ‘Plus’ icon and you will see this screen.  It gives you a list of modules that are available with the current SDK you have installed.  For this document we are working on 3.2.1.GA.  If you want notifications for iOS add the ti.cloud module.  Android you will need to add ti.cloudpush, or add both of them.

Become familiar with the Cloud Section of the Dashboard

Go to the Dashboard at https://dashboard.appcelerator.com/ and enter your Username and Password.  

There you will see a bar on top which is the main navigation.  Click the ‘Apps’ tab to show a list of apps that you have registered with Appcelerator.  Select the app you want to enable push notifications for.  Then click the ‘Cloud’ tab, which will load the ACS page.  

Screen Shot 2014-02-27 at 4.31.48 PM.png

Note:  There are two forms of Cloud Functionality on this Dashboard.  Select either Development or Production.  If you start with Development make sure you add what you need into Production when you want to distribute the app to either Apple or Google.

Register your application with Apple

iOS Setup

  1. Create an App Identifier
  2. Create a Push Notifications Certificate
  3. Create a Provisioning Profile
  4. Register Certificate with Appcelerator Cloud Services

Step 1:  Create an App Identifier

Apple requires you to register your application’s id and create a special certificate to be able to utilize push notifications.  You will need to login to the Apple Developer Member Center.  Once there you will see a section that looks similar to the one pictured below.

Select ‘Certificates, Identifiers & Profiles’ from this page.  Once there select the ‘Identifiers’ folder.  Click the + icon on the top right of the page to add a new Identifier.  Fill out the form below with the information required.  Under the ‘App Services’ section there is a column of checkboxes.  Select ‘Push Notifications’ and click ‘Continue’, then ‘Submit’, then ‘Done’.

Screen Shot 2014-02-27 at 2.19.19 PM.png  Note : You cannot use a Wildcard App ID for an app with Push Notifications

Step 2 : Create a Push Notifications Certificate

Go to the Certificates, Identifiers & Profilers.  On this page you will need to click the Certificates folder Icon.  That will load a screen that lists any certificates that you currently have created.  We need a Push Notification certificate so click the + button on the top right.

You will then come to a page asking you “What type of certification do you need?”  There are two sections for this called Development or Production.  You must decide which kind of certificate you need at this point.  Under each section there is a choice called “Apple Push Notification service SSL” .The Development version is just for testing and such.  Production will be what you need to send the app to Apple and make it public.

Then you will be asked to create a CSR (Certificate Signing Request).  The instructions to do this are listing on the page itself.  Follow the instructions and when complete click ‘Continue’.

Now you will need to upload that CSR file.  Click ‘Choose File’ and locate the CSR, which has an extension of ‘.certSigningRequest’.  Once selected click ‘Generate’

The certificate will be generated and available for you to download.  Save it somewhere on your computer.  Then open Keychain Access on your computer by either double clicking the Certificate or going to Applications – Keychain Access.  Locate the certificate inside Keychain by choosing ‘Certificates’ under the Category section.  Find the certificate in that list and right-click/two finger click it.  Choose ‘Export’ and you will be prompted to save a .p12 file.  Save it to your computer and open your web browser.  Go back to the Dashboard and select the ‘Cloud’ tab to continue Push Notification setup.

Choose ‘Settings & Configuration’ and a new page will load containing a tabbed view on it.  Select ‘iOS Push’ and you will see a section called ‘Push Certificate’ and an button to add a file. Click that button and find your .p12 file on your computer.  Upload the .p12 file and that will allow Appcelerator Cloud Services to communicate with Apple for Push Notifications.  If you set a certificate password you must also enter that as well.

Step 3 : Create a Provisioning Profile

Enabling Push Notifications

Go back to the Apple Developer Member Center and click ‘Certificates, Identifiers & Profiles’.  Click the + button on the top right of the page.

Screen Shot 2014-02-27 at 2.38.31 PM.png

Then you will need to select what type of profile you need.  There are two sections, Development and Distribution.  Select the most appropriate one for your project at this time and click ‘Continue’.

Screen Shot 2014-02-27 at 2.40.44 PM.png

Choose your applications id (the app identifier you created earlier) from the drop down list and click ‘Continue’.Screen Shot 2014-02-27 at 2.48.21 PM.png

Select your certificate that you created and click ‘Continue’.

Screen Shot 2014-02-27 at 2.49.21 PM.png

Now you can choose which devices you want to run the app on.  You can pick and choose or just select all.Screen Shot 2014-02-27 at 2.50.14 PM.png

Now you will need to name the profile.  Then click ‘Generate’ and download it.  It will save as a ‘.mobileprovision’ file.  Double-click that file to install it into Xcode.

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 2 and the following with part 3.

Page 1 of 212