新手的第一個Android項目該如何選擇targetSdkVersion

vusn4784 7年前發布 | 7K 次閱讀 安卓開發 Android開發 移動開發

新手的第一個 Android 項目或許沒有認真考慮過如何選擇 targetSdkVersion 的問題,也或許還有一部分像TeachCourse一樣的開發者,積累一些工作經驗后才回頭來思考這個問題。那么該如何選擇一個targetSdkVersion的屬性值?一個屬性值為23的targetSdkVersion表示什么含義?那么API 24和Android 7.0又是什么關系?為什么API 19開發的Android項目可以在Android 7.0系統的手機上運行,反之Android 4.x系統的手機可以運行API 24開發的Android項目?最后,正確理解compileSdkVersion、 minSdkVersion 和targetSdkVersion三者之間的關系。

一、認識targetSdkVersion

targetSdkVersion 即目標軟件開發版本,在創建每一個Android項目的時候都需要選擇 targetSdkVersion 和 minSdkVersion ,一個 targetSdkVersion 的屬性值表示創建的Android項目使用哪個API版本,一個API版本使用一個整型數字表示,API的全稱是 Application Programming Interface ,即應用程序編程接口,API 19對應的編程接口和API 23定義的編程接口存在差別,因為使用整型數字表示 targetSdkVersion 的屬性值,容易記憶和便于比較它們之間的大小,高版本API編程接口可以兼容低版本API編程接口,反之則不行。

需要區別 Android 7.0API 24 之間的關系,Android 7.0定義的手機系統的版本,該系統的版本對外開放的應用程序接口被定義為API 24,如果開發者想要在開發的APP中使用Android 7.0系統提供的功能,這些功能包括:多窗口支持、通知顯示變更、JIT/AOT編譯、快速的應用安裝路徑等等,那么新手在創建的Android項目的時候就需要選擇API 24的應用程序接口。

不知道開發者也沒有注意到,為什么API 19開發的Android項目可以在Android 7.0系統的手機上運行,反之Android 4.x系統的手機可以運行API 24開發的Android項目,它們運行的效果是否一樣呢?如果是Android 7.0系統運行API 24開發的應用程序,效果又是怎么樣?這就讓TeachCourse聯想到了API 23開發的應用程序在 低于Android 6.0系統 上運行時,如果權限被禁用后,會提示如下圖:

但是,如果API 23開發的應用程序在 高于或等于Android 6.0系統 的手機上運行時需要自己定義打印上述 Toast ,下面是完整的運行時權限申請的代碼:

private static final int REQUEST_CODE_PERMISSION=0x112;
    private void initPermission() {
        int flag= ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
        if(PackageManager.PERMISSION_GRANTED!=flag){
            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA}, REQUEST_CODE_PERMISSION);
        }else{
            alterImageNew();
        }
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (REQUEST_CODE_PERMISSION==requestCode){
            switch (grantResults[0]){
                case PackageManager.PERMISSION_DENIED:
                    boolean isSecondRequest=ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.CAMERA);
                    if(isSecondRequest)
                        ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA},REQUEST_CODE_PERMISSION);
                    else
                        Toast.makeText(this, "拍照權限被禁用,請在權限管理修改", Toast.LENGTH_SHORT).show();
                    break;
                case PackageManager.PERMISSION_GRANTED:
                    alterImageNew();
                    break;
            }
        }
    }

如果需要顯示類似于上面圖片顯示的 Toast 提示,開發者需要在 onRequestPermissionResult 回調方法中,打印拍照權限被禁用,請在權限管理修改這句話,在使用API 23應用程序編程接口開發的APP中都可以反復復制上面代碼,僅將 CAMERA 替換成定義的權限參數,將 alterImageNew() 替換成擁有權限后要執行的代碼。

舉這個例子的目的,想要說明為什么在API 23版本開發的APP在 低于Android 6.0系統 不會執行上述代碼的原因。

高版本的API定義了一些的編程接口,但是通常不需要開發者考慮是否 高版本API 開發的APP在 低版本的Android系統 的兼容性問題, APIAndroid系統 是兩個不一樣的概念, API 屬于應用層的東西, Android系統 屬于底層的東西,開發者想要顯示底層的演示效果,就需要使用API來完成,如果想要不同的演示效果,又需要考慮選擇哪個版本的API,也就是文章的標題提到的:如何選擇 targetSdkVersion 屬性值的問題。

二、如何選擇targetSdkVersion

一個Android系統,對外提供一套API,如何選擇 targetSdkVersion 取決于應用程序需要實現的功能,如果你的應用程序使用API 7就可以實現的功能,可以不用考慮使用API 24,使用低版本API的其中一個好處,可以讓更多的Android系統運行的效果保持一致,即兼容性更好,打個比方:API 7開發的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 異常,請求拍照并保存到本地的正確的寫法,如下:

/**
     * 調用系統相機
     */
    private void goToTakePhoto() {
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            File file = new File(mSDCardPath, System.currentTimeMillis() + ".jpg");
            /**Android 7.0以上的方式**/
            Uri contentUri = getUriForFile(this, getString(R.string.install_apk_path), file);
            grantUriPermission(getPackageName(), contentUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
            /**Android 7.0以前的方式**/
//            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
            startActivityForResult(intent, RESULT_CAPTURE_IMAGE);
        } else {
            Toast.makeText(this, "sdcard不存在", Toast.LENGTH_SHORT).show();
        }
    }

想要查看完整的例子,文章后面附上源碼,可以下載測試。本來已經代碼可以實現的拍照功能,API 24開發的APP在Android 7.0以上系統需要 至少四個步驟:

  1. 在AndroidManifest.xml文件中定義一個FileProvider
  2. 指定寫入或讀取本地文件的目錄
  3. 生成完整的URI
  4. 請求授予URI權限
  5. 實現手機拍照并保存本地功能

三、關于minSdkVersion和compileSdkVersion

minSdkVersion 定義應用程序支持的最低API版本,最低版本設置為API 11,目標版本設置為API 24,那么應用程序調用使用API 14提供的方法時,Android Studio或Eclipse開發工具將提醒開發者引用一個未定義的方法,使用該方法需要將 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 有什么用呢?選擇最新的API版本,在編譯的時候檢查代碼的錯誤和警告,提示開發者修改和優化,因為通常在Android項目中會引入第三方的支持庫,支持庫使用了 23.1.1 版本, compileSdkVersion 的屬性值至少為 23.0.0 ,新版本的支持庫的發布緊跟著對應的Android系統平臺,能夠更好的兼容。

四、targetSdkVersion、minSdkVersion和CompileSdkVersion之間的關系

記住一點:Android系統平臺的行為變更,只有 targetSdkVersion 的屬性值被設置為大于或等于該系統平臺的API版本時,才會生效; compileSdkVersion 屬于Android編譯項目時其中的一項配置,主要區別是 compileSDKVersion 在不會被打包的APK文件中, targetSdkVersion 和 minSdkVersion 將被打包到APK文件中,具體可以解壓APK文件后,查看AndroidManifest.xml文件,如下圖:

你會發現在使用Android Studio開發工具時,手動修改 AndroidManifest.xml 的屬性值,使用Gradle構建后,將會被忽略,最終生成的是 build.gradle 配置文件指定的屬性值。它們之間的關系如下:

minSdkVersion <= targetSdkVersion <= compileSdkVersion

 

 

來自:http://www.androidchina.net/6598.html

 

 本文由用戶 vusn4784 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!