Poor mans GPS - Cell(Tower)ID / Location Area Code -Lookup

Tutorials that use the MapActivity. Many using GPS functionality.

Poor mans GPS - Cell(Tower)ID / Location Area Code -Lookup

Postby plusminus » Tue Dec 11, 2007 3:46 pm

This Tutorial was inspired by the awesome, but almost uncommented davanum Apache Blog.

Poor mans GPS - Cell(Tower)ID / Location Area Code -Lookup


What is this: This tutorial shows how to approximate your current location in the world using the CellID ( CellTowerID ) and LAC ( Location Area Code ), by requesting data, from a 'secret' Google-API.

What you will learn:
  • Reading out the CellID ( CellTowerID ) and LAC ( Location Area Code ) of your current Phone-Cell.
  • Setting up a HTTP-Connection
  • Posting Requests to that HTTP-Connection
  • Retrieve Latitude/Longitude from a 'secret' Google-API usign CellID and LAC.
  • Displaying a ProgressBar
  • Many more...
:?: Problems/Questions: post right below...

Difficulty: 3 of 5 :)

What it will look like:
Input (loaded automatically) :arrow: searching :arrow: found
Image Image
Image


Description:
0.) As always the first thoughts go to the GUI-Design using XML. As you all know a bit about XML-Layouting :arrow: from :arrow: other :arrow: Tutorials, we will handle this part a bit shorter here.

What we want to achieve is a layout like the first of the three pictures above. We achieve it with the following xml-code:
Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.              android:orientation="vertical"
  4.              android:layout_width="fill_parent"
  5.              android:layout_height="fill_parent"
  6.        >
  7.         <!-- Input-Stuff -->
  8.         <TextView ... >
  9.         <EditText ... />
  10.  
  11.         <TextView ... />
  12.         <EditText ... />
  13.         <!-- The Buttons next to each other -->
  14.         <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  15.                         android:orientation="horizontal"
  16.                         android:layout_width="fill_parent"
  17.                         android:layout_height="wrap_content"
  18.            >
  19.         <Button ... />
  20.         <Button ...>
  21.             <requestFocus/> <!-- Didn't know that this tag can be placed here <img src="http://www.anddev.org/images/smilies/smile.png" alt=":)" title="Smile" /> -->
  22.         </Button>
  23.     </LinearLayout>
  24. </LinearLayout>
Parsed in 0.003 seconds, using GeSHi 1.0.8.4


1.) Lets have a look at the well commented OnCreate(...)-method.
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. // ...
  2.         protected PhoneStateIntentReceiver myPhoneStateReceiver;
  3.         protected int myCellID = -1;
  4.         protected int myLAC = -1;
  5.         // ...
  6.  
  7.         @Override
  8.         public void onCreate(Bundle icicle) {
  9.                 super.onCreate(icicle);
  10.                 this.setContentView(R.layout.main);
  11.  
  12.                 /* Set up the PhoneStateIntentReceiver
  13.                  * and register it to notify us on changes
  14.                  * to the Phone's ServiceState. */
  15.                 this.myPhoneStateReceiver = new PhoneStateIntentReceiver(this,
  16.                                 this.myServiceStateHandler);
  17.                 this.myPhoneStateReceiver.notifyServiceState(MY_NOTIFICATION_ID);
  18.                 this.myPhoneStateReceiver.registerIntent();
  19.  
  20.                 // Save references to the EditTexts
  21.                 this.myEditLac = (EditText) findViewById(R.id.edit_lac);
  22.                 this.myEditCid = (EditText) findViewById(R.id.edit_cellid);
  23.  
  24.                 // Set the OnClickListeners            
  25.                 this.myCmdUpdate = (Button) findViewById(R.id.cmd_update);
  26.                 this.myCmdUpdate.setOnClickListener(this.cmdUpdateListener);
  27.                
  28.                 this.myCmdLocateMe = (Button) findViewById(R.id.cmd_locateme);
  29.                 this.myCmdLocateMe.setOnClickListener(this.cmdLocateListener);
  30.         }
Parsed in 0.033 seconds, using GeSHi 1.0.8.4


2.) Lets digg a bit deeper to the myServiceStateHandler, we used above. When the ServiceState of our Phone changed, it will read out the CellID and the LAC and set it to the EditTexts, at least once.(Constant updates, when the constant CONTINUOUS_UPDATING == true).
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.         /** Notification Handler for changed PhoneState 'events' */
  2.         Handler myServiceStateHandler = new Handler() {
  3.                 private boolean firstUpdate = true;
  4.                
  5.                 // @Override
  6.                 public void handleMessage(Message msg) {
  7.                         /* Recognize our message based on the what-ID*/
  8.                         switch (msg.what) {
  9.                                 case MY_NOTIFICATION_ID:
  10.                                         ServiceState sState = myPhoneStateReceiver
  11.                                                         .getServiceState();
  12.                                         /* Save the CellID and the LAC */
  13.                                         CellIDToLatLong.this.myCellID = sState.getCid();
  14.                                         CellIDToLatLong.this.myLAC = sState.getLac();
  15.                                         /* At least one refresh, then continuous refreshes, if set */
  16.                                         if (firstUpdate || CONTINUOUS_UPDATING == true) {
  17.                                                 firstUpdate = false;
  18.                                                 // Update the CellID and LAC EditTexts in the GUI
  19.                                                 updateTextFields();
  20.                                         }
  21.                                         return;
  22.                         }
  23.                 }
  24.         };
Parsed in 0.033 seconds, using GeSHi 1.0.8.4


3.)Now the both OnClickListeners:
The cmdUpdateListener is pretty easy, as it just updates the Edittexts.
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.         protected OnClickListener cmdUpdateListener = new OnClickListener() {
  2.                 // @Override
  3.                 public void onClick(View arg0) {
  4.                         // Update the CellID and LAC EditTexts in the GUI
  5.                         updateTextFields();
  6.                 }
Parsed in 0.034 seconds, using GeSHi 1.0.8.4

The cmdLocateListener as its name already says is a bit more complex.
To pretend that this task it an extremely complex operation we display a ProgressDialog that is shown for 5 seconds, before any work is done :lol:

At first it creates the ProgressDialog, then diggs into a Thread (Remember doing extensive work in the GUI Thread is :evil: ) trys to locate ourself by the CellID & LAC and finally dismisses the ProgressDialog.
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.         protected OnClickListener cmdLocateListener = new OnClickListener() {
  2.                 // @Override
  3.                 public void onClick(View arg0) {
  4.                         /* Show a progress-bar */
  5.                         myProgressDialog = ProgressDialog.show(CellIDToLatLong.this,
  6.                                         "Please wait...", "Doing Extreme Calculations...", true);
  7.                         new Thread() {
  8.                                 public void run() {
  9.                                        
  10.                                         try {
  11.                                                 /* Pretend this is really complex <img src="http://www.anddev.org/images/smilies/wink.png" alt=";)" title="Wink" /> */
  12.                                                 sleep(5000);
  13.                                                
  14.                                                 /* Parse the values from the EditTexts
  15.                                                  * and try to locate ourselves */
  16.                                                 int cellid = Integer.parseInt(myEditCid.getText().toString());
  17.                                                 int lac = Integer.parseInt(myEditLac.getText().toString());
  18.                                                
  19.                                                 tryToLoate(cellid, lac);
  20.                                                
  21.                                         } catch (NumberFormatException nfe) {
  22.                                                 // Crap was typed <img src="http://www.anddev.org/images/smilies/wink.png" alt=";)" title="Wink" />
  23.                                         } catch (Exception e) {
  24.                                                 Log.e("LocateMe", e.toString(), e);
  25.                                         }
  26.                                         myProgressDialog.dismiss();
  27.                                 }
  28.                         }.start();
  29.                 }
  30.         };
Parsed in 0.039 seconds, using GeSHi 1.0.8.4

4.)The most interesting part in this Tutorial is definitely the part, where the actual locating takes place. This happens in the tryToLocate(...)-method:
The first thing to be done is to set up a HTTP-Connection to communicate with a 'hidden' Google-API.
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.         public void tryToLoate(int aCellID, int aLAC) throws Exception {
  2.                 // Create a connection to some 'hidden' Google-API
  3.                 String baseURL = "http://www.google.com/glm/mmap";
  4.                 // Setup the connection
  5.                 HttpURL httpURL = new HttpURL(baseURL);
  6.                 HostConfiguration host = new HostConfiguration();
  7.                 host.setHost(httpURL.getHost(), httpURL.getPort());
  8.                 HttpConnection connection = connectionManager.getConnection(host);
Parsed in 0.038 seconds, using GeSHi 1.0.8.4


Now we open that Connection and send some data, using a RequestEntity, to it:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.                 try{
  2.                         // Open it
  3.                         connection.open();
  4.        
  5.                         // Post (send) data to the connection
  6.                         PostMethod postMethod = new PostMethod(baseURL);
  7.                         /* MyCellIDRequestEntity will provides
  8.                          * the request-content to send */
  9.                         postMethod.setRequestEntity(new MyCellIDRequestEntity(aCellID, aLAC));
  10.                         postMethod.execute(new HttpState(), connection);
Parsed in 0.037 seconds, using GeSHi 1.0.8.4


Having executed the Request, we want to grab what was responded by the Google-Service.
:idea: Note the data returned (also the data we sent) is highly proprietary :!:

Read some bytes until we reach the """errorCode""":
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.                         InputStream response = postMethod.getResponseBodyAsStream();
  2.                         DataInputStream dis = new DataInputStream(response);
  3.                        
  4.                         // Read some prior data
  5.                         dis.readShort();
  6.                         dis.readByte();
  7.                         // Read the error-code
  8.                         int errorCode = dis.readInt();
Parsed in 0.040 seconds, using GeSHi 1.0.8.4


If the """errorCode""" was Zero (0), there will be the lat/long waiting for us. Having read them, we start the System-Map-Activity with the lat/long we just read out:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.                         if (errorCode == 0) {
  2.                                 double lat = (double) dis.readInt() / 1000000D;
  3.                                 double lng = (double) dis.readInt() / 1000000D;
  4.                                 // Read the rest of the data
  5.                                 dis.readInt();
  6.                                 dis.readInt();
  7.                                 dis.readUTF();
  8.                                
  9.                                 /* Create a geo-ContentURI containing the
  10.                                  * lat/long-values and start the Map-Application */
  11.                                 ContentURI geoURI = ContentURI.create("geo:" + lat + "," + lng);
  12.                                 Intent mapViewIntent = new Intent(
  13.                                                 android.content.Intent.VIEW_ACTION, geoURI);
  14.                                 startActivity(mapViewIntent);
Parsed in 0.039 seconds, using GeSHi 1.0.8.4

If the """errorCode""" was not Zero (0), we display a "Sorry"-Notification:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.                         } else {
  2.                                 /* If the return code was not
  3.                                  * valid or indicated an error,
  4.                                  * we display a Sorry-Notification */
  5.                                 NotificationManager nm = (NotificationManager)
  6.                                                         getSystemService(NOTIFICATION_SERVICE);
  7.                                 nm.notifyWithText(100, "Could not find lat/long information",
  8.                                                 NotificationManager.LENGTH_SHORT, null);
  9.                         }
Parsed in 0.036 seconds, using GeSHi 1.0.8.4

And finally ensure, that the connection gets closed :!:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.                 }finally{
  2.                         connection.close();
  3.                 }
  4.         }
Parsed in 0.036 seconds, using GeSHi 1.0.8.4



5.) The MyCellIDRequestEntity.java is the last thing to be looked at. Its writeRequest(...)-method writes some data to an OutputStream. In our case this is very specific and highly proprietary data, as we are going to pretend to be a Sony Ericsson-K750. Have a look:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.         /** Pretend to be a French Sony Ericsson-K750 that
  2.          * wants to receive its lat/long-values =)
  3.          * The data written is highly proprietary !!! */
  4.         public void writeRequest(OutputStream outputStream) throws IOException {
  5.                 DataOutputStream os = new DataOutputStream(outputStream);
  6.                 os.writeShort(21);
  7.                 os.writeLong(0);
  8.                 os.writeUTF("fr");
  9.                 os.writeUTF("Sony_Ericsson-K750");
  10.                 os.writeUTF("1.3.1");
  11.                 os.writeUTF("Web");
  12.                 os.writeByte(27);
  13.  
  14.                 os.writeInt(0); os.writeInt(0); os.writeInt(3);
  15.                 os.writeUTF("");
  16.                 os.writeInt(myCellID); // CELL-ID
  17.                 os.writeInt(myLAC); // LAC
  18.                 os.writeInt(0); os.writeInt(0);
  19.                 os.writeInt(0); os.writeInt(0);
  20.                 os.flush();
  21.         }
Parsed in 0.039 seconds, using GeSHi 1.0.8.4


So, thats it :).

:idea: The CellID and LAC - Values provided by the emulator are not valid.
:arrow: Try the following to see an actual result (type them to the EditTexts):

Code: Select all
cellid=20442
lac=6015


The full source:

"/res/layout/main.xml":
Syntax: [ Download ] [ Hide ]
Using xml Syntax Highlighting
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.              android:orientation="vertical"
  4.              android:layout_width="fill_parent"
  5.              android:layout_height="fill_parent"
  6.        >
  7.         <!-- Input-Stuff -->
  8.         <TextView
  9.                 android:layout_width="wrap_content"
  10.                 android:layout_height="wrap_content"
  11.                 android:text="CELL-ID"
  12.                 />
  13.         <EditText id="@+id/edit_cellid"
  14.                 android:layout_width="fill_parent"
  15.                 android:layout_height="wrap_content"
  16.                 android:singleLine="true"
  17.                 />
  18.         <!-- The Buttons next to each other -->
  19.         <TextView
  20.                 android:layout_width="wrap_content"
  21.                 android:layout_height="wrap_content"
  22.                 android:text="LAC"
  23.                 />
  24.         <EditText id="@+id/edit_lac"
  25.                 android:layout_width="fill_parent"
  26.                 android:layout_height="wrap_content"
  27.                 android:singleLine="true"
  28.                 />
  29.                  
  30.         <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  31.                         android:orientation="horizontal"
  32.                         android:layout_width="fill_parent"
  33.                         android:layout_height="wrap_content"
  34.            >
  35.         <Button id="@+id/cmd_update"
  36.                         android:layout_width="wrap_content"
  37.                         android:layout_height="fill_parent"
  38.                         android:text="Update"
  39.                         />
  40.         <Button id="@+id/cmd_locateme"
  41.                         android:layout_width="wrap_content"
  42.                         android:layout_height="fill_parent"
  43.                         android:text="Locate Me!">
  44.             <requestFocus/>
  45.         </Button>
  46.     </LinearLayout>
  47. </LinearLayout>
Parsed in 0.006 seconds, using GeSHi 1.0.8.4


"/src/your_package_structure/CellIDToLatLong.java":
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package org.anddev.android.cellidtolatlong;
  2.  
  3. import java.io.DataInputStream;
  4. import java.io.InputStream;
  5.  
  6. import org.apache.commons.httpclient.HostConfiguration;
  7. import org.apache.commons.httpclient.HttpConnection;
  8. import org.apache.commons.httpclient.HttpConnectionManager;
  9. import org.apache.commons.httpclient.HttpState;
  10. import org.apache.commons.httpclient.HttpURL;
  11. import org.apache.commons.httpclient.SimpleHttpConnectionManager;
  12. import org.apache.commons.httpclient.methods.PostMethod;
  13.  
  14. import android.app.Activity;
  15. import android.app.NotificationManager;
  16. import android.app.ProgressDialog;
  17. import android.content.Intent;
  18. import android.net.ContentURI;
  19. import android.os.Bundle;
  20. import android.os.Handler;
  21. import android.os.Message;
  22. import android.telephony.PhoneStateIntentReceiver;
  23. import android.telephony.ServiceState;
  24. import android.util.Log;
  25. import android.view.View;
  26. import android.view.View.OnClickListener;
  27. import android.widget.Button;
  28. import android.widget.EditText;
  29.  
  30. public class CellIDToLatLong extends Activity {
  31.  
  32.         // ===========================================================
  33.         // Static Final Fields
  34.         // ===========================================================
  35.  
  36.         protected static final boolean CONTINUOUS_UPDATING = false;
  37.         protected static final int MY_NOTIFICATION_ID = 0x1337;
  38.         protected static final int PROGRESSBAR_ID = 0x1234;
  39.  
  40.         // ===========================================================
  41.         // Static Fields
  42.         // ===========================================================
  43.  
  44.         protected static HttpConnectionManager connectionManager = new SimpleHttpConnectionManager();
  45.  
  46.         // ===========================================================
  47.         // Fields
  48.         // ===========================================================
  49.  
  50.         protected PhoneStateIntentReceiver myPhoneStateReceiver;
  51.         /* GUI-Stuff */
  52.         protected EditText myEditLac;
  53.         protected EditText myEditCid;
  54.         protected Button myCmdLocateMe;
  55.         protected Button myCmdUpdate;
  56.  
  57.         protected int myCellID = -1;
  58.         protected int myLAC = -1;
  59.        
  60.         protected ProgressDialog myProgressDialog;
  61.  
  62.         // ===========================================================
  63.         // Fields with anonymous SubClasses
  64.         // ===========================================================
  65.  
  66.         protected OnClickListener cmdLocateListener = new OnClickListener() {
  67.                 // @Override
  68.                 public void onClick(View arg0) {
  69.                         /* Show a progress-bar */
  70.                         myProgressDialog = ProgressDialog.show(CellIDToLatLong.this,
  71.                                         "Please wait...", "Doing Extreme Calculations...", true);
  72.                         new Thread() {
  73.                                 public void run() {
  74.                                        
  75.                                         try {
  76.                                                 /* Pretend this is really complex <img src="http://www.anddev.org/images/smilies/wink.png" alt=";)" title="Wink" /> */
  77.                                                 sleep(5000);
  78.                                                
  79.                                                 /* Parse the values from the EditTexts
  80.                                                  * and try to locate ourselves */
  81.                                                 int cellid = Integer.parseInt(myEditCid.getText().toString());
  82.                                                 int lac = Integer.parseInt(myEditLac.getText().toString());
  83.                                                
  84.                                                 tryToLoate(cellid, lac);
  85.                                                
  86.                                         } catch (NumberFormatException nfe) {
  87.                                                 // Crap was typed <img src="http://www.anddev.org/images/smilies/wink.png" alt=";)" title="Wink" />
  88.                                         } catch (Exception e) {
  89.                                                 Log.e("LocateMe", e.toString(), e);
  90.                                         }
  91.                                         myProgressDialog.dismiss();
  92.                                 }
  93.                         }.start();
  94.                 }
  95.         };
  96.  
  97.         protected OnClickListener cmdUpdateListener = new OnClickListener() {
  98.                 // @Override
  99.                 public void onClick(View arg0) {
  100.                         updateTextFields();
  101.                 }
  102.         };
  103.  
  104.         /** Notification Handler for changed PhoneState 'events' */
  105.         Handler myServiceStateHandler = new Handler() {
  106.                 private boolean firstUpdate = true;
  107.                
  108.                 // @Override
  109.                 public void handleMessage(Message msg) {
  110.                         /* Recognize our message based on the what-ID*/
  111.                         switch (msg.what) {
  112.                                 case MY_NOTIFICATION_ID:
  113.                                         ServiceState sState = myPhoneStateReceiver
  114.                                                         .getServiceState();
  115.                                         /* Save the CellID and the LAC */
  116.                                         CellIDToLatLong.this.myCellID = sState.getCid();
  117.                                         CellIDToLatLong.this.myLAC = sState.getLac();
  118.                                         /* At least one refresh, then continuous refreshes, if set */
  119.                                         if (firstUpdate || CONTINUOUS_UPDATING == true) {
  120.                                                 firstUpdate = false;
  121.                                                 updateTextFields();
  122.                                         }
  123.                                         return;
  124.                         }
  125.                 }
  126.         };
  127.  
  128.         @Override
  129.         public void onCreate(Bundle icicle) {
  130.                 super.onCreate(icicle);
  131.                 this.setContentView(R.layout.main);
  132.  
  133.                 /* Set up the PhoneStateIntentReceiver
  134.                  * and register it to notify us on changes
  135.                  * to the Phone's ServiceState. */
  136.                 this.myPhoneStateReceiver = new PhoneStateIntentReceiver(this,
  137.                                 this.myServiceStateHandler);
  138.                 this.myPhoneStateReceiver.notifyServiceState(MY_NOTIFICATION_ID);
  139.                 this.myPhoneStateReceiver.registerIntent();
  140.  
  141.                 // Save references to the EditTexts
  142.                 this.myEditLac = (EditText) findViewById(R.id.edit_lac);
  143.                 this.myEditCid = (EditText) findViewById(R.id.edit_cellid);
  144.  
  145.                 // Set the OnClickListeners            
  146.                 this.myCmdUpdate = (Button) findViewById(R.id.cmd_update);
  147.                 this.myCmdUpdate.setOnClickListener(this.cmdUpdateListener);
  148.                
  149.                 this.myCmdLocateMe = (Button) findViewById(R.id.cmd_locateme);
  150.                 this.myCmdLocateMe.setOnClickListener(this.cmdLocateListener);
  151.         }
  152.  
  153.         /**
  154.          * Update the UI from the values stored in the notification handler
  155.          */
  156.         private void updateTextFields() {
  157.                 this.myEditCid.setText("" + this.myCellID);
  158.                 this.myEditLac.setText("" + this.myLAC);
  159.         }
  160.  
  161.         public void tryToLoate(int aCellID, int aLAC) throws Exception {
  162.                 // Create a connection to some 'hidden' Google-API
  163.                 String baseURL = "http://www.google.com/glm/mmap";
  164.                 // Setup the connection
  165.                 HttpURL httpURL = new HttpURL(baseURL);
  166.                 HostConfiguration host = new HostConfiguration();
  167.                 host.setHost(httpURL.getHost(), httpURL.getPort());
  168.                 HttpConnection connection = connectionManager.getConnection(host);
  169.                
  170.                 try{
  171.                         // Open it
  172.                         connection.open();
  173.        
  174.                         // Post (send) data to the connection
  175.                         PostMethod postMethod = new PostMethod(baseURL);
  176.                         /* MyCellIDRequestEntity will provides
  177.                          * the request-content to send */
  178.                         postMethod.setRequestEntity(new MyCellIDRequestEntity(aCellID, aLAC));
  179.                         postMethod.execute(new HttpState(), connection);
  180.                        
  181.                         InputStream response = postMethod.getResponseBodyAsStream();
  182.                         DataInputStream dis = new DataInputStream(response);
  183.                        
  184.                         // Read some prior data
  185.                         dis.readShort();
  186.                         dis.readByte();
  187.                         // Read the error-code
  188.                         int errorCode = dis.readInt();
  189.                         if (errorCode == 0) {
  190.                                 double lat = (double) dis.readInt() / 1000000D;
  191.                                 double lng = (double) dis.readInt() / 1000000D;
  192.                                 // Read the rest of the data
  193.                                 dis.readInt();
  194.                                 dis.readInt();
  195.                                 dis.readUTF();
  196.                                
  197.                                 /* Create a geo-ContentURI containing the
  198.                                  * lat/long-values and start the Map-Application */
  199.                                 ContentURI geoURI = ContentURI.create("geo:" + lat + "," + lng);
  200.                                 Intent mapViewIntent = new Intent(
  201.                                                 android.content.Intent.VIEW_ACTION, geoURI);
  202.                                 startActivity(mapViewIntent);
  203.                         } else {
  204.                                 /* If the return code was not
  205.                                  * valid or indicated an error,
  206.                                  * we display a Sorry-Notification */
  207.                                 NotificationManager nm = (NotificationManager)
  208.                                                         getSystemService(NOTIFICATION_SERVICE);
  209.                                 nm.notifyWithText(100, "Could not find lat/long information",
  210.                                                 NotificationManager.LENGTH_SHORT, null);
  211.                         }
  212.                 }finally{
  213.                         connection.close();
  214.                 }
  215.         }
  216. }
Parsed in 0.065 seconds, using GeSHi 1.0.8.4


"/src/your_package_structure/MyCellIDRequestEntity.java":
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. package org.anddev.android.cellidtolatlong;
  2.  
  3. import java.io.DataOutputStream;
  4. import java.io.IOException;
  5. import java.io.OutputStream;
  6.  
  7. import org.apache.commons.httpclient.methods.RequestEntity;
  8.  
  9. class MyCellIDRequestEntity implements RequestEntity {
  10.  
  11.         protected int myCellID;
  12.         protected int myLAC;
  13.  
  14.         public MyCellIDRequestEntity(int aCellID, int aLAC) {
  15.                 this.myCellID = aCellID;
  16.                 this.myLAC = aLAC;
  17.         }
  18.  
  19.         public boolean isRepeatable() {
  20.                 return true;
  21.         }
  22.  
  23.         /** Pretend to be a French Sony_Ericsson-K750 that
  24.          * wants to receive its lat/long-values =)
  25.          * The data written is highly proprietary !!! */
  26.         public void writeRequest(OutputStream outputStream) throws IOException {
  27.                 DataOutputStream os = new DataOutputStream(outputStream);
  28.                 os.writeShort(21);
  29.                 os.writeLong(0);
  30.                 os.writeUTF("fr");
  31.                 os.writeUTF("Sony_Ericsson-K750");
  32.                 os.writeUTF("1.3.1");
  33.                 os.writeUTF("Web");
  34.                 os.writeByte(27);
  35.  
  36.                 os.writeInt(0); os.writeInt(0); os.writeInt(3);
  37.                 os.writeUTF("");
  38.                 os.writeInt(myCellID); // CELL-ID
  39.                 os.writeInt(myLAC); // LAC
  40.                 os.writeInt(0); os.writeInt(0);
  41.                 os.writeInt(0); os.writeInt(0);
  42.                 os.flush();
  43.         }
  44.  
  45.         public long getContentLength() {
  46.                 return -1;
  47.         }
  48.  
  49.         public String getContentType() {
  50.                 return "application/binary";
  51.         }
  52. }
Parsed in 0.042 seconds, using GeSHi 1.0.8.4


Regards,
plusminus
Last edited by plusminus on Tue Dec 18, 2007 9:07 pm, edited 2 times in total.
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Top

Postby Katharnavas » Wed Dec 12, 2007 5:53 am

Hi,
Its really a very nice application and really worth waiting for it. Thanks for the nice work .. Can u tell me how to get the LAC and CellId for any location. (ex Im from india how to get the LAC and cellid for a location in India)..
Katharnavas
Senior Developer
Senior Developer
 
Posts: 100
Joined: Tue Dec 04, 2007 5:57 am
Location: India

Postby venkat » Wed Dec 12, 2007 6:59 am

Hi Plusminus,
once again very useful tutorial from anddev. :D . i am exited to see your tutorial. I run your application. if i click the Locate Me button, it is shows progress ProgressDialog box. after that, it's shows same screen only. i am from India and my port number is 3128. i have read below article in google group and they are saying google map will not display other than 1080(Port number). is it true??

Hey Adrian thats a bad news ....
but i guess its not all that bad ....there is one last option i can
think of but it'll be bit slow ...
but u'll have internet access on ur emulator...but don't try maps on
its coz it wud give u speeds of around 10kBps

get HTTPTunnel ( http://www.http-tunnel.com/html/ ) ....
install it and set it to use your proxy server
it's establish a tunnel over http(something that'll never be blocked)
it'll run a socks proxy on port 1080 by default ...
so make proxifier use this proxy (localhost:1080)
and make sure HTTPTunnel is excluded from proxifier...or else it'll
get stuck in a loop
best option proxify only ur emulator

this should probably help...
in case it doesn't IM me i'm online till 2 in the night Indian
Standard Time


regards.
venkat
venkat
Senior Developer
Senior Developer
 
Posts: 152
Joined: Tue Nov 27, 2007 5:42 am
Location: India

Why not Location Manager

Postby gsmith53 » Wed Dec 12, 2007 5:06 pm

Ok, this is great, but why wouldn't you create a LocationManager that uses the CellID functionality. Then you program your application to the existing LocationManager interface. That would make your application able to use the real GPS capabilities, if it has them, or the CellID capabilities if it doesn't have the GPS.

It would seem to me that this is where Google is going. It's GoogleMaps for mobile devices seems to already do this.

Don't get me wrong. It's a nice tutorial.
gsmith53
Freshman
Freshman
 
Posts: 9
Joined: Sat Dec 01, 2007 5:40 am
Location: Dallas, TX

Postby plusminus » Wed Dec 12, 2007 5:23 pm

venkat wrote:Hi Plusminus,
once again very useful tutorial from anddev. :D . i am exited to see your tutorial. I run your application. if i click the Locate Me button, it is shows progress ProgressDialog box. after that, it's shows same screen only. i am from India and my port number is 3128. i have read below article in google group and they are saying google map will not display other than 1080(Port number). is it true??

regards.
venkat


Hello venkat,

unfortunately I don't haven't been digging on that issue, but if they say that and no one complains about it it is probably true ;)

:idea: Btw: The CellID and LAC - Values provided by the emulator are not valid.
Try the following to see an actual result (type them to the EditTexts):
Code: Select all
cellid=20442
lac=6015


Regards,
plusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Postby quauhtlimtz » Thu Dec 13, 2007 5:51 pm

It is not clear for me why use this way to locate people if you have the GPS option that is even more accurate. Does anybody can tell me what are the advantages of using this the Cell-ID to locate your phone?
Last edited by quauhtlimtz on Thu Dec 13, 2007 5:53 pm, edited 1 time in total.
quauhtlimtz
Junior Developer
Junior Developer
 
Posts: 13
Joined: Mon Nov 26, 2007 5:56 pm
Location: Mexico

Top

Postby plusminus » Thu Dec 13, 2007 5:53 pm

quauhtlimtz wrote:It is not clear for me why use this way to locate people if you have the GPS option that is even more accurate. What are the advantages about using this way to locate people???


Hello quauhtlimtz,

there is exactly NO advantage, except the fact that perhaps not all phones come with a GPS-chip ;).

Regards,
olusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Postby quauhtlimtz » Thu Dec 13, 2007 5:56 pm

Thanks, plusminus, I thought that all the Android-based devices would have GPS :S
quauhtlimtz
Junior Developer
Junior Developer
 
Posts: 13
Joined: Mon Nov 26, 2007 5:56 pm
Location: Mexico

Postby plusminus » Thu Dec 13, 2007 6:15 pm

quauhtlimtz wrote:Thanks, plusminus, I thought that all the Android-based devices would have GPS :S


I hope they'll all have GPS :)

Regards,
plusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Postby jeremian » Fri Dec 14, 2007 12:22 am

Hi plusminus,

can you check, that this application is still runnable? I have tried several cellID/LAC values (20442/6015, 53361/9800, 32981/6206) without any success. The received errorCode is quite a big number, for example 1329812569. Any ideas?

Thanks in advance,
jeremian.
jeremian
Freshman
Freshman
 
Posts: 6
Joined: Thu Dec 13, 2007 11:28 pm

Postby plusminus » Fri Dec 14, 2007 12:56 am

Hello jeremian,

it works with me using: 20442/6015 or 53361/9800 (others probably too).
Perhaps Google added a ... "missuse"-blocker from countries too far from France (your IP provides Google your approximate location). :? :?: :?:
Where do you live then :?:

Edit: As the service is obviously highly proprietary it is hard to guess what is the problem here :(
Just tried some alternatives in the MyCellIDRequestEntity.java:
Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.                 // ...
  2.                 os.writeLong(0);
  3.                 os.writeUTF("fr"); // "de", "us" all work..
  4.                 os.writeUTF("Sony_Ericsson-K750");
  5.                 // ...
Parsed in 0.036 seconds, using GeSHi 1.0.8.4


Sorry that I cannot really help on this issue :(

Regards,
plusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Postby bhamdeveloper » Wed Dec 26, 2007 10:05 pm

quauhtlimtz wrote:It is not clear for me why use this way to locate people if you have the GPS option that is even more accurate. Does anybody can tell me what are the advantages of using this the Cell-ID to locate your phone?


There will be times where you will have really good cell coverage but not good satellite coverage (downtown in large cities with lots of tall buildings comes to mind). GPS works best with good open skies. This can be used when you have good signal even if you can't get a good GPS location.

Good tutorial plusminus.
bhamdeveloper
Freshman
Freshman
 
Posts: 3
Joined: Wed Dec 26, 2007 4:13 pm
Location: Alabama, United States

Postby puyopuy » Sun Feb 03, 2008 9:02 am

Hi plusminus,

I tried this sample and I got errorCode = 1, do you know what is this error code mean? I also tried to visit http://www.google.com/glm/mmap but I got "Not Found Error 404", is that mean this hidden Google API not valid any more?

Good luck to your exams and thank you for your hard work.
puyopuy
Junior Developer
Junior Developer
 
Posts: 17
Joined: Sun Feb 03, 2008 4:46 am

Postby plusminus » Sun Feb 03, 2008 11:13 am

Hello puyopuy,

calling the in the browser also leads to a 404 with me.
Tried my code with several values (20442/6015 ; 53361/9800 ; ... ) and it is still working (just tried it again).

Perhaps they are blocking some IP-Groups from specific countries :?

Regards,
plusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Postby chris » Tue Feb 05, 2008 10:39 am

Hi

Before i try getting into this , did anyone tried to do this with the com.google.googlenav.* classes ?
I'm thinking especialy of the CellTowerReporter ?
It's not documented so subject to change without notice but that would certainly be better than faking a request from a phone to a service ?

Cheers
chris
Junior Developer
Junior Developer
 
Posts: 18
Joined: Sat Feb 02, 2008 4:39 pm

Top
Next

Return to Map Tutorials

Who is online

Users browsing this forum: No registered users and 5 guests