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 或更高版本一起使用
更多詳細可見:https://android-developers.googleblog.com/2024/05/google-io-2024-whats-new-in-android-development-tools.html
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 設置為共享代碼的平臺目標,如下所示:
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
更多可見:https://android-developers.googleblog.com/2024/05/android-support-for-kotlin-multiplatform-to-share-business-logic-across-mobile-web-server-desktop.html
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 ,并在它們之間平滑過渡。
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()
添加到列表里,操作的更改就會自動呈現動畫,另外還可以通過提供不同的動畫規范來自定義動畫。
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.Modifiervar 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())}}
}
更多可見:https://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/LazyItemScope#(androidx.compose.ui.Modifier).animateItem(androidx.compose.animation.core.FiniteAnimationSpec,androidx.compose.animation.core.FiniteAnimationSpec,androidx.compose.animation.core.FiniteAnimationSpec)
Text
Text 現在通過新的 AnnotatedString.fromHtml() 擴展支持內聯鏈接和基本 HTML 格式,這會轉換基本的 HTML 格式,包括指向 AnnotatedString 的鏈接,然后由 Compose 展示。
// 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 等豐富內容,并且還可以從組件中提升并異步更新。
// 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()}}
)
注意:Material TextField 將在后續版本中更新為使用新的 BasicTextField,更多可見https://developer.android.com/reference/kotlin/androidx/compose/foundation/text/package-summary#BasicTextField(androidx.compose.foundation.text.input.TextFieldState,androidx.compose.ui.Modifier,kotlin.Boolean,kotlin.Boolean,androidx.compose.foundation.text.input.InputTransformation,androidx.compose.ui.text.TextStyle,androidx.compose.foundation.text.KeyboardOptions,androidx.compose.foundation.text.input.KeyboardActionHandler,androidx.compose.foundation.text.input.TextFieldLineLimits,kotlin.Function2,androidx.compose.foundation.interaction.MutableInteractionSource,androidx.compose.ui.graphics.Brush,androidx.compose.foundation.text.input.OutputTransformation,androidx.compose.foundation.text.input.TextFieldDecorator,androidx.compose.foundation.ScrollState)
Contextual Flow Layouts
ContextualFlowRow 和 ContextualFlowColumn 適合惰性流布局,給定最大行數,流布局將組成盡可能多的適合的項目,然后為開發者提供渲染內容的上下文,有了這個上下文,就可以渲染一個自定義展開指示器,顯示剩余項目的計數。
@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 - shownItemCountMyOverflowIndicator(remainingItems = remainingItems,modifier = Modifier.clickable {// Expand the max lines on clickmaxLines += 1})},itemCount = snacks.size) { index ->val snack = snacks[index]SnackItem(snack, onSnackClick)}
}
性能改進
與 1 月份的版本相比, Jetsnack 的首次像素基準測試時間縮短了 17%,下圖顯示了 Jetsnack 在每個 Compose 版本中的改進,自 2023 年 8 月版本以來, Jetsnack 首次繪制像素的時間幾乎減少了一半:
Indication API 已被重寫,從而支持延遲創建 ripples,這對于滾動性能非常重要,對于大多數應用來說應該不需要進行任何更改,但如果你有自定義 Indication ,升級可能會帶來重大更改。
更多可見 :https://developer.android.com/develop/ui/compose/touch-input/user-interactions/migrate-indication-ripple?hl=zh-cn
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 的生命周期,還支持在相機坐標系中進行復雜的交互,這樣可以讓開發者輕松實現點擊對焦或捏合縮放等手勢。