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: 2,024
  • FusedLocationProvider_library_files_v1.31.zip
    20 KB · Views: 3,037
Last edited by a moderator:

warwound

Expert
Licensed User
Longtime User
I think you'll need to create a LocationRequest with a much shorter interval - say 5 seconds.
Start listening for location updates using that LocationRequest.
Once you have a valid location update stop listening for that LocationRequest, create a new LocationRequest with the 1 hour interval and start listening again.

You might instead be able to change the LocationRequest interval using the method:

SetFastestInterval (Millis As Long)

So instead of creating 2 LocationRequests you might simply be able to change the interval of the existing LocationRequest.
I've not tested that.
 

Cebuvi

Active Member
Licensed User
Longtime User
Thank you for your answers.

I tested with a LocationRequest changing the interval and it works perfectly.

Cesar
 

stanks

Active Member
Licensed User
Longtime User
is it possible for user to start that resolution dialog and turn gps on and off? (ui button)
i tried but no dialog...idk y
i am trying to do this from another activity not main activity

thanks
 
Last edited:

warwound

Expert
Licensed User
Longtime User
is it possible for user to start that resolution dialog and turn gps on and off? (ui button)
i tried but no dialog...idk y
i am trying to do this from another activity not main activity

thanks

No, that dialog simply asks the device user if they will allow the device settings to be updated to allow the application's LocationRequests to succeed.
It doesn't have any option to explicitly enable or disable the GPS.
 

Carlo2015

Member
Licensed User
Longtime User
Hi warwound,

I tried using the lib, downloaded it and tried to compile the sample. but i get this

B4A version 4.30
Parsing code. 0.03
Compiling code. 0.15
Compiling layouts code. 0.03
Generating R file. Error
AndroidManifest.xml:20: error: Error: No resource found that matches the given name (at 'value' with value '@Integer/google_play_services_version').

my google play services is updated to version 24

TIA

Carlo
 

warwound

Expert
Licensed User
Longtime User
Have you got an #AdditionalRes attribute in your project that points to the Google Play Services 'res' folder in your android sdk?
 

Carlo2015

Member
Licensed User
Longtime User
Oh! my bad. I forgot I commented out the additionalres because it was pointed to your local file.

It was supposed to point to my local file.

Sorry

Edit: Thank you
 

kohle

Active Member
Licensed User
Longtime User
Hi,
made some tests with only the gps library and with the google location services (FusedLocationProvider).

Google : 15 meters, every 1 sec and High Acc.
GPS: : 15 meters, every 1 sec

When the device is moving, it looks ok, but when the device is not moving I get
strange results with theFusedLocationProvider Lib.

See my screenshots. (First pic is GPS, second pic is FusedLocationProvider)

Some ideas ?
 

Attachments

  • 2015_06_04_08.15.55.jpg
    2015_06_04_08.15.55.jpg
    85.8 KB · Views: 374
  • 2015_06_04_08.15.14.jpg
    2015_06_04_08.15.14.jpg
    190.8 KB · Views: 357
  • 2015_06_04_08.15.55.jpg
    2015_06_04_08.15.55.jpg
    85.8 KB · Views: 331
  • 2015_06_04_08.15.14.jpg
    2015_06_04_08.15.14.jpg
    190.8 KB · Views: 320

warwound

Expert
Licensed User
Longtime User
Nothing springs to mind.
Is it possible that FusedLocationProvider is mixing low accuracy network location fixes with high accuracy gps location fixes?
 

kohle

Active Member
Licensed User
Longtime User
Nothing springs to mind.
Is it possible that FusedLocationProvider is mixing low accuracy network location fixes with high accuracy gps location fixes?

Hi,
I made a workaround. Now it seems to work for fine for me. I tested it with 3 different phones.

I integrate the accuracy in my programming . I only save my trackpoint when Location1.Accuracy<=15 or AccuracyValid=False (all phones returned TRUE until yet)

When the celphone is not moving than the accuracy goes up to 25 - 90 meters.
When the celphone is moving it´s about 3-10 meters.


Sub FusedLocationProvider1_LocationChanged (Location1 As Location)

GPS_lat = Location1.Latitude
GPS_long = Location1.Longitude

If Location1.AccuracyValid=False or Location1.Accuracy<=15 Then
saveTrackPoint
End If

End Sub
 

fishwolf

Well-Known Member
Licensed User
Longtime User
Hi, good lib

i have try to set the example with the meter to 100 meter

LocationRequest1.SetSmallestDisplacement(100)

but i receive the same coord with the phone on desk.

FusedLocationProvider1_ConnectionSuccess
FusedLocationProvider1_LocationChanged
16:56:43 (41.9235858, 12.4093655)
16:56:43 (41.9235858, 12.4093655)
16:56:43 (41.9235858, 12.4093655)
16:57:14 (41.9235702, 12.4093633)
16:57:14 (41.9235702, 12.4093633)
16:57:14 (41.9235702, 12.4093633)
16:57:37 (41.9235647, 12.4093633)
 

warwound

Expert
Licensed User
Longtime User
What do you mean?

You run the example on a device and the device is sitting still on your desk?
What do you expect to see?

Look at post #29 in this thread where @kohle reports 'odd' locations when the device is not moving.
 

fishwolf

Well-Known Member
Licensed User
Longtime User
What do you mean?

You run the example on a device and the device is sitting still on your desk?
What do you expect to see?

Look at post #29 in this thread where @kohle reports 'odd' locations when the device is not moving.

a first event with geo coord and aften no event until i move the phone more of 100 meter

i need understand when the phone is moving or stay in a place with minor power consuming
 

Harris

Expert
Licensed User
Longtime User
a first event with geo coord and aften no event until i move the phone more of 100 meter

i need understand when the phone is moving or stay in a place with minor power consuming


I see basically same issue. When moving, GPS accuracy will report 4 - 6 meters (generally). When stopped - all bets are off - particularly when starting from cold boot. This is not a problem with the (B4A) wrap but how Android (Google) implemented the FusedLocationProvider. It is tricky business and hopefully, with our efforts to figure it out, it shall shall become clear how to deal with it. Right now I have to accept, without using the heavy GPS object, what Fused_Location can provide. For me, it a matter of testing and figuring out what is the best direction to go with - GPS object or Fused Location.

Good luck to us all.
 

netchicken

Active Member
Licensed User
Longtime User
I have updated Google Play Services, and copied the latest version to the libraries, and rerouted the #AdditionalRes path to match mine, but all I get when I run either example, is the following, it times out.

Anyone have any idea why?


B4A version: 5.02 (1)
Parsing code. (0.00s)
Compiling code. (0.04s)
Compiling layouts code. (0.00s)
Generating R file. (0.16s)
Compiling generated Java code. (0.81s)
Convert byte code - optimized dex. Error
UNEXPECTED TOP-LEVEL ERROR:
java.lang.OutOfMemoryError: GC overhead limit exceeded
 

aaronk

Well-Known Member
Licensed User
Longtime User
When I run the example from post 2 I get the following error:

B4X:
Installing file.
** Activity (main) Pause, UserClosed = false **
PackageAdded: package:uk.co.martinpearman.b4a.fusedlocationproviderexample
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
main_activity_resume (B4A line: 42)
FusedLocationProvider1.Connect
java.lang.IllegalStateException: The meta-data tag in your app's AndroidManifest.xml does not have the right value.  Expected 6111000 but found 7571000.  You must have the following declaration within the <application> element:     <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
    at com.google.android.gms.common.GooglePlayServicesUtil.E(Unknown Source)
    at com.google.android.gms.common.GooglePlayServicesUtil.isGooglePlayServicesAvailable(Unknown Source)
    at com.google.android.gms.common.internal.d.connect(Unknown Source)
    at com.google.android.gms.common.api.b.connect(Unknown Source)
    at uk.co.martinpearman.b4a.fusedlocationprovider.FusedLocationProviderWrapper.Connect(FusedLocationProviderWrapper.java:147)
    at uk.co.martinpearman.b4a.fusedlocationproviderexample.main._activity_resume(main.java:399)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:187)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:171)
    at uk.co.martinpearman.b4a.fusedlocationproviderexample.main.afterFirstLayout(main.java:108)
    at uk.co.martinpearman.b4a.fusedlocationproviderexample.main.access$000(main.java:17)
    at uk.co.martinpearman.b4a.fusedlocationproviderexample.main$WaitForLayout.run(main.java:80)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5417)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
java.lang.IllegalStateException: The meta-data tag in your app's AndroidManifest.xml does not have the right value.  Expected 6111000 but found 7571000.  You must have the following declaration within the <application> element:     <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
** Activity (main) Resume **

In my Manifest I have:
B4X:
'This code will be applied to the manifest file during compilation.
'You do not need to modify it in most cases.
'See this link for for more information: http://www.b4x.com/forum/showthread.php?p=78136
AddManifestText(
<uses-sdk android:minSdkVersion="5" android:targetSdkVersion="14"/>
<supports-screens android:largeScreens="true"
    android:normalScreens="true"
    android:smallScreens="true"
    android:anyDensity="true"/>)
SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")
SetApplicationAttribute(android:theme, "@android:style/Theme.Holo")
'End of default text.

'    FusedLocationProvider:

'    required manifest entry required for Google Play Services
AddApplicationText(<meta-data
    android:name="com.google.android.gms.version"
    android:value="@integer/google_play_services_version" />)
   
'    you must add one of these two permissions
'    the permission you add will define the accuracy of location updates
AddPermission(android.permission.ACCESS_FINE_LOCATION)
'    AddPermission(android.permission.ACCESS_COARSE_LOCATION)

Anyone have any ideas what is wrong ?
 
Top