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:

Johan Hormaza

Well-Known Member
Licensed 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
 

aeric

Expert
Licensed User
Do I need to convert the Java code to OBJC in order to use in B4i?
 

aeric

Expert
Licensed User
I found a code shared by @marcick but still not able to use in B4i
B4X:
Sub MapsDecodePolyline(encoded As String)
    Dim index As Int
    Dim lat As Int
    Dim lng As Int
    Dim fLat As Float
    Dim fLng As Float
    Dim b As Int
    Dim shift As Int
    Dim result As Int
    Dim dlat As Int
    Dim dlng As Int
    Dim poly As List
    poly.Initialize
    index = 0 : lat = 0 : lng = 0
    Do While index < encoded.Length
        shift = 0 : result = 0
        Do While True
            b = Asc(encoded.SubString2(index, index + 1)) - 63 : index = index + 1
            result = Bit.Or(result, Bit.ShiftLeft(Bit.And(b, 0x1f), shift))
            shift = shift + 5
            If b < 0x20 Then Exit
        Loop     
        If Bit.And(result, 1) = 1 Then
            dlat = Bit.Not(Bit.ShiftRight(result, 1))
        Else
            dlat = Bit.ShiftRight(result, 1)
        End If
        lat = lat + dlat
        shift = 0 : result = 0
        Do While True
            b = Asc(encoded.SubString2(index, index + 1)) - 63 : index = index + 1
            result = Bit.Or(result, Bit.ShiftLeft(Bit.And(b, 0x1f), shift))
            shift = shift + 5
            If b < 0x20 Then Exit
        Loop     
        If Bit.And(result, 1) = 1 Then
            dlng = Bit.Not(Bit.ShiftRight(result, 1))
        Else
            dlng = Bit.ShiftRight(result, 1)
        End If
        lng = lng + dlng
        fLat = lat
        fLng = lng   
        Dim ll As LatLng
        ll.Initialize(fLat/100000, fLng/100000)
        Dim mpiCurrent As MapsPointItem
        mpiCurrent.Initialize
        mpiCurrent.iPassed = 0
        mpiCurrent.dLatitude = fLat / 100000
        mpiCurrent.dLongitude = fLng / 100000
        poly.add(mpiCurrent)
        NavigationPoints.Add(ll)
    Loop   
End Sub

Navigation : Find a Route and navigate
 

aeric

Expert
Licensed User
I modified the code and it is working for me now.
B4X:
Sub MapsDecodePolyline(encoded As String) As List
    Dim index As Int
    Dim lat As Int
    Dim lng As Int
    'Dim fLat As Float
    'Dim fLng As Float
    Dim b As Int
    Dim shift As Int
    Dim result As Int
    Dim dlat As Int
    Dim dlng As Int
    Dim poly As List
    poly.Initialize
    index = 0 : lat = 0 : lng = 0
    Do While index < encoded.Length
        shift = 0 : result = 0
        Do While True
            b = Asc(encoded.SubString2(index, index + 1)) - 63 : index = index + 1
            result = Bit.Or(result, Bit.ShiftLeft(Bit.And(b, 0x1f), shift))
            shift = shift + 5
            If b < 0x20 Then Exit
        Loop
        If Bit.And(result, 1) = 1 Then
            dlat = Bit.Not(Bit.ShiftRight(result, 1))
        Else
            dlat = Bit.ShiftRight(result, 1)
        End If
        lat = lat + dlat
        shift = 0 : result = 0
        Do While True
            b = Asc(encoded.SubString2(index, index + 1)) - 63 : index = index + 1
            result = Bit.Or(result, Bit.ShiftLeft(Bit.And(b, 0x1f), shift))
            shift = shift + 5
            If b < 0x20 Then Exit
        Loop
        If Bit.And(result, 1) = 1 Then
            dlng = Bit.Not(Bit.ShiftRight(result, 1))
        Else
            dlng = Bit.ShiftRight(result, 1)
        End If
        lng = lng + dlng
        'fLat = lat
        'fLng = lng
        Dim ll As LatLng
        'll.Initialize(fLat/100000, fLng/100000)
        ll.Initialize(lat / 100000, lng / 100000)
        poly.Add(ll)
        'Dim mpiCurrent As MapsPointItem
        'mpiCurrent.Initialize
        'mpiCurrent.iPassed = 0
        'mpiCurrent.dLatitude = fLat / 100000
        'mpiCurrent.dLongitude = fLng / 100000
        'poly.add(mpiCurrent)
        'NavigationPoints.Add(ll)
    Loop
    Return poly
End Sub
 

Johan Hormaza

Well-Known Member
Licensed User
I did it this way.
B4X:
Sub MapsDecodePolyline(encoded As String, poly As List)
    Log("MapsDecodePolyline")
    Dim index As Int
    Dim lat As Int
    Dim lng As Int
    Dim fLat As Float
    Dim fLng As Float
    Dim b As Int
    Dim shift As Int
    Dim result As Int
    Dim dlat As Int
    Dim dlng As Int
    index = 0 : lat = 0 : lng = 0
    Do While index < encoded.Length
        shift = 0 : result = 0
        Do While True
            b = Asc(encoded.SubString2(index, index + 1)) - 63 : index = index + 1
            result = Bit.Or(result, Bit.ShiftLeft(Bit.And(b, 0x1f), shift))
            shift = shift + 5
            If b < 0x20 Then Exit
        Loop
        
        If Bit.And(result, 1) = 1 Then
            dlat = Bit.Not(Bit.ShiftRight(result, 1))
        Else
            dlat = Bit.ShiftRight(result, 1)
        End If
        lat = lat + dlat
        shift = 0 : result = 0
        Do While True
            b = Asc(encoded.SubString2(index, index + 1)) - 63 : index = index + 1
            result = Bit.Or(result, Bit.ShiftLeft(Bit.And(b, 0x1f), shift))
            shift = shift + 5
            If b < 0x20 Then Exit
        Loop
        If Bit.And(result, 1) = 1 Then
            dlng = Bit.Not(Bit.ShiftRight(result, 1))
        Else
            dlng = Bit.ShiftRight(result, 1)
        End If
        lng = lng + dlng
        fLat = lat
        fLng = lng
        Dim mpiCurrent As MapsPointItem
        mpiCurrent.Initialize
        mpiCurrent.iPassed = 0
        mpiCurrent.dLatitude = fLat / 100000
        mpiCurrent.dLongitude = fLng / 100000
        poly.add(mpiCurrent)
    Loop
End Sub
 

aeric

Expert
Licensed User
I did it this way.
B4X:
Sub MapsDecodePolyline(encoded As String, poly As List)
    Log("MapsDecodePolyline")
    Dim index As Int
    Dim lat As Int
    Dim lng As Int
    Dim fLat As Float
    Dim fLng As Float
    Dim b As Int
    Dim shift As Int
    Dim result As Int
    Dim dlat As Int
    Dim dlng As Int
    index = 0 : lat = 0 : lng = 0
    Do While index < encoded.Length
        shift = 0 : result = 0
        Do While True
            b = Asc(encoded.SubString2(index, index + 1)) - 63 : index = index + 1
            result = Bit.Or(result, Bit.ShiftLeft(Bit.And(b, 0x1f), shift))
            shift = shift + 5
            If b < 0x20 Then Exit
        Loop
       
        If Bit.And(result, 1) = 1 Then
            dlat = Bit.Not(Bit.ShiftRight(result, 1))
        Else
            dlat = Bit.ShiftRight(result, 1)
        End If
        lat = lat + dlat
        shift = 0 : result = 0
        Do While True
            b = Asc(encoded.SubString2(index, index + 1)) - 63 : index = index + 1
            result = Bit.Or(result, Bit.ShiftLeft(Bit.And(b, 0x1f), shift))
            shift = shift + 5
            If b < 0x20 Then Exit
        Loop
        If Bit.And(result, 1) = 1 Then
            dlng = Bit.Not(Bit.ShiftRight(result, 1))
        Else
            dlng = Bit.ShiftRight(result, 1)
        End If
        lng = lng + dlng
        fLat = lat
        fLng = lng
        Dim mpiCurrent As MapsPointItem
        mpiCurrent.Initialize
        mpiCurrent.iPassed = 0
        mpiCurrent.dLatitude = fLat / 100000
        mpiCurrent.dLongitude = fLng / 100000
        poly.add(mpiCurrent)
    Loop
End Sub
It looks similar. I removed mpiCurrent because I think I only need the value of poly as List.
 

aeric

Expert
Licensed User
So I modified the code in post #3 as below:
B4X:
Sub drawDirections
    Dim Points As List
    Points.Initialize
    'Dim jo As JavaObject
    'jo.InitializeContext  
    'Points = jo.RunMethod("decodePoly", Array(polyPoints))
    Points = MapsDecodePolyline(polyPoints)  
    If Points.Size > 0 Then
        pline = gmap.AddPolyline
        pline.Points = Points
        pline.Color = Colors.ARGB(240, 186, 85, 211) ' Purple // Colors.Blue
        pline.Width = 6dip
    End If
End Sub
 

ibs06t

Member
Licensed User
Hi

im using this code but error comes

REQUEST_DENIED

what is error how to solve this

regards
kumar
 

aeric

Expert
Licensed User
Hi

im using this code but error comes

REQUEST_DENIED

what is error how to solve this

regards
kumar
Did you check post #7 ?
 

ciginfo

Well-Known Member
Licensed User
Hello,
I can't get "Sub LatLonToPlace (lat As Double, lon As Double)" to run
t seems that this part of the code is not taken into account
B4X:
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
Which libraries are needed or have I forgotten something?
Thank you
 

ciginfo

Well-Known Member
Licensed User
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
Hello,
What means "Complete (ll() As Double", what is (ll()) ?
When I run the program I obtain in the Log: Log("Failed to geocode.")
Thank you
 

ciginfo

Well-Known Member
Licensed User
It is the Latitude and Longitude or the coordinate of a Place.
OK, thank you but why it doesn't return Longitude & Latitude, it returns only 9999 & 9999
I thought it returned" Israel Yodfat"Long & Lat. Where is the problem?
Thank you
 

aeric

Expert
Licensed User
OK, thank you but why it doesn't return Longitude & Latitude, it returns only 9999 & 9999
I thought it returned" Israel Yodfat"Long & Lat. Where is the problem?
Thank you
I think you better start a new thread. You may have make a mistake somewhere in your code.
 
Top