...方案—全新的動態化框架Android App Bundles分析 Seasoninthesun

2020-12-15 騰訊網

金九銀十跳槽季如何進階找到合適滿意的工作?

作者:*家偉

來源:https://zhuanlan.zhihu.com/p/36902641

Android App Bundles

Android App Bundles(以下簡稱AAB)是今年Google I/O大會帶來的一款全新動態化框架,與Instant App不同,AAB是藉助Split Apk完成動態加載。介紹AAB之前,先來了解下SplitApk。

Split Apks

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工作原理,可以發現其是能夠支持按需加載。

初識Android App Bundles

針對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功能介紹

AAB並不是一個插件化框架,它是利用Android Framework提供的split apks功能完成。所有安裝split apk工作均是通過IPC交由google play完成。(第三方app是沒有安裝split apk能力,只有platform籤名應用才行,或者被Root手機)。

Dynamic Feature Module

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中。

Build Bundle(s)

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

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完成。

兼容性問題

OS版本不高於6.0

當app運行設備版本不高於6.0時,需要使用SplitCompat庫才能立即訪問下載模塊代碼和資源。AAB提供SplitCompatApplication類用於開啟SplitCompat。

在Application#attachBaseContext(Context)中調用SplitCompat.install(Context)。在該方法中主要完成split apks代碼(dex和so)和資源的安裝。

OS版本不低於8.0

在Android 8.0中,Instant Apps相關代碼嵌入至Framework。因此如果on-demand模塊用於Instant Apps中,需要在on-demand下載成功中,調用SplitInstallHelper.updateAppInfo(Context)

從上述代碼得知其反射調用ActivityThread#dispatchPackageBroadcast方法。最終是調用至LoadedApk#updateApplicationInfo。該方法做了如下事情

重新創建mClassLoader

重新創建mResources

更新applicationInfo(調用LoadedApk#setApplicationInfo完成)。

加載C/C++庫

Play Core庫提供SplitInstallHelper#loadLibrary用於加載C/C++庫。具體用法可以查看示例。

結語

Android App Bundles的出現,相當是官方提供的一套動態化框架,所有的on-demand模塊也會被google play審核,這對用戶來說是非常有利的。

你有什麼想說的?歡迎留言區留言討論!

最後,歡迎大家加入我們的知識星球,這期是到2019年3月10日結束,所以越早加入越好,現在加入的球友快1000人了,到1000人時將大幅提價(還有最後幾十個名額了),所以快上車!

相關焦點

  • 愛奇藝開源 Qigsaw,基於 Android App Bundle 的動態化框架
    Qigsaw是愛奇藝自主研發的動態化框架,其核心優勢如下: 利用Android App Bundle開發套件,極速開發體驗。 支持Android App Bundle所有功能特性,"山寨"Play Core Library公開接口實現,開發者閱讀官方文檔即可愉快開發。
  • 對 Android 未來的發展十分重要的技術 | App Bundles
    哈,標題是我根據官方推送取得,之前剛看到文章,沒想到就有同學已經實踐並分享出來了,如果你對標題表示困惑,強烈建議先閱讀下官方的這篇文章:在今年的Google I/O大會上,Google向 Android 引入了新 App 動態化框架(即Android App Bundle,縮寫為AAB),AAB是藉助Split Apk完成動態加載,使用AAB動態下發方式,可以大幅度減少應用體積
  • Android Crash 案例解決方案
    Log 分析如下IndexOutOfBoundsException Log分析4. IndexOutOfBoundsException 解決方案在使用時判斷對象內容是否為0.IllegalStateException 解決方案IllegalStateException 類異常很多,不同的代碼會有不同的解決方案,上述舉例解決方案如下
  • 最新Android框架排行榜,上百項資源匯總!
    ,9.4k的star數量,也是榜單裡第一個出現的中國開源框架,涉及網絡的app都會用到json,fastjson值得作為你的首選!compile 'de.hdodenhof:circleimageview:2.1.0'}<de.hdodenhof.circleimageview.CircleImageView    xmlns:app="http://schemas.android.com/apk/res-auto"    android:id="@+id/profile_image"    android
  • 移動APP自動化測試框架對比
    本文通過分析幾種自動化框架的異同,使測試人員在選擇自動化框架時有所參考。   https://developer.android.com/reference/android/app/Instrumentation.htmlInstrumentaion是Android自帶的一個測試框架,是很多其它測試框架的基礎
  • 谷歌Flutter 1.7正式發布:支持AndroidX和Android App Bundles
    當創建 Flutter 項目時,可通過添加 --androidx 來確保生成的項目文件支持 AndroidX,更多關於將項目遷移到 AndroidX 的相關信息,請訪問 flutter.dev。我們也在積極努力為使用了 AndroidX 和 Android 混合庫的應用帶去 AndroidX 或 Jetifier 的支持,也會將其作為 add-to-app 中的一項來支持,之後的文章中會為大家帶來更多相關的內容。
  • 最新Android框架排行榜,上百項資源匯總不容錯過
    使用:down源碼,修改學習21.tinker一句話介紹:它是微信官網的Android熱補丁解決方案上榜理由:9.1k個star,微信在用的熱補丁方案,心動不如行動22.ViewPagerIndicator一句話介紹:一款基於ViewPager的頁面指示器開源框架上榜理由:上古神器,儘管已經五年未更新了,但你仍然可以在淘寶等app
  • (烤鴨聽歌學口語)第二十四期--seasoninthesun
    We had joy, we had fun,  we had seasons in the sun;  but the hills that we climb  were just seasons out of time.  Goodbye, Papa, please pray for me,  2.
  • App工程搭建:幾種常見Android代碼架構分析
    本文先分析幾個當今比較流行的android軟體包,最後我們汲取其中覺得優秀的部分,搭建我們自己的通用android工程模板。1. 微盤微盤的架構比較簡單,我把最基本,最主幹的畫了出來:第一層:com.sina.VDisk:com.sina(公司域名)+app(應用程式名稱) 。
  • Qigsaw 1.3.2.2 版本發布,基於 Android App Bundle 組件動態化方案
    Qigsaw 是基於Android App Bundles開發的一套組件動態化方案,你可以享受Android App Bundles的開發工具極速開發體驗。
  • 餓了麼許錦洋:移動動態化方案在蜂鳥的架構演進
    【51CTO活動】8.26 帶你深度了解清華大學、搜狗基於算法的IT運維實踐與探索 【51CTO.com原創稿件】當下,移動動態化已經成為各大公司都迴避不了的問題,產品的快速迭代對技術提出了更高的要求,而移動端的動態化方案也是層出不窮:Hypid
  • Android徹底組件化方案實踐
    但是苦於目前還沒有一個完全合適、完美兼容的插件化方案(RePlugin的飢餓營銷做的很好,但還沒看到療效),特別是對於已經有幾十萬代碼量的一個成熟產品來講,套用任何一個插件化方案都是很危險的工作。所以我們決定先從組件化做起,本著做一個最徹底的組件化方案的思路去進行代碼的重構,下面是最近的思考結果,歡迎大家提出建議和意見。
  • Android DropBox SDK漏洞(CVE-2014-8889)分析
    在許多方面,包括訪問控制功能的app與服務之間的互操作總是具有挑戰性的,為了解決訪問控制來來的挑戰,OAuth1和2等授權協議陸續被提出,它們可以安全地授予app訪問特定服務中個人數據的權限,而又不洩露用戶的個人憑據。為便於開發,這些服務通常為app提供一個框架或SDK,使app能夠和服務進行通信。
  • AOP編程_Android優雅權限框架(1)概念基礎
    正文大綱1、Demo地址2、本文所涉技術盤點3、關於Android權限的梗4、初級/中級/高級android開發的權限請求寫法5、AOP優雅權限框架詳解     gradle配置     Java代碼6、AOP思想以及常用AOP框架
  • (第六講)分析你的第一個 Android 程序 3
    1x0 從 AndroidManifest.xml 入手我們已經知道了項目的結構,那麼下一步就按照應用程式運行的流程來分析吧。你在手機上點擊 apk 文件後,會打開軟體包安裝程序。軟體包安裝程序會讀取 apk 中的 AndroidManifest.xml 文件,從裡面分析出軟體的名字 版本還有各種權限,然後展示給用戶,用戶確定安裝後就會交給框架程序來真正完成安裝。
  • 【移動安全】Android程序分析入門
    前言分析Android程序是開發Android程序的逆過程,要想分析一個Android程序,首先應該了解其開發流程、程序結構、語句分支和解密原理等。package com.droider.tideandroid;import android.os.Bundle;import android.app.Activity;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button
  • Android Studio打包apk,aar,jar包
    一片楓葉_劉超的博客地址:http://blog.csdn.net/qq_23547831作者編寫了github項目解析、android源碼分析以及產品研發多個專題,有興趣的可以關注下學習學習~文本我們將講解android studio打包apk,aar,jar包的相關知識。
  • android app被殺原因專題及常見問題 - CSDN
    分析長按HOME鍵清理App最終會執行到ActivityManagerService.cleanUpRemovedTaskLocked方法中,ActivityManagerService類在文件"frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java"中,
  • 某Android模擬器的廣告植入分析
    這是一個做的還不錯的模擬器,不過它的廣告讓人很煩,考慮先分析看看。
  • android 工具箱
    adb am start -D -n 包/啟動類2) adb forward tcp:你要轉發的埠 jdwp:調轉 app 的 pid3) ida pro attach 進程, 設置新線程,加載 so 時斷點,continue4) jdb -connect com.sun.jdi.SocketAttach:port=轉發的埠,hostname=localhostps