自從2024年初的時候,谷歌發布了第一個Android15的預覽版,我就一直在關注著這個版本的走向,為什麼呢?因為據說Android15裡面的變化非常大,後來事實證明果真如此,無論是特性上的改動如預測性返回、邊緣到邊緣還是16kb內存頁面,或者是編譯環境上的改動如targetSdkVersion、Agp、gradle以及jdk的一些升級,都讓我覺得這次升級非同一般,來勢洶洶,不是那麼好對付,不過好在之前工作上都沒有海外上的業務,國內的應用商店對應用的targetSdk也沒有太強制的要求,所以Android15跟我都一直保持著一種敵不動我不動的和平局勢,不過局勢終將被打破了...
前段時間經歷了裁員以及三個月的找工作,讓我深刻體會到了嚴峻的行業局勢以及可怕的就業壓力,促使我不得不降低自己的底線,面了各種未曾嘗試過的崗位面試,如車載、FW或者面向谷歌市場開發,有一次面試中:
然後offer就來了...雖然明白這個offer不是那麼好接,入職後主要任務就是跟谷歌的一系列政策鬥法,但由於行情實在是不容樂觀,招聘市場上已經被一堆外包跟短期項目搞得烏煙瘴氣了,考慮再三還是接下了這個offer,於是乎我跟Android15之間的鬥爭也拉開了序幕
接手到項目後,無意外的被分配到的第一個任務就是谷歌市場合規要求,適配Android15,不得不感慨不到兩年前還在慶幸自己與Android15無緣,誰知道這麼快就要跟這個「大魔王」面對面接觸,實在是世事難料,應了那句話,出來混的,終究要還的,吃Android這碗飯,就要做好適配各種Android新版本的準備,不過另我感到欣慰的是項目並不是特別的老,讓我產生一種錯覺,應該沒有想像中的那麼費勁,項目基本配置如下

既然如此,廢話不多說了,咱先把targetSdk跟compileSdk都升級到35再說,萬一跑下來沒啥問題呢,我就嘻嘻了,修改了一下gradle.properties中的幾個變數

sync一下後發現沒啥問題,嗯?就這?run一下試試,發現果然報錯了,瞬間不嘻嘻

報了個無法加載sdk路徑下/platforms/android-35/android.jar的這個文件,有點摸不著頭腦,查了一下馬上就知道了,原因很簡單,項目中使用的gradle插件以及AGP插件已經不支持targetSdk35了,必須要升級了,升到多少呢,官方文檔上看看去


寫的很清楚了,當升級到target35後,AGP版本最低需要8.6,此版本對應的gradle最低版本是8.7,那麼開始升級這兩個插件
首先將項目中gradle/wrapper/gradle-wrapper.properties中的以下代碼

替換成

然後再把根目錄build.gradle文件裡面的AGP插件從

替換成

一頓操作之後心裡就犯怵,這兩個插件一下子都抬高了一個大版本,真的沒問題嗎?編譯下看看吧,果然怕啥來啥,出現以下報紅

不過還好還算容易懂,現在用的jdk版本11過低了,需要用更高的jdk版本17才可以。
沒想到剛開始還沒幹啥呢,隨著升完gradle與AGP之後,jdk版本也要升級了,一下子就感到疑惑了起來,要知道jdk11這個版本大多數項目還是在用的,不過人家gradle插件的changelog裡面可是寫的清清楚楚,升級到8.0後,jdk的最小版本就要求必須是17了

那就升吧,升這個東西沒啥難的,左上角Android Studio->Settings->Build Tools->Gradle裡面選擇JDK17,沒有的話就去下個

Apply並且ok後我們再編譯看看

這真是頭一次見啊,說的啥debug的build type有一些自定義的BuildConfig的變量,但是被禁用了,說的應該是下面這段代碼

這段代碼很常見,大多數項目中都會在buildTypes裡面定義一些buildConfigField變量,用來區分生產環境跟debug環境,我這裡定義了一個布林類型的Coffee_Test值為true的變量,現在說的是這個已經被禁用了,肯定又是升級gradle帶來的副作用,果然在AGP8.0的更新中就有看到

同時解決方法也很簡單,就是在每個定義過自定義變量的模塊的build.gradle文件下添加一句代碼android.buildFeatures.buildConfig true就可以了,像這樣

這個問題也就解決了

隨著再次編譯,又出現上述報錯,跟之前的BuildConfig類似,這次是要求在每個模塊的build文件中需要添加個namespace的命名空間,這個變更是在AGP7.3中出現,但是AGP8.0就要被強制執行

通常這個命名空間就是指的是當前模塊的包名,所以可以看到報錯紅字下方也提示了,可以借助AGP的升級助手來完成這一步,完成後在你的build.gradle文件中就會多出一行配置

上面說的添加android.buildFeatures.buildConfig true以及命名空間的做法,在一些小型,模塊沒幾個的項目中,配置起來不是特別難受,但是若是項目規模大一些,動輒十幾個幾十個模塊的話,逐個加那就真的是件很痛苦的事情,那麼有沒有輕鬆一點的辦法呢?第一個想到的就是新增一個common.gradle的文件,在裡面添加一些諸如android.buildFeatures.buildConfig true這樣的配置,然後其他模塊引入這個common.gradle文件,倒是可以達到效果,但是存在著一些缺點
所以我這裡選擇的是在項目的根目錄的gradle文件中使用subprojects,動態給每個參與到編譯的模塊添加android.buildFeatures.buildConfig true以及命名空間,代碼如下

如果這個模塊沒有定義過命名空間,比如依賴的一些源碼庫,那麼才會給這個模塊添加命名空間,至於buildConfig,由於我不知道如何判斷gradle文件中已經聲明過自定義變量了,所以只能全量添加,這樣就能避免某些模塊因漏加這兩個配置而產生編譯報錯
言歸正傳,剛才已經添加完namespace了,我心裡琢磨著這下應該差不多了吧,可以正常跑了吧,誰知道Android15給我憋了坨大的,報出以下紅字

莫名其妙啊,怎麼有些string資源說找不到就找不到了呢?開始沒太在意,琢磨著補全R路徑就好了,類似於這樣

這種又奇葩又醜的方式不用想肯定也知道沒法解決本質問題,果然再次編譯後又報出來一堆找不到資源的R文件,其中包括layout、color、drawable等,這下徹底凌亂了,肯定不能一個個路徑去補全,心想這麼大的事官網上肯定會有說明吧,找找看果然在gradle8.0的更新日誌裡以及設置命名空間的介紹裡找到了具體更新信息,谷歌引入namespace的主要原因是為了以後在每個模塊裡面,只會生成當前模塊下的資源文件,其他子模塊的資源文件就不會生成了,若要訪問的話必須使用對應命名空間導入R類,我認為谷歌這一改動就是為了加速構建速度吧,但是真的要我們開發者一個個資源前面補全路徑嗎,當然不會,谷歌還是給出了對策的

在標誌項的表格中就看到了兩個跟R文件相關的設置
R 類R 類將這兩個設置加在gradle.properties中後,項目果然可以正常運行了,不容易!終於可以提測了!
還是以前搞適配沒啥壓力啊,每個版本出來就一點變動,現在這個Android15著實有點費體力,光一個編譯環境都折騰了那麼久,瞅瞅這些坑,我寫都寫半天,更別說一個個踩了,那些新出來的特性都還沒開始正經適配,休息一下,下一篇文章正式領教下edge-to-edge以及16kb內存頁面