close

作者:callmepeanut來源:https://juejin.cn/post/6964737926617890853

背景

64位的應用性能更好,也能運行在未來僅支持 64 位架構的設備上。目前各個應用市場也對 64 適配提出了要求。

Google Play:

自 2019 年 8 月 1 日起,在 Google Play 上發布的應用必須支持 64 位架構。

國內:

小米應用商店與OPPO應用商店、vivo應用商店等已經發出通知

2021年12月底:現有和新發布的應用/遊戲,需上傳包含64位包體的APK包(支持雙包在架,和64位兼容32位的兩個形式,不再接收僅支持32位的APK包)

2022年8月底:硬件支持64位的系統,將僅接收含64位版本的APK包

2023年底:硬件將僅支持64位APK,32位應用無法在終端上運行

32 和 64 位區別

這裡需要先說一下 CPU 類型,每種 CPU 類型對應了一種 ABI(Application Binary Interface),常見的 abi 有armeabi、armeabi-v7a、arm64-v8a、x86、x86_64 等。

armeabi: 第5代、第6代的ARM處理器,早期的手機用的比較多,基本可以淘汰了

armeabiv-v7a: 第7代及以上的 ARM 處理器。2011年15月以後的生產的大部分Android設備都使用它

arm64-v8a: 第8代、64位ARM處理器

x86: 平板、模擬器用得比較多

x86_64: 64位的平板

這裡主要看 arm 架構的,新的架構能夠兼容舊的 abi 對應的 so,例如 arm64-v8a 架構的 CPU 能夠運行 armeabi-v7a 架構的so,反過來不行,這就是為什麼現在很多 APP 只包含 armeabi-v7a 的包但是能夠在最新的 CPU 上運行。如果以後的 CPU不再兼容舊的架構了的話,現在只包含 armeabi 或者 armeabi-v7a 架構的 APP 就不能再運行了。

那如果同時包含兩種架構呢?如果是支持 64 位系統的機器,會有兩個Zygote(一個32位,一個64位)進程同時運行。APP 安裝的時候根據 lib目錄裡面支持的架構和機器自己的 CPU 類型來決定 primaryCpuAbi,在啟動的時候會根據安裝時候確定的 primaryCpuAbi的值來決定是從64位還是32位的Zygote進程fork出子進程,如果從 64的 fork,則是以64位模式運行。

是否已滿足 64 位要求

如果沒有使用任何原生代碼,那就已經滿足 64 位的要求了。如何查看是否有使用原生庫?,比較快捷的方法是使用 Android Studio 提供的 APK分析器。入口在菜單 Build > Analyze APK…

查看 lib 文件夾,如果里只有 armeabi 或者 armeabi-v7a 文件夾,就是只支持 32 位,不支持 64 位。 如果同時還有arm64-v8a 文件夾,則說明有 64 位原生庫,是否與 32 位有相同的功能和質量,還需要進行測試。

快速找出不支持 64 位的原生庫

應用內的原生庫的來源一般有三處:

第三方庫

工程內的 so 文件

C/C++ 源碼模塊

目前很多第三方庫已經同時支持 32 和 64 位了,但是有些還不支持,如何找出這部分不支持的庫或者文件呢?如果項目中的 so文件數量很多,就很難通過肉眼的方式來查找,這裡提供一個 gradle 腳本可以很方便快速得找出那些不支持 64 位的庫。 在主模塊的build.gradle 最後面添加如下代碼:

1tasks.whenTaskAdded{task-> 2if(task.name=='mergeDebugNativeLibs'){ 3task.doFirst{ 4println("==========================================================") 5defv7a=[] 6defarm64=[] 7it.inputs.files.each{file-> 8if(file.absolutePath.endsWith("/jni")){ 9//println("=========="+file.absolutePath)10if(file.isDirectory()){11file.listFiles().each{soFileDir->12if(soFileDir.absolutePath.contains("armeabi-v7a")){13if(soFileDir.isDirectory()){14soFileDir.listFiles().each{15println(it.absolutePath)16v7a.add(it.name)17}18}19}20if(soFileDir.absolutePath.contains("arm64-v8a")){21if(soFileDir.isDirectory()){22soFileDir.listFiles().each{23println(it.absolutePath)24arm64.add(it.name)25}26}27}28}29}30}31}32println("v7asize:${v7a.size()}")33println("arm64size:${arm64.size()}")34println("soinv7a,butnotinarm64:")35v7a.each{36if(!arm64.contains(it)){37println("$it")38}39}40println("==========================================================")41}42}43}

然後執行 .\gradlew assembleDebug,這裡的 Debug 可以根據實際項目中的 Flavor 進行替換。Demo 工程的輸出如下:

1>Task:app:mergeDebugNativeLibs 2========================================================== 3xxx\5d0e00f6a703ec622708978bebed0322\mmkv-static-1.2.8\jni\arm64-v8a\libmmkv.so 4xxx\5d0e00f6a703ec622708978bebed0322\mmkv-static-1.2.8\jni\armeabi-v7a\libmmkv.so 5xxx\7206efbbb5863dbe5969c1c384b81177\openDefault-4.2.7\jni\armeabi-v7a\libweibosdkcore.so 6xxx\ccd11b53aab95a933b06ef9e74f9fb44\sentry-android-ndk-3.1.3\jni\arm64-v8a\libsentry-android.so 7xxx\ccd11b53aab95a933b06ef9e74f9fb44\sentry-android-ndk-3.1.3\jni\arm64-v8a\libsentry.so 8xxx\ccd11b53aab95a933b06ef9e74f9fb44\sentry-android-ndk-3.1.3\jni\armeabi-v7a\libsentry-android.so 9xxx\ccd11b53aab95a933b06ef9e74f9fb44\sentry-android-ndk-3.1.3\jni\armeabi-v7a\libsentry.so10v7asize:411arm64size:312soinv7a,butnotinarm64:13libweibosdkcore.so14==========================================================

從輸出可以快速看出哪些已經支持 64 位,找到哪些還不支持 64 位的 so 文件,以及他們所在的路徑。

Demo工程見:github.com/callmepeanu…

適配 64 位

找到不支持 64 位的 so 列表後,如果是第三方庫或者從外部引入的 so 文件,需要看是否有適配過 64 位的新版本,或者找提供方獲取支持 64位的版本。 如果是自己項目中的 C/C++ 源碼編譯出來的,需要在編譯選項和源碼層面做對 64 位架構的適配並生成對應架構的 so 庫文件。

打包

可以把所有支持的 abi 的 so 都打在一個包里,這樣一個安裝包就可以適配所有設備,缺點就是包體積會增大,特別是原生庫比較多的情況。目前應用市場提供了分別上傳32位兼容包和64位包的能力,所以可以利用構建多個 APK 的能力來打出支持不同 abi 的包,應用市場根據用戶手機 CPU類型分發對應的包,可以減少用戶下載包的大小。 支持構建多個 APK 只需要在 build.gradle 中添加如下配置:

1android{ 2 3... 4 5splits{ 6abi{ 7enabletrue 8reset() 9include'armeabi-v7a','arm64-v8a'10universalApkfalse11}12}13}

生成的安裝包如下圖所示:

image.png參考:

developer.android.com/distribute/…

www.fresco-cn.org/docs/multip…

www.infoq.cn/article/8wa…

dev.mi.com/distribute/…

dev.mi.com/distribute/…

developer.android.com/studio/buil…

推薦閱讀:

Android IO監控 | 性能監控系列

RxJava 堆棧異常信息顯示不全,怎麼搞

程序員該如何寫好自己的簡歷,一位 5 年中大廠老哥跟你聊聊

面試官:簡歷上最好不要寫Glide,不是問源碼那麼簡單

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 鑽石舞台 的頭像
    鑽石舞台

    鑽石舞台

    鑽石舞台 發表在 痞客邦 留言(0) 人氣()