先拋出一個問題:
我們的應用開發的時候android最新版本是6.0,當一年過去之后,7.0發布了,那么我們的應用在7.0手機上是否還能運行?會奔潰嗎?
根據我們的實際經驗,覺得應該不會奔潰,可能有些功能會有問題,但是具體是那一塊呢?又說不太好,這就涉及到了Android的向前兼容的問題了。
我們在創建App的時候經常會設置這幾個參數
android {
compileSdkVersion 23
buildToolsVersion “23.0.1”
defaultConfig {
applicationId “com.example.ssy"
minSdkVersion 16
targetSdkVersion 23
versionCode 1
versionName “1.0”
}
}
其中著名的就是compileSdkVersion,minSdkVersion,targetSdkVersion。平時這些參數都是自動設置的,我們只需設置minSdkVersion,最低SDK版本,然后compileSdkVersion和targetSdkVersion可能是一致的。這就是我們平時使用AS的時候不注意的問題,平時操作習慣了,但是真的不知道這幾個參數是什么意思。
minSdkVersion
最好理解的就是minSdkVersion了,就是我們的app能夠運行的最小版本,如果選擇16,那么就是Android 4.1 以及以上的設備才能運行我們app,如果小于這個版本,那么抱歉運行不了,我們不支持。這是應用程序支持api的下限。這也是應用商店判斷這個應用是否能運行在設備上的一個依據之一。
在開發中也會根據這個下限去判斷,是否可以用某個api方法,如果是下限之下的那么就會有警告,避免調用一些在新的版本已經改變或者過時的方法。
當我們引用了第三方的庫,如果某幾個庫的minSdkVersion分別是API5,API10,API16的方法,那么我們的minSdkVersion最少就是16。
對于minSdkVersion的選擇,我們應該看各個api的占比,不過因為基數太大了(十幾億)所以就算是0.7%也是個天文數字,所以我們需要根據自己應用的受眾,以及是否需要適配低版本的需要,一般說來我們適配4.1以上,即minSdkVersion=16,不過還要根據自己的實際情況,去選擇相應的版本號。
compileSdkVersion
compileSdkVersion是我們告訴Gradle,我們是用哪一版本的Android Sdk去編譯程序的,可以使用這個版本的API,比如我們使用的是7.0的版本,compileSdkVersion=24,那么我們對于拍照裁剪圖片等功能的操作,就可以使用FileProvider了。
我們需要注意的是:我們改變compileSdkVersion的版本號,本質上改變不了我們程序的運行,雖然可能會報錯誤?或者警告??,但compileSdkVersion 只會在編譯期間起作用,因為環境是compileSdkVersion這個版本的SDK,所以你可以用一些這個版本的API,但是只是IDE給你的便利性幫助而已,幫助你檢測代碼,避免使用一些棄用的API。就算你用個低版本的compileSdkVersion,你依然可以那么寫,但是可能會報錯,報警告,但是你強制打包,其實也是沒有問題的。IDE只是個工具,他的環境也只是工具的環境,不代表你應用運行時的表現。
所以希望大家用最新的sdk版本作為開發環境,compileSdkVersion設置成最新的,這樣我們可以使用到最新SDK的API方法和機制。
如果我們使用了比如V4,V7包,有沒有發現必須和compileSdkVersion的版本相匹配,比如我們compileSdkVersion = 26,那么V4,v7的版本也要相應的是26.xx.xx,首位的26必須一致,后兩位沒有要求,就是說明編譯所依賴的SDK和依賴包必須是統一版本,不然兩個不兼容,編譯會通不過。同時也是為了使用該版本的新特性。
targetSdkVersion
targetSdkVersion是這哥三里面最難以理解的一個了,不過也是最有趣的一個。
targetSdkVersion的含義對于我們來說就有點陌生而熟悉了。
- 什么是目標設備SDK版本?
- 是和minSdkVersion相對應的上限嗎?
- 如果我運行在比targetSdkVersion高的設備上,會出現什么?
- 如果是比targetSdkVersion低的設備呢?
滿滿的疑問
首先targetSdkVersion是android向前兼容的主要方式,怎么說呢?官方是這樣說的:
除非更新targetSdkVersion,否則不改變應用的行為。 這允許您在處理行為更改之前使用新的API(如您更新過的compileSdkVersion)
簡單的說就是你的應用已經針對這個版本的手機,做了充分的兼容性處理和測試性處理,比如 if(Build.VERSION.SDK_INT >= 23) { ... } ,這樣針對不同的SDK版本做不同的處理,這就說明我們不能隨便的改變targetSdkVersion得值,我們必須做好充足的兼容性處理和測試處理才行。
在 Android 4.4 (API 19)以后,AlarmManager 的 set() 和 setRepeat() 這兩個 API 的行為發生了變化。在 Android 4.4 以前,這兩個 API 設置的都是精確的時間,系統能保證在 API 設置的時間點上喚醒 Alarm。因為省電原因 Android 4.4 系統實現了 AlarmManager 的對齊喚醒,這兩個 API 設置喚醒的時間,系統都對待成不精確的時間,系統只能保證在你設置的時間點之后某個時間喚醒。雖然api的名字沒有改變,但是功能結果已經發生改變,我們設置targetSdkVersion為16,Android4.4之前,那么我們在Android4.4之后運行會出現什么呢?難道就不能用了嗎?不準確了嗎?
當然不是,系統通過targetSdkVersion來保證Android的向前兼容性,在Android4.4之后的設備上,系統會判斷你的targetSdkVersion是否小于19,如果小于的話,那就按照19之前的api方法,如果大于等于19,那么就按照之后的api方法來走,保證了程序運行的一致性。也就是向前兼容性。
但是還有一個問題:
Android 6.0新增加了動態權限申請,我們的targetSdkVersion是5.0,如果我們運行在Android 6.0的設備上怎么辦?
因為我們這個可以向前兼容,向后不行啊,如果你的代碼里處理了Android 6.0的動態權限處理,那么可以的,如果沒呢?你想啥呢大哥?更新應用處理唄~~
targetSdkVersion 的大部分更新變化都會記錄在VERSION_CODES,所有的細節也會在每個版本的平臺亮點寫明。
targetSdkVersion保證的是api的一致性。
所以一般minSdkVersion <targetSdkVersion<= compileSdkVersion
不隨意更改targetSdkVersion,更改targetSdkVersion必須做好兼容。
Gradle和SDK版本
所以設置正確的compileSdkVersion,minSdkVersion和targetSdkVersion很重要。正如Gradle和Android Studio的世界中的那樣,這些值通過包含在我們模塊的build.gradle文件中(也可通過Android Studio中的Project Structure選項獲得)集成到工具系統中:
android {
compileSdkVersion 23
buildToolsVersion“23.0.1”
defaultConfig {
applicationId“com.example.ssy”
minSdkVersion 7
targetSdkVersion 23
versionCode 1
versionName“1.0”
}
}
compileSdkVersion是一個編譯時的事情(TMD這誰知道),是與我們的構建工具版本一起使用的Android設置之一。
minSdkVersion和targetSdkVersion不同于compileSdkVersion,因為它們包含在APK中。查看生成的AndroidManifest.xml
<uses-sdk android:targetSdkVersion =“23”android:minSdkVersion =“16”/>
理清楚這些后,下次更改這些參數的時候,就不會犯一些低級錯誤了。但是其中的更細節的東西,需要看android編譯原理和運行原理了,任重而道遠,這只是一個結果論。
大家可以點個關注,告訴我大家想要深入探究哪些問題,希望看到哪方面的文章,我可以免費給你寫專題文章。。哈哈。。。
希望大家多多支持。。你的一個關注,是我堅持的最大動力。。