B4A Library RSFluffyLocation - Battery-friendly background location updates

Hi everyone

I'm happy to introduce a new library to Basic4Android.

Drop this tiny library into your Android app, configure your manifest, initialise it in your application's .. and that's it!

Location updates will be broadcast to your app periodically, including after phone reboot. And your users won't complain about it killing their batteries.

Perfect for widgets that require periodic updates in background, and for apps that need a reasonably current location available to them on startup. Also works great for apps that do something with location periodically, such as using it to get updates from a server.

Requires Android 2.1 and up. Works best with 2.2 and up.

The library works by using Froyo's passive location listener (only possible with Android 2.2 and up, hence why it works best with it), which listens to location updates requested by other apps on your phone. The most accurate location is broadcast to your app approximately every 15 minutes. If a location update hasn't been received from another app for an hour, the library forces a location update of its own.

The original library is written by Kenton Price, co-founder of Little Fluffy Toys Ltd.

Features:

  • location updates broadcast to your app approximately every 15 minutes (if a new location update was found)
  • if no location update found for an hour, an update is requested
  • optionally, every location update is broadcast
  • frequency of regular broadcasts (default 15 minutes) and forced updates (default 60 minutes) configurable
  • force update feature
  • get latest location feature
  • choose the most accurate location from the location providers available
  • debug output optional


API Documentation

RSFluffyLocation
Author:
XverhelstX
Version: 1
  • RSFluffyLocation
    Fields:
    • DEFAULT_ALARM_FREQUENCY As Long
    • DEFAULT_MAXIMUM_LOCATION_AGE As Int
    • LOCATION_BROADCAST_EXTRA_LOCATIONINFO As String
    • getLocationChangedPeriodicBroadcastAction As String
    • getLocationChangedTickerBroadcastAction As String
    Methods:
    • EnableDebugging
    • ForceLocationUpdate
      To force a location update, call this and soon you'll get a broadcast containing the latest location.
    • Initialize (PackageName As String) As Int
      Initializes the RSFluffylocation Library.
      PackageName - Your package name of your app.
    • Initialize2 (PackageName As String, BroadcastEveryLocationUpdate As Boolean) As Int
      Initializes the RSFluffylocation Library.
      PackageName - Your package name of your app.

      BroadcastEveryLocationUpdate - If true, in addition to broadcasting periodic updates,
      it broadcasts every location update as it is found,
      using intent action com.your.package.name.littlefluffylocationlibrary.LOCATION_CHANGED_TICK. The default is false
    • Initialize3 (PackageName As String, AlarmFrequency As Long, LocationMaximumAge As Int) As Int
      Initializes the RSFluffylocation Library.
      PackageName - Your package name of your app.

      AlarmFrequency - How often to broadcast a location update in milliseconds, if one was received.
      For battery efficiency, this should be one of the available inexact recurrence intervals.
      You are not prevented from using any other value.The default is AlarmManager.INTERVAL_FIFTEEN_MINUTES.

      LocationMaximumAge - The maximum age of a location update.
      If when the alarm fires the location is older than this, a location update will be requested.
      The default is AlarmManager.INTERVAL_HOUR.
    • Initialize4 (PackageName As String, BroadcastEveryLocationUpdate As Boolean, AlarmFrequency As Long, LocationMaximumAge As Int) As Int
      Initializes the RSFluffylocation Library.
      PackageName - Your package name of your app.

      BroadcastEveryLocationUpdate - If true, in addition to broadcasting periodic updates,
      it broadcasts every location update as it is found,
      using intent action com.your.package.name.littlefluffylocationlibrary.LOCATION_CHANGED_TICK. The default is false

      AlarmFrequency - How often to broadcast a location update in milliseconds, if one was received.
      For battery efficiency, this should be one of the available inexact recurrence intervals.
      You are not prevented from using any other value.The default is AlarmManager.INTERVAL_FIFTEEN_MINUTES.

      LocationMaximumAge - The maximum age of a location update.
      If when the alarm fires the location is older than this, a location update will be requested.
      The default is AlarmManager.INTERVAL_HOUR.
    • UseFineAccuracyForRequests (useFineAccuracyForRequests As Boolean)
      Uses fine accuracy for requests.
    • getLocationInfo (intent As IntentWrapper) As LocationInfo
      Returns the latest LocationInfo object from an intent.
      You should call this from your BroadCastReceiver OnReceive method.
    Permissions:
    • android.permission.ACCESS_COARSE_LOCATION
    • android.permission.ACCESS_FINE_LOCATION
    • android.permission.RECEIVE_BOOT_COMPLETED
  • RSFluffyLocationInfo
    Methods:
    • AnyLocationDataBroadcast As Boolean
      Returns true if any location data been broadcast since the last reboot
    • AnyLocationDataReceived As Boolean
      Returns true if any location data been received since the last reboot.
    • HasLatestDataBeenBroadcast As Boolean
      Returns true if the location data in the object has already been broadcast.
    • Initialize
      Initializes the RSFluffylocation Library.
      PackageName - Your package name of your app.
    • IsInitialized As Boolean
    • Refresh
      Refresh the fields with the latest location info
    Properties:
    • Accuracy As Int [read only]
      Gets the last location update's accuracy, in metres
    • Latitude As Float [read only]
      Gets the last location update's latitude.
    • LocationBroadcastTimestamp As Long [read only]
      Gets the time a location update was last broadcast, in milliseconds
    • LocationUpdateTimestamp As Long [read only]
      Gets the time the last location update was recorded, in milliseconds
    • Longitude As Float [read only]
      Gets the last location update's longitude
    • Provider As String [read only]
      Gets the latest location provider.
    • TimestampAgeInSeconds As Long [read only]
      Returns the age of the last location update in seconds


Manifest:

B4X:
AddManifestText(
<uses-feature android:name="android.hardware.location" android:required="true" />
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
)

SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")
'End of default text.

AddReceiverText(LocationListener,
<intent-filter>
    <action android:name="com.rootsoft.rsfluffylocation.littlefluffylocationlibrary.LOCATION_CHANGED" />
    <action android:name="com.rootsoft.rsfluffylocation.littlefluffylocationlibrary.LOCATION_CHANGED_TICK" />
</intent-filter>)

AddApplicationText(
<service android:name="com.littlefluffytoys.littlefluffylocationlibrary.LocationBroadcastService" />
    <receiver android:name="com.littlefluffytoys.littlefluffylocationlibrary.StartupBroadcastReceiver" android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
<receiver android:name="com.littlefluffytoys.littlefluffylocationlibrary.PassiveLocationChangedReceiver" android:exported="true" />
)

Change "com.rootsoft.rsfluffylocation" to your own package name.

Kind regard,
Tomas
RootSoft LLC
 

Attachments

  • RSFluffyLocation.zip
    503 KB · Views: 892
Last edited:

korshkov

Member
Licensed User
Longtime User
Tomas, thanks for you library!
I test you sample and not found how to stop service.

Need Initialize with maximum interval?

P.S. Excuse me for my bad English.
 

XverhelstX

Well-Known Member
Licensed User
Longtime User
Tomas, thanks for you library!
I test you sample and not found how to stop service.

Need Initialize with maximum interval?

P.S. Excuse me for my bad English.

Hi

I've seen the same.
Perhaps try StopService(locationlistener), but I think the author of the original library did not include how to stop sending updates.
I've already emailed him, but I haven't gotten a reply yet.

Tomas
 

mokrokuce

Member
Licensed User
Longtime User
Tried to DL the lib, but I only get 210 KB out of 503. Could you repost the file, please?
 

Harris

Expert
Licensed User
Longtime User
Tomas,

Which version was used of littlyfluffy to produce the wrapped lib?

I am experiencing the following issue:
What's new - v15 - June 2013
  • fixed an issue whereby if a user has GPS location services enabled but not network (wifi/celltower) services enabled, the library would never return an on-demand or after-timeout location
When I have only GPS enabled, a ForceLocationUpdate will never return an on-demand...
When network and GPS are both enabled in location settings, it works just fine.
When network and GPS are both enabled in location settings, but wifi is not turned on, it won't report a location until I turn wifi on...

Thanks for the lib.
 
Last edited:

Mark Zraik

Member
Licensed User
Longtime User
Well I had to try this out.
Since I don't know enough, nor can I seem to retain enough knowledge before the phone rings and I need to run out the door and pay the bills ;).
I thought I would post some things that may help with implementing this library using win8.1.
I use B4A 3.82, and initially test on a Samsung i927 (S2 Slide/Glide) rooted and unlocked with Android 2.3.5 as a custom rom, it's older but it works. This where i start, and then grab the other phone, tablets, etc.
First, download the library file and place the 2 jars and the xml in your additional library files location for B4A. Refresh your project in the B4A libs tab, make sure you can see the new library RSFluffyLocation (version 1.00)
Then, copy the RSFluffyLocation project folder that is within the zip file to whatever folder you keep your projects in on your hard drive.
I found it easier to copy and paste from the RSFluffyLocation test project provided in the RSFluffyLocation.zip to my current project.
Since I started out in a new app, this worked well. Don't forget the to copy manifold text from this forum, or from the test project into your manifest editor.

I am also new to working and understanding services (Listeners), and how to implement the different ways android allows for a service.
Jumping to and fro from this page and the android developer website with respect to services and the manifest requirements, I learned plenty, forgot even more and was confused even longer. So, onto the info!

Place a copy of the littlefluffylocationlibrary.jar within your project "Files" folder (The same location as your project extra files are in), then,

Using B4A 3.8 and above, add the #AdditionalJar: littlefluffylocationlibrary to your main activity in the region section.
Like so...
B4X:
#Region  Project Attributes
    #ApplicationLabel: Where Was That
    #VersionCode: 1
    #VersionName: 1.0
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: portrait
    #CanInstallToExternalStorage: False
    #AdditionalJar: littlefluffylocationlibrary
#End Region

You can add it anywhere in the Region.
I kept the Service module in my project the same as the example "LocationListener", at least for now.

As you can see, the StartingIntent.Actions are modified to match my project - com.cazmaz.wwt.littlefluffylocationlibrary.LOCATION_CHANGED and
com.cazmaz.wwt.littlefluffylocationlibrary.LOCATION_CHANGED_TICK

B4X:
Sub Service_Start (StartingIntent As Intent)
    Dim FluffyLocation As RSFluffyLocation
    Dim LocationInfo As RSFluffyLocationInfo
  
    If StartingIntent.Action = "com.cazmaz.wwt.littlefluffylocationlibrary.LOCATION_CHANGED" Then
        Log("FLUFFY - LOCATION CHANGED.")
  
        LocationInfo = FluffyLocation.getLocationInfo(StartingIntent)
        CallSubDelayed2(Main, "FluffyLocation_LocationUpdated", LocationInfo)
  
    Else If StartingIntent.Action = "com.cazmaz.wwt.littlefluffylocationlibrary.LOCATION_CHANGED_TICK" Then
        Log("FLUFFY - LOCATION CHANGED TICK.")
  
        LocationInfo = FluffyLocation.getLocationInfo(StartingIntent)
        CallSubDelayed2(Main, "FluffyLocation_LocationUpdated", LocationInfo)
    End If

End Sub
Manifest looks like this...
As Thomas stated in the forum post, only change the intent filters to your project package name, not the receiver parts.
Those need to stay the same as they refer to sub classes within the littlefluffylocationlibrary.jar file.

B4X:
AddReceiverText(LocationListener,
<intent-filter>
    <action android:name="com.cazmaz.wwt.littlefluffylocationlibrary.LOCATION_CHANGED" />
    <action android:name="com.cazmaz.wwt.littlefluffylocationlibrary.LOCATION_CHANGED_TICK" />
</intent-filter>)

AddApplicationText(
<service android:name="com.littlefluffytoys.littlefluffylocationlibrary.LocationBroadcastService" />
    <receiver android:name="com.littlefluffytoys.littlefluffylocationlibrary.StartupBroadcastReceiver" android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
<receiver android:name="com.littlefluffytoys.littlefluffylocationlibrary.PassiveLocationChangedReceiver" android:exported="true" />
)

Thomas did a good job of explaining it, I just had to do a better job of learning the Android hoops, and realizing that this was last updated in 2013.
Android has changed and so has B4A.

I got this to work, so far.
 
Last edited:

Mark Zraik

Member
Licensed User
Longtime User
Thomas,

This is marked as Chargeable. Where can I find out what you are charging?

I found this on the website for Little Fluffy Toys, is it the same policy for this lib as well??

Announcing Little Fluffy Location Library for Android
by Little Fluffy Toys Ltd on Apr.24, 2012, under Little Fluffy Location Library, Open source

Sorry we’ve been quiet – we’ve been snowed under! As part of that, we’ve been creating an app that needed background location updates without wrecking users’ batteries. We were so pleased with the result, we think others should be able to use it too, so we took the guts of it and made a simple library that anyone can use in their Android apps. And it’s open source so you can change the code as much as you like. And it’s free!
 

coslad

Well-Known Member
Licensed User
Longtime User
Hi i tested the sample code, but i doesn't works .
It fire FluffyLocation_LocationUpdated only with gps active !
 

iatall

Member
Licensed User
Longtime User
I am trying to get location from service module and store it to my gps.txt file.
But i am getting this error : Module: locationlistener_br not found.
sry, i am new to b4a.

My service module :
B4X:
#Region  Service Attributes
    #StartAtBoot: True
    #StartCommandReturnValue: android.app.Service.START_STICKY
#End Region

Sub Process_Globals       
      Dim FluffyLocation As RSFluffyLocation
      Dim LocationInfo As RSFluffyLocationInfo
      Dim p As PhoneWakeState
End Sub
Sub Service_Create
    Dim n As Notification
    n.Initialize
    n.Icon = Null
    n.Vibrate = False
    n.OnGoingEvent = True
    n.SetInfo("armap", "Store GPS Info", Null)
    Service.StartForeground(0, n)                   
End Sub

Sub Service_Start (StartingIntent As Intent)
    p.KeepAlive(True)
    p.PartialLock
    FluffyLocation.EnableDebugging
    If StartingIntent.Action = "com.rootsoft.rsfluffylocation.littlefluffylocationlibrary.LOCATION_CHANGED" Then
        Log("FLUFFY - LOCATION CHANGED.")       
        LocationInfo = FluffyLocation.getLocationInfo(StartingIntent)
        FluffyLocation_LocationUpdated        
    Else If StartingIntent.Action = "com.rootsoft.rsfluffylocation.littlefluffylocationlibrary.LOCATION_CHANGED_TICK" Then
        Log("FLUFFY - LOCATION CHANGED TICK.")       
        LocationInfo = FluffyLocation.getLocationInfo(StartingIntent)
        FluffyLocation_LocationUpdated
    End If   
    If FluffyLocation.Initialize4("com.rootsoft.rsfluffylocation", True, 60 * 1000, 2 * 60 * 1000) = 1 Then
        FluffyLocation_LocationUpdated
    Else
        Log("FluffyLocation is not supported.")
    End If
    FluffyLocation.ForceLocationUpdate
End Sub
Sub FluffyLocation_LocationUpdated
    Log("Location update: " & LocationInfo.Longitude)
End Sub
Sub Service_Destroy

End Sub
 

TrisectDevelopment

Active Member
Licensed User
Longtime User
Any news on how to stop the update.
In my Main acitvity i call the update function but when I go to another activity is suddently goes back to Main and execute the update sub.
This is very annoying.
 

Firpas

Active Member
Licensed User
Longtime User
I'm testing this library and I found two problems:

After restarting the device, the service (LocationListener) is stopped and not will be available until the library is initialized again from the application.

The same applies when the device has been out of network and GPS coverage (such as in a woman's purse)

The author's website (http://www.littlefluffytoys.mobi/) is no longer available.

Any solution?

Thanks in advance for your cooperation.
 
Top