2024 Google I/O Android 相关内容汇总
本次 Google I/O 的核心虽然是 AI ,但是 Android 也是作为主要议题出现, Android 部分可以简单分为产品和开发相关内容,接下来主要介绍这两部分的相关更新。
重点开始开发相关,内容不少
产品
Gemini
Android 端的 Gemini 将升级支持,让 Gemini 可以更好地理解屏幕上的内容,帮助用户分析工作、生活数据,从而提供更有用的建议。
另外用户目前将 Gemini 设为默认辅助工具之后,还能总结或回答有关网页或截图的问题,判断屏幕上是否有视频,并根据你提出相关问题,Gemini 会基于视频的字幕来寻找答案,另外还支持分析 PDF 文件等等。
谷歌预告推出安卓 15 Beta 2 更新
AI 检测诈骗电话
对于在通话中提醒可能存在的诈骗行为,使用 Gemini Nano 在通话过程中去检测到诈骗相关的对话模式时,会提供实时警报,例如,如果 "银行代表" 要求紧急转账、使用礼品卡付款或要求提供卡 PIN 码或密码等个人信息,用户就会收到提醒,这种保护全部发生在设备上,因此用户的对话也会是私密的。
谷歌开源安卓版 Gameface
谷歌开源了 https://github.com/google/project-gameface ,它是支持用户通过表情控制光标,目前支持 Window 和 Android 平台,可以在游戏中控制鼠标光标,目标用户是选择使用面部控制和头部运动进行游戏的人。
开发
Android Studio
在本次 I/O 之前 Android Studio 就发布了Jellyfish | 2023.3.1正式版,里面就着重介绍了 Gemini AI 的能力,本次 I/O 发布了 Android Studio Koala | 2024.1.1 Beta 1 ,现在你可以在 Android Studio Koala 中使用 Gemini 提供自定义提示以生成代码建议,可以通过 View > Tool Windows > Gemini 启用后,右键通过 Gemini > Transform selected code 查看提示字段。
另外 Gemini 还会提供关于崩溃报告的建议,还提供了模板 Gemini API 的集成支持等等。
目前在 Android Studio 中的 Gemini 预览阶段,暂时向所有用户免费提供 Gemini 1.0 Pro ,Gemini 1.5 Pro 型号将于今年晚些时候登陆 Android Studio。
另外相关支持还有:
-
Android 远程流媒体设备支持,可以连接到 Google 数据中心托管的远程物理 Android 设备
-
Android Studio Koala Feature Drop 现在可以轻松区分低性能 USB 和高性能 USB
-
Android Studio Profiler 改进
-
Glance 预览,Android Studio Koala Feature Drop 可以直接在 IDE 中预览 Jetpack Compose Glance (1.1.0-rc01)
-
默认启用 Compose 实时编辑,Android Studio Koala 下实时编辑默认在手动模式下启用,并提高了稳定性和更强大的更改检测,包括对导入语句的支持。
-
Compose 预览屏幕截图测试插件,Compose 预览屏幕截图测试插件的第一个 alpha 版本作为单独的插件提供,可与 AGP 8.5.0-beta01 或更高版本一起使用
Kotlin Multiplatform
Kotlin Multiplatform 由 JetBrains 开发,通过将 Kotlin 编译为平台原生二进制文件,提供了一种跨平台共享代码的新颖方法。
核心:Kotlin Multiplatform 的是 JetBrains 主导,Android 提供支持。
目前许多库都提供对 Kotlin Multiplatform 的内置支持,从而简化跨平台开发体验,例如:
- Ktor通过处理 REST 服务消耗来简化网络任务,
- kotlinx.serialization将数据转换为 JSON 等格式
- Okio管理基本的文件 I/O
- SKIE 适配了类型和协程在 iOS 上的使用
- CocoaPods 集成支持使用 iOS 特定的依赖项
谷歌与 JetBrains 和 Kotlin 开发者社区合作,为许多 Jetpack 库添加了 Kotlin 多平台支持,并在某些情况下提供 iOS 平台目标,而在其他情况下,JetBrains 和社区提供多平台发行版。
如今,Annotations、Collections 和 DataStore 库都在稳定版本中支持 Kotlin Multiplatform,另外还添加了对验证 iOS 平台目标的二进制兼容性的支持,使其与 Android 的标准保持一致。
除了上面的库之外,目前还在致力于为 Room、 Lifecycle 和 ViewModels 提供 Kotlin 多平台支持,并且现已提供 alpha 版本。
可以说 Kotlin Multiplatform 持续投入的力度还是不错的。
Android 与 JetBrains 合作开发的 Kotlin 编译器,提高了 Kotlin/Native(适用于 iOS 和桌面操作系统)的运行时性能,编译器基准测试显示运行时性能提高了 18%,此外,Android 团队还为 Kotlin Native 编译器的构建时间性能提升做出了贡献,速度提升了 2 倍。
最后 Android Gradle 插件现在正式支持 Kotlin Multiplatform,可以使用简洁的构建定义将 Android 设置为共享代码的平台目标,如下所示:
groovy
plugins {
id("org.jetbrains.kotlin.multiplatform")
id("com.android.library")
}
kotlin {
androidTarget {
compilations.all {
kotlinOptions {
jvmTarget = "11"
}
}
}
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach { iosTarget ->
iosTarget.binaries.framework {
baseName = "Shared"
isStatic = true
}
}
sourceSets {
commonMain.dependencies {
// put your Multiplatform dependencies here
}
}
Android 官方也 Github 上了一个 Samples 仓库,使用 Kotlin Multiplatform Room、DataStore 和 Ktor 库来获取、存储和显示数据:https://github.com/android/kotlin-multiplatform-samples
Compose Preview Screenshot Testing
上面介绍 Android Studio Koala 的时候就提到了 Compose 预览屏幕截图测试插件,屏幕截图测试是一种自动化测试,它会截取一段 UI 的屏幕截图,然后将其与之前批准的参考图像进行比较,如果图像不匹配,测试就会失败,并生成 HTML 报告来帮助比较并找出差异。
更多可见:https://developer.android.com/studio/preview/compose-screenshot-testing
Jetpack Compose 的新增功能
共享元素转换
现在 Modifier.sharedElement()
和 Modifier.sharedBounds()
已添加到 Compose 支持中,它们支持在屏幕之间创建漂亮的过渡,并且比视图系统支持更精细的控制。
将 AnimatedContent
composables 嵌套在 SharedTransitionLayout
中,然后将 Modifier.sharedElement()
或 Modifier.sharedBounds()
添加到想要在屏幕之间共享的内容上 然后 Compose 会将找到具有匹配键的 composables ,并在它们之间平滑过渡。
kotlin
var showDetails by remember {
mutableStateOf(false)
}
SharedTransitionLayout {
AnimatedContent(
showDetails,
label = "basic_transition"
) { targetState ->
if (!targetState) {
MainContent(
onShowDetails = {
showDetails = true
},
animatedVisibilityScope = this@AnimatedContent,
sharedTransitionScope = this@SharedTransitionLayout
)
} else {
DetailsContent(
onBack = {
showDetails = false
},
animatedVisibilityScope = this@AnimatedContent,
sharedTransitionScope = this@SharedTransitionLayout
)
}
}
}
另外,Android 15 中的导航和预测性返回动画,也可以与共享元素过渡顺利配合,更多可见:https://developer.android.com/develop/ui/compose/animation/shared-elements
惰性列表项动画
Lazy row 和 column 现在能够自动对项目的插入、删除和重新排序进行动画处理,你只需将Modifier.animateItem()
添加到列表里,操作的更改就会自动呈现动画,另外还可以通过提供不同的动画规范来自定义动画。
kotlin
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
var list by remember { mutableStateOf(listOf("A", "B", "C")) }
Column {
Button(onClick = { list = list + "D" }) {
Text("Add new item")
}
Button(onClick = { list = list.shuffled() }) {
Text("Shuffle")
}
LazyColumn {
items(list, key = { it }) {
Text("Item $it", Modifier.animateItem())
}
}
}
Text
Text 现在通过新的 AnnotatedString.fromHtml() 扩展支持内联链接和基本 HTML 格式,这会转换基本的 HTML 格式,包括指向 AnnotatedString 的链接,然后由 Compose 展示。
kotlin
// First, download a string as a plain text using one of the resources' methods. At this stage
// you will be handling plurals and formatted strings in needed. Moreover, the string will be
// resolved with respect to the current locale and available translations.
val string = stringResource(id = R.string.example)
// Next, convert a string marked with HTML tags into AnnotatedString to be displayed by Text
val styledAnnotatedString = AnnotatedString.fromHtml(htmlString = string)
BasicText(styledAnnotatedString)
BasicTextField 配合 TextFieldState 的 overload,可以做到支持键盘 gif 等丰富内容,并且还可以从组件中提升并异步更新。
kotlin
// Demonstrates how to use the decorator API on BasicTextField
val state = rememberTextFieldState("Hello, World!")
BasicTextField(
state = state,
decorator = { innerTextField ->
// Because the decorator is used, the whole Row gets the same behaviour as the internal
// input field would have otherwise. For example, there is no need to add a
// `Modifier.clickable` to the Row anymore to bring the text field into focus when user
// taps on a larger text field area which includes paddings and the icon areas.
Row(
Modifier
.background(Color.LightGray, RoundedCornerShape(percent = 30))
.padding(16.dp)
) {
Icon(Icons.Default.MailOutline, contentDescription = "Mail Icon")
Spacer(Modifier.width(16.dp))
innerTextField()
}
}
)
Contextual Flow Layouts
ContextualFlowRow 和 ContextualFlowColumn 适合惰性流布局,给定最大行数,流布局将组成尽可能多的适合的项目,然后为开发者提供渲染内容的上下文,有了这个上下文,就可以渲染一个自定义展开指示器,显示剩余项目的计数。
kotlin
@OptIn(ExperimentalLayoutApi::class)
@Composable
private fun SuggestedSnacks(
snacks: List<Snack>,
onSnackClick: (Snack) -> Unit,
modifier: Modifier = Modifier
) {
var maxLines by remember { mutableIntStateOf(1) }
ContextualFlowRow(
maxLines = maxLines,
overflow = ContextualFlowRowOverflow.expandIndicator {
val remainingItems = totalItemCount - shownItemCount
MyOverflowIndicator(
remainingItems = remainingItems,
modifier = Modifier
.clickable {
// Expand the max lines on click
maxLines += 1
}
)
},
itemCount = snacks.size
) { index ->
val snack = snacks[index]
SnackItem(snack, onSnackClick)
}
}
性能改进
与 1 月份的版本相比, Jetsnack 的首次像素基准测试时间缩短了 17%,下图显示了 Jetsnack 在每个 Compose 版本中的改进,自 2023 年 8 月版本以来, Jetsnack 首次绘制像素的时间几乎减少了一半:
Indication API 已被重写,从而支持延迟创建 ripples,这对于滚动性能非常重要,对于大多数应用来说应该不需要进行任何更改,但如果你有自定义 Indication ,升级可能会带来重大更改。
Strong skipping mode
Strong skipping mode 现在正式投入生产,在即将发布的 2.0.20 编译器版本将默认启用此功能。
Strong skipping mode 允许跳过具有不稳定参数的可组合项,从而简化了 composable 的 skipped,这意味着会有更多的 composable 将自动跳过,从而减少手动将类注释为稳定的需要。
Now In Android 示例在启用 Strong skipping mode 时,主屏幕重组时间缩短了 20%,更多可见:https://developer.android.com/develop/ui/compose/performance/stability/strongskipping?hl=zh-cn
Compose 编译器移至 Kotlin 存储库
Compose 编译器将从 Kotlin 2.0 开始托管在 Kotlin 存储库中,这意味着开发者不再需要等待匹配的 Compose 编译器发布来升级的 Kotlin 版本。
Compose adaptive layouts
使用 Compose adaptive layouts 构建全新的自适应布局,让 App 设计适应手机之外的应用,包括Compose for TV 和 Compose for Wear OS ,详细可见:https://developer.android.com/develop/ui/compose/layouts/adaptive
Navigation Compose 类型安全
从 Jetpack Navigation 2.8.0-alpha08 开始,导航组件具有基于 Kotlin 序列化的完整类型安全支持,可以用于在使用 Kotlin DSL 时定义导航图,旨在与 Navigation Compose 等集成完美配合。
现在,可以将导航目的地和参数定义为可序列化对象,将导航目的地和参数定义为可序列化对象。
// Define a home destination that doesn't take any arguments
@Serializable
object Home
// Define a profile destination that takes an ID
@Serializable
data class Profile(val id: String)
NavHost(navController, startDestination = Home) {
composable<Home> {
HomeScreen(onNavigateToProfile = { id ->
navController.navigate(Profile(id))
})
}
composable<Profile> { backStackEntry ->
val profile: Profile = backStackEntry.toRoute()
ProfileScreen(profile)
}
}
CameraX 合成
针对 Compose 将会有一个特定的 CameraX 库,称为 camera-viewfinder-compose,在第一个 alpha 版本中,可以使用新的取景器在屏幕上显示相机预览,无论调整窗口大小、展开设备还是更改显示或方向,该预览始终显示正确的宽高比和旋转。
它还可以正确处理相机和 surface 的生命周期,还支持在相机坐标系中进行复杂的交互,这样可以让开发者轻松实现点击对焦或捏合缩放等手势。