B4A Library FusedLocationProvider

FusedLocationProvider is Android's latest attempt to improve the location services available to your applications.

Official documentation can be found here: https://developer.android.com/google/play-services/location.html.

This library depends on the Google Play Services library, android-support-v4 library and the GPS library.
The GPS library is required in order to use it's Location object.

FusedLocationProvider
Events:

  • ConnectionFailed (ConnectionResult1 As Int)
  • ConnectionSuccess
  • ConnectionSuspended (SuspendedCause1 As Int)
  • LocationChanged (Location1 As Location)
  • LocationSettingsChecked (LocationSettingsResult1 As LocationSettingsResult)
Fields:
  • ConnectionResult As ConnectionResult
    Contains the various ConnectionResult constants.
  • SuspendedCause As SuspendedCause
    Contains the various SuspendedCause constants.
Methods:
  • CheckLocationSettings (LocationSettingsRequest1 As LocationSettingsRequest)
    Checks if the relevant system settings are enabled on the device to carry out the desired location requests.
    Raises the event:
    LocationSettingsChecked(LocationSettingsResult1 As LocationSettingsResult)
  • Connect
    Attempt to connect to the Location Services.
    Will raise either event:
    ConnectionFailed(ConnectionResult1 As Int)
    ConnectionSuccess
  • Disconnect
    Disconnect from the Location Services.
  • GetLastKnownLocation As Location
    Returns the best most recent location currently available.
    Can only be called if the FusedLocationProvider is connected.
    The returned Location object will not be initialized if no last known location is available.
  • Initialize (EventName As String)
    Initialize the FusedLocationProvider object.
  • IsConnected As Boolean
    Returns whether the FusedLocationProvider is connected to the Location Services.
  • IsConnecting As Boolean
    Returns whether the FusedLocationProvider is trying to connect to the Location Services.
  • IsInitialized As Boolean
  • RemoveLocationUpdates
    Remove all requests for location updates.
  • RequestLocationUpdates (LocationRequest1 As LocationRequest)
    Request for location updates.
    The LocationRequest object defines the criteria for which location updates are requested.

This is the main library object.
You call the FusedLocationProvider Initialize method and then it's Connect method.
It will then raise the ConnectionFailed event or the ConnectionSuccess event.
Assuming the ConnectionSuccess event is raised you can now call:
  • GetLastKnownLocation As Location
  • RequestLocationUpdates (LocationRequest1 As LocationRequest)

So you could connect, get the last known location and then disconnect.
There is no requirement to request location updates.
This is a quick and simple way to get the device location.

Or you could connect then initialize and configure a LocationRequest object and then request location updates.
The LocationRequest object has various methods you can call to configure the request for location updates:

LocationRequest
Fields:

  • Priority As Priority
    Contains the various priority constants.
Methods:
  • GetExpirationTime As Long
    Get the request expiration time, in milliseconds since boot.
  • GetFastestInterval As Long
    Get the fastest interval of this request, in milliseconds.
  • GetInterval As Long
    Get the desired interval of this request, in milliseconds.
  • GetNumUpdates As Int
    Get the number of updates requested.
  • GetPriority As Int
    Get the quality of the request.
  • GetSmallestDisplacement As Float
    Get the minimum displacement between location updates in meters.
    By default this is 0.
  • Initialize
    Initialize the LocationRequest with default parameters.
    Default parameters are for a block accuracy, slowly updated location.
  • IsInitialized As Boolean
  • SetExpirationDuration (Millis As Long) As LocationRequest
    Set the duration of this request, in milliseconds.
  • SetExpirationTime (Millis As Long) As LocationRequest
    Set the request expiration time, in millisecond since boot.
  • SetFastestInterval (Millis As Long) As LocationRequest
    Explicitly set the fastest interval for location updates, in milliseconds.
  • SetInterval (Millis As Long) As LocationRequest
    Set the desired interval for active location updates, in milliseconds.
  • SetNumUpdates (NumUpdates As Int) As LocationRequest
    Set the number of location updates.
  • SetPriority (Priority As Int) As LocationRequest
    Set the priority of the request.
  • SetSmallestDisplacement (SmallestDisplacementMeters As Float) As LocationRequest
    Set the minimum displacement between location updates in meters.
    By default this is 0.

It is important to note that part of the criteria that defines your request for a location is the location permission that you (manually) set in the manifest file.
This library does not automatically add any permission to your manifest and this library will fail to work if you do not manually add a required permission to your manifest file.

You can add one of two permissions to your manifest:
  • android.permission.ACCESS_FINE_LOCATION
  • android.permission.ACCESS_COARSE_LOCATION

See: https://developer.android.com/training/location/retrieve-current.html
Apps that use location services must request location permissions.
Android offers two location permissions: ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION.
The permission you choose determines the accuracy of the location returned by the API.
If you specify ACCESS_COARSE_LOCATION, the API returns a location with an accuracy approximately equivalent to a city block.

Also note that as this library uses the Google Play Services library, you must also add this entry to your manifest:

B4X:
AddApplicationText(<meta-data
    android:name="com.google.android.gms.version"
    android:value="@integer/google_play_services_version" />)

Two versions of the library are attached.
  • If you're using a version of Google Play Services older than version 27 then you need to use FusedLocationProvider version 1.10.
  • If you're using Google Play Services version 27 or newer then you need to use FusedLocationProvider version 1.30 or newer

Martin.

Edit by Erel:
Add these two lines if using with B4A v6+:
B4X:
#AdditionalJar: com.android.support:support-v4
#AdditionalJar: com.google.android.gms:play-services-location
New example where FLP is managed from the starter service: https://www.b4x.com/android/forum/threads/fusedlocationprovider.50614/post-717726
 

Attachments

  • FusedLocationProvider_library_files_v1.10.zip
    19.3 KB · Views: 1,227
  • FusedLocationProvider_library_files_v1.31.zip
    20 KB · Views: 2,109
Last edited by a moderator:

warwound

Expert
Licensed User
The first post in this thread explains how the accuracy criteria is set:

It is important to note that part of the criteria that defines your request for a location is the location permission that you (manually) set in the manifest file.
This library does not automatically add any permission to your manifest and this library will fail to work if you do not manually add a required permission to your manifest file.

You can add one of two permissions to your manifest:
  • android.permission.ACCESS_FINE_LOCATION
  • android.permission.ACCESS_COARSE_LOCATION

See: https://developer.android.com/training/location/retrieve-current.html
Apps that use location services must request location permissions.
Android offers two location permissions: ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION.
The permission you choose determines the accuracy of the location returned by the API.
If you specify ACCESS_COARSE_LOCATION, the API returns a location with an accuracy approximately equivalent to a city block.

So the application permission you choose determines whether GPS or network location is requested.
And then the user setting you referred to determines whether or not the application permission is granted.
 

marcel

Active Member
Licensed User
Hi, I released my app and in some cases I get error that the google play service is not up to date. The way to handle this is to call
public Dialog getErrorDialog (Activity activity, int errorCode, int requestCode)
How can I do this??
 

marcel

Active Member
Licensed User
Hi, I released my app and in some cases I get error that the google play service is not up to date. The way to handle this is to call
public Dialog getErrorDialog (Activity activity, int errorCode, int requestCode)
How can I do this??

RESOLVED:

I created a sub in the main activity and call this from the service:

B4X:
Sub ErrorDialogGooglePlayServices(code As Int)
        Dim jo As JavaObject
        Dim r As Reflector

        jo.InitializeStatic("com.google.android.gms.common.GooglePlayServicesUtil")
        If jo.RunMethod("isUserRecoverableError", Array As Object(code)) Then
            'Log(jo.RunMethod("getErrorString",Array As Object(code)))
            jo.RunMethodJO("getErrorDialog", Array As Object(code, r.GetActivity, 1001)).RunMethod("show", Null)
        Else
            ToastMessageShow("Play Services not available for this device",True)
        End If 
End Sub
 

Daniel-White

Active Member
Licensed User
@warwound, I have tested the new version & SetAlwaysShow option.
Its working great. Thank you so much.

I was trying to test it, but I guess I am doing something wrong, or I did not understand the concept. I applied this
LocationSettingsRequestBuilder1.SetAlwaysShow(true) and the message appears as usual like this when the GPS is turned off ok :
upload_2016-2-21_14-27-0.png


if I press "NEVER" in Spanish "NUNCA", the APP when need the GPS again 2 minutes later, fused does not show this dialog again. when I turned off the GPS and WIFI etc and re-compiled that dialog box never show up again neither. I tested LocationSettingsRequestBuilder1.SetAlwaysShow(False)
and with True.

Perhaps I misunderstanding the JimmyQG question "'never ask permission' option during the location access permission on initial run,"
 

Attachments

  • upload_2016-2-21_14-26-36.png
    upload_2016-2-21_14-26-36.png
    97 KB · Views: 62

warwound

Expert
Licensed User
@Daniel-White

Maybe when you use SetAlwaysShow(True), the permission prompt will always show but only when your app initially starts.
So set it to True and clean install your app.
Answer Never to the permission prompt.
Now reboot your device and run your app again.
Do you now see the permission prompt again?
 

Daniel-White

Active Member
Licensed User
Thanks you for you reply.

mmm, ok I reboot and run the APP, and it is not showing the prompt. so that is the behavior we are looking for?
 

Daniel-White

Active Member
Licensed User
Hi, everybody, I have a curiosity about the "GPS_GpsStatus" from the Erel Example https://www.b4x.com/android/forum/threads/gps-tutorial.6592/#content
We have an equivalent in FusedLocationProvider? , I would like to detect when the GPS is under tunnel or similar situation. I am using the Satellite.UsedInFix = true that will indicate that specific Satellite is helping to my device to obtain the Geo-position. etc.

I am looking to use some like this but I don't know the method in Fused library. Or it will be fine mix fusedLibrary and Gps1.start(0,0) etc. o_O Right now it is working mixed . :D, But I don't know if it is clever and clean way to do it.:eek:


Sub GPS_GpsStatus (Satellites As List)
Dim Quantity As Int
For i = 0 To Satellites.Size - 1
Dim Satellite As GPSSatellite
Satellite = Satellites.Get(i)
If Satellite.UsedInFix=True Then
Quantity=Quantity+1
End If

If Quantity < 3 Then
Log("It is not enough to put the Boolean variable GPSfix = FALSE")
End If
Next
End Sub
 
Last edited:

Daniel-White

Active Member
Licensed User
Hi everybody.
One simple question for you, hard for me. :eek:
I am looking to detect when fusedlocation lib is using the GPS or the (wifi ,cells towers), I think this can help me.
LocationSettingsStates
Methods:

  • IsLocationUsable As Boolean
    Whether location is enabled and is usable by the app.
    This method returns true when either GPS or network location provider is usable.
  • IsNetworkLocationUsable As Boolean
    Whether network location provider is enabled and usable by the app.
If I am not wrong, if I take this one, IsNetworkLocationUsable and the value is = True than mean the APP is using in that moment the (wifi or towers).

Now, how can I implement it?. I don't know how to structure that routine. I don't see the sub Fusedlocation1_LocationSettingsStates

I had been reading this in this place https://github.com/microg/android_e...roid/gms/location/LocationSettingsStates.java
public LocationSettingsStates(boolean gpsUsable, boolean networkLocationUsable, boolean bleUsable, boolean gpsPresent, boolean networkLocationPresent, boolean blePresent) {
this.gpsUsable = gpsUsable;
this.networkLocationUsable = networkLocationUsable;
this.bleUsable = bleUsable;
this.gpsPresent = gpsPresent;
this.networkLocationPresent = networkLocationPresent;
this.blePresent = blePresent;
}


Thanks you Indeed, I will very appreciate any light. :D
 
Last edited:
Top