B4A Library Geocoder library

warwound

Expert
Licensed User
Geocoder library

The Geocoder library enables you to geocode coordinates and reverse geocode addresses.

The library adds two new Objects to the IDE:

Version: 2.1
  • Address
    Methods:
    • HasLatitude As Boolean
      Returns True if a latitude has been assigned to this Address, False otherwise.
    • HasLongitude As Boolean
      Returns True if a longitude has been assigned to this Address, False otherwise.
    • IsInitialized As Boolean
    Properties:
    • AddressLines As List [read only]
      Returns a List of Strings which are the address lines of the Address.
    • AdminArea As String [read only]
      Returns the administrative area name of the Address.
      For example, "CA", or Null if it is unknown.
    • CountryCode As String [read only]
      Returns the country code of the Address.
      For example "US", or Null if it is unknown.
    • CountryName As String [read only]
      Returns the localized country name of the Address.
      For example "Iceland", or Null if it is unknown.
    • FeatureName As String [read only]
      Returns the feature name of the Address.
      For example, "Golden Gate Bridge", or Null if it is unknown.
    • Latitude As Double [read only]
      Returns the latitude of the Address if known.
    • Locality As String [read only]
      Returns the locality of the Address.
      For example "Mountain View", or Null if it is unknown.
    • Longitude As Double [read only]
      Returns the longitude of the Address if known.
    • Phone As String [read only]
      Returns the phone number of the Address if known, or Null if it is unknown.
    • PostalCode As String [read only]
      Returns the postal code of the Address.
      For example "94110", or Null if it is unknown.
    • Premises As String [read only]
      Returns the premises of the Address, or Null if it is unknown.
    • SubAdminArea As String [read only]
      Returns the sub-administrative area name of the Address.
      For example, "Santa Clara County", or Null if it is unknown.
    • SubLocality As String [read only]
      Returns the sub-locality of the Address, or Null if it is unknown.
    • SubThoroughfare As String [read only]
      Returns the sub-thoroughfare name of the Address, or Null if it is unknown.
    • Thoroughfare As String [read only]
      Returns the thoroughfare name of the Address.
      For example, "1600 Ampitheater Parkway", or Null if it is unknown.
    • Url As String [read only]
      Returns the public URL for the Address, or Null if it is unknown.
  • Geocoder
    Events:
    • GeocodeDone (Addresses() As Address, Tag As Object)
    Methods:
    • GetFromLocation (Latitude As Double, Longitude As Double, MaxResults As Int, Tag As Object)
      Gets an Array of Address objects that describe the area immediately surrounding the given Latitude and Longitude.
      The Array of Address objects is passed back to B4A in the GeocodeDone event along with the Tag Object.
      Tag is not used by this method, it is simply a means by which you can associate an identifying Object with this task.
    • GetFromLocationName (LocationName As String, MaxResults As Int, Tag As Object)
      Gets an Array of Address objects that describe the named location.
      LocationName may be a place name such as "Dalvik, Iceland", an address such as "1600 Amphitheatre Parkway, Mountain View, CA", an airport code such as "SFO", etc...
      The Array of Address objects is passed back to B4A in the GeocodeDone event along with the Tag Object.
      Tag is not used by this method, it is simply a means by which you can associate an identifying Object with this task.
    • GetFromLocationName2 (LocationName As String, MaxResults As Int, LowerLeftLatitude As Double, LowerLeftLongitude As Double, UpperRightLatitude As Double, UpperRightLongitude As Double, Tag As Object)
      Returns an array of Addresses that are known to describe the named location within the geographical bounds.
      LocationName may be a place name such as "Dalvik, Iceland", an address such as "1600 Amphitheatre Parkway, Mountain View, CA", an airport code such as "SFO", etc..
      The Array of Address objects is passed back to B4A in the GeocodeDone event along with the Tag Object.
      Tag is not used by this method, it is simply a means by which you can associate an identifying Object with this task.
    • Initialize (EventName As String)
      Initialize the Geocoder object with the device's system Locale.
    • Initialize2 (EventName As String, Language As String)
      Initialize the Geocoder object with a Locale based on Language.
    • Initialize3 (EventName As String, Language As String, Country As String)
      Initialize the Geocoder object with a Locale based on Language and Country.
    • IsInitialized As Boolean
    • IsPresent As Boolean
      Returns true if the Geocoder methods GetFromLocation and GetFromLocationName etc are implemented.
      Lack of network connectivity may still cause these methods to return null or empty lists.

If any of the three Geocoder methods Get??? fail then the GeocodeDone event will simply be passed an array of zero Address objects.
Any exceptions will be caught and sent to the log.

Library files and demo code attached.

Martin.
 

Attachments

Last edited:

marcick

Well-Known Member
Licensed User
Great job, many thanks !!

I'm trying to understand why this couple of values gives an error:

Latitude=45.589
Longitude=8.99

Marco
 

warwound

Expert
Licensed User
Marco, update your demo code Sub Button1_Click:

B4X:
Sub Button1_Click
   ResultsList.Clear
   
   Dim Latitude, Longitude As Double
   Latitude=LatitudeEdit.Text
   Longitude=LongitudeEdit.Text
   
   '   MaxResults parameter hardcoded to 5 for the demo
   Dim MaxResults As Int
   MaxResults=5
   
   Dim Results() As Address
   Results=Geocoder1.GetFromLocation(Latitude, Longitude, MaxResults)
   
   If Results.Length>0 Then
      Dim Address1 As Address
      Dim i As Int
      For i=0 To Results.Length-1
         Address1=Results(i)
         Log(Address1.AddressLines.Size)
         If Address1.AddressLines.Size>0 Then
            ResultsList.AddTwoLines(Address1.AddressLines.Get(0), Address1.AddressLines.Get(0))
         Else
            Log("Debug")
         End If
      Next
   Else
      Msgbox("GetFromLocation", "No Address matched the Latitude and Longitude")
   End If
End Sub
On my ZTE Blade, your query (45.589, 8.99) returns 5 results.
The last result however has zero AddressLines so causes an IndexOutOfBounds exception here: Address1.AddressLines.Get(0).

All users of this library should note that a successfuly geocode or reverse geocode does not guarantee that all properties of the Address result object will contain values.

Test for Null before trying to use an Address object property.

Martin.
 

dealsmonkey

Active Member
Licensed User
Thankyou for this, just what I needed !

I had been geocoding using the maps api, this has simplified things somewhat :sign0060:
 

corwin42

Expert
Licensed User
The library works well. (I call the GetFrom... methods in their own thread so they won't lock UI)

Anybody got more than one result from GetFromLocationName() ?

I only receive one result. Even if I search for "Santiago" which exists several times in the world I get "Santiago, Chile" as the only result. If I search for "Santiago Mexico" I get another result. It's a bit strange but perhaps it is the implementation on my phone?


By the way: It would be safe to add isPresent method to the library. You should only mention that this will throw a MethodNotFound exception for Froyo or older which can be trapped in B4A.
 

IamBot

Member
Licensed User
Is it possible to get the country and city name in English regardless what language chosen under Settings -> Language and Input?
 

warwound

Expert
Licensed User
Is it possible to get the country and city name in English regardless what language chosen under Settings -> Language and Input?
Hi.

Can you test the attached library update?
I've added a couple of new Geocoder Initialize methods that should enable you to chose the Locale that will be used:

  • Initialize2 (Language As String)
    Initialize the Geocoder object with a Locale based on Language.
  • Initialize3 (Language As String, Country As String)
    Initialize the Geocoder object with a Locale based on Language and Country.

Post with your results and if it all works as expected i'll get the update uploaded 'properly'.

Martin.
 
Last edited:

IamBot

Member
Licensed User
Hi.

Can you test the attached library update?
I've added a couple of new Geocoder Initialize methods that should enable you to chose the Locale that will be used:

  • Initialize2 (Language As String)
    Initialize the Geocoder object with a Locale based on Language.
  • Initialize3 (Language As String, Country As String)
    Initialize the Geocoder object with a Locale based on Language and Country.

Post with your results and if it all works as expected i'll get the update uploaded 'properly'.

Martin.
Amazing job, thank you :)

I replaced:

B4X:
Geocoder1.Initialize
with:

B4X:
Geocoder1.Initialize2("en")
and data was displayed in English (I had different language on my phone while trying this). I tried also initialize Geocoder1 using few other languages and it worked as well.

Thx!
 

warwound

Expert
Licensed User
Geocoder library updated to version 1.10

This update adds two new Initialize methods to the Geocoder object:

  • Initialize2 (Language As String)
    Initialize the Geocoder object with a Locale based on Language.
  • Initialize3 (Language As String, Country As String)
    Initialize the Geocoder object with a Locale based on Language and Country.

These new methods enable you to specify a Locale that will be used when geocoding.
(You can specify the language that you want text results to be returned in).

Version 1.10 is attached to the first post in this thread.

Martin.
 

buladin

New Member
Licensed User
I need a little help. when I already have latitude and longitude (from GPS), how can i print only the name of the country in MsgBox or Label?
 

warwound

Expert
Licensed User
Hi.

Look at the attached project:

B4X:
'Activity module
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.
   
   '   the Geocoder object can be declared as Process_Global - it is NOT an Activity object.
   Dim Geocoder1 As Geocoder
End Sub

Sub Globals
   'These global variables will be redeclared each time the activity is created.
   'These variables can only be accessed from this module.

   Dim LatitudeEdit As EditText
   Dim LongitudeEdit As EditText
   Dim ResultsList As ListView
   Dim AddressEdit As EditText
End Sub

Sub Activity_Create(FirstTime As Boolean)
   If FirstTime Then
      Geocoder1.Initialize
   End If
   
   Activity.LoadLayout("GetFromLocation")
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub Button1_Click
   ResultsList.Clear
   
   Dim Latitude, Longitude As Double
   Latitude=LatitudeEdit.Text
   Longitude=LongitudeEdit.Text
   
   '   MaxResults parameter hardcoded to 5 for the demo
   Dim MaxResults As Int
   MaxResults=5
   
   Dim Results() As Address
   Results=Geocoder1.GetFromLocation(Latitude, Longitude, MaxResults)
   
   If Results.Length>0 Then
      Dim Address1 As Address
      Dim i As Int
      For i=0 To Results.Length-1
         Address1=Results(i)
         '   check the reference to see all possible properties of the Address object
         '   http://www.basic4ppc.com/forum/additional-libraries-classes-official-updates/17115-geocoder-library.html#post97857
         
         '   the CountryName property is what you're asking for:
         '   Returns the localized country name of the Address.
         '   For example "Iceland", OR Null if it Is unknown.
         
         ResultsList.AddSingleLine(Address1.CountryName)
         
         '   ResultsList.AddTwoLines(Address1.PostalCode, Address1.CountryName)
      Next
   Else
      Msgbox("GetFromLocation", "No Address matched the Latitude and Longitude")
   End If
End Sub
It uses Geocoder1.GetFromLocation(Latitude, Longitude, MaxResults) to make the query, Results is an Array of Address objects, or an empty Array if the query couldn't get a location name from the coordinates.

Each Address object has various properties, see the first post in this thread for complete reference.
The Address object's CountryName property is what you want.

Martin.
 

Attachments

bluedude

Well-Known Member
Licensed User
Backend service with rate limit

Hi,

I have a question about this library. Can you confirm it does not use some kind of external services with a rate limit? Most GEOcoder services have this problem.

Is it a native Android option?

Cheers,
 

warwound

Expert
Licensed User
Well this B4A Geocoder library wraps the native Android Geocoder service.
And the Android Geocoder uses a web service, no doubt the same web service that the web based Google APIs use - and these web based APIs all have limits.

BUT i've searched (and found others ask the same question) and found nowhere is there any documented usage limit with the Android API.
That's not to say extreme usage wouldn't get the device a temporary blockage of further queries.

Whether the lack of a documented usage limit means there is no limit, or whether the lack of documentation implies that Google expect developers not to abuse the service i don't know.

You have an app that uses the Geocoder a lot do you?

Martin.
 

bluedude

Well-Known Member
Licensed User
Not using it a lot yet but working on a new local weather app. which would preferable use geocoding (so I can cache city and country).

Caching lat, lng is hard because then you need to do radius calculations because 5 meters would mean creating another filename.

Anyway, will see.

Thanks!
 
Top