How do I code/access the Google Maps Android API v2 build-in LocationChange event?

BvdB

Member
Licensed User
Longtime User
Hi there all clever V4A folks :)

I am using the B4A GoogleMaps and GoogleMapsExtras libraries, and I would like to use the build-in location provider that provides the location updates for the my-location layer of the Google Maps for Android v2 API, as documented here. But it seems as though these B4A libraries does not make provision for the build-in Google maps Location Change event. I only managed to find the _CameraChange event is present but not documented here: Basic4android - GoogleMaps

I am wondering whether the _LocationChange event is perhaps also implemented but not documented?
If not already implemented, I think it will really make sense to expand the B4A Google Maps library to include the _LocationChange event.

I know I can use the GPS library or the esLocation2, or b4aLocationManager libraries for the same purpose, but it can be valuable to newbies if the native event available in the Google Maps for Android API is.

Your feedback will be much appreciated.
 

warwound

Expert
Licensed User
Longtime User
The way i am reading that page is that the Google Map has a built in method to obtain the device location when it requires the device location.

The developer can replace that built in method, supplying the Google Map with a custom method to obtain the device location.

But i don't think that means that the built in method makes it's location available to the developer - that built in method makes it's location available only to the Google Map.

Martin.
 
Upvote 0

BvdB

Member
Licensed User
Longtime User
Hi Martin,
Thanks for your prompt response, it is much appreciated.

If you read the Android "OnLocationChangedListner" it is surely an event and not the method from which you can get the MyLocation.Target Lat&Long.

I tested it by removing the GPS code and switching on the MyLocation Layer and reposition button, and the Google Map places a small blue circle at the device location and when you start moving it changes to an blue arrow that tracks on the Google map. It uses the GSM and/or GPS to provide the location. GSM has a large circle around it, and as soon as the GPS radio receives reception and accurate location information, the large circle change to a smaller diameter semi transparent circle.

I just want to use the build in method to determine location changes and update the CameraPosition, without additional GPS coding (which means additional code to test and maintain ;) )

Or am I misreading the Google Maps Android V2 documentation? Which is quite possible, since I am new to this platform and B4A.
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
I think what i said in my previous post is correct.

LocationSource
Defines an interface for providing location data, typically to a GoogleMap object.

So you've switched the MyLocation layer and the Google Map built in LocationSource is detecting the device location and passing the location to the Google Map.

If developing using java you could create a custom LocationSource and that custom LocationSource would detect the device location.
The custom LocationSource would implement an OnLocationChangedListener method, this method would be called by the Google Map when it requires a location and your custom LocationSource would provide the location to the Google Map in that method.

Actually i just found https://developers.google.com/maps/documentation/android/location.
Read the My Location layer paragraph:

...
Should you wish to access location data programmatically, use the Location API.

So that confirms what i guessed.
  • You can't get the location that the My Location layer provides to the Google Map.
  • You can (in java) provide your own location to the My Location layer and obviously your code can access the location that it provides to My Location itself.

I'm currently developing a b4a LocationAPI library.
Hopefully i shall have enough time this weekend to complete a working version that can be uploaded for testing.

Otherwise you will have to use one of the existing b4a 'get my location' libraries as you mentioned in your first post.

Martin.
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
Hmmm...

Take a look here: https://developers.google.com/maps/...ms.maps.GoogleMap.OnMyLocationChangeListener).

The GoogleMap setOnMyLocationChangeListener (GoogleMap.OnMyLocationChangeListener listener) was introduced in the February 2013 official java update.

Then with the May 2013 update this new method and listener became deprecated - Google instead intending developers to use the new Location API instead.

So there is currently a deprecated method and listener that could be used to get the location as reported to the My Location layer.
I'll try to add support for it to Google Maps Extras - either later today or over the weekend.

Martin.
 
Upvote 0

BvdB

Member
Licensed User
Longtime User
Thank you for the explanation Martin, I understand what you are saying.

Does it make sense to spend time to implement a deprecated event?
Which of the esLocation2, or b4aLocationManager libraries are best to use at this stage?

Will the new Location Library that you are developing replace both of these or is it a different library that you develop?

Thanks again for your assistance, it is much appreciated.
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
Can you give the updated GoogleMapsExtras a test?
A new method:

SetOnMyLocationChangeListener (GoogleMap1 As GoogleMap, OnMyLocationChangeListener1 As OnMyLocationChangeListener)
Sets a callback that's invoked when the my location dot changes location.
To unset the callback use Null.


and a new listener object:

OnMyLocationChangeListener
Events:
  • MyLocationChange (Location1 As Location)
Methods:
  • Initialize (EventName As String)
  • IsInitialized As Boolean

Basic syntax:

B4X:
Dim OnMyLocationChangeListener1 As OnMyLocationChangeListener
OnMyLocationChangeListener1.Initialize("OnMyLocationChangeListener1")
GoogleMapsExtras1.SetOnMyLocationChangeListener(GoogleMap1, OnMyLocationChangeListener1)

' and a Sub

Sub OnMyLocationChangeListener1_MyLocationChange(Location1 As Location)
    ' handle the location change here
End Sub

Until the deprecated method and listener are removed from the API they are at least there to use if you want.

The new Location API from Google is an attempt to create better ways for the developer to get the device location, the Location API also introduces new Geofence and Activity Detection functionality.
So the existing b4a libraries that enable getting the device location will continue to function.
And the new LocationAPI library will co-exist with Google's promise of easier, more battery friendly ways to get the device location.
Whether the new LocationAPI offers any real world benefits over the older methods only time will tell.

So if you can test the update and post with your results - i shall then properly upload the update in the correct thread.

Martin.
 
Last edited:
Upvote 0

BvdB

Member
Licensed User
Longtime User
Thank you for the speedy response and update to the library, Martin.

I will give it a run over the weekend and provide feedback - or questions ;)

Chat to you soon.
 
Upvote 0

BvdB

Member
Licensed User
Longtime User
Hi Martin.

I have the new method a run yesterday, and it worked great. I didn't pick-up any issues.

The nice thing of using this event in conjunction with MyLocation layer is that the accuracy is indicated on the google map by means of the semi-transparent circle of MyLocation marker.

Thank you very much for adding event to the extras library.

I have one more question though which I hope you have experimented with.
Is there an enent that fires when the MyLocationButton is pressed and/or an event that fires when the user manually moves the map?
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
There's (currently) no event that is raised when the MyLocation button is clicked.
And it looks as though there is no unimplemented callback in the java API that could be used to detect such a click.

But there is the MapFragment event:

CameraChange (Position As CameraPosition)

I'd guess that will be raised if the user drags the map or changes the zoom level.

Martin.
 
Upvote 0

Dario126

Member
Licensed User
Longtime User
Basic syntax:

B4X:
Dim OnMyLocationChangeListener1 As OnMyLocationChangeListener
OnMyLocationChangeListener1.Initialize("OnMyLocationChangeListener1")
GoogleMapsExtras1.SetOnMyLocationChangeListener(GoogleMap1, OnMyLocationChangeListener1)

' and a Sub

Sub OnMyLocationChangeListener1_MyLocationChange(Location1 As Location)
    ' handle the location change here
End Sub

Until the deprecated method and listener are removed from the API they are at least there to use if you want.

This last sentence means this listeners are not available any more ??

By using this
B4X:
            OnMyLocationChangeListener1.Initialize("OnMyLocationChangeListener1")   
            gXtra.SetOnMyLocationChangeListener(gMap, OnMyLocationChangeListener1)

i get this error
java.lang.RuntimeException: Object should first be initialized (OnMyLocationChangeListener).
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
@Dario126

The official documentation still lists the OnMyLocationChangeListener.
See here: https://developers.google.com/maps/...gms/maps/GoogleMap.OnMyLocationChangeListener.

It is deprecated but still available for use - that is it has not yet been removed from the Google Maps API.
(Unless that documentation page is not up to date).

My Windows computer is not available right now - it's being backed up.
I'll try the demo code for the OnMyLocationChangeListener later and post again with my results.

Martin.
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
Ok i've tested the OnMyLocationListener with the latest version of the Google Play Services library and it is still available.

@Dario126
Look in the logs just before the line "Object should first be initialized (OnMyLocationChangeListener)".
Do you see another line that reads: OnMyLocationChangeListener not initialized, no event handling Sub found?

When you call the OnMyLocationChangeListener Initialize event it checks to see if a Sub exists for the MyLocationChange, if no such Sub exists then the OnMyLocationChangeListener is not initialized.
The logic being there's no point initializing the object if no Sub exists to handle it's event.

So check that your code contains the required Sub to handle the OnMyLocationChangeListener MyLocationChange event.

Martin.
 
Upvote 0
Top