Monthly Archives: January 2009

Creating a Blackberry GPS Tracker

As I mentioned in my article about Creating a Blackberry Game, I love this mobile phone and writing programs for it. The device has a serious amount of untapped potential. That’s not to say the phone isn’t already a great tool for its intended purposes (I don’t think I could make it without mine these days), but with the capabilities it has, there are a lot of creative ways it could be used for unconventional purposes.

Global Positioning System

One great feature of many modern Blackberrys is the built in GPS. This is an awesome technology for navigation – I don’t have a GPS in the car and my phone has saved my butt on a number of occasions. However, past that, think about the power this really gives. We’re starting to take positioning for granted these days, but the ability to pinpoint your exact location wherever you are is amazingly powerful. And not only for navigation – we have seen a number of very inventive programs popping up lately from trackers that pinpoint a lost/stolen phone, to photo tagging to attach a location to a picture taken. I’ve had lots of conversations with people as well who have great ideas for unique uses of GPSes. We’re definitely not even close to exhausting this functionality in the Blackberry.

Writing a GPS Program

When I first got my phone, I wanted to write a program to make use of the GPS. I decided I’d write a little tracker program, basically to continually read my current coordinates and post them to a website in realtime (that’s the other amazing piece about a Blackberry, the fact that you have an Internet connection whenever in cell range). The website would display these points on a google map, and people could see my current location and where I’d been (and how fast I was going!). It was a fun project, amazingly easy, and worked right off the bat!

Below is a very quick and dirty program to get the job done. It is not meant to be a polished product – it was a quick test, and I present it here as information on how to grab coordinates and upload them to a website. If you decide to make your own project, you’ll want to write the code a little more cleanly and organized – but this should give some tips on how the libraries are used. I’ve added lots of commenting to explain things as I go.

Also – a portion of the GPS code is grabbed from the RIM site I believe, though it was a long time ago and I’m not sure where. No disrespect to any code I’ve copied – if you find the original source, please post it and I’ll credit it.


tracker.java

package com.syntheticdreams.tracker;

/* This project makes use of many standard javax libraries, especially in reading the GPS.
** The microedition package in javax contains a number of mobile device related libraries, including the
** location package, which has methods specially designed for working with coordinates and 
** pulling them from a GPS.  The Blackberry supports the use of this package interfacing with its GPS (for 
** providers that have not locked the phone.  Verizon has, until recently, locked the GPS of many of its models
** from use by third party applications.)  The rest of our package importing is mainly for the user interface. */
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.system.*;
import javax.microedition.location.*;
import javax.microedition.location.Location.*;
import javax.microedition.location.Criteria.*;
import javax.microedition.io.*;
import java.util.*;

// The UiApplication is a class designed for presenting a user interface to the user and maintaining screens on a stack.  
// See Creating a Blackberry Game - Part 2 for more info (http://www.toniwestbrook.com/archives/71)
public class tracker extends UiApplication 
{
    // Our main method is always called first, starts the ball rolling
    public static void main(String[] args)
    {
        // Create a new instance of the main "tracker" class, pushes the main screen onto the stack
        tracker trackerApp = new tracker();

        // Enter the event dispatcher to intercept key and trackball events
        trackerApp.enterEventDispatcher();
    }

    public tracker() 
    {    
        // See startScreen class below, our main screen where the magic takes place.  Push it onto the stack so
        // the user sees it and the instance of the class starts running and processing.
        pushScreen(new startScreen());
    }
} 

// Our only screen to be pushed on the screen stack
final class startScreen extends MainScreen
{
    // A timer that will continually poll the GPS
    Timer updateTimer = new Timer(); 
        
    // The specific task for our timer where the dirty work takes place
    TimerTask updateTask = new TimerTask()
    {       
        // The run method is what is actually run by the timer every time it resets
        public void run()
        {
            LocationProvider lp; // LocationProvider does the actual work of reading coordinates from the GPS
            Location currentLoc; // Stores component information of our position
            Criteria cr = new Criteria(); // Settings for the GPS - we can read it at different accuracy levels
            HttpConnection httpConn;  // An HTTP socket connection class to send our results to a webserver
            String getStr; 

            // I basically set no requirements on any of the horizontal, vertical, or power consumption requirements below.  
            // The distance components are set in meters if you do want to establish accuracy - the less the accuracy, the 
            // quicker and more likely a successful read (I believe). 
            // You can also set power consumption, between low, medium, high (or no requirement)
            // There are also a number of other settings you can tweak such as minimum response time, if altitude is required,
            // speed required, etc.  It all depends on the exact application you're writing and how specific you need the info to
            // be.  For our purposes, a rough coordinate is good enough.
            cr.setCostAllowed(true);
            cr.setHorizontalAccuracy(javax.microedition.location.Criteria.NO_REQUIREMENT);
            cr.setVerticalAccuracy(javax.microedition.location.Criteria.NO_REQUIREMENT);
            cr.setPreferredPowerConsumption(javax.microedition.location.Criteria.NO_REQUIREMENT);

            try
            {
                // Get a new instance of the location provider using the criteria we established above.
                lp = LocationProvider.getInstance(cr);
 
                // Now populate our location object with our current location (with a 60 second timeout)
                currentLoc = lp.getLocation(60);
            }

            // If we hit the timeout or encountered some other error, report it.
            catch(LocationException e)
            {
                Dialog.alert("Error getting coordinates");
                return;
            }

            // If reading the GPS was interrupted, report it
            catch(InterruptedException e)
            {
                Dialog.alert("GPS Interrupted!");
                return;    
            }

            // If we made it here, we got a successful read.  I transmit it to a webserver via a simple querystring.
            try
            {
                // I build the querystring here             
                // set the "lat" querystring var with the latitude from getLatitude
                getStr = "lat=" + currentLoc.getQualifiedCoordinates().getLatitude();

                //lon with longitude
                getStr = getStr + "&lon=" + currentLoc.getQualifiedCoordinates().getLongitude();

                // alt with altitude
                getStr = getStr + "&alt=" + currentLoc.getQualifiedCoordinates().getAltitude();

                // vel with speed
                getStr = getStr + "&vel=" + currentLoc.getSpeed();

                // Now I establish an http connection the webserver running a server side script that can read the values from
                // the querystring and save them to a database.  In my case, I had a simple ASP page that wrote them to a MSSQL
                // database - this database being read by another webpage that printed said coordinates out on a google map.  
                // But you could do the same with PHP, PERL, or any other server side language of your choice.
                httpConn = (javax.microedition.io.HttpConnection) javax.microedition.io.Connector.open("http://www.yourwebsitehere.com/yourpage.asp?" + getStr);

                // Just an easy GET with a querystring.
                httpConn.setRequestMethod(HttpConnection.GET);

                // Set HTTP values
                httpConn.setRequestProperty("Connection","close");
                httpConn.setRequestProperty("Content-Length","0");

                // Make the request (e.g. send the data)
                httpConn.getResponseCode();

                // Close the socket
                httpConn.close();
            }

            // If there was an error contacting the webserver, post it
            catch (java.io.IOException e)
            {
                Dialog.alert("Error contacting web server");
                return;
            }
        }
    };

    // Our main screen's constructor
    public startScreen()
    {
        super();

        // Set the window's title
        LabelField title = new LabelField("GPS Tracker", LabelField.ELLIPSIS | LabelField.USE_ALL_WIDTH);
        setTitle(title);

        // Feel free to snazz up your program with your own messages or real time info from the GPS
        add(new RichTextField("Starting transmission..."));

        // Add the update task to the update timer, running it starting in 10 milliseconds, and then every
        // 240000 milliseconds (4 minutes)
        updateTimer.scheduleAtFixedRate(updateTask, 10, 240000);                   
    }
    
    // Cleanup on close
    public boolean onClose()
    {
       Dialog.alert("Transmission Ended!");
       System.exit(0);
       return true;    
    }
}

Nothing too bad – but very powerful! I hope this helps a bit on the road to making cool GPS applications!

I’m Back! PSX64 Sold Out (more soon)! New Job!

Lots of exclamation marks up there!

The Big Project Done

First off, I’m back to blogging after a 2-3 week hiatus finishing up fairly large programming project for work. The site has launched and things have (mostly) wrapped up. I’m glad to have done it for the experience, both the project itself and the issues that can go along with a large project, but I can’t explain how relieved I am to be done with it as well. I’ve read many horror stories concerning crunch time at dev houses (some of my favorites concerning projects at Commodore in On the Edge: the Spectacular Rise and Fall of Commodore, READ this book if you haven’t) – and while this one wasn’t a “pitch a sleeping bag under your desk for two weeks” kind of scenario, it was definitely a working into the wee hours of the morning for a while kind of deal. But it’s over, I had a very relaxing weekend of some serious video game playing, and I’m rested up for…

My New Job!

I will be starting as network administrator for Manchester Boston Regional Airport next week. I’m sad to be leaving friends at work, but I’m extremely psyched for the job. I’m a programmer and CS guy to the core, but there is a huge piece of me that misses network administration and working with a team managing infrastructure, and an airport seems like such an awesome environment to do it in. Plus, programming all day, sometimes you can get a little burnt out by the end of the day and not want to look at code at all. This has been a bummer in the past, because there are a lot of times when I want to work on private projects or blog related stuff, but have just been too pooped. Hopefully this will help that a bit. Trying to find the perfect balance.

PSX64

Lastly – I had opened up the Synthetic Dreams store to sell a small batch of PSX64s left over from conventions, and they sold out before I got a chance to advertise them. I will be putting in an order with the fab house on Wednesday, and soldering them up as soon as I get them. Look for the store to reopen with stock in the next 4 weeks. I apologize for the long wait, unfortunately it’s tough to turn out the boards as fast as I’d like to with full-time work and the time it takes to make the boards. But they are indeed coming!

Until the 19th

Just a heads up, I’m wrapping up a large project at work and it’s uber crunch time, so I’ll be posting mainly on the weekends only until the 19th. Purchasing is ready to go for the PSX64, I just had to push it off a few days unfortunately – the button to purchase will be up by this weekend.

In the meantime, for you text adventure fans like myself, check out this absolutely awesome video featuring MC Frontalot , nerdcore rapper extraordinaire (And guest appearance by Steve Meretsky!). I figured it was most appropriate with all the Gruepal work going on. :)