Android Studio(Java)中Maps Directions API路线不显示求助
问题诊断与修复方案
从代码和描述来看,Directions API调用成功(Cloud后台有调用量)但地图不显示路线,核心问题集中在路径点收集、线程操作和标记管理上,以下是具体诊断和修复方案:
核心问题分析
- 路径点收集不完整:仅提取每个
DirectionsStep的startLocation,未解析step中包含完整路线的encodedPolyline,导致生成的折线只有零散节点,无法形成连续路线。 - 后台线程操作UI:Google Maps Services的回调运行在后台线程,直接调用
mMap.addPolyline违反Android UI线程规则,折线无法正确绘制。 - 初始Marker未加入列表:
onMapReady中首次添加的"Ubicación actual" Marker未加入markers集合,导致点击按钮时getCurrentLocation可能返回null。 - 错误回调未处理:
onFailure无任何日志提示,无法排查API返回的潜在错误。
修复后的完整代码
package com.example.mapa; import android.Manifest; import android.content.pm.PackageManager; import android.graphics.Color; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.view.View; import android.widget.Button; import android.widget.Toast; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import androidx.fragment.app.FragmentActivity; import com.example.mapa.databinding.RutaLocalBinding; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; import com.google.android.gms.location.FusedLocationProviderClient; import com.google.android.gms.location.LocationServices; import com.google.android.gms.maps.model.Polyline; import com.google.android.gms.maps.model.PolylineOptions; import com.google.maps.DirectionsApi; import com.google.maps.DirectionsApiRequest; import com.google.maps.GeoApiContext; import com.google.maps.PendingResult; import com.google.maps.android.PolyUtil; import com.google.maps.model.DirectionsResult; import com.google.maps.model.DirectionsRoute; import com.google.maps.model.DirectionsStep; import com.google.maps.model.TravelMode; import java.util.ArrayList; import java.util.List; public class RutaLocal extends FragmentActivity implements OnMapReadyCallback { private GoogleMap mMap; private RutaLocalBinding binding; private FusedLocationProviderClient fusedLocationProviderClient; private Polyline routePolyline; private List<Marker> markers = new ArrayList<>(); private Handler mainHandler = new Handler(Looper.getMainLooper()); // 主线程Handler @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = RutaLocalBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); Button btnRuta = binding.btnRuta; btnRuta.setOnClickListener(v -> { LatLng currentLocation = getCurrentLocation(); LatLng destination = getDestinationLocation(); if (currentLocation != null && destination != null) { getDirections(currentLocation, destination); } else { Toast.makeText(RutaLocal.this, "No hay puntos", Toast.LENGTH_SHORT).show(); } }); // 合并权限请求,避免重复弹窗 if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 100); } fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this); SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(this); } private LatLng getCurrentLocation() { for (Marker marker : markers) { if (marker.getTitle().equals("Ubicación actual")) { return marker.getPosition(); } } return null; } private LatLng getDestinationLocation() { for (Marker marker : markers) { if (marker.getTitle().equals("Destino")) { return marker.getPosition(); } } return null; } @Override public void onMapReady(GoogleMap googleMap) { mMap = googleMap; if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { return; } fusedLocationProviderClient.getLastLocation() .addOnSuccessListener(this, location -> { if (location != null) { double latitude = location.getLatitude(); double longitude = location.getLongitude(); LatLng currentLocation = new LatLng(latitude, longitude); // 将初始Marker加入markers列表 Marker currentMarker = mMap.addMarker(new MarkerOptions().position(currentLocation).title("Ubicación actual")); markers.add(currentMarker); mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLocation, 15)); mMap.setOnMapClickListener(point -> { mMap.clear(); markers.clear(); LatLng currentLoc = new LatLng(latitude, longitude); Marker currMarker = mMap.addMarker(new MarkerOptions().position(currentLoc).title("Ubicación actual")); markers.add(currMarker); Marker destinationMarker = mMap.addMarker(new MarkerOptions().position(point).title("Destino")); markers.add(destinationMarker); getDirections(currentLoc, point); }); } }); } private void getDirections(LatLng origin, LatLng destination) { GeoApiContext context = new GeoApiContext.Builder() .apiKey("你的API Key") .build(); DirectionsApiRequest request = DirectionsApi.newRequest(context) .mode(TravelMode.DRIVING) .origin(new com.google.maps.model.LatLng(origin.latitude, origin.longitude)) .destination(new com.google.maps.model.LatLng(destination.latitude, destination.longitude)); request.setCallback(new PendingResult.Callback<DirectionsResult>() { @Override public void onResult(DirectionsResult result) { mainHandler.post(() -> { // 切换到主线程操作UI if (routePolyline != null) { routePolyline.remove(); } if (result.routes == null || result.routes.length == 0) { Toast.makeText(RutaLocal.this, "未找到可用路线", Toast.LENGTH_SHORT).show(); return; } DirectionsRoute route = result.routes[0]; List<LatLng> points = new ArrayList<>(); // 解析每个step的encodedPolyline,获取完整路径点 for (DirectionsStep step : route.legs[0].steps) { points.addAll(PolyUtil.decode(step.polyline.getEncodedPath())); } PolylineOptions polylineOptions = new PolylineOptions() .addAll(points) .color(Color.BLUE) .width(8); // 加宽折线,更容易看到 routePolyline = mMap.addPolyline(polylineOptions); }); } @Override public void onFailure(Throwable e) { mainHandler.post(() -> { Toast.makeText(RutaLocal.this, "路线请求失败:" + e.getMessage(), Toast.LENGTH_LONG).show(); e.printStackTrace(); }); } }); } }
关键修复说明
- 完整解析路径点:使用
PolyUtil.decode(step.polyline.getEncodedPath())解析每个step的编码折线,获取路线的所有坐标点,替代之前仅取startLocation的方式。 - 主线程操作UI:通过
Handler将添加折线的操作切换到主线程,符合Android UI线程规则。 - 完善Marker管理:初始添加的当前位置Marker加入
markers集合,保证按钮点击时能正确获取起点。 - 错误处理:在
onFailure中添加错误提示和日志,方便排查API调用异常。 - 合并权限请求:将两个位置权限请求合并,避免重复弹窗。
内容的提问来源于stack exchange,提问作者Cristian
相关产品推荐
相关产品推荐

