In wayfinding applications you may not want to keep your application positioning all the time. Imagine this situation: the user opens the map and you start positioning, then she closes it and you a stop, but just after a few seconds, she opens the app again and you need to start positioning.
The problem is that each time Situm SDK will need to start positioning from scratch after each re-start, therefore requiring a few seconds each time to provide an accurate location. For the user, this makes no sense: after all, she was perfectly located a few seconds ago, and she didn't move!
To solve this issue, Situm SDK provides an option that can be activated using the method LocationRequest.Builder.useLocationsCache. In essence, this option saves the last know location in the smartphone's cache and uses it at a hint when you start positioning, provided that this last known location is not older than 30 seconds.
If the user did not move significantly since the last stop, Situm SDk will provide a first accurate location almost inmediatelly. Otherwise, behaviour may change as described in the following table.
User moved from last stored location | Expected behaviour |
---|---|
0 meters - 5 meters | An accurate location will be provided inmediatelly |
10 meters-20 meters | An approximate location will be provided inmediatelly (error = 10-20 meters). It will regain the usual accuracy after a few seconds, specially if the user moves |
20-50 meters | A not so accurate location will be provided inmediatelly (error = 20-50 meters). Situm SDK will probably try to geolocate the user again from scratch, resulting in a beheviour similar to what's expected when this option is not active. |
The user may also change her orientation since the last know location. This table describes what to expect in this case:
User orientation changed from last stored location | Smartphone has a working compass (calibrated) | Expected behaviour |
---|---|---|
User does not change orientation or turns right/left less than 45 degrees | Yes | An accurate orientation will be provided quickly. |
No | Orientation will be accurate enough very quickly (+-45 degrees of maximum error). | |
Otherwise | Yes | An unaccurate orientation (error over +-45 degrees) will be provided at first. Situm SDK will re-compute an accurate orientation in a few seconds. |
No | An unaccurate orientation (error over +-45 degrees) will be provided at first. In order to achieve better accuracy, user may have to walk around. |
Code example
The following code example shows how to use this method. In this example, we create two buttons to Start and Stop the positioning system (just for the sake of the example). The buttons are defined in your activity_main.xml file:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <!-- Start Button --> <Button android:id="@+id/button_start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginStart="10dp" android:layout_marginTop="10dp" android:text="Start" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <!-- Stop Button --> <Button android:id="@+id/button_stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="10dp" android:layout_marginEnd="10dp" android:text="Stop" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
Then, in your MainActivity.java
package com.example.situmsdkbasicapp; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import es.situm.sdk.SitumSdk; import es.situm.sdk.location.LocationListener; import es.situm.sdk.location.LocationRequest; import es.situm.sdk.location.LocationStatus; import es.situm.sdk.model.location.Location; import es.situm.sdk.error.Error; public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); private Button buttonStart, buttonStop; private LocationListener locationListener = new LocationListener() { @Override public void onLocationChanged(Location location) { Log.i(TAG, "onLocationChanged() called with: location = [" + location + "]"); } @Override public void onStatusChanged(@NonNull LocationStatus status) { Log.i(TAG, "onStatusChanged() called with: status = [" + status + "]"); } @Override public void onError(@NonNull Error error) { Log.e(TAG, "onError() called with: error = [" + error.getMessage() + "]" + " and code = ["+error.getCode() + "]"); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //Initializes Situm SDK SitumSdk.init(this); //Creates the LocationRequest with the Locations Cache activated final LocationRequest locationRequest = new LocationRequest.Builder().useLocationsCache(true).build(); //Start Button: starts positioning buttonStart = (Button) findViewById(R.id.button_start); buttonStart.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (!SitumSdk.locationManager().isRunning()) SitumSdk.locationManager().requestLocationUpdates(locationRequest, locationListener); } }); //Stop Button: stops positioning buttonStop = (Button) findViewById(R.id.button_stop); buttonStop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (SitumSdk.locationManager().isRunning()) SitumSdk.locationManager().removeUpdates(locationListener); } }); } }
Execution
If you build & run this example, your application log should look like this:
2021-04-10 13:41:48.190 onStatusChanged() called with: status = [CALCULATING] 2021-04-10 13:41:51.196 onStatusChanged() called with: status = [STARTING] 2021-04-10 13:41:52.292 onLocationChanged() called with: location = [Location{provider='SITUM_PROVIDER', deviceId=724614936937, timestamp=1618054912258, position=Point{buildingIdentifier='-1', floorIdentifier='-1', cartesianCoordinate=CartesianCoordinate{x=0.00, y=0.00}, coordinate=Coordinate{latitude=43.356493, longitude=-8.413401}, isOutdoor=true}, quality=HIGH, accuracy=22.846, cartesianBearing=Angle{radians=0.00, degrees=0.00}, bearing=Angle{radians=0.00, degrees=0.00}, bearingQuality=HIGH, customFields={}}] .... 2021-04-10 13:42:02.034 onLocationChanged() called with: location = [Location{provider='SITUM_PROVIDER', deviceId=724614936937, timestamp=1618054921993, position=Point{buildingIdentifier='6541', floorIdentifier='13483', cartesianCoordinate=CartesianCoordinate{x=14.02, y=8.57}, coordinate=Coordinate{latitude=43.356419, longitude=-8.413083}, isOutdoor=false}, quality=HIGH, accuracy=2.5115864, cartesianBearing=Angle{radians=3.06, degrees=175.46}, bearing=Angle{radians=4.79, degrees=274.54}, bearingQuality=LOW, customFields={}}]
At this point, Situm SDK has converged to an accurate location in building 6541, floor 13483, latitude 43.356419 and longitued -8.413083. If you hit the Stop button, Situm SDK will will stop but, if you hit the Start button again (before 30 seconds), the last known location will be uset at startup again.
2021-04-10 13:42:02.280 onStatusChanged() called with: status = [STOPPED] 2021-04-10 13:42:04.630 onStatusChanged() called with: status = [CALCULATING] 2021-04-10 13:42:05.686 onStatusChanged() called with: status = [STARTING] 2021-04-10 13:42:07.691 onLocationChanged() called with: location = [Location{provider='SITUM_PROVIDER', deviceId=724614936937, timestamp=1618054927396, position=Point{buildingIdentifier='6541', floorIdentifier='13483', cartesianCoordinate=CartesianCoordinate{x=14.02, y=8.57}, coordinate=Coordinate{latitude=43.356419, longitude=-8.413083}, isOutdoor=false}, quality=LOW, accuracy=0.0, cartesianBearing=Angle{radians=3.06, degrees=175.46}, bearing=Angle{radians=4.79, degrees=274.54}, bearingQuality=LOW, customFields={}}] ...
Notice that the last know location is exactly repeated in the first geolocations provided by the SDK after the re-start, in just a few seconds. After a few seconds, the SDK starts integrating sensor data as usual and new locations will be computed.