I am trying to refresh the current location through a click of a button. The location can be acquired via GPS or Cell Tower, whichever is available. My problem is I never see the "Loading Screen". I know it appears as something appears/closes instantly while the coordinates remain zero. Can somebody help me - what I am doing wrong below?
Neither the location is updated nor the loading screen appears. Without the loading screen and by multiple clicks of the "refresh button" I do get the location. Below is my code for handling clicks on the "Refresh Button":
FieldChangeListener refreshImgListener = new FieldChangeListener() {
public void fieldChanged(Field field, int context)
{
Thread backgroundWorker = new Thread(new Runnable() {
public void run() {
refreshCoordinates();
}
});
busyDialog.setEscapeEnabled(false);
busyDialog.show();
backgroundWorker.start();
}
};
And my refreshCoordinates()
method is as below:
public void refreshCoordinates() {
do
{
getLatitude(handleeGPS.latitude);
getLongitude(handleeGPS.longitude);
} while ((longi == "0.0" || lati == "0.0") || (longi.length() == 0 || lati.length()==0));
UiApplication.getUiApplication().invokeLater( new Runnable()
{
public void run ()
{
lblLatitude.setText(lati);
lblLongitude.setText(longi);
busyDialog.cancel();
}
} );
}
public static String getLatitude(double value)
{
lati= Double.toString(value);
return lati;
}
public static String getLongitude(double value)
{
longi= Double.toString(value);
return longi;
}
Class that returns the latitude and longitude values:
public class handleeGPS{
static GPSThread gpsThread;
public static double latitude;
public static double longitude;
public handleeGPS(){
gpsThread = new GPSThread();
gpsThread.start();
}
private static class GPSThread extends Thread{
public void run() {
Criteria myCriteria = new Criteria();
myCriteria.setCostAllowed(false);
int m_bbHandle = CodeModuleManager.getModuleHandle("net_rim_bb_lbs");
if(m_bbHandle>0){
try {
int cellID = GPRSInfo.getCellInfo().getCellId();
int lac = GPRSInfo.getCellInfo().getLAC();
String urlString2 = "http://www.google.com/glm/mmap";
// Open a connection to Google Maps API
ConnectionFactory connFact = new ConnectionFactory();
ConnectionDescriptor connDesc;
connDesc = connFact.getConnection(urlString2);
HttpConnection httpConn2;
httpConn2 = (HttpConnection)connDesc.getConnection();
httpConn2.setRequestMethod("POST");
// Write some custom data to Google Maps API
OutputStream outputStream2 = httpConn2.openOutputStream();//getOutputStream();
WriteDataGoogleMaps(outputStream2, cellID, lac);
// Get the response
InputStream inputStream2 = httpConn2.openInputStream();//getInputStream();
DataInputStream dataInputStream2 = new DataInputStream(inputStream2);
// Interpret the response obtained
dataInputStream2.readShort();
dataInputStream2.readByte();
int code = dataInputStream2.readInt();
//Dialog.alert(code+"");
if (code == 0) {
latitude= dataInputStream2.readInt() / 1000000D;
longitude=dataInputStream2.readInt() / 1000000D;
//Dialog.alert(latitude+"-----"+longitude);
dataInputStream2.readInt();
dataInputStream2.readInt();
dataInputStream2.readUTF();
} else {
System.out.println("Error obtaining Cell Id ");
}
outputStream2.close();
inputStream2.close();
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
} else {
try {
LocationProvider myLocationProvider = LocationProvider.getInstance(myCriteria);
try {
Location myLocation = myLocationProvider.getLocation(300);
latitude = myLocation.getQualifiedCoordinates().getLatitude();
longitude = myLocation.getQualifiedCoordinates().getLongitude();
if(latitude==0.0 && longitude==0.0){
try {
int cellID = GPRSInfo.getCellInfo().getCellId();
int lac = GPRSInfo.getCellInfo().getLAC();
String urlString2 = "http://www.google.com/glm/mmap";
// Open a connection to Google Maps API
ConnectionFactory connFact = new ConnectionFactory();
ConnectionDescriptor connDesc;
connDesc = connFact.getConnection(urlString2);
HttpConnection httpConn2;
httpConn2 = (HttpConnection)connDesc.getConnection();
httpConn2.setRequestMethod("POST");
// Write some custom data to Google Maps API
OutputStream outputStream2 = httpConn2.openOutputStream();
//getOutputStream();
WriteDataGoogleMaps(outputStream2, cellID, lac);
// Get the response
InputStream inputStream2 = httpConn2.openInputStream();
//getInputStream();
DataInputStream dataInputStream2 = new DataInputStream(inputStream2);
// Interpret the response obtained
dataInputStream2.readShort();
dataInputStream2.readByte();
int code = dataInputStream2.readInt();
//Dialog.alert(code+"");
if (code == 0) {
latitude= dataInputStream2.readInt() / 1000000D;
longitude=dataInputStream2.readInt() / 1000000D;
//Dialog.alert(latitude+"-----"+longitude);
dataInputStream2.readInt();
dataInputStream2.readInt();
dataInputStream2.readUTF();
} else {
System.out.println("Error obtaining Cell Id ");
}
outputStream2.close();
inputStream2.close();
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}
catch ( InterruptedException iex ) {
return;
}
catch ( LocationException lex ) {
return;
}
} catch ( LocationException lex ) {
return;
}
}
return;
}
}
private static void WriteDataGoogleMaps(OutputStream out, int cellID, int lac)
throws IOException {
DataOutputStream dataOutputStream = new DataOutputStream(out);
dataOutputStream.writeShort(21);
dataOutputStream.writeLong(0);
dataOutputStream.writeUTF("en");
dataOutputStream.writeUTF("Android");
dataOutputStream.writeUTF("1.0");
dataOutputStream.writeUTF("Web");
dataOutputStream.writeByte(27);
dataOutputStream.writeInt(0);
dataOutputStream.writeInt(0);
dataOutputStream.writeInt(3);
dataOutputStream.writeUTF("");
dataOutputStream.writeInt(cellID);
dataOutputStream.writeInt(lac);
dataOutputStream.writeInt(0);
dataOutputStream.writeInt(0);
dataOutputStream.writeInt(0);
dataOutputStream.writeInt(0);
dataOutputStream.flush();
}
}
Ok, so although my original answer was valid, the new code you posted has some different problems, so I'm posting a second answer. There were enough things that didn't look right, that I just rewrote your
handleeGPS
class. I'll explain the major changes I made, one-by-one:Try to use Java naming conventions. This makes it easier for us to help you. Before you posted the code to your
handleeGPS
class, I thought it was a variable, because lowercase names are usually used for variables, not classes.Avoid duplicating code. The
handleeGPS
class had a lot of code to read through, but most of it was the code to get location from Google's web service, which you duplicated in two places. Just make a method that contains only that code, and call it twice.I renamed your
handleeGPS
class toGPSHandler
. I'm not sure ifhandlee
was an error, or if that's a word in another language that you used. Anyway, the name should at least start with an uppercase letter.Avoid lots of
static
variables and methods. Sometimes, there really should be only one of something. A GPS handling class is probably a good example of that, because the device only has one GPS system. But, to enforce this code construct, don't mark everything asstatic
. Just make the class a Singleton, which involves creating only onestatic
member variable (_instance
) and one static method (getInstance()
). In my code, you will access the class like this:GPSHandler gps = GPSHandler.getInstance();
.I believe the check you had for whether BB maps was installed was actually backwards. You looked up the
net_rim_bb_lbs
module, and if it was greater than zero (which means BB Maps is installed) then you went directly to the Google webservice. I think you want it the other way around (try device GPS if BB Maps installed). Also, since 6.0, you need to check fornet_rim_bb_maps
, too.Before you posted the update, I thought your
getLatitude()
andgetLongitude()
methods were actually fetching the device location. That was a bad assumption on my part. They were just converting numbers to strings. So, there's no reason for that to be done in the background (with aThread
). You already wrote yourhandleeGPS
class to use a background thread, which is good. One background thread is enough. The UI that uses the location information should not also need a backgroundThread
. I changed the code to add aGPSListener
interface. That interface should be implemented by your UI code, to receive location updates. There is no reason to keep looping, asking if the location is not equal to {0.0, 0.0}. That's inefficient. With my code, you will just get notified when the location does change.The original code was not thread safe. The
handleeGPS
latitude
andlongitude
variables were set on the background thread, and accessed on the UI thread. That's not safe. Two threads should not be reading and writing the same piece of data at once. By changing the code to push location data to theGPSListener
, it avoids this problem.I uncommented the
Dialog.alert()
code you had inside yourhandleeGPS
class, which would not have worked for you, because you're not allowed to make UI calls from the background. I surrounded those calls withUiApplication.getUiApplication().invokeLater()
to make them safe.To use this class, in your UI code somewhere, you would do this, instead of using a
Thread
to run yourrefreshCoordinates()
method:...
Make sure the class where you put that code (above) also
implements GPSListener
, which is an interface, defined here:and finally, the
GPSHandler
: