- 原文地址:Google Santa Tracker — Moving to an Android App Bundle
- 原文做者:Chris Banes
- 譯文出自:掘金翻譯計劃
- 本文永久連接:github.com/xitu/gold-m…
- 譯者:phxnirvana
- 校對者:portandbridge
谷歌尋蹤聖誕老人應用(Santa Tracker)遷移到 Android App Bundle 記錄html
本文是 2018 谷歌尋蹤聖誕老人應用改進探索系列文章的第一篇。前端
尋蹤聖誕老人是谷歌每一年都會發布的一款應用,這款應用讓人們能夠在全球追尋聖誕老人的足跡。不幸的是,這款應用在通過幾年的迭代後,體積劇增,2017 年甚至達到了 60MB。咱們在剛剛過去的聖誕季的目標是幫它大量減肥,本文講述了咱們實現該目標的過程。java
若是讀者體驗過 尋蹤聖誕老人應用 的話,就會發現該應用有兩大特點,「追蹤器」讓用戶得以在全球範圍內尋覓聖誕老人,另一系列在十二月提供的小遊戲來幫助用戶享受聖誕季🎄。android
「追蹤器」是該應用的主要功能,也是最多被用戶使用的功能。該功能事實上只在聖誕節前 26 小時(12 月 24 日)可用,在此期間,追蹤器是最多被使用的功能。更準確地說,在 12 月的全部界面使用統計中,37% 是在 12 月 24 日 使用的,而那一天,追蹤器的使用率超過了 65%。ios
那麼,爲何這項功能如此重要呢?只有瞭解咱們的主要特點是什麼,才能讓咱們想明白,哪些是應用首次安裝時最關鍵的功能,哪些是次要的、能夠移到另外 module 中動態下發的功能,這樣就使得咱們的首次安裝體積變小。2017 年發佈的 app 包含所有功能,其中包括所有的遊戲,即便用戶根本不玩這些遊戲。git
是時候對尋蹤聖誕老人動刀子了,咱們設立了將首次下載體積減小到僅僅 10MB 的目標😥。github
什麼,爲何是這個數字?由於數據顯示,相比 100MB 的應用,10MB 的應用提升了 30% 的轉化率。固然,儘管許多應用都在追蹤轉化率,尋蹤聖誕老人卻並非咱們追蹤轉化率的 app。10MB 也是一個嘗試起來很難達到的目標,咱們想看看這到底是不是可行的。關於更多統計背後的信息,能夠閱讀 Google Play 團隊 的這篇文章:後端
讀者可能據說過 Android App Bundle 這項新技術,該技術使得 Google Play 商店能夠動態下發僅僅和用戶設備相關的定製應用。這項技術也幫助咱們開了個好頭。只需上傳 AAB(Android App Bundle)來代替 APK,咱們就立刻讓下載體積減小了將近 20% ,達到了 48.5MB(從 60MB)。們只不過是花了一小步的功夫,就在縮減體積方面邁進了一大步!bash
若是隻打算從本文中學一項技術,必定得是上傳 AAB 來取代 APK。這一小改動有很大機會來節省用戶的時間和金錢。網絡
Google Play 是怎麼實現這種瘦身的呢?這一作法可以分發針對個別設備的優化包,這麼一來,相應工具就能從安裝包中移除全部不適用於設備的語言資源、分辨率資源以及本地庫。好比,若是你的設備設置是 fr-FR
(法語),分辨率是 xxhdpi
,CPU是 arm64-v8a
架構的,下發的 APK 便只會包含必要的資源,而不會包含諸如針對西班牙語本地化的字符串之類的東西。當發現本地化字符串佔用的空間有多大時,你必定會大吃一驚。
不要忘了觀看 Android 開發大會 ’18 上的 ‘優化應用的體積’ 演講來獲取更多信息:
儘管咱們有着良好的開頭,卻仍距離 10MB 的目標十萬八千里!因此咱們開始考慮哪些功能能夠被拆到動態功能模塊中,用戶能夠經過 Play Core library 來獲取所需的模塊。好消息是咱們已經按邏輯分離了一大模塊:遊戲🎮。
因而便有了以下的計劃:將每一個遊戲拆分到單獨的功能模塊中,並只當用戶第一次打開特定遊戲的時候才安裝。聽起來很棒,不是麼?儘管邏輯上游戲都分離了,但基礎代碼卻並無分離。通過數年的功能變遷,它們已經纏纏綿綿難以分離了。應用中的庫模塊層層疊疊,並且處處是重複的資源。
咱們的首要工做是將其解耦和,並在遊戲模塊之間創建足夠清晰的邊界。咱們當心翼翼地分離了所有的遊戲模塊,經過使用新的 com.android.dynamic-feature
Gradle 插件,如今每一個遊戲都是徹底獨立的模塊了。對於那些有着相同依賴的遊戲(好比 ‘Penguin Swim’ 和 ‘Elf Jetpack’ 共享了許多代碼),依賴被添加到 ‘base’ 模塊中,這樣一來,就能夠只安裝一次(同時玩兩個遊戲)了。
正如以前說過的那樣,模塊遷移中佔大頭的工做是已有代碼的從新組織,另外也有一些小的整合工做須要經過 Play Core library 來將其穿插起來。
首先是用戶啓動遊戲時的 UX。咱們首先打開顯示 logo 和遊戲標題的 ‘啓動頁(splash screen)’ activity,過一小段時間再運行遊戲。運行遊戲須要的所有信息都做爲 intent extras 傳送到啓動頁了。數年來該行爲都沒有變化,咱們也並不打算修改這一行爲。相反,咱們從中找到了動態分發功能模塊的切入點。
2018 年咱們更新了啓動行爲,發送了四點信息:遊戲標題、遊戲圖標、要運行的 Activity 類以及該功能模塊的 ID。一旦啓動頁展現出來,就檢查是否安裝了相關模塊。若是安裝了,就直接運行,反之則經過 Play Core library 請求安裝,並展現下載進度條:
咱們在早期測試中發現須要當心處理下載安裝時的場景。咱們並不想由於在用戶處於移動網絡時安裝功能模塊,而無心中讓他們花錢。爲了應對這種情形,咱們在檢測到當前網絡是流量網絡(如移動網絡)時增長了確認對話框:
總體邏輯以下:
/* Copyright 2018 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
override fun onCreate(savedInstanceState: Bundle?) {
// ... 安裝
// 遊戲功能模塊的 Id
val featureModuleId = intent.getStringExtra(...)
if (featureModuleName in splitInstallManager.installedModules) {
// 功能模塊已經安裝,直接運行
launchTargetActivity()
} else {
// 功能模塊沒有安裝,請求安裝
val mgr = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (mgr.activeNetworkInfo?.isConnected == true) {
// 有網絡...
if (mgr.isActiveNetworkMetered) {
// TODO ...流量網絡,請求用戶確認
showMeteredNetworkConfirmDialog()
} else {
// ...不然,直接下載
startModuleInstall(featureModuleId)
}
} else {
// 沒有網絡,顯示錯誤框並退出
onFeatureModuleLaunchFailure()
}
}
}
複製代碼
因爲 Play Core API 的緣故,startModuleInstall()
的方法看起來有些複雜。須要在安裝時添加一個用於回調的 listener,而後再請求安裝,以下所示:
/* Copyright 2018 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
private lateinit var splitInstallManager: SplitInstallManager
private lateinit var installListener: SplitInstallStateUpdatedListener
private fun startModuleInstall(featureModuleId: String) {
// 顯示進度條
progressbar.isVisible = true
progressbar.isIndeterminate = true
// 添加 listener
splitInstallManager.registerListener(installListener)
// 發送請求,開始安裝
val request = SplitInstallRequest.newBuilder()
.addModule(featureModuleId)
.build()
splitInstallManager.startInstall(request)
}
複製代碼
listener 會監聽到安裝完成的信號,而後運行遊戲。能夠在 這裏 找到完整代碼。
若是你讀到這裏了,必定會想知道咱們的成果如何……
Android Studio 分析 App Bundle(以及 APK)的工具至關好用,能夠深刻觀察每一個功能模塊的下載體積。咱們能夠在其中看到咱們應用的初始下載體積是 11.6MB (並無達到 10MB 的目標),總下載體積是 25.5MB。
但……這些值只展現了生成的 Android App Bundle 文件,並無計算 Google Play 動態下發(上文討論過)節省的體積。觀察特定設備下載體積最準確的方式是在 Google Play 開發者控制檯 中。上傳 App Bundle 後,就能夠在 ‘Release Management’ -> ‘Artifact Library’ 看到特定設備的下發包體積:
能夠看到咱們達到了 10MB 的目標,下載體積只有 9.21MB!相比 2017 年 60MB 的應用,咱們減小了 85% 的體積! 🎉🎆
但願本文展現了遷移到 App Bundle 能夠帶給用戶的巨大收益。儘管分離模塊並非什麼舉手之勞,但好的代碼實踐諸如高內聚低耦合也會收益良多。
關於上面的數字還有一小點要注意的是,其中也有咱們使用的其餘體積壓縮技術的功勞,包括 asset 壓縮和遷移到 R8。咱們會在下篇文章中討論這些。
若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。