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

Android反向地理编码调用失败,API密钥权限受限问题求助

问题解决:Google Geocoding API 请求被拒绝(REQUEST_DENIED)

核心问题分析

你遇到的问题主要来自两个方面:

  1. Retrofit参数注解误用:你把Google API要求的查询参数(latlng、key)用了@Path注解,但@Path是用来替换URL路径中的占位符的,会导致请求URL格式完全错误——Google服务器无法正确识别密钥和坐标参数,直接触发权限验证失败。
  2. Android应用限制的验证逻辑:当API密钥设置为Android应用限制时,Google需要验证请求来自指定包名+SHA1签名的应用,但Retrofit发起的普通HTTP请求不会自动携带这些验证信息(这部分是Google Maps SDK内部自动处理的),所以服务器无法确认请求合法性,返回拒绝。

解决步骤

1. 先修正Retrofit接口方法

把@Path替换为@Query,确保参数以查询参数的形式传递,符合Google API的URL规范:

@GET(ApiRoute.GEOCODE)
suspend fun getAddress(
    @Query("latlng") latLng: String?,
    @Query("key") apiKey: String,
): Response<ReverseGeocodeEntity>

假设ApiRoute.GEOCODE的值是"geocode/json",修正后生成的URL会是正确的格式:https://maps.googleapis.com/maps/api/geocode/json?latlng=xxx&key=xxx。

2. 适配Android应用限制的验证(二选一)

如果要保留API密钥的Android应用限制(推荐,更安全),可以选下面任意一种方案:

方案A:使用Google Maps SDK内置的Geocoder

直接用SDK提供的地理编码工具,它会自动处理API密钥的验证(完全符合Android应用限制的要求),无需手动调用HTTP接口:

val geocoder = Geocoder(context, Locale.getDefault())
// 传入纬度、经度,获取1条地址结果
val addresses = geocoder.getFromLocation(latitude, longitude, 1)
if (addresses?.isNotEmpty() == true) {
    val fullAddress = addresses[0].getAddressLine(0)
    // 处理获取到的地址数据
}

注意:这个类依赖设备上的Google Play服务,部分地区可能需要特殊网络环境。

方案B:通过后端代理请求

自己搭建一个后端接口,由后端调用Google Geocoding API(后端使用IP限制的API密钥),你的Android应用只需要调用自己的后端接口。这种方式既保证了密钥的安全性,又避开了移动端直接调用的验证问题。

额外检查项

  • 确认Google Cloud控制台中,API密钥的Android应用限制里的包名完全匹配你的应用包名(注意大小写和拼写)。
  • 通过./gradlew signingReport命令重新获取调试和发布版本的SHA1,对比控制台中的记录,确保没有填错。
  • 清除应用缓存并重启设备,保证Google Play服务的验证信息同步更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 04:35:32