金九銀十跳槽季如何進階找到合適滿意的工作?
作者:*家偉
來源:https://zhuanlan.zhihu.com/p/36902641
Android App Bundles(以下簡稱AAB)是今年Google I/O大會帶來的一款全新動態化框架,與Instant App不同,AAB是藉助Split Apk完成動態加載。介紹AAB之前,先來了解下SplitApk。
split apks是Android 5.0開始提供多apk構建機制,藉助split apks可以將一個apk基於ABI和屏幕密度兩個維度拆分城多個apk,這樣可以有效減少apk體積。當用戶下載應用程式安裝包時,只會包含對應平臺的so和資源。因為需要google play支持,所以國內就沒戲了。針對不同cpu架構問題,國內應用開發商大部分都會將so文件只放在armabi目錄下,如此做雖然可以有效減少包體積,但可能帶來性能問題。
安裝應用程式時,首先安裝base apk,然後安裝split apks。為了解splite apks運作原理,我們還是結合源碼做簡要分析。因為splite apks是Android 5.0開始支持,所以我們以5.0版本開始分析。
在愛奇藝組件化探索之原理篇文中有介紹相關動態化知識,因此本文不再贅述。
在ApplicationInfo中,增加splites apk相關欄位。
LoadeApk中有PathClassLoader和Resources創建過程。LoadedApk#mClassLoader是PathClassLoader實例引用,接著分析PathClassLoader創建過程。
在創建PathClassLoader時,dex文件路徑包含base app和split apps路徑。LoadedApk#mResources是Resources實例引用,其創建過程如下。
該方法中,split apks資源路徑(LoadedApk#mSplitResDirs)也會被增加至Resources中。
以上簡要介紹split apks加載過程,包括code和resources加載。split apks並不支持動態加載split apk,即base apk 和split apks在app安裝時,全部安裝。但通過split apks工作原理,可以發現其是能夠支持按需加載。
針對split apks的不足,Google今年在其I/O大會上推出AAB,AAB提供動態安裝apk功能,這樣可以進一步減少apk體積,首先來看張圖。
很遺憾,AAB需要google play支持,國內開發者依舊無緣。
從上圖可以看出,AAB較split apks多出on-demand模式。AAB也是基於spilt apks來完成按需加載功能,split apks安裝需要藉助google play來完成。
Base APK: 當用戶下載你的app時,base apk是首個被安裝,所有split apks都能訪問base apk代碼和資源。
Configuration APKs: 這些apks包含特定屏幕密度、CPU架構so文件、語言。當下載base或者feature apk時,google play會根據當前設備特徵下載指定configuration apks。
Dynamic feature APKs: 這些apks包括代碼和資源,當app首次安裝時,它們不會被安裝,在用戶需要使用該feature功能時才會被加載。
更多關於AAB說明,大家可以閱讀官方文檔。下載最新Preview release版Android Studio和AAB Sample,接著我們根據官方Samples來看看如何玩轉AAB。
AAB並不是一個插件化框架,它是利用Android Framework提供的split apks功能完成。所有安裝split apk工作均是通過IPC交由google play完成。(第三方app是沒有安裝split apk能力,只有platform籤名應用才行,或者被Root手機)。
Android Studio新增一項module——Dynamic Feature Module。
在創建dynamic_feature時,有兩個選項是默認勾選的,當然我們也可以更改其狀態。
Enable on-demand: 是否支持按需下載模式。如果不支持,那麼該feature則在安裝app時被安裝。
Fusing: 如果app運行在Android 5.0(不包括5.0)以下,勾選Fusing則表示該feature會被一起打包至完整apk中。
接著分析AAB示例。
在示例中,有四個feature,通過module名很清楚這些feature是舉例介紹如何訪問代碼、資源、so等。
接著反編譯主apk(com.android.application插件生成產物),發現:
所有dynamic feature module的代碼、資源、so並未打包至主apk中。
主apk manifest信息包括所有dynamic feature module的manifest,即feature manifest會被合併至主apk manifest中。
Android App Bundle提供一種全新編譯產物格式文件aab。
如上圖,當選擇Build Bundle(s)時,在主工程build目錄下回生成bundle.aab文件,該文件是壓縮格式文件,因此將其解壓分析。
從aab文件內容,可知其包含base和feature的代碼、資源、so等,同時還有BundleConfig.pb這一配置文件,該配置文件是google play用於拆分apk。如果我們需要在google play上支持動態發布,只需要上傳aab文件即可,後續工作交給google play完成。
另外需要注意的是,如果app運行在4.4及以下設備,則用戶下載的將是完成的apk文件,不支持任何split apks特性。
上圖是AAB文檔提供的一張關於aab文件結構圖,藍色方框區域就是configuration apks支持的配置項。
在之前split apks打包中,是不支持語言配置。
以上簡要介紹了AAB相關知識點,如有興趣深入了解還是查閱官方文檔。
Play Core Library是AAB提供的核心庫,用於下載、安裝dynamic feature模塊。另外,我們也可以用這些API下載on-demand模塊用於instant app。
關於Play Core Library具體如何使用,大家看下文檔,本文主要講解一些原理性知識點。
主工程模塊app,首先分析MainActivity.kt文件。該類是用kotlin編寫,如果沒有接觸過不要緊,大體上還是能看懂。
在MainActivity.kt的onCreate方法中,增加如下邏輯:
列印結果如下:
從運行結果可知,split apks(即使是on-demand模塊)在debug模式下,是緊接著base apk安裝完成後安裝。
SplitInstallManager類提供獲取已安裝模塊方法。
因為Play Core Library非對外暴露接口都是混淆過的,因此就不直接附源碼分析。但通過追蹤分析源碼可知,獲取已安裝模塊的核心過程是:
通過PackageInfo#splitNames欄位獲取。
在示例中,每當我們需要啟動dynamic feature模塊時,都要判斷該模塊是否安裝。如果沒有安裝,則啟動下載,Play Core Library提供了比較完善的下載狀態回調,比如下載進度,下載失敗原因等等。
通過粗略分析這些混淆源碼可知,下載與安裝on-demand模塊均是通過ipc交由google play完成。
當app運行設備版本不高於6.0時,需要使用SplitCompat庫才能立即訪問下載模塊代碼和資源。AAB提供SplitCompatApplication類用於開啟SplitCompat。
在Application#attachBaseContext(Context)中調用SplitCompat.install(Context)。在該方法中主要完成split apks代碼(dex和so)和資源的安裝。
在Android 8.0中,Instant Apps相關代碼嵌入至Framework。因此如果on-demand模塊用於Instant Apps中,需要在on-demand下載成功中,調用SplitInstallHelper.updateAppInfo(Context)
從上述代碼得知其反射調用ActivityThread#dispatchPackageBroadcast方法。最終是調用至LoadedApk#updateApplicationInfo。該方法做了如下事情
重新創建mClassLoader
重新創建mResources
更新applicationInfo(調用LoadedApk#setApplicationInfo完成)。
Play Core庫提供SplitInstallHelper#loadLibrary用於加載C/C++庫。具體用法可以查看示例。
Android App Bundles的出現,相當是官方提供的一套動態化框架,所有的on-demand模塊也會被google play審核,這對用戶來說是非常有利的。
你有什麼想說的?歡迎留言區留言討論!
最後,歡迎大家加入我們的知識星球,這期是到2019年3月10日結束,所以越早加入越好,現在加入的球友快1000人了,到1000人時將大幅提價(還有最後幾十個名額了),所以快上車!