使用 Android XR、Geospatial API 和 Gemini 构建混合现实导游应用

7 分钟阅读时间

在今年的 Google I/O 大会上,我们宣布了空间体验的更新:Geospatial API 现已在ARCore for Jetpack XR 中以预览版的形式提供。通过将 Google 的视觉定位系统 (VPS) 引入 Android XR,Android XR 能够在支持的区域内以亚米级精度和精确的方向将数字内容锚定到现实世界。*为了探索 Geospatial API 的潜力,我们的团队构建了一个演示应用:XR Geospatial Tour。

想象一下,您走进一座新城市,戴上一副有线 XR 眼镜(例如即将推出的 XREAL Project Aura),就能立即获得一位知识渊博的当地导游,带您四处游览。您无需低头查看 2D 地图,而是由 3D 模型轻柔地引导您的路线,智能语音会告诉您眼前的历史地标。我们结合了 Geospatial API使用 Firebase AI Logic 的 Gemini APIGoogle 地图接地Jetpack XR SDK,打造了免手持沉浸式步行游览体验。

 

 

免责声明:视频和导游应用仅用于演示目的。部分序列已缩短。所描绘的任何硬件可能仍在开发中;最终产品详细信息可能会有所不同。

接下来,我们将详细介绍实现细节,并展示如何将这些 API 结合在一起,构建世界级的空间体验。

1. 使用 ARCore Geospatial API (VPS) 精确定位用户

结合 GPS 的强大功能和 VPS 的精确性,提升 XR 上的导航体验。VPS 提供的准确性和精确的方向可让 3D 航点与现实世界对齐。

因此,Android XR 上的 Geospatial API 可以帮助您构建自定义体验。通过使用先进的计算机视觉技术,VPS 尝试提供比 GPS 更准确的 GeospatialPose(包括纬度、经度和航向)。

以下是我们如何通过将设备的方向映射到地理空间坐标来检索用户的地理空间姿态:

// Retrieve the current geospatial pose from the ARCore session
val result = geospatial.createGeospatialPoseFromPose(arDevice.state.value.devicePose)
if (result is CreateGeospatialPoseFromPoseSuccess) {
    val pose = result.pose
    Log.d("VPS", "Accurate Location: ${pose.latitude}, ${pose.longitude}")
}

由于整个体验都依赖于此准确性,因此我们会监控 horizontalAccuracyorientationYawAccuracy,直到它们达到我们的阈值。如果用户在室内或在无法识别的区域,我们会提示他们“走到室外公共场所并四处看看”。

2. 使用 Gemini API 和 Google 地图接地功能制作行程

获得位置后,我们使用 使用 Firebase AI Logic 的 Gemini API 提示 Gemini 模型充当当地导游。我们将用户的坐标传递给模型,并要求其输出包含附近步行游览路线的 JSON 结构化响应:

   val configForTools = ToolConfig(
      functionCallingConfig = null,
      retrievalConfig = retrievalConfig {
        latLng = FirebaseLatLng(pose.latitude, pose.longitude)
        languageCode = "en"
      }
    )

    val responseJsonSchema = Schema.obj(
      mapOf(
        "locationIntro" to Schema.string(),
        "tours" to Schema.array(
          Schema.obj(
            mapOf(
              "title" to Schema.string(),
              "description" to Schema.string(),
              "stops" to Schema.array(
                Schema.obj(
                  mapOf(
                    "name" to Schema.string(),
                    "detailedName" to Schema.string(),
                    "description" to Schema.string()
                  )
                )
              )
            )
          )
        )
      )
    )

    val model = Firebase.ai(backend = GenerativeBackend.googleAI()).generativeModel(
      modelName = "gemini-3.5-flash",
      tools = listOf(Tool.googleMaps()),
      generationConfig = generationConfig {
        responseMimeType = "application/json"
        responseSchema = responseJsonSchema
      }
    )

   val result = model.generateContent("The user is at latitude ${pose.latitude} and longitude ${pose.longitude}. Generate exactly 3 diverse tours near this location (e.g., historical, food, nature). All tour ideas should be walking distance only.")

大语言模型非常擅长生成丰富的内容描述,但有时可能会产生幻觉,给出不准确的纬度/经度坐标。为了解决这个问题,我们使用了 Google 地图接地功能来接地 AI。

3. 语音导览:Gemini 2.5 TTS

为了让导游感觉真正存在,我们实现了动态旁白。

使用 gemini-2.5-flash-tts model,我们可以将模型生成配置配置为原生返回音频数据,而不仅仅是文本!以下是如何请求 ResponseModality.AUDIO

val ttsModel = Firebase.ai(backend = GenerativeBackend.googleAI())
    .generativeModel(
        modelName = "gemini-2.5-flash-tts",
        generationConfig = generationConfig {
            // Instruct the model to return Audio
            responseModalities = listOf(ResponseModality.AUDIO)
        }
    )

val response = ttsModel.generateContent("Say in a neutral but positive voice:\n$prompt")

// Extract the raw audio bytes from the response
val audioBytes = response.candidates.firstOrNull()?.content?.parts
    ?.filterIsInstance<InlineDataPart>()
    ?.firstOrNull { it.mimeType.contains("audio") }?.inlineData

4. 使用 Jetpack XR 以 3D 形式呈现

最后一步是在用户的视野中呈现这些数据。Jetpack XR SDK 可以让您直观地从 2D Android 界面过渡到空间计算。

我们使用 Jetpack Compose for XR 构建了空间组件。为了表示游览路线上的兴趣点,我们构建了一个名为 InfoSphere 的可组合项,其中包含一个 3D 球体的 GltfModel,该球体漂浮在空间中,可以与之互动以显示信息。

使用 Jetpack XR SDK,我们可以使用 SpatialBox 和 SceneCoreEntity 将 3D 模型放置在 Compose 界面旁边。我们还使用了 InteractableComponent 来响应用户点按。

通过将传统 Compose 界面表面的 AnimatedSpatialVisibility 与 SceneCoreEntity 3D 元素相结合,我们可以将数据无缝融入现实世界。

@Composable
fun InfoSphere(
    content: InfoBubbleContent,
    session: Session,
    sphereModel: GltfModel,
    isSelected: Boolean,
    onClick: () -> Unit
) {
    // SpatialBox lets us arrange 3D components and SpatialPanels together
    SpatialBox(
        SubspaceModifier
            .offset(x = 2.dp, y = 1.dp, z = (-3).dp) // Positioned in 3D space
    ) {
        // Smoothly animate the visibility of our 2D Compose UI Panel
        AnimatedSpatialVisibility(visible = isSelected) {
            SpatialPanel {
                InfoBubble(content) // Regular 2D Compose UI
            }
        }
        // Render our interactive 3D sphere
        SceneCoreEntity(
            factory = {
                GltfModelEntity.create(session, sphereModel).also { entity ->
                    // Make the 3D model respond to user taps
                    entity.addComponent(InteractableComponent.create(session) { inputEvent ->
                        if (inputEvent.action == InputEvent.Action.UP) {
                            onClick()
                        }
                    })
                }
            }
        )
    }
}

探索 Android XR 的无限可能

构建 XR Geospatial Tour 应用让我们看到,对于 Android 开发者来说,构建世界级空间体验的门槛比以往任何时候都低。随着 Geospatial API 现已在 Android XR 上以预览版的形式提供,您的应用可以无缝了解周围的现实世界。通过将 Compose for XR 的 API 与 VPS 的高精度位置数据和 Gemini 的生成能力相结合,我们可以创建既能了解用户所在位置,又能了解用户正在观看的内容的体验。

为了帮助您亲身体验 Android XR,我们很高兴开放 Android XR 开发者催化剂计划的申请,该计划包括 XREAL Project Aura。从今天开始,您可以在未来几个月内申请获取 XREAL Project Aura 开发者套件或我们的带屏眼镜开发者套件!

*免责声明:适用于部分设备。需要连接到互联网。适用于兼容的应用和平台。实际情况可能会有所不同。

继续阅读