Cloud Anchors 托管解析超时和失败排查
问题描述
Cloud Anchors 的 Host 或 Resolve 操作一直没有完成,或最终返回错误状态:
| 现象 | 可能原因 |
|---|---|
| 一直处于 PENDING | 网络问题、Cloud 服务延迟 |
| ERROR_INTERNAL | Google 内部错误,通常可重试 |
| ERROR_NOT_AUTHORIZED | API Key 配置问题 |
| ERROR_RATE_LIMITED | 频率超限 |
| ERROR_RESOURCE_EXHAUSTED | 配额用完 |
| TTL_EXPIRED | 锚点已过期 |
| NOT_FOUND | anchorId 无效或被删除 |
排查流程
Cloud Anchors 操作失败
↓
第一步:网络检查
↓ OK
第二步:API Key 验证(Google Cloud Console)
↓ OK
第三步:确认 Cloud Anchors API 已启用
↓ OK
第四步:检查配额用量
↓ OK
第五步:检查 API Key 绑定的包名/Bundle ID
↓ OK
第六步:检查设备时间是否准确
↓ OK
第七步:重试(ERROR_INTERNAL 通常是暂时性的)
↓ OK但仍失败
第八步:在完全不同的网络和设备上测试
步骤一:网络检查
Cloud Anchors 需要稳定的互联网连接(建议 WiFi,移动网络在信号差时容易超时)。
// 在 Host / Resolve 之前检查网络
fun isNetworkAvailable(context: Context): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkInfo = connectivityManager.activeNetworkInfo
return networkInfo != null && networkInfo.isConnected
}
中国国内的特殊情况
Cloud Anchors 在中国大陆可能不可用或极不稳定——Google Cloud 服务受网络环境限制。表现:
- 请求一直 PENDING(无法连接 Google Cloud)
- 偶发性 ERROR_INTERNAL 或超时
- 部分时段突然可以工作
解决方案:检测到设备在中国时降级 Cloud Anchors 功能(只保留本地 Anchor),或提示用户需要境外网络。
步骤二:API Key 完整验证
API Key 是 Cloud Anchors 最常见的问题来源。以下是完整验证清单:
Android 端
1. GCP Console 中有这个 Key 吗?
→ 打开 console.cloud.google.com → APIs & Services → Credentials → 找你的 Key
2. Key 限制了哪些应用可以用?
→ 限制类型:Android apps → 包名和签名 SHA1 是否正确?
→ 用你的 APK 的实际签名 SHA1,不要用 debug.keystore 的 SHA1
3. Key 限制了哪些 API?
→ 确保 ARCore Cloud Anchor API 在白名单里
→ 不要把 Key 限制得太死(比如只允许某个 IP)
4. AndroidManifest 中的 Key 对吗?
→ <meta-data android:name="com.google.android.ar.API_KEY" android:value="你的Key">
→ 注意是 com.google.android.ar.API_KEY(Android 的),不是其他名字
iOS 端
1. GCP Console 中有这个 Key 吗?
→ 限制类型:iOS apps → Bundle ID 是否正确?
2. Info.plist 中的 Key 对吗?
→ <key>GARAPIKey</key><string>你的Key</string>
→ Key 是字符串值,直接写进去(注意引号)
3. 同时用了 ARCore iOS SDK + Cloud Anchors 吗?
→ 必须集成 GoogleARCore 这个 CocoaPods / Swift Package
跨平台共享时的 Key 注意
Android 和 iOS 的 Key 必须来自同一个 GCP 项目——Cloud Anchors 的 Host 和 Resolve 是跨设备的,两端必须共享同一个项目配额。
步骤三:Cloud Anchors API 启用
1. 打开 Google Cloud Console
2. APIs & Services → Library
3. 搜索 "ARCore Cloud Anchor API"
4. 确保 API 已 ENABLED(不是 DISABLED)
5. 如果是首次启用,可能需要等几十分钟生效
步骤四:配额检查
1. GCP Console → APIs & Services → ARCore Cloud Anchor API
2. 查看 Metrics 页面的 Host 和 Resolve 用量
3. 免费配额:每月 10,000 Host + 10,000 Resolve
4. 超出后 → ERROR_RESOURCE_EXHAUSTED
5. 可以升级配额或付费购买
// 捕获配额错误
cloudAnchorFuture.addListener({
val state = cloudAnchorFuture.result?.cloudAnchorState
if (state == CloudAnchorState.ERROR_RESOURCE_EXHAUSTED) {
showQuotaExhaustedMessage()
// 或者排队等待下个月配额重置
}
}, mainHandler)
步骤五:设备时间校准
Cloud Anchors 的请求包含时间戳,Google 会验证时间的合理性。设备时间偏离网络时间太大时,Cloud Anchors 可能拒绝请求:
// 检查设备时间是否在合理范围
fun isDeviceTimeReasonable(): Boolean {
val deviceTime = System.currentTimeMillis() / 1000
val networkTime = NtpClient.getNetworkTime() // 需要自己实现或用库
return Math.abs(deviceTime - networkTime) < 60 // 允许 ±60 秒偏差
}
如果设备时间不准,提示用户"请检查手机的自动时间设置"。
步骤六:重试策略
Cloud Anchors 的错误大多是暂时性的——Google 云端偶发性波动或网络抖动。实现自动重试:
private const val MAX_RETRY = 3
private const val RETRY_DELAY_MS = 1000L
fun hostCloudAnchor(anchor: Anchor, retryCount: Int = 0) {
val future = session.hostCloudAnchor(anchor)
future.addListener({
val state = future.result?.cloudAnchorState
when {
state == CloudAnchorState.SUCCESS -> {
// 成功
onHostSuccess(future.result!!.anchorId)
}
(state == CloudAnchorState.ERROR_INTERNAL ||
state == CloudAnchorState.ERROR_NETWORK) && retryCount < MAX_RETRY -> {
// 可重试错误,等一会再试
handler.postDelayed({
hostCloudAnchor(anchor, retryCount + 1)
}, RETRY_DELAY_MS * (retryCount + 1)) // 线性退避
}
else -> {
// 不可重试错误,报告给用户
onHostFailed(state)
}
}
}, handler)
}
适合重试的错误
| 错误状态 | 是否可重试 | 原因 |
|---|---|---|
| ERROR_INTERNAL | ✅ | Google 内部服务暂不可用 |
| ERROR_NETWORK | ✅ | 网络波动 |
| ERROR_RATE_LIMITED | ⚠️ | 可以延迟重试,但不要太频繁 |
| ERROR_NOT_AUTHORIZED | ❌ | 需要修复 API Key |
| ERROR_RESOURCE_EXHAUSTED | ❌ | 等配额重置 |
| TTL_EXPIRED | ❌ | 锚点已永久过期 |
| NOT_FOUND | ❌ | anchorId 无效 |
步骤七:极端情况
如果所有排查都做了还是失败:
- 在完全不同的网络上测试:换 WiFi / 换移动网络 / 换地区
- 在不同设备上测试:同一应用包在不同手机上测
- 换一个新的 GCP 项目:排除项目级配置问题
- 使用 Google 官方 Cloud Anchors Demo:确认是你的应用问题还是 Google 服务问题
- 等几小时再试:Google Cloud 偶发波动会影响所有用户
调试工具
ARCore Debug Overlay
session.configure(
Session.Config(context).apply {
setShowDiagnostics(true)
}
)
Debug Overlay 会显示 Cloud Anchors 的托管/解析状态——在 Host 或 Resolve 时能实时看到进度和错误信息。
Google Cloud Console 日志
打开 GCP Console → Cloud Logging → 查看 Cloud Anchors API 的请求日志,可以看到 Google 返回的具体错误码。