解决方案在于谷歌地图路线链接的扩展网址中的“数据”参数。
让我们以这个 URL 为例 - https://goo.gl/maps/zrcP5gL1cd2AHGoq8
这扩展为https://www.google.com/maps/dir/Eiffel+Tower,+Paris,+France/Palais+Garnier,+Pl.+de+l'Op%C3%A9ra,+75009+Paris,+France/@48.8606129,2.2961092,14z/am=t/data=!4m29!4m28!1m20!1m1!1s0x47e6701f7e8337b5:0xa2cb58dd28914524!2m2!1d2.2930458!2d48.8560934!3m4!1m2!1d2.3122286!2d48.8490916!3s0x47e6702fa62d0bc5:0xd2d94ed604f2e5a0!3m4!1m2!1d2.3035972!2d48.8729816!3s0x47e66fc1755cf609:0x3c5040f902b41a5f!3m4!1m2!1d2.3235117!2d48.8581242!3s0x47e66e2ac3bca3ed:0x1c289763e3096e61!1m5!1m1!1s0x47e66e30d4668339:0xa9abf21c286d0767!2m2!1d2.3316014!2d48.8719697!3e0
仔细检查后,您会发现数据参数中嵌入了 lat-lng 坐标。例如这个
!1d2.2930458!2d48.8560934 或 !1d2.3122286!2d48.8490916。这些是代表路线上各种航路点的经纬度对。经度始终以!1d 开头并以!2d 结尾,纬度以!2d 开头并以!3 结尾。
这是一个提取所有坐标的小 kotlin 方法:
//https://stackoverflow.com/a/62191093/3090120
fun String?.indexesOf(pat: String, ignoreCase: Boolean = true): List<Int> =
pat.toRegex(if (ignoreCase) setOf(RegexOption.IGNORE_CASE) else emptySet())
.findAll(this ?: "")
.map { it.range.first }
.toList()
fun extractCoordinates(expandedUrl: String): List<LatLng> {
val latLngList = arrayListOf<LatLng>()
val indexes = expandedUrl.indexesOf("!1d")
indexes.forEach {
val coordinatesStr = expandedUrl.substring(it + 3).substringBefore("!3").split("!2d")
latLngList.add(LatLng(coordinatesStr[1].toDouble(), coordinatesStr[0].toDouble()))
}
return latLngList
}
这个字符串的结果是
[lat/lng: (48.8560934,2.2930458), lat/lng: (48.8490916,2.3122286), lat/lng: (48.8729816,2.3035972), lat/lng: (48.8581242,2.3235117), lat/lng: (48.8719697,2.3316014)]
一旦我们有了所有的 lat-lng 对,我们就可以简单地启动 Google Maps Directions API 调用并在链接中重新创建路线并将其导出为 GPX 文件。