You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android开发求助:基于PlaceAutocompleteFragment输入绘制地图路径

嗨,我来帮你搞定这个问题!其实从PlaceAutocompleteFragment获取地点后绘制路径,核心逻辑和点击地图选点的方式是相通的,只是获取起点终点坐标的入口不同而已。下面我给你一步步拆解实现过程:

第一步:从PlaceAutocompleteFragment获取起点/终点的经纬度

首先你需要处理PlaceAutocomplete的返回结果,拿到选中地点的LatLng坐标,把起点和终点分别存起来。这里是示例代码:

private static final int REQUEST_ORIGIN = 1;
private static final int REQUEST_DESTINATION = 2;
private LatLng mOriginLatLng;
private LatLng mDestinationLatLng;
private GoogleMap mMap;

// 启动起点选择的自动完成框
public void launchOriginAutocomplete() {
    try {
        Intent intent = new PlaceAutocomplete.IntentBuilder(PlaceAutocomplete.MODE_FULLSCREEN)
                .build(this);
        startActivityForResult(intent, REQUEST_ORIGIN);
    } catch (Exception e) {
        e.printStackTrace();
        Toast.makeText(this, "无法启动地点选择", Toast.LENGTH_SHORT).show();
    }
}

// 启动终点选择的自动完成框
public void launchDestinationAutocomplete() {
    try {
        Intent intent = new PlaceAutocomplete.IntentBuilder(PlaceAutocomplete.MODE_FULLSCREEN)
                .build(this);
        startActivityForResult(intent, REQUEST_DESTINATION);
    } catch (Exception e) {
        e.printStackTrace();
        Toast.makeText(this, "无法启动地点选择", Toast.LENGTH_SHORT).show();
    }
}

// 处理自动完成框的返回结果
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK && data != null) {
        Place selectedPlace = PlaceAutocomplete.getPlace(this, data);
        if (requestCode == REQUEST_ORIGIN) {
            mOriginLatLng = selectedPlace.getLatLng();
            // 给起点加个标记
            mMap.addMarker(new MarkerOptions().position(mOriginLatLng).title("起点"));
        } else if (requestCode == REQUEST_DESTINATION) {
            mDestinationLatLng = selectedPlace.getLatLng();
            mMap.addMarker(new MarkerOptions().position(mDestinationLatLng).title("终点"));
            // 当起点和终点都拿到后,就可以请求路径了
            if (mOriginLatLng != null) {
                fetchRouteData();
            } else {
                Toast.makeText(this, "请先选择起点", Toast.LENGTH_SHORT).show();
            }
        }
    }
}
第二步:调用Google Directions API获取路径数据

要绘制路径,你需要先从Google Directions API拿到路径的坐标点集合。这里我用OkHttp来发送网络请求,你需要先在build.gradle里添加依赖:

implementation 'com.squareup.okhttp3:okhttp:4.10.0'

然后写请求路径的方法,以及解析返回的JSON数据,解码Polyline字符串(API返回的路径点是编码后的字符串):

private void fetchRouteData() {
    String apiKey = "你的Google Maps API Key"; // 替换成你自己的API Key
    String requestUrl = String.format(
            "https://maps.googleapis.com/maps/api/directions/json?origin=%f,%f&destination=%f,%f&key=%s",
            mOriginLatLng.latitude, mOriginLatLng.longitude,
            mDestinationLatLng.latitude, mDestinationLatLng.longitude,
            apiKey
    );

    OkHttpClient client = new OkHttpClient();
    Request request = new Request.Builder().url(requestUrl).build();

    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(@NotNull Call call, @NotNull IOException e) {
            e.printStackTrace();
            runOnUiThread(() -> Toast.makeText(MainActivity.this, "获取路径失败,请检查网络", Toast.LENGTH_SHORT).show());
        }

        @Override
        public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
            if (!response.isSuccessful()) {
                runOnUiThread(() -> Toast.makeText(MainActivity.this, "请求路径失败", Toast.LENGTH_SHORT).show());
                return;
            }

            String jsonResponse = response.body().string();
            try {
                JSONObject jsonObject = new JSONObject(jsonResponse);
                JSONArray routes = jsonObject.getJSONArray("routes");
                if (routes.length() == 0) {
                    runOnUiThread(() -> Toast.makeText(MainActivity.this, "未找到可行路径", Toast.LENGTH_SHORT).show());
                    return;
                }

                // 解析路径的Polyline点
                JSONObject route = routes.getJSONObject(0);
                JSONArray legs = route.getJSONArray("legs");
                JSONObject leg = legs.getJSONObject(0);
                JSONArray steps = leg.getJSONArray("steps");

                List<LatLng> pathPoints = new ArrayList<>();
                for (int i = 0; i < steps.length(); i++) {
                    JSONObject step = steps.getJSONObject(i);
                    JSONObject polyline = step.getJSONObject("polyline");
                    String encodedPoints = polyline.getString("points");
                    pathPoints.addAll(decodePolyline(encodedPoints));
                }

                // 在UI线程绘制路径
                runOnUiThread(() -> drawRouteOnMap(pathPoints));

            } catch (JSONException e) {
                e.printStackTrace();
                runOnUiThread(() -> Toast.makeText(MainActivity.this, "解析路径数据失败", Toast.LENGTH_SHORT).show());
            }
        }
    });
}

// 解码Polyline编码字符串的工具方法
private List<LatLng> decodePolyline(String encoded) {
    List<LatLng> polylinePoints = new ArrayList<>();
    int index = 0;
    int lat = 0, lng = 0;
    int length = encoded.length();

    while (index < length) {
        int shift = 0;
        int result = 0;
        int b;
        do {
            b = encoded.charAt(index++) - 63;
            result |= (b & 0x1F) << shift;
            shift += 5;
        } while (b >= 0x20);
        int deltaLat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
        lat += deltaLat;

        shift = 0;
        result = 0;
        do {
            b = encoded.charAt(index++) - 63;
            result |= (b & 0x1F) << shift;
            shift += 5;
        } while (b >= 0x20);
        int deltaLng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
        lng += deltaLng;

        polylinePoints.add(new LatLng((double) lat / 1E5, (double) lng / 1E5));
    }
    return polylinePoints;
}
第三步:在GoogleMap上绘制路径

拿到解码后的坐标点集合后,就可以用PolylineOptions在地图上画出路径了,还可以调整地图视角让起点终点都显示:

private void drawRouteOnMap(List<LatLng> pathPoints) {
    PolylineOptions polylineOptions = new PolylineOptions()
            .addAll(pathPoints)
            .width(12) // 设置路径宽度
            .color(Color.parseColor("#1E88E5")) // 设置路径颜色
            .geodesic(true); // 让路径沿着地球曲率绘制

    // 添加路径到地图
    mMap.addPolyline(polylineOptions);

    // 调整地图视角,包含起点和终点
    LatLngBounds.Builder boundsBuilder = new LatLngBounds.Builder();
    boundsBuilder.include(mOriginLatLng);
    boundsBuilder.include(mDestinationLatLng);
    LatLngBounds bounds = boundsBuilder.build();

    // 移动相机到合适的位置,100是屏幕边距(像素)
    mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 100));
}
重要注意事项
  • 确保你在Google Cloud Console已经启用了Directions API,并且你的API Key配置了正确的权限和限制(比如绑定你的应用包名和SHA-1,防止被滥用)
  • 别忘了在AndroidManifest.xml中添加网络权限:
<uses-permission android:name="android.permission.INTERNET" />
  • 可以添加一些异常处理,比如用户未选择起点就选终点的情况,或者API请求返回空路径的情况

内容的提问来源于stack exchange,提问作者Ebet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:02:25