UOC Maps

The free UOC Maps app for iOS / Android provides a virtual forum for members of the UOC community around the world, letting them find each other, communicate and express themselves. This social tool aims to promote community spirit and a feeling of belonging. It is designed to aid communication between members, help people get to know each other and establish professional and personal links within the community.

Apple App Store
Google Play Store
Open University of Catalonia

UOC Maps

The free UOC Maps app for iOS / Android provides a virtual forum for members of the UOC community around the world, letting them find each other, communicate and express themselves. This social tool aims to promote community spirit and a feeling of belonging. It is designed to aid communication between members, help people get to know each other and establish professional and personal links within the community.

Prefixing thirds libraries when developing a Titanium iOS module

Often we need to wrap thirds native open sourced libraries to our iOS module projects. Although is not dangerous at all, could be a problem. For example, if two different modules are wrapping the same library we’ll get a linker error when XCode begins the linking process. That’s because there’ll be duplicate symbols. To avoid that situation is highly recommended to prefix symbols (classes, constants, etc.) with some unique prefix.
It would be fine if the library is tiny or just requires a couple of lines to be changed. But if the library is a big one, could be very tedious. And it also implies that a simple git pull implies an extra effort: renaming each time.

I found an easier -IMHO- solution. Suppose we need to include a newer version of Reachability class, which is already bundled with the Titanium SDK. As soon as we try to run a project including our module we’re going to get linker errors. But if we:

1st add the following line to titanium.xconfig of our module project:

PREFIXED_SYMBOLS=-DReachability=YourPrefixReachability
-DkInternetConnection=YourPrefixkInternetConnection
-DkLocalWiFiConnection=YourPrefixkLocalWiFiConnection
-DkReachabilityChangedNotification=YourPrefixkReachabilityChangedNotification
-DkConnectionDown=YourPrefixkConnectionDown

2nd open XCode > Choose our module target (above Build & test target) > Build settings > search for ‘other c flags’.

And finally we add a line with $(PREFIXED_SYMBOLS) in both Debug and Release, we’re avoiding that linker conflicts.

Link strong!

GCM push notifications for Titanium (made easy)

gcm.js is an open source module for Titanium Android SDK that lets developers receive GCM push notifications in their Android apps.
It has a very simple API -almost identical to iOS!- yet flexible and powerful, as it executes Javascript whenever a notification is received, no matter whether the app is in foreground or background or even if it’s not running.
Another very useful feature of the module is that we’re going to be able to know if the user has clicked on a status bar notification.

If you’re a newbie with GCM, please read the GCM: Getting Started first!

Let’s start with a few lines of configuration. Open the tiapp.xml file of your Titanium project since we need to declare the module first. Once done, gcm.js only needs one property to make things work: the sender id. As you see in the following example, just fill the property value with that info:


<property name="GCM_sender_id" type="string">YOUR_SENDER_ID</property>
<modules>
	<module platform="android" version="0.2">net.iamyellow.gcmjs</module>
</modules>

Now, somewhere in your app you’ll need to register it for push notifications:


var gcm = require('net.iamyellow.gcmjs')

var pendingData = gcm.data;
if (pendingData && pendingData !== null) {
	// if we're here is because user has clicked on the notification
	// and we set extras for the intent 
	// and the app WAS NOT running
	// (don't worry, we'll see more of this later)
	Ti.API.info('******* data (started) ' + JSON.stringify(pendingData));
}

gcm.registerForPushNotifications({
	success: function (ev) {
		// on successful registration
		Ti.API.info('******* success, ' + ev.deviceToken);
	},
	error: function (ev) {
		// when an error occurs
		Ti.API.info('******* error, ' + ev.error);
	},
	callback: function () {
		// when a gcm notification is received WHEN the app IS IN FOREGROUND
		alert('hellow yellow!');
	},
	unregister: function (ev) {
		// on unregister 
		Ti.API.info('******* unregister, ' + ev.deviceToken);
	},
	data: function (data) {
		// if we're here is because user has clicked on the notification
		// and we set extras in the intent 
		// and the app WAS RUNNING (=> RESUMED)
		// (again don't worry, we'll see more of this later)
		Ti.API.info('******* data (resumed) ' + JSON.stringify(data));
	}
});

// in order to unregister:
// require('net.iamyellow.gcmjs').unregister();

If you ever worked with iOS Push notifications in Titanium you’re going to find the API very familiar, right? But… wait! what happens if the app is in background? That’s pretty simple: we’re going to create a new file called gcm.js in our project ‘Resources’ directory, I mean where app.js is. When the app receives a notification, the javascript in gcm.js is going to be executed as an Android service. We can do whatever we want there: save data in database, or store some Ti.App.Properties, etc. but obviously whatever not GUI related.
It’s important to understand that Android fires an IntentService as soon as the device receives a GCM message notification, no matter if the app is running or not, that’s the point, isn’t it?! gcm.js ‘fires’ our javascript code there as well, so yes, it also works if the app is not running!.
IMPORTANT NOTICE: starting in Android SDK 3.1, if the user force stop the app, a manual app invocation must be done in order to be able to receive GCM notifications again. Check this out.

Since the most common stuff we’re going to do with gcm.js is showing visual notifications appearing on the status bar, and I know sometimes it’s hard to understand the many flags there are, I wrote an example for just show the visual notification:


/*global Ti: true, require: true */

(function (service) {

	var serviceIntent = service.getIntent(),
	title = serviceIntent.hasExtra('title') ? serviceIntent.getStringExtra('title') : '',
	statusBarMessage = serviceIntent.hasExtra('message') ? serviceIntent.getStringExtra('message') : '',
	message = serviceIntent.hasExtra('message') ? serviceIntent.getStringExtra('message') : '',
	notificationId = (function () {
		// android notifications ids are int32
		// java int32 max value is 2.147.483.647, so we cannot use javascript millis timpestamp
		// let's make a valid timed based id:

		// - we're going to use hhmmssDYLX where (DYL=DaysYearLeft, and X=0-9 rounded millis)
		// - hh always from 00 to 11
		// - DYL * 2 when hour is pm
		// - after all, its max value is 1.159.597.289

		var str = '',
		now = new Date();

		var hours = now.getHours(),
		minutes = now.getMinutes(),
		seconds = now.getSeconds();
		str += (hours > 11 ? hours - 12 : hours) + '';
		str += minutes + '';
		str += seconds + '';

		var start = new Date(now.getFullYear(), 0, 0),
		diff = now - start,
		oneDay = 1000 * 60 * 60 * 24,
		day = Math.floor(diff / oneDay); // day has remaining days til end of the year
		str += day * (hours > 11 ? 2 : 1);

		var ml = (now.getMilliseconds() / 100) | 0;
		str += ml;

		return str | 0;
	})();
		
	// create launcher intent
	var ntfId = Ti.App.Properties.getInt('ntfId', 0),
	launcherIntent = Ti.Android.createIntent({
		className: 'net.iamyellow.gcmjs.GcmjsActivity',
		action: 'action' + ntfId, // we need an action identifier to be able to track click on notifications
		packageName: Ti.App.id,
		flags: Ti.Android.FLAG_ACTIVITY_NEW_TASK | Ti.Android.FLAG_ACTIVITY_SINGLE_TOP
	});
	launcherIntent.addCategory(Ti.Android.CATEGORY_LAUNCHER);
	launcherIntent.putExtra("ntfId", ntfId);

	// increase notification id
	ntfId += 1;
	Ti.App.Properties.setInt('ntfId', ntfId);

	// create notification
	var pintent = Ti.Android.createPendingIntent({
		intent: launcherIntent
	}),
	notification = Ti.Android.createNotification({
		contentIntent: pintent,
		contentTitle: title,
		contentText: message,
		tickerText: statusBarMessage,
		icon: Ti.App.Android.R.drawable.appicon,
		flags: Ti.Android.FLAG_AUTO_CANCEL | Ti.Android.FLAG_SHOW_LIGHTS
	});
	Ti.Android.NotificationManager.notify(notificationId, notification);

	service.stop();

})(Ti.Android.currentService);

I’ve commented the code as you can see (but it’s fine if you comment on this post asking for some help). Notice that we’re using intent ‘extras’ in order to receive data from our server. But… wait again! what is that ‘net.iamyellow.gcmjs.GcmjsActivity’ thing in the className property of the launcher intent? Since we don’t know when the user is going to click on the notification, we’re not able to know if the app is not running, or in foreground or in background. So, we need a man in the middle activity smart enough to forward the user to the correct Titanium activity. But our man in the middle could do more job! He’s going to collect the data associated to the notification (through the intent extras). We could do the same job with the stock Titanium API, but then we would need to add a lot of event listeners in order to ‘catch’ the intent extras… actually, I decided to add this feature to the module to make my apps logic more simple, since all the job is centralized in only one place. So, and where is that place? Just create a new file called gcm_activity.js inside ‘Resources’ directory, like we did before. Then let’s do something like this:


/*global Ti: true, require: true */

(function (activity, gcm) {

	var intent = activity.intent;

	// HERE we catch the intent extras of our notifications
	if (intent.hasExtra('ntfId')) {
		// and then we'll use 'data' property to pass info to the app (see pendingData lines of the 1st snippet)
		gcm.data = {
			ntfId: intent.getIntExtra('ntfId', 0)
		};
	}
	
	// 'isLauncherActivity' is a module property which tell us if the app is not running
	if (gcm.isLauncherActivity) {
		// if the app is not running, we need to start our app launcher activity
		// (launcher activity shows the splash screen and setup your app environment, so we need this)
		var mainActivityIntent = Ti.Android.createIntent({
			// 'mainActivityClassName' is another module property with name of our app launcher activity
			className: gcm.mainActivityClassName,
			packageName: Ti.App.id,
			flags : Ti.Android.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Ti.Android.FLAG_ACTIVITY_SINGLE_TOP
		});	
		mainActivityIntent.addCategory(Ti.Android.CATEGORY_LAUNCHER);
		activity.startActivity(mainActivityIntent);
	}
	else {
		// if the app is running (is being resumed), just finish this activity!
		activity.finish();
	}

})(Ti.Android.currentActivity, require('net.iamyellow.gcmjs'));

That’s all, now we can use a NodeJS instance as server to try it all:


/*global require: true, console: true, process: true */

(function (messageId, callback) {
	var _GCM = require('gcm').GCM,
	GCM = new _GCM('API_KEY'); // API KEY at Google APIs Console

	var message = {
		registration_id: 'USER_REGISTRATION_ID',
		'data.title': 'shephard: what lies in the shadow of the statue?',
		'data.message': '4 8 15 16 23 42',
		'data.sound': 'blacksmoke.mp3',
		collapse_key: messageId
	};

	GCM.send(message, function (err, messageId) {
		if (err) {
			console.error('error!');
		}
		callback(0);
	});
})((new Date()).getTime() + '', process.exit);

For a working example app, check both ‘example’ and ‘example_server’ directories out in the gcm.js github repo.Also you can download the zip in the ‘dist’ directory and install the module as usual.

meteoarbúcies

meteoarbúcies app now available for both iOS as an universal app and Android! 
It shows real time data from a Vantage Pro2 professional weather station placed at Arbúcies, Catalonia, including temperature, humidity, pressure and a graph with 24 hour history for each measure.
The iOS version is optimized for iPhone 5 and retina iPads.

Apple App Store
Google Play Store
meteoarbúcies website

meteoarbúcies

meteoarbúcies app now available for both iOS as an universal app and Android!
It shows real time data from a Vantage Pro2 professional weather station placed at Arbúcies, Catalonia, including temperature, humidity, pressure and a graph with 24 hour history for each measure.
The iOS version is optimized for iPhone 5 and retina iPads.

Websockets for Titanium (and socket.io)

TiWS is a very simple Titanium module for both iOS and Android and, as you may guess, it let’s you open Websocket connections with remote servers.

Its API is event oriented and quite simple to understand as the following example shows:


var websocket = require('net.iamyellow.tiws').createWS();

websocket.addEventListener('open', function () {
	Ti.API.debug('websocket opened');
});

websocket.addEventListener('close', function (ev) {
	Ti.API.info('websocket closed');
});

websocket.addEventListener('error', function (ev) {
	// ev.error contains error description, if any
	Ti.API.error(ev.error);
});

websocket.addEventListener('message', function (ev) {
	// ev.data contains message data
	Ti.API.log(ev.data);
});

WS.open('ws://IP_OR_URL[:PORT]');

But I’m pretty sure that most of the users of this module (like me) needed a websocket implementation for Titanium in order to make socket.io work natively in Titanium. Well, I’ve already done that job! I forked the socket.io client and made a few changes to make it work with TiWS. Also added XHR polling using Titanium XHR client to have the chance to fall back on it whenever websocket connections are not possible / fails.

Before start, grab the lastest version of the socket.io client from here.
More info at: