1. 程式人生 > >Android的minSdkVersion,targetSdkVersion,maxSdkVersion

Android的minSdkVersion,targetSdkVersion,maxSdkVersion

API Level 是一個整型值,表示Android釋出的某個特定版本,新API Level相對於老API Level會增加以下內容:
* 新增類、或者已有類中新增、修改、甚至刪除的API
* 新定義的xml tag
* 新定義Intent
* 新定義的Permission
* 其它…


API Level和版本有如下對應關係:
Platform VersionAPI Level
Android 3.011
Android 2.3.310
Android 2.39
Android 2.28
Android 2.17
Android 2.0.16
Android 2.05
Android 1.64
Android 1.53
Android 1.12
Android 1.01


先說一下minSdkVersion的用處:
新版本中public了老版本沒有的介面,如果我寫的一個App中用到了只有新版本才有的介面,肯定不能讓它跑在老版本SDK上,不然會報錯。 Android是如何保證這一點的?靠定義minSdkVersion來實現。 比如,如果我定義了<uses-sdk android:minSdkVersion="8"  ... />, 編譯生成的apk是無法安裝到Android 2.1(API Level 7)系統上的,系統會提示: ERROR: Application requires API version 8. Device API version is 7。

AndroidManifest.xml中如果不寫,預設 minSdkVersion = 1, 表示程式至少能安裝到,並且作者也希望它能跑到Android 1.0上。

接下來說一下targetSdkVersion的用處:
一般而言,新版本要相容老版本,這就是為什麼Android中很多介面即使過時了(deprecated)但還依然保留在新SDK中,所以絕大多數情況下,為老版本開發的應用可以執行在新版SDK上。但是也有一些例外,主要是以下三類問題:

1. 老介面被刪除或修改了(這種case有,但很少),本文不關注
2. 同樣的介面,但新老版本的實現有所不同。比如有一些API早期設計時考慮不周全,新版本做了改進。
3. 即使不涉及任何介面呼叫,但由於物理裝置的擴充套件,同樣的apk需要在新版本上需要適配更多的物理裝置,從而具備了新的特性

對於第二類問題,指定targetSdkVersion為具體的某個API Level,則表示呼叫介面時只會呼叫該版本實現的API,而不是早期版本的API。
對於第三類問題,就是這封信碰到情況,Google從開發Android 1.6 (API Level 4)開始意識到,程式執行時需要考慮到手機螢幕大小、解析度不同。因此從1.6開始引入了針對多螢幕的支援,定義了不同螢幕尺寸與解析度、密度的一個對應關係。注意到此前google只意識到會在中密度螢幕(mdpi)下開發,所以1.5以及以前版本的圖片圖示等資源、佈局都是按照中密度螢幕設計的。

從Android 1.6開始,Google提供了多套資源(ldpi, mdpi, hdpi) 支援,對內建應用以及Framework的資源(比如控制元件),系統可以在編譯時刻決定只打包某個特定密度的資源(定義在PRODUCT_LOCALES中,對N1,應該是PRODUCT_LOCALES := hdpi ...)。

對基於SDK開發的應用,eclipse預設會打包所有密度的資源,在Android 1.6之後的版本上跑,會在執行時刻根據物理裝置實際密度來選擇對應密度的資源。


如果某個App中定義的targetSdkVersion <= 3, , 表示該App無法用到Android 1.6才有的多螢幕支援能力, 所以即使應用本身包含了hdpi,mdpi,ldpi資源,但執行到hdpi的物理裝置上時只會去載入mdpi的資源,當然顯示就不正常了。
注意:如果App中也用到的系統級資源(比如控制元件),一般來說特定的物理裝置只可能是hdpi,mdpi, ldpi (以後會有擴充套件,比如xdpi)中的一種,所以只會載入那唯一的一種dpi資源,因此顯示系統控制元件本來不應該有任何問題。不過,如果Image沒有優化,而是包含了所有資源,那麼控制元件顯示也會不正常 。

再回到正題上來,為什麼eclipse下編譯的程式執行起來和ubuntu下編譯的顯示效果不同?

在ubuntu下編譯,系統認為你編譯的是內建應用,內建應用在正常情況下不會被變態的人扒出來放到其他裝置上去,所以不存在安裝相容性問題,minSdkVersion預設就是當前物理裝置的current sdk version。另外既然是內建應用,當然執行在當前物理裝置上效果最好,所以targetSdkVersion預設也是當前物理裝置的current sdk version。這個在編譯時刻打包apk時,build system首先檢測這兩個值有沒有設定,沒設定的話它會替你加上。 

在eclipse下編譯,系統認為你編譯的是第三方應用,忘了寫就是你的錯了,minSdkVersion和targetSdkVersion預設都是1,所以會出現上面說到的悲劇。

結論:
1. 對內建應用,不要自己去設定minSdkVersion和targetSdkVersion;
2. 基於SDK開發的,根據自己的實際情況,一定要設定minSdkVersion和targetSdkVersion;
3. 剛剛沒說maxSdkVersion,我們別定義它,以後可能會OTA升級整個Android系統,定義了它對我們是個悲劇