Mapbox Android:如何获取从当前位置到您选择的目的地的路线?

Posted

技术标签:

【中文标题】Mapbox Android:如何获取从当前位置到您选择的目的地的路线?【英文标题】:Mapbox Android: How to get directions from current location to a destination you choose? 【发布时间】:2016-09-06 02:20:13 【问题描述】:

好的,所以我对 Mapbox 还很陌生,在此之前我使用过 GMaps,但我发现 Mapbox 更能满足我的需求,问题是我碰壁了。

我使用了他们网站上可用示例的组合,例如

https://www.mapbox.com/android-sdk/examples/geocoding 和 https://www.mapbox.com/android-sdk/examples/directions

我试图让用户搜索目的地,然后将其转换为用于在地图中绘制的坐标。然后我想画一条从他们当前位置到目的地的路线,这就是我的问题所在。

 mapView.getMapAsync(new OnMapReadyCallback() 
        @Override
        public void onMapReady(MapboxMap mapboxMap) 

            map = mapboxMap;


            // Set the origin waypoint to the devices location
            Position origin = Position.fromCoordinates(mapboxMap.getMyLocation().getLongitude(), mapboxMap.getMyLocation().getLatitude());

            // Set the destination waypoint to the location point long clicked by the user
            final Position destination = updateMap(feature.getLongitude(), feature.getLatitude());

            mapboxMap.addMarker(new MarkerOptions()
                    .position(new LatLng(origin.getLatitude(), origin.getLongitude()))
                    .title("Origin")
                    .snippet("Alhambra"));
            mapboxMap.addMarker(new MarkerOptions()
                    .position(new LatLng(latitude, destination.getLongitude()))
                    .title("Destination")
                    .snippet("Plaza del Triunfo"));

            // Get route from API
            try 
                getRoute(origin, destination);
             catch (ServicesException e) 
                e.printStackTrace();
            
        
    );

    AndroidGeocoder geocoder = new AndroidGeocoder(context, Locale.getDefault());
    geocoder.setAccessToken(MAPBOX_ACCESS_TOKEN);
    addresses = geocoder.getFromLocation(
            location.getLatitude(),
            location.getLongitude(),
            1);

    // Set up autocomplete widget
    GeocoderAutoCompleteView autocomplete = (GeocoderAutoCompleteView) findViewById(R.id.query);
    autocomplete.setAccessToken("pk.eyJ1IjoiYmV1dHJveCIsImEiOiJjaW5ybzlwYnQwMGlqdnhtMno3cmtwNTlqIn0.y16mZzmertL4-eEfQNGeqQ");
    autocomplete.setType(GeocodingCriteria.TYPE_POI);
    autocomplete.setOnFeatureListener(new GeocoderAutoCompleteView.OnFeatureListener() 
        @Override
        public void OnFeatureClick(GeocodingFeature feature) 
            Position position = feature.asPosition();
            updateMap(position.getLatitude(), position.getLongitude());
        
    );



private void getRoute(Position origin, Position destination) throws ServicesException 

    MapboxDirections client = new MapboxDirections.Builder()
            .setOrigin(origin)
            .setDestination(destination)
            .setProfile(DirectionsCriteria.PROFILE_CYCLING)
            .setAccessToken("pk.eyJ1IjoiYmV1dHJveCIsImEiOiJjaW5ybzlwYnQwMGlqdnhtMno3cmtwNTlqIn0.y16mZzmertL4-eEfQNGeqQ")
            .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.e(TAG, "No routes found, make sure you set the right user and access token.");
                return;
            

            // Display some info about the route
            currentRoute = response.body().getRoutes().get(0);
            Log.d(TAG, "Distance: " + currentRoute.getDistance());
            Toast.makeText(MainActivity.this, "Route is " +  currentRoute.getDistance() + " meters long.", Toast.LENGTH_SHORT).show();

            // Draw the route on the map
            drawRoute(currentRoute);
        

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


private void drawRoute(DirectionsRoute route) 
    // Convert LineString coordinates into LatLng[]
    LineString lineString = LineString.fromPolyline(route.getGeometry(), Constants.OSRM_PRECISION_V5);
    List<Position> coordinates = lineString.getCoordinates();
    LatLng[] points = new LatLng[coordinates.size()];
    for (int i = 0; i < coordinates.size(); i++) 
        points[i] = new LatLng(
                coordinates.get(i).getLatitude(),
                coordinates.get(i).getLongitude());
    

    // Draw Points on MapView
    map.addPolyline(new PolylineOptions()
            .add(points)
            .color(Color.parseColor("#009688"))
            .width(5));



private void myLocation() 

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) 
        // TODO: Consider calling
        //    ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
        //                                          int[] grantResults)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.
        return;
    

    mapView.setMyLocationEnabled(true);
    mapView.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
    mapView.getMyLocation();

所以这里的某个地方是我的问题,我在网上找不到太多关于 Mapbox 的信息,因为他们的新 sdk 与以前的版本非常不同,主要是因为 MapView 和 MapboxMap 现在是分开的(这仍然让我感到困惑)。

任何帮助将不胜感激:D

:编辑:我主要是在设置目的地方面苦苦挣扎,因此我的很多当前变量都混淆了。如果你需要解释,我很乐意。

【问题讨论】:

请粘贴你的logcat 我的 logcat 似乎不起作用,“...调试器不再处于活动状态”是它所说的,但这是我的消息选项卡所说的:错误:(77、56)错误:不能查找符号变量特征 错误:(77, 80) 错误:找不到符号变量特征 错误:(84, 46) 错误:找不到符号变量纬度 错误:(97, 56) 错误:找不到符号变量上下文 错误:(99 , 9) 错误:找不到符号变量地址 错误:(100, 17) 错误: 找不到符号变量位置 错误:(101, 17) 错误: 找不到符号变量位置 错误:(186, 16) 错误: setMyLocationEnabled(boolean) is在 MapView 中不公开;无法从外部包访问错误:(187, 16) 错误: setMyLocationTrackingMode(int) 在 MapView 中不公开;无法从外部包访问错误:(188, 16) 错误:getMyLocation() 在 MapView 中不公开;无法从外部包访问:app:compileDebugJavaWithJavac FAILED Error:Execution failed for task ':app:compileDebugJavaWithJavac'。 您是否尝试清理并重建项目? 嗯,我之前试过了,但没用,但现在可以了,给你 :) txt.do/5brjg 【参考方案1】:

您的代码中存在一些错误,最大的问题是您仍在使用MapView 来获取位置信息,而您可以改用MapboxMap。这是一些粗略的代码,可以满足您的要求。它不会像你应该的那样检查用户权限,但它会告诉你如何做 Mapbox 的东西。

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import com.mapbox.mapboxsdk.annotations.MarkerOptions;
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.Constants;
import com.mapbox.services.android.geocoder.ui.GeocoderAutoCompleteView;
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.v5.DirectionsCriteria;
import com.mapbox.services.directions.v5.MapboxDirections;
import com.mapbox.services.directions.v5.models.DirectionsResponse;
import com.mapbox.services.directions.v5.models.DirectionsRoute;
import com.mapbox.services.geocoding.v5.GeocodingCriteria;
import com.mapbox.services.geocoding.v5.models.GeocodingFeature;

import java.util.List;

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

public class MainActivity extends Activity 

    private final static String TAG = "MainActivity";

    private MapView mapView;
    private MapboxMap map;
    private DirectionsRoute currentRoute;

    private Position origin;
    private Position destination;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

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

                mapboxMap.setMyLocationEnabled(true);

                // Set up autocomplete widget
                GeocoderAutoCompleteView autocomplete = (GeocoderAutoCompleteView) findViewById(R.id.query);
            autocomplete.setAccessToken("<your access token>");
            autocomplete.setType(GeocodingCriteria.TYPE_POI);
            autocomplete.setOnFeatureListener(new GeocoderAutoCompleteView.OnFeatureListener() 
                @Override
                public void OnFeatureClick(GeocodingFeature feature) 

                    if(map.getMyLocation() != null) 
                        // Set the origin as user location only if we can get their location
                        origin = Position.fromCoordinates(map.getMyLocation().getLongitude(), map.getMyLocation().getLatitude());
                    else
                        return;
                    

                    destination = feature.asPosition();

                    // Add origin and destination to the map
                    map.addMarker(new MarkerOptions()
                            .position(new LatLng(origin.getLatitude(), origin.getLongitude())));
                    map.addMarker(new MarkerOptions()
                            .position(new LatLng(destination.getLatitude(), destination.getLongitude())));

                    // Get route from API
                    try 
                        getRoute(origin, destination);
                     catch (ServicesException e) 
                        e.printStackTrace();
                    

                
            );
        
    );


private void getRoute(Position origin, Position destination) throws ServicesException 

    MapboxDirections client = new MapboxDirections.Builder()
            .setOrigin(origin)
            .setDestination(destination)
            .setProfile(DirectionsCriteria.PROFILE_CYCLING)
            .setAccessToken("<your access token>")
            .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.e(TAG, "No routes found, make sure you set the right user and access token.");
                return;
            

            // Print some info about the route
            currentRoute = response.body().getRoutes().get(0);
            Log.d(TAG, "Distance: " + currentRoute.getDistance());
            Toast.makeText(MainActivity.this, "Route is " +  currentRoute.getDistance() + " meters long.", Toast.LENGTH_SHORT).show();

            // Draw the route on the map
            drawRoute(currentRoute);
        

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


private void drawRoute(DirectionsRoute route) 
    // Convert LineString coordinates into LatLng[]
    LineString lineString = LineString.fromPolyline(route.getGeometry(), Constants.OSRM_PRECISION_V5);
    List<Position> coordinates = lineString.getCoordinates();
    LatLng[] points = new LatLng[coordinates.size()];
    for (int i = 0; i < coordinates.size(); i++) 
        points[i] = new LatLng(
                coordinates.get(i).getLatitude(),
                coordinates.get(i).getLongitude());
    

    // Draw Points on MapView
    map.addPolyline(new PolylineOptions()
            .add(points)
            .color(Color.parseColor("#009688"))
            .width(5));


@Override
public void onResume() 
    super.onResume();
    mapView.onResume();


@Override
public void onPause() 
    super.onPause();
    mapView.onPause();


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


@Override
protected void onDestroy() 
    super.onDestroy();
    mapView.onDestroy();


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

希望这会有所帮助!

【讨论】:

谢谢你,我会试一试,让你知道:D 它工作得很好,但不幸的是,我的地理编码似乎无法在全球范围内工作。所以很遗憾,我无法在自己的国家进行测试,您有什么建议吗? 好的,再次感谢,我目前居住在南非。它说“地点”是否意味着搜索南非地址将没有结果? 您对我如何解决这个问题有什么建议吗?

以上是关于Mapbox Android:如何获取从当前位置到您选择的目的地的路线?的主要内容,如果未能解决你的问题,请参考以下文章

Mapbox Flutter:初始相机位置显示不正确的位置

Mapbox:我想使用 Locationengine 来获取用户的当前位置,但它给我一个错误

MapBox 用户位置图标 (Android)

React Native MapBox 获取点击位置

我如何从 struct 获取纬度和经度并在 mapbox Swift 上显示它们

如何在 MapBox(Z-Order)上的地图标记后面设置当前位置指示器?