Map matching

Match raw GPS points to the map so they align with roads and pathways.

This example requires trace.geojson, which should be placed in the app's assets directory. The activity_mas_map_matching.xml layout file is also required.
    import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;

import com.mapbox.mapboxandroiddemo.R;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.annotations.PolylineOptions;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.services.commons.ServicesException;
import com.mapbox.services.commons.geojson.LineString;
import com.mapbox.services.commons.models.Position;
import com.mapbox.services.directions.v4.DirectionsCriteria;
import com.mapbox.services.mapmatching.v4.MapboxMapMatching;
import com.mapbox.services.mapmatching.v4.models.MapMatchingResponse;

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class MapMatchingActivity extends AppCompatActivity {

  private static final String TAG = "MapMatchingActivity";

  private MapView mapView;
  private MapboxMap map;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Mapbox access token is configured here. This needs to be called either in your application
    // object or in the same activity which contains the mapview.
    Mapbox.getInstance(this, getString(R.string.access_token));

    // This contains the MapView in XML and needs to be called after the access token is configured.
    setContentView(R.layout.activity_mas_map_matching);

    mapView = (MapView) findViewById(R.id.mapView);
    mapView.onCreate(savedInstanceState);
    mapView.getMapAsync(new OnMapReadyCallback() {
      @Override
      public void onMapReady(MapboxMap mapboxMap) {

        map = mapboxMap;

        new DrawGeoJson().execute();

      }
    });
  }

  @Override
  protected void onStart() {
    super.onStart();
    mapView.onStart();
  }
  
  @Override
  public void onResume() {
    super.onResume();
    mapView.onResume();
  }

  @Override
  public void onPause() {
    super.onPause();
    mapView.onPause();
  }
  
  @Override
  protected void onStop() {
    super.onStop();
    mapView.onStop();
  }

  @Override
  public void onLowMemory() {
    super.onLowMemory();
    mapView.onLowMemory();
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    mapView.onDestroy();
  }
  
  @Override
  protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    mapView.onSaveInstanceState(outState);
  }

  private class DrawGeoJson extends AsyncTask<Void, Void, List<Position>> {
    @Override
    protected List<Position> doInBackground(Void... voids) {

      List<Position> points = new ArrayList<>();

      try {
        // Load GeoJSON file
        InputStream inputStream = getAssets().open("trace.geojson");
        BufferedReader rd = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
        StringBuilder sb = new StringBuilder();
        int cp;
        while ((cp = rd.read()) != -1) {
          sb.append((char) cp);
        }

        inputStream.close();

        // Parse JSON
        JSONObject json = new JSONObject(sb.toString());
        JSONArray features = json.getJSONArray("features");
        JSONObject feature = features.getJSONObject(0);
        JSONObject geometry = feature.getJSONObject("geometry");
        if (geometry != null) {
          String type = geometry.getString("type");

          // Our GeoJSON only has one feature: a line string
          if (!TextUtils.isEmpty(type) && type.equalsIgnoreCase("LineString")) {

            // Get the Coordinates
            JSONArray coords = geometry.getJSONArray("coordinates");
            for (int lc = 0; lc < coords.length(); lc++) {
              JSONArray coord = coords.getJSONArray(lc);
              Position position = Position.fromCoordinates(coord.getDouble(0), coord.getDouble(1));
              points.add(position);
            }
          }
        }
      } catch (Exception exception) {
        Log.e(TAG, "Exception Loading GeoJSON: " + exception.toString());
      }

      return points;
    }

    @Override
    protected void onPostExecute(List<Position> points) {
      super.onPostExecute(points);

      drawBeforeMapMatching(points);

      // Convert the route to a linestring
      LineString lineString = LineString.fromCoordinates(points);
      drawMapMatched(lineString, 8);

    }
  }

  private void drawBeforeMapMatching(List<Position> points) {

    LatLng[] pointsArray = new LatLng[points.size()];
    for (int i = 0; i < points.size(); i++) {
      pointsArray[i] = new LatLng(points.get(i).getLatitude(), points.get(i).getLongitude());
    }

    map.addPolyline(new PolylineOptions()
      .add(pointsArray)
      .color(Color.parseColor("#8a8acb"))
      .width(4));
  }

  private void drawMapMatched(LineString lineString, int precision) {
    try {
      // Setup the request using a client.
      MapboxMapMatching client = new MapboxMapMatching.Builder()
        .setAccessToken(MapboxAccountManager.getInstance().getAccessToken())
        .setProfile(DirectionsCriteria.PROFILE_DRIVING)
        .setGpsPrecison(precision)
        .setTrace(lineString)
        .build();

      // Execute the API call and handle the response.
      client.enqueueCall(new Callback<MapMatchingResponse>() {
        @Override
        public void onResponse(Call<MapMatchingResponse> call, Response<MapMatchingResponse> response) {

          // Create a new list to store the map matched coordinates.
          List<LatLng> mapMatchedPoints = new ArrayList<>();

          // Check that the map matching API response is "OK".
          if (response.code() == 200) {
            // Convert the map matched response list from position to latlng coordinates.
            for (int i = 0; i < response.body().getMatchedPoints().length; i++) {
              mapMatchedPoints.add(new LatLng(
                response.body().getMatchedPoints()[i].getLatitude(),
                response.body().getMatchedPoints()[i].getLongitude()));
            }

            // Add the map matched route to the Mapbox map.
            map.addPolyline(new PolylineOptions()
              .addAll(mapMatchedPoints)
              .color(Color.parseColor("#3bb2d0"))
              .width(4));
          } else {
            // If the response code does not response "OK" an error has occurred.
            Log.e(TAG, "Too many coordinates, Profile not found, invalid input, or no match");
          }
        }

        @Override
        public void onFailure(Call<MapMatchingResponse> call, Throwable throwable) {
          Log.e(TAG, "MapboxMapMatching error: " + throwable.getMessage());
        }
      });
    } catch (ServicesException servicesException) {
      Log.e(TAG, "MapboxMapMatching error: " + servicesException.getMessage());
      servicesException.printStackTrace();
    }
  }
}

  
      
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:mapbox="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".examples.mas.MapMatchingActivity">

    <com.mapbox.mapboxsdk.maps.MapView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        mapbox:mapbox_cameraTargetLat="34.01591350351023"
        mapbox:mapbox_cameraTargetLng="-118.4945560781314"
        mapbox:mapbox_styleUrl="mapbox://styles/mapbox/streets-v9"
        mapbox:mapbox_cameraZoom="14.5"/>

</LinearLayout>


    
    

{
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "properties": {},
            "geometry": {
                "type": "LineString",
                "coordinates": [
                    [
                        -118.49956108015326,
                        34.015319897586835
                    ],
                    [
                        -118.49941355865747,
                        34.015175386153295
                    ],
                    [
                        -118.4993169991329,
                        34.015053107055856
                    ],
                    [
                        -118.49916947763707,
                        34.01495750691154
                    ],
                    [
                        -118.49903536718635,
                        34.014884139285925
                    ],
                    [
                        -118.4988610236004,
                        34.014792985480916
                    ],
                    [
                        -118.49867326896933,
                        34.01470405484513
                    ],
                    [
                        -118.49859816711692,
                        34.014599561229055
                    ],
                    [
                        -118.49850697201039,
                        34.01444393220072
                    ],
                    [
                        -118.49837822597769,
                        34.01431275894099
                    ],
                    [
                        -118.4982360688999,
                        34.014217157963
                    ],
                    [
                        -118.49811000507619,
                        34.01413489657018
                    ],
                    [
                        -118.4979866234615,
                        34.01406152823367
                    ],
                    [
                        -118.49778545778538,
                        34.014217157963
                    ],
                    [
                        -118.49764330070758,
                        34.0142994192761
                    ],
                    [
                        -118.4974823681667,
                        34.01444393220072
                    ],
                    [
                        -118.4973026601627,
                        34.014570658716785
                    ],
                    [
                        -118.49719537180209,
                        34.01467515236845
                    ],
                    [
                        -118.49696201961783,
                        34.01485968339663
                    ],
                    [
                        -118.4968547312572,
                        34.01498196277266
                    ],
                    [
                        -118.49669379871632,
                        34.01517760940798
                    ],
                    [
                        -118.49650872629431,
                        34.01529988832609
                    ],
                    [
                        -118.49636388700749,
                        34.015433283308624
                    ],
                    [
                        -118.49619759004858,
                        34.01554444563394
                    ],
                    [
                        -118.49606884401585,
                        34.01565116132932
                    ],
                    [
                        -118.49587840717578,
                        34.01580234166814
                    ],
                    [
                        -118.49570674579883,
                        34.01599131671306
                    ],
                    [
                        -118.4955431310489,
                        34.01610914799874
                    ],
                    [
                        -118.49540633838916,
                        34.01621141652921
                    ],
                    [
                        -118.49525077026628,
                        34.016335917182616
                    ],
                    [
                        -118.49512738865158,
                        34.01641150677596
                    ],
                    [
                        -118.49493963402053,
                        34.016253657842796
                    ],
                    [
                        -118.49478674810669,
                        34.01608913892402
                    ],
                    [
                        -118.4945560781314,
                        34.01591350351023
                    ],
                    [
                        -118.49443806093475,
                        34.01576454660868
                    ],
                    [
                        -118.4942288486316,
                        34.01564449160231
                    ],
                    [
                        -118.49415374677916,
                        34.01552665967168
                    ],
                    [
                        -118.49402231853739,
                        34.0154199438198
                    ],
                    [
                        -118.49380774181621,
                        34.015259869790476
                    ],
                    [
                        -118.49365753811138,
                        34.01512425127944
                    ],
                    [
                        -118.4935368387057,
                        34.015028651215246
                    ],
                    [
                        -118.49318815153376,
                        34.01512202802334
                    ],
                    [
                        -118.49313450735347,
                        34.01537770209138
                    ],
                    [
                        -118.49295748155849,
                        34.01553999914373
                    ],
                    [
                        -118.49282068889875,
                        34.01562003593204
                    ],
                    [
                        -118.49269730728406,
                        34.015753430411515
                    ],
                    [
                        -118.49258197229642,
                        34.01585347613357
                    ],
                    [
                        -118.49241835754653,
                        34.01604022783263
                    ],
                    [
                        -118.49222255628843,
                        34.01607579953825
                    ],
                    [
                        -118.49213672559998,
                        34.01624921138973
                    ],
                    [
                        -118.49200529735822,
                        34.01640261388612
                    ],
                    [
                        -118.49185777586239,
                        34.01647153375803
                    ],
                    [
                        -118.49166733902238,
                        34.016578248288006
                    ],
                    [
                        -118.49151445310851,
                        34.01639594421813
                    ],
                    [
                        -118.49131865185045,
                        34.016253657842796
                    ],
                    [
                        -118.49118185919066,
                        34.016084692462336
                    ],
                    [
                        -118.49102092664977,
                        34.015995763179646
                    ],
                    [
                        -118.49085462969086,
                        34.01581790433479
                    ],
                    [
                        -118.49069906156801,
                        34.015657831055826
                    ],
                    [
                        -118.49053008240004,
                        34.01553999914373
                    ],
                    [
                        -118.49037987869521,
                        34.0154043810802
                    ],
                    [
                        -118.49018139522809,
                        34.01521540472875
                    ],
                    [
                        -118.49000168722405,
                        34.01529544182306
                    ],
                    [
                        -118.4898970810725,
                        34.01541772057146
                    ],
                    [
                        -118.48972810190453,
                        34.01553777589853
                    ],
                    [
                        -118.48954302948253,
                        34.01562225917507
                    ],
                    [
                        -118.48940623682275,
                        34.01567784023221
                    ],
                    [
                        -118.48927480858103,
                        34.01576010012998
                    ],
                    [
                        -118.48918361347452,
                        34.01586903879085
                    ],
                    [
                        -118.48912192266717,
                        34.015993539946386
                    ]
                ]
            }
        }
    ]
}