Android Code Snippet [B4X] Google Geocoding REST API

This code is compatible with B4A, B4i and B4J.

1. Get an API key: https://developers.google.com/maps/documentation/geocoding/get-api-key

2.
B4X:
Sub PlaceToLatLon(Place As String) As ResumableSub
   Dim res() As Double = Array As Double(9999, 9999)
   Dim j As HttpJob
   j.Initialize("", Me)
   j.Download2("https://maps.googleapis.com/maps/api/geocode/json", Array As String("key", API_KEY, "address", Place))
   Wait For (j) JobDone(j As HttpJob)
   If j.Success Then
     Dim jp As JSONParser
     jp.Initialize(j.GetString)
     Dim m As Map = jp.NextObject
     If m.Get("status") = "OK" Then
       Dim results As List = m.Get("results")
       If results.Size > 0 Then
         Dim first As Map = results.Get(0)
         Dim geometry As Map = first.Get("geometry")
         Dim location As Map = geometry.Get("location")
         res(0) = location.Get("lat")
         res(1) = location.Get("lng")
       End If
     End If
   Else
     Log("Error!")
   End If
   j.Release
   Return res
End Sub

Usage example:
B4X:
Wait For(PlaceToLatLon("Israel Yodfat")) Complete (ll() As Double)
If ll(0) <> 9999 Then
   Log("Location: " & ll(0) & ", " & ll(1))
Else
   Log("Failed to geocode.")
End If
 
Last edited:

KMatle

Expert
Licensed User
Longtime User
Get address from latitude & longitude (e.g. from the GPS coordinates)
B4X:
Dim GetAddressJob As HttpJob
    GetAddressJob.Initialize("GetAddress", Me)
    GetAddressJob.Download2("https://maps.googleapis.com/maps/api/geocode/json", _
              Array As String("latlng", lat & "," & lon,"key",API_KEY))

Get directions (Location A -> Location B)
B4X:
Dim GetDirectionsJob As HttpJob
    GetDirectionsJob.Initialize("Directions", Me)
    GetDirectionsJob.Download2("https://maps.googleapis.com/maps/api/directions/json", _
              Array As String("origin","Cologne","destination","Paris","key",API_KEY))
 

wes58

Active Member
Licensed User
Longtime User
If you use code from post #2 to get directions, you might want to use this code to draw polylines from encoded polyline that you will receive. This gives you an accurate polyline that follows the road.

B4X:
Dim travelduration As Int = 0
Dim traveldistance As Int = 0
Dim start_address As String
Dim end_address As String
Dim pline As Polyline
Dim polyPoints As String

Sub GetDirections(source As String, destination As String) 'As ResumableSub
    Dim j As HttpJob
    Dim API_KEY As String = "insert your api key "        'directions api key
'    Get directions (Location A -> Location B)
    j.Initialize("Directions", Me)
    j.Download2("https://maps.googleapis.com/maps/api/directions/json", Array As String("origin", source,"destination", destination,"key",API_KEY))

    Wait For (j) JobDone(j As HttpJob)
    If j.Success Then
        Dim parser As JSONParser
        parser.Initialize(j.GetString)
        Dim root As Map = parser.NextObject
        If root.Get("status") = "OK" Then
            Dim routes As List = root.Get("routes")
            For Each colroutes As Map In routes
                Dim legs As List = colroutes.Get("legs")
                For Each collegs As Map In legs
                    start_address  = collegs.Get("start_address")
                    end_address = collegs.Get("end_address")
                    Dim steps As List = collegs.Get("steps")
                    For Each colsteps As Map In steps
                        Dim duration As Map = colsteps.Get("duration")
                        travelduration = travelduration + duration.Get("value")
                        Dim distance As Map = colsteps.Get("distance")
                        traveldistance = traveldistance + distance.Get("value")
                    Next
                    Dim overview_polyline As Map = colroutes.Get("overview_polyline")
                    polyPoints = overview_polyline.Get("points")
                Next
            Next
            j.Release
            drawDirections
            ToastMessageShow("Distance = " & traveldistance & "m, Time = " & travelduration & "s", True)
        Else
            ToastMessageShow("Error: " & root.Get("status"), True)
        End If
    Else
        Log("Error!")
    End If
    j.Release
End Sub

Sub drawDirections
    Dim jo As JavaObject
    Dim Points As List
    Points.Initialize
    jo.InitializeContext
    Points = jo.RunMethod("decodePoly", Array(polyPoints))  
    If Points.Size > 0 Then
        pline = gmap.AddPolyline
        pline.Points = Points
        pline.Color = Colors.Blue
    End If
End Sub

#if JAVA
/**
    * Method to decode polyline points
    * Courtesy : jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java
    * */
import java.util.ArrayList;
import java.util.List;
import com.google.android.gms.maps.model.LatLng;
   
    public List<LatLng> decodePoly(String encoded){

        List<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((((double) lat / 1E5)), (((double) lng / 1E5)));
            poly.add(p);
        }
        return poly;
    }
#End If
 

wes58

Active Member
Licensed User
Longtime User
Post #3
I try your code, but the polyline is approximated, why? (it does not follow the streets)
( in googlemap the path is more precise)

thanks for help
For me, it works fine. It follows the roads, roundabouts very well. By decoding polyline data the code is using all the information it gets from Google to draw the polyline path. Maybe you should post a picture to show what it looks like?
 

Andris

Active Member
Licensed User
Longtime User

Is it true that the API key restrictions options should be left at None? Trying to connect with anything else seems to result in a REQUEST_DENIED response.

API.PNG
 
Last edited:

Almora

Active Member
Licensed User
Longtime User
B4X:
Dim GetAddressJob As HttpJob
    GetAddressJob.Initialize("GetAddress", Me)
    GetAddressJob.Download2("https://maps.googleapis.com/maps/api/geocode/json", _
              Array As String("latlng", lat & "," & lon,"key",API_KEY))

how can I find the address using this code. can you add a sample project? Thank you
 
Last edited:

wes58

Active Member
Licensed User
Longtime User
B4X:
Dim GetAddressJob As HttpJob
    GetAddressJob.Initialize("GetAddress", Me)
    GetAddressJob.Download2("https://maps.googleapis.com/maps/api/geocode/json", _
              Array As String("latlng", lat & "," & lon,"key",API_KEY))

how can I find the address using this code. can you add a sample project? Thank you
You had all information how to do it in posts #1 and #2. But if you still haven't done it, you can try this code:
B4X:
Sub LatLonToPlace(lat As Double, lon As Double) 'As ResumableSub
    Dim API_KEY As String = "your geocoding api key here"
    Dim res As String
    Dim GetAddressJob As HttpJob
    GetAddressJob.Initialize("GetAddress", Me)
    GetAddressJob.Download2("https://maps.googleapis.com/maps/api/geocode/json", Array As String("latlng", lat & "," & lon,"key",API_KEY))
    Wait For (GetAddressJob) JobDone(GetAddressJob As HttpJob)
    If GetAddressJob.Success Then
        Dim jp As JSONParser
        jp.Initialize(GetAddressJob.GetString)
        Dim m As Map = jp.NextObject
        If m.Get("status") = "OK" Then
            Dim results As List = m.Get("results")
            If results.Size > 0 Then
                Dim first As Map = results.Get(0)
                res = first.Get("formatted_address")
                Log(res)
                'res contain address string
            End If
        End If
    End If
    GetAddressJob.Release
End Sub
 

Cebuvi

Active Member
Licensed User
Longtime User
Hello

I need help to get the city name from the result of GetAddressJob.GetString.

*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
*** Service (httputils2service) Create ***
** Service (httputils2service) Start **
{
"plus_code" : {
"compound_code" : "JVQC+X2 Leicester, UK",
"global_code" : "9C4WJVQC+X2"
},
"results" : [
{
"address_components" : [
{
"long_name" : "157",
"short_name" : "157",
"types" : [ "street_number" ]
},
{
"long_name" : "Belgrave Gate",
"short_name" : "Belgrave Gate",
"types" : [ "route" ]
},
{
"long_name" : "Leicester",
"short_name" : "Leicester",
"types" : [ "postal_town" ]
},
{
"long_name" : "Leicester",
"short_name" : "Leicester",
"types" : [ "administrative_area_level_2", "political" ]
},
{
"long_name" : "England",
"short_name" : "England",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "United Kingdom",
"short_name" : "GB",
"types" : [ "country", "political" ]
},
{
"long_name" : "LE1 3HS",
"short_name" : "LE1 3HS",
"types" : [ "postal_code" ]
}
],
"formatted_address" : "157 Belgrave Gate, Leicester LE1 3HS, UK",
"geometry" : {
"location" : {
"lat" : 52.64005479999999,
"lng" : -1.1300998
},
"location_type" : "ROOFTOP",
"viewport" : {
"northeast" : {
"lat" : 52.64140378029149,
"lng" : -1.128750819708498
},
"southwest" : {
"lat" : 52.6387058197085,
"lng" : -1.131448780291502
}
}
},
"place_id" : "ChIJRToYdRxhd0gR6MW-duRlnyM",
"plus_code" : {
"compound_code" : "JVR9+2X Leicester, United Kingdom",
"global_code" : "9C4WJVR9+2X"
},
"types" : [ "street_address" ]
},
{
"address_components" : [
{
"long_name" : "153",
"short_name" : "153",
"types" : [ "street_number" ]
},
{
"long_name" : "Belgrave Gate",
"short_name" : "Belgrave Gate",
"types" : [ "route" ]
},
{
"long_name" : "Leicester",
"short_name" : "Leicester",
"types" : [ "postal_town" ]
},
{
"long_name" : "Leicester",
"short_name" : "Leicester",
"types" : [ "administrative_area_level_2", "political" ]
},
{
"long_name" : "England",
"short_name" : "England",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "United Kingdom",
"short_name" : "GB",
"types" : [ "country", "political" ]
},
{
"long_name" : "LE1",
"short_name" : "LE1",
"types" : [ "postal_code", "postal_code_prefix" ]
}
],
"formatted_address" : "153 Belgrave Gate, Leicester LE1, UK",
"geometry" : {
"location" : {
"lat" : 52.640072,
"lng" : -1.1303318
},
"location_type" : "RANGE_INTERPOLATED",
"viewport" : {
"northeast" : {
"lat" : 52.64142098029151,
"lng" : -1.128982819708498
},
"southwest" : {
"lat" : 52.63872301970851,
"lng" : -1.131680780291502
}
}
},
"place_id" : "EiAxNTMgQmVsZ3JhdmUgR2F0ZSwgTGVpY2VzdGVyLCBVSyIbEhkKFAoSCa2IC3UcYXdIEVg_
Message longer than Log limit (4000). Message was truncated.



Thanks
 

Beja

Expert
Licensed User
Longtime User
Hello

I need help to get the city name from the result of GetAddressJob.GetString.

*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
*** Service (httputils2service) Create ***
** Service (httputils2service) Start **
{
"plus_code" : {
"compound_code" : "JVQC+X2 Leicester, UK",
"global_code" : "9C4WJVQC+X2"
},
"results" : [
{
"address_components" : [
{
"long_name" : "157",
"short_name" : "157",
"types" : [ "street_number" ]
},
{
"long_name" : "Belgrave Gate",
"short_name" : "Belgrave Gate",
"types" : [ "route" ]
},
{
"long_name" : "Leicester",
"short_name" : "Leicester",
"types" : [ "postal_town" ]
},
{
"long_name" : "Leicester",
"short_name" : "Leicester",
"types" : [ "administrative_area_level_2", "political" ]
},
{
"long_name" : "England",
"short_name" : "England",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "United Kingdom",
"short_name" : "GB",
"types" : [ "country", "political" ]
},
{
"long_name" : "LE1 3HS",
"short_name" : "LE1 3HS",
"types" : [ "postal_code" ]
}
],
"formatted_address" : "157 Belgrave Gate, Leicester LE1 3HS, UK",
"geometry" : {
"location" : {
"lat" : 52.64005479999999,
"lng" : -1.1300998
},
"location_type" : "ROOFTOP",
"viewport" : {
"northeast" : {
"lat" : 52.64140378029149,
"lng" : -1.128750819708498
},
"southwest" : {
"lat" : 52.6387058197085,
"lng" : -1.131448780291502
}
}
},
"place_id" : "ChIJRToYdRxhd0gR6MW-duRlnyM",
"plus_code" : {
"compound_code" : "JVR9+2X Leicester, United Kingdom",
"global_code" : "9C4WJVR9+2X"
},
"types" : [ "street_address" ]
},
{
"address_components" : [
{
"long_name" : "153",
"short_name" : "153",
"types" : [ "street_number" ]
},
{
"long_name" : "Belgrave Gate",
"short_name" : "Belgrave Gate",
"types" : [ "route" ]
},
{
"long_name" : "Leicester",
"short_name" : "Leicester",
"types" : [ "postal_town" ]
},
{
"long_name" : "Leicester",
"short_name" : "Leicester",
"types" : [ "administrative_area_level_2", "political" ]
},
{
"long_name" : "England",
"short_name" : "England",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "United Kingdom",
"short_name" : "GB",
"types" : [ "country", "political" ]
},
{
"long_name" : "LE1",
"short_name" : "LE1",
"types" : [ "postal_code", "postal_code_prefix" ]
}
],
"formatted_address" : "153 Belgrave Gate, Leicester LE1, UK",
"geometry" : {
"location" : {
"lat" : 52.640072,
"lng" : -1.1303318
},
"location_type" : "RANGE_INTERPOLATED",
"viewport" : {
"northeast" : {
"lat" : 52.64142098029151,
"lng" : -1.128982819708498
},
"southwest" : {
"lat" : 52.63872301970851,
"lng" : -1.131680780291502
}
}
},
"place_id" : "EiAxNTMgQmVsZ3JhdmUgR2F0ZSwgTGVpY2VzdGVyLCBVSyIbEhkKFAoSCa2IC3UcYXdIEVg_
Message longer than Log limit (4000). Message was truncated.



Thanks


Use string utilities library
 

Johan Hormaza

Well-Known Member
Licensed User
Longtime User
If you use code from post #2 to get directions, you might want to use this code to draw polylines from encoded polyline that you will receive. This gives you an accurate polyline that follows the road.

B4X:
Dim travelduration As Int = 0
Dim traveldistance As Int = 0
Dim start_address As String
Dim end_address As String
Dim pline As Polyline
Dim polyPoints As String

Sub GetDirections(source As String, destination As String) 'As ResumableSub
    Dim j As HttpJob
    Dim API_KEY As String = "insert your api key "        'directions api key
'    Get directions (Location A -> Location B)
    j.Initialize("Directions", Me)
    j.Download2("https://maps.googleapis.com/maps/api/directions/json", Array As String("origin", source,"destination", destination,"key",API_KEY))

    Wait For (j) JobDone(j As HttpJob)
    If j.Success Then
        Dim parser As JSONParser
        parser.Initialize(j.GetString)
        Dim root As Map = parser.NextObject
        If root.Get("status") = "OK" Then
            Dim routes As List = root.Get("routes")
            For Each colroutes As Map In routes
                Dim legs As List = colroutes.Get("legs")
                For Each collegs As Map In legs
                    start_address  = collegs.Get("start_address")
                    end_address = collegs.Get("end_address")
                    Dim steps As List = collegs.Get("steps")
                    For Each colsteps As Map In steps
                        Dim duration As Map = colsteps.Get("duration")
                        travelduration = travelduration + duration.Get("value")
                        Dim distance As Map = colsteps.Get("distance")
                        traveldistance = traveldistance + distance.Get("value")
                    Next
                    Dim overview_polyline As Map = colroutes.Get("overview_polyline")
                    polyPoints = overview_polyline.Get("points")
                Next
            Next
            j.Release
            drawDirections
            ToastMessageShow("Distance = " & traveldistance & "m, Time = " & travelduration & "s", True)
        Else
            ToastMessageShow("Error: " & root.Get("status"), True)
        End If
    Else
        Log("Error!")
    End If
    j.Release
End Sub

Sub drawDirections
    Dim jo As JavaObject
    Dim Points As List
    Points.Initialize
    jo.InitializeContext
    Points = jo.RunMethod("decodePoly", Array(polyPoints)) 
    If Points.Size > 0 Then
        pline = gmap.AddPolyline
        pline.Points = Points
        pline.Color = Colors.Blue
    End If
End Sub

#if JAVA
/**
    * Method to decode polyline points
    * Courtesy : jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java
    * */
import java.util.ArrayList;
import java.util.List;
import com.google.android.gms.maps.model.LatLng;
  
    public List<LatLng> decodePoly(String encoded){

        List<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((((double) lat / 1E5)), (((double) lng / 1E5)));
            poly.add(p);
        }
        return poly;
    }
#End If
It is possible to do it in B4i.
Thank you!
 

DonManfred

Expert
Licensed User
Longtime User
It is possible to do it in B4i.
it is a rest api. If there is a iokhttputils2 available then it should work.

Away from my answer:

What about the statement from Erel?
This code is compatible with B4A, B4i and B4J (versions with support for resumable subs that return values).
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
If there is a iokhttputils2 available then it should work.
Called iHttpUtils2. Same b4xlib as OkhttpUtils2. Different name because of historic reasons.

"(versions with support for resumable subs that return values)."
I've removed this statement as all recent versions support this feature.
 

Johan Hormaza

Well-Known Member
Licensed User
Longtime User
it is a rest api. If there is a iokhttputils2 available then it should work.
I mean the Java code generated in the example of
wes58.
But I already solved it by turning it into B4X
Thanks friend!
B4X:
#if JAVA
/**
    * Method to decode polyline points
    * Courtesy : jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java
    * */
import java.util.ArrayList;
import java.util.List;
import com.google.android.gms.maps.model.LatLng;
  
    public List<LatLng> decodePoly(String encoded){

        List<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((((double) lat / 1E5)), (((double) lng / 1E5)));
            poly.add(p);
        }
        return poly;
    }
#End If
 
Top