Titanium: the Good, the Bad and the Ugly

I’ve been following Appcelerator Titanium Mobile with a keen interest since they decided, for mobile, to move from HTML to native UIs. I just love this idea: use the platform’s native UI controls from Javascript. I did have a fairly good experience doing a little test app with Titanium Mobile 1.5 and noted for myself to use it for real when I’ll have a project.

More recently Appcelerator bought Aptana, the arguably most advanced Eclipse plugin for Javascript (and HTML) development, and renamed it TitaniumStudio. Honestly I dislike Eclipse very much but I thought it was a great move to gain the professional developers’ hearts.

Since I had a new occasion to do a mobile app I thought I was time to get up to date by giving Titanium 1.8 another run.

This was a “mixed” experience, but my conclusion is quite positive!

Updated 27/02/12 (see end of the article)

Warning: MacOS stuff ahead 😉


The Good

Titanium API is pretty fantastic nowadays if you want to avoid the burden of getting into both the huge UI Kit framework and this Objective-C weirdo. You can code truly native UIs in a few lines of Javascript, and, hopefully, you’ll have a good base to create an Android version as well with a reasonable amount of modifications.

The Bad Studio

“Argh, please kill me now” – that’s me after a few hours using the “Studio”.

But I’ll first list the things that can be liked:

  • interactive Javascript debugger,
  • decent Javascript code completion and syntax checking.

That’s about it.

Now onto the painful things:

  • it’s Eclipse in all it’s glory: snappy as a dead horse, I’m dying a little each time I see the infamous “Building Workspace”,
  • I still didn’t understand the link between Eclipse’s regular top Debug/Run buttons and Titanium’s custom Debug/Run/Package buttons in the Project panel,
  • Javascript code completion isn’t quite as good as some other editors,
  • by default iOS apps are packaged for device into an IPA that you must then install manually through iTunes (and it’s awfully long to compile).

The balance isn’t in TitaniumStudio’s favor and I quickly decided to get back to the command line.

Getting rid of the Studio

Thankfully, the command line SDK still exists, and it generally works as expected!

If you installed TitaniumStudio, you’ll find it in:

/Library/Application Support/Titanium/mobilesdk/osx/1.8.0.1/
or /Users/(yourname)/Library/Application Support/...

The SDK alone can be found in the Continuous Integration (CI) area, but beware, it’s a development area – I’d suggest to install Studio and run once in a while to keep up with the releases. Also follow the dev blog to see what’s happening.

In both cases you’ll run it from the command line like:

/<titaniumsdk>/titanium.py <args>

Now to create a new project:

/<titaniumsdk>/titanium.py create --type=project
   --platform=iphone,android --name=MyProject --id=com.foo.myproject

and to run it in the iPhone simulator:

cd MyProject
/<titaniumsdk>/titanium.py run --platform=iphone

The basics are very easy, simple and fast (unlike in Eclipse) – now pick up your preferred Javascript editor and… where’s the code completion?

Where’s the Javascript API?

Well Appcelerator doesn’t provide any ready to use way to have code completion in other editors, but some cool people have worked on it:

Now any good JS editor will provide your with some code completion for the API – open the API documentation (old API) in your browser and get started. Also Google is your friend if you need samples. Easy.

Debugging

Now we’re out of the Studio we don’t have the nifty interactive debugger, but it’s ok:

  • we do have detailed errors reported (in the terminal with the iPhone simulator and in adb with Android),
  • and you’ll learn back to log and dump objects using Ti.API.log() or good ol’ alert()

Getting on the device

Apple has made it insanely difficult to target iOS without using XCode – and this time again we’re not going to fight.

iOS provisioning

  • if you don’t know what this is, you can stop reading now and consider paying the Apple tax to be allowed to dev for iOS and to get up to speed with creating provisioning profiles,
  • if you didn’t already create an iOS provisioning profile, create one,
  • if your provisioning profile doesn’t match the one you provided when creating the project, change it in ‘tiapp.xml’. Then clean your build (see ‘Troubleshooting’ below) and run the project once in the simulator,
  • if an installed provisioning profile matches the project XCode will detect it automatically.

Running from XCode

Titanium actually generates a usable regular XCode project in the build/ directory:

open build/iphone/MyProject.xcodeproj/

At first, for me, XCode doesn’t offer to run the app on my device (iPod Touch 4); here’s the solution to select your device:

  • select ‘Edit Scheme…’ in the toolbar’s Scheme combo box,
  • select the Scheme your interested in (like ‘MyProject-universal’),
  • then you can choose your device in the ‘Destination’ list.

Now clean the project (Command+Shift+K), wait until this completes, then press Run (Command+R), and the app should eventually start on your device – woohoo 🙂

The Ugly

Ok the experience of running the project in the iPhone simulator and even on an iOS device is pretty good, and iOS is clearly a first class citizen in Titanium API.

Now what about Android? Well don’t expect miracles and your app is going to look like shit (if it works at all) on Android. There will be work to do.

Also on my computer the interactive debugger (in the Studio) wouldn’t connect to the emulator, and from the command line I couldn’t make the “fastdev” server work (very good idea, similar as Spaceport.io’s excellent workflow). In this conditions targeting Android is just incredibly painfully slow but I have hopes that it’s only a problem with my config.

I’m confident it can be solved however, and I suppose I’ll find a way (probably thanks to “fastdev”) to directly run on an Android device because the emulator workflow is ridiculously slow for now.

Troubleshooting

Because there will be troubles.

Cleaning a project

Sometimes changes/assets are not picked up in the simulator:

# Warning: "rm -rf" is a very dangerous command
rm -rf build/iphone/
rm -rf build/android/

Note: strangely you may have to build twice (yeah) after a cleanup.

Code completion conflict

When building, many copies of your JS files will be created under build/ and some editors may be confused by older versions of your code – I personally automatically delete all the JS copies after a simulation:

# Warning: "rm -rf" is a very dangerous command
find build/ -name "*.js" -exec rm -f {} \;

Note: this trick doesn’t work well with Android target, you have to clean the Android build completely instead.

Automating

You don’t want to mess with all these commands in the terminal (especially those with “rm -rf” inside) so you should write scripts!

Here’s my ‘titanium’ script:

#!/bin/bash
/Library/Application\ Support/Titanium/(...)
(...)mobilesdk/osk/1.8.0.1/titanium.py $@
if [[ $1 == run ]]
then
  find build/ -name "*.js" -exec rm -f {} \;
fi

Make it executable:

sudo chmod 755 titanium

I’m keeping those in ‘/usr/local/bin’ so I can type in the terminal:

titanium run --platform=iphone

Sublime Text 2

My preferred text editor on Mac has some useful plugins for JS dev. Using Package Control you can install:

  • SublimeCodeIntel: code completion (I usually disable its CSS completion),
  • SublimeLinter: syntax checking (my JS syntax preferences),
  • Terminal: open the terminal in current file’s location

A super trick, to run my project from ST2 without even opening the terminal:

  1. Tools > Build System > New Build System…
  2. paste this build config (and check the reference),
  3. save as ‘Titanium.sublime-build’ in the default location (ie. in ST2/Packages/User/),
  4. restart ST2,
  5. now you can select this build system in Tools > Build System menu and press Command+B to run the project and enjoy the log directly in ST2 console.

Notes:

  • it works better to exit (Command+Q) the simulator as soon as you don’t use it, and always before launching a new build,
  • SublimeCodeIntel doesn’t support CommonJS modules so stick to Ti.include() and regular prototype-based Javascript and use composition over inheritance.

Final notes

Now that everything is properly setup I’m having a lot of fun using Appcelerator Titanium; so far it has been working pretty fantastically: the API is quite intuitive and you can find plenty of sample code, and tricky things, like loading data/images from the web, just work without any effort. And if the API isn’t good enough, I know I can dig into the Objective-C/Java side to extend/fix it.

Warning: it’s not because it’s Javascript that everything is easy to do, you must be very careful about your memory consumption and code quality. Also avoid running several Javascript contexts (ie. calling createWindow with an ‘url’ property); check the Tweetanium project for some good practices.

Next thing to try: using haxe-js and the Titanium API externs to develop the app.

Update : and things got uglier

After a few weeks of work on a real project (for iOS – we actually don’t have much hope for an easy Android port), most of the development went well and has been quite fun & productive thanks to the easy views/layout/skinning/XHR features offered by Titanium. Obviously we’ve worked very carefully, writing MVC Javascript and using Node.js to automate tests.

But… it’s far from perfect and things got really uglier as we stepped outside the most common features:

  • Titanium doesn’t have any “drawing API” (well actually there’s one incomplete Ti.UI.Canvas roting in the framework at least since version 1.4.1.1 of the SDK)
  • I bumped into some really nasty bugs, some of which exist since forever too.

What does it mean? It means that the framework is in lazy-maintenance mode and don’t expect AppCelerator to fix bugs quickly – maybe they have been working on Android support or commercial plugins? maybe they were busy assimilating Aptana and adding the debugger? In any case the 2.0 developer version doesn’t seem to present meaningful changes but mostly a refactoring of the threading management.

Now if you’re not ready to get your hands very dirty into the Objective-C source of the framework you’ll be in trouble:

  • I’ve written a native iOS plugin to create a custom graphical component; it was actually easy enough, but I’m familiar with native memory management and threading,
  • I had to rewrite a critical feature of the VideoPlayer* because I need to extract frames of videos; my version is actually much more advanced because I’m adding direct croping/scaling of the images to optimize the memory.

I had only spent a few days, one year ago, learning some Objective-C so this experience was distressing at the beginning, but nothing I couldn’t overcome.

Eventually I’m thrilled by what I learnt and coded – now I can mix JS’s productivity and Objective-C’s raw power. Also Apple tools aren’t too bad.

* I’m happy to report that my patch was accepted by AppCelerator – there’s hope 😉

9 thoughts on “Titanium: the Good, the Bad and the Ugly

  1. Great post! I had to use Titanium and OSX a few months ago and faced some problems just like those you pointed out.

    Your scripts and tips will help me a lot. Thanks! 😀

  2. Nice review! What advantages do you see over developing in ActionScript with Adobe AIR for mobile? From your description, it seems like ActionScript provides a nicer development experience, and can target multiple platforms much more easily? Thanks!

  3. @Jacob AIR is a good option for games and other rich interactive projects,
    but it’s not going to feel as snappy as a native UI. This is kind of like Flash VS html in the browser.

  4. Nice article. I tried to use the steps above for SublimeText 2 (my favorite editor as well). My project built and ran in the simulator, but it ran in the iPhone simulator — it is an iPad only app.

    Why?

  5. Also, at the end of running the app in the simulator, on quit of the simulator, the ST2 console says:

    [INFO] Application has exited from Simulator
    find: -f: unknown option
    [Finished]

    why the unknown option for the rm?

  6. @Steve
    find -f is used to removed copies of your JS files in the /bin output as they conflict with ST2 completion. Not sure why ‘find’ doesn’t work for you.

    Titanium runs by default in the iPhone simulator, but it can be hacked:
    – edit : /Library/Application\ Support/Titanium/mobilesdk/osx/1.8.1/iphone/builder.py
    – search 1st occurrence of: devicefamily = ‘iphone’
    – replace ‘iphone’ by ‘ipad’
    – do a clean rebuild

  7. Thanks Scott, you’re right, I should have looked again at Titanium Developer – does it support the new Android server workflow? that would make it worth checking.

Comments are closed.