https://juejin.im/post/5aae7200f265da23a3350317
徹底弄清support支持庫(kù)绕德,以及v4 v7重復(fù)依賴問(wèn)題深究
一般在Android Studio的項(xiàng)目配置build.gradle里殃姓,有3個(gè)SDKversion,即:compileSdkVersion嚣镜、minSdkVersion和targetSDKVersion爬迟,這些version指的并不是我們使用的SDK的版本,而是我們使用的Android平臺(tái)(Android Platform)的版本菊匿,即API Level付呕,是一個(gè)整數(shù)计福,指的是我們使用的框架(Framework)的版本,也就是SDK中platforms文件夾下各個(gè)level中的android.jar的版本徽职,API Level就是android.jar(Framework開(kāi)發(fā)包象颖、一套接口)的代號(hào)。一般Android系統(tǒng)版本表示為Android2.3.3姆钉,在系統(tǒng)內(nèi)部會(huì)記錄它的API level说订,不同的Android系統(tǒng)版本對(duì)應(yīng)不同的API Level(最后有詳細(xì)介紹),但是有時(shí)候Android系統(tǒng)版本更新了潮瓶,其對(duì)應(yīng)的API Level并不一定更新陶冷,所以他們是多對(duì)一的關(guān)系,Android系統(tǒng)版本是面向用戶毯辅,API Level是面向開(kāi)發(fā)者埂伦。
compileSDKVersion
各個(gè)其中compileSDKVersion是AS編譯APK使用的API Level,一般修改了compileSDKVersion不會(huì)改變運(yùn)行時(shí)的行為思恐,可能會(huì)出現(xiàn)一些編譯的警告和錯(cuò)誤沾谜, compileSDKVersion并不會(huì)被包含到apk中,它只是純粹在編譯時(shí)候使用胀莹。一般推薦使用最新的版本進(jìn)行編譯基跑,避免使用廢棄的API,同時(shí)Support Library 也需要相應(yīng)的編譯SDK版本來(lái)支持描焰,我們經(jīng)常使用的Support Library的依賴語(yǔ)句形式如下:compile 'com.android.support:support-v4:24.2.1
媳否,其格式是compile jar文件組(group/命名空間):jar文件名(name):jar文件版本(version)
,這里jar文件版本需要和compileSDKVersion保持一致栈顷。
關(guān)于Support Library參考:http://www.reibang.com/p/f5f9a4fd22e8
簡(jiǎn)單總結(jié)一下:Support Library提供了一些低版本API Level中不存在的API接口逆日,如App配置為minSdkVersion=9,targetSdkVersion=23萄凤,在程序里使用了android 3.0 (API level 11)提供的ActionBar類室抽,使用compileSdkVersion=23成功編譯出apk,App在android 3.0以及以上的版本上正常運(yùn)行靡努,但在API 9的版本上回crash坪圾,因?yàn)檎也坏紸ctionBar類,因?yàn)榕f版本上沒(méi)有新版本里新增的類惑朦。為了避免使用了最新功能開(kāi)發(fā)的app只能在最新系統(tǒng)的設(shè)備上運(yùn)行的尷尬兽泄,官方把新版系統(tǒng)framework中新增加的接口提出來(lái)放到了Android Support Library(支持包)中,開(kāi)發(fā)者在遇到上面的情況時(shí)漾月,就可以使用支持包中具有同樣功能的ActionBar類病梢,這個(gè)支持包會(huì)打包進(jìn)apk里,這樣使用了新版本系統(tǒng)上功能的App也可以向后兼容以前的老系統(tǒng)版本設(shè)備了。
Support V4和V7是使用最廣泛的2個(gè)包蜓陌,其實(shí)是包的集合觅彰,v4在后期被拆分為幾個(gè)子包,v7一開(kāi)始就是不同的子包钮热,這樣可以減少apk的體積填抬,另外在編譯的時(shí)候使用代碼混淆ProGuard,除了可以混淆源代碼外隧期,還可以移除依賴支持庫(kù)中沒(méi)有使用到的類飒责,達(dá)到apk瘦身的效果。
7/22/2017 7:58:00 AM
App編譯時(shí)用的android sdk(android.jar)不會(huì)打包進(jìn)我們的apk中仆潮。因?yàn)閍pk編碼是使用android.jar中的接口就是android設(shè)備里系統(tǒng)框架層(framework)對(duì)外提供的接口宏蛉。
minSdkVersion
minSdkVersion表示應(yīng)用兼容的最低API Level,如果手機(jī)的Android系統(tǒng)的API level低于該值性置,則該手機(jī)無(wú)法安裝此apk檐晕。API level在選擇時(shí)應(yīng)該兼顧市場(chǎng)上大部分的手機(jī)Android系統(tǒng)版本。原則上蚌讼,如果我們?cè)诰帉懗绦驎r(shí)使用了最低API Level里沒(méi)有的API接口,那么程序就會(huì)報(bào)錯(cuò)个榕,我們通過(guò)使用Support Library來(lái)提供最低API Level里沒(méi)有的API接口篡石,但注意,這些Support Library本身也使用了minSdkVersion西采,那么我們工程里的minSdkVersion版本不能低于Support Library使用的minSdkVersion版本凰萨。例如我們用了3個(gè)庫(kù),他們的minSdkVersion分別是4械馆、7胖眷、9,那么我們工程的minSdkVersion至少應(yīng)該是9霹崎,否則編譯通不過(guò)珊搀。如果minSdkVersion沒(méi)有設(shè)置的話,默認(rèn)為1尾菇。
targetSdkVersion
targetSdkVersion境析,谷歌給出的解釋是:
targetSdkVersion is the main way Android provides forward compatibility,Specifies the API Level on which the application is designed to run. In some cases. As Android evolves with each new version, some behaviors and even appearances might change. However, if the API level of the platform is higher than the version declared by your app's targetSdkVersion, the system may enable compatibility behaviors to ensure that your app continues to work the way you expect.
If not set, the default value equals that given to minSdkVersion
targetSdkVersion是Android系統(tǒng)提供前向兼容的主要手段,用來(lái)保證以前老的app即使運(yùn)行在新的Android系統(tǒng)上派诬,它的行為還是和以前兼容劳淆。因?yàn)锳ndroid系統(tǒng)是不斷更新的,有些API的行為在新系統(tǒng)上發(fā)生了變化默赂,那么對(duì)于那些以前的apk沛鸵,即使它安裝在了最新的Android系統(tǒng)上,調(diào)用的最新Android系統(tǒng)的API接口缆八,只要apk的targetSdkVersion不變曲掰,那么它的行為依然保持不變疾捍,依然執(zhí)行原來(lái)的行為。這就保證了系統(tǒng)對(duì)以前老的app應(yīng)用的前向兼容性蜈缤。
例如拾氓,在 Android 4.4 (API 19)以后,AlarmManager 的 set() 和 setRepeat() 這兩個(gè) API 的行為發(fā)生了變化底哥。在 Android 4.4 以前咙鞍,這兩個(gè) API 設(shè)置的都是精確的時(shí)間,系統(tǒng)能保證在 API 設(shè)置的時(shí)間點(diǎn)上喚醒 Alarm趾徽。因?yàn)槭‰娫?Android 4.4 系統(tǒng)實(shí)現(xiàn)了 AlarmManager 的對(duì)齊喚醒续滋,這兩個(gè) API 設(shè)置喚醒的時(shí)間,系統(tǒng)都對(duì)待成不精確的時(shí)間孵奶,系統(tǒng)只能保證在你設(shè)置的時(shí)間點(diǎn)之后某個(gè)時(shí)間喚醒疲酌。
這時(shí),雖然 API 沒(méi)有任何變化了袁,但是實(shí)際上 API 的行為卻發(fā)生了變化朗恳,如果老的 APK 中使用了此 API,并且在應(yīng)用中的行為非常依賴 AlarmManager 在精確的時(shí)間喚醒载绿,例如鬧鐘應(yīng)用粥诫。如果 Android 系統(tǒng)不能保證兼容,老的 APK 安裝在新的系統(tǒng)上崭庸,就會(huì)出現(xiàn)問(wèn)題怀浆。
Android 系統(tǒng)是怎么保證這
種兼容性的呢?這時(shí)候 targetSdkVersion 就起作用了怕享。APK 在調(diào)用系統(tǒng) AlarmManager 的 set() 或者 setRepeat() 的時(shí)候执赡,系統(tǒng)首先會(huì)查一下調(diào)用的 APK 的 targetSdkVersion 信息,如果小于 19函筋,就還是按照老的行為沙合,即精確設(shè)置喚醒時(shí)間,否者執(zhí)行新的行為跌帐。
我們來(lái)看一下 Android 4.4 上 AlarmManger 的一部分源代碼:
private final boolean mAlwaysExact;
AlarmManager(IAlarmManager service, Context ctx) {
mService = service;
final int sdkVersion = ctx.getApplicationInfo().targetSdkVersion;
mAlwaysExact = (sdkVersion < Build.VERSION_CODES.KITKAT);
}
看到這里灌诅,首選獲取應(yīng)用的 targetSdkVersion,判斷是否是小于 Build.VERSION_CODES.KITKAT (即 API Level 19)含末,來(lái)設(shè)置 mAlwaysExact 變量猜拾,表示是否使用精確時(shí)間模式。
public static final long WINDOW_EXACT = 0;
public static final long WINDOW_HEURISTIC = -1;
private long legacyExactLength() {
return (mAlwaysExact ? WINDOW_EXACT : WINDOW_HEURISTIC);
}
public void set(int type, long triggerAtMillis, PendingIntent operation) {
setImpl(type, triggerAtMillis, legacyExactLength(), 0, operation, null);
}
這里看到佣盒,直接影響到 set() 方法給 setImpl() 傳入不同的參數(shù)挎袜,從而影響到了 set() 的執(zhí)行行為。具體的實(shí)現(xiàn)在 AlarmManagerService.java
,這里就不往下深究了盯仪。
看到這里紊搪,發(fā)現(xiàn)其實(shí) Android 的 targetSdkVersion 并沒(méi)有什么特別的,系統(tǒng)使用它也非常直接全景,甚至很“粗糙”耀石。僅僅是用過(guò)下面的 API 來(lái)獲取 targetSdkVersion,來(lái)判斷是否執(zhí)行哪種行為:
getApplicationInfo().targetSdkVersion;
所以爸黄,我們可以猜測(cè)到滞伟,如果 Android 系統(tǒng)升級(jí),發(fā)生這種兼容行為的變化時(shí)炕贵,一般都會(huì)在原來(lái)的保存新舊兩種邏輯梆奈,并通過(guò) if-else 方法來(lái)判斷執(zhí)行哪種邏輯。果然称开,在源碼中搜索亩钟,我們會(huì)發(fā)現(xiàn)不少類似 getApplicationInfo().targetSdkVersion < Buid.XXXX
這樣的代碼,相對(duì)于浩瀚的 Android 源碼量來(lái)說(shuō)鳖轰,這些還是相對(duì)較少了清酥。其實(shí)原則上,這種會(huì)導(dǎo)致兼容性問(wèn)題的修改還是越少越好蕴侣,所以每次發(fā)布新的 Android 版本的時(shí)候总处,Android 開(kāi)發(fā)者網(wǎng)站都會(huì)列出做了哪些改變,在這里睛蛛,開(kāi)發(fā)者需要特別注意。
最后胧谈,這3者之間的關(guān)系忆肾,理想上,在穩(wěn)定狀態(tài)下三者的關(guān)系應(yīng)該更像這樣:
minSdkVersion (lowest possible) <= targetSdkVersion == compileSdkVersion (latest SDK)
用較低的 minSdkVersion 來(lái)覆蓋最大的人群菱肖,用最新的 SDK 設(shè)置 target 和 compile 來(lái)獲得最好的外觀和行為客冈。#BuildBetterApps
AS默認(rèn)的targetSdkVersion和compileSdkVersion都是使用的最新的API Level。
另外稳强,minSdkVersion 和 targetSdkVersion 與 compileSdkVersion 的另一個(gè)不同之處是它們會(huì)被包含進(jìn)最終的 APK 文件中场仲,如果你查看生成的 AndroidManifest.xml 文件,你會(huì)看到類似下面這樣的標(biāo)簽:
<uses-sdk android:targetSdkVersion="23" android:minSdkVersion="7" />
如果你在 manifest 文件中手工設(shè)置退疫,你會(huì)發(fā)現(xiàn) Gradle 在構(gòu)建時(shí)會(huì)忽略它們(盡管其它構(gòu)建系統(tǒng)可能會(huì)明確依賴它們)渠缕。
What is API Level?
API Level is an integer value that uniquely identifies the framework API revision offered by a version of the Android platform.
The Android platform provides a framework API that applications can use to interact with the underlying Android system. The framework API consists of:
- A core set of packages and classes
- A set of XML elements and attributes for declaring a manifest file
- A set of XML elements and attributes for declaring and accessing resources
- A set of Intents
- A set of permissions that applications can request, as well as permission enforcements included in the system
Each successive version of the Android platform can include updates to the Android application framework API that it delivers.
Updates to the framework API are designed so that the new API remains compatible with earlier versions of the API. That is, most changes in the API are additive and introduce new or replacement functionality. As parts of the API are upgraded, the older replaced parts are deprecated but are not removed, so that existing applications can still use them. In a very small number of cases, parts of the API may be modified or removed, although typically such changes are only needed to ensure API robustness and application or system security. All other API parts from earlier revisions are carried forward without modification.
The framework API that an Android platform delivers is specified using an integer identifier called "API Level". Each Android platform version supports exactly one API Level, although support is implicit for all earlier API Levels (down to API Level 1). The initial release of the Android platform provided API Level 1 and subsequent releases have incremented the API Level.
The API Level identifier serves a key role in ensuring the best possible experience for users and application developers:
- It lets the Android platform describe the maximum framework API revision that it supports
- It lets applications describe the framework API revision that they require
- It lets the system negotiate the installation of applications on the user's device, such that version-incompatible applications are not installed.
Each Android platform version stores its API Level identifier internally, in the Android system itself.
參考:
如何選擇 compileSdkVersion, minSdkVersion 和 targetSdkVersion
Android中build target,minSdkVersion褒繁,targetSdkVersion亦鳞,maxSdkVersion概念區(qū)分
https://developer.android.com/guide/topics/manifest/uses-sdk-element.html