先描述一下結論:
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分別打包為aar
與apk
,兩者占用的磁盤空間差距巨大:
打包為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 對比分析如下:
兩種打包方式Rwa File Size
與Download Size
差距較大,那Raw File Size
與Download 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 Size
與download file size
:
Raw File Size
代表對應實體在磁盤上未進行壓縮的大小;
Download Size
代表對應實體在Google Play中,預估的壓縮后的大小;
% of Total Download Size
代表對應模塊實體,在Download Size總大小中所占百分比。
看到這里,懷疑:
打包為aar時,AndroidStudio對Module中的so庫進行了壓縮;但打包為apk時,未對Module中的so庫進行壓縮
。
三、android:extractNativeLibs
查詢相關資料,發現文章Android APK Raw File Size vs Download Size:
文章中提到:
打包APK時,是否對so庫進行壓縮
的控制屬性為 android:extractNativeLibs
。
AndroidManifest.xml
中extractNativeLibs
屬性使用方式:
<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默認值為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