Building a Ti Mobile App: GrillTime, part 1

I am an avid griller, and I’ve always wanted an app to help me cook up a great New York Strip steak or other delicious dishes on the grill. There are a couple of things I need all the time:

  • a versatile timer
  • cooking temperature guide
I have seen timers on the markets, but none do quite what I want. And for some reason, I can never remember the safe cooking temperatures for poultry, pork, beef, etc. So if I could build one app that has all of this at my fingertips, I’d get a lot of use out of it. So I saw this as a good opportunity to build an app in tutorial form so everyone can see the kinds of steps you take to build a Titanium Mobile app.

Creating the Project

The first step is to create the project. From the File menu, we choose New and then Titanium Mobile Project. Here we enter the details of the project:

  • Project name: GrillTime
  • Application ID: com.smorgasbork.grilltime
  • Publisher URL: http://www.smorgasbork.com/
  • Titanium SDK Version: 2.1.1 GA
  • Deployment Targets: iphone and android
  • Automatically cloud-enable: no

We’re not going to try to target ipad or mobile web just yet.

Next, we are going to add the TitanUp library. This will help us with our window management, among many other things. All we have to do is copy the entire /Resources/TitanUp directory from the sample project into our /Resources directory.

In every module where we want to use TitanUp, we add this code:

Defining the Data

We’re going to start with the safe temperatures reference, as that’s a little less complicated than the timer code. First, create /Resources/data/SafeTemps.js with a reference data structure. You can see the data structure I’m using:

We’re building an array of objects, one for each type of meat that we’re grilling. Each object has a label property (notice that we’re using Titanium’s built-in i18n for the labels), and an array of cooking temperatures (each corresponding to a different level of doneness, for meats where that is relevant). Here in the US, many people refer to the guidelines laid out by the USDA, but some find them to be too conservative, and like their meat a little less well-done. So I plan to let the user make the decision about how conservative he wishes to be. In anticipation of such an option, we provide both temperature values here. Again, we’re using i18n, which would let us even show values in Celsius where appropriate.

For all the i18n strings we used in our SafeTemps.js file, we need to create the corresponding strings in /i18n/en/strings.xml. For example:

Building the UI

Next, we are going to define a window class to display the list of meat types. We haven’t talked much about the UI to this point, but I plan to use a TabGroup as the central navigation within the app. So this window will be attached to one of the tabs. Create a new Javascript file in /Resources/ui/common/TempsWindow.js. Using good CommonJS techniques and parasitic inheritance, we will define a window class called TempsWindow

Within our TempsWindow class, we will make use of the TU.UI.Theme and TU.UI.Sizer modules of the TitanUp library. This will help us centralize key aspects of the look and feel of our app and ensure uniform size of our UI elements across different platforms.

The main UI element in TempsWindow is a TableView. We will load this table with data from SafeTemps.js.

Now we need something to happen when the user taps one of the items in the TableView. We want to bring up details for the selected meat type. So we define a new window class, TempDetailWindow in a separate Javascript file, /Resources/ui/common/TempDetailWindow.js. Again, we use TU.UI.Theme and TU.UI.Sizer.

We load the TableView in this window with data that gets passed into the constructor.

Next we need to add an event listener to the TempsWindow that will open a TempDetailWindow:

Note that we use TU.UI.TGWM to open the window. The way you open and close windows within a TabGroup-based application is different on iOS and android. The TGWM (Tab Group Window Manager) shields you from having to deal with this (and provides some other useful capabilities).

Cleanup

Titanium Studio put a lot of boilerplate code into our app when we first created it. We want to remove some of that and make a few modifications.

First, we clear out the CHANGELOG.txt file, and we put an appropriate license into LICENSE.txt. We update the contents of README.

Next we delete /i18n/ja, since we don’t have any Japanese translations available to us at the current time.

We open /Resources/ui/common/ApplicationTabGroup.js and remove win2/tab2 references; we’ll start with just one tab. We’re going to use TU.UI.TGWM to create our TabGroup. This is necessary for TGWM to function properly.

Delete the ApplicationWindow.js files from the /ui/handheld and /ui/tablet directories.

Finally, we open up app.js, add the TitanUp require code, and we remove all the code that sets osname, version, height, width, and isTablet. TU.Device already provides these things for us if we decide that we need them.

Running the App

Things are now ready to run. In Ti Studio, you can click the Debug button and choose “iPhone Simulator” to run your app. You should see something like this:

GrillTime on iOS

Tap on “Beef”, and you’ll see this:

GrillTime on iOS

Gotcha: numeric string names in i18n files

When I went to run the code on android, I got compilation errors like this:

It turns out that you cannot use string names that start with digits in your i18n files. I had to change my names from names like “125deg” to “t125deg” in i18n/en/strings.xml:

Further, I found that spaces in string names don’t work, either:

So I had to change all my string names to use underscores instead of spaces:

Of course, I had to make all the corresponding changes in my Javascript where I reference these strings by name. After making these changes, I had to clean the project and build it again.

Running on android, it looks like this:

GrillTime on android

Things are a little plain, but in our next installment, we’ll work on some cosmetic issues.

Download source code

Part 2 · Part 3 · Part 4

Leave a Reply

Your email address will not be published. Required fields are marked *