dotMobimobiForgemobiReadyDeviceAtlasgoMobi
background image

Adding Location to a non-GPS Phone - Part II

Section Feature Image
Posted by tomsoft - 20 Oct 2008
Twitter share icon Facebook share icon Google Plus share icon

In the first part of this article, we introduced the concept of CellID, and OpenCellID – an open source database of CellIDs that can be used to build location based services, and we created a small program to determine location from CellID information. This time, we will go a step further and display a map on a mobile device, using the open source "OpenStreetMap", and we position the map using the device's location. This will deliver an experience similar to that offered by the Google Maps for Mobile "MyLocation" feature, and will run on top of JavaME.

So to achieve this, we will use the J2meMap component. J2meMap is a library that we have created to develop our flagship product, a mobile tourist guide. The main purpose of this library is to make it easier to create mobile applications which make use of maps. This library is free for non-commercial use. J2meMap can display a map based on any of the main tile providers, such as Google, MSN or others, including the open source provider OpenStreetMap. We will look at how to make use of OpenStreetMap below. In addition, with J2meMap, you can add extra layers as bitmap, KML, GeoRSS, GPX and much more. A complete description of the J2meMap is available at http://j2memap.8motions.com.

The HelloMap program

So how how do we use J2meMap? It's very simple to get started; we use the MapDisplay class. The most simple J2meMap program is listed below:

import com.eightmotions.map.MapDisplay;
import com.eightmotions.util.UtilMidp;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
 
public class HelloMap extends MIDlet {
    public void startApp() {
        UtilMidp.checkMIDP(this);  //Initialise the utility library...
        Display.getDisplay(this).setCurrent((new MapDisplay()).getCanvas());
    }    
    public void pauseApp() {}
    public void destroyApp(boolean unconditional) {}
}

We create a MapDisplay object, and display the related Canvas. Already this gives us a good result: a map that we can play with and move about:

Using OpenStreeMap as a map provider

We now need to do two things: integrate OpenStreetMap, and make use of the OpenCellID database information. The OpenStreeMap integration is quite easy: you can implement or replace layers, by implementing the MapOverlay interface. Even better still, there is the GenericOverlay class, which abstracts away most of the complexity. For the GenericOverlay class we just need a URL, and a few settings:

    //Use GenericOverlay class
 
    MapOverlay openStreetMap = GenericOverlay("OpenStreetMap", "http://tile.openstreetmap.org/!z!/!x!/!y!.png");

The URL contains some special tokens, the ones between "!" characters: "!x!","!y!", and "!z!". These are dynamically replaced by appropriate values at run time. They are related to longitude, latitude, and zoom level. We will not go into detail of these values now, as they are beyond the scope of this article, but you should be aware that there are other related parameters such as !minLon!, !minLat!. In other words, this could be very easily used to connect to a Web Map Service (WMS) server.

Next we tell the engine to display it:

myMap.setMapProvider(0,openStreeMap);

Retrieving results from OpenCellID

At this point, we now have a map application where we can zoom in and out, and which is connected to OpenStreeMap. We can now make use of the code from part I. We add the following code after we retrieve and process the OpenCellID result:

                ....
                int pos=res.indexOf(',');
                String latStr=res.substring(0,pos);
                int pos2=res.indexOf(',',pos+1);
                String lonStr=res.substring(pos+1,pos2);
 
                myMap.setInfoOnScreen(latStr+" "+lonStr);
 
                float lat=Float.parseFloat(latStr);
                float lon=Float.parseFloat(lonStr);
                // If we are in a lower zoom mode, go into an higher mod
                if(myMap.getZoom()<10)myMap.setZoom(14);
                // If the 'current location' is not yet created, do it, and add it in the current track
                if(lastLoc==null){
                    lastLoc=new MyLoc();
                    t.addLoc(lastLoc);
                }
                lastLoc.setLonLat(lon,lat);
                myMap.goTo(lastLoc);

Adding a custom marker

So what is this MyLoc reference? Using the library, we can add elements on top of the map, such as pins or markers for example. We can also use images to make our own marker, but in this example, we will draw our own custom marker: an empty circle. To do this, we simply extend the default Marker, and add the size field.

class MyLoc extends Marker{
    public int range=1000;
    public MyLoc(){
        super();
    }
    public void paint(Graphics g,int inpx,int inpy,int offx,int offy,int w,int h,int zoom){
        int x=offx+w/2+(px-inpx)/(1<<zoom);
        int y=offy+h/2+(py-inpy)/(1<<zoom);
        g.setColor(0x8080A0);
        g.fillArc(x-6,y-6,12,12,0,360);
        g.setColor(0x0000C0);
        g.drawArc(x-50,y-50,100,100,0,360);
    }
}

Conclusion

The result of all this is as follows: when we press the "LocateMe" button on our device, a request will be sent to the OpenCellID server to see if there is a correspondence between this CellID and a geographical location stored on the server. If the CellID is identified, then we move the map to this location. That's it! Of course, the accuracy of the positioning depends on the quality of data in the OpenCellID database. Let us know how you get on, and if you see a gap in the database, you can help fill it by sending back information to the OpenCellID database using the client found here.

A few shortcuts are available:

  • 1 to zoom in
  • 3 to zoom out
  • 5 to change of map provider (choose between satellite and map views from Google, Microsoft, Yahoo, and Ask)

Important: as mentioned in the first part of this article, right now the OpenCellID client only supports SonyEricsson devices. On other phones, if you attempt to use this feature, the program will warn you with a "this phone does not support CellID" message.

The complete source code is available below, and the compiled program is available as both jad and jar archives. Please check the 8motions site for updates.

AttachmentSize
OpenCellIDSample.jad286 bytes
OpenCellIDSample.jar110.15 KB
MyOpenPos.java5.23 KB

Posted by tomsoft - 20 Oct 2008

tomsoft's picture

Thomas Landspurg is the CEO of 8Motions, a company specialized in providing services and technologies for mobile geolocalized system. Thomas also runs the OpenCellID opensource project.
Thomas is also involved in the Webwag project, aming to provide Widgets on all our connected devices...

Previsouly, Thomas was CTO of In-Fusio where he leaded the devleopment which created the first and one of the most succesful mobile game engine.

Posted by saneku 6 years ago

Very Nice, but i cant install OpenCellIdSample :(

Posted by ruadhan 6 years ago

Hi Saneku,

What device are you using? I have confirmed it's working like a charm on a Sony Ericsson V640i.

I've also sent some data back to the OpenCellID database using a bluetooth GPS paired with the V640i and the 8motions client, so it locates me even better now!

Ruadhan O'Donoghue
Editor, mobiForge

Posted by saneku 6 years ago

Hi!
I used Nokia 6267. After downloading application it wrote "Incorect application".

Then i tried Eten M700 and after downloading appeared error:
Midlet cannot be installed beacause critical information between the website and the Midlet file does not match. -31. Please contact the Midlet provider for more information.

Posted by saneku 6 years ago

Hi again Sony Ericsson W660i
does not work too

Posted by ruadhan 6 years ago

Hi Saneku,

I'm surprised that the SE didn't work, since the author has said it will work on later SE models... For the Nokia, I would have expected the application to install, but not to be able to retrieve cellID information.

Ruadhan O'Donoghue
Editor, mobiForge

Posted by tomsoft 6 years ago

Hello Saneku,

How do you install it on your mobile? Through Bluetooth or directly through the URL in this website?

Posted by abanjo 6 years ago

Hi,
this article is very interesting!
I've installed the sample application.
I found a little error in the Jad file.
The size of the jar is 112.791 and not 112782.

Once intalled, i've tryied it, but the localization doesn't work.
Then i've read with more accurancy the article and i see that the client use a SonyEricsson specific properties.
Well... my question is... how i can get the cell number with a nokia device?
There is a "standard" way to get this information, that works with different devices (nokia, sony, motorola ecc..)?

Thanks
Davide

Posted by saneku 6 years ago

Thanks, ABANJO!
Its really works!

Should be the next string in jad file:
MIDlet-Jar-Size: 112791

Posted by ronanhigg 6 years ago

OpenCellIDSample.jar placed me at latitude 0, longitude 0 from my SonyEricssn K800i GSM on O2 Ireland. I'm guessing it passed an unknown cell-ID and OpenCellID returned a 0,0 result.

Posted by ruadhan 6 years ago

Quote:

OpenCellIDSample.jar placed me at latitude 0, longitude 0

When I installed it on a SonyEricsson v640i on the Vodafone Ireland network, it placed me a couple of kilometers from my true location. After sending some location information back with the help of my trusty Holux M-1200 bluetooth GPS, it was pinpointing me perfectly, as it should.

I never got 0,0 for lat,lon though. You could try to send some data back to the database if you have a GPS handy. Thomas might be able to tell us if this is normal behaviour too.

Ruadhan O'Donoghue
Editor, mobiForge