调用LatLngBounds.Builder.build()抛出IllegalStateException: no included points异常
解决LatLngBounds.Builder.build()抛出IllegalStateException: no included points异常
这个错误的核心很明确:你调用LatLngBounds.Builder.build()时,这个Builder对象里没有包含任何LatLng坐标点,所以触发了Google Maps的参数检查异常。而导致polyLineList为空的原因,大概率出在Directions API的响应解析或者API请求本身上,咱们一步步排查:
一、先排查API请求的有效性
首先得确认你的Directions API请求是否真的返回了有效路线:
- 把你打印的
requestAPI完整字符串复制到浏览器里直接访问,看看返回的JSON结构:- 先看
status字段:如果是"OK"才代表请求成功;如果是"ZERO_RESULTS"说明起点终点之间没有可行路线,"NOT_FOUND"说明地址解析失败,"REQUEST_DENIED"说明API密钥权限有问题 - 再看
routes数组是否有内容,如果是空数组,那自然解析不出polyline
- 先看
常见的API请求问题:
- API密钥权限不足:你需要在Google Cloud控制台里给这个密钥启用Directions API,同时检查密钥的应用限制(比如包名、SHA-1是否和你的APP匹配),另外如果免费额度用完也会返回空响应
- destination格式错误:确保
destination变量是合法的格式,比如"纬度,经度"或者可被Google解析的地址字符串 - 请求参数拼接错误:你的代码里用了
&,这是HTML转义后的&符号,应该直接用&,虽然有些框架会自动处理,但这可能导致参数解析错误(比如mode=driving&transit_routing_preference=less_driving会被当成一个参数)
二、给代码添加防御性处理
就算API请求偶尔出问题,代码也不能直接崩溃,得加判空和错误处理:
1. 先检查API响应的status
在解析JSON之前,先判断请求是否成功:
JSONObject jsonObject = new JSONObject(response.body().toString()); String status = jsonObject.getString("status"); if (!"OK".equals(status)) { // 处理请求失败的情况,比如弹Toast提示用户 Toast.makeText(MapsActivity.this, "无法获取路线:" + status, Toast.LENGTH_SHORT).show(); return; }
2. 检查polyLineList是否为空
在构建LatLngBounds之前,先确认polyLineList有内容:
polyLineList = decodePoly(polyline); // 循环结束后检查 if (polyLineList == null || polyLineList.isEmpty()) { Toast.makeText(MapsActivity.this, "没有找到可用路线", Toast.LENGTH_SHORT).show(); return; }
3. 确保decodePoly方法正确
如果你的decodePoly方法有问题,也会导致返回空列表,这里给你一个标准的polyline解码实现:
private List<LatLng> decodePoly(String encoded) { List<LatLng> poly = new ArrayList<>(); int index = 0; int len = encoded.length(); int lat = 0, lng = 0; while (index < len) { int b, shift = 0, result = 0; do { b = encoded.charAt(index++) - 63; result |= (b & 0x1f) << shift; shift += 5; } while (b >= 0x20); int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); lat += dlat; shift = 0; result = 0; do { b = encoded.charAt(index++) - 63; result |= (b & 0x1f) << shift; shift += 5; } while (b >= 0x20); int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); lng += dlng; LatLng p = new LatLng((((double) lat / 1E5)), (((double) lng / 1E5))); poly.add(p); } return poly; }
三、修改后的核心代码片段
把这些检查加到你的onResponse方法里,避免空指针和非法状态异常:
@Override public void onResponse(Call<String> call, Response<String> response) { try { JSONObject jsonObject = new JSONObject(response.body().toString()); String status = jsonObject.getString("status"); if (!"OK".equals(status)) { Toast.makeText(MapsActivity.this, "路线请求失败:" + status, Toast.LENGTH_SHORT).show(); return; } JSONArray jsonArray = jsonObject.getJSONArray("routes"); if (jsonArray.length() == 0) { Toast.makeText(MapsActivity.this, "未找到可用路线", Toast.LENGTH_SHORT).show(); return; } polyLineList = new ArrayList<>(); for (int i = 0; i < jsonArray.length(); i++) { JSONObject route = jsonArray.getJSONObject(i); JSONObject poly = route.getJSONObject("overview_polyline"); String polyline = poly.getString("points"); polyLineList.addAll(decodePoly(polyline)); // 用addAll避免覆盖 } if (polyLineList.isEmpty()) { Toast.makeText(MapsActivity.this, "路线解析失败", Toast.LENGTH_SHORT).show(); return; } // 下面继续执行你的LatLngBounds构建和地图绘制逻辑 LatLngBounds.Builder builder = new LatLngBounds.Builder(); for (LatLng latLng : polyLineList) builder.include(latLng); LatLngBounds bounds = builder.build(); // ... 剩下的代码不变 } catch (JSONException e) { e.printStackTrace(); Toast.makeText(MapsActivity.this, "数据解析错误", Toast.LENGTH_SHORT).show(); } }
最后提醒一下,记得在Google Cloud控制台里确认你的API密钥已经启用了Directions API,并且没有超过配额,这是很多人忽略的点。
内容的提问来源于stack exchange,提问作者Anushka Narayan
相关产品推荐
相关产品推荐

