B4A Library Geocoder library

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

  • Geocoder_v2_10.zip
    21.6 KB · Views: 2,003
Last edited:

bluedude

Well-Known Member
Licensed User
Longtime User
Hi,

I have been testing this now for a while on the road and it seems getting the results freezes the app. for a while. I'm using it in a service that stores latest country and city in a user preferences file.

When WIFI is enabled I never have a problem but on a mobile connection it happens a lot with even sometimes a force close.

Any suggestions?
 

warwound

Expert
Licensed User
Longtime User
Hi,

I have been testing this now for a while on the road and it seems getting the results freezes the app. for a while. I'm using it in a service that stores latest country and city in a user preferences file.

When WIFI is enabled I never have a problem but on a mobile connection it happens a lot with even sometimes a force close.

Any suggestions?

Can you test the attached update?

The two Geocoder Get??? methods no longer return a value, instead they run in their own Thread and raise an event:

GeocodeDone (Address1() As Address, Tag As Object)

Tag is not used by these methods, it is simply a means by which you can associate an identifying Object with this task.
So if you are geocoding more than one task you can pass a unique value as the Tag Object and in your GeocodeDone Sub identify which task has completed.

All three Initialize methods now require an EventName parameter.

The attachment includes the original demo code updated to work with the updated library.
If you can confirm the library update works as expected i'll update the first post in this thread.

Martin.
 
Last edited:

marcick

Well-Known Member
Licensed User
Longtime User
Hi Martin,
for the same bahaviour bluedude describe, I had to implement an option to disable the geocoding requests when the mobile connection is not very stable.
The new demo works, but It is not clear to me how to use the tag object.
I would like to call the getfromlocation with a INT number.
Marco
 

warwound

Expert
Licensed User
Longtime User
Here's a simple example showing use of an Int as the Tag value:

B4X:
Sub Process_Globals
   Dim Geocoder1 As Geocoder
End Sub

Sub Globals

End Sub

Sub Activity_Create(FirstTime As Boolean)
   If FirstTime Then
      Geocoder1.Initialize("Geocoder1")
   End If
   
   Geocoder1.GetFromLocation(52.843, 0.85, 5, 1)
   Geocoder1.GetFromLocation(51.52, -3.22, 5, 2)
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub Geocoder1_GeocodeDone(Results() As Address, Tag As Object)
   Dim JobId As Int=Tag
   Select JobId
      Case 1
         Log("Task 1 done")
         If Results.Length>0 Then
            Dim Address1 As Address
            Dim i As Int
            For i=0 To Results.Length-1
               Address1=Results(i)
               If Address1.AddressLines.Size>0 Then
                  Log(JobId&" : "&Address1.AddressLines.Get(0))
               Else
                  Log(JobId&" : "&"Address1.AddressLines.Size is 0")
               End If
            Next
         Else
            Msgbox("GetFromLocation", JobId&" : "&"No Address matched the Latitude and Longitude")
         End If
      Case 2
         Log("Task 2 done")
         If Results.Length>0 Then
            Dim Address1 As Address
            Dim i As Int
            For i=0 To Results.Length-1
               Address1=Results(i)
               If Address1.AddressLines.Size>0 Then
                  Log(JobId&" : "&Address1.AddressLines.Get(0))
               Else
                  Log(JobId&" : "&"Address1.AddressLines.Size is 0")
               End If
            Next
         Else
            Msgbox("GetFromLocation", JobId&" : "&"No Address matched the Latitude and Longitude")
         End If
   End Select
End Sub

The example takes the same action for both geocoding tasks - logging them.
But use of a Select enables you to take whatever action you need for each task.

Martin.
 

bluedude

Well-Known Member
Licensed User
Longtime User
The latest version with the threading and event solve all my problems. The app., doesn't freeze anymore, thumbs up!
 

warwound

Expert
Licensed User
Longtime User
Geocoder updated to version 2.00

This update significantly changes how the library works.
Updating to version 2.00 from previous versions will require that you modify your code.


In previous versions the methods GetFromLocation and GetFromLocationName were synchronous, you called these methods and they performed a task and returned a result.
As the tasks they perform are network based queries these methods should ideally run in their own Thread and raise an Event once they have completed.
The version 2.00 update implements the Thread and Event technique, preventing these two methods from blocking the UI Thread and causing Force Close problems with your application.

Verison 2.00, a demo project and HTML reference page are attached to the first post in this thread.

Martin.
 

marcick

Well-Known Member
Licensed User
Longtime User
Hi Martin,
I'm experiencing this kind of behaviour and I think it is similar (or the same) also with the v1.00 library.

  1. Internet connection present, both Wi-Fi and mobile
  2. Call GetFromLocation several time, event always raised, no problem
  3. Put the device offline (disable wi-fi and mobile connection)
  4. Call GetFromLocation several time. After 5 seconds the event is always raised, with no result. Ok.
  5. Re-enable Wi-Fi and mobile connection.
  6. Call GetFromLocation, but events are no longer raised. Also closing and starting again the app does not solve. A reboot of the device is required.

I have checked a second time and instead it worked, so after re-enabling internet connection all was ok. But sometimes happens thet the geocoder enter in a situation that is not able to recover, unless you reboot the device.
Marco
 

warwound

Expert
Licensed User
Longtime User
This is a known problem with the Geocoder service.
When i was creating this library i read many reports where people were confused as to why the Geocoder was failing.
The only solution was a reboot of the device.

Recently another forum member contacted me with the same problem and i suggested to simply reboot the device - the Geocoder worked again.

Maybe the Geocoder service is searched for when you boot your device only.
So if you disable all network access and try but fail to use the Geocoder the device presumably flags the Geocoder service as not available.

If you later re-enable network access the device seems to presume the Geocoder service is still not available rather than actually trying to use the service and finding out that it is now available again.

Maybe instead of rebooting the device, if you left the device with network enabled for a 'certain period of time', it would at some point automatically check the avilability of the Geocoder service and flag it as available.
But i have no idea if that would work or whether a reboot is the only way to re-enable the Geocoder service after a network interuption.

Have a read, you'll find it's a common issue: https://www.google.co.uk/search?q=android+restart+geocoder&ie=UTF-8&oe=UTF-8.

I've searched and found no way to force the Geocoder service to reset itself and be available - a device reboot seems the only fix.

If it's a problem with your app then the only solution would be to use a different geocoder service - either the web-based Google Geocoder (not strictly allowed in their terms and conditions i think), or to find a third party geoocoder service.

Martin.
 

bluedude

Well-Known Member
Licensed User
Longtime User
Marcick,

I think it takes a while before I can do geocoding requests after switching on network connection. The "old" library blocked my whole app. and even generated a force close.

The problem with most third party geocoding services is the rate limit, when your app. is popular it will not work anymore.

Need to do a little more testing to see what works and what doesn't. Overall I haven't experienced not getting results. I run it in a service and always store the last results in a preferences file which i access from an activity.

Cheers,
 

marcick

Well-Known Member
Licensed User
Longtime User
Understand.
I experience this truble quite often. I could say never if the device uses wi-fi, but quite often if uses mobile connection. So it should not depend on rate limits I think. Anyway it seems there are no other chances. The only solid solution seems to be google web geocoding, but I don't use the address info on a google map, so i would brake licence right.
Marco
 

warwound

Expert
Licensed User
Longtime User
There are other geocoder services based on open source/open street map data and with these other services there are (i think but you'd be advised to check!) no usage terms and conditions.

Sounds good but these other services vary greatly in quality of results, speed of query processing and general availability of the service.
That is thier data could contain errors and their servers could be slow and overloaded.

Take a look at the OSMBonusPack, it's a library i plan to wrap for B4A as an add-on for the OSMDroid library.
It has geocoding and reverse geocoding functionality, look at the Wiki overview page Overview - osmbonuspack - Why this "OSMBonusPack", and what does it give. - A third-party library of (very) useful additional objects for osmdroid - Google Project Hosting, scroll down to Geocoding and Reverse Geocoding.
Note the WARNING!

I've completed the B4A wrapper library for the directions service but didn't plan to wrap the geocoder stuff as i assumed the Google Android Geocoder would be the better choice.

If either of you would like me to look at creating a wrapper around the OSMBonusPack geocoder and reverse geocoder classes i can do that.

Take a look at the source code for the GeocoderNominatim class.

This is the class that uses either the OpenStreetMap Nominatim or the MapQuest web services.
The getFromLocation and getFromLocationName methods are the methods of interest.
The OSMBonusPack author has written these 3rd party geocoder classes to mimic the Android Geocoder methods so you'd not have to change much code to switch to 3rd party geocoding.

Probably the best option is to query the Google Android Geocoder, if that fails then have these 3rd party services available as a fallback.

Shall i create the 3rd party Geocoder library from the OSMBonusPack class?

Is the OSMBonusPack directions service of use in your apps?
(I've already wrapped the directions service into a B4A library).

Martin.

PS Are either of you using OSMDroid?
 

bluedude

Well-Known Member
Licensed User
Longtime User
For me no need for external GEO services, all works like expected with event stuff etc. Did several tests and after switching ON/OFF WIFI or GPRS it starts geocoding without a problem. Tried several scenarios and no problem at all.

I can do fallbacks myself with external services by using a REST interface, no libraries needed for that.

Cheers and thanks!
 

marcick

Well-Known Member
Licensed User
Longtime User
Let me do some more test to evaluate better how much often it fails, respect with 1.0 library.
Marco
 

walterf25

Expert
Licensed User
Longtime User
Geocode Library not working for me

Hi all, i really hope someone can point me in the right direction, i plan to use this library on one of my already published apps, the problem is i downloaded the library files along with the example attached to it, the example compiles just fine and it runs fine also, but when i enter either coordinates, or an address i do not get anything back, I've tried different latitude and longitude values and also different addresses, and still get the same problem.
geocode scrnshot1.jpg
Does anyone know if anything changed?

Thanks,
Walter
 

walterf25

Expert
Licensed User
Longtime User
Geocode Library not working for me

Hey Corwin, i have a Motorola Photon 4G and i'm pretty sure it works with geocoding, i remember it working before, which is why i was asking if there's anything that changed in the library, if this doesn't work i'm going to have to use a third party api to be able to do what i need to for my app.

Cheers,
Walter
 

warwound

Expert
Licensed User
Longtime User
Hi all, i really hope someone can point me in the right direction, i plan to use this library on one of my already published apps, the problem is i downloaded the library files along with the example attached to it, the example compiles just fine and it runs fine also, but when i enter either coordinates, or an address i do not get anything back, I've tried different latitude and longitude values and also different addresses, and still get the same problem.
View attachment 15060
Does anyone know if anything changed?

Thanks,
Walter

Have you read this post:http://www.b4x.com/forum/additional...ates/17115-geocoder-library-3.html#post138643?

Try rebooting the device and trying again.

Martin.
 

ivanomonti

Expert
Licensed User
Longtime User
Resul[] nil empty !!!

MappAddress.GetFromLocationName("via del commercio 2, Solaro, MI",1,Null)

I need to find the latitude and longitude starting at address, THANK
 
Top