解析 Android 開發(fā)時的 SDK 版本參數(shù)設(shè)定

在開發(fā) Android App 時,開發(fā)人員最容易出現(xiàn)困惑的地方之一應(yīng)該是 compileSdkVersion、minSdkVersion 和 targetSdkVersion 這些參數(shù)的用途。對此,有 Google 內(nèi)部的 Android 開發(fā)人員就這個議題寫了一篇文章:Picking your compileSdkVersion, minSdkVersion, and targetSdkVersion。在這里會用不同的角度來說明這些參數(shù)的用途,希望能對大家在理解上有所幫助。

buildToolsVersion

首先,這是在那篇文章中沒有說明到的另一個與版本有關(guān)的參數(shù)。這個參數(shù)主要是用來指定用哪一組編譯程序來將你所編寫的 Source Code 轉(zhuǎn)成操作系統(tǒng)可以載入的形式,也就是產(chǎn)出 Apk。所以 Build Tools 在概念上可以看成是 Android Studio 的一部份或是其中一個套件,只是同時會有好幾組。

譬如說要修理車輛,每一組的 Build Tools 就像是有人把修車的工具,扳手、起子、套筒之類的放在一個包包里。只是隨著工具設(shè)計的翻新,包包里的工具可能會做調(diào)整,像是起子原本是各尺寸一只,現(xiàn)在可能改成只有一只但可以換各種尺寸的頭。同樣是拿來修車,工具也一樣,但是為了區(qū)別內(nèi)容物的不同所以給了不同的編號。

選用哪一組 Build Tools 原則上不會有太大的差異,大概就是編譯的效能、產(chǎn)出的文件大小等等的細(xì)節(jié)。但有時候還是可能會牽涉到 Apk 內(nèi)容或結(jié)構(gòu)的問題影響運行,仍然要多注意改版的資訊。最保險的做法還是讓 buildToolsVersion 的主版本編號與 compileSdkVersion 同步。

compileSdkVersion

compileSdkVersion 則是 Build Tools 在進(jìn)行編譯時,檢查源代碼在呼叫 SDK 所使用的規(guī)格是否正確的基準(zhǔn),但所指定的 SDK 并不會被編入 Apk 中。Google 會在發(fā)行新版系統(tǒng)時對 SDK 做調(diào)整,為了保持相容性,在規(guī)格上不太可能采取激進(jìn)的方式,例如:同樣名稱的函式改為不同的參數(shù)規(guī)格。最常出現(xiàn)的大概就是在函式上標(biāo)注 @Deprecated,等系統(tǒng)發(fā)行過幾個版本之后再正式廢止。

buildToolsVersion 及 compileSdkVersion 顧名思義就是在編譯、生成時期所使用的工具,這句話的重點是編譯過了、順利產(chǎn)出 Apk,不代表運行上就沒有問題,而且所謂的運行還要細(xì)分是在哪個版本上運行。因為 SDK 不是包含在 Apk 里,是包含在 Android 的系統(tǒng)之中。Apk 在哪一個版本的 Android 中運行,調(diào)用?的就是對應(yīng)版本的 SDK。所以運行調(diào)用叫會不會報錯,跟編譯會不會成功是沒有直接的關(guān)連,除非運行的環(huán)境和 compileSdkVersion 指定的版本相同,但也僅限于規(guī)格的部份。

用旅游來做例子,Build Tools 就好像旅行社,把你對旅游的構(gòu)想轉(zhuǎn)成實際的行程。而 Compile SDK 則是旅行社在行前檢查所使用的檢查表,用來確認(rèn)在行前是不是有什么細(xì)節(jié)遺漏了。選用哪一個旅行社對于規(guī)劃行程沒有什么太大的差別,頂多只是能夠提供服務(wù)的多寡或細(xì)致的程度。而行前檢查表如果用錯了版本就有可能會出問題,像是要去的目的地簽證條件改變了,舊的版本沒有列上去,在行前檢查時一切沒問題,到了當(dāng)?shù)夭虐l(fā)現(xiàn)沒有辦法入境,于是整個行程就報銷了。但如果是用新的檢查表,就可以在行前發(fā)現(xiàn)問題,并且做出補救的措施,確保行程能夠如計劃進(jìn)行。

由于 Google Play 只限制 App 可運行的 SDK 最低版本,并沒有限定最高的版本。也就是,使用者可以在硬體廠商有提供更新的情況下不斷地升級系統(tǒng)版本,而 App 則會一直保持在可安裝的狀態(tài)下。如果一直不更動 compileSdkVersion,則有一些變動在編譯時期不會被發(fā)現(xiàn),前段提到的標(biāo)注 @Deprecated 就是一例。前幾次的系統(tǒng)版本更新在運行 App 上可能不會有問題,但是一旦真的有函式被廢止了,則要到運行時才能發(fā)現(xiàn),這時要偵錯就不是件容易的事。但如果是使用新的 compileSdkVersion,則是在編譯時就會有對應(yīng)的訊息供作參考。

所以在開頭提到的文章中有一個很重要的關(guān)鍵點是:當(dāng)編譯的結(jié)果還存有警告時,一定要進(jìn)行對應(yīng)的處理,這些警告的設(shè)計是有其作用的。

targetSdkVersion

在推出新的 Android SDK 版本有函式的行為新舊版本不一致時,為保持相容性,舊的行為會被保留,并且會以 targetSdkVersion 的值來判斷要運行哪一種行為。以開頭提到的文章中舉例的 AlarmManager#set 來說,依官方文件的說明,Android 4.4 (API 19)以后使用的是不精確的時間,以減少設(shè)備被喚醒的次數(shù)及降低電量的耗損。官方文件中的另一段注解文字說到:targetSdkVersion 小于 API 19 的會繼續(xù)之前舊的行為,也就是 SDK 中會判斷 targetSdkVersion 的資訊來決定運行的源代碼內(nèi)容。

以前段提到旅游的例子來說,當(dāng)實際出發(fā)到了當(dāng)?shù)氐暮jP(guān),targetSdkVersion 的規(guī)則就如同海關(guān)柜臺人員不是一體套用新的簽證規(guī)則,而是會好心地依照填寫的申請日期決定適用的簽證規(guī)則。如果填的是新規(guī)則公布之后的日子,代表填寫的人應(yīng)該知道新的簽證規(guī)則,所以當(dāng)然就照新的簽證規(guī)則來審核。相對地,填寫的日期在新規(guī)則公布之前的日子,則會使用舊的簽證規(guī)則來審核。

Android 透過這種方式讓 App 在新的系統(tǒng)版本中不會有預(yù)期之外的行為出現(xiàn),即便 Google 打算在新版本中改變原本的行為。所以 targetSdkVersion 主要的用途是讓開發(fā)者告知 SDK,開發(fā)者所認(rèn)知的函式行為應(yīng)該是哪一種,如果 targetSdkVersion 是設(shè)定成改變之前的值,則 SDK 會運行舊的版本,否則就運行新的。對開發(fā)者來說,修改 targetSdkVersion 后代表的意義是:開發(fā)者已經(jīng)知道了新的 SDK 行為,并且確認(rèn)這個行為是 App 所需要的。所謂的確認(rèn)通常指的是要在參數(shù)指定之對應(yīng)版本的運行環(huán)境中做過測試,而不光只是編譯成功。

依照以上的說明,如果在更換了 targetSdkVersion 內(nèi)容,卻還是使用萬年的模擬器設(shè)定來進(jìn)行測試,以致模擬器上系統(tǒng)的版本一直沒換,這時就有必要重新檢討開發(fā)時的測試策略了。

minSdkVersion

最直接的用途就是要求 Google Play 設(shè)定 App 可被安裝的系統(tǒng)版本最底限,在這個版本之后的則不會被限制。

對開發(fā)者來說有另外一個要觀注的重點和 targetSdkVersion 一樣,minSdkVersion 也具有相同的意義。試想有一個 App 是在 Android 4.4 (API 19)開發(fā)的,預(yù)期的是 AlarmManager#set 的新行為,但是當(dāng) minSdkVersion 的值比 API 19 小時,程式運作在 API 18 以下的環(huán)境中一定沒有 AlarmManager#set 的新行為,這時 App 會產(chǎn)生什么結(jié)果?

如果是上架很久的 App,源代碼應(yīng)該也是對應(yīng)著系統(tǒng)版本演進(jìn)的歷程做修改。所以源代碼中或多或少都有包含先前所提到和 SDK 類似用系統(tǒng)版本來判斷程式要運行的新、舊邏輯區(qū)塊,以適應(yīng)各種不同版本的系統(tǒng)。在這種情況之下,minSdkVersion 理所當(dāng)然的可以是很早期的版本數(shù)值。

如果是新開發(fā)的 App,因為沒有經(jīng)歷過這些過程,所以 targetSdkVersion 和 minSdkVersion 在開發(fā)初始的階段里意義上是一樣的,這時對 minSdkVersion 調(diào)整最保守的做法應(yīng)該是逐次逐版地往前調(diào)。當(dāng) minSdkVersion 的數(shù)值逐版向前調(diào)整時,也應(yīng)逐版在對應(yīng)的環(huán)境中做過測試,確保程式在舊行為下所呈現(xiàn)的結(jié)果也符合預(yù)期,并且在必要時要加上對新舊版本的判斷式、補上合于舊版環(huán)境的源代碼。

就像開頭提到的文章中所指出,即使 14 億臺設(shè)備中的 0.7% 也是逼進(jìn)一千萬臺可觀的數(shù)字,如果不想放棄這樣的商機(jī),在砸了自己的招牌之前,還是乖乖地每一個版本確實地做好測試,否則寧可不要輕易地下調(diào) minSdkVersion。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容