轉(zhuǎn)載自:http://blog.csdn.net/zhangjg_blog/article/details/17142395
本文參考了谷歌開發(fā)者文檔:http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#provisional
如果開發(fā)的應(yīng)用用戶較多,那么必須保證應(yīng)用在多個版本不同的設(shè)備上能夠正確的運(yùn)行。這就要求對各個版本比較熟悉,知道在什么版本中加入了什么新的功能或特性。但是Android的版本太多了,是個令人頭疼的問題。如果想了解Android的版本差異,建議讀一下Android開發(fā)者文檔上相關(guān)的章節(jié)。
為了讓你的應(yīng)用程序指定可以運(yùn)行的版本,Android的manifest文件中提供了<uses-sdk>標(biāo)簽。該標(biāo)簽中有三個屬性,分別是minSdkVersion,targetSdkVersion,maxSdkVersion。這三個屬性比較容易讓人迷惑,我也是仔細(xì)讀了谷歌的官方文檔,才弄清楚這三個屬性的意義。此外,在項(xiàng)目構(gòu)建時(shí),還有個概念叫build target,在本文中也會進(jìn)行分析。
什么是API level
其實(shí)標(biāo)簽<uses-sdk>中指定的并不是我們使用的sdk的版本,也不是Android系統(tǒng)的版本,而是我們使用的Android平臺的版本,即API level。API level是一個整數(shù),它指的是我們使用的框架(Framework)的版本,也就是我們使用的sdk中的各個平臺下的android.jar。但是這個API level又和Android系統(tǒng)的版本有著對應(yīng)關(guān)系,并且每個系統(tǒng)都會在內(nèi)部記錄它所使用的API level。舉例來說,我使用的手機(jī)系統(tǒng)是Android 2.3.3, 那么它就會在內(nèi)部記錄使用的API level為10。這個內(nèi)部的API level可以讓系統(tǒng)判定能不能安裝一款app,這個問題會在下文中提及。
下面給出android系統(tǒng)版本,API level和版本代號之間的對應(yīng)關(guān)系表。(該表來自谷歌官方文檔:http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#provisional)

由上表可以看出,android的系統(tǒng)版本和API level之間并不是一一對應(yīng)的,比如Android 2.3, Android 2.3.1, Android 2.3.2對應(yīng)API level 9, 而Android 2.3.3, Android 2.3.4對應(yīng)API level 10。API level是Android向開發(fā)者提供的一套Framework(android.jar)的代號,可能發(fā)布了新的系統(tǒng)版本,但是這一套接口并沒有變化,所以就不必提供新的Framework開發(fā)包,所以API level也不必改變。由此可知Android系統(tǒng)版本和API level是多對一的關(guān)系。由于API level就是發(fā)布的android.jar(一套接口)的代號,所以API level和sdk中platforms目錄中的各個android.jar是一一對應(yīng)的。說白了,Android系統(tǒng)版本是給Android用戶看的,而API level是給應(yīng)用程序開發(fā)者看的。
什么是build target
build target并不存在于manifest文件中,而是存在于項(xiàng)目根目錄中的project.properties文件中。如果使用Eclipse構(gòu)建項(xiàng)目的話,那么每個項(xiàng)目的根目錄下都會有一個project.properties文件,這個文件中的內(nèi)容用于告訴構(gòu)建系統(tǒng),怎樣構(gòu)建這個項(xiàng)目。打開這個文件,除了注釋之外,還有以下一行:
target=android-18
這句話就是指明build target,也就是根據(jù)哪個android平臺構(gòu)架這個項(xiàng)目。指明build target為android-18,就是使用sdk中platforms目錄下android-18目錄中的android.jar這個jar包編譯項(xiàng)目。同樣,這個android.jar會被加入到本項(xiàng)目的build path中。如下圖:
每當(dāng)修改了build target,就會將另一個android.jar加入到build path中替換原來的jar。將build target改成android-17后的效果如下圖:

如果將build target 改成android-8,那么就會使用sdk中android-8下的android.jar編譯項(xiàng)目,如果在Activity中調(diào)用ActionBar相關(guān)的Api,那么就會報(bào)錯,因?yàn)锳ctionBar相關(guān)的Api是在API level 11中才加進(jìn)來的。

一般情況下,應(yīng)該使用最新的API level作為build target。這也是eclipse生成項(xiàng)目時(shí)的默認(rèn)行為。
android:minSdkVersion
指明應(yīng)用程序運(yùn)行所需的最小API level。如果不指明的話,默認(rèn)是1。也就是說該應(yīng)用兼容所有的android版本。我們應(yīng)該總是聲明這個屬性。
如果系統(tǒng)的API level低于android:minSdkVersion設(shè)定的值,那么android系統(tǒng)會阻止用戶安裝這個應(yīng)用。下載將android:minSdkVersion設(shè)置為11, 并且將該應(yīng)用安裝在android 2.3的手機(jī)上(對應(yīng)API level 9),在安裝時(shí)會有如下提示:
提示手機(jī)API level的版本太低,安裝失敗。
如果指明了這個屬性,并且在項(xiàng)目中使用了高于這個API level的API, 那么會在編譯時(shí)報(bào)錯。將build target設(shè)為最新的android-19,那么就會使用最新的android-19下的android.jar來編譯項(xiàng)目。將minSdkVersion設(shè)置為8。在使用的android.jar中,肯定會有和ActionBar相關(guān)的API, 但是在項(xiàng)目中調(diào)用ActionBar API, 項(xiàng)目會報(bào)錯。因?yàn)閙inSdkVersion指明的API level 8中不存在ActionBar相關(guān)的API。
調(diào)用Activity.getActionBar()和ActionBar.getHeight()方法需要API level 11, 但是指定的minSdkVersion為8,所以報(bào)錯。由此可見,minSdkVersion不僅在程序安裝時(shí)起作用,也會在項(xiàng)目構(gòu)建時(shí)起作用。
如果沒有設(shè)置minSdkVersion這個屬性,那么默認(rèn)是1。表明程序兼容所有的Android系統(tǒng),能夠在所有Android系統(tǒng)上運(yùn)行。如果使用了高于API level 1 的API, 如ActionBar。那么在構(gòu)建項(xiàng)目時(shí),會提示和上面相同的錯誤,項(xiàng)目構(gòu)建失敗。

android:targetSdkVersion
標(biāo)明應(yīng)用程序目標(biāo)API Level的一個整數(shù)。如果不設(shè)置,默認(rèn)值和minSdkVersion相同。
這個屬性通知系統(tǒng),你已經(jīng)針對這個指定的目標(biāo)版本測試過你的程序,系統(tǒng)不必再使用兼容模式來讓你的應(yīng)用程序向前兼容這個目標(biāo)版本。應(yīng)用程序仍然能在低于targetSdkVersion的系統(tǒng)上運(yùn)行。
由于Android不斷向著更新的版本進(jìn)化,一些行為甚至是外觀可能會改變。然而,如果平臺的API Level高于你的應(yīng)用程序中的targetSdkVersion屬性指定的值,系統(tǒng)會開啟兼容行為來確保你的應(yīng)用程序繼續(xù)以期望的形式來運(yùn)行。你可以通過指定targetSdkVersion來匹配運(yùn)行程序的平臺的 API level來禁用這種兼容性行為。舉例來說,設(shè)置這個值為11或更高,當(dāng)你的應(yīng)用運(yùn)行在Android3.0或更高的系統(tǒng)上時(shí),系統(tǒng)會為你的應(yīng)用使用新的默認(rèn)主題(Holo主題),并且當(dāng)運(yùn)行在大屏幕的設(shè)備上時(shí)會禁用屏幕兼容模式(screen compatibility mode),因?yàn)橹С至?API level 11就暗示了支持大屏幕。
根據(jù)你設(shè)置的targetSdkVersion 的值,系統(tǒng)會執(zhí)行很多兼容行為。一些行為在對應(yīng)平臺版本的Build.VERSION_CODES中有討論。
為了讓你的應(yīng)用程序支持每個Android版本,你應(yīng)當(dāng)提高targetSdkVersion的值到最新的API level,然后在對應(yīng)的平臺上徹底的測試你的應(yīng)用。
從上面的論述可知,targetSdkVersion這個屬性是在程序運(yùn)行時(shí)期起作用的,系統(tǒng)根據(jù)這個屬性決定要不要以兼容模式運(yùn)行這個程序。
一般情況下,應(yīng)該將這個屬性的值設(shè)置為最新的API level 值,這樣的話可以利用新版本系統(tǒng)上的新特性。eclipse在生成項(xiàng)目時(shí),默認(rèn)將該值設(shè)置為最高,如果設(shè)置一個較低的值,會給出一個警告,如下圖所示。

這個警告的意思是沒有將targetSdkVersion的值設(shè)置為最高值,較新的系統(tǒng)會以兼容模式運(yùn)行該程序。請考慮在新版本系統(tǒng)上測試程序并將targetSdkVersion設(shè)置為最新。更詳細(xì)的信息請參考android.os.Build.VERSION_CODES 。
android:maxSdkVersion
標(biāo)明可以運(yùn)行你的應(yīng)用的最高API Level版本。
在Android1.5, 1.6, 2.0 和2.0.1,在安裝應(yīng)用或系統(tǒng)升級時(shí),系統(tǒng)會檢查這個值。在這兩種情況下,如果應(yīng)用設(shè)置的maxSdkVersion 值低于系統(tǒng)本身使用的API Level,系統(tǒng)將不會允許安裝該應(yīng)用。在系統(tǒng)升級后,新系統(tǒng)會重新校驗(yàn)這個值,如果新系統(tǒng)的API Level高于這個值,新系統(tǒng)會刪除你的應(yīng)用。
在高于2.0.1的系統(tǒng)上,安裝應(yīng)用時(shí)不會再檢驗(yàn)應(yīng)用中設(shè)置的maxSdkVersion值,在系統(tǒng)升級后也不會重新校驗(yàn)這個值。但是在向用戶展示可用的應(yīng)用時(shí),Google Play會繼續(xù)使用這個屬性進(jìn)行過濾。
maxSdkVersion這個屬性本來是在程序安裝時(shí)和系統(tǒng)升級后起作用的。但是根據(jù)官方文檔中的說明, 已經(jīng)不再推薦使用這個屬性。
經(jīng)過測試,將maxSdkVersion的值設(shè)置成9,程序是可以安裝在4.2的手機(jī)上的。說明這個值已經(jīng)不再起作用。
- <uses-sdk
- droid:minSdkVersion="8"
- android:targetSdkVersion="19"
- android:maxSdkVersion="9"/>