如何将Google Maps交通数据解析为JSON?安卓路径规划应用求助
解决Google Maps交通数据解析为JSON并实现最优路径的方案
Hey there! Let's break down how you can parse Google Maps Traffic data into JSON and build that optimal path feature for your campus Android app—here's a practical, step-by-step approach:
1. 先搞懂要用哪个API
你需要用Google Maps Directions API,它本身就会返回带实时/预测交通数据的JSON响应,完全不需要自己去“解析”原始交通数据(Google已经帮你封装好啦)。这个API能直接返回考虑交通状况的路径时长、距离,甚至多条路线供你对比选最优。
2. 准备工作:启用API并获取密钥
- 去Google Cloud Console启用「Directions API」
- 创建一个受限制的API密钥(强烈建议:只允许你的安卓应用包名+SHA-1指纹访问,避免密钥被盗用)
3. 构造API请求(直接获取JSON格式的交通路径数据)
你需要发送一个GET请求到以下地址,替换参数为你的实际数据:
https://maps.googleapis.com/maps/api/directions/json?origin=当前位置经纬度&destination=目的地经纬度&departure_time=now&traffic_model=best_guess&key=你的API密钥
参数解释:
departure_time=now:告诉API获取实时交通数据(如果要预测未来时间的交通,换成对应的Unix时间戳)traffic_model:可选值best_guess(默认,最准确的预测)、pessimistic(最坏情况)、optimistic(最佳情况)
4. 在安卓里发送请求并解析JSON
推荐用Retrofit+Gson来做网络请求和自动解析,比手动写JSONObject简洁太多。下面是具体代码示例:
第一步:添加依赖
在你的app模块build.gradle里加入:
implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
第二步:定义API接口
interface DirectionsApi { @GET("maps/api/directions/json") suspend fun getOptimalRoute( @Query("origin") origin: String, // 格式:"纬度,经度",比如"39.9042,116.4074" @Query("destination") destination: String, @Query("departure_time") departureTime: Long = System.currentTimeMillis() / 1000, // 转成Unix时间戳(秒) @Query("traffic_model") trafficModel: String = "best_guess", @Query("key") apiKey: String ): Response<RouteResponse> }
第三步:定义对应JSON结构的数据模型
Gson会自动把JSON响应映射到这些类里:
data class RouteResponse( val routes: List<Route> // API可能返回多条路线 ) data class Route( val legs: List<Leg> // 每条路线的分段(比如从起点到终点的整个路段) ) data class Leg( val distance: Distance, // 总距离(无视交通) val duration: Duration, // 总时长(无视交通) val duration_in_traffic: DurationInTraffic, // 考虑交通的总时长(核心!用来选最优路径) val steps: List<Step> // 路径的每一步细节 ) // 辅助数据类 data class Distance(val text: String, val value: Int) // value是米数 data class Duration(val text: String, val value: Int) // value是秒数 data class DurationInTraffic(val text: String, val value: Int) data class Step(val html_instructions: String, val distance: Distance, val duration: Duration)
第四步:发起请求并处理结果
在ViewModel或者Repository里用协程调用(避免阻塞主线程):
// 初始化Retrofit val retrofit = Retrofit.Builder() .baseUrl("https://maps.googleapis.com/") .addConverterFactory(GsonConverterFactory.create()) .build() val directionsApi = retrofit.create(DirectionsApi::class.java) // 在协程中执行请求 viewModelScope.launch { try { // 替换成你实际获取的当前位置和目的地经纬度 val currentLocation = "${location.latitude},${location.longitude}" val destination = "39.9526,116.3972" // 示例坐标 val response = directionsApi.getOptimalRoute( origin = currentLocation, destination = destination, apiKey = "YOUR_RESTRICTED_API_KEY" ) if (response.isSuccessful) { val routeResponse = response.body() routeResponse?.let { // 从多条路线中选最优:找duration_in_traffic最小的那条 val optimalRoute = it.routes.minByOrNull { route -> route.legs.firstOrNull()?.duration_in_traffic?.value ?: Int.MAX_VALUE } optimalRoute?.legs?.firstOrNull()?.let { leg -> // 拿到最优路径的关键数据 val trafficAwareDuration = leg.duration_in_traffic.text val totalDistance = leg.distance.text // 这里把数据更新到你的地图UI上,比如显示"预计15分钟(交通拥堵)" updateMapWithOptimalPath(leg.steps) // 可以把steps解析成地图上的路线点 } } } else { Log.e("DirectionsError", "请求失败: ${response.errorBody()?.string()}") } } catch (e: Exception) { Log.e("NetworkError", "网络异常: ${e.message}") } }
5. 关键注意事项
- 权限:别忘了在AndroidManifest.xml里添加
ACCESS_FINE_LOCATION和INTERNET权限,还要动态请求位置权限。 - 密钥安全:绝对不要把API密钥硬编码在代码里!把它放在
local.properties里,通过gradle引用,或者用Google Cloud的API限制功能。 - 多条路线选择:如果API返回多条routes,对比每条的
duration_in_traffic.value(秒数),最小的就是交通状况下的最优路径。
内容的提问来源于stack exchange,提问作者Risel Bata




