Here's a basic example of detecting the device location using LocationClient, LocationRequest and LocationListener.
An Activity:
Sub Process_Globals
Dim LastLocation As Location
Dim TrackingEnabled As Boolean=False
End Sub
Sub Globals
Dim AltitudeLabel As Label
Dim BearingLabel As Label
Dim EnableToggle As ToggleButton
Dim LatLngLabel As Label
Dim SpeedLabel As Label
Dim TimeLabel As Label
End Sub
Sub Activity_Create(FirstTime As Boolean)
Activity.LoadLayout("Main")
EnableToggle.Checked=TrackingEnabled
If LastLocation.IsInitialized Then
LocationChanged
End If
End Sub
Sub Activity_Resume
End Sub
Sub Activity_Pause (UserClosed As Boolean)
End Sub
Sub EnableToggle_CheckedChange(Checked As Boolean)
TrackingEnabled=Checked
If TrackingEnabled Then
StartService(LocationTracker)
Else
StopService(LocationTracker)
End If
End Sub
Sub LocationChanged
AltitudeLabel.Text=LastLocation.Altitude
BearingLabel.Text=LastLocation.Bearing
LatLngLabel.Text=LastLocation.Latitude&", "&LastLocation.Longitude
SpeedLabel.Text=LastLocation.Speed
TimeLabel.Text=DateTime.Time(LastLocation.Time)
End Sub
And a Service:
Sub Process_Globals
Dim GooglePlayServicesHelper1 As GooglePlayServicesHelper
Dim LocationClient1 As LocationClient
Dim LocationListener1 As LocationListener
Dim LocationRequest1 As LocationRequest
End Sub
Sub Service_Create
LocationClient1.Initialize("LocationClient1")
End Sub
Sub Service_Start (StartingIntent As Intent)
If LocationClient1.IsConnected Then
Log("LocationClient IsConnected")
Else
Dim ServiceStatus As Int=GooglePlayServicesHelper1.IsGooglePlayServicesAvailable
Select ServiceStatus
Case GooglePlayServicesHelper1.SUCCESS
Log("GooglePlayServicesHelper IsGooglePlayServicesAvailable service available")
Log("LocationClient Connecting")
LocationClient1.Connect
Case Else
Log("GooglePlayServicesHelper IsGooglePlayServicesAvailable returned: "&ServiceStatus)
Log("Google Play Services unavailable")
StopService("")
End Select
End If
End Sub
Sub Service_Destroy
If LocationRequest1.IsInitialized Then
LocationClient1.RemoveLocationUpdates(LocationListener1)
End If
If LocationClient1.IsConnected Then
LocationClient1.Disconnect
End If
End Sub
Sub LocationClient1_Connected
Log("LocationClient1_Connected")
' the GPS library is required as we are using the Location object
' check to see if a previous last location exists
' if it does then pass it to our Sub that handles the LocationListener LocationChanged event
' (force a location changed event before the LocationClient gets it's next GPS fix)
Dim LastLocation As Location=LocationClient1.GetLastLocation
If LastLocation.IsInitialized Then
Log("LastLocation being passed to LocationListener1_LocationChanged")
LocationListener1_LocationChanged(LastLocation)
End If
LocationRequest1.Initialize
' detailed info on the LocationRequest parameters can be found:
' http://developer.android.com/training/location/receive-location-updates.html
' http://developer.android.com/reference/com/google/android/gms/location/LocationRequest.html
LocationRequest1.SetFastestInterval(1000*1) ' think of this as the fastest updates that your event handling Sub can handle
LocationRequest1.SetInterval(1000*6) ' this is the desired frequency of location update (units of milliseconds)
LocationRequest1.SetNumUpdates(9999) ' the maximum number of updates that should be reported, after this number no more will be reported
LocationRequest1.SetPriority(LocationRequest1.PRIORITY_HIGH_ACCURACY) ' the desired accuracy/power usage mode
LocationListener1.Initialize("LocationListener1")
LocationClient1.RequestLocationUpdates(LocationRequest1, LocationListener1)
End Sub
Sub LocationClient1_ConnectionFailed(ErrorCode As Int)
Log("LocationClient1_ConnectionFailed ErrorCode="&ErrorCode)
StopService("")
End Sub
Sub LocationClient1_Disconnected
Log("LocationClient1_Disconnected")
StopService("")
End Sub
Sub LocationListener1_LocationChanged (Location1 As Location)
Main.LastLocation=Location1
CallSub(Main, "LocationChanged")
End Sub
So in the Activity the user can use the ToggleButton to start and stop the Service.
The Service, when running, listens for location updates.
The Activity has a Process Global Location object that is initially not initialized.
When the Service gets a location update it sets the location update as the Activity Process Global Location object and calls a Sub in the Activity to update the Activity layout.
If the service is running and the user exits the app then the service will continue to run and update the Process Global, if the Activity is resumed it will update it's layout with the values of the last reported location.
All pretty straightforward stuff!
Lines 70 to 73 of the Service define the accuracy and frequency of the location requests and therefore the amount of device battery power that will be used.
It's listening for maximum accuracy location changes every 6000 milliseconds.
After 9999 location updates have bene reported presumably the LocationClient will report no more.
Compile the code and look in the manifest.xml file, you'll see:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
This permission is currently hardcoded into the library.
You can use the Location API with either android.permission.ACCESS_FINE_LOCATION or android.permission.ACCESS_COARSE_LOCATION.
If that permission in the manifest was ACCESS_COARSE_LOCATION instead of ACCESS_FINE_LOCATION then:
Location requests from applications with ACCESS_COARSE_LOCATION and not ACCESS_FINE_LOCATION will be automatically throttled to a slower interval, and the location object will be obfuscated to only show a coarse level of accuracy.
Sometimes it will be desirable/preferable to use android.permission.ACCESS_COARSE_LOCATION instead of android.permission.ACCESS_FINE_LOCATION.
Question: Shall i therefore remove the hardcoded android.permission.ACCESS_FINE_LOCATION from the library and leave the b4a developer to manually add the permission they require to the manifest file?
Or i believe i could leave the android.permission.ACCESS_FINE_LOCATION hardcoded and if a b4a developer wants to instead use android.permission.ACCESS_COARSE_LOCATION there are manifest editor commands that can be used to remove the unwanted permission and add the wanted permission.
Neither solution is perfect - the b4a developer will be required to manually manage their manifest permissions.
LocationClient, LocationRequest and LocationListener work well and can be considered to be ready for use in your b4a apps.
Be sure to check out both links to the android documentation in the code to read about the various LocationRequest parameters.
The FastestUpdate parameter is particularly interesting - if another app on the device is getting location updates then these location updates can also be passed to your app. The FastestInterval parameter tells android how fast your code can handle location updates so that it doesn't report updates (raise events) faster than your code can handle.
Demo project attached.
Martin.
(PS Please do comment on the permissions and how you think it is best to handle them).