APK瘦身屬性——android:extractNativeLibs

xiaxveliang 發表於 2021-03-26

先描述一下結論:

android:extractNativeLibs = true時,gradle打包時會對工程中的so庫進行壓縮,最終生成apk包的體積會減小
但使用者在手機端進行apk安裝時,系統會對壓縮後的so庫進行解壓,從而造成使用者安裝apk的時間變長

關於android:extractNativeLibs預設值設定方面,若開發人員未對android:extractNativeLibs進行特殊配置:

  • minSdkVersion < 23 或 Android Gradle plugin < 3.6.0情況下,打包時 android:extractNativeLibs=true
  • minSdkVersion >= 23 並且 Android Gradle plugin >= 3.6.0情況下,打包時android:extractNativeLibs=false

一、起因

偶然發現,使用AndroidStudio將同一Module分別打包為aarapk,兩者佔用的磁碟空間差距巨大:
打包為aar,佔用磁碟空間4.4M;打包為apk,佔用磁碟空間為11.7M;

使用AndroidStudio中 apkanalyzer 對比分析,兩種打包方式so庫 Rwa File Size 差距較大,但兩者的Download Size 大小完全一致:
打包為aar,so庫Rwa File Size為3.4M;打包為apk,so庫Rwa File Size為8.2M;
打包為aar,so庫Download Size為3.3M;打包為apk,so庫Download Size為3.3M;

兩種打包方式 apkanalyzer 對比分析如下:

打包為aar

打包為apk

兩種打包方式Rwa File SizeDownload Size 差距較大,那Raw File SizeDownload Size又是如何定義的呢?

二、Raw File Size & Download Size

官方 view_file_and_size_information: 描述如下:

APK Analyzer shows raw file size and download file size values for each entity, as shown in figure 1. Raw File Size represents the unzipped size of the entity on disk while Download Size represents the estimated compressed size of the entity as it would be delivered by Google Play. The % of Total Download Size indicates the percentage of the APK's total download size the entity represents.

翻譯後:

APK Analyzer 展示每個實體的 Raw File Sizedownload file size
Raw File Size 代表對應實體在磁碟上未進行壓縮的大小;
Download Size 代表對應實體在Google Play中,預估的壓縮後的大小;
% of Total Download Size 代表對應模組實體,在Download Size總大小中所佔百分比。

View file and size information

看到這裡,懷疑:

打包為aar時,AndroidStudio對Module中的so庫進行了壓縮;但打包為apk時,未對Module中的so庫進行壓縮

三、android:extractNativeLibs

查詢相關資料,發現文章Android APK Raw File Size vs Download Size:
文章中提到:
打包APK時,是否對so庫進行壓縮的控制屬性為 android:extractNativeLibs

Android APK Raw File Size vs Download Size

AndroidManifest.xmlextractNativeLibs屬性使用方式:

<application
    android:extractNativeLibs="true">
</application>

3.1、android:extractNativeLibs = true

android:extractNativeLibs = true,進行apk打包時,AndroidStudio會對Module中的so庫進行壓縮,最終得到的apk體積較小。

  • 好處是:使用者在應用市場下載和升級時,因為消耗的流量較小,使用者有更強的下載和升級意願。
  • 缺點是:因為so是壓縮儲存的,因此使用者安裝時,系統會將so解壓出來,重新儲存一份。因此安裝時間會變長,佔用的使用者磁碟儲存空間反而會增大。

3.2、android:extractNativeLibs = false

android:extractNativeLibs = false,進行apk打包時,AndroidStudio不會對Module中的so庫進行壓縮,最終生成的apk體積較大。

  • 好處是:使用者安裝後,直接使用/data/data/your.app.package/lib路徑下的so,沒有額外的so複製操作,相對於android:extractNativeLibs = true而言,節省使用者磁碟儲存空間;

3.3、結論

android:extractNativeLibs = true的設定還是利大於弊的。

設定為true可以工程中的so庫進行壓縮,最終減小生成的apk包大小。至於安裝應用時,因so庫解壓縮而造成的安裝時間增長,相對於帶來的好處(提高應用市場使用者的下載和升級意願)而言,我認為是可接受的。

四、android:extractNativeLibs預設值

android:extractNativeLibs官方API描述如下:

android:extractNativeLibs官方API描述

從android:extractNativeLibs官方API描述中可以瞭解到:

  • 原始碼中 android:extractNativeLibs預設值為true;
  • 編譯器Android Gradle plugin 3.6.0 或更高版本,android:extractNativeLibs預設值為false;

但真的是這樣嗎?一起來探究一下。

4.1、原始碼中extractNativeLibs預設設定

從Android 6.0(API 23)開始,Android frame原始碼中PackageParser.java在讀取android:extractNativeLibs屬性值時,預設值為true;

對應的原始碼路徑:frameworks/base/core/java/android/content/pm/PackageParser.java

if (sa.getBoolean(
        com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
        true)) {
    ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
}

4.2、Android Gradle plugin 3.6.0 或更高版本

編譯器Android Gradle plugin 3.6.0 或更高版本,在構建應用時會預設將 extractNativeLibs 設定為 false

通過觀察編譯後生成的AndroidManifest.xml檔案,發現 gradle 外掛設定預設值為false,是通過在處理AndroidManifest.xml檔案的時,在其中自動插入 android:extractNativeLibs=“false"來實現的
由於 android:extractNativeLibs 這個屬性是在Android 6.0(API 23)引入的,因此如果專案配置 中minSdkVersion < 23 的話,gradle 外掛不會自動插入android:extractNativeLibs=“false"

4.3、結論

開發人員在進行apk打包時,若未對android:extractNativeLibs進行特殊配置:

  • minSdkVersion < 23 或 Android Gradle plugin < 3.6.0,打包時 android:extractNativeLibs=true
  • minSdkVersion >= 23 並且 Android Gradle plugin >= 3.6.0,打包時android:extractNativeLibs=false

五、參考

apkanalyzer:
https://developer.android.com/studio/command-line/apkanalyzer

view_file_and_size_information:
https://developer.android.com/studio/build/apk-analyzer.html#view_file_and_size_information

Android APK Raw File Size vs Download Size:
https://stackoverflow.com/questions/45024723/android-apk-raw-file-size-vs-download-size-how-to-shrink-the-raw-file-size

android:extractNativeLibs:
https://developer.android.com/guide/topics/manifest/application-element.html#extractNativeLibs

Setting android:extractNativeLibs to reduce app size:
https://stackoverflow.com/questions/42998083/setting-androidextractnativelibs-false-to-reduce-app-size

========== THE END ==========

歡迎關注我的公眾號

相關文章