android - 如何在两点之间沿着现有道路绘制路线?

标签 android google-maps google-maps-android-api-2

我想在我的 Android 应用中显示两个位置之间的行车路线。我只想在路段顶部绘制路线。

堆栈溢出本身有几个答案,所有答案都使用相同的方法。使用谷歌方向 API 获取从起点到目的地的路线,并在返回的点之间绘制一条折线。以下是使用此方法的一些答案。

https://stackoverflow.com/a/17007360/1015678

https://stackoverflow.com/a/40563930/1015678

但是,上述方法的问题是,当道路不直时,黎明死记硬背并不总是在道路顶部,因为方向 API 只返回您需要从一条道路转向另一条道路的点(在路口) .它不会在同一路段的弯道中提供点详细信息。因此,当我在道路有很多弯道的区域使用上述方法时,绘制的路线几乎总是不在路段的顶部。

我找到了 this使用 javascript API 来回答我需要做的事情。在此解决方案中,绘制的路线很好地遵循道路,类似于 google maps android 应用程序。有人知道这是否可以在 android 应用中实现?

Google Maps android 应用程序可以很好地绘制从一个点到另一个点的路线,使路线保持在道路上。有谁知道谷歌地图是如何做到的?是否使用了其他未公开的 API?

最佳答案

确实,您可以使用 Directions API 网络服务提供的结果在 Google Maps Android API 中绘制精确路线。如果您阅读了 Directions API 的文档您将看到该响应包含有关路线段和步骤的信息。每个步骤都有一个字段 polyline,在文档中描述为

polyline contains a single points object that holds an encoded polyline representation of the step. This polyline is an approximate (smoothed) path of the step.

因此,解决您的问题的主要思路是从 Directions API 获得响应,循环遍历路线支路和步骤,对于每个步骤获取 encoded polyline并将其解码为坐标列表。完成后,您将获得组成路线的所有坐标的列表,不仅是每个步骤的起点和终点。

为简单起见,我建议将 Java 客户端库用于 Google Maps Web 服务:

https://github.com/googlemaps/google-maps-services-java

使用这个库,您可以避免为折线实现自己的异步任务和解码功能。阅读文档以了解如何在项目中添加客户端库。

在 Gradle 中应该类似于

compile 'com.google.maps:google-maps-services:(insert latest version)'
compile 'org.slf4j:slf4j-nop:1.7.25'

我创建了一个简单的示例来演示它是如何工作的。看看我在代码中的注释

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {

    private GoogleMap mMap;
    private String TAG = "so47492459";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

        LatLng barcelona = new LatLng(41.385064,2.173403);
        mMap.addMarker(new MarkerOptions().position(barcelona).title("Marker in Barcelona"));

        LatLng madrid = new LatLng(40.416775,-3.70379);
        mMap.addMarker(new MarkerOptions().position(madrid).title("Marker in Madrid"));

        LatLng zaragoza = new LatLng(41.648823,-0.889085);

        //Define list to get all latlng for the route
        List<LatLng> path = new ArrayList();


        //Execute Directions API request
        GeoApiContext context = new GeoApiContext.Builder()
                .apiKey("YOUR_API_KEY")
                .build();
        DirectionsApiRequest req = DirectionsApi.getDirections(context, "41.385064,2.173403", "40.416775,-3.70379");
        try {
            DirectionsResult res = req.await();

            //Loop through legs and steps to get encoded polylines of each step
            if (res.routes != null && res.routes.length > 0) {
                DirectionsRoute route = res.routes[0];

                if (route.legs !=null) {
                    for(int i=0; i<route.legs.length; i++) {
                        DirectionsLeg leg = route.legs[i];
                        if (leg.steps != null) {
                            for (int j=0; j<leg.steps.length;j++){
                                DirectionsStep step = leg.steps[j];
                                if (step.steps != null && step.steps.length >0) {
                                    for (int k=0; k<step.steps.length;k++){
                                        DirectionsStep step1 = step.steps[k];
                                        EncodedPolyline points1 = step1.polyline;
                                        if (points1 != null) {
                                            //Decode polyline and add points to list of route coordinates
                                            List<com.google.maps.model.LatLng> coords1 = points1.decodePath();
                                            for (com.google.maps.model.LatLng coord1 : coords1) {
                                                path.add(new LatLng(coord1.lat, coord1.lng));
                                            }
                                        }
                                    }
                                } else {
                                    EncodedPolyline points = step.polyline;
                                    if (points != null) {
                                        //Decode polyline and add points to list of route coordinates
                                        List<com.google.maps.model.LatLng> coords = points.decodePath();
                                        for (com.google.maps.model.LatLng coord : coords) {
                                            path.add(new LatLng(coord.lat, coord.lng));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch(Exception ex) {
            Log.e(TAG, ex.getLocalizedMessage());
        }

        //Draw the polyline
        if (path.size() > 0) {
            PolylineOptions opts = new PolylineOptions().addAll(path).color(Color.BLUE).width(5);
            mMap.addPolyline(opts);
        }

        mMap.getUiSettings().setZoomControlsEnabled(true);

        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(zaragoza, 6));
    }
}

请注意,对于 Web 服务,您必须创建单独的 API key ,具有 Android 应用限制的 API key 将不适用于 Web 服务。

我的例子的结果显示在屏幕截图中

enter image description here

您也可以从

下载完整的示例项目

https://github.com/xomena-so/so47492459

别忘了用你的替换 API key 。

我希望这会有所帮助!

关于android - 如何在两点之间沿着现有道路绘制路线?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47492459/

相关文章:

java - 创建一个 4 向 ScrollView

javascript - Gmap3 多个标记加载缓慢。怎么解决?

php - 通过AJAX接收和显示html数据

ios - 警告 : New version of Google Maps SDK for iOS available - How do I update?

java - 如何在 android 谷歌地图版本 2 中的 2 个地理点之间画线?

javascript - cordova navigator.app.close() 将应用程序保持在后台

android - 阻止应用程序显示在 android kitkat 4.4.2 上的最近应用程序列表中

android - 等待调用 onMapReady()

android - 使用 android fused location api 的 MyLocation 上未显示蓝点和圆圈

android - 如何以某个角度倾斜子布局