Android XR DP4 发布了,我们主要聚焦两个问题:手机 App 怎么投到眼镜,以及 Compose / SceneCore 怎么处理 3D 内容。

Projected
DP4 里比较实用的是 Device Availability API。它把连接状态、佩戴状态这类信号收敛到标准的 Lifecycle.State,App 可以按生命周期状态决定是否展示眼镜界面、暂停刷新,或者回到手机端普通界面。
写法大概是这样:
bash
val projectedContext =
ProjectedContext.createProjectedDeviceContext(context)
val xrDevice = XrDevice.getCurrentDevice(projectedContext)
lifecycleScope.launch {
xrDevice.getLifecycle().currentStateFlow.collect { state ->
when (state) {
Lifecycle.State.STARTED -> showGlassesContent()
Lifecycle.State.CREATED -> pauseGlassesContent()
Lifecycle.State.DESTROYED -> closeGlassesContent()
else -> Unit
}
}
}
这段代码里的重点是状态来源。原来你可能要自己维护连接状态、设备是否佩戴、页面是否可见这些条件,现在统一按 Lifecycle.State 处理。

Glimmer
Jetpack Compose Glimmer 是 display glasses 的 Compose UI 工具包。它和普通 Compose 写法接近,但组件、字号、颜色、交互模型是按 optical see-through display 调过的。
DP4 里 Glimmer 加了 Google Sans Flex,主要处理透视显示里的文字可读性。组件上新增了 Stacks 和 Title Chips。Stacks 适合触摸板导航,一次突出一个 item;Title Chips 用来给内容卡片补分类和上下文。
普通手机界面直接搬到眼镜上,经常会出两个问题:信息太密,触摸路径太长。Glimmer 的组件设计就是在限制这两个问题。比如一个提醒列表,在手机上可以是一屏多个 item;放到眼镜上,更适合做成单项聚焦的 stack。
示意代码可以写成这样,真实项目里组件名和参数以当前 Glimmer 版本为准:
bash
@Composable
fun ReminderGlassesScreen(items: List<Reminder>) {
GlimmerTheme {
VerticalStack {
items.forEach { item ->
ContentCard(
title = item.title,
subtitle = item.time,
leading = {
TitleChip(text = item.type)
}
)
}
}
}
}
这段代码对应的是布局形态:眼镜上更偏"聚焦当前内容"。手机列表的密度原样投过去,文字和操作都会变得吃力。写 UI 时先确认信息层级,再决定用 Glimmer 组件还是自己写 Compose。
SceneCore 和 glTF
沉浸式场景主要看 SceneCore 和 Compose for XR。DP4 里 XR Runtime、Jetpack SceneCore、ARCore for Jetpack XR 的一批感知能力准备进入 Beta,同时 API 往 Kotlin-first 的方向整理,旧的 Guava 和 RxJava3 包会被移掉。
已经试过早期 XR SDK 的项目会碰到异步写法和依赖调整。后续升级时不要只改版本号,要看有没有还在引用旧包,尤其是 perception、scene、anchor 这类模块。
SceneCore 新增的重点是 glTF 节点能力。通过 GltfModelNode,可以访问模型里的指定 node,修改 pose、material、texture,也可以触发某个 node 的 animation。以前只把 3D 模型当成一个整体加载,现在可以对模型内部节点做更细的控制。
根据 DP4 信息整理后的 Compose for XR 写法大概是这样:
bash
@Composable
fun ProductModel(modelSource: SpatialGltfModelSource) {
val modelState = rememberSpatialGltfModelState(modelSource)
SpatialGltfModel(
state = modelState,
modifier = SubspaceModifier
.width(1.2.meters)
.height(1.2.meters)
)
LaunchedEffect(modelState) {
val animation = modelState.animations()
.firstOrNull { it.name == "open" }
animation?.play()
}
}
这段示例只保留核心对象:rememberSpatialGltfModelState 负责模型状态,SpatialGltfModel 负责在 Compose for XR 里显示 glTF,animations() 可以拿到模型动画。模型文件从哪里加载、动画名称是什么,要和美术资源约定好。
DP4 还提到了 Custom Meshes,可以用代码动态创建几何体。它适合运行时生成标注、路径、扫描结果这类内容,会以实验能力进入,正式业务里要先确认 API 稳定性。

Geospatial
ARCore for Jetpack XR 在 wired XR glasses 上加入 Geospatial API 早期预览。它结合 ARCore 的 Visual Positioning System,把数字内容锚定到真实世界的位置。文档里提到覆盖范围超过 87 个国家。
它更接近"位置绑定"。比如做步行导览时,内容会绑定到某个建筑、路口或空间位置。App 侧要处理位置可用性、定位精度、网络状态和内容更新,不然用户站在真实空间里看到的提示会飘。
Android 工程里可以把它理解成另一类 anchor。普通空间锚点解决当前环境里的相对位置,Geospatial 处理更大范围的真实地理位置。接入前先确认场景是否需要真实地点绑定,很多室内演示用普通 spatial anchor 就够了。
最后
Android XR DP4 可以优先验证 Device Availability API、ProjectedTestRule、Glimmer 的 glasses UI 组件,以及 SpatialGltfModel 的 glTF 加载。