indie mobile / web developer.
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.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 app now available for both iOS 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.
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:
TiGrowingTextField is yet another simple iOS module for Titanium that let’s you create a text field which grows or shinks depending on the the content the user types, like iMessage, WhatsApp, etc.
The module wraps a third party library TiGrowingTextField uses a third party by Hans Pinckaers (Github).
A demo snippet showing all the config options:
var textField = require('net.iamyellow.tigrowingtextfield').createView({
// layout stuff -it works as any other view-
height: 40, // 40 is the minimum height, the view height won't be less than 40
left: 10, right: 10,
// growing / shrink
minNumberOfLines: 1, // default = 1
maxNumberOfLines: 10, // default = 3,
// this shows the keyboard as soon the view (window) gains the focus (is opened)
showKeyboardImmediately: true,
// background stuff
backgroundImage: 'images/MessageEntryInputField.png',
backgroundLeftCap: 12,
backgroundTopCap: 20,
value: 'hellow',
// appearance
appearance: Ti.UI.KEYBOARD_APPEARANCE_ALERT,
// text stuff, works as Ti.UI.TextField
autocorrect: false, // disables / enables autocorrection
textAlign: 'left',
font: {
fontFamily: 'Georgia',
fontSize: 12
},
color: '#333333'
});
// now, we're ready to add the view to a parent view / window
tIDs is a Javascript wrapper for OpenUDID, a drop-in replacement for the deprecated uniqueIdentifier property of the UIDevice class on iOS (a.k.a. UDID).
In order to keep safe the OpenUDID across multiple app installations, tIDs also stores the OpenUDID in iOS Keychain.
The API is damn simple:
var did = (function () {
var did = Ti.App.Properties.getString('did', null);
if (did !== null) {
return did;
}
did = require('net.iamyellow.tids').openUDID;
// let's store the ID in the properties object
Ti.App.Properties.setString('did', did);
return did;
})();
Ti.API.info("My OpenUDID is " + did);