這一次谷歌很強硬,App 再不支持,兩個月後將拒絕上架!

一. 序

事情是這樣的,前幾天收到 Google Play 的通知郵件,這纔想起來有幾款在 Google Play 上架的 App,還沒有支持 64 位 CPU 架構。

早在今年一月份,Google 就發佈通知,在今年 8 月 1 日開始,上架的 App,除了提供 32 位的版本之外,還需要提供 64 位的版本。

這眼看着離強制升級窗口,只剩下最後兩個月的時間,很多第三放來源的 so 支持庫,如果沒有提供 64 位的版本,還需要同步催促合作方更新。

那今天就來聊聊 Android APK 升級 64 位 CUP 架構的細節,看看你的應用是否需要支持 64 位 CPU 架構,如果要支持,需要做什麼?

二. Android CPU 架構細節

2.1 這是強制規範

早在 2015 年 Google 發佈 Android 5.0 版本時,就加入了 64 位處理器的支持,當時就提出了以 19 年 8 月爲最後的更新支持期限,並在今年又重申了這個強制要求。

只要你的 App 存在國際版,需要上架 Google Play,這個規定都必須準守。

2.2 那些 APK 需要支持 64 位?

那假如你有一個國際化的 App 需要維護,在今年 8 月 1 日之後,更新 Google Play 時,就必須提供 64 位的版本。

那這裏說的 64 位版本支持,到底是什麼?

如果你的應用,完全是使用 Java 或者 Kotlin 編寫代碼,不包含任何原生(Native)的支持,那麼就表示這個應用已經支持 64 位。

但是應用內使用了任何原生(Native)的支持(so 庫),就需要針對這些 so 文件,針對不同的 CPU 架構提供不同的版本的 so 支持。

需要注意的是,有些時候,在我們自身的代碼中,確實沒有用到原生的支持,但是在 App 中使用的一些第三方庫中卻包含了。

此時最穩妥的方式,就是針對最終打包生成的 APK 文件進行分析,來判斷是否需要提供 64 位架構的支持。

那 CPU 架構是什麼?什麼又是 ABIs?

在 Android 中,雖然 ARM 的 CPU 架構是主流,但是目前至少支持幾類 CPU 架構,ARM 下的 ARMv5/ARMv7/ARMv8,x86 下的 x86/x86_64,以及很不常見的 MIPS 類架構。這裏的每一種 CPU 類型對應了一種 API(Application Binary Interface),例如 armeabi-v7a 中的 "armeabi"  指的就是 ARM 這種類型的 ABI,後面的 “v7a” 指的是 ARMv7。

通常我們可以簡單的理解:

這三個概念是相通的,通常在技術討論中,說的是一個東西。

2.3 爲什麼是強制的?

谷歌之所以會有強制更新的要求,很大一方面原因是因爲作爲開發者,更新補全 ABIs 的動力並不足。

主要原因來自以下幾個方面:

1. APK 體積增大

針對不同 CPU 架構提供對應的 so 庫,當然是效率最高的做法。但是這種做法,最直接的影響,就是 APK 文件的增大,有些時候補全這些 so 支持,會導致整個 APK 體積有幾 MB 到幾十 MB 的增幅。

APK 體積優化,很多公司都將其算做是一個 API 指標,加入一個新特性,導致 APK 體積的增大,在很多時候都是不允許的,爲此換技術方案都是常有的事。

從增長的角度來看,越小的 APK,用戶下載的意願就更大,轉化率就越高。

但是隨着現在流量越來越便宜,近期 iOS 已經將 蜂窩數據下載限制從 150MB 放寬至 200MB,針對安裝包的體積優化標準,也可以適當的放寬了。

2. 本身有一定的兼容性

應用市場中,很多 APP 其實都只有 armeabi 或者 armeabi-v7a 的支持,而市面上的設備,支持的並不是只有這兩種 CPU 架構。

但是這並沒有影響在這些設備上運行這些 App,這就是 CPU 架構的兼容性。

不同架構,並不意味着之間一定是不兼容的,在不同版本下,其實提供了兩種 ABI 支持,分別是

  • 主要 ABI:與系統本身使用的原生代碼一樣,最優方案。

  • 輔助 ABI:支持的另一個 ABI 方案,兼容方案。

這種兼容策略就不在這裏展開說了,最簡單的就是 64 位的 arm64-v8a 在支持本身的 CPU 架構之外,還兼容支持 armeabi-v7a、armeabi;x86_64 同時也兼容支持 X86 和 armeabi。

你看,雖然添加 64 位的支持,可以有效的使用硬件的優勢,提升性能,但大部分時候,採用兼容方案,是一種更簡單的方式。

3. 沒有對應架構的 so 文件

這個原因就比較尷尬了,我們 App 中使用到的原生代碼,其實有兩種。

一種是我們自己編寫的,源碼在手,想提供對應的支持,修改配置重新編譯一下就解決了。

另一種來自第三方提供的,這種時候我們沒有源碼,無法做到重新編譯,只能和第三方溝通,看能不能提供一個對應 CPU 架構的 so 庫。這種情況就非常的不可控了。

例如比較常見的一個 WebView 的替換方案,騰訊 X5 內核,本身就不提供 X86 的庫。

官方給的建議是使用 armeabi 或者 armeabi-v7a。

在前文有提到,ABIs 本身是有一些兼容規則的,但是這種兼容規則,是有條件的。

舉個例子:64 位的 arm64-v8a 是可以向下兼容的,但是這有個前提,那就是如果你的項目中,有 armeabi-v7a 和 arm64-v8a 兩個目錄,就需要保證這兩個目錄下支持的 so 庫文件保持一致。

在左邊的情況下,如果 arm64-v8a 的手機用到 b.so 時,就會去 arm64-v8a 目錄下找,當然是找不到 b.so 文件的,就會直接拋異常,而不會再去 armeabi-v7a 目錄下繼續尋找。

如果需要提供多套 ABIs 的支持,就需要保證所有 ABI 目錄下,對應的 so 文件保持一致。

而在一些特殊的情況下,我們無法提供對應平臺的 so 庫,例如騰訊 X5 內核這種情況,就需要做個取捨了。

在沒有 Google Play 的強制策略下,同時又因爲各方考慮,大多數時候我們可能會捨棄其他 ABIs 的支持。但是現在既然強制執行了,騰訊 X5 內核就可能升級以提供 64 位的 so 庫,畢竟一邊是無法上架,另外一遍是一個 WebView 的內核,誰都知道怎麼取捨。

三、支持 64 位架構

3.1 是否包含 64 位庫?

介紹了 Android 下 CPU 架構的一些細節,接下來就要開始正題了,如何升級並支持 64 位架構。

從前文中應該瞭解到,支持對應的 ABIs,反映在項目中,就是存在對應 ABIs 架構的目錄,並且目錄中有完備的 so 庫支持。

Google 並不要求我們支持所有的 64 位架構,但是對於已經支持的每種原生 32 位架構,就必須包含對應的 64 位架構。

例如:

  • 對於 ARM 架構,有 armeabi-v7a(32位) 就必須 arm64-v8a(64位)。

  • 對於 x86 架構,有 x86(32位) 就必須有 x86_64(64位)

這就要求我們有對應的目錄,並且目錄中包含對應的 so 文件。APK 中提供了完備的 ABIs 支持,運行的之後,會選取對應的最優支持進行加載和使用。

需要注意的是,有時候我們將 32 位的 so 複製到 64 位中,運行不會出現異常,但是這依然存在隱患。最好的辦法是根據不同的架構,編譯對應的 so 文件,原則上,我們的目標是確保應用可以在僅支持 64  位架構的環境中正常運行。

3.2 判斷是否支持 64 位架構

前面也提到,我們的項目中,可能會引入一些第三方庫,導致在不明確的情況下,引入了一些預期之外的 ABIs 庫。

通常我們的做法是在 Gradle 中增加 abiFilters 過濾,來確保不會在打包輸出的 APK 中存在預期之外的 ABIs 目錄和 so 庫。

ndk {
    //設置支持的SO庫架構
    abiFilters 'armeabi-v7a' 
}

那麼我們拿最終打包輸出的 APK 文件去分析,是最穩妥的辦法。

分析的方法有兩種:

1. AS 的 APK 分析器

在 Android Studio 中,從菜單依次選擇  Build → Analyze APK…

選擇需要分析的 APK 文件,查看其 lib 目錄,是否存在預期的 ABIs 目錄以及完備的 so 文件。

2. 使用 zipinfo 命令進行分析

得到待分析的 APK 文件,就可以通過 zipinfo + grep 命令,輸出其內包含的 so 文件。

> zipinfo -1 YOUR_APK_FILE.apk | grep \.so$
    lib/armeabi-v7a/libmain.so
    lib/armeabi-v7a/libmono.so
    lib/armeabi-v7a/libunity.so
    lib/arm64-v8a/libmain.so
    lib/arm64-v8a/libmono.so
    lib/arm64-v8a/libunity.so

依然是去看對應目錄和 so 文件是否完備。

3.3 在 64 位設備上測試應用

支持 64 位架構是爲了讓我們利用 CPU 的特性,以提升性能,但是穩定依然是我們首先要保證的,所以在升級之後,就需要進行測試。

要測試 App,最簡單的方式是使用 adb 命令安裝該應用,可以配合 --abi 參數,用以指示要將那些 so 庫,安裝到設備上,這樣我們在這個設備上安裝的 App,就會僅包含我們制定的庫。

# 成功安裝 APK :
> adb install --abi armeabi-v7a YOUR_APK_FILE.apk
Success

#
 如果 APK 中不包含 64 位 so 文件:
> adb install --abi arm64-v8a YOUR_APK_FILE.apk
adb: failed to install YOUR_APK_FILE.apk: Failure [INSTALL_FAILED_NO_MATCHING_ABIS: Failed to extract native libraries, res=-113]

#
 如果你的設備(手機)不支持 64 位架構
> adb install --abi arm64-v8a YOUR_APK_FILE.apk
ABI arm64-v8a not supported on this device

去年上市的手機,大部分都是 64 位架構的,找一款來測試即可。

3.4 分包處理

如果我們的應用只需要在國內分發,當前的策略對我們並不影響,保持原樣就好了。但是如果存在國際版,需要上架 Google Play 就一定要重視此次升級。

在 Google Play 上傳 APK,是可以根據 CPU 架構上傳不同的 APK 的,也就是我們可以針對 32 位上傳一個 APK,再上傳一個 64 位的 APK。

此時就需要用到 Gradle 的打包技巧了,分別輸出幾個僅包含對應平臺的 APK,以此完成 Google Play 的要求,分別上傳 32 位的支持 APK 和 64 位的支持 APK,這樣能夠 APK 文件不至於增大很多。

android {
    ... 
    splits {
        abi {
            enable true
            reset()
            include 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a' //select ABIs to build APKs for
            universalApk true //generate an additional APK that contains all the ABIs
        }
    }
    // map for the version code
    project.ext.versionCodes = ['armeabi': 1, 'armeabi-v7a': 2, 'arm64-v8a': 3, 'mips': 5, 'mips64': 6, 'x86': 8, 'x86_64': 9]

    android.applicationVariants.all { variant ->
        // assign different version code for each output
        variant.outputs.each { output ->
            output.versionCodeOverride =
                    project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 0) * 1000000 + android.defaultConfig.versionCode
        }
    }
 }

這裏利用 Gradle 的 splite 配置,有興趣可以直接查閱文檔,就不展開講了。

四. 小結時刻

在本文中,我們藉此次 Google Play 的強制支持 64 位架構的事情,講解了 Android 下 so 庫的一些兼容問題。

如果你在 Google Play 上有應用需要更新,別忘了提前準備需要的 so 庫,大多數原生支持的第三方庫,在此之前其實都已經提供了對應的 64 位架構。我們只需要在最終日期之前,仔細的進行增加 so 文件,以達到適配的效果。

更新完成之後,別忘了測試,本文就到這裏,你有什麼更新的見解,歡迎在留言區討論。

本文對你有幫助嗎?留言、轉發、點好看是最大的支持,謝謝!

reference:

https://developer.android.com/distribute/best-practices/develop/64-bit


聯機圓桌」????推薦我的知識星球,一年 50 個優質問題,上桌聯機學習。

公衆號後臺回覆成長『成長』,將會得到我準備的學習資料,也能回覆『加羣』,一起學習進步;你還能回覆『提問』,向我發起提問。


發佈了327 篇原創文章 · 獲贊 8 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章