使用 MapBox 生成两个位置之间的路线和导航信息。

5

我正在尝试为两个指定点在地图上显示一条路线,最终目标是生成逐步说明。 我正在使用MapBox提供的Directions API,并根据此示例构建我的代码。

地图似乎按预期加载,并且在显示地图方面没有错误,但是对于指定的调用或者说整张地图上都没有路线/线路呈现。

我曾尝试使用不同的起点和终点,但仍无法生成提供的示例中所示的期望结果

代码:

@SuppressWarnings("deprecation")
public class MainActivity extends AppCompatActivity implements
        OnMapReadyCallback, PermissionsListener, View.OnClickListener, MapboxMap.OnMapClickListener, MapboxMap.OnMarkerClickListener {

    private MapView mapView;
    private MapboxMap mapboxMap;

    private static final String TAG = "MainActivity";

    private MapboxDirections client;
    private DirectionsRoute currentRoute;
    private static final String ROUTE_LAYER_ID = "route-layer-id";
    private static final String ROUTE_SOURCE_ID = "route-source-id";


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

        // Mapbox access token is configured here.

        Mapbox.getInstance(this, getString(R.string.mapbox_access_token));

        setContentView(R.layout.activity_main);

        mapView = findViewById(R.id.mapView);
        mapView.onCreate(savedInstanceState);
        mapView.getMapAsync(this);

    }


    @Override
    public void onMapReady(@NonNull final MapboxMap mapboxMap) {
        this.mapboxMap = mapboxMap;
        mapboxMap.addOnMapClickListener(this);

        mapboxMap.setStyle(Style.MAPBOX_STREETS,
                new Style.OnStyleLoaded() {
                    @Override
                    public void onStyleLoaded(@NonNull Style style) {

                        enableLocationComponent(style);

                        Point origin = Point.fromLngLat(-3.588098, 37.176164);

                        Point destination = Point.fromLngLat(-3.601845, 37.184080);

                        initSource(style);

                        initLayers(style);

                        getRoute(origin, destination);

                    }
                });


        mapboxMap.setOnMarkerClickListener(this);
    }


    private void initLayers(@NonNull Style loadedMapStyle) {
        LineLayer routeLayer = new LineLayer(ROUTE_LAYER_ID, ROUTE_SOURCE_ID);

        routeLayer.setProperties(
                lineCap(Property.LINE_CAP_ROUND),
                lineJoin(Property.LINE_JOIN_ROUND),
                lineWidth(5f),
                lineColor(Color.parseColor("#009688"))
        );
        loadedMapStyle.addLayer(routeLayer);

    }

    private void initSource(@NonNull Style loadedMapStyle) {
        loadedMapStyle.addSource(new GeoJsonSource(ROUTE_SOURCE_ID,
                FeatureCollection.fromFeatures(new Feature[] {})));

    }

    private void getRoute(Point origin, Point destination) {
        client = MapboxDirections.builder()
                .origin(origin)
                .destination(destination)
                .overview(DirectionsCriteria.OVERVIEW_FULL)
                .profile(DirectionsCriteria.PROFILE_DRIVING)
                .accessToken(Mapbox.getAccessToken())
                .build();

        client.enqueueCall(new Callback<DirectionsResponse>() {
            @Override
            public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
// You can get the generic HTTP info about the response
                Timber.d("Response code: " + response.code());
                if (response.body() == null) {
                    Timber.e("No routes found, make sure you set the right user and access token.");
                    return;
                } else if (response.body().routes().size() < 1) {
                    Timber.e("No routes found");
                    return;
                }

// Get the directions route
                currentRoute = response.body().routes().get(0);

// Make a toast which displays the route's distance
                /*Toast.makeText(MainActivity.this, String.format(
                        getString(R.string.directions_activity_toast_message),
                        currentRoute.distance()), Toast.LENGTH_SHORT).show();*/

                if (mapboxMap != null) {
                    mapboxMap.getStyle(new Style.OnStyleLoaded() {
                        @Override
                        public void onStyleLoaded(@NonNull Style style) {

// Retrieve and update the source designated for showing the directions route
                            GeoJsonSource source = style.getSourceAs(ROUTE_SOURCE_ID);

// Create a LineString with the directions route's geometry and
// reset the GeoJSON source for the route LineLayer source
                            if (source != null) {
                                Timber.d("onResponse: source != null");
                                source.setGeoJson(FeatureCollection.fromFeature(
                                        Feature.fromGeometry(LineString.fromPolyline(currentRoute.geometry(), PRECISION_6))));
                            }
                        }
                    });
                }
            }

            @Override
            public void onFailure(Call<DirectionsResponse> call, Throwable throwable) {
                Timber.e("Error: " + throwable.getMessage());
                Toast.makeText(MainActivity.this, "Error: " + throwable.getMessage(),
                        Toast.LENGTH_SHORT).show();
            }
        });
    }

有任何 Toast 显示吗?有任何 Timber 日志传递到 logcat 吗?当您搜索 Mbgl 时,您的 logcat 中是否有任何内容? - langsmith
@langsmith 谢谢。没有出现任何木材日志。这是搜索“Mbgl”时的输出:https://pastebin.com/pmEVVC6D - Enigmatic
以下是我的答案/代码,对你有用吗? - langsmith
@langsmith 看起来这个应用程序需要重新安装几次才能正常工作,但我已经接受了你的答案。谢谢! - Enigmatic
@langsmith 现在我正在努力让navigationLauncher工作 ;) - Enigmatic
1个回答

7

我采用了你的代码,并将其放入Mapbox演示应用程序的SimpleMapViewActivityhttps://docs.mapbox.com/android/maps/examples/create-a-simple-map-view/

你的代码和我的代码之间唯一的主要区别是,我将this.mapboxMap = mapboxMap;mapboxMap.addOnMapClickListener(this); 放在OnStyleLoaded()回调区域而不是onMapReady()区域。 也许这就是你需要的。请尝试并查看结果。我添加了enableLocationComponent()代码和其他权限方法覆盖。

除了显示LocationComponent之外,我不确定你如何调整https://docs.mapbox.com/android/java/examples/show-directions-on-a-map/中的代码。 https://docs.mapbox.com/android/java/examples/show-directions-on-a-map/ 应该可以很好地运行,所以也许你可以通过解释你如何调整https://docs.mapbox.com/android/java/examples/show-directions-on-a-map/来帮助我。

看看我的最终结果:https://imgur.com/a/QJeK0vB

package com.mapbox.mapboxandroiddemo.examples.basics;

import android.graphics.Color;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.mapbox.android.core.permissions.PermissionsListener;
import com.mapbox.android.core.permissions.PermissionsManager;
import com.mapbox.api.directions.v5.DirectionsCriteria;
import com.mapbox.api.directions.v5.MapboxDirections;
import com.mapbox.api.directions.v5.models.DirectionsResponse;
import com.mapbox.api.directions.v5.models.DirectionsRoute;
import com.mapbox.geojson.Feature;
import com.mapbox.geojson.FeatureCollection;
import com.mapbox.geojson.LineString;
import com.mapbox.geojson.Point;
import com.mapbox.mapboxandroiddemo.R;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.location.LocationComponent;
import com.mapbox.mapboxsdk.location.LocationComponentActivationOptions;
import com.mapbox.mapboxsdk.location.modes.CameraMode;
import com.mapbox.mapboxsdk.location.modes.RenderMode;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.style.layers.LineLayer;
import com.mapbox.mapboxsdk.style.layers.Property;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;

import java.util.List;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;


import static com.mapbox.core.constants.Constants.PRECISION_6;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineCap;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineColor;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineJoin;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineWidth;


/**
 * The most basic example of adding a map to an activity.
 */
public class SimpleMapViewActivity extends AppCompatActivity implements
  OnMapReadyCallback, PermissionsListener, View.OnClickListener, MapboxMap.OnMapClickListener, MapboxMap.OnMarkerClickListener {

  private MapView mapView;

  private static final String TAG = "SimpleMapViewActivity";

  private MapboxDirections client;
  private DirectionsRoute currentRoute;
  private static final String ROUTE_LAYER_ID = "route-layer-id";
  private static final String ROUTE_SOURCE_ID = "route-source-id";
  private PermissionsManager permissionsManager;
  private MapboxMap mapboxMap;

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

    // Mapbox access token is configured here.

    Mapbox.getInstance(this, getString(R.string.access_token));

    setContentView(R.layout.activity_basic_simple_mapview);

    mapView = findViewById(R.id.mapView);
    mapView.onCreate(savedInstanceState);
    mapView.getMapAsync(this);
  }


  @Override
  public void onMapReady(@NonNull final MapboxMap mapboxMap) {
    mapboxMap.setStyle(Style.MAPBOX_STREETS,
      new Style.OnStyleLoaded() {
        @Override
        public void onStyleLoaded(@NonNull Style style) {
          SimpleMapViewActivity.this.mapboxMap = mapboxMap;

          enableLocationComponent(style);

          Point origin = Point.fromLngLat(-3.588098, 37.176164);

          Point destination = Point.fromLngLat(-3.601845, 37.184080);

          initSource(style);

          initLayers(style);

          getRoute(origin, destination);

          mapboxMap.addOnMapClickListener(SimpleMapViewActivity.this);

          mapboxMap.setOnMarkerClickListener(SimpleMapViewActivity.this);

        }
      });
  }


  private void initLayers(@NonNull Style loadedMapStyle) {
    LineLayer routeLayer = new LineLayer(ROUTE_LAYER_ID, ROUTE_SOURCE_ID);

    routeLayer.setProperties(
      lineCap(Property.LINE_CAP_ROUND),
      lineJoin(Property.LINE_JOIN_ROUND),
      lineWidth(5f),
      lineColor(Color.parseColor("#009688"))
    );
    loadedMapStyle.addLayer(routeLayer);

  }

  private void initSource(@NonNull Style loadedMapStyle) {
    loadedMapStyle.addSource(new GeoJsonSource(ROUTE_SOURCE_ID,
      FeatureCollection.fromFeatures(new Feature[] {})));

  }

  private void getRoute(Point origin, Point destination) {
    client = MapboxDirections.builder()
      .origin(origin)
      .destination(destination)
      .overview(DirectionsCriteria.OVERVIEW_FULL)
      .profile(DirectionsCriteria.PROFILE_DRIVING)
      .accessToken(Mapbox.getAccessToken())
      .build();

    client.enqueueCall(new Callback<DirectionsResponse>() {
      @Override
      public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
// You can get the generic HTTP info about the response
        Log.d(TAG, "Response code: " + response.code());
        if (response.body() == null) {
          Log.d(TAG, "No routes found, make sure you set the right user and access token.");
          return;
        } else if (response.body().routes().size() < 1) {
          Log.d(TAG, "No routes found");
          return;
        }

// Get the directions route
        currentRoute = response.body().routes().get(0);

// Make a toast which displays the route's distance
                /*Toast.makeText(SimpleMapViewActivity.this, String.format(
                        getString(R.string.directions_activity_toast_message),
                        currentRoute.distance()), Toast.LENGTH_SHORT).show();*/

        if (mapboxMap != null) {
          mapboxMap.getStyle(new Style.OnStyleLoaded() {
            @Override
            public void onStyleLoaded(@NonNull Style style) {

// Retrieve and update the source designated for showing the directions route
              GeoJsonSource source = style.getSourceAs(ROUTE_SOURCE_ID);

// Create a LineString with the directions route's geometry and
// reset the GeoJSON source for the route LineLayer source
              if (source != null) {
                Log.d(TAG, "onResponse: source != null");
                source.setGeoJson(FeatureCollection.fromFeature(
                  Feature.fromGeometry(LineString.fromPolyline(currentRoute.geometry(), PRECISION_6))));
              }
            }
          });
        }
      }

      @Override
      public void onFailure(Call<DirectionsResponse> call, Throwable throwable) {
        Log.d(TAG, "Error: " + throwable.getMessage());
        Toast.makeText(SimpleMapViewActivity.this, "Error: " + throwable.getMessage(),
          Toast.LENGTH_SHORT).show();
      }
    });
  }

  @Override
  public void onClick(View view) {

  }

  @SuppressWarnings( {"MissingPermission"})
  private void enableLocationComponent(@NonNull Style loadedMapStyle) {
    // Check if permissions are enabled and if not request
    if (PermissionsManager.areLocationPermissionsGranted(this)) {

      // Get an instance of the component
      LocationComponent locationComponent = mapboxMap.getLocationComponent();

      // Activate with options
      locationComponent.activateLocationComponent(
        LocationComponentActivationOptions.builder(this, loadedMapStyle).build());

      // Enable to make component visible
      locationComponent.setLocationComponentEnabled(true);

      // Set the component's camera mode
      locationComponent.setCameraMode(CameraMode.TRACKING);

      // Set the component's render mode
      locationComponent.setRenderMode(RenderMode.COMPASS);
    } else {
      permissionsManager = new PermissionsManager(this);
      permissionsManager.requestLocationPermissions(this);
    }
  }


  @Override
  public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
  }

  @Override
  public void onExplanationNeeded(List<String> permissionsToExplain) {
    Toast.makeText(this, R.string.user_location_permission_explanation, Toast.LENGTH_LONG).show();
  }

  @Override
  public void onPermissionResult(boolean granted) {
    if (granted) {
      mapboxMap.getStyle(new Style.OnStyleLoaded() {
        @Override
        public void onStyleLoaded(@NonNull Style style) {
          enableLocationComponent(style);
        }
      });
    } else {
      Toast.makeText(this, R.string.user_location_permission_not_granted, Toast.LENGTH_LONG).show();
      finish();
    }
  }

  @Override
  public boolean onMapClick(@NonNull LatLng point) {


    return true;
  }

  @Override
  public boolean onMarkerClick(@NonNull Marker marker) {
    return false;
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接