Finding your way with LOST

“Not all those who wander are lost.” ― J.R.R. Tolkien, The Fellowship of the Ring

Location Open Source Tracker (LOST) is an Android SDK we’ve been working on that provides open source location services for Android. It is a drop-in replacement for the Google Play Services Location APIs that depends only on the Android framework.

In non-Android speak: LOST makes it easy for an app on your Android device to figure out where you are, without having to talk to Google about it.

Let’s take a look at how devices figure out where you are, how Google does that, and how LOST does that.

Location Providers

image alt text

A location provider is a component, sensor, or system that can be used to determine the geographic location of a device. All location providers have different strengths and weaknesses, so they’re usually combined to generate the most accurate location possible. The Android platform uses several location providers:

GPS

The GPS location provider uses satellites to determine location. It has the best accuracy of all the providers but also the highest power consumption. GPS requires an unobstructed line of sight to four or more satellites, which means it is adversely affected by things like tree cover, bridges, tunnels, and buildings.

Network

The network location provider determines location using Wi-Fi and/or cell towers. Wi-Fi positioning operates reasonably well in areas with a high number of visible networks. Cell tower positioning is the least accurate of all location providers but also consumes the least power.

Passive

The passive provider is not a true location provider but rather a low-power alternative to actively requesting a location. Whenever another app or service requests a location update the same location is forwarded to the passive provider with no additional power consumption.

Sensors

Sensors are unable to determine an absolute location by themselves but can be used in conjunction with other providers. Raw data from the accelerometer, gyroscope, and magnetometer can be used to enhance location accuracy and measure displacement from the last known location.

image alt text Source: https://developers.google.com/events/io/sessions/325337477

For more information on location providers check out the Location and Sensor API Guide.

Fused Location Provider

Managing so many different location providers while maximizing accuracy and minimizing power consumption can greatly increase the complexity of an application. That’s where the Fused Location Provider comes in. Basically, it provides a high-level API that makes it easy to request location updates without needing to focus on the underlying details–location simplified.

Android’s official Fused Location Provider is part of Google Play Services, a collection of client libraries tightly integrated with Android. It’s installed via the Google Play Store and updated independently from the OS. It includes APIs for documents, games, in-app payments, maps, location, and other proprietary add-ons. However, there are some tradeoffs to using Google Play Services in your application.

Closed Source

Unlike the Android framework, Google Play Services is not open source. This provides less transparency and flexibility for developers. It also raises some questions regarding security and privacy.

Application Size

Google Play Services increases the number of methods and overall size of your application. These effects can be somewhat mitigated by stripping unused methods with ProGuard and enabling multidex support but can still have implications for overall APK size and the 65K Dalvik Executable (DEX) method limit as well as for the complexity of your build process.

Device Compatibility

Since Google Play Services is only available on devices that support the Google Play ecosystem, it reduces the number of devices your app can run on. Your application will be incompatible with devices running a forked version of Android such as the Kindle Fire or Blackphone as well as most devices in China.

This is where LOST comes in

LOST provides a pure open source implementation of the FusedLocationProviderApi. Its only dependency is the LocationManager so LOST can be used on any device that runs Android. It implements the same location APIs as Google Play Services so dropping it into an existing application is a snap.

Connecting to the LOST API Client

When using LOST, GoogleApiClient is replaced by LostApiClient. Connecting to LOST is even easier since there are no ConnectionCallbacks or OnConnectionFailedListener objects to manage.

LostApiClient lostApiClient = new LostApiClient.Builder(this).build();
lostApiClient.connect();

LOST instantly connects to the LocationManager and can immediately retrieve that last known location or begin sending location updates.

Getting the Last Known Location

Once connected you can request the last known location. The actual logic to determine the best most recent location is based this classic blog post by Reto Meier.

Location location = LocationServices.FusedLocationApi.getLastLocation();
if (location != null) {
  // Do stuff
}

Requesting Location Updates

LOST also provides the ability to request ongoing location updates. You can specify the update interval, minimum displacement, and priority. The priority determines which location providers will be activated.

LocationRequest request = LocationRequest.create()
    .setInterval(5000)
    .setSmallestDisplacement(10)
    .setPriority(LocationRequest.PRIORITY_LOW_POWER);

LocationListener listener = new LocationListener() {
  @Override
  public void onLocationChanged(Location location) {
    // Do stuff
  }
};

LocationServices.FusedLocationApi.requestLocationUpdates(request, listener);

Currently location updates can only be requested with a LocationListener object. In the future we are planning to add location updates via a PendingIntent as well.

Mock Locations

With LOST you can mock not just individual locations but also entire routes. By loading a GPX trace file onto the device you can configure LOST to replay locations from the trace file including latitude, longitude, speed, and bearing.

Mocking a single location

To mock a single location with LOST you must first enable mock mode. Then you simply create a mock location object and pass it to the API.

Location mockLocation = new Location("mock");
mockLocation.setLatitude(40.7484);
mockLocation.setLongitude(-73.9857);
LocationServices.FusedLocationApi.setMockMode(true);
LocationServices.FusedLocationApi.setMockLocation(mockLocation);

The mock location object you set will be immediately returned to all registered listeners and will be returned the next time getLastLocation() is called.

Mocking an entire route

To mock an entire route you must first transfer a GPX trace file to the device using adb. Sample GPX traces can be found on the public GPS traces page for OpenStreetMap. Once the trace file is loaded on the device you can tell LOST to replay the locations in the trace at the requested update interval.

File file = new File(Environment.getExternalStorageDirectory(), "mock_track.gpx");
LocationServices.FusedLocationApi.setMockMode(true);
LocationServices.FusedLocationApi.setMockTrace(file);

For more in-depth examples, please refer to the sample application.

Feedback & Contributions

We originally created LOST for location services in the Open by Mapzen application. We’re excited to see how other developers will use LOST and are looking forward to evolving the project based on your feedback and contributions. If you’re interested in using or contributing to LOST you can fork us on GitHub.