Android-0.Android中minsdkversion和targetSdkVersion的選擇
問題
在呼叫系統播放mp4時,程式碼如下:
private void viewMediaFile(String path) { if (!TextUtils.isEmpty(path)) { String type = "video/*"; if (path.contains("png") || path.contains("jpeg") || path.contains("jpg")) { type = "image/*"; } String value = String.valueOf(path); File file = new File(value); Intent intent = new Intent(); intent.setAction(android.content.Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(file), type); startActivity(intent); } }
發現原工程可以正常呼叫,而我的demo卻直接崩潰了,錯誤如下:
android.os.FileUriExposedException:
file:///storage/emulated/0/Movies/VID_88.mp4 exposed beyond app through Intent.getData()
最後得出結論為
targetSdkVersion
不同,我的demo設定成了28,而原工程是21,從而導致行為不同。
簡介
targetSdkVersion
即目標軟體開發版本,在建立每一個Android專案的時候都需要選擇targetSdkVersion
和minSdkVersion
,一個targetSdkVersion
targetSdkVersion 24
API 19開發的Android專案在Android 7.0系統的手機上執行。 或 API 24開發的Android專案在Android 4.x系統的手機上執行。 它們執行的效果是否一樣呢? API 23開發的應用程式在低於Android 6.0系統上執行時,如果許可權被禁用後,會提示如下圖:
但是,如果API 23開發的應用程式在高於或等於Android 6.0系統的手機上執行時需要自己定義執行時許可權申請的程式碼:
https://blog.csdn.net/hgy413/article/details/82968070
如果需要顯示類似於上面圖片顯示的Toast
提示,開發者需要在onRequestPermissionResult
回撥方法中,列印拍照許可權被禁用,請在許可權管理修改
這句話。
舉這個例子的目的,想要說明為什麼在API 23版本開發的APP在低於Android 6.0系統不會執行上述程式碼的原因。
高版本的API定義了一些程式設計介面,但是通常不需要開發者考慮是否高版本API開發的APP在低版本的Android系統的相容性問題,API和Android系統是兩個不一樣的概念,API屬於應用層的東西,Android系統屬於底層的東西,開發者想要顯示底層的演示效果,就需要使用API來完成,如果想要不同的演示效果,又需要考慮選擇哪個版本的API,也就是文章的標題提到的:如何選擇targetSdkVersion
屬性值的問題。
如何選擇targetSdkVersion
一個Android系統,對外提供一套API,如何選擇targetSdkVersion
取決於應用程式需要實現的功能,如果你的應用程式使用API 10就可以實現的功能,可以不用考慮使用API 24,使用低版本API的其中一個好處,可以讓更多的Android系統執行的效果保持一致,即相容性更好,打個比方:API 10開發的APP可能相容98%以上的Android手機,而API 24開發的APP可能相容僅有60%,所謂的不相容並不是無法正常執行,而是在不同Android系統的手機執行的效果差異比較大,會讓使用者感覺難以接受;
使用低版本API的其中一個不足,顯示的效果比較OUT,提供的可用的介面或類比較少,本來一句程式碼可以完成的功能(封裝的類或介面),需要自己花一天琢磨寫很多的程式碼,也就是有高版本API的其中一個原因,提供更多的或封裝好的應用程式介面讓開發者使用。
同時,高版本API會針對低版本存在的問題進行改進和完善,擯棄一下不用的類或介面,新增一些方法或屬性,如果你使用的方法是在某個API被另一個方法代替的話,你可能就得在程式碼中區分APP是執行在哪個版本的Android系統。一個很典型的例子:
WebChromeClient
的onShowFileChooser()
方法和openFileChooser()
方法,如果你的targetSdkVersion
小於19,在處理WebView上傳表單的資料的時候就需要重寫openFileChooser
方法;如果你的targetSdkVersion
大於或等於19,你就必須同時重寫onShowFileChooser
和openFileChooser
兩個方法,openFileChooser
方法在Android 4.0以下系統被回撥,另一則在Android 4.0以上系統被回撥。這是高低版本API擯棄或新增一些類和方法時需要注意的其中一個問題。
瞭解並學習Android 4.x、Android 5.x、Android 6.x或Android 7.x系統的特性,重點掌握不同系統同一個功能的實現方式,即行為變更,特點:變更的行為在當前系統或更高系統版本中被支援,一個簡單的例子:Android 7.0系統其中的一個行為變更是許可權更改,嘗試傳遞file:// URI 的方式寫入本地檔案或讀取本地檔案,使用API 24開發的APP將會觸發 FileUriExposedException
異常,也即文章開頭提到的問題。
關於minSdkVersion和compileSdkVersion
minSdkVersion
定義應用程式支援的最低API版本,最低版本設定為API 11,目標版本設定為API 24,那麼應用程式呼叫使用API 14提供的方法時,Android Studio將提醒開發者引用一個未定義的方法,使用該方法需要將minSdkVersion
設定為API 14以上,如下圖:
繼續在上述程式碼,造成的結果大於或等於Android 4.0的系統可以正常執行,小於Android 4.0的系統將在執行時嘗試訪問不可用的API 時發生崩潰。
compileSdkVersion
定義應用程式編譯選擇哪個Android SDK版本,通常compileSDKVersion
屬性值被設定為最新的API版本,例如:25,改變compileSDKVersion
的屬性值不會影響Android系統執行行為,比如說,將屬性值設定為25,targetSdkVersion屬性值為23,程式碼如下:
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "cn.teachcourse.demos"
minSdkVersion 11
targetSdkVersion 23
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
開發的應用程式在Android 7.0系統執行,不會以Android 7.0新增的行為執行,決定Android系統行為的仍然是targetSDKVersion
,那麼compileSDKVersion
有什麼用呢?
因為環境是compileSdkVersion
這個版本的SDK,所以你可以用一些這個版本的API,但是隻是IDE給你的便利性幫助而已,幫助你檢測程式碼,避免使用一些棄用的API。就算你用個低版本的compileSdkVersion
,你依然可以那麼寫,但是可能會報錯,報警告,但是你強制打包,其實也是沒有問題的。IDE只是個工具,他的環境也只是工具的環境,不代表你應用執行時的表現。
targetSdkVersion、minSdkVersion和CompileSdkVersion之間的關係
記住一點:Android系統平臺的行為變更,只有targetSdkVersion
的屬性值被設定為大於或等於該系統平臺的API版本時,才會生效;compileSdkVersion
屬於Android編譯專案時其中的一項配置,主要區別是compileSDKVersion
不會被打包的APK檔案中,targetSdkVersion
和minSdkVersion
將被打包到APK檔案中,具體可以解壓APK檔案後,檢視AndroidManifest.xml檔案,如下圖: