studio - google maps api key android
Decodificación de polilínea con la nueva API de Google Maps (8)
Aquí está la implementación en iOS, para cualquiera que tenga curiosidad, que se basa completamente en la respuesta de @Fustigador, pero que se convirtió a iOS. Tenga en cuenta que no he formateado el código en consecuencia. Solo agregué algunas variables para devolver el objeto prometido.
- (GMSPath *)decodedPolylinePathFromEncodedPolylineString:(NSString *)encodedPolylineString {
NSString *decodedPolylineString = @"";
GMSMutablePath *decodedPolylinePath = [GMSMutablePath new];
CLLocationCoordinate2D decodedCoordinate;
CLLocationDegrees latitude, longitude;
int index = 0;
NSUInteger len = encodedPolylineString.length;
int lat = 0, lng = 0;
while (index < len) {
int b, shift = 0, result = 0;
do {
b = [encodedPolylineString characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = [encodedPolylineString characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
latitude = (((double) lat / 1E5));
longitude = (((double) lng / 1E5));
decodedCoordinate = CLLocationCoordinate2DMake(latitude, longitude);
decodedPolylineString = [NSString stringWithFormat:@"%f%f", latitude, longitude];
;
NSLog(@"%@",decodedPolylineString);
[decodedPolylinePath addCoordinate:decodedCoordinate];
}
return decodedPolylinePath;
}
Estoy dibujando una ruta entre dos puntos en un mapa. Recibo los puntos de esta manera:
StringBuilder urlString = new StringBuilder();
urlString.append("http://maps.googleapis.com/maps/api/directions/json");
urlString.append("?origin=");// from
urlString.append(Double.toString(src.latitude));
urlString.append(",");
urlString.append(Double.toString(src.longitude));
urlString.append("&destination=");// to
urlString.append(Double.toString(dest.latitude));
urlString.append(",");
urlString.append(Double.toString(dest.longitude));
urlString.append("&sensor=false&mode=");
if (tipo != null) {
urlString.append(tipo);
}
return urlString.toString;
Recibo la respuesta de Google y obtengo el JSON:
resp = new JSONObject(builder.toString());
Log.i("Location", "Contenido del kml: "+resp);
JSONArray routeObject = resp.getJSONArray("routes");
JSONObject routes = routeObject.getJSONObject(0);
JSONObject overviewPolylines = routes
.getJSONObject("overview_polyline");
String encodedString = overviewPolylines.getString("points");
ArrayList<LatLng> puntos=decodePoly(encodedString);
La respuesta que recibo de google: (en formato JSON):
Response: {"status":"OK","routes":[{"waypoint_order":[],"summary":"R-3 and A-3","bounds":{"southwest":{"lng":-3.676540000000001,"lat":40.00040000000001},"northeast":{"lng":-2.99933,"lat":40.43357}},"legs":[{"duration":{"value":3267,"text":"54 mins"},"distance":{"value":85039,"text":"85.0 km"},"end_location":{"lng":-2.99933,"lat":40.00040000000001},"start_address":"Calle del General Díaz Porlier, 91, 28006 Madrid, Spain","end_address":"Camino Veinticuatro, 2, 16400 Tarancón, Cuenca, Spain","start_location":{"lng":-3.676540000000001,"lat":40.43331000000001},"via_waypoint":[],"steps":[{"html_instructions":"Head <b>north<//b> on <b>Calle del Gral Díaz Porlier<//b> toward <b>Calle de Maldonado<//b>","duration":{"value":6,"text":"1 min"},"distance":{"value":29,"text":"29 m"},"end_location":{"lng":-3.676520000000001,"lat":40.43357},"polyline":{"points":"ecxuFjamUs@C"},"travel_mode":"DRIVING","start_location":{"lng":-3.676540000000001,"lat":40.43331000000001}},{"html_instructions":"Take the 1st <b>right<//b> onto <b>Calle de Maldonado<//b>","duration":{"value":62,"text":"1 min"},"distance":{"value":266,"text":"0.3 km"},"end_location":{"lng":-3.6734,"lat":40.43345},"polyline":{"points":"ydxuFfamUPkG@a@JuGGk@"},"travel_mode":"DRIVING","start_location":{"lng":-3.676520000000001,"lat":40.43357}},{"html_instructions":"Take the 2nd <b>right<//b> onto <b>Calle de Fco. Silvela<//b>","duration":{"value":57,"text":"1 min"},"distance":{"value":245,"text":"0.2 km"},"end_location":{"lng":-3.671830000000001,"lat":40.4316},"polyline":{"points":"adxuFvmlURQl@e@zAoATSTMf@]pBeBLK"},"travel_mode":"DRIVING","start_location":{"lng":-3.6734,"lat":40.43345}},{"html_instructions":"Slight <b>right<//b> onto <b>Calle de Francisco Silvela<//b>","duration":{"value":51,"text":"1 min"},"distance":{"value":437,"text":"0.4 km"},"end_location":{"lng":-3.66913,"lat":40.42827},"polyline":{"points":"oxwuF|clUJADAFCbBkAjAeA`BoA^[XUPMLMFEnAeALIdBuAZUPMXS"},"travel_mode":"DRIVING","start_location":{"lng":-3.671830000000001,"lat":40.4316}},{"html_instructions":"Turn <b>right<//b> onto <b>Pl. de Manuel Becerra<//b>","duration":{"value":32,"text":"1 min"},"distance":{"value":154,"text":"0.2 km"},"end_location":{"lng":-3.668380000000001,"lat":40.42827},"polyline":{"points":"ucwuF`skU@?@@@@@?@@@?FBD?F@FAFAFADEDCFGDGDIBI@I@K@KAI?IAGAGAGCGCC?ACEEEIGGEICI?I?G@IBGD"},"travel_mode":"DRIVING","start_location":{"lng":-3.66913,"lat":40.42827}},{"html_instructions":"Turn <b>right<//b> onto <b>Calle Alcala<//b>","duration":{"value":61,"text":"1 min"},"distance":{"value":709,"text":"0.7 km"},"end_location":{"lng":-3.66107,"lat":40.43126000000001},"polyline":{"points":"ucwuFjnkUo@}A_AcCiEeLKYq@mBYq@[o@u@kB?KAQ]aAI[EQQu@Gc@QwAM_BEa@AU"},"travel_mode":"DRIVING","start_location":{"lng":-3.668380000000001,"lat":40.42827}},{"html_instructions":"Turn <b>right<//b> onto the ramp to <b>M-30//A-3//A-4<//b>","duration":{"value":44,"text":"1 min"},"distance":{"value":453,"text":"0.5 km"},"end_location":{"lng":-3.660580000000001,"lat":40.42720000000001},"polyline":{"points":"kvwuFt`jU//CjIg@nBKD?rCOvDY"},"travel_mode":"DRIVING","start_location":{"lng":-3.66107,"lat":40.43126000000001}},{"html_instructions":"Continue straight","duration":{"value":45,"text":"1 min"},"distance":{"value":1009,"text":"1.0 km"},"end_location":{"lng":-3.659120000000001,"lat":40.41822000000001},"polyline":{"points":"_}vuFr}iUzKgBvCe@t@KvGm@hDUbAMPCZElAM|D_@^En@EjBEd@Df@DnAD"},"travel_mode":"DRIVING","start_location":{"lng":-3.660580000000001,"lat":40.42720000000001}},{"html_instructions":"Take exit <b>7B<//b> to merge onto <b>M-23<//b> toward <b>Vicálvaro//R-3//Valencia<//b>","duration":{"value":117,"text":"2 mins"},"distance":{"value":2552,"text":"2.6 km"},"end_location":{"lng":-3.63392,"lat":40.41499},"polyline":{"points":"{duuFntiUFHB@^PDBFFFDDFDFBDDFBH@BBJ@F@H?F@H?FAH?FAF?FADAFAFCDADADEFCFEDEDEDEBEBEBGBE@G@E@G?G?EAG?GCGAGCEEGEEEEEEGEICIEIAKCKAK?K?MDgA?G?E?KJq@BODY@CBODW?C@I@AFe@F_@V{An@gED[@C?EHe@Ho@@G?A^{BjA}HF[tAiGzBwIdAcEVgApAuFr@sEF]Ju@DW?EDUHa@f@qEFo@f@iGXmHDgFCgGG{DM
Y finalmente, decodifico la Cadena recibida de esta manera, que encontré en muchas respuestas aquí en Stackoverflow:
private ArrayList<LatLng> decodePoly(String encoded) {
Log.i("Location", "String received: "+encoded);
ArrayList<LatLng> poly = new ArrayList<LatLng>();
int index = 0, len = encoded.length();
int lat = 0, lng = 0;
while (index < len) {
int b, shift = 0, result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
LatLng p = new LatLng((int) (((double) lat /1E5)* 1E6), (int) (((double) lng/1E5 * 1E6)));
poly.add(p);
}
for(int i=0;i<poly.size();i++){
Log.i("Location", "Point sent: Latitude: "+poly.get(i).latitude+" Longitude: "+poly.get(i).longitude);
}
return poly;
}
Aquí es donde creo que está el error, porque configuro un para ver los puntos que se están decodificando, y la respuesta es algo como:
04-10 13:33:54.578: I/Location(25065): Point sent: Latitude: 90.0 Longitude: -110.0
04-10 13:33:54.578: I/Location(25065): Point sent: Latitude: 90.0 Longitude: -120.0
04-10 13:33:54.578: I/Location(25065): Point sent: Latitude: 90.0 Longitude: 100.0
04-10 13:33:54.578: I/Location(25065): Point sent: Latitude: 90.0 Longitude: 120.0
04-10 13:33:54.578: I/Location(25065): Point sent: Latitude: 90.0 Longitude: 40.0
Obviamente, estos puntos están mal analizados. El resultado es, ninguna línea dibujada en ninguna parte.
Mi pregunta es ... ¿alguien sabe cómo analizar la respuesta de Google y traducirla a objetos LatLng (NO a objetos GeoPoints)?
¡Gracias!
EDITAR:
Esta es la cadena que está a punto de ser decodificada:
04-10 13:50:51.608: I/Location(25065): String to decode: gcxuFjamUq@CPkGLwHJ}@hCuBdEeDf@SrJuHnG{Ed@Fr@q@AmAm@k@e@DaIaSiEuLqAwJ~Mw@~ZwDtZuC`FKbCVjA`ANdAs@nBw@Py@]c@oAT}DhC{PlBcM~GaY|DyS`BmPRy]yBu/UsNvAqObAuEnC}KpAqIh@gK[}NcByWXoRt@}GlDeWvFcq@nFi`@~G}/|@aDdDoLn`@}gAfe@upA`JyV|CiN~@uId@{ZyBwVkBmOwB{^AsNt@iWb@qYcCyS_DkPmAaK{@gRN{RbCkWrFgUbHmPxLsP|JwIpPwN|G}JfE}I|C_KlCsNvAwSFaQj@i]jCmXbHg/pIgSpGaLnN}P`JsHfVaNbQkHtZyIrOsCnTaCx/aA`i@b@nSRz]K`J{AxJiDfNkJjU{WbKkJpGeEpVkPpEiEzMcQjQw]nJyM~IoJ`IoKnH{NrOaWtIeJdNgNrLcPjKqOhIuI~MeJxKgErR{Cn]EjQkBjHqBfJeE|/yTlI_JvEqJxHsS|Xuc@~IeR|EiRr@kEz@sNOoL_B}Lk@mCsFgKkCoGwAsG]}N`CuO`D}GjHoHtFwC|HgBhFg@fJ}BtHaF~D_FjLqSfGqE|FcBnGEnEv@xK`BzNeAxQfAlJ{@jIwEjE}FvBuF|B{NtCsNrBgEdHiIdGuIxDoFpGkFhDaBrHyBbF[pHPlDg@jEuBnCkCtFgKjEqEfIcGpC{D|GoNdAcExAkSjBgDrCsBpDa@vHLfSAfBk@nE_F|Im`@tO_ZxCyEzJmKtHyElG_ClZeF|j@sIlQaD|EuChGkHnK{MdIsMfPwa@bDeJpD_RpFsz@nA}IrCqIrYoa@|BeGlEiYpD}HbKoRfCyKdBwUjEmo@zBkKzDyJvCeQdB}LJqGmAqQJ_Gx@uFtHkO`ImMfMmXtFySpCkXRuN]aYVoT~@}LxB{NvD{OjJaYbFsLnCcEtLoMfJyXzIiXbIiL~D_EzQcMjDeF|AcFhA_M`BkXpC_KjCsDnDeClQcHvEgElFqJfF_Jp/mWzd@k]`WkWlVy`@nOcTz`@_s@rP_ZbNkQ~Tu^jJaUhCuIpHgUrPi/zd@uq@~McQh/e]vTaU~KcF~KoGhG{KzF{HzGmDbDwBfDiEzB}GbEmTrBsHpCuFxe@oq@xb@el@tDgC`ZeJnXkHrKmB~EeB~C{A`Ce@bCUrBoAnAuGSqIn@yEhDeOrCuQ|A}EvAwFdDgAfGSrHUJ/p@Bj@_A|Ao@tCsD|C}Rj@wAdCuW~Ds]VCJw@OUpEc_@jDKbDwB
Si con formato LatLng te refieres a la forma en que se crean los objetos LatLng, puedes ver en el método decodePoly. Estos objetos latLng se agregan a los objetos PolylineOptions, y esto se agrega al mapa, de esta manera:
PolylineOption ruta=new PolylineOptions();
for(int i=0;i<puntos.size();i++){
ruta.add(new LatLng(puntos.get(i).latitude, puntos.get(i).longitude));
}//puntos is an array where the array returned by the decodePoly method are stored
ruta.color(Color.RED).width(7);
Polyline polygon=mapa.addPolyline(ruta);
Aquí está tu función en Visual Basic, que uso a menudo.
Structure LatLng
Dim Lat As Decimal
Dim Lon As Decimal
End Structure
Function decodePoly(ByRef encoded As String) As List(Of LatLng)
Dim poly As List(Of LatLng) = New List(Of LatLng)
Dim index As Integer = 0
Dim len As Integer = encoded.Length()
Dim lat As Integer = 0
Dim lng As Integer = 0
While (index < len)
Dim b As Integer
Dim shift As Integer = 0
Dim result As Integer = 0
Do
b = AscW(encoded.Chars(index)) - 63
index += 1
result = result Or (b And &H1F) << shift
shift += 5
Loop While (b >= &H20)
Dim dlat As Integer
If (result And 1) <> 0 Then
dlat = Not (result >> 1)
Else
dlat = result >> 1
End If
lat += dlat
shift = 0
result = 0
Do
b = AscW(encoded.Chars(index)) - 63
index += 1
result = result Or (b And &H1F) << shift
shift += 5
Loop While (b >= &H20)
Dim dlng As Integer
If (result And 1) <> 0 Then
dlng = Not (result >> 1)
Else
dlng = result >> 1
End If
lng += dlng
Dim p As LatLng = New LatLng With {.Lat = (lat / 100000.0), .Lon = (lng / 100000.0)}
poly.Add(p)
End While
decodePoly = poly
End Function
Cambié el decodePoly que estaba usando para este que encontré después de una larga búsqueda en Google, y ahora la ruta se dibuja correctamente.
Cambiando
LatLng p = new LatLng((int) (((double) lat /1E5)* 1E6), (int) (((double) lng/1E5 * 1E6)));
para
LatLng p = new LatLng((((double) lat / 1E5)),(((double) lng / 1E5)));
Y ahora funciona.
Este método es útil para decodificar polilínea.
private List<LatLng> decodePoly(String encoded) {
List<LatLng> poly = new ArrayList<>();
int index = 0, len = encoded.length();
int lat = 0, lng = 0;
while (index < len) {
int b, shift = 0, result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
lng += dlng;
LatLng p = new LatLng((((double) lat / 1E5)),
(((double) lng / 1E5)));
poly.add(p);
}
return poly;
}
Así es como estoy haciendo polilínea.
JSONObject poly = route.getJSONObject("overview_polyline");
String polyline = poly.getString("points");
polyLineList = decodePoly(polyline);
Lo mismo en Javascript
function decodePolyline(encoded) {
if (!encoded) {
return [];
}
var poly = [];
var index = 0, len = encoded.length;
var lat = 0, lng = 0;
while (index < len) {
var b, shift = 0, result = 0;
do {
b = encoded.charCodeAt(index++) - 63;
result = result | ((b & 0x1f) << shift);
shift += 5;
} while (b >= 0x20);
var dlat = (result & 1) != 0 ? ~(result >> 1) : (result >> 1);
lat += dlat;
shift = 0;
result = 0;
do {
b = encoded.charCodeAt(index++) - 63;
result = result | ((b & 0x1f) << shift);
shift += 5;
} while (b >= 0x20);
var dlng = (result & 1) != 0 ? ~(result >> 1) : (result >> 1);
lng += dlng;
var p = {
latitude: lat / 1e5,
longitude: lng / 1e5,
};
poly.push(p);
}
return poly;
}
Lo mismo en Pascal (Delfos):
var lat,lon,lat_f,lon_f:Double;
var index:Integer;
var len:Integer;
var b:Integer;
var shift:Integer;
var result:Integer;
var encoded:String;
var dlat:Integer;
var dlng:Integer;
encoded:=''ibgqGq}ycIMvM'';
len:= Length(encoded);
lat:=0;
lon:=0;
While (index <=len) do
begin
b:=$20;
shift:=0;
result:=0;
While (b >= $20) do
begin
b:=ord(encoded[index]);
b:=b-63;
index:= index+1;
result:= result OR (b AND $1f) Shl shift;
shift:=shift + 5;
end;
If (result And 1) <> 0 Then
dlat:= Not (result Shr 1)
Else
dlat:= result Shr 1;
lat:=lat+dlat;
shift:= 0;
result:= 0;
b:=$20;
While (b >= $20) do
begin
b:=ord(encoded[index]);
b:=b-63;
index:= index+1;
result:= result OR (b AND $1f) Shl shift;
shift:=shift + 5;
end;
If (result And 1) <> 0 Then
dlng:= Not (result Shr 1)
Else
dlng:= result Shr 1;
lon:=lon+dlng;
{ The coordinates of the point are used for our purposes }
lon_f:=lon/100000.0;
lat_f:=lat/100000.0;
end; //while
Para aquellos que necesitan esto ahora, hay una biblioteca de código abierto con muchas cosas útiles relacionadas con la API de Android de Google Maps, incluida la decodificación y codificación de polilíneas.
Compruébelo en Android Maps Utils y android-maps-utils . Para decodificación y codificación de uso:
PolyUtil.decode(String encodedPath);
PolyUtil.encode(List<LatLng> path);
Publiqué una respuesta similar a esta pregunta en otra publicación para Android / Java. Decodificando el poly y devolviendo Latlng en lugar de Geopoints.