Monday 8 March 2010

Appcelerator Titanium and Haxe

I have been tracking the beta development of Appcelerator's Titanium platform over the last year. Today it reaches General Availability. Having spent 300+ hours creating my first Android-powered application in Java, I was intrigued by the prospect of porting Creelcard across to the iPhone without having to learn ObjectiveC. What got me really interested was when I realised that I should be able to use Haxe's cross-platform capabilities to work with Titanium. Because all the source code of a Titanium mobile application is written in Javascript, this opens the door to being able to write iPhone and Android applications in Haxe using the Titanium APIs as extern libraries, compiling out to javascript, and then getting the Titanium SDK to work its magic and build iPhone and Android targets.

I had spent some time experimenting with the earlier versions of the Titanium SDK, but Appcelerator has recently re-designed the APIs in readiness of their v1.0 release. I have spent a short time since understanding the new APIs (without any documentation, but that is supposed to be coming by end of today), and doing some experiments in Haxe, with some success!

Here's a quick summary of my findings:

1. Haxe js target assumes a windows DOM

Unfortunately in this specific use case, the Haxe javascript - target specific code assumes that the javascript interpreter is running within a standard Browser, with access to the HTML Document Object Model. This was actually OK in the earlier versions of Titanium where all the code effectively ran within the context of a HTML page. But this is no longer the case with v0.9/v1.0 of the Titanium Mobile SDK. So far, I have had to make the following modifications to standard Haxe code:

js\Boot.hx:
private static function __trace(v,i : haxe.PosInfos) {
untyped {
var msg = if( i != null ) i.fileName+":"+i.lineNumber+": " else "";
#if jsfl
msg += __string_rec(v,"");
fl.trace(msg);
#else
#if titanium
API.info(v);
#else
msg += __unhtml(__string_rec(v,""))+"
";
var d = document.getElementById("haxe:trace");
if( d == null )
alert("No haxe:trace element defined\n"+msg);
else
d.innerHTML += msg;
#end
#end
}
}

Trace was not working because of the use of the "document" object which doesn't exist in the native context of a Titanium application. So I used a "titanium" Haxe compiler flag to switch to use a call to Titanium API's own logging method (see below).

private static function __clear_trace() {
untyped {
#if jsfl
fl.outputPanel.clear();
#else
#if titanium
// Do nothing here
#else
var d = document.getElementById("haxe:trace");
if( d != null )
d.innerHTML = "";
#end
#end
}
}

Same thing again with circumventing use of the DOM document object.

private static function __init() {
untyped {
#if titanium
js.Lib.isIE = false;
Lib.isOpera = false;
#else
Lib.isIE = (__js__("typeof document!='undefined'") && document.all != null && __js__("typeof window!='undefined'") && window.opera == null );
Lib.isOpera = (__js__("typeof window!='undefined'") && window.opera != null );
#end

And again, the titanium compiler directive switches out the use of document and window DOM objects again.

js\Lib.hx

#if !titanium
public static var document : Document;
public static var window : Window;
#end

then:
static function __init__() untyped {
#if titanium
document = untyped __js__("{}");
window = untyped __js__("{}");
#else
document = untyped __js__("document");
window = untyped __js__("window");
#end

2. Compile Haxe code into "app.js", or separate js files

Titanium apps start with a single javascript file, called 'app.js" by default, that builds the basic UI scaffolding of the application, and forms a global namespace that is shared by other Windows. You can stuff all your code into this single file, or associate different js files with each Titanium Window. So far, I have been using a single js file, which is conveniently created by the Haxe compiler.

3. Titanium APIs and Haxe extern

The core value of Titanium is the access it provides to the native capabilities of the mobile device (Mobile SDK) or desktop (Desktop SDK) via a rich and extensible set of Javascript APIs. These are (or are imminently about to be as I write this) documented on Appcelerator's website. Additionally, Haxe provides an elegant mechanism to import external Javascript namespaces and libraries / APIs into Haxe. I have started building extern class declarations to be able to access the API directly within haxe in a typesafe fashion.

For example:
package titanium.database;

import titanium.database.ResultSet;

/**
* @see http://www.codestrong.com/timobile/api/titanium/Database/DB/
*/
extern class DB
{

/**
* Same as getLastInsertRowId method.
*/
public var lastInsertRowId:Int;
/**
* Same as getRowsAffected method.
*/
public var rowsAffected:Int;
/**
* Close the database. This should be called to prevent resource leaks.
*/
public function close():Void;

/**
* Perform an operation on the database.
* @param sql SQL String
* @param ?args one or more arguments appearing after the sql parameter. Must be integer, float, string, or any data converted to string
* @return
*/
public function execute(sql:String, ?args:Dynamic):ResultSet;
/**
* The row id of the last insert operation.
* @return
*/
public function getLastInsertRowId():Int;
/**
* The number of rows affected by the last operation
* @return
*/
public function getRowsAffected():Int;
/**
* Remove this database from the device. This is a destructive operation.
*/
public function remove():Void;

}

4. haxe.unit.TestRunner.hx

Unfortunately in this case (again!), the haxe.unit.TestRunner class makes some direct calls to a DOM div element "haxe:trace" if compiling to the javascript target. Like the standard js classes above, I had to make a copy of this file in my own project and switch off these calls using the same "titanium" compiler switch.

5. Compile & Build

I have a simple compile and build chain that lets me go from haxe source to a running application on the Apple iPhone Simulator in 2 clicks:
  1. Set up a Titanium Mobile project in the Titanium Developer application. Leave all the default settings in the tiapp.xml file.
  2. Create and start writing the Haxe source code project ( I use FlashDevelop)
  3. Write the build.hxml fileused by the Haxe compiler. You need to compile to the javascript target, and make sure the custom "titanium' compiler directive is set (so that the changes made in the standard haxe files above will work). Here's what my current build.hxml file looks like for my unit test suite:

    -js CreelcardUnit\Resources\app.js
    -main com.creelcard.iphone.test.main.TestAll
    -cp haxe\src
    -cp haxe\lib\titanium\src
    -cp haxe\lib\haxe
    -D titanium
    -D unittest
    -debug

  4. Run the Haxe compiler using the build.hxml file. If things go OK, you should have an newly minted app.js file sitting in the Resources folder of your Titanium project.
  5. Build & test the Titanium application using the Titanium Developer program. Again, if things go OK, it will automatically launch the appropriate emulator (iPhone or Android) and run your application!





Monday 23 November 2009

CreelcardPro released!

After some more hard work, we launched our very first paid app onto the Google Market a couple of weeks ago. We hope you appreciate some of the new functionality we added, mostly as a result of feedback from our users. The key new feature is the ability to export data to a series of csv files so you can import the information into other desktop applications for further analysis.

The layout of the csv files are fairly easy to understand. There is one file generated for each main record type in Creelcard. For example, the catch csv file references the ID of other records (e.g. fish, angler), which you will find listed in their respective csv files. Each csv file also includes any custom fields you may have defined for that record type, making this completely flexible.

We would be very interested to hear back from anyone who starts using these files for further analysis ... what kind of reporting and number crunching do you do ? We may add some analysis tools in the Pro version in the future; it would be great to know what kind of stats are the most useful.

Enjoy using the new Pro version! Please let us know your thoughts, experiences , questions and queries.



Sunday 4 October 2009

CreelCardPro ... coming soon!

Now that the free, ad-supported CreelCard application has been out in the market for a few months now, we have had some great feedback from some of the user community which we have been able to address and add back into the feature set. However, it was always our idea to launch a paid-for, no-ads version alongside the original free app, to test the waters for this kind of offering in the Android Marketplace.

Since the last version, v0.9.3, of the free version, we have been working on the pro version. We don't want to spoil all of the surprises, but the main theme is import and export of your fishing data. You will be able to import all the data from a previously - installed CreelCard free version when you first launch the Pro version. You will also be able export the entire data set out for CreelCard Pro into a series of individual csv text files (one file for trip, one files for catches, one file for fish etc). This will let you pull the data into other analysis packages and databases to do further reporting and archiving. This is working just great in our test version, including all custom fields, media file links and text notes for each record type.

We will continue to maintain the codebase of the free version, focusing on addressing any issues that may arise with new versions of the Android firmware, differences between different vendor-specific application stacks etc. For example, we have found a difference in the way the original Google Camera activity and the HTC Hero's HTCCamera activity create links to newly created photos that are passed back to the calling application (CreelCard in this case). Fortunately, a friend has lent his brand new HTC Hero phone to help with the problem diagnosis (thanks Sess!).

Look forward to providing more details when we are go for launch. Please don't hesitate to contact us with any ideas and feedback ... using our Get Satisfaction site is probably the best route. Thanks for your continuing support!

Tuesday 1 September 2009

v0.9.3 released

Today we released Creelcard for Android v0.9.3, with the major addition of custom fields to let you define your own trip and catch attributes. In fact, you can add custom fields to any Creelcard record type (trip, catch, angler, bait, fish, location).

You can decide where each custom field should appear amongst the existing, fixed record fields. You can specify the visible field label, and even the hint text to remind you what to use each field for.

The following custom field types are supported in this version:
1. Text
2. Number (e.g. "30")
3. Number with fractions (e.g. "3.5")
4. CheckBox (true or false)
5. Length with small units (centimeters or inches)

For the first three types, you can either have a simple entry field to type in your value, or specify a lookup list of values (e.g. "Catch,Sighting,Missed"). Instead of typing in a value, you simply pick a value from the list, speeding up entry time.

We'd love to hear any feedback you have on further field types you'd like to see added next (e.g. speed, temperature - based fields?). Or is there anything else you love or would like to see improved with Creelcard? Let us know!

Monday 3 August 2009

Wikitude Augmented Reality

What's the most likely killer app for smartphones once everyone has got used to the basic web / maps offerings? I reckon it's going to augmented reality; overlaying data information on a realtime view of the world (e.g overlaying data on the Camera view of an Android device).

Having gotten Google maps and gps sorted out for Creelcard, so that you can specify and view detailed catch position info, what's the next logical jump? How about being able to hold the phone up and see an overlay of the catch location and other data overlayed directly on the realtime camera view ahead of you? Interested ?

After reading a post on AndroidGuys about the new Wikitude Augmented Reality browser and developer API, I contacted the Wikitude dev team and got access to the private beta of their SDK.

The documentation was very clear; the library JAR file easy to add to the code base of the creelcard code project in Eclipse. Within 30 minutes I had added a simple Button View to the Creelcard catch list screen that launched the WikitudeCam screen. Then it took another couple of hours to figure out how to capture altitude info from Android's location API. The Wikitude browser is altitude - aware as well as latitude/longitude; set a point-of-interest (POI in wikitude-speak) on the top of a mountain, and you would have to point the camera up at the summit from the mountain's base to see the overlayed information - very cool! A final hours work to be able to pass a list of catch information as individual POIs, and I had a working basic Creelcard AR screen!

Unfortunately I can't release a version of creelcard with this functionality yet as the SDK is still is in an initial private beta phase. I have to say that the Wikitude team have been very responsive with the few questions I have had to ask to get this far. I really need to do some real - world testing to figure out how best to make use of this promising technology. Am also waiting for the commercial terms & conditions to be published before making a final decision. It would be great to hear from any readers of this blog as to your thoughts on how you could see AR helping your fishing experience !!

Friday 24 July 2009

v0.9.2.1 released this evening with a couple of bug fixes that slipped through the net. You should be able to use the app without having any location providers (wireless and GPS) activated on your phone without it crashing! It is very important that Creelcard can be used out in the field without having the benefits of internet access or even location providers. Of course, if you can find a fishing spot with wifi or 3G access, so much the better ... use the View Maps button on the Catch List screen to see your current phone location in relation to catches from a previous trip.

Wednesday 22 July 2009

v0.9.2 released with Maps & GPS support

The obvious next step for Creelcard had to be using some of the great location and map features of the Android platform. After some long hours getting my head round the unfamiliar Location and Maps APIs, helped by some great tutorials, we have just released the next version with some cool new geo features.

You can now specify the position of a Location record (e.g. a fishery, lake or riverside) and / or individual catches by either using your current phone GPS location, manually selecting from a map, or simply by typing in the co-ordinates yourself. For when the catch position is not known exactly, you can also define the approximate circular area in which the catch happened by resizing the area circle overlayed on the map. We will use this feature in future updates (setting proximity alerts, suggesting nearest "favourite" catch locations etc).

Please let us know how you would like to see Creelcard's features improve .. we would really appreciate any feedback. You can contact us by email (support (at) creelcard (dot) com), using our Get Satisfaction site, or by leaving comments on this blog.

More soon!