Zazzle Shop

Screen printing

Wednesday, September 17, 2008

How to Build a Simple SMS notification app

Everybody's talking about how mobile devices are key to the web's future. It's easy to see we're headed in that direction, as iPhones and other devices are squishing real web browsers onto our tiny, pocket-sized screens.

What about everybody on slightly less cutting edge devices? Or, even iPhone owners with slow connections that want access to specific data quickly? The answer is the SMS app, which is now accessible to the average web developer.

When we wrote about three SMS services on the Webmonkey blog, we wondered what it would take to put something together ourselves. In a shockingly short time, we wrote the Sunrise SMS App, which accepts a city as input and gives the sunrise (and sunset) times.

In this tutorial, I'll show you how I built this SMS app and how you can build your own.

This article is a wiki. Got extra advice that could help improve it? Log in and contribute.


Contents

[hide]

What is an SMS App?

An SMS app takes input from a user's text message and replies with a new text message as a response. Let's take a look at some example applications.

First, our Sunrise app, which returns sunrise and sunset times for a user's city. To test out a working version, grab your phone and text "sunrise " to 41411. Here's an example response from my iPhone:


Google SMS has a vast array of features to their SMS app. You can use it to get sports scores, movie times -- all sorts of data. This shows the real power behind SMS apps.

Are you ready to create one of your own?

What You Need

  • A TextMarks account (which requires giving it your mobile number)
  • Google API key to geocode city names
  • Some basic server-side programming experience. My examples will use PHP5 with SimpleXML and cUrl.


Create Keyword With TextMarks

To create an SMS application, we need to first make a keyword for that application using the TextMarks service. You'll need an account and a mobile number, but you can get started without one by creating a keyword. It will walk you through creating an account at the same time.


  1. Choose a keyword. This may take a few tries to find one you want. Everything three letters or less is reserved by TextMarks, as are some common words. There are still many good keywords to choose from. Tip: if you choose a real word, see whether it's known by predictive text on phones without QWERTY keyboards.
  2. Tell TextMarks your URL. Click the "respond to a keyword with text from a web page" option. An app that returns plain text isn't really an app. We want to change our response based on input. To that end, be sure to include \0 somewhere in your URL, so that you can pass everything the user types to your application. Don't worry about getting that URL right the first time. You can edit it later.

That's it! Two steps and you're ready to start providing feedback to text messages. In the upcoming sections, I'll show you how to write a basic "Hello World" SMS app, then dig a little deeper with an example app that tells users when the sun will rise and set when given their current location.


Write a basic SMS App

Before dedicating a lot of effort to a project, I'd like to make sure to first prove the concept will work. For this "Hello World" app, we'll write a short message and then repeat what the user sent to us.

In a PHP file (I called mine /sun.php/), include the following few lines:

$city = $_GET["city"];
print "It worked! You wrote: $city";
?>


Here, we're expecting something to be passed in the city parameter. You can test this in your browser before texting by bringing up the PHP page and passing a city value. For example, your URL might be:

www.example.com/sms/sun.php?city=San+Francisco+CA


The results would be:

It worked! Your wrote: San Francisco CA


Note that the plusses disappear from the city name. Those are URL encoded spaces and PHP decodes them automatically.

The corresponding TextMarks URL for this example would be:

www.example.com/sms/sun.php?city=\0


Go ahead and text your keyword, plus a city name to 41411. You should get a similar result on your phone. It will include an advertisement on the bottom. That's just the way it goes when you're using a service for free.

I like to do this basic SMS test to make sure everything is working. I use the same URL that I will eventually use for my full-fledged application. We'll be doing the same thing in the next section. Let's take sun.php and turn it into an SMS app to return the sunrise and sunset times for a given location.


Sunrise/Sunset Example SMS App

Now that you have an idea of how information flows through an SMS app, let's create something with a little more substance.

We know Webmonkeys often work until dawn, so we wrote an SMS app that makes it easy to find out when the sun will be rising. I'll show you how we did it by tying into a couple of APIs as we create the sunrise/sunset example app.

To test out a working version, grab your phone and text "sunrise " to 41411. Again, here's an example from my iPhone:


Are you as eager as I am?

You can grab the entire PHP file from Webmonkey's Code Library, or follow along piece by piece below. Let's get to coding this app before the sun sets.


Geocoding the City Name

Before we can get sunrise and sunset information, we need to know the latitude and longitude points of the city the user sent us in the text message. I won't go into a lot of detail into geocoding, because Webmonkey already has a whole tutorial on using Google's HTTP geocoder.

The quick version is that we send Google a city name (Tip: ZIP codes and entire addresses work, too) and its geocoder replies with comma separated values. It has XML, too, but we don't need to get detailed results. All we want are the coordinates.

Here is the code for geocoding, using the "city" argument in the URL:

/*** REMEMBER to use your own API key ***/
$apikey = "yourkeyhere";

// Get lat/long from Google HTTP Geocoder
$city = $_GET["city"];
$city = urlencode($city);
$geourl = "http://maps.google.com/maps/geo?q=$city&output=csv&key=$apikey";
$csvContent = get_url($geourl);
list($status, $accuracy, $lat, $long) = split(",", $csvContent);

if ($status != 200)
{
display_output("Eek! Couldn't determine where you are based on: $city");
}
else
{
display_output("Worked!\nLat: $lat\nLong: $long"); // For debugging--REMOVE at next step
}

/*** Functions used by the rest of the app go here ***/
function display_output($content)
{
print header("Content-type: text/plain");
print $content;
exit;
}
?>


The CSV result from Google looks something like this:

200,4,37.775196,-122.419204


There are four values returned:

  1. status - should be 200, or there was an error
  2. accuracy - city-level, zip-level, etc. More about accuracy here.
  3. Latitude
  4. Longitude

I used PHP to split the values into four variables. Then, if the status is 200, there's a message displaying latitude and longitude. We'll remove this message in the next step, but it's always a good idea to make sure everything is working as expected at each stage.


Determining the Time Zone

Now that we have the latitude and longitude, we can use it to determine sunrise and sunset times... except that we also need to know the time zone. Lucky for us, there are two different calls from the EarthTools API that help us with each of these pieces of data.

First, we'll retrieve the time zone and daylight savings information from EarthTools. Replace the debugging line that displayed the lat/long data with the following code:

  // Get time zone from Earthtools
// http://www.earthtools.org/webservices.htm
$timeurl = "http://www.earthtools.org/timezone/$lat/$long";
$xmlContent = get_url($timeurl);
$xmlObject = simplexml_load_string($xmlContent);
$zone = $xmlObject->offset;
$localtime = reformat_time($xmlObject->localtime);
$dst = dst_to_number($xmlObject->dst);

display_output("Time zone: $zone\nLocaltime: $localtime\nDST: $dst"); // For debugging--REMOVE at next step


You'll also need these few helper functions. You can put them below the display_output function, but make sure they're above the ?> PHP tag:

function reformat_time($time, $fmt="g:i A")
{
return date($fmt, strtotime($time));
}
function dst_to_number($dst)
{
if ($dst == "True")
{
return 1;
}
else
{
return 0;
}
}
function get_url($url)
{
// Create cUrl object to grab XML content using passed variable $url
$c = curl_init();
curl_setopt($c, CURLOPT_URL, $url);
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
$content = trim(curl_exec($c));
curl_close($c);

return $content;
}


As with the previous step, I included a debugging line to show that everything is working properly. The time zone is reported with as the number of hours different than Greenwich Mean Time (GMT). For example, in the US, the number will be negative, because we are behind England.

To get an idea for what results come from the EarthTools API, try passing the $xmlContent variable to the display_output function. XML tags (such as the "offset" tag) are accessible as elements of the SimpleXML object. The Google geocoder tutorial, we go indepth about accessing SimpleXML results.


Retrieving the Sunrise and Sunset Times

Now that we have the longitude, latitude, and time zone, we can call the EarthTools API to get the sunrise and sunset data. Replace that debugging line from the previous step with the following code:

  // Get sunrise/sunset data from Earthtools
// http://www.earthtools.org/webservices.htm
$daymonth = date("j/n");
$sunurl = "http://www.earthtools.org/sun/$lat/$long/$daymonth/$zone/$dst";
$xmlContent = get_url($sunurl);
$xmlObject = simplexml_load_string($xmlContent);
$sunrise = reformat_time($xmlObject->morning->sunrise);
$sunset = reformat_time($xmlObject->evening->sunset);

// Print out sunrise/sunset msg
display_output("Sunrise: $sunrise\nSunset: $sunset\n\nbtw, we think it's $localtime where you are. Adjust accordingly.");


Here we grab the appropriate items from the EarthTools XML. In this case, we need to go down two levels and get the sunrise item from the morning item. The sunset item is part of the evening item. Again, check out the raw $xmlContent variable to see the full XML available.

The reason my output includes the user's local time is that EarthTools has some daylight savings time issues in some places, especially the US. If you know about a better way to determine whether DST is observed, or a different data source for our application, edit this Wiki-fied tutorial. An app can only be as good as its data.

As we've gone along, you've probably been checking progress in a web browser. That's the best and easiest way to test an SMS app. (Did you grab the full code from Webmonkey's code library?)

Now for the fun part: try it on your phone. Text to your keyword and include your city. Do you get sunrise and sunset information quickly back to your phone? Is that not the coolest?


Where to go from here

OK, so now you've copied our app, but how about making your own? You'll need to find a data source. ProgrammableWeb is an excellent resource for APIs.

Someone created an SMS domain name checker. Is there similar data you'd like to have at your fingertips anywhere you are?

Also, the best data source may be your own. Maybe the latest headlines from your blog? I created a WiFi finder for Portland using my own database of WiFi hotspots.

You'll also see that this tutorial is only a taste of the many possibilities for SMS applications. Check out the advanced Textmarks usage, such as using a user's unique code or creating multiple choice menus. There's a lot more that can be done and you could do it.

So, when you create a killer SMS app, be sure to let us know by adding it here or to your user profile page.

  • This page was last modified 23:37, 16 September 2008.