Building a mashup service using messaging, maps and location

Introduction

This tutorial shows how to combine telco based services (SMS, MMS and location) with the map service provided by Yahoo! to create a new mashup service for mobile devices.

To keep the focus narrowed to the task of combining telco Web services with Web 2.0 service, it is assumed knowledge of several technologies and standards mentioned and used throughout this tutorial. More specifically the reader should be familiar with:

  • HTML
  • XML, SOAP and Web Services
  • Eclipse – as an environment for Java and web service development
  • Java, inclusive basic HTTP/URL handling
  • SMS and MMS messaging

MyMap - The service

The goal of our tutorial service is to provide the end-user with a map showing his current location, utilizing the messaging capabilities of his mobile phone. The service will be branded as MyMap. The location of the mobile device will be retrieved from the mobile operator’s network and combined with map data from Yahoo!Maps we will send a map image back to the user as a MMS message. The end-user initiates the service by sending a SMS message to our service.

The building blocks

Following is a short description of the building blocks used to build the new location and map based mashup service.

The playground Parlay X API

ParlayX is a standardized web service API for telco related services. Abstracting telco specific complexity in networks and protocols, it is simple enough to be used by any Web 2.0 developer. We will use the following ParlayX methods in our example:

  • RetrieveSMS – to pick up the SMS sent by the end-user when he wants to get the map
  • SendMessage – to send the map as a MMS message back to the enduser
  • TerminalLocation – to retrieve the current location of the mobile phone

Please check out the playground tutorials to see detailed tutorials for how to use these ParlayX services from Eclipse.

To get access to the Parlay X web services in the playground Lab, you will need to sign up as a partner with Telenor playground. Please read more here on how to apply for playground partnership and how to get access to the playground lab.

Yahoo!Map service

Yahoo! provides a HTTP based service to get a map image based on latitude and longitude coordinates (geo-coordinates). You can also use street address and city as input, if you have this information. Our service will use the geo-coordinates retrieved using the above mentioned ParlayX service. The Yahoo!Maps API are specified as a REST service, meaning we need to create an URL address with needed arguments to get our map image. This URL can also be built using JavaScript and used your HTML code.

You will need an application ID to use the Yahoo!Maps API. Sign-up for free at http://search.yahooapis.com/webservices/register_application to get your ID.

Eclipse - Java IDE

This tutorial assumes that the Eclipse Web Platform is used as the Java IDE. This version of Eclipse includes all the libraries and plug-ins needed for easy Web Service development. It is available for download at http://download.eclipse.org/webtools/downloads/.

The MyMap service

The figure below shows how the playground building blocks will be used to create our MyMap service.

The Works

It is time to look at the code that is needed to get service going.

Getting the SMS message

First thing we need to do is to make sure we receive the SMS message from the end-user's handset. Normally this is done by setting up a Web Service listener being called by the operator when there is an inbound SMS to our service. But, a polling scenario also exists, and we will for simplicity in our code use the polling mechanism. The never-ending loop polling for inbound message will look something like:

    public void pollingLoop ()
    {
        while (true)
        {
            try
            {
                SMSRequestObject smsRequest = getIncomingSMS();
                handleSMSRequest(smsRequest);
                //Adjust sleep time according to the SLA agreed with the operator.
                Thread.sleep (15*1000);
            }
            catch (Throwable th)
            {
                //TODO Add appropriate Exception handling
                logger.warning("Caught unhandled Throwable " + th);
            }
        }
    }

The polling loop uses the getSMS() method which uses ParlayX getReceivedSms() to check if there are any messages waiting for us to be picked up.

Handling the SMS request

The following method implements the functional flow of our service, first asking for location, secondly getting an URL to the map provided by Yahoo!, thirdly downloading the map from Yahoo! and finally sending the map to the end-user as a MMS message. The code will look something like:

    public void handleSMSRequest (SMSRequestObject smsRequest)
    {
        //Get the location of the device based on the MSISDN
        LocationInfo li = getLocation(smsRequest.getSender());        
        
        if (li == null)
        {
            return; //TODO Handle customer interaction
        }
        
        //Get the URL to the generated map from Yahoo!Maps
        URL mapURL = getMapImageURL(li, 300, 300, 4);
        
        if (mapURL != null)
        {
            //The sender of the SMS request will be the recipient of the MMS.
            String[] recipients = new String[1];
            recipients[0] = smsRequest.getSender();
            try
            {
                //Download the image based on the found URL, 
                // using standard Java toolkit. 
                Image mapImage = Toolkit.getDefaultToolkit().getImage(mapURL);

                //sendMMS(recipients, mapImage, null);
            }
            catch (Throwable th)
            {
                //TODO Add appropriate Exception handling
                logger.warning("Caught unhandled Throwable " + th);
            }
        }
    }

Using Yahoo!Maps

The following method sends a requests to Yahoo!Maps to get the Image. Yahoo! will respond with a XML document containing the a link to the actual map image for the location we have given. This URL can be used to download the map image. We will be using XPath to get the URL from the XML document.

    /**
     * Retrieves an URL pointing to a Yahoo Map.
     * See http://developer.yahoo.com/maps/
     * for further details on the Yahoo!Maps service API.
     * @param li the object containing longitude and lattitude values.
     * @param zoom The zoom level for the map, 
     *     from 1 (street level) to 12 (country level)
     * @param imgWidt width of the map image
     * @param imgHeight height of the map image
     * @return the URL to a map image generated by Yahoo!Maps. 
     *     Returns null if an error occured.
     */
    public URL getMapImageURL (LocationInfo li, int imgWidt, int imgHeight, int zoom)
    {
        //STEP 1: generate the URL to request Yahoo!Maps to generate a map image.
        
        //Sign up at Yahoo!Developer to retrieve your 
        //Yahoo application ID. http://developer.yahoo.com/
        StringBuffer urlBuffer = new StringBuffer ();
        urlBuffer.append ("http://local.yahooapis.com/MapsService/V1/mapImage");
        urlBuffer.append ("?appid="+yahooId);
        urlBuffer.append ("&latitude="+li.getLatitude());
        urlBuffer.append ("&longitude="+li.getLongitude());
        urlBuffer.append ("&zoom="+zoom);
        urlBuffer.append ("&image_width="+imgWidt);
        urlBuffer.append ("&image_height="+imgHeight);
        try
        {
            //STEP 2: Ask for an URL pointing to the map image. 

            //The URL for requesting the map generation.
            URL mapRequestURL = new URL(urlBuffer.toString());
            
            //Send the request to the Yahoo!Maps and 
            //read the response using an InputStream.
            Object contentObj = mapRequestURL.getContent();
            if (contentObj instanceof InputStream)
            {
                //Read the response XML from Yahoo!Maps
                InputStream in = (InputStream)contentObj;
                StringBuffer mapResponse = new StringBuffer();
                int r = in.read();
                while (r >= 0)
                {
                    mapResponse.append((char)r);
                    r = in.read();
                }
                in.close();
                
                //Using XPath to get the URL to the map image from the XML text
                XPath xpath = XPathFactory.newInstance().newXPath();
                String expression = "/Result/text()";
                ByteArrayInputStream bin = 
                    new ByteArrayInputStream(mapResponse.toString().getBytes());
                String result =  xpath.evaluate(expression, new InputSource(bin));
                bin.close();
                return new URL(result);
            }
            else
            {
                //TODO Add appropriate Exception handling
                logger.info ("Unexpected result when requesting a InputStream to " +
                    "read map URL. Expected InputStream, got: "+ contentObj.getClass());
                return null;
            }
        }
        catch (Throwable th)
        {
            //TODO Add appropriate Exception handling
            logger.warning("Caught unhandled Throwable " + th);
            return null;
        }
    }

Helper classes and methods

The following class encapsulates information for an incoming SMS. The basic get and set methods should be added.

    public class SMSRequestObject
    {
        private String message;
        private String sender;
        private String recipient;
        private long timestamp;
    }

A few more helper methods for the ParlayX calls need to be implemented, namely getLocation(...), sendMMS(...) and getSMS(...). These methods can be downloaded from attached resources, and a step by step tutorial for creating these can be found at http://playground.telenor.com/tutorials.