miércoles, 14 de septiembre de 2011

Sin GPS, No hay problema, Google nos dice donde estamos | Ecuador Blackberry

Sin GPS, No hay problema, Google nos dice donde estamos

Algunos modelos de BlackBerry desgraciadamente no disponen de GPS. Peor aun, con GPS, igual podemos estar bajo techo o en un lugar sin disponibilidad del servicio. Cada dia que pasa las aplicaciones y servicios basados en localizacion se hacen cada vez mas universales y necesarias.

Algunas apps requieren de un valor mas exacto de nuestra ubicacion, otras no tanto. Para esas aplicaciones que solo requieren aproximar en el rango de un kilometro nuestra ubicacion podemos utilizar un servicio de localizacion de Google, el cual mediante la informacion de la red celular y nivel de sennal nos dice donde estamos, o al menos una aproximacion.

La API de Google se puede encontrar en la URL http://www.google.com/loc/json y como pueden suponer utiliza el formato JSON para recibir la peticion y enviar la respuesta.

gloc = new Thread() {
public void run() {
try {
JSONObject jsonString = new JSONObject();
jsonString.put("version", "1.1.0");
jsonString.put("host", "maps.google.com");
int x = RadioInfo.getMCC(RadioInfo.getCurrentNetworkIndex());
jsonString.put("home_mobile_country_code", ((Helper.DEBUG)?Helper.GPS_TEST_HMCC:x));
jsonString.put("home_mobile_network_code", ((Helper.DEBUG)?Helper.GPS_TEST_HMNC:RadioInfo.getMNC(RadioInfo.getCurrentNetworkIndex())));

jsonString.put("radio_type","gsm");
jsonString.put("carrier", ((Helper.DEBUG)?Helper.GPS_TEST_CARRIER:RadioInfo.getCurrentNetworkName()));
jsonString.put("request_address", true);
jsonString.put("address_language", "en_GB");

CellTower cellInfo = new CellTower(x, GPRSInfo.getCellInfo().getLAC(),GPRSInfo.getCellInfo().getRSSI(), GPRSInfo.getCellInfo().getCellId(),0,RadioInfo.getMNC(RadioInfo.getCurrentNetworkIndex()));
JSONObject map = new JSONObject();
map.put("mobile_country_code", ((Helper.DEBUG)?Helper.GPS_TEST_HMCC:cellInfo.mobileCountryCode));
map.put("location_area_code", ((Helper.DEBUG)?Helper.GPS_TEST_LAC:cellInfo.locationAreaCode));
map.put("signal_strength", new Integer(cellInfo.signalStrength));
map.put("cell_id", ((Helper.DEBUG)?Helper.GPS_TEST_CELLID:cellInfo.cellID));
map.put("age", 0);
map.put("mobile_network_code", ((Helper.DEBUG)?Helper.GPS_TEST_HMNC:cellInfo.mobileNetworkCode));

JSONArray array = new JSONArray();
array.put(0,map);

jsonString.put("cell_towers",array);

// Enviar por HTTP POST
HttpConnection con = (HttpConnection)Connector.open(Helper.url("http://www.google.com/loc/json"));
con.setRequestMethod(HttpConnection.POST);
OutputStream dos = con.openOutputStream();
dos.write(jsonString.toString().getBytes());
dos.close();

if (con.getResponseCode()==HttpConnection.HTTP_OK) {
InputStream is = con.openInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[8192];
int leido = is.read(buffer);
while (leido>0) {
baos.write(buffer,0,leido);
leido = is.read(buffer);
}
is.close();
con.close();
try {
JSONObject jsonResponse = new JSONObject(baos.toString());
JSONObject location = jsonResponse.getJSONObject("location");
GPSFixInfo info = new GPSFixInfo();
info.fromGPS = false;
info.latitude = Double.parseDouble(location.get("latitude").toString());
info.longitude = Double.parseDouble(location.get("longitude").toString());
double accuracy = Double.parseDouble(location.get("accuracy").toString());
info.horAccuracy = (float)(accuracy/2);
info.verAccuracy = (float)(accuracy/2);
storage.addElement(info);
if (events!=null) {
locationObtained(info);
}
} catch (Exception e) {
googleLocationResponseError();
}
} else {
con.close();
googleLocationError(con.getResponseMessage());
}
} catch (Exception e) {
events.googleLocationError(e.getMessage());
}
finishedLocationByGoogle();
}
};
gloc.start();

En este ejemplo podemos ver varios elementos adicionales que iremos incluyendo:

Clase Helper
Esta es una clase estatica con variables y metodos usados en todo el proyecto. En este caso define algunas variables de localizacion para el simulador. Ya que este metodo de localizacion no funciona en el simulador porque la informacion de antenas simuladas no es real, con estas variables simulamos directamente que nos encontramos en una posicion al norte de la ciudad (de Guayaquil).

public class Helper {

public static final boolean DEBUG = DeviceInfo.isSimulator();
public static final String GPS_TEST_CARRIER = "movistar";
public static final int GPS_TEST_HMCC = 1856; // Ecuador
public static final int GPS_TEST_HMNC = 0; // Movistar
public static final int GPS_TEST_LAC = 51301; // Location Area Code
public static final int GPS_TEST_CELLID = 52817; // Cell ID

public static String url(String string) {
TransportDetective td = new TransportDetective();
URLFactory urlFac = new URLFactory(string);
if (td.isCoverageAvailable(TransportDetective.TRANSPORT_TCP_WIFI)) {
return urlFac.getHttpTcpWiFiUrl();
} else if (td.isCoverageAvailable(TransportDetective.TRANSPORT_BIS_B)) {
return urlFac.getHttpBisUrl();
} else if (td.isCoverageAvailable(TransportDetective.TRANSPORT_WAP2)) {
ServiceRecord sr = getWAP2ServiceRecord();
if (sr!=null) {
return urlFac.getHttpWap2Url(sr);
}
}
return urlFac.getHttpDefaultUrl();
}

private static ServiceRecord getWAP2ServiceRecord() {
ServiceRecord[] records = ServiceBook.getSB().getRecords();
int currentRecord;

for(currentRecord = 0; currentRecord < records.length; currentRecord++) {
if(records[currentRecord].getCid().toLowerCase().equals("wptcp")) {
if(records[currentRecord].getName().toLowerCase().indexOf("wap2") >= 0) {
return records[currentRecord];
}
}
}
return null;
}
}

Clase GPSFixInfo
Esta clase solo es una agregacion de las coordenadas y datos adicionales de GPS

public class GPSFixInfo {
public double latitude;
public double longitude;
public boolean fromGPS;
public float horAccuracy;
public float verAccuracy;

public GPSFixInfo() {

}
}

Adicionalmente necesitaran la API de JSON Mobile Edition que pueden encontrar en otro articulo del blog, asi como TransportDetective y URLFactory, tambien en el blog.

En las pruebas que he realizado me ha logrado ubicar con bastante presicion de hasta 1km el lugar donde me encuentro. Mientras mas cerca este de la torre celular mejor exactitud me da.


Sin GPS, No hay problema, Google nos dice donde estamos | Ecuador Blackberry: